# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/03/17 18:55:48-08:00 akpm@osdl.org 
#   [PATCH] ISDN kernelcapi notifier NULL pointer fix
#   
#   From: Armin Schindler <armin@melware.de>
#   
#   Fixed NULL pointer reference in recv_handler()
# 
# drivers/isdn/capi/kcapi.c
#   2004/03/17 18:43:05-08:00 akpm@osdl.org +3 -3
#   ISDN kernelcapi notifier NULL pointer fix
# 
# ChangeSet
#   2004/03/17 18:55:39-08:00 akpm@osdl.org 
#   [PATCH] ISDN kernelcapi notifier workqueue re-structured
#   
#   From: Armin Schindler <armin@melware.de>
#   
#   Use the notifier workqueue in a cleaner way.
# 
# drivers/isdn/capi/kcapi.c
#   2004/03/17 18:45:04-08:00 akpm@osdl.org +35 -95
#   ISDN kernelcapi notifier workqueue re-structured
# 
# ChangeSet
#   2004/03/17 18:55:29-08:00 akpm@osdl.org 
#   [PATCH] ISDN kernelcapi debug message enable
#   
#   From: Armin Schindler <armin@melware.de>
#   
#   Show debug messages if debug is enabled only.
# 
# drivers/isdn/capi/kcapi.c
#   2004/03/17 18:45:04-08:00 akpm@osdl.org +14 -6
#   ISDN kernelcapi debug message enable
# 
# ChangeSet
#   2004/03/17 18:55:20-08:00 akpm@osdl.org 
#   [PATCH] exportfs - Remove unnecessary locking from find_exported_dentry()
#   
#   From: "Jose R. Santos" <jrsantos@austin.ibm.com>
#   
#   After discussing it with Neil, he fell that the original justification for
#   taking the kernel_lock on find_exported_dentry() is not longer valid and
#   should be safe to remove.
#   
#   This patch fixes an issue while running SpecSFS where under memory
#   pressure, shrinking dcache cause find_exported_dentry() to allocate
#   disconnected dentries that later needed to be properly connected.  The
#   connecting part of the code was done with BKL taken which cause a sharp
#   drop in performance during iterations and profiles showing 75% time spent
#   on find_exported_dentry().  After applying the patch, time spent on the
#   function is reduce to <1%.
#   
#   I have tested this on an 8-way machine with 56 filesystems for several days
#   now with no problems using ext2, ext3, xfs and jfs.
# 
# fs/exportfs/expfs.c
#   2004/03/17 18:43:04-08:00 akpm@osdl.org +0 -3
#   exportfs - Remove unnecessary locking from find_exported_dentry()
# 
# ChangeSet
#   2004/03/17 18:55:11-08:00 akpm@osdl.org 
#   [PATCH] JBD: avoid panic on corrupted journal superblock
#   
#   Don't panic if the journal superblock is wrecked: just fail the mount.
# 
# fs/jbd/recovery.c
#   2004/03/17 18:43:04-08:00 akpm@osdl.org +4 -1
#   JBD: avoid panic on corrupted journal superblock
# 
# ChangeSet
#   2004/03/17 18:55:01-08:00 akpm@osdl.org 
#   [PATCH] ppc64: CONFIG_PREEMPT Kconfig help fix
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   From: Robert Love <rml@ximian.com>
#   
#   arch/ppc64/Kconfig's entry for CONFIG_PREEMPT is missing the description
#   after the "bool" statement, so the entry does not show up.
#   
#   Also, the help description mentions a restriction that is not [any longer]
#   true.
# 
# arch/ppc64/Kconfig
#   2004/03/17 18:43:04-08:00 akpm@osdl.org +2 -4
#   ppc64: CONFIG_PREEMPT Kconfig help fix
# 
# ChangeSet
#   2004/03/17 18:54:52-08:00 akpm@osdl.org 
#   [PATCH] ppc64: xmon oops-the-kernel option
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Sometimes we just want to pass the error up to the kernel and let it oops.
#   X it is.
# 
# arch/ppc64/xmon/xmon.c
#   2004/03/17 18:43:04-08:00 akpm@osdl.org +6 -1
#   ppc64: xmon oops-the-kernel option
# 
# ChangeSet
#   2004/03/17 18:54:42-08:00 akpm@osdl.org 
#   [PATCH] ppc64: wrap some stuff in __KERNEL__
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   - remove now unused kernel syscalls.
#   - wrap recently added defines in #ifdef __KERNEL__, fixes glibc
#     compile issue
#   - some of our extra syscalls used asmlinkage, some did not. Make them
#     consistent
# 
# include/asm-ppc64/unistd.h
#   2004/03/17 18:43:04-08:00 akpm@osdl.org +13 -22
#   ppc64: wrap some stuff in __KERNEL__
# 
# ChangeSet
#   2004/03/17 18:54:33-08:00 akpm@osdl.org 
#   [PATCH] ppc32: Fix booting some IBM PRePs
#   
#   From: Tom Rini <trini@kernel.crashing.org>
#   
#   The following patch comes from Paul Mackerras.  Earlier on in 2.6,
#   arch/ppc/boot/utils/mkprep.c was changed slightly so that it would build
#   and work on Solaris.  Doing this required changing from filling out
#   pointers to an area to filling out a local copy of the struct.  However, a
#   memcpy was left out, and the info is only needed on some machines to boot.
#   The following adds in the missing memcpy and allows for IBM PRePs to boot
#   from a raw floppy again.
# 
# arch/ppc/boot/utils/mkprep.c
#   2004/03/17 18:43:04-08:00 akpm@osdl.org +2 -0
#   ppc32: Fix booting some IBM PRePs
# 
# ChangeSet
#   2004/03/17 18:54:23-08:00 akpm@osdl.org 
#   [PATCH] ppc32: fix SMP build
#   
#   From: Olaf Hering <olh@suse.de>
#   
#   Current Linus tree adds an extra space and dot to the mkprep options.
#   `make all' with an smp config doesnt work.  This patch fixes it.
# 
# arch/ppc/boot/simple/Makefile
#   2004/03/17 18:43:04-08:00 akpm@osdl.org +1 -1
#   ppc32: fix SMP build
# 
# ChangeSet
#   2004/03/17 20:12:15-05:00 brazilnut@us.ibm.com 
#   [PATCH] back out netdev_priv() for loopback
#   
#   Please apply this fix to backout an erroneous change in loopback.c
#   The statistics structure is allocated separately from the
#   loopback_dev structure, and the current code overwrites something
#   other than the statistics.  In my case the scsi_cmd_pool structure.
# 
# drivers/net/loopback.c
#   2004/03/17 11:46:40-05:00 brazilnut@us.ibm.com +1 -1
#   2.6.5-rc1-bk2 loopback.c
# 
# ChangeSet
#   2004/03/17 14:32:58-05:00 jgarzik@redhat.com 
#   [netdrvr de2104x] initialize bus mode properly
# 
# drivers/net/tulip/de2104x.c
#   2004/03/17 14:32:53-05:00 jgarzik@redhat.com +9 -9
#   [netdrvr de2104x] initialize bus mode properly
# 
# ChangeSet
#   2004/03/17 10:18:16-08:00 davidm@tiger.hpl.hp.com 
#   ia64: Prevent GCC from clobbering r13.  Found by Luming You.
#   
#   Without this change, GCC thinks it's OK to clobber r13.  It doesn't do it
#   very often, but it's enough if it does it once and it turns out
#   acpi_bus_receive_event() had code that would trigger this issue.
#   Fix by declaring r13 as a global register variable.
# 
# include/asm-ia64/gcc_intrin.h
#   2004/03/17 10:18:09-08:00 davidm@tiger.hpl.hp.com +3 -4
#   (ia64_r13): Declare as a global register.
# 
# ChangeSet
#   2004/03/17 12:54:59-05:00 khc@pm.waw.pl 
#   [netdrvr de2104x] fix ifup/down and promise mode
#   
#   The attached patch fixes the problem: de->macmode variable,
#   meant to shadow MacMode (CSR6) register, was used inconsistently,
#   causing some updates to this register to be dropped.
#   
#   2.4 kernel doesn't shadow this register at all, so I removed
#   shadowing from 2.6 as well.
# 
# drivers/net/tulip/de2104x.c
#   2004/03/17 12:54:54-05:00 khc@pm.waw.pl +13 -12
#   [netdrvr de2104x] fix ifup/down and promise mode
#   
#   The attached patch fixes the problem: de->macmode variable,
#   meant to shadow MacMode (CSR6) register, was used inconsistently,
#   causing some updates to this register to be dropped.
#   
#   2.4 kernel doesn't shadow this register at all, so I removed
#   shadowing from 2.6 as well.
# 
# ChangeSet
#   2004/03/17 09:54:01-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] ide-dma.c: remove unused/obsoleted code for hwif->mmio == 1
#   
#   All users of hwif->mmio correctly handle resources themselves
#   (hwif->mmio == 2) so remove ide_mmio_dma() and ide_release_mmio_dma().
# 
# drivers/ide/ide-dma.c
#   2004/03/16 14:10:15-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -46
#   ide-dma.c: remove unused/obsoleted code for hwif->mmio == 1
# 
# ChangeSet
#   2004/03/17 09:53:52-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] remove AMIGA/MAC hacks from IDE resource handling code
#   
#   Nowadays buddha.c, gayle.c and macide.c handle resources themselves
#   (hwif->mmio == 2).
#   
#   Acked by Geert.
# 
# drivers/ide/ide.c
#   2004/03/16 14:03:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +2 -20
#   remove AMIGA/MAC hacks from IDE resource handling code
# 
# ChangeSet
#   2004/03/17 09:53:42-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] remove ide_hwif_t->initializing
#   
#   It's write-only these days.
# 
# include/linux/ide.h
#   2004/03/16 14:12:28-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -1
#   remove ide_hwif_t->initializing
# 
# drivers/ide/pci/pdc202xx_old.c
#   2004/03/16 14:12:28-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -4
#   remove ide_hwif_t->initializing
# 
# drivers/ide/pci/pdc202xx_new.c
#   2004/03/16 14:12:28-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -4
#   remove ide_hwif_t->initializing
# 
# drivers/ide/ide.c
#   2004/03/16 14:12:28-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -1
#   remove ide_hwif_t->initializing
# 
# drivers/ide/ide-probe.c
#   2004/03/16 14:12:28-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -2
#   remove ide_hwif_t->initializing
# 
# ChangeSet
#   2004/03/17 07:14:24-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] hpt366.c: PLL fix needed for some HPT374
#   
#   From: Boehm Olaf <olaf.boehm@lanner.de>
#   From: Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
#   
#   Wider range for 33MHz timing and PLL setup for HPT374
#   (using the HPT370A timing table, as it is the same as
#   used in the "opensource" driver by HighPoint).
#   
#   fixes bugzilla bugs #2209 and #2271
# 
# drivers/ide/pci/hpt366.c
#   2004/03/17 05:11:50-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +2 -2
#   hpt366.c: PLL fix needed for some HPT374
# 
# ChangeSet
#   2004/03/17 07:12:43-08:00 cieciwa@alpha.zarz.agh.edu.pl 
#   [PATCH] drivers/cdrom/cdu31a - wrong tmp_irq declaration
#   
#   cdu31a.c needs tmp_irq outside of the block it is declared in.  Move it
#   to the outer block.
# 
# drivers/cdrom/cdu31a.c
#   2004/03/16 23:59:46-08:00 cieciwa@alpha.zarz.agh.edu.pl +2 -1
#   drivers/cdrom/cdu31a - wrong tmp_irq declaration
# 
# ChangeSet
#   2004/03/17 07:11:07-08:00 akpm@osdl.org 
#   [PATCH] Fix x86_64 compile warning in bad_page()
#   
#   On x84_64, page->flags is no longer unsigned long.
# 
# mm/slab.c
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +2 -1
#   Fix x86_64 compile warning in bad_page()
# 
# mm/page_alloc.c
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +1 -1
#   Fix x86_64 compile warning in bad_page()
# 
# ChangeSet
#   2004/03/17 07:10:56-08:00 akpm@osdl.org 
#   [PATCH] Remove old config options from defconfigs.
#   
#   From: Dave Jones <davej@redhat.com>
#   
#   These options are only ever referenced in the defconfigs of various archs
#   now.
# 
# arch/sparc64/defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -4
#   Remove old config options from defconfigs.
# 
# arch/ppc64/defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -2
#   Remove old config options from defconfigs.
# 
# arch/ppc64/configs/pSeries_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -2
#   Remove old config options from defconfigs.
# 
# arch/ppc64/configs/g5_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/ppc/configs/rainier_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/ppc/configs/power3_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -4
#   Remove old config options from defconfigs.
# 
# arch/ppc/configs/cedar_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/ppc/configs/ash_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/mips/configs/rm200_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/ia64/configs/zx1_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/ia64/configs/generic_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -2
#   Remove old config options from defconfigs.
# 
# arch/i386/defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -2
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/trizeps_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/shannon_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/rpc_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/pfs168_satft_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/pfs168_sastn_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/pfs168_mqvga_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/pfs168_mqtft_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm26/defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/netwinder_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/neponset_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/footbridge_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/ebsa110_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/clps7500_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/cerfcube_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -1
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/badge4_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -4
#   Remove old config options from defconfigs.
# 
# arch/arm/configs/a5k_defconfig
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +0 -3
#   Remove old config options from defconfigs.
# 
# ChangeSet
#   2004/03/17 07:10:45-08:00 akpm@osdl.org 
#   [PATCH] SHMLBA compat task alignment fix
#   
#   From: Arun Sharma <arun.sharma@intel.com>
#   
#   The current Linux implementation of shmat() insists on SHMLBA alignment even
#   when shmflg & SHM_RND == 0.  This is not consistent with the man pages and
#   the single UNIX spec, which require only a page-aligned address.
#   
#   However, some architectures require a SHMLBA alignment for correctness in all
#   cases.  Such architectures use __ARCH_FORCE_SHMLBA.
# 
# ipc/shm.c
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +4 -1
#   SHMLBA compat task alignment fix
# 
# include/asm-sparc64/shmparam.h
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +1 -0
#   SHMLBA compat task alignment fix
# 
# include/asm-sparc/shmparam.h
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +2 -0
#   SHMLBA compat task alignment fix
# 
# include/asm-parisc/shmparam.h
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +2 -0
#   SHMLBA compat task alignment fix
# 
# include/asm-mips/shmparam.h
#   2004/03/17 04:02:30-08:00 akpm@osdl.org +2 -0
#   SHMLBA compat task alignment fix
# 
# ChangeSet
#   2004/03/17 07:10:35-08:00 akpm@osdl.org 
#   [PATCH] cpqarray: check pci_register_driver() return value
#   
#   From: <mikem@beardog.cca.cpqcorp.net>
#   
#   * Examines rc of pci_register_driver and returns
# 
# drivers/block/cpqarray.c
#   2004/03/17 04:02:29-08:00 akpm@osdl.org +7 -6
#   cpqarray: check pci_register_driver() return value
# 
# ChangeSet
#   2004/03/17 07:10:25-08:00 akpm@osdl.org 
#   [PATCH] cpqarray: use PCI APIs
#   
#   From: <mikem@beardog.cca.cpqcorp.net>
#   
#   - Change to use pci APIs (change from 2.4.18 to 2.4.19)
#   
#     This also includes eisa detection fix during initialization which was
#     missing from 2.4.19 but fixed in 2.4.25
# 
# drivers/block/cpqarray.c
#   2004/03/17 04:02:29-08:00 akpm@osdl.org +343 -197
#   cpqarray: use PCI APIs
# 
# ChangeSet
#   2004/03/17 07:10:16-08:00 akpm@osdl.org 
#   [PATCH] cpqarray: I/O address fixes
#   
#   From: <mikem@beardog.cca.cpqcorp.net>
#   
#   * cpqarray in kernel 2.6.1 seems to be based from 2.4.18 kernel with
#     specific 2.6.x stuff added.
#   
#   * Defines io_mem_addr and io_mem_length to replace ioaddr (change from
#     2.4.18 to 2.4.19)
# 
# drivers/block/smart1,2.h
#   2004/03/17 04:02:29-08:00 akpm@osdl.org +21 -21
#   cpqarray: I/O address fixes
# 
# drivers/block/cpqarray.h
#   2004/03/17 04:02:29-08:00 akpm@osdl.org +2 -1
#   cpqarray: I/O address fixes
# 
# drivers/block/cpqarray.c
#   2004/03/17 04:02:29-08:00 akpm@osdl.org +3 -3
#   cpqarray: I/O address fixes
# 
# ChangeSet
#   2004/03/17 07:10:06-08:00 akpm@osdl.org 
#   [PATCH] cpqarray: rmmod oops fix
#   
#   From: <mikem@beardog.cca.cpqcorp.net>
#   
#   * Fix for segmentation fault when calling rmmod
# 
# drivers/block/cpqarray.c
#   2004/03/17 04:02:29-08:00 akpm@osdl.org +1 -1
#   cpqarray: rmmod oops fix
# 
# ChangeSet
#   2004/03/17 07:09:57-08:00 akpm@osdl.org 
#   [PATCH] cpqarray: increment version number
#   
#   From: <mikem@beardog.cca.cpqcorp.net>
#   
#   The following patch bumps the driver version to 2.6.0.  Please apply in
#   order.
# 
# drivers/block/cpqarray.c
#   2004/03/17 04:02:28-08:00 akpm@osdl.org +4 -4
#   cpqarray: increment version number
# 
# ChangeSet
#   2004/03/17 07:09:48-08:00 akpm@osdl.org 
#   [PATCH] devices.txt: add more devices
#   
#   From: "Cagle, John (ISS-Houston)" <john.cagle@hp.com>
#   
#   Patch 3 adds all the new official device registrations that weren't already
#   there.  This brings devices.txt up-to-date with LANANA.
# 
# Documentation/devices.txt
#   2004/03/17 04:02:28-08:00 akpm@osdl.org +341 -5
#   devices.txt: add more devices
# 
# ChangeSet
#   2004/03/17 07:09:38-08:00 akpm@osdl.org 
#   [PATCH] devices.txt: typos and removal of dead devices
#   
#   From: "Cagle, John (ISS-Houston)" <john.cagle@hp.com>
#   
#   Patch 2 fixes some typos in devices.txt and removes ancient devices never
#   used.  Pretty obvious stuff.
# 
# Documentation/devices.txt
#   2004/03/17 04:02:28-08:00 akpm@osdl.org +60 -45
#   devices.txt: typos and removal of dead devices
# 
# ChangeSet
#   2004/03/17 07:09:29-08:00 akpm@osdl.org 
#   [PATCH] clean up devices.txt
#   
#   From: "Cagle, John (ISS-Houston)" <john.cagle@hp.com>
#   
#   Patch 1 cleans up the format by making devices.txt easily parsable.
#   Mainly this involved adding the word "block" after all the block major
#   numbers since the previous format didn't include it.
# 
# Documentation/devices.txt
#   2004/03/17 04:02:28-08:00 akpm@osdl.org +120 -114
#   clean up devices.txt
# 
# ChangeSet
#   2004/03/17 07:09:18-08:00 akpm@osdl.org 
#   [PATCH] hugetlb_zero_setup() race fix
#   
#   Make the handling of the hugetlb-backed shm file's name counter SMP-safe.
#   
#   (What stops hugetlb_zero_setup() racing with umount?)
# 
# fs/hugetlbfs/inode.c
#   2004/03/17 04:02:27-08:00 akpm@osdl.org +16 -5
#   hugetlb_zero_setup() race fix
# 
# ChangeSet
#   2004/03/17 07:09:08-08:00 akpm@osdl.org 
#   [PATCH] make config_max_raw_devices work
#   
#   From: "Kenneth Chen" <kenneth.w.chen@intel.com>
#   
#   Even though there is a CONFIG_MAX_RAW_DEVS option, it doesn't actually
#   increase the number of raw devices beyond 256 because during the char
#   registration, it uses the standard register_chrdev() interface which has
#   hard coded 256 minor in it.  Here is a patch that fix this problem by using
#   register_chrdev_region() and cdev_(init/add/del) functions.
# 
# drivers/char/raw.c
#   2004/03/17 04:02:27-08:00 akpm@osdl.org +23 -2
#   make config_max_raw_devices work
# 
# ChangeSet
#   2004/03/17 07:08:58-08:00 akpm@osdl.org 
#   [PATCH] x86 vsyscall alignment fix
#   
#   From: Andy Whitcroft <andyw@uk.ibm.com>
#   
#   The vsyscall implementation for ia32 provides two different vsyscall pages;
#   one to use int80 and the other to use sysenter.  Each includes a common
#   signal trailer.  The kernel requires the alignment of routines in this
#   trailer be consistent in both copies.  However this is not enforced at
#   compile time.  Failure to maintain this alignment typically leads to an
#   obscure SIGSEGV in init during boot.  This critical alignment requirement
#   is not well documented.
#   
#   Below is a patch to better document the alignment requirements and to
#   enforce the requirement.
# 
# arch/i386/kernel/vsyscall-sysenter.S
#   2004/03/17 04:02:27-08:00 akpm@osdl.org +5 -0
#   x86 vsyscall alignment fix
# 
# arch/i386/kernel/vsyscall-sigreturn.S
#   2004/03/17 04:02:27-08:00 akpm@osdl.org +3 -3
#   x86 vsyscall alignment fix
# 
# arch/i386/kernel/vsyscall-int80.S
#   2004/03/17 04:02:27-08:00 akpm@osdl.org +5 -0
#   x86 vsyscall alignment fix
# 
# ChangeSet
#   2004/03/17 07:08:48-08:00 akpm@osdl.org 
#   [PATCH] s390: tape driver fixes.
#   
#   From: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   
#   tape driver fixes:
#    - Link from ccw device to class device in sysfs.
#    - Cosmetic changes.
#    - Add copyright statements.
# 
# drivers/s390/char/tape_class.h
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +24 -17
#   s390: tape driver fixes.
# 
# drivers/s390/char/tape_class.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +65 -36
#   s390: tape driver fixes.
# 
# drivers/s390/char/tape_char.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +16 -31
#   s390: tape driver fixes.
# 
# drivers/s390/char/tape.h
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +2 -2
#   s390: tape driver fixes.
# 
# drivers/s390/char/Makefile
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +2 -2
#   s390: tape driver fixes.
# 
# ChangeSet
#   2004/03/17 07:08:38-08:00 akpm@osdl.org 
#   [PATCH] s390: z/VM monitor stream.
#   
#   From: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   
#   Fix for z/VM monitor stream:
#    - Add try_module_get and module_put to the [un]register functions.
#    - Some code beautification.
# 
# arch/s390/appldata/appldata_base.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +21 -36
#   s390: z/VM monitor stream.
# 
# ChangeSet
#   2004/03/17 07:08:29-08:00 akpm@osdl.org 
#   [PATCH] s390: dasd driver fixes.
#   
#   From: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   
#   dasd driver fixes:
#    - Remove additional dasd attributes for a ccw-device if the discipline
#      (=driver) gets unloaded.
#    - Fix race of dasd_generic_offline against dasd_open.
#    - Remove irq_exit calls from diag interrupt handler. The irq_enter/
#      irq_exit is done in the external interrupt handler.
# 
# drivers/s390/block/dasd_int.h
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +3 -1
#   s390: dasd driver fixes.
# 
# drivers/s390/block/dasd_diag.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +1 -3
#   s390: dasd driver fixes.
# 
# drivers/s390/block/dasd_devmap.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +8 -1
#   s390: dasd driver fixes.
# 
# drivers/s390/block/dasd.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +39 -10
#   s390: dasd driver fixes.
# 
# drivers/s390/block/Kconfig
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +4 -4
#   s390: dasd driver fixes.
# 
# ChangeSet
#   2004/03/17 07:08:18-08:00 akpm@osdl.org 
#   [PATCH] s390: network driver fixes.
#   
#   From: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   
#   network driver fixes:
#    - Use SET_NETDEV_DEV to create the link from the network device to the
#      physical device. Remove link from physical to network device.
#    - Remove some unnecessary casts in netiucv.
#    - Add missing strings to dev_stat_names & dev_event_names.
#    - Add missing preempt_disable/preempt_enable pairs in iucv.
#    - Allow to change the peer username in netiucv.
# 
# drivers/s390/net/qeth.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +2 -15
#   s390: network driver fixes.
# 
# drivers/s390/net/netiucv.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +85 -43
#   s390: network driver fixes.
# 
# drivers/s390/net/lcs.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +4 -18
#   s390: network driver fixes.
# 
# drivers/s390/net/iucv.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +9 -7
#   s390: network driver fixes.
# 
# drivers/s390/net/ctcmain.c
#   2004/03/17 04:02:26-08:00 akpm@osdl.org +6 -21
#   s390: network driver fixes.
# 
# ChangeSet
#   2004/03/17 07:08:09-08:00 akpm@osdl.org 
#   [PATCH] s390: sclp fix.
#   
#   From: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   
#   sclp console fixes:
#     - Replace irq_enter/irq_exit pair with Add local_bh_enable/local_bh_disable.
# 
# drivers/s390/char/sclp.c
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +3 -3
#   s390: sclp fix.
# 
# ChangeSet
#   2004/03/17 07:07:59-08:00 akpm@osdl.org 
#   [PATCH] s390: common i/o layer.
#   
#   From: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   
#   Common i/o layer fixes:
#    - Improve blacklist argument parsing.
#    - Fix device recognition for devices where SenseID fails.
#    - Don't try to set a device online that has no driver.
#    - Chain a release ccw to the unconditional reserve ccw for forced online.
#    - Fix irb accumulation for pure status pending with eswf set.
#    - Fix rc handling in qdio_shutdown.
#    - Improve retry behavious for busy conditions on qdio.
#    - Fix activity check in ccw_device_start/read_dev_chars and read_conf_data.
# 
# include/asm-s390/cio.h
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +1 -0
#   s390: common i/o layer.
# 
# drivers/s390/cio/qdio.h
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +5 -2
#   s390: common i/o layer.
# 
# drivers/s390/cio/qdio.c
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +94 -18
#   s390: common i/o layer.
# 
# drivers/s390/cio/device_status.c
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +1 -1
#   s390: common i/o layer.
# 
# drivers/s390/cio/device_ops.c
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +31 -9
#   s390: common i/o layer.
# 
# drivers/s390/cio/device_fsm.c
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +3 -0
#   s390: common i/o layer.
# 
# drivers/s390/cio/device.c
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +38 -17
#   s390: common i/o layer.
# 
# drivers/s390/cio/css.h
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +1 -0
#   s390: common i/o layer.
# 
# drivers/s390/cio/blacklist.c
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +41 -23
#   s390: common i/o layer.
# 
# Documentation/s390/driver-model.txt
#   2004/03/17 04:02:25-08:00 akpm@osdl.org +1 -1
#   s390: common i/o layer.
# 
# ChangeSet
#   2004/03/17 07:07:50-08:00 akpm@osdl.org 
#   [PATCH] s390: core
#   
#   From: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   
#   s390 core changes:
#    - Merge 31 and 64 bit NR_CPUS config option. Default to 32 cpus.
#    - Remove unused system calls from compat_linux.c.
#    - Add statfs64 and fstatfs64. Reserve system call number for
#      remap_file_pages.
#    - Merge do_signal32 into do_signal.
#    - Don't remove the per bit and the program mask from the user psw
#      due to a signal.
#    - Fix a problem with gdb and interrupted system calls.
#    - Fix single stepping of interrupted system calls.
#    - Fix compiler warnings in bitops.h.
# 
# kernel/signal.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +2 -1
#   s390: core
# 
# kernel/exit.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +2 -1
#   s390: core
# 
# include/asm-s390/unistd.h
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +4 -1
#   s390: core
# 
# include/asm-s390/ptrace.h
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +8 -0
#   s390: core
# 
# include/asm-s390/lowcore.h
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +4 -0
#   s390: core
# 
# include/asm-s390/bitops.h
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +8 -8
#   s390: core
# 
# arch/s390/kernel/traps.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +1 -21
#   s390: core
# 
# arch/s390/kernel/syscalls.S
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +3 -1
#   s390: core
# 
# arch/s390/kernel/sys_s390.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +1 -46
#   s390: core
# 
# arch/s390/kernel/signal.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +56 -48
#   s390: core
# 
# arch/s390/kernel/ptrace.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +6 -6
#   s390: core
# 
# arch/s390/kernel/entry64.S
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +9 -3
#   s390: core
# 
# arch/s390/kernel/entry.S
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +11 -5
#   s390: core
# 
# arch/s390/kernel/compat_wrapper.S
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +15 -0
#   s390: core
# 
# arch/s390/kernel/compat_signal.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +7 -85
#   s390: core
# 
# arch/s390/kernel/compat_linux.h
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +5 -0
#   s390: core
# 
# arch/s390/kernel/compat_linux.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +0 -50
#   s390: core
# 
# arch/s390/kernel/asm-offsets.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +4 -0
#   s390: core
# 
# arch/s390/Kconfig
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +2 -15
#   s390: core
# 
# ChangeSet
#   2004/03/17 07:07:38-08:00 akpm@osdl.org 
#   [PATCH] ppc64: run bitops.c through Lindent
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   bitops.c was a bit of a mess wrt formatting so run it through Lindent.  No
#   code changes.
# 
# arch/ppc64/kernel/bitops.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +39 -36
#   ppc64: run bitops.c through Lindent
# 
# ChangeSet
#   2004/03/17 07:07:29-08:00 akpm@osdl.org 
#   [PATCH] ppc32: Fix thinko in PCI_DMA_FOO to DMA_FOO conversion
#   
#   From: Tom Rini <trini@kernel.crashing.org>
#   
#   When I converted the use of PCI_DMA_foo constants to DMA_foo constants, I
#   forgot that it's PCI_DMA_FROMDEVICE and DMA_FROM_DEVICE.  The following
#   fixes that.
# 
# arch/ppc/mm/cachemap.c
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +1 -1
#   ppc32: Fix thinko in PCI_DMA_FOO to DMA_FOO conversion
# 
# ChangeSet
#   2004/03/17 07:07:19-08:00 akpm@osdl.org 
#   [PATCH] ppc32: Update <asm-ppc/dma-mapping.h>
#   
#   From: Tom Rini <trini@kernel.crashing.org>
#   
#   include/asm-ppc/dma-mapping.h was made to be a 'real' header recently and
#   therefore missed out on the updates that davem did to all of the other
#   versions.  This updates <asm-ppc/dma-mapping.h> to match what's expected
#   now.
# 
# include/asm-ppc/dma-mapping.h
#   2004/03/17 04:02:24-08:00 akpm@osdl.org +43 -9
#   ppc32: Update <asm-ppc/dma-mapping.h>
# 
# ChangeSet
#   2004/03/17 07:07:10-08:00 akpm@osdl.org 
#   [PATCH] ppc32: Fix PCI DMA API changes
#   
#   From: Tom Rini <trini@kernel.crashing.org>
#   
#   When Dave Miller updated <asm-ppc/pci.h> for the _for_device and _for_cpu
#   portions of the PCI DMA API, he assumed that on PPC32 consistent_sync*
#   would also need to be changed for device or cpu.  This is not the case, so
#   what this does is the pci_*_for_{cpu,device} calls call
#   consistent_sync{,page} again.
# 
# include/asm-ppc/pci.h
#   2004/03/17 04:02:23-08:00 akpm@osdl.org +6 -6
#   ppc32: Fix PCI DMA API changes
# 
# ChangeSet
#   2004/03/17 07:07:00-08:00 akpm@osdl.org 
#   [PATCH] ppc32: Fix c&p error in arch/ppc/syslib/indirect_pci.c
#   
#   From: Tom Rini <trini@kernel.crashing.org>
#   
#   Fix a cut & paste error in forward porting from 2.4, we don't reference
#   dev->bus or dev->devfn, both are passed as arguments.
# 
# arch/ppc/syslib/indirect_pci.c
#   2004/03/17 04:02:23-08:00 akpm@osdl.org +4 -4
#   ppc32: Fix c&p error in arch/ppc/syslib/indirect_pci.c
# 
# include/linux/proc_fs.h
#   2004/03/17 05:43:35-08:00 anton@samba.org +0 -4
#   fix ppc rtas compile
# 
# ChangeSet
#   2004/03/17 04:45:58-05:00 mcgrof@studorgs.rutgers.edu 
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/prism54/oid_mgt.c
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +1 -1
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/prism54/islpci_mgt.h
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +3 -1
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/prism54/islpci_mgt.c
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +2 -1
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/prism54/islpci_hotplug.c
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +11 -3
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +6 -1
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/prism54/isl_oid.h
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +124 -6
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +64 -9
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# drivers/net/wireless/Kconfig
#   2004/03/17 04:45:53-05:00 mcgrof@studorgs.rutgers.edu +8 -7
#   [wireless prism54] several minor updates
#   
#   Here is the ChangeLog:
#   
#   	* wireless/Kconfig: fix typos, add SMC2835W-V2
#   	* islpci_hotplug.c: new version 1.1, authors list, and
#   	module description updated appropriately
#   	* isl_ioctl.c, islpci_dev.c, 
#   	islpci_eth.c, islpci_hotplug.c, islpci_mgt.c: 
#   	s/ndev->priv/netdev_priv(ndev)/g
#   	* islpci_hotplug.c: Add PCI ID values for SMC2835W-V2 cardbus card
#   	Patch by Manuel Lauss <manuel.lauss@fh-hagenberg.at>
#   	* isl_38xx.[ch]: include firmware.h in header, remove
#   	declaration of headers in c file. Fix compiler warnings.
#   	* islpci_dev.c (islpci_alloc_memory),
#   	* islpci_eth.c (islpci_eth_cleanup_transmit, 
#   	islpci_eth_transmit, islpci_eth_receive): deal with skb stray 
#   	pointer, declare NULL.
#   	* isl_38xx.c: remove unecessary __KERNEL_SYSCALLS__ and
#   	re-ordered headers per vger.kernel.org - liking.
#   	* isl_ioctl.c, islpci_mgt.c: move from MODULE_PARAM to the new
#   	module_param, which is type-safe. Includes the new 
#   	<linux/moduleparam.h>.
#   	* isl_ioctl.c (prism54_[s|g]et_[maxframeburst|profile]): added.
#   	Not adding ioctls as ajfa is working on moving current private ioctls
#   	to subioctls.
#   	* isl_oid.h (dot11_[maxframeburst|preamblesettings|
#   	slotsettings|nonerpstatus|nonerpprotection]_t): added.
#   	Note: more ioctls can be added here, I believe problems
#   	with mixed modes can be pinpointed here, with these values.
# 
# ChangeSet
#   2004/03/17 04:38:28-05:00 mcgrof@studorgs.rutgers.edu 
#   [wireless prism54] use netdev_priv() helper
# 
# drivers/net/wireless/prism54/islpci_mgt.c
#   2004/03/17 04:38:23-05:00 mcgrof@studorgs.rutgers.edu +5 -5
#   [wireless prism54] use netdev_priv() helper
# 
# drivers/net/wireless/prism54/islpci_hotplug.c
#   2004/03/17 04:38:23-05:00 mcgrof@studorgs.rutgers.edu +5 -5
#   [wireless prism54] use netdev_priv() helper
# 
# drivers/net/wireless/prism54/islpci_eth.c
#   2004/03/17 04:38:23-05:00 mcgrof@studorgs.rutgers.edu +2 -2
#   [wireless prism54] use netdev_priv() helper
# 
# drivers/net/wireless/prism54/islpci_dev.c
#   2004/03/17 04:38:23-05:00 mcgrof@studorgs.rutgers.edu +3 -3
#   [wireless prism54] use netdev_priv() helper
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2004/03/17 04:38:23-05:00 mcgrof@studorgs.rutgers.edu +49 -48
#   [wireless prism54] use netdev_priv() helper
# 
# ChangeSet
#   2004/03/16 20:53:43-08:00 ak@suse.de 
#   [PATCH] Fix memory corruption on hyperthreaded x86-64 machines
#   
#   Fix memory corruption in the HT init on x86-64 recently introduced by me.
#   
#   Fix from from Suresh B. Siddha.
# 
# include/asm-x86_64/smp.h
#   2004/03/16 19:01:26-08:00 ak@suse.de +1 -0
#   Fix memory corruption on hyperthreaded x86-64 machines
# 
# arch/x86_64/kernel/setup.c
#   2004/03/16 19:01:41-08:00 ak@suse.de +0 -3
#   Fix memory corruption on hyperthreaded x86-64 machines
# 
# ChangeSet
#   2004/03/16 20:53:34-08:00 chyang@clusterfs.com 
#   [PATCH] Make intermezzo work again
#   
#    - Chen Yang's fix to work with NGROUPS
#    - Chen Yang's fix to handle file deletion
#    - Remove TCGETS handling and return  -ENOTTY for unknown ioctl code.
#    - Removed InterMezzo from BROKEN state
# 
# fs/intermezzo/vfs.c
#   2004/03/16 06:30:04-08:00 chyang@clusterfs.com +2 -6
#   Make intermezzo work again
# 
# fs/intermezzo/kml_reint.c
#   2004/03/15 08:08:48-08:00 chyang@clusterfs.com +4 -4
#   Make intermezzo work again
# 
# fs/intermezzo/journal.c
#   2004/03/15 08:11:06-08:00 chyang@clusterfs.com +22 -22
#   Make intermezzo work again
# 
# fs/intermezzo/intermezzo_kml.h
#   2004/03/15 08:10:35-08:00 chyang@clusterfs.com +1 -1
#   Make intermezzo work again
# 
# fs/intermezzo/intermezzo_fs.h
#   2004/03/15 08:10:20-08:00 chyang@clusterfs.com +13 -11
#   Make intermezzo work again
# 
# fs/intermezzo/fileset.c
#   2004/03/15 06:29:48-08:00 chyang@clusterfs.com +1 -1
#   Make intermezzo work again
# 
# fs/intermezzo/file.c
#   2004/03/15 06:25:09-08:00 chyang@clusterfs.com +3 -3
#   Make intermezzo work again
# 
# fs/intermezzo/dir.c
#   2004/03/16 06:26:24-08:00 chyang@clusterfs.com +1 -5
#   Make intermezzo work again
# 
# fs/Kconfig
#   2004/03/16 06:17:55-08:00 chyang@clusterfs.com +1 -1
#   Make intermezzo work again
# 
# ChangeSet
#   2004/03/16 18:54:46-08:00 anton@samba.org 
#   [PATCH] fix ppc rtas compile
#   
#   The proc_rtas_init call in procfs was removed (replaced with an
#   initcall) but the prototype was still hiding. Kill it.
# 
# ChangeSet
#   2004/03/16 16:47:04-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] hpt366.c: DMA timeout fix for HPT374
#   
#   From: Andre Hedrick <andre@linux-ide.org>
#   
#   Tested on Epox 8K9A3+ and 4PCA3+ by Tomi Orava <Tomi.Orava@ncircle.nullnet.fi>.
# 
# drivers/ide/pci/hpt366.c
#   2004/03/16 13:02:16-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +31 -4
#   hpt366.c: DMA timeout fix for HPT374
# 
# ChangeSet
#   2004/03/16 16:46:50-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] ATI IXP IDE support
#   
#   It was tested by a few people and has been in -mm since 2.6.4-rc2-mm1.
# 
# drivers/ide/pci/atiixp.c
#   2004/03/16 12:49:40-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +512 -0
#   ATI IXP IDE support
# 
# include/linux/pci_ids.h
#   2004/03/16 12:49:40-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +2 -0
#   ATI IXP IDE support
# 
# drivers/ide/pci/atiixp.c
#   2004/03/16 12:49:40-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -0
#   BitKeeper file /home/torvalds/v2.5/linux/drivers/ide/pci/atiixp.c
# 
# drivers/ide/pci/Makefile
#   2004/03/16 12:49:40-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -0
#   ATI IXP IDE support
# 
# drivers/ide/Kconfig
#   2004/03/16 12:49:40-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +10 -0
#   ATI IXP IDE support
# 
# ChangeSet
#   2004/03/16 16:46:39-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] remove dead "hdXlun=" kernel parameter
# 
# include/linux/ide.h
#   2004/03/16 12:30:15-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -2
#   remove dead "hdXlun=" kernel parameter
# 
# drivers/ide/ide.c
#   2004/03/16 12:30:15-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -16
#   remove dead "hdXlun=" kernel parameter
# 
# drivers/ide/ide-probe.c
#   2004/03/16 12:30:15-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -3
#   remove dead "hdXlun=" kernel parameter
# 
# Documentation/ide.txt
#   2004/03/16 12:30:15-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -2
#   remove dead "hdXlun=" kernel parameter
# 
# ChangeSet
#   2004/03/16 16:46:25-08:00 B.Zolnierkiewicz@elka.pw.edu.pl 
#   [PATCH] ide-scsi.c: fix ATAPI multi-lun support
#   
#   ATAPI multi-lun support has been broken for a long time.
#   
#   It used to be that "(drive->id->last_id & 0x7) + 1" was used as
#   shost->max_lun and the "hdXlun=" kernel parameter could be used to
#   override this value.
#   
#   However it was far from optimal:
#   - people played with "hdXlun=" and then complained about multiple instances
#     of the same device (most ATAPI drives respond to each LUN)
#   - probably some devices return 7 not 0 in id->last_id (=> 7 x same device)
#   
#   This patch from Willem Riede <wrlk@riede.org> fixes it w/o need
#   for "hdXlun=" option.  It was tested by Willem on ATAPI PD/CD drive.
# 
# drivers/scsi/ide-scsi.c
#   2004/03/16 12:21:04-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +10 -1
#   ide-scsi.c: fix ATAPI multi-lun support
# 
# ChangeSet
#   2004/03/16 16:38:36-08:00 rusty@rustcorp.com.au 
#   [PATCH] wait_task_inactive should not return on preempt
#   
#   wait_task_inactive is now only used in two non-time-critical places: the
#   ptrace code to guarantee a schedule and kthread_bind so we can change
#   the thread CPU.  Unfortunately with preempt, the code as stands has a
#   race: we might return because the thread is preempted, not because it
#   actually reached schedule().  The ptrace code (probably) doesn't care,
#   but the kthread code does.
#   
#   This patch simplifies the (now over-optimized) code, and does a yield()
#   for the preemption case.
# 
# kernel/sched.c
#   2004/03/16 14:54:38-08:00 rusty@rustcorp.com.au +8 -15
#   wait_task_inactive should not return on preempt
# 
# ChangeSet
#   2004/03/16 14:57:47-08:00 greg@kroah.com 
#   Merge kroah.com:/home/greg/linux/BK/bleed-2.6
#   into kroah.com:/home/greg/linux/BK/usb-2.6
# 
# drivers/usb/input/wacom.c
#   2004/03/16 14:57:44-08:00 greg@kroah.com +0 -4
#   Auto merged
# 
# drivers/usb/input/hid-core.c
#   2004/03/16 14:57:43-08:00 greg@kroah.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 14:44:49-08:00 katzj@redhat.com 
#   [PATCH] Fix blkpg ioctl32 handling
#   
#   Simple obvious patch so that all calls to blkpg from the non-native
#   environment don't get -EINVAL
# 
# fs/compat_ioctl.c
#   2004/03/16 13:12:40-08:00 katzj@redhat.com +1 -0
#   Fix blkpg ioctl32 handling
# 
# ChangeSet
#   2004/03/16 16:02:52-05:00 ralf@linux-mips.org 
#   [hamradio 6pack] cleanup
# 
# drivers/net/hamradio/6pack.c
#   2004/03/16 16:02:47-05:00 ralf@linux-mips.org +542 -545
#   [hamradio 6pack] cleanup
# 
# ChangeSet
#   2004/03/16 16:02:01-05:00 jgarzik@redhat.com 
#   [blk carmel] call del_gendisk(), if disk is 'up', at cleanup time
# 
# drivers/block/carmel.c
#   2004/03/16 16:01:56-05:00 jgarzik@redhat.com +3 -0
#   [blk carmel] call del_gendisk(), if disk is 'up', at cleanup time
# 
# ChangeSet
#   2004/03/16 12:44:45-08:00 torvalds@ppc970.osdl.org 
#   Remove bogus linux/irq.h include that fails build on ARM.
#   
#   Verified to not break anything on x86 either.
# 
# include/linux/netpoll.h
#   2004/03/16 12:44:40-08:00 torvalds@ppc970.osdl.org +0 -1
#   Remove bogus linux/irq.h include that fails build on ARM.
# 
# ChangeSet
#   2004/03/16 15:36:03-05:00 mpm@selenic.com 
#   [PATCH] fix netpoll warning in tulip
#   
#   On Tue, Mar 16, 2004 at 12:36:02PM +0200, Meelis Roos wrote:
#   > FYI: with netpoll configured out, I get
#   >
#   >   CC [M]  drivers/net/tulip/tulip_core.o
#   > drivers/net/tulip/tulip_core.c:256: warning: `poll_tulip' declared `static' but never defined
# 
# drivers/net/tulip/tulip_core.c
#   2004/03/16 14:22:30-05:00 mpm@selenic.com +2 -1
#   Re: netpoll warning in tulip
# 
# ChangeSet
#   2004/03/16 15:35:54-05:00 scott.feldman@intel.com 
#   [PATCH] update e100.txt
#   
#   * e100.txt needs to refer to the v3 driver and its settings.
#     Spotted by Calum Mackay [calum.mackay@cdmnet.org]
# 
# Documentation/networking/e100.txt
#   2004/03/15 14:19:29-05:00 scott.feldman@intel.com +2 -193
#   update e100.txt
# 
# ChangeSet
#   2004/03/16 15:15:18-05:00 jgarzik@redhat.com 
#   [netdrvr natsemi] Fix RX DMA mapping
#   
#   RX skbs are always considered maximally sized, until actual reception
#   of the RX frame occurs.  So, update this driver to always map and
#   unmap a maximally sized skb.  This fixes this driver on several
#   non-x86 platforms.
# 
# drivers/net/natsemi.c
#   2004/03/16 15:13:56-05:00 jgarzik@redhat.com +13 -9
#   [netdrvr natsemi] Fix RX DMA mapping
#   
#   RX skbs are always considered maximally sized, until actual reception
#   of the RX frame occurs.  So, update this driver to always map and
#   unmap a maximally sized skb.  This fixes this driver on several
#   non-x86 platforms.
# 
# ChangeSet
#   2004/03/16 14:02:51-06:00 shaggy@austin.ibm.com 
#   JFS: zero new log pages, etc.
# 
# fs/jfs/super.c
#   2004/03/16 14:02:36-06:00 shaggy@austin.ibm.com +1 -1
#   zero jfs incore inode
# 
# fs/jfs/jfs_metapage.c
#   2004/03/16 14:02:36-06:00 shaggy@austin.ibm.com +4 -0
#   zero new metadata pages
# 
# fs/jfs/jfs_logmgr.c
#   2004/03/16 14:02:36-06:00 shaggy@austin.ibm.com +1 -1
#   zero new log pages
# 
# ChangeSet
#   2004/03/16 11:55:27-08:00 ahaas@airmail.net 
#   [IPVS]: Add C99 initializers to net/ipv4/ipvs/ip_vs_lblcr.c
# 
# net/ipv4/ipvs/ip_vs_lblcr.c
#   2004/03/16 11:55:14-08:00 ahaas@airmail.net +41 -21
#   [IPVS]: Add C99 initializers to net/ipv4/ipvs/ip_vs_lblcr.c
# 
# ChangeSet
#   2004/03/16 11:54:39-08:00 ahaas@airmail.net 
#   [IPVS]: Add C99 initializers to net/ipv4/ipvs/ip_vs_lblc.c
# 
# net/ipv4/ipvs/ip_vs_lblc.c
#   2004/03/16 11:54:26-08:00 ahaas@airmail.net +41 -21
#   [IPVS]: Add C99 initializers to net/ipv4/ipvs/ip_vs_lblc.c
# 
# ChangeSet
#   2004/03/16 11:53:40-08:00 ahaas@airmail.net 
#   [IPVS]: Add C99 initializers to ip_vs_ctl.c
# 
# net/ipv4/ipvs/ip_vs_ctl.c
#   2004/03/16 11:50:24-08:00 ahaas@airmail.net +219 -88
#   [IPVS]: Add C99 initializers to ip_vs_ctl.c
# 
# ChangeSet
#   2004/03/16 11:28:52-08:00 greg@kroah.com 
#   [PATCH] USB: replace kobject with kref in usb-serial core.
#   
#   This saves some memory and is easier to understand what is happening.
# 
# drivers/usb/serial/usb-serial.h
#   2004/03/16 02:59:48-08:00 greg@kroah.com +3 -2
#   USB: replace kobject with kref in usb-serial core.
# 
# drivers/usb/serial/usb-serial.c
#   2004/03/16 03:00:22-08:00 greg@kroah.com +9 -16
#   USB: replace kobject with kref in usb-serial core.
# 
# ChangeSet
#   2004/03/16 10:22:41-08:00 bjorn_helgaas@hp.com 
#   [PATCH] ia64: fix up DMA API breakage in generic build
#   
#   We also need the following patch to build the generic_defconfig
#   after the DMA API change:
#       http://linux.bkbits.net:8080/linux-2.5/cset@405490e15inT3T0H2x887j9SaMkYRQ
# 
# include/asm-ia64/machvec.h
#   2004/03/15 07:53:54-08:00 bjorn_helgaas@hp.com +4 -4
#   ia64: fix up DMA API breakage in generic build
# 
# ChangeSet
#   2004/03/16 10:14:07-08:00 greg@kroah.com 
#   Merge kroah.com:/home/linux/BK/bleed-2.6
#   into kroah.com:/home/linux/BK/usb-2.6
# 
# include/linux/usb_gadget.h
#   2004/03/16 10:14:00-08:00 greg@kroah.com +0 -0
#   Auto merged
# 
# include/linux/usb.h
#   2004/03/16 10:14:00-08:00 greg@kroah.com +0 -0
#   Auto merged
# 
# drivers/usb/core/usb.c
#   2004/03/16 10:14:00-08:00 greg@kroah.com +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/03/16 10:13:59-08:00 greg@kroah.com +0 -0
#   Auto merged
# 
# CREDITS
#   2004/03/16 10:13:59-08:00 greg@kroah.com +0 -0
#   Auto merged
# 
# arch/ppc64/kernel/pmac_iommu.c
#   2004/03/16 09:45:10-08:00 benh@kernel.crashing.org +5 -2
#   g5: Fix iommu vs. pci_device_to_OF_node
# 
# ChangeSet
#   2004/03/16 12:30:29-05:00 jgarzik@redhat.com 
#   [blk carmel] add copyright statement and license mention
# 
# drivers/block/carmel.c
#   2004/03/16 12:29:06-05:00 jgarzik@redhat.com +12 -1
#   [blk carmel] add copyright statement and license mention
# 
# ChangeSet
#   2004/03/16 08:07:17-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/vojtech/input
#   into ppc970.osdl.org:/home/torvalds/v2.5/linux
# 
# Documentation/kernel-parameters.txt
#   2004/03/16 08:07:14-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 07:51:27-08:00 axboe@suse.de 
#   [PATCH] allow random write to cdrom devices with profile 2 (removable disk)
#   
#   This patch is from Iomega, and it allows random write opens of CDROM's
#   that support the feature.
# 
# include/linux/cdrom.h
#   2004/03/16 00:39:41-08:00 axboe@suse.de +32 -1
#   allow random write to cdrom devices with profile 2 (removable disk)
# 
# drivers/scsi/sr.c
#   2004/03/16 00:39:41-08:00 axboe@suse.de +8 -3
#   allow random write to cdrom devices with profile 2 (removable disk)
# 
# drivers/ide/ide-cd.c
#   2004/03/16 00:39:41-08:00 axboe@suse.de +6 -1
#   allow random write to cdrom devices with profile 2 (removable disk)
# 
# drivers/cdrom/cdrom.c
#   2004/03/16 00:41:01-08:00 axboe@suse.de +99 -0
#   allow random write to cdrom devices with profile 2 (removable disk)
# 
# ChangeSet
#   2004/03/16 07:29:37-08:00 akpm@osdl.org 
#   [PATCH] ppc64: fix for massive OF properties
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   We have some versions of firmware out there that have huge OF properties.
#   So huge that we end up overwriting our initrd.
#   
#   Place a 1MB limit and warn bitterly if its over this.  Also fix a use of
#   package-to-path where the variable was 64bytes but we would pass in a
#   length of 255.
# 
# arch/ppc64/kernel/prom.c
#   2004/03/16 03:30:39-08:00 akpm@osdl.org +33 -3
#   ppc64: fix for massive OF properties
# 
# ChangeSet
#   2004/03/16 07:29:25-08:00 akpm@osdl.org 
#   [PATCH] ppc64 defconfig update
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   ppc64 defconfig update
# 
# arch/ppc64/defconfig
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +27 -15
#   ppc64 defconfig update
# 
# arch/ppc64/configs/pSeries_defconfig
#   2004/03/16 03:30:39-08:00 akpm@osdl.org +27 -15
#   ppc64 defconfig update
# 
# arch/ppc64/configs/iSeries_defconfig
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +20 -4
#   ppc64 defconfig update
# 
# ChangeSet
#   2004/03/16 07:29:15-08:00 akpm@osdl.org 
#   [PATCH] Fix hvc console sleep in spinlock bug
#   
#   From: Jeremy Kerr <jk@ozlabs.org>
#   
#   This patch fixes the sleep in spinlock hvc bug in hvc_write().
#   
#   The code is a little longer, but protects against large amounts of memory
#   being kmalloc()ed by userspace, and minimises calls to copy_from_user().
# 
# drivers/char/hvc_console.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +52 -18
#   Fix hvc console sleep in spinlock bug
# 
# ChangeSet
#   2004/03/16 07:29:03-08:00 akpm@osdl.org 
#   [PATCH] Clean up xmon backtrace code.
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Clean up xmon backtrace code, it was doing all manner of scary things.
# 
# arch/ppc64/xmon/xmon.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +57 -79
#   Clean up xmon backtrace code.
# 
# ChangeSet
#   2004/03/16 07:28:51-08:00 akpm@osdl.org 
#   [PATCH] Cleanup ppc64 procfs code
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Cleanup ppc64 procfs code:
#   
#   - Use initcalls everywhere. This allowed us to remove the iseries proc
#     callback interface.
#   - Kill proc_pmc.c. Most of it wasnt used (and we are planning to export the
#     PMCs via sysfs). The few things left were iseries specific so they
#     got moved into iSeries_proc.c.
#   - Kill pmc.c. We dont use those statistics and the ones that are left
#     can be gained via PMCs.
#   - Create /proc/iSeries and /proc/ppc64 very early. This means we no
#     longer have to call proc_ppc64_init in all the drivers, we can
#     assume its there.
#   - Fix some error return cases in rtas-proc.c and rtas-flash
#   - Dont even try some pseries specific drivers on pmac.
# 
# include/asm-ppc64/iSeries/mf.h
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -2
#   Cleanup ppc64 procfs code
# 
# include/asm-ppc64/iSeries/iSeries_proc.h
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -6
#   Cleanup ppc64 procfs code
# 
# fs/proc/root.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -3
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/mm/init.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -1
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/mm/hash_utils.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -1
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/viopath.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +50 -51
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/scanlog.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +1 -11
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/rtasd.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +7 -11
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/rtas_flash.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +62 -32
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/rtas.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -1
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/rtas-proc.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +36 -40
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/ras.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -1
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/proc_ppc64.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +69 -82
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -2
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/mf_proc.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +14 -10
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/mf.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -3
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/iSeries_setup.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +0 -4
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/iSeries_proc.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +146 -117
#   Cleanup ppc64 procfs code
# 
# arch/ppc64/kernel/Makefile
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +2 -2
#   Cleanup ppc64 procfs code
# 
# arch/ppc/platforms/proc_rtas.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +7 -3
#   Cleanup ppc64 procfs code
# 
# BitKeeper/deleted/.del-proc_pmc.h~fa188a01cdbd56f2
#   2004/03/16 07:28:45-08:00 akpm@osdl.org +0 -0
#   Delete: include/asm-ppc64/proc_pmc.h
# 
# BitKeeper/deleted/.del-proc_pmc.c~1b91b529be9350c0
#   2004/03/16 07:28:45-08:00 akpm@osdl.org +0 -0
#   Delete: arch/ppc64/kernel/proc_pmc.c
# 
# BitKeeper/deleted/.del-proc_fs.h~68528c7caf0c1ef1
#   2004/03/16 07:28:45-08:00 akpm@osdl.org +0 -0
#   Delete: include/asm-ppc64/proc_fs.h
# 
# BitKeeper/deleted/.del-pmc.h~5f711a1118f8f38
#   2004/03/16 07:28:45-08:00 akpm@osdl.org +0 -0
#   Delete: include/asm-ppc64/pmc.h
# 
# BitKeeper/deleted/.del-pmc.c~e5a1dd618650f12b
#   2004/03/16 07:28:44-08:00 akpm@osdl.org +0 -0
#   Delete: arch/ppc64/kernel/pmc.c
# 
# ChangeSet
#   2004/03/16 07:28:37-08:00 akpm@osdl.org 
#   [PATCH] Add kernel version to oops.
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Add kernel version to oops.
# 
# arch/ppc64/kernel/process.c
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +3 -2
#   Add kernel version to oops.
# 
# ChangeSet
#   2004/03/16 07:28:25-08:00 akpm@osdl.org 
#   [PATCH] Fixed NULL ptr deref in RTAS syscall ppc_rtas()
#   
#   From: John Rose <johnrose@austin.ibm.com>
#   
#   Fixed NULL ptr deref in RTAS syscall ppc_rtas()
# 
# arch/ppc64/kernel/rtas.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +8 -5
#   Fixed NULL ptr deref in RTAS syscall ppc_rtas()
# 
# ChangeSet
#   2004/03/16 07:28:13-08:00 akpm@osdl.org 
#   [PATCH] Added rtas_set_power_level()
#   
#   From: John Rose <johnrose@austin.ibm.com>
#   
#   Added rtas_set_power_level()
# 
# include/asm-ppc64/rtas.h
#   2004/03/16 03:30:38-08:00 akpm@osdl.org +1 -0
#   Added rtas_set_power_level()
# 
# arch/ppc64/kernel/rtas.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +28 -0
#   Added rtas_set_power_level()
# 
# ChangeSet
#   2004/03/16 07:28:03-08:00 akpm@osdl.org 
#   [PATCH] Remove pci DMA exports
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Remove pci DMA exports we now access them via inline functions that
#   operate on pci_dma_ops.
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +0 -9
#   Remove pci DMA exports
# 
# ChangeSet
#   2004/03/16 07:27:52-08:00 akpm@osdl.org 
#   [PATCH] Dont enable interrupts during interrupt processing on iseries
#   
#   From: Stephen Rothwell <sfr@canb.auug.org.au>
#   
#   Dont enable interrupts during interrupt processing on iseries
# 
# arch/ppc64/kernel/irq.c
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +4 -0
#   Dont enable interrupts during interrupt processing on iseries
# 
# ChangeSet
#   2004/03/16 07:27:40-08:00 akpm@osdl.org 
#   [PATCH] Add slow path lookup in xics_get_irq
#   
#   From: Jake Moilanen <moilanen@austin.ibm.com>
#   
#   In xics_get_irq(), for a real-to-virt irq lookup, go down the
#   slowpath by looking through the entire virt_irq_to_real_map array
#   if take a miss on the radix tree.  This is possible, when an
#   interrupt is taken before the driver has called request_irq() (eg IDE).
# 
# arch/ppc64/kernel/xics.c
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +4 -0
#   Add slow path lookup in xics_get_irq
# 
# arch/ppc64/kernel/irq.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +33 -0
#   Add slow path lookup in xics_get_irq
# 
# ChangeSet
#   2004/03/16 07:27:28-08:00 akpm@osdl.org 
#   [PATCH] Export find_next_bit
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   - export find_next_bit and move the other exports here
#   - fix a few minor style issues
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +0 -3
#   Export find_next_bit
# 
# arch/ppc64/kernel/bitops.c
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +13 -7
#   Export find_next_bit
# 
# ChangeSet
#   2004/03/16 07:27:18-08:00 akpm@osdl.org 
#   [PATCH] update iseries default target
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   update iseries default target
# 
# arch/ppc64/Makefile
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +1 -1
#   update iseries default target
# 
# ChangeSet
#   2004/03/16 07:27:05-08:00 akpm@osdl.org 
#   [PATCH] Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
#   
#   From: Stephen Rothwell <sfr@canb.auug.org.au>
#   
#   After this the only iSeries specific EXPORT_SYMBOLS in ppc_ksyms.c are
#   the assembler ones ...
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +1 -24
#   Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
# 
# arch/ppc64/kernel/mf.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +3 -0
#   Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
# 
# arch/ppc64/kernel/iSeries_proc.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +2 -0
#   Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
# 
# arch/ppc64/kernel/iSeries_pci_reset.c
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +2 -0
#   Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
# 
# arch/ppc64/kernel/iSeries_pci.c
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +10 -0
#   Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
# 
# arch/ppc64/kernel/iSeries_VpdInfo.c
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +2 -0
#   Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
# 
# arch/ppc64/kernel/HvLpConfig.c
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +2 -3
#   Move iSeries specific EXPORT_SYMBOLs out of ppc_ksyms.c
# 
# ChangeSet
#   2004/03/16 07:26:54-08:00 akpm@osdl.org 
#   [PATCH] Add some functions to make vio.h consistant with pci_dma.h and dma_mapping.h
#   
#   From: Dave Boutcher <boutcher@us.ibm.com>
#   
#   Add some functions to make vio.h consistant with pci_dma.h and dma_mapping.h
# 
# include/asm-ppc64/vio.h
#   2004/03/16 03:30:37-08:00 akpm@osdl.org +31 -0
#   Add some functions to make vio.h consistant with pci_dma.h and dma_mapping.h
# 
# ChangeSet
#   2004/03/16 07:26:41-08:00 akpm@osdl.org 
#   [PATCH] Fix xics IRQ affinity
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   - Merge some whitespace differences with the ameslab tree
#   - We check for CPU_MASK_ALL in xics to send irqs to all cpus.
#     In some cases CPU_MASK_ALL is smaller than the cpumask (eg
#     NR_CPUS == 32 and cpumask is a long), so we mask it here to
#     be consistent.
# 
# arch/ppc64/kernel/irq.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +19 -9
#   Fix xics IRQ affinity
# 
# ChangeSet
#   2004/03/16 07:26:29-08:00 akpm@osdl.org 
#   [PATCH] Fix multiple EEH-related bugs
#   
#   From: Linas Vepstas <linas@austin.ibm.com>
#   
#   This patch fixes multiple EEH-related bugs:
#   
#    - Fixes the eeh_check_failure() usage in an interrupt context.
#      This routine is now safe to use in an interrupt. The fix was to
#      build a cache of IO addresses and check that, instead of using
#      the pci routines.
#    - Merges in Olof Johansson's sizeof patch when checking for failure
#    - Adds EEH tests to array/string reads
#    - Fixes bugs with address resolution (some i/o addresses were handled
#      incorrectly, resulting in EEH errors slipping by undetected.)
#    - Adds EEH support to the PCI Hotplug system (so that devices that
#      get added/removed get properly registered with the EEH subsystem.)
#    - Fixes improper use of /proc filesystem.
#    - Adds some misc statistics.
#   
#   While merging Linas' patch I also converted the proc usage to
#   seq_single, used per cpu variables for the stats and removed the
#   eeh-force-off option.
# 
# include/asm-ppc64/io.h
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +20 -8
#   Fix multiple EEH-related bugs
# 
# include/asm-ppc64/eeh.h
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +117 -56
#   Fix multiple EEH-related bugs
# 
# drivers/pci/hotplug/rpaphp_core.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +1 -0
#   Fix multiple EEH-related bugs
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2004/03/16 03:31:51-08:00 akpm@osdl.org +0 -4
#   Fix multiple EEH-related bugs
# 
# arch/ppc64/kernel/pci.h
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +4 -1
#   Fix multiple EEH-related bugs
# 
# arch/ppc64/kernel/pci.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +4 -37
#   Fix multiple EEH-related bugs
# 
# arch/ppc64/kernel/eeh.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +536 -139
#   Fix multiple EEH-related bugs
# 
# ChangeSet
#   2004/03/16 07:26:19-08:00 akpm@osdl.org 
#   [PATCH] Fix for hotplug of multifunction cards.
#   
#   From: Linda Xie <lxiep@us.ibm.com>
#   
#   The changes in this patch are for multifunction cards insertions/removals
#   and  bug fixes:
#   
#   1. fix up new nodes' linux_phandle field.
#   2. new nodes' phb, devfn(and so on) need to be fixed even the nodes don't
#   	have "interrupts".
#   3. change of_remove_node to non-recurisve func. The recursions will be done
#   	by the caller.
#   4. add a new function -- of_finish_dynamic_node_interrupts()
# 
# arch/ppc64/kernel/prom.c
#   2004/03/16 03:31:49-08:00 akpm@osdl.org +59 -75
#   Fix for hotplug of multifunction cards.
# 
# ChangeSet
#   2004/03/16 07:26:08-08:00 akpm@osdl.org 
#   [PATCH] Add some missing EXPORT_SYMBOLs
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Add some missing EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/vio.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +1 -2
#   Add some missing EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2004/03/16 03:31:51-08:00 akpm@osdl.org +2 -0
#   Add some missing EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/pSeries_lpar.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +6 -0
#   Add some missing EXPORT_SYMBOLs
# 
# ChangeSet
#   2004/03/16 07:25:57-08:00 akpm@osdl.org 
#   [PATCH] Handle longbusy return codes in IBM VETH driver
#   
#   From: Santiago Leon <santil@us.ibm.com>
#   
#   Handle longbusy return codes in IBM VETH driver
# 
# drivers/net/ibmveth.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +11 -4
#   Handle longbusy return codes in IBM VETH driver
# 
# ChangeSet
#   2004/03/16 07:25:46-08:00 akpm@osdl.org 
#   [PATCH] Add hypervisor busy return codes
#   
#   From: Dave Boutcher <boutcher@us.ibm.com>
#   
#   Add hypervisor busy return codes
# 
# include/asm-ppc64/hvcall.h
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +22 -1
#   Add hypervisor busy return codes
# 
# ChangeSet
#   2004/03/16 07:25:35-08:00 akpm@osdl.org 
#   [PATCH] Make dma API handle PCI and VIO
#   
#   From: Stephen Rothwell <sfr@canb.auug.org.au>
#   
#   Make dma API handle PCI and VIO
# 
# arch/ppc64/kernel/dma.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +184 -0
#   Make dma API handle PCI and VIO
# 
# include/asm-ppc64/dma-mapping.h
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +75 -1
#   Make dma API handle PCI and VIO
# 
# arch/ppc64/kernel/dma.c
#   2004/03/16 03:30:36-08:00 akpm@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.5/linux/arch/ppc64/kernel/dma.c
# 
# arch/ppc64/kernel/Makefile
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +1 -1
#   Make dma API handle PCI and VIO
# 
# ChangeSet
#   2004/03/16 07:25:22-08:00 akpm@osdl.org 
#   [PATCH] Remove some unused ppc64 variables
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Remove some unused ppc64 variables
# 
# arch/ppc64/mm/init.c
#   2004/03/16 03:31:50-08:00 akpm@osdl.org +0 -2
#   Remove some unused ppc64 variables
# 
# ChangeSet
#   2004/03/16 07:25:10-08:00 akpm@osdl.org 
#   [PATCH] Remove bogus sys_oldumount sign extension code
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Remove bogus sys_oldumount sign extension code. We were sign extending
#   the flags argument which doesnt make sense.
# 
# arch/ppc64/kernel/sys_ppc32.c
#   2004/03/16 03:30:35-08:00 akpm@osdl.org +0 -11
#   Remove bogus sys_oldumount sign extension code
# 
# arch/ppc64/kernel/misc.S
#   2004/03/16 03:30:35-08:00 akpm@osdl.org +1 -1
#   Remove bogus sys_oldumount sign extension code
# 
# ChangeSet
#   2004/03/16 07:24:59-08:00 akpm@osdl.org 
#   [PATCH] Reduce stack overflow check to 4096 bytes
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Reduce stack overflow check to 4096 bytes free, we were tripping it
#   too much at 8192.
# 
# arch/ppc64/kernel/irq.c
#   2004/03/16 03:31:51-08:00 akpm@osdl.org +2 -2
#   Reduce stack overflow check to 4096 bytes
# 
# ChangeSet
#   2004/03/16 07:22:49-08:00 akpm@osdl.org 
#   [PATCH] iostats averaging fix
#   
#   From: Rick Lindsley <ricklind@us.ibm.com>
#   
#   Fix bug #2230.
#   
#   I've corresponded with the submitter and he did find a real bug -- when we
#   were merging I/O requests we didn't always take the oldest request start
#   time, which would cause a couple of the calculations like wait time and
#   average queue size to be too small.  He found it mathematically but having
#   done so, I think logic and inspection makes it easy to verify.
# 
# drivers/block/ll_rw_blk.c
#   2004/03/16 02:29:58-08:00 akpm@osdl.org +9 -0
#   iostats averaging fix
# 
# ChangeSet
#   2004/03/16 07:22:38-08:00 akpm@osdl.org 
#   [PATCH] blk: statically initialise the congestion waitqueue_heads
#   
#   On a really small memory machine (or one with a monstrous kernel memory leak)
#   we can end up calling blk_congestion_wait() before the waitqueue_heads are set
#   up.
# 
# drivers/block/ll_rw_blk.c
#   2004/03/16 02:43:49-08:00 akpm@osdl.org +4 -6
#   blk: statically initialise the congestion waitqueue_heads
# 
# ChangeSet
#   2004/03/16 07:22:26-08:00 akpm@osdl.org 
#   [PATCH] kill INIT_THREAD_SIZE
#   
#   From: Matt Mackall <mpm@selenic.com>
#   
#   This piece of the THREAD_SIZE cleanup got dropped.  If you make THREAD_SIZE
#   > 8k, the init thread overlaps the .init section and gets smashed.  I've
#   gone ahead and killed INIT_THREAD_SIZE throughout as it wasn't doing much.
#   This also saves 4k when we use 4k stacks.  Please apply.  Couple more minor
#   pieces remaining.
# 
# include/linux/sched.h
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +1 -5
#   kill INIT_THREAD_SIZE
# 
# include/asm-um/processor-generic.h
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +0 -2
#   kill INIT_THREAD_SIZE
# 
# include/asm-sparc/thread_info.h
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +0 -3
#   kill INIT_THREAD_SIZE
# 
# include/asm-arm26/thread_info.h
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +0 -2
#   kill INIT_THREAD_SIZE
# 
# arch/sparc64/kernel/init_task.c
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +0 -8
#   kill INIT_THREAD_SIZE
# 
# arch/parisc/kernel/process.c
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +1 -1
#   kill INIT_THREAD_SIZE
# 
# ChangeSet
#   2004/03/16 07:22:15-08:00 akpm@osdl.org 
#   [PATCH] kthreads hold files open
#   
#   keventd and friends are currently holding /dev/console open three times.
#   It's all inherited from init.
#   
#   Steal the relevant parts of daemonize() to fix that up.
# 
# kernel/kthread.c
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +18 -0
#   kthreads hold files open
# 
# ChangeSet
#   2004/03/16 07:22:03-08:00 akpm@osdl.org 
#   [PATCH] slab: fix display of object length in corruption detector
#   
#   From: Manfred Spraul <manfred@colorfullife.com>
#   
#   print_objinfo() dumps the first few characters of an interesting object for
#   debugging.  It used the wrong object len (including debug padding, instead
#   of just the data area), which could cause an oops if DEBUG_PAGEALLOC is
#   enabled.
# 
# mm/slab.c
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +1 -1
#   slab: fix display of object length in corruption detector
# 
# ChangeSet
#   2004/03/16 07:21:52-08:00 akpm@osdl.org 
#   [PATCH] document unchecked do_munmaps in ipc/shm.c
#   
#   From: Manfred Spraul <manfred@colorfullife.com>
#   
#   There are a few unchecked do_munmap()s in the shm code.  Manfred's comment
#   explains why they are OK.
# 
# ipc/shm.c
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +15 -0
#   document unchecked do_munmaps in ipc/shm.c
# 
# ChangeSet
#   2004/03/16 07:21:39-08:00 akpm@osdl.org 
#   [PATCH] do_write_mem() return value check
#   
#   From: BlaisorBlade <blaisorblade_spam@yahoo.it>, and me
#   
#   - remove unused `file *' arg from do_write_mem()
#   
#   - Add checking for copy_from_user() failures in do_write_mem()
#   
#   - Return correct value from kmem writes() when a fault is encountered.  A
#     write()-style syscall's return values are:
#   
#      0 when nothing was written and there was no error (someone tried to
#      write zero bytes)
#   
#      >0: the number of bytes copied, whether or not there was an error.
#      Userspace detects errors by noting that the write() return value is less
#      than was requested.
#   
#      <0: there was an error and no bytes were copied
# 
# drivers/char/mem.c
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +26 -9
#   do_write_mem() return value check
# 
# ChangeSet
#   2004/03/16 07:21:28-08:00 akpm@osdl.org 
#   [PATCH] resierfs: AIO support
#   
#   From: Chris Mason <mason@suse.com>
#   
#   reiserfs can safely use the generic fs aio functions.
# 
# fs/reiserfs/file.c
#   2004/03/16 02:29:47-08:00 akpm@osdl.org +10 -0
#   resierfs: AIO support
# 
# ChangeSet
#   2004/03/16 07:21:18-08:00 akpm@osdl.org 
#   [PATCH] reiserfs: atomicity fix
#   
#   From: Chris Mason <mason@suse.com>
#   
#   reiserfs_file_write() can use stale metadata after a schedule.
#   
#   Two reiserfs_file_write bugs, where items can change during a schedule.
# 
# fs/reiserfs/file.c
#   2004/03/16 02:43:50-08:00 akpm@osdl.org +8 -4
#   reiserfs: atomicity fix
# 
# ChangeSet
#   2004/03/16 07:21:05-08:00 akpm@osdl.org 
#   [PATCH] reiserfs: fix transaction sizes
#   
#   From: Chris Mason <mason@suse.com>
#   
#   Make sure reiserfs uses a reasonable number when restarting long unbounded
#   transactions (creating holes or deleting files).
#   
#   Without this patch, the number of blocks requested grows with each
#   transaction restart, until it hits MAX_BATCH_COUNT and starts forcing
#   commits with every new transaction.
#   
#   Oleg Drokin tracked this bug down
# 
# fs/reiserfs/stree.c
#   2004/03/16 02:29:46-08:00 akpm@osdl.org +1 -1
#   reiserfs: fix transaction sizes
# 
# fs/reiserfs/inode.c
#   2004/03/16 02:29:46-08:00 akpm@osdl.org +1 -1
#   reiserfs: fix transaction sizes
# 
# ChangeSet
#   2004/03/16 07:20:54-08:00 akpm@osdl.org 
#   [PATCH] reiserfs: search_by_key fix
#   
#   From: Chris Mason <mason@suse.com>
#   
#   Fix a bug in reiserfs search_by_key call, where it might not properly
#   detect a change in tree height during a schedule.  Originally from
#   vs@namesys.com
# 
# fs/reiserfs/stree.c
#   2004/03/16 02:43:50-08:00 akpm@osdl.org +10 -6
#   reiserfs: search_by_key fix
# 
# ChangeSet
#   2004/03/16 07:20:41-08:00 akpm@osdl.org 
#   [PATCH] resierfs: scheduling latency improvements
#   
#   From: Chris Mason <mason@suse.com>
#   
#   Add conditional schedules to reiserfs to help lower latencies.  Bits of
#   this orginated long ago in code akpm sent me.
# 
# include/linux/reiserfs_fs.h
#   2004/03/16 02:29:46-08:00 akpm@osdl.org +2 -1
#   resierfs: scheduling latency improvements
# 
# fs/reiserfs/stree.c
#   2004/03/16 02:43:50-08:00 akpm@osdl.org +6 -7
#   resierfs: scheduling latency improvements
# 
# ChangeSet
#   2004/03/16 07:20:29-08:00 akpm@osdl.org 
#   [PATCH] reiserfs: fix null pointer deref
#   
#   From: Chris Mason <mason@suse.com>
#   
#   From: Jeff Mahoney <jeffm@suse.de>
#   
#   fsstress manages to setup a sequence of events that allow an attempt to
#   perform direct-io on a tail.  bh_result->b_page == NULL, which causes the
#   PageLocked and PageWriteback checks to perform a NULL deref, causing the
#   oops.
# 
# fs/reiserfs/inode.c
#   2004/03/16 02:43:50-08:00 akpm@osdl.org +1 -1
#   reiserfs: fix null pointer deref
# 
# ChangeSet
#   2004/03/16 07:20:17-08:00 akpm@osdl.org 
#   [PATCH] kernel-doc build fix
#   
#   From: Michael Still <mikal@stillhq.com>
#   
#   This is needed to get any of the SGML documentation to build with 2.6.4.
# 
# Documentation/DocBook/parportbook.tmpl
#   2004/03/16 02:29:46-08:00 akpm@osdl.org +1 -1
#   kernel-doc build fix
# 
# ChangeSet
#   2004/03/16 07:20:05-08:00 akpm@osdl.org 
#   [PATCH] fbdev: character drawing enhancement.
#   
#   From: James Simmons <jsimmons@infradead.org>
#   
#   This patch merges two of the drawing functions.  The patch uses aligned
#   transfers when possible even on displays where the characters are not byte
#   align.  Tested on my my laptop for 12 bit width fonts and 8 bit wide fonts.
#   It works very nicely.
# 
# drivers/video/console/fbcon.c
#   2004/03/16 02:29:46-08:00 akpm@osdl.org +76 -131
#   fbdev: character drawing enhancement.
# 
# ChangeSet
#   2004/03/16 07:19:52-08:00 akpm@osdl.org 
#   [PATCH] page_referenced() simplification
#   
#   There's no point in calling mark_page_accessed() here.  The page is never on
#   the LRU so all mark_page_accessed() will do is to set PG_referenced, which we
#   immediately clear again.
# 
# mm/rmap.c
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +1 -1
#   page_referenced() simplification
# 
# ChangeSet
#   2004/03/16 07:19:41-08:00 akpm@osdl.org 
#   [PATCH] flush_workqueue(): detect excessive nesting
#   
#   Add a debug check for workqueues nested more than three deep via the
#   direct-run-workqueue() path.
# 
# kernel/workqueue.c
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +10 -0
#   flush_workqueue(): detect excessive nesting
# 
# ChangeSet
#   2004/03/16 07:19:29-08:00 akpm@osdl.org 
#   [PATCH] flush_scheduled_work() deadlock fix
#   
#   Because keventd is a resource which is shared between unrelated parts of the
#   kernel it is possible for one person's workqueue handler to accidentally call
#   another person's flush_scheduled_work().  thockin managed it by calling
#   mntput() from a workqueue handler.  It deadlocks.
#   
#   It's simple enough to fix: teach flush_scheduled_work() to go direct when it
#   discovers that the calling thread is the one which should be running the
#   work.
#   
#   Note that this can cause recursion.  The depth of that recursion is equal to
#   the number of currently-queued works which themselves want to call
#   flush_scheduled_work().  If this ever exceeds three I'll eat my hat.
# 
# kernel/workqueue.c
#   2004/03/16 02:43:51-08:00 akpm@osdl.org +8 -0
#   flush_scheduled_work() deadlock fix
# 
# ChangeSet
#   2004/03/16 07:19:18-08:00 akpm@osdl.org 
#   [PATCH] selinux: fix compute_av bug
#   
#   From: Stephen Smalley <sds@epoch.ncsc.mil>
#   
#   This patch fixes a bug in the SELinux compute_av code; the current code
#   yields the right access computation but can cause unnecessary (but
#   harmless) processing to occur when transition permission wasn't granted in
#   the first place by the TE configuration.  Thanks to Chad Hanson of TCS for
#   reporting the bug.
# 
# security/selinux/ss/services.c
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +1 -1
#   selinux: fix compute_av bug
# 
# ChangeSet
#   2004/03/16 07:19:07-08:00 akpm@osdl.org 
#   [PATCH] kbuild: fix modpost when used with O=
#   
#   From: Sam Ravnborg <sam@ravnborg.org>
#   
#   modpost or to be more specific sumversion.c was not behaving correct when
#   used with O= and MODULE_VERSION was used.  Previously it failed to use
#   local .h when calculation the md-sum in case of a O= build.
#   
#   The following patch introduces the following:
#   
#   - A generic get_next_line()
#   
#   - Check that the topmost part of the directory matches
#   
#   - Using strrch when checking for file with suffix .o
#   
#   - Use NOFAIL for allocations in sumversion
#   
#   - Avoid memory leak in new_module
#   
#   The generic get_next_line will pay off when Andreas implmentation of
#   storing symbol addresses in a seperate file is introduced.
# 
# scripts/sumversion.c
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +33 -39
#   kbuild: fix modpost when used with O=
# 
# scripts/modpost.h
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +4 -0
#   kbuild: fix modpost when used with O=
# 
# scripts/modpost.c
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +42 -9
#   kbuild: fix modpost when used with O=
# 
# ChangeSet
#   2004/03/16 07:18:55-08:00 akpm@osdl.org 
#   [PATCH] fix modular fb drivers
#   
#   From: Arnd Bergmann <arnd@arndb.de>
#   
#   The recent "fbdev: monitor detection fixes" patch broke modular frame
#   buffer drivers.
# 
# drivers/video/modedb.c
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +1 -1
#   fix modular fb drivers
# 
# ChangeSet
#   2004/03/16 07:18:45-08:00 akpm@osdl.org 
#   [PATCH] move PCIBIOS access help text
#   
#   From: "Randy.Dunlap" <rddunlap@osdl.org>
#   
#   Moves PCI BIOS Access Mode help text to its top level instead of under
#   PCI_GOBIOS (which is only 1 of 4 possible choices).
# 
# arch/i386/Kconfig
#   2004/03/16 02:29:45-08:00 akpm@osdl.org +3 -3
#   move PCIBIOS access help text
# 
# ChangeSet
#   2004/03/16 07:18:33-08:00 akpm@osdl.org 
#   [PATCH] drivers_cdrom_cdu31c.c check_region() fix
#   
#   From: <viro@parcelfarce.linux.theplanet.co.uk>
#   
#   check_region() fixes.
# 
# drivers/cdrom/cdu31a.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +29 -42
#   drivers_cdrom_cdu31c.c check_region() fix
# 
# ChangeSet
#   2004/03/16 07:18:22-08:00 akpm@osdl.org 
#   [PATCH] add warning to DocBook/Makefile
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  maximilian attems <janitor@sternwelten.at>
#   
#   Print something friendlier than:
#   
#   /bin/sh: fig2dev: command not found
#   make[1]: *** [Documentation/DocBook/parport-share.eps] Error 127
#   make: *** [pdfdocs] Error 2
# 
# Documentation/DocBook/Makefile
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +6 -0
#   add warning to DocBook/Makefile
# 
# ChangeSet
#   2004/03/16 07:18:09-08:00 akpm@osdl.org 
#   [PATCH] Fix comment in drivers/block/genhd.c
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  a.othieno@bluewin.ch (Arthur Othieno)
#   
#   add_gendisk() was replaced with add_disk(), but the comment suggests
#   otherwise.  Breaks `make *docs'.
# 
# drivers/block/genhd.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +1 -1
#   Fix comment in drivers/block/genhd.c
# 
# ChangeSet
#   2004/03/16 07:17:58-08:00 akpm@osdl.org 
#   [PATCH] minor credits updates
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  andersen@codepoet.org
#   
#   I've moved...  This patch updates my contact info.
# 
# CREDITS
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +5 -5
#   minor credits updates
# 
# ChangeSet
#   2004/03/16 07:17:48-08:00 akpm@osdl.org 
#   [PATCH] chardev module aliases
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From: Steve Youngs <sryoungs@bigpond.net.au> Add module aliases for 21285,
#   amba, anakin, clps711x, mux, and sa1100 serial drivers.
# 
# drivers/serial/sa1100.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +1 -0
#   chardev module aliases
# 
# drivers/serial/mux.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +2 -0
#   chardev module aliases
# 
# drivers/serial/clps711x.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +2 -0
#   chardev module aliases
# 
# drivers/serial/anakin.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +2 -0
#   chardev module aliases
# 
# drivers/serial/amba.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +2 -0
#   chardev module aliases
# 
# drivers/serial/21285.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +2 -0
#   chardev module aliases
# 
# ChangeSet
#   2004/03/16 07:17:35-08:00 akpm@osdl.org 
#   [PATCH] Fix scripts/ver_linux
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  Thomas Molina <tmolina@cablespeed.com>
#   
#   ver_linux hasn't displayed binutils version right for some time.  This patch
#   corrects that and preserves the old behaviour as well, as suggested by Rusty.
# 
# scripts/ver_linux
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +3 -2
#   Fix scripts/ver_linux
# 
# ChangeSet
#   2004/03/16 07:17:23-08:00 akpm@osdl.org 
#   [PATCH] fix for kallsyms module symbol resolution problem
#   
#   From:  Rusty Russell <rusty@rustcorp.com.au>
#   
#   Fix a problem with kallsyms being unable to look up symbols which are in
#   modules.
#   
#   add_kallsyms should be above module_finalize, which means you can just use
#   the mod->symtab and mod->strtab members.
# 
# kernel/module.c
#   2004/03/16 02:29:44-08:00 akpm@osdl.org +11 -5
#   fix for kallsyms module symbol resolution problem
# 
# ChangeSet
#   2004/03/16 07:17:12-08:00 akpm@osdl.org 
#   [PATCH] filemap.c comment fix
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  Carl Spalletta <ioanamitu@yahoo.com>
# 
# mm/filemap.c
#   2004/03/16 02:29:43-08:00 akpm@osdl.org +1 -1
#   filemap.c comment fix
# 
# ChangeSet
#   2004/03/16 07:17:01-08:00 akpm@osdl.org 
#   [PATCH] rename one of the acpi_disable() instances
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  Pavel Machek <pavel@ucw.cz>
#   
#   There's acpi_disable somewhere in the acpi interpreter (it disables
#   interrupts, iirc).  Thus blacklisting function needs better name.
# 
# arch/i386/kernel/dmi_scan.c
#   2004/03/16 02:29:43-08:00 akpm@osdl.org +2 -2
#   rename one of the acpi_disable() instances
# 
# ChangeSet
#   2004/03/16 07:16:48-08:00 akpm@osdl.org 
#   [PATCH] drivers_cdrom_sjcd.c check_region() fix
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  Omkhar Arasaratnam <omkhar@rogers.com>
# 
# drivers/cdrom/sjcd.c
#   2004/03/16 02:29:43-08:00 akpm@osdl.org +1 -1
#   drivers_cdrom_sjcd.c check_region() fix
# 
# ChangeSet
#   2004/03/16 07:16:38-08:00 akpm@osdl.org 
#   [PATCH] Document tricks to get S3_swsusp working
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  Pavel Machek <pavel@ucw.cz>
#   
#   I was sending this to users that had problems with swsusp, then lost it.  It
#   would be nice to have it directly in the tree.
# 
# Documentation/power/tricks.txt
#   2004/03/16 02:29:43-08:00 akpm@osdl.org +25 -0
#   Document tricks to get S3_swsusp working
# 
# Documentation/power/tricks.txt
#   2004/03/16 02:29:43-08:00 akpm@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.5/linux/Documentation/power/tricks.txt
# 
# ChangeSet
#   2004/03/16 07:16:27-08:00 akpm@osdl.org 
#   [PATCH] ACPI: document acpi_sleep option
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  Pavel Machek <pavel@ucw.cz>
#   
#   acpi_sleep option should be documented.
# 
# Documentation/kernel-parameters.txt
#   2004/03/16 02:29:43-08:00 akpm@osdl.org +4 -0
#   ACPI: document acpi_sleep option
# 
# ChangeSet
#   2004/03/16 07:16:15-08:00 akpm@osdl.org 
#   [PATCH] drivers_cdrom_cm206.c check_region() fix
#   
#   From: Trivial Patch Monkey <trivial@rustcorp.com.au>
#   
#   From:  Omkhar Arasaratnam <omkhar@rogers.com>
#   
#   check_region() fix
# 
# drivers/cdrom/cm206.c
#   2004/03/16 02:29:43-08:00 akpm@osdl.org +5 -4
#   drivers_cdrom_cm206.c check_region() fix
# 
# ChangeSet
#   2004/03/16 07:16:02-08:00 akpm@osdl.org 
#   [PATCH] ide-scsi error handling fixes
#   
#   From: Willem Riede <wrlk@riede.org>
#   
#   The patch revises the error handling in ide-scsi, fixing the scheduling
#   while locked issues, and make it work properly, at least for me...
#   
#   Specific changes in this patch:
#   
#   - introduce idescsi_expiry, a timeout routine for the ide subsystem,
#     which simply flags the fact that the command timed out, but postpones
#     any other action until either the command still finishes on its own
#     (unlikely?) or the scsi error handler kicks in;
#   
#   - introduce idescsi_atapi_error and idescsi_atapi_abort, error routines
#     for the ide subsystem, which are modeled after those of ide-cd, but
#     take only minimal effort to recover, leaving the heavy lifting for
#     the scsi error handler;
#   
#   - rewrite (and rename for clarity) idescsi_eh_abort and idescsi_eh_error,
#     the abort/error routines to be called by the scsi error handler --
#     this redesign should not have the scheduling while atomic problems
#     of the old implementation.
#   
#   - move ide_cdrom_dump_status() from ide-cd.c to ide-lib.c as
#     ide_dump_atapi_status() and both ide-cd and ide-scsi call it.
#   
#   - replaces BUG() by WARN_ON()/printk in the error handling code.
#   
#   - sets TASK_UNINTERRUPTIBLE before schedule_timeout() and moves the host
#     unlock/lock around the while loop inside the loop in idescsi_eh_reset().
# 
# include/linux/ide.h
#   2004/03/16 02:29:32-08:00 akpm@osdl.org +1 -0
#   ide-scsi error handling fixes
# 
# drivers/scsi/ide-scsi.c
#   2004/03/16 02:29:32-08:00 akpm@osdl.org +186 -53
#   ide-scsi error handling fixes
# 
# drivers/ide/ide-lib.c
#   2004/03/16 02:29:32-08:00 akpm@osdl.org +52 -0
#   ide-scsi error handling fixes
# 
# drivers/ide/ide-cd.c
#   2004/03/16 02:29:32-08:00 akpm@osdl.org +2 -49
#   ide-scsi error handling fixes
# 
# ChangeSet
#   2004/03/16 07:15:51-08:00 akpm@osdl.org 
#   [PATCH] selinux: Conditional policy extension and MLS detection support
#   
#   From: Stephen Smalley <sds@epoch.ncsc.mil>
#   
#   This patch extends the SELinux policy engine to support conditional policy
#   logic based on a set of policy booleans, allowing well-formed changes to
#   the policy to be defined within and mediated by the policy itself.
#   
#   The conditional policy extensions were implemented and contributed by
#   Tresys Technology.
#   
#   Userland packages that support these extensions are already available from
#   nsa.gov/selinux, and backward compatibility is provided for the prior
#   policy version.
#   
#   The patch also includes a small change to enable detection of the optional
#   MLS policy model on a SELinux system and fixes to the conditional policy
#   extensions to allow the MLS policy to work correctly with them that were
#   implemented and contributed by Trusted Computer Solutions.
# 
# security/selinux/ss/services.c
#   2004/03/16 02:43:51-08:00 akpm@osdl.org +141 -0
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/policydb.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +31 -2
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/policydb.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +63 -15
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/mls.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +6 -6
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/conditional.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +77 -0
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/conditional.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +487 -0
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/avtab.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +20 -0
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/avtab.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +194 -62
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/Makefile
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +1 -1
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/selinuxfs.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +426 -8
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/include/conditional.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +22 -0
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/ss/conditional.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.5/linux/security/selinux/ss/conditional.h
# 
# security/selinux/ss/conditional.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.5/linux/security/selinux/ss/conditional.c
# 
# security/selinux/include/security.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +10 -1
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/include/conditional.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.5/linux/security/selinux/include/conditional.h
# 
# security/selinux/include/av_permissions.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +1 -0
#   selinux: Conditional policy extension and MLS detection support
# 
# security/selinux/include/av_perm_to_string.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +1 -0
#   selinux: Conditional policy extension and MLS detection support
# 
# ChangeSet
#   2004/03/16 07:15:39-08:00 akpm@osdl.org 
#   [PATCH] s390: update for altered page_state structure
#   
#   From: Gerald Schaefer <gerald.schaefer@gmx.net>
#   
#   Update s390 to track the new fields in struct page_state.
# 
# include/linux/page-flags.h
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +0 -3
#   s390: update for altered page_state structure
# 
# arch/s390/appldata/appldata_os.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +9 -0
#   s390: update for altered page_state structure
# 
# arch/s390/appldata/appldata_net_sum.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +8 -0
#   s390: update for altered page_state structure
# 
# arch/s390/appldata/appldata_mem.c
#   2004/03/16 02:29:22-08:00 akpm@osdl.org +13 -12
#   s390: update for altered page_state structure
# 
# ChangeSet
#   2004/03/16 07:15:28-08:00 akpm@osdl.org 
#   [PATCH] ppc32 compile fix
#   
#   From: Tom Rini <trini@kernel.crashing.org>
#   
#   The problem is that on PPC32 (and probably sparc64) 'asmlinkage' is a
#   useless keyword, and should just be removed from include/asm-ppc/unistd.h.
# 
# include/asm-ppc/unistd.h
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +4 -4
#   ppc32 compile fix
# 
# ChangeSet
#   2004/03/16 07:15:17-08:00 akpm@osdl.org 
#   [PATCH] Save some memory in mem_map on x86-64
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   This patch saves 2MB of memory on a 1GB x86-64 machine, 20MB on a 10GB
#   machine.  It does this by eliminating 8 bytes of useless padding in struct
#   page.
#   
#   This resurrects an older patch in a hopefully cleaner form.
# 
# include/linux/rmap-locking.h
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +2 -2
#   Save some memory in mem_map on x86-64
# 
# include/linux/mmzone.h
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +1 -1
#   Save some memory in mem_map on x86-64
# 
# include/linux/mm.h
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +8 -2
#   Save some memory in mem_map on x86-64
# 
# include/asm-x86_64/bitops.h
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +2 -0
#   Save some memory in mem_map on x86-64
# 
# ChangeSet
#   2004/03/16 07:15:05-08:00 akpm@osdl.org 
#   [PATCH] Fix early parallel make failures
#   
#   From: Sam Ravnborg <sam@ravnborg.org>
#   
#   Ingo said:
#   
#     Starting at around 2.6.4-rc2-mm1, I keep seeing 'scripts/fixdep: Text
#     file busy' messages when doing a -j10 bzImage build - which seems to
#     suggest that by the time fixdep is used by the build system it's not
#     built yet.
#   
#   Sam said:
#   
#   I was pretty sure it was something I had caused, so I gave it a spin.  What
#   actually happened was that we tried to build the target 'silentoldconfig'
#   in parrallel with 'scripts'.  Since 'silentoldconfig' started a new make
#   and then the config target needed 'scripts' we saw two parallel runs.
#   
#   The way I decided to fix it was to split scripts/ in two parts.  The first
#   part is now the very basic stuff - moved to scripts/basic/.  The second
#   part is dependent on kernel config etc.  and kept in scripts/
#   
#   In the 2.7 timeframe i will redo this initial stuff - it's becoming too
#   messy for anyone to understand today.
#   
#   
#   Description:
#   
#   Fix dependencies in early phases of kernel build.  This solves a few
#   problems nively: modpost is no longer rebuild twicewhen reaching the
#   'target' state 'make -j10' now works nicely again
#   
#   The patch is rather large due to the following file moves:
#   mkdir scripts/basic
#   mv scripts/fixdep.c        scripts/basic
#   mv scripts/split-include.c scripts/basic
#   mv scripts/docproc.c       scripts/basic
# 
# scripts/basic/split-include.c
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +1 -1
#   Fix early parallel make failures
# 
# scripts/basic/fixdep.c
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +13 -13
#   Fix early parallel make failures
# 
# scripts/basic/docproc.c
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +8 -8
#   Fix early parallel make failures
# 
# scripts/basic/Makefile
#   2004/03/16 07:14:58-08:00 akpm@osdl.org +18 -0
# 
# scripts/Makefile
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +2 -9
#   Fix early parallel make failures
# 
# scripts/Makefile.lib
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +1 -1
#   Fix early parallel make failures
# 
# scripts/Makefile.build
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +1 -1
#   Fix early parallel make failures
# 
# Makefile
#   2004/03/16 02:29:21-08:00 akpm@osdl.org +23 -18
#   Fix early parallel make failures
# 
# Documentation/DocBook/Makefile
#   2004/03/16 02:43:52-08:00 akpm@osdl.org +1 -1
#   Fix early parallel make failures
# 
# scripts/basic/Makefile
#   2004/03/16 07:14:58-08:00 akpm@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.5/linux/scripts/basic/Makefile
# 
# ChangeSet
#   2004/03/16 07:07:38-08:00 benh@kernel.crashing.org 
#   [PATCH] g5: Fix iommu vs. pci_device_to_OF_node
#   
#   The g5 iommu code would fill the "iommu_table" member of whatever
#   device node was pointed to by pcidev->sysdata during boot. However,
#   the ppc64 kernel fills that with a pointer to the PHB node which is
#   later replaced "lazily" with a pointer to the real node when calling
#   pci_device_to_OF_node(). In this case, we were thus "losign" the
#   iommu_table pointer. Typical symptom: loss of the SATA when looking
#   at it's /proc entry.
#   
#   This fixes it by forcing the update to the final sysdata pointer
#   when filling up the iommu_table pointers. The "lazy" thing is useless
#   on pmac anyway.
# 
# ChangeSet
#   2004/03/16 11:31:31+01:00 vojtech@suse.cz 
#   Merge bk://dtor.bkbits.net/input into suse.cz:/data/bk/input
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/16 11:31:28+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 11:10:38+01:00 vojtech@suse.cz 
#   Merge suse.cz:/data/bk/linus into suse.cz:/data/bk/input
# 
# init/main.c
#   2004/03/16 11:10:35+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/char/Kconfig
#   2004/03/16 11:10:34+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# Documentation/kernel-parameters.txt
#   2004/03/16 11:10:34+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/16 00:03:48-08:00 davidm@tiger.hpl.hp.com 
#   ia64: Update defconfig
# 
# arch/ia64/defconfig
#   2004/03/16 00:03:41-08:00 davidm@tiger.hpl.hp.com +331 -213
#   Update
# 
# ChangeSet
#   2004/03/16 02:39:14-05:00 jgarzik@redhat.com 
#   [libata] bump libata and sata_sil driver versions
# 
# drivers/scsi/sata_sil.c
#   2004/03/16 02:35:49-05:00 jgarzik@redhat.com +1 -1
#   [libata] bump libata and sata_sil driver versions
# 
# drivers/scsi/libata.h
#   2004/03/16 02:35:49-05:00 jgarzik@redhat.com +1 -1
#   [libata] bump libata and sata_sil driver versions
# 
# ChangeSet
#   2004/03/15 23:31:37-08:00 kaos@sgi.com 
#   [PATCH] ia64: Decode salinfo oemdata for SN2 via PROM
#   
#   SN2 platforms provide oemdata in salinfo records.  The decode of that
#   oemdata is done via prom routines.  This patch provides the interface
#   from user space through the kernel into the prom to do the oem decode.
# 
# arch/ia64/sn/kernel/mca.c
#   2004/03/15 10:05:52-08:00 kaos@sgi.com +66 -29
#   ia64: Decode salinfo oemdata for SN2 via PROM
# 
# ChangeSet
#   2004/03/15 23:30:13-08:00 davidm@tiger.hpl.hp.com 
#   ia64: Based on patch by Keith Owens: put stop bit to work around GCC problem.
#   
#   Apparently GCC sometimes fails to insert a stop-bit when re-using p14
#   after the spinlock directives, even though the register is clearly marked
#   as "clobbered".
# 
# include/asm-ia64/spinlock.h
#   2004/03/15 23:30:06-08:00 davidm@tiger.hpl.hp.com +2 -2
#   Put stop-bit after brl.cond/brl.call to work around GCC limitation.
# 
# ChangeSet
#   2004/03/15 23:21:48-08:00 hch@lst.de 
#   [PATCH] ia64: update simscsi to 2.6 scsi APIs
#   
#   Use the proper (and cleaner) probing API instead of the old
#   scsi_module.c hack, don't use the typedefs I plan to kill in 2.7 and
#   mark everything static
# 
# arch/ia64/hp/sim/simscsi.c
#   2004/03/15 06:20:36-08:00 hch@lst.de +47 -48
#   ia64: update simscsi to 2.6 scsi APIs
# 
# BitKeeper/deleted/.del-simscsi.h~7bbe5e65bd3b62b6
#   2004/03/15 23:21:41-08:00 hch@lst.de +0 -0
#   Delete: arch/ia64/hp/sim/simscsi.h
# 
# ChangeSet
#   2004/03/15 22:39:06-08:00 davidm@tiger.hpl.hp.com 
#   Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5
#   into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5
# 
# arch/ia64/Kconfig
#   2004/03/15 22:39:00-08:00 davidm@tiger.hpl.hp.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/15 22:34:08-08:00 bjorn.helgaas@hp.com 
#   [PATCH] ia64: update ia64/Kconfig
#   
#   This Kconfig patch basically just makes ia64 look a little more like i386:
#           - moves system type above processor type
#           - moves PM & ACPI to a new top-level menu
#           - moves PCI/PCMCIA to a new top-level menu
# 
# arch/ia64/Kconfig
#   2004/03/15 09:15:31-08:00 bjorn.helgaas@hp.com +99 -87
#   ia64: update ia64/Kconfig
# 
# ChangeSet
#   2004/03/15 22:33:05-08:00 davidm@tiger.hpl.hp.com 
#   ia64: Forward-port hp-agp.c fix from 2.4
#   
#   See this ChangeSet:
#   
#   http://lia64.bkbits.net:8080/linux-ia64-2.4/cset@40524248tkgE0RDYQL0IyiAdFxo_Ew
# 
# drivers/char/agp/hp-agp.c
#   2004/03/15 09:41:03-08:00 davidm@hpl.hp.com +84 -28
#   ia64: Forward-port hp-agp.c fixes from 2.4
# 
# ChangeSet
#   2004/03/15 22:24:32-08:00 jbarnes@sgi.com 
#   [PATCH] ia64: kill CONFIG_IA64_MCA
#   
#   The MCA code is now slim enough that there isn't much point in keeping
#   CONFIG_IA64_MCA anymore.
# 
# arch/ia64/sn/kernel/setup.c
#   2004/03/15 06:19:50-08:00 jbarnes@sgi.com +0 -3
#   ia64: kill CONFIG_IA64_MCA
# 
# arch/ia64/mm/init.c
#   2004/03/15 06:20:43-08:00 jbarnes@sgi.com +0 -4
#   ia64: kill CONFIG_IA64_MCA
# 
# arch/ia64/kernel/smpboot.c
#   2004/03/15 06:20:27-08:00 jbarnes@sgi.com +0 -2
#   ia64: kill CONFIG_IA64_MCA
# 
# arch/ia64/kernel/setup.c
#   2004/03/15 06:20:19-08:00 jbarnes@sgi.com +0 -2
#   ia64: kill CONFIG_IA64_MCA
# 
# arch/ia64/kernel/efi.c
#   2004/03/15 06:20:10-08:00 jbarnes@sgi.com +0 -4
#   ia64: kill CONFIG_IA64_MCA
# 
# arch/ia64/kernel/Makefile
#   2004/03/15 06:17:01-08:00 jbarnes@sgi.com +1 -2
#   ia64: kill CONFIG_IA64_MCA
# 
# arch/ia64/Kconfig
#   2004/03/15 06:21:32-08:00 jbarnes@sgi.com +0 -7
#   ia64: kill CONFIG_IA64_MCA
# 
# ChangeSet
#   2004/03/15 22:22:13-08:00 bjorn.helgaas@hp.com 
#   [PATCH] ia64: move consistent_dma_mask to the generic device
#   
#   The patch that moved and renamed consistent_dma_mask neglected
#   to fix up arch/ia64/hp/common/sba_iommu.c.
# 
# arch/ia64/hp/common/sba_iommu.c
#   2004/03/15 06:51:33-08:00 bjorn.helgaas@hp.com +3 -3
#   ia64: move consistent_dma_mask to the generic device
# 
# ChangeSet
#   2004/03/15 22:20:48-08:00 pfg@sgi.com 
#   [PATCH] ia64: fix missing braces in SN2 console code
#   
#   The last mod to fix the staircase printing - missed some bracing...
# 
# drivers/char/sn_serial.c
#   2004/03/15 06:28:24-08:00 pfg@sgi.com +2 -1
#   ia64: fix missing braces in SN2 console code
# 
# ChangeSet
#   2004/03/15 22:18:13-08:00 mort@wildopensource.com 
#   [PATCH] ia64: Update SN2 defconfig
#   
# 
# arch/ia64/configs/sn2_defconfig
#   2004/03/15 05:55:41-08:00 mort@wildopensource.com +420 -156
#   ia64: Update SN2 defconfig
# 
# ChangeSet
#   2004/03/15 22:17:27-08:00 jsm@udlkern.fc.hp.com 
#   yia64: Fix show_mem() panic
# 
# arch/ia64/mm/init.c
#   2004/03/14 20:55:08-08:00 jsm@udlkern.fc.hp.com +4 -1
#   ia64: Fix show_mem panic
# 
# arch/ia64/mm/discontig.c
#   2004/03/11 22:15:26-08:00 jsm@udlkern.fc.hp.com +2 -0
#   ia64: Fix show_mem panic
# 
# arch/ia64/mm/contig.c
#   2004/03/11 21:59:24-08:00 jsm@udlkern.fc.hp.com +2 -0
#   ia64: Fix show_mem panic
# 
# ChangeSet
#   2004/03/12 15:09:53-08:00 bjorn.helgaas@hp.com 
#   [PATCH] ia64: clean up ACPI GSI/IRQ conversions (ia64 part)
#   
#   Add "acpi_gsi_to_irq()" as a generic replacement for "acpi_irq_to_vector()".
#   This converts from an ACPI global system interrupt number to a Linux IRQ.
#   Also, convert ia64-specific terminology to use GSI when appropriate.
# 
# include/asm-ia64/acpi.h
#   2004/03/12 04:32:41-08:00 bjorn.helgaas@hp.com +2 -1
#   ia64: clean up ACPI GSI/IRQ conversions (ia64 part)
# 
# arch/ia64/kernel/acpi.c
#   2004/03/12 04:32:11-08:00 bjorn.helgaas@hp.com +18 -0
#   ia64: clean up ACPI GSI/IRQ conversions (ia64 part)
# 
# ChangeSet
#   2004/03/12 13:51:14+01:00 oliver@neukum.org 
#   input: fixes in wacom.c
#     -use GFP_KERNEL where SLAB_ATOMIC is not needed
#     -fix count bug in open() error path
# 
# drivers/usb/input/wacom.c
#   2004/03/12 13:51:09+01:00 oliver@neukum.org +4 -2
#   input: fixes in wacom.c
#     -use GFP_KERNEL where SLAB_ATOMIC is not needed
#     -fix count bug in open() error path
# 
# ChangeSet
#   2004/03/11 16:39:08-08:00 david-b@pacbell.net 
#   [PATCH] USB Gadget: add "gadget_chips.h"
#   
#   This adds standard gadget_is_*() calls.  Gadget drivers using
#   those calls can get rid of some inlined #ifdefs, and will also
#   be able to do more "late binding" to their hardware.
#   
#   
#   Define gadget_is_*() calls, to help do late binding to USB controllers.
#   
#   Current gadget drivers expect to know at compile time what hardware
#   they'll bind to.  That's not very friendly to a generic PDA distro,
#   which might prefer to defer such choices to run time.
#   
#   These macros let drivers change that code from inlined #ifdefs (ugh) to
#   normal C statements (looks much nicer), so making those "what hardware"
#   policy choices at run time gets easier.
# 
# drivers/usb/gadget/gadget_chips.h
#   2004/03/10 17:45:51-08:00 david-b@pacbell.net +57 -0
#   USB Gadget: add "gadget_chips.h"
# 
# drivers/usb/gadget/gadget_chips.h
#   2004/03/10 17:45:51-08:00 david-b@pacbell.net +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/drivers/usb/gadget/gadget_chips.h
# 
# ChangeSet
#   2004/03/12 00:29:52+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# init/main.c
#   2004/03/12 00:29:49+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/11 02:27:59-05:00 dtor_core@ameritech.net 
#   Input: if Synaptics' absolute mode is disabled make sure that
#          touchpad is reset back to relative mode and gestures
#          (taps) are enabled
# 
# drivers/input/mouse/synaptics.h
#   2004/03/10 21:27:47-05:00 dtor_core@ameritech.net +1 -0
#   Add synaptics_reset()
# 
# drivers/input/mouse/synaptics.c
#   2004/03/10 21:27:47-05:00 dtor_core@ameritech.net +7 -1
#   Add synaptics_reset() to reset touchpad back into relative mode
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/10 21:27:47-05:00 dtor_core@ameritech.net +4 -0
#   If Synaptics' absolute mode is disabled make sure that touchpad
#   is reset back to relative mode
# 
# ChangeSet
#   2004/03/11 02:20:12-05:00 dtor_core@ameritech.net 
#   Input: do a full reset of Synaptics touchpad if extended protocol
#          probes failed, otherwise trackpoint on the pass-through port
#          may stop working (reset-disable isn't enough to revive it)    
# 
# drivers/input/mouse/synaptics.c
#   2004/03/10 21:19:57-05:00 dtor_core@ameritech.net +1 -12
#   Use psmouse_reset instead of local function to reset the device
# 
# drivers/input/mouse/psmouse.h
#   2004/03/10 21:19:57-05:00 dtor_core@ameritech.net +1 -0
#   Add psmouse_reset
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/10 21:19:57-05:00 dtor_core@ameritech.net +21 -2
#   - implement psmouse_reset()
#   - do a full reset if extended protocol probes fail with Synaptics,
#     otherwise trackpoint on the pass-through port may not work 
# 
# ChangeSet
#   2004/03/11 02:16:51-05:00 dtor_core@ameritech.net 
#   Input: when disconnecting PS/2 mouse give protocol's disconnect 
#          handler chance to run before starting ignoring mouse data.
#          Otherwise interrupt handler will discard all ACKs and the
#          very first command in cleanup sequence will fail (Synaptics
#          was failing to return to relative mode on module unload).
# 
# drivers/input/mouse/psmouse.h
#   2004/03/10 21:16:31-05:00 dtor_core@ameritech.net +2 -2
#   Rename PSMOUSE_NEW_DEVICE to PSMOUSE_CMD_MODE, trailing whitespace fix.
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/10 21:16:31-05:00 dtor_core@ameritech.net +5 -3
#   When disconnecting mouse give disconnect handler chance to run
#   before starting ignoring mouse data.
# 
# ChangeSet
#   2004/03/10 14:50:30-08:00 pmarques@grupopie.com 
#   [PATCH] USB: usblp.c (Was: usblp_write spins forever after an error)
#   
#   Paulo Marques wrote:
#   
#   > David Woodhouse wrote:
#   >
#   >> On Thu, 2004-03-04 at 12:33 +0000, Paulo Marques wrote:
#   >>
#   >>> Yes, unfortunately it did went into 2.6.4-rc1. However it is already
#   >>> corrected in 2.6.4-rc2. Luckily it didn't went into any "non-rc"
#   >>> official release.
#   >>>
#   >>> Please try 2.6.4-rc2, and check to see if the bug went away...
#   >>>
#   >>
#   >> Seems to work; thanks. Does this need backporting to 2.4 too?
#   >>
#   >
#   >
#   > Unfortunately this isn't over yet.
#   >
#   > I got suspicious about this bug fix, because I *did* test my patch
#   > before submitting it and the kernel that didn't work before, worked fine
#   > with my patch.
#   >
#   > But now it seems that it is the other way around. After a few digging I
#   > found out the problem:
#   >
#   > The application that I was testing with uses the usblp handle with
#   > non-blocking I/O .
#   >
#   > So my patch does work for non-blocking I/O uses of the port, but wrecks
#   > the normal blocking mode.
#   >
#   > I've already produced a version that works for both cases. I'll just
#   > clean it up a bit and submit it to 2.4 and 2.6 kernels.
#   
#   
#   Here it is.
#   
#   The patch is only one line for 2.6.4-rc2. (I also did a little formatting
#   adjustment to better comply with CodingStyle)
#   
#   For the 2.4.26-pre1 kernel, I also backported the return codes correction patch
#   from Oliver Neukum.
#   
#   
#   The problem with the write function was that, in non-blocking mode, after
#   submitting the first urb, the function would return with -EAGAIN, not reporting
#   to the application that in fact it had already sent "transfer_length" bytes.
#   This way the application would have to send the data *again* causing lots of
#   errors.
#   
#   It did return the correct amount with my first patch, because the writecount was
#   being updated on the end of the loop. However this was wrong for blocking I/O.
#   
#   The "transfer_length" local variable is still needed because if we used the
#   transfer_buffer_length field from the urb, then on a second call to write, if
#   the urb was still pending (in non-blocking mode), the write would return an
#   incorrect amount of data written.
#   
#   Anyway, this time I tested it using blocking and non-blocking I/O and it works
#   for both cases. Even better, this patch only changes the behaviour for
#   non-blocking I/O, and keeps the same behaviour for the more usual blocking I/O
#   (at least on kernel 2.6).
# 
# drivers/usb/class/usblp.c
#   2004/03/05 09:10:30-08:00 pmarques@grupopie.com +5 -2
#   USB: usblp.c (Was: usblp_write spins forever after an error)
# 
# ChangeSet
#   2004/03/10 13:44:37-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Altsetting/interface update for USB image drivers
#   
#   This patch contains minute updates for the hpusbscsi, mdc800, and microtek
#   drivers.  Only two things are worth noting.  In the mdc800 driver I
#   removed some unnecessary calls to usb_driver_claim_interface(),
#   usb_driver_release_interface(), and usb_set_interface().  Likewise, in the
#   microtek driver I removed an unnecessary call to usb_set_interface().
# 
# drivers/usb/image/microtek.c
#   2004/03/09 08:50:21-08:00 stern@rowland.harvard.edu +3 -18
#   USB: Altsetting/interface update for USB image drivers
# 
# drivers/usb/image/mdc800.c
#   2004/03/09 08:46:49-08:00 stern@rowland.harvard.edu +1 -10
#   USB: Altsetting/interface update for USB image drivers
# 
# drivers/usb/image/hpusbscsi.c
#   2004/03/09 08:41:37-08:00 stern@rowland.harvard.edu +1 -1
#   USB: Altsetting/interface update for USB image drivers
# 
# ChangeSet
#   2004/03/10 13:42:31-08:00 henning@wh9.tu-dresden.de 
#   [PATCH] USB: unusual_devs.h update
#   
#   *** linux-2.6.3/drivers/usb/storage/unusual_devs.h	2004-02-18 04:59:06.000000000 +0100
# 
# drivers/usb/storage/unusual_devs.h
#   2004/03/04 06:24:56-08:00 henning@wh9.tu-dresden.de +7 -0
#   USB: unusual_devs.h update
# 
# ChangeSet
#   2004/03/10 13:32:02-08:00 david-b@pacbell.net 
#   [PATCH] USB gadget: gadget zero, simplified controller-specific configuration
#   
#   This removes several controller-specific #define, and
#   converts to using the config_buf utilities.  Depends
#   on the patch I submitted yesterday.  Looking simpler!
#   
#   
#   Simplify "gadget zero" compile-time configuration.
#   
#   This removes several controller-specific compile-time config options;
#   the others are about to be autoconfigured.
#   
#    - HIGHSPEED replaced by CONFIG_USB_GADGET_DUALSPEED
#    - Default to self-powered operation
#    - There's no UI for remote wakeup
#   
#   It also uses the new config_buf utilities, so it's a bit easier to see
#   what's really going on (this driver implements four configurations).
# 
# drivers/usb/gadget/zero.c
#   2004/03/09 10:14:18-08:00 david-b@pacbell.net +93 -100
#   USB gadget: gadget zero, simplified controller-specific configuration
# 
# drivers/usb/gadget/Makefile
#   2004/03/09 09:15:26-08:00 david-b@pacbell.net +1 -1
#   USB gadget: gadget zero, simplified controller-specific configuration
# 
# ChangeSet
#   2004/03/10 13:31:40-08:00 david-b@pacbell.net 
#   [PATCH] USB: usb buffer allocation shouldn't require DMA
#   
#   Deepak's recent dma_pool changes accidentally assumed that
#   all HCDs use DMA.  The fix is simple:  use kmalloc/kfree
#   when there's no DMA.
# 
# drivers/usb/core/buffer.c
#   2004/03/09 06:01:10-08:00 david-b@pacbell.net +14 -2
#   USB: usb buffer allocation shouldn't require DMA
# 
# ChangeSet
#   2004/03/10 13:31:12-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbtest updates (new firmware)
#   
#   This includes some small updates to "usbtest", mostly
#   from Martin Diehl.  Please merge.
#   
#   
#   
#   usbtest updates, supporting new firmware
#   
#       - Support the new usbtest_fw-20040305 EZ-USB firmware,
#         which renumerates and handles full speed ISO transfers.
#         (From Martin Diehl.)
#   
#       - Minor cleanups:  use dev_dbg(), let some slightly-off
#         devices work in the control queueing test.
#   
#       - Be pickier about unlink tests:  insist that async
#         and sync unlinks give the appropriate fault code.
# 
# drivers/usb/misc/usbtest.c
#   2004/03/05 12:25:56-08:00 david-b@pacbell.net +23 -15
#   USB: usbtest updates (new firmware)
# 
# ChangeSet
#   2004/03/10 13:30:47-08:00 david-b@pacbell.net 
#   [PATCH] USB: usb_unlink_urb() has distinct "not linked" fault
#   
#   This gets rid of an often-bogus diagnostic, and lets
#   at least the unlink test code recover reasonably when
#   it hits that brief window while another CPU has gotten
#   the complete() callback but hasn't yet resubmitted.
#   
#   
#   
#   Return distinct code when unlinking an urb that's not linked.
#   
#   This lets drivers handle this fault sanely, when they need to.
#   Gets rid of annoying non-error messages about drivers that unlink
#   in disconnect() even when the urb isn't linked.
# 
# drivers/usb/core/hcd.c
#   2004/03/07 11:29:08-08:00 david-b@pacbell.net +2 -2
#   USB: usb_unlink_urb() has distinct "not linked" fault
# 
# ChangeSet
#   2004/03/10 13:30:20-08:00 david-b@pacbell.net 
#   [PATCH] USB gadget: dualspeed {run,compile}-time flags
#   
#   This is the first several autoconfig patches; please merge.
#   This particular one abstracts dual-speed (high and full)
#   support.
#   
#   
#   Support some more autoconfiguration for gadget drivers.
#   
#       Run-time:
#   	* Add gadget->is_dualspeed flag for controllers to set.
#   	* Tested by "ethernet" gadget, to decide whether certain
#   	  operations are errors or not.
#   	* Turned on by net2280.
#   
#       Compile-time
#   	* Generic CONFIG_USB_GADGET_DUALSPEED, not net2280-specific.
#   	* Used by "ethernet" gadget, to decide whether to
#   	  include extra code and data for dual-speed support.
#   	* Turned on by net2280.
#   
#   The basic idea behind this, and other autoconfig patches yet to come,
#   is minimizing the controller-specific compile-time configuration
#   needed by gadget drivers.
# 
# include/linux/usb_gadget.h
#   2004/03/08 09:51:12-08:00 david-b@pacbell.net +3 -0
#   USB gadget: dualspeed {run,compile}-time flags
# 
# drivers/usb/gadget/net2280.c
#   2004/03/07 12:37:35-08:00 david-b@pacbell.net +1 -0
#   USB gadget: dualspeed {run,compile}-time flags
# 
# drivers/usb/gadget/ether.c
#   2004/03/08 10:19:56-08:00 david-b@pacbell.net +15 -13
#   USB gadget: dualspeed {run,compile}-time flags
# 
# drivers/usb/gadget/Kconfig
#   2004/03/08 10:19:23-08:00 david-b@pacbell.net +8 -0
#   USB gadget: dualspeed {run,compile}-time flags
# 
# ChangeSet
#   2004/03/10 12:42:44-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbcore doc update
#   
#   Some doc updates, mostly from Alan Stern, clarifying
#   quetions folk have asked recently about unlinking
#   and about iso transfers.
# 
# include/linux/usb.h
#   2004/03/08 09:27:12-08:00 david-b@pacbell.net +14 -13
#   USB: usbcore doc update
# 
# drivers/usb/core/urb.c
#   2004/03/08 09:33:41-08:00 david-b@pacbell.net +54 -11
#   USB: usbcore doc update
# 
# ChangeSet
#   2004/03/10 12:42:17-08:00 rddunlap@osdl.org 
#   [PATCH] USB: fix net2280 section usage
#   
#    net2280_remove() is called by net2280_probe() so it
#    shouldn't be marked as __exit;
# 
# drivers/usb/gadget/net2280.c
#   2004/03/07 15:59:18-08:00 rddunlap@osdl.org +2 -2
#   USB: fix net2280 section usage
# 
# ChangeSet
#   2004/03/10 12:23:05-08:00 bunk@fs.tum.de 
#   [PATCH] USB: remove USB_SCANNER MAINTAINERS entry
#   
#   When sending the patch to remove USB_SCANNER, I forgot to remove the
#   MAINTAINERS entry.
# 
# MAINTAINERS
#   2004/03/08 17:44:30-08:00 bunk@fs.tum.de +0 -8
#   USB: remove USB_SCANNER MAINTAINERS entry
# 
# ChangeSet
#   2004/03/10 12:22:42-08:00 bunk@fs.tum.de 
#   [PATCH] USB_STORAGE: remove a comment
#   
#   In 2.6, USB_STORAGE selects SCSI, so there's no longer a need for this
#   comment.
# 
# drivers/usb/storage/Kconfig
#   2004/03/08 17:31:42-08:00 bunk@fs.tum.de +0 -2
#   USB_STORAGE: remove a comment
# 
# ChangeSet
#   2004/03/10 12:22:13-08:00 oliver@neukum.org 
#   [PATCH] USB: wacom driver fixes
#   
#   the same error code path as in the other drivers.
#   In addition I added the endianness macros. They save cycles
#   in interrupt.
#   
#     -use endian macros
#     -use GFP_KERNEL where SLAB_ATOMIC is not needed
#     -fix count bug in open() error path
# 
# drivers/usb/input/wacom.c
#   2004/03/08 15:36:35-08:00 oliver@neukum.org +13 -9
#   USB: wacom driver fixes
# 
# ChangeSet
#   2004/03/10 12:21:49-08:00 oliver@neukum.org 
#   [PATCH] USB: bug in error code path of kbtab driver
#   
#   this fixes
#   - a leak in the error code path of open()
#   - removes SLAB_ATOMIC where it isn't needed
#   - uses le16_to_cpu (yes Pete, unaligned access is taken care of)
# 
# drivers/usb/input/kbtab.c
#   2004/03/08 05:38:44-08:00 oliver@neukum.org +8 -4
#   USB: bug in error code path of kbtab driver
# 
# ChangeSet
#   2004/03/10 12:21:20-08:00 oliver@neukum.org 
#   [PATCH] USB: fixes for aiptek driver
#   
#   - don't pass buffers allocated on stack to the sync helpers
#   - check errors in probe
#   - fix count in open
#   - proper macros
# 
# drivers/usb/input/aiptek.c
#   2004/03/08 06:33:36-08:00 oliver@neukum.org +40 -17
#   USB: fixes for aiptek driver
# 
# ChangeSet
#   2004/03/10 12:20:55-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Remove interface/altsetting assumptions from usb-midi
#   
#   This patch makes the usb-midi driver use usb_ifnum_to_if(), thereby
#   removing assumptions about which interface is stored in which array entry.
#   Similarly, it stores the bAlternateSetting value rather than the array
#   index for an altsetting entry.
#   
#   Like the earlier patch for the audio driver, this also changes the driver
#   to use the in-memory rawdescriptor buffer rather than reading a
#   configuration descriptor from the device.  Unlike that earlier patch, this
#   time there's no question that the deallocation of the buffer is done
#   correctly.  (I suspect the audio driver just left out a call to kfree.)
# 
# drivers/usb/class/usb-midi.c
#   2004/03/08 08:52:16-08:00 stern@rowland.harvard.edu +28 -65
#   USB: Remove interface/altsetting assumptions from usb-midi
# 
# ChangeSet
#   2004/03/10 12:20:24-08:00 oliver@neukum.org 
#   [PATCH] USB: locking fix for pid.c
#   
#   you forgot to drop a spinlock before you report an error. A deadlock
#   will occur.
# 
# drivers/usb/input/pid.c
#   2004/03/07 19:52:14-08:00 oliver@neukum.org +1 -0
#   USB: locking fix for pid.c
# 
# ChangeSet
#   2004/03/10 11:55:44-08:00 lists@mdiehl.de 
#   [PATCH] USB: fix stack usage in pl2303 driver
#   
#   Arghh - while trying to follow this I just realized the pl2303 is DMA'ing
#   to the stack - not good!
#   Could you please just try with the patch below. I'm not sure if this might
#   cause the MA620 trouble but it's definedly a bug and maybe it improves
#   things for you...
# 
# drivers/usb/serial/pl2303.c
#   2004/03/04 00:42:18-08:00 lists@mdiehl.de +7 -1
#   USB: fix stack usage in pl2303 driver
# 
# ChangeSet
#   2004/03/10 09:05:31+01:00 davidm@hpl.hp.com 
#   input: When reading input reports from a device via the ctrl pipe,
#          set idle time of the device. This makes buggy devices which
#          take the idle time into account for the ctrl pipe work.
# 
# drivers/usb/input/hid-core.c
#   2004/03/10 09:05:24+01:00 davidm@hpl.hp.com +21 -2
#   input: When reading input reports from a device via the ctrl pipe,
#          set idle time of the device. This makes buggy devices which
#          take the idle time into account for the ctrl pipe work.
# 
# ChangeSet
#   2004/03/10 09:02:48+01:00 davidm@hpl.hp.com 
#   input: Avoid an endless loop in hid-core.c, if a device has some
#          empty reports.
# 
# drivers/usb/input/hid-input.c
#   2004/03/10 09:02:42+01:00 davidm@hpl.hp.com +3 -1
#   input: Avoid an endless loop in hid-core.c, if a device has some
#          empty reports.
# 
# ChangeSet
#   2004/03/09 17:25:56-08:00 david-b@pacbell.net 
#   [PATCH] USB: clarify CONFIG_USB_GADGET
#   
#   Marc-Christian Petersen wrote:
#   >
#   > I think the attached patch is needed to stop showing us USB Gadget support if
#   > Support for USB is disabled.
#   
#   No it isn't.  But maybe the attached patch would clarify what's
#   really going on:  CONFIG_USB is the host side, and CONFIG_USB_GADGET
#   is the peripheral side.
# 
# drivers/usb/gadget/Kconfig
#   2004/03/07 07:05:25-08:00 david-b@pacbell.net +10 -1
#   USB: clarify CONFIG_USB_GADGET
# 
# drivers/usb/Kconfig
#   2004/03/07 06:42:33-08:00 david-b@pacbell.net +21 -17
#   USB: clarify CONFIG_USB_GADGET
# 
# ChangeSet
#   2004/03/09 17:25:33-08:00 david-b@pacbell.net 
#   [PATCH] USB: gadget config buf utilities
#   
#   Somehow I sent you a version of this code with a misplaced
#   semicolon ... it makes for awkward failures!
#   
#   Please merge.  Bad semicolon!
# 
# drivers/usb/gadget/config.c
#   2004/03/05 08:00:10-08:00 david-b@pacbell.net +1 -1
#   USB: gadget config buf utilities
# 
# ChangeSet
#   2004/03/09 17:25:08-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet and ALI M5632
#   
#   Some of the 480 Mbit/sec USB host-to-host links have ALI
#   chips in them.  They seem to work with no problem, given
#   this patch, even when the ends talk different speed.
# 
# drivers/usb/net/usbnet.c
#   2004/03/04 06:24:59-08:00 david-b@pacbell.net +24 -0
#   USB: usbnet and ALI M5632
# 
# drivers/usb/net/Kconfig
#   2004/03/04 06:21:32-08:00 david-b@pacbell.net +8 -0
#   USB: usbnet and ALI M5632
# 
# ChangeSet
#   2004/03/09 14:12:30-08:00 petkan@nucleusys.com 
#   [PATCH] USB: 2.6 pegasus.h updates
#   
#   a few more IDs added, could you please apply it?
# 
# drivers/usb/net/pegasus.h
#   2004/03/09 10:48:49-08:00 petkan@nucleusys.com +8 -0
#   USB: 2.6 pegasus.h updates
# 
# ChangeSet
#   2004/03/09 14:12:08-08:00 s.doyon@videotron.ca 
#   [PATCH] USB brlvger: Driver obsoleted by rewrite using usbfs
#   
#   We have rewritten the brlvger (Tieman Voyager USB Braille display) driver
#   so that it works from user-space through usbfs. It appears to work just as
#   well as the in-kernel driver.
#   
#   The brlvger driver in the 2.6.x kernel is now obsolete and should be
#   removed. The attached patch against 2.6.3 does this. Please apply.
#   NB: The following files are completely deleted:
#       Documentation/usb/brlvger.txt
#       drivers/usb/misc/brlvger.c
#       include/linux/brlvger.h
#   
#   The new Voyager driver is available (stil under GPL) as part of BRLTTY,
#   starting with version 3.5pre1 (http://mielke.cc/brltty).
#   Thanks to Dave Mielke who implemented BRLTTY's usbfs functionality, among
#   lots of other stuff.
# 
# drivers/usb/misc/Makefile
#   2004/03/09 01:50:35-08:00 s.doyon@videotron.ca +0 -1
#   USB brlvger: Driver obsoleted by rewrite using usbfs
# 
# drivers/usb/misc/Kconfig
#   2004/03/09 01:51:14-08:00 s.doyon@videotron.ca +0 -11
#   USB brlvger: Driver obsoleted by rewrite using usbfs
# 
# drivers/usb/Makefile
#   2004/03/09 01:52:05-08:00 s.doyon@videotron.ca +0 -1
#   USB brlvger: Driver obsoleted by rewrite using usbfs
# 
# MAINTAINERS
#   2004/03/09 01:48:11-08:00 s.doyon@videotron.ca +0 -7
#   USB brlvger: Driver obsoleted by rewrite using usbfs
# 
# CREDITS
#   2004/03/09 04:29:41-08:00 s.doyon@videotron.ca +0 -10
#   USB brlvger: Driver obsoleted by rewrite using usbfs
# 
# BitKeeper/deleted/.del-brlvger.txt~281c551849400437
#   2004/03/09 14:11:47-08:00 s.doyon@videotron.ca +0 -0
#   Delete: Documentation/usb/brlvger.txt
# 
# BitKeeper/deleted/.del-brlvger.h~24510706dc74b0b9
#   2004/03/09 14:11:47-08:00 s.doyon@videotron.ca +0 -0
#   Delete: include/linux/brlvger.h
# 
# BitKeeper/deleted/.del-brlvger.c~af9a17941a445cad
#   2004/03/09 14:11:47-08:00 s.doyon@videotron.ca +0 -0
#   Delete: drivers/usb/misc/brlvger.c
# 
# ChangeSet
#   2004/03/09 09:47:21-08:00 greg@kroah.com 
#   [PATCH] USB: fix compiler warning in hfc_usb.c driver.
# 
# drivers/isdn/hisax/hfc_usb.c
#   2004/03/09 01:46:18-08:00 greg@kroah.com +1 -1
#   USB: fix compiler warning in hfc_usb.c driver.
# 
# ChangeSet
#   2004/03/09 09:47:03-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Interface/altsetting update for ISDN hisax driver
#   
#   On Mon, 8 Mar 2004, Greg KH wrote:
#   
#   > Oh, could you look at drivers/isdn/hisax/hfc_usb.c if you get a chance?
#   > I tried to figure out the mess there with regards to act_altsetting, but
#   > gave up :(
#   
#   You're right, it is a mess.  Beats me why they didn't use a plain old
#   "for" statement to do that altsetting loop.  Probably the most confusing
#   part is where the code needlessly resets intf->act_altsetting.
#   
#   Anyway, this patch sets things right.  I haven't tried to compile it, but
#   any errors ought to be pretty small, obvious, and easy to fix.
#   
#   My intention was to go through the files under driver/usb (in alphabetical
#   order!) and then do the ones outside that subtree -- I've got a little
#   list.  But it's no problem to take care of this one first.
# 
# drivers/isdn/hisax/hfc_usb.c
#   2004/03/09 02:41:16-08:00 stern@rowland.harvard.edu +16 -13
#   USB: Interface/altsetting update for ISDN hisax driver
# 
# ChangeSet
#   2004/03/08 15:07:52-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB UHCI: restore more state following PM resume
#   
#   Some systems don't save the internal state of the UHCI registers across a
#   PM suspend/resume cycle very well.  This patch saves & restores the
#   Frame Number and the Framelist Base Address registers (in addition to the
#   Interrupt Enable register, which was added separately in a recent patch.)
# 
# drivers/usb/host/uhci-hcd.h
#   2004/03/08 04:04:32-08:00 stern@rowland.harvard.edu +1 -0
#   USB UHCI: restore more state following PM resume
# 
# drivers/usb/host/uhci-hcd.c
#   2004/03/08 04:11:22-08:00 stern@rowland.harvard.edu +10 -4
#   USB UHCI: restore more state following PM resume
# 
# ChangeSet
#   2004/03/08 15:07:27-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Remove interface/altsettings assumption from audio driver
#   
#   This patch updates the USB audio class driver to use the usb_ifnum_to_if()
#   and usb_altnum_to_altsetting() routines, thereby removing assumptions
#   about which interface or altsetting is stored in which array entry.
#   
#   It also simplifies the driver's probe() routine by using the raw
#   configuration descriptor already loaded into memory instead of reading the
#   descriptor from the device.  Now, either the current driver has a bug and
#   never deallocates the buffer used to hold the descriptor, or else I've
#   introduced a double-free error.  There's no obvious place where the buffer
#   gets freed, but it's hard to be certain.
#   
#   It would be good if someone could try out this patch.  I can't test it,
#   not having any USB audio devices handy.  If the double-free error is
#   present, it will show up when the device is disconnected and the
#   configuration data is released.
# 
# drivers/usb/class/audio.c
#   2004/03/08 03:11:28-08:00 stern@rowland.harvard.edu +61 -74
#   USB: Remove interface/altsettings assumption from audio driver
# 
# ChangeSet
#   2004/03/08 15:07:07-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Update USB class drivers
#   
#   This patch makes the necessary updates to the bluetty, cdc-acm, and usblp
#   class drivers for the new interface/altsetting paradigm.  The changes are
#   quite small.
#   
#   Unfortunately, the audio and usb-midi drivers are in much worse shape.
#   They will require more in-depth hacking, to come later...
# 
# drivers/usb/class/usblp.c
#   2004/03/05 03:40:58-08:00 stern@rowland.harvard.edu +6 -3
#   USB: Update USB class drivers
# 
# drivers/usb/class/cdc-acm.c
#   2004/03/05 03:16:32-08:00 stern@rowland.harvard.edu +3 -3
#   USB: Update USB class drivers
# 
# drivers/usb/class/bluetty.c
#   2004/03/05 03:11:33-08:00 stern@rowland.harvard.edu +1 -1
#   USB: Update USB class drivers
# 
# ChangeSet
#   2004/03/08 11:53:44-08:00 greg@kroah.com 
#   USB: fix usb-serial core to look at the proper interface descriptor
# 
# drivers/usb/serial/usb-serial.c
#   2004/03/08 11:53:38-08:00 greg@kroah.com +1 -1
#   USB: fix usb-serial core to look at the proper interface descriptor
# 
# ChangeSet
#   2004/03/08 11:53:02-08:00 greg@kroah.com 
#   USB: fix the pcwd_usb driver due to act_altsetting going away.
# 
# drivers/char/watchdog/pcwd_usb.c
#   2004/03/08 11:52:54-08:00 greg@kroah.com +1 -1
#   USB: fix the pcwd_usb driver due to act_altsetting going away.
# 
# ChangeSet
#   2004/03/08 11:11:32-08:00 greg@kroah.com 
#   merge fixups with irda usb code
# 
# drivers/net/irda/stir4200.c
#   2004/03/08 11:11:23-08:00 greg@kroah.com +0 -46
#   merge fixups with irda usb code
# 
# ChangeSet
#   2004/03/08 11:00:29-08:00 greg@kroah.com 
#   merge
# 
# drivers/net/irda/stir4200.c
#   2004/03/08 11:00:22-08:00 greg@kroah.com +46 -0
#   merge
# 
# drivers/usb/serial/keyspan.h
#   2004/03/08 10:51:45-08:00 greg@kroah.com +0 -13
#   Auto merged
# 
# ChangeSet
#   2004/03/08 14:32:00+01:00 vojtech@suse.cz 
#   input: Fix oops (NULL pointer dereference) on resume in psmouse.c,
#          when the mouse goes away while sleeping.
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/08 14:31:55+01:00 vojtech@suse.cz +4 -2
#   input: Fix oops (NULL pointer dereference) on resume in psmouse.c,
#          when the mouse goes away while sleeping.
# 
# ChangeSet
#   2004/03/08 14:09:15+01:00 szuk@telusplanet.net 
#   input: Restore LED state in atkbd.c after resume.
# 
# drivers/input/keyboard/atkbd.c
#   2004/03/08 14:09:10+01:00 szuk@telusplanet.net +9 -0
#   input: Restore LED state in atkbd.c after resume.
# 
# ChangeSet
#   2004/03/08 13:30:04+01:00 vojtech@suse.cz 
#   input: Don't define DEBUG in hid-ff by default. It spews messgaes
#          even when no FF device is present.
# 
# drivers/usb/input/hid-ff.c
#   2004/03/08 13:29:59+01:00 vojtech@suse.cz +1 -1
#   input: Don't define DEBUG in hid-ff by default. It spews messgaes
#          even when no FF device is present.
# 
# ChangeSet
#   2004/03/08 13:16:03+01:00 vojtech@suse.cz 
#   input: Add a Chic gamepad into badpad quirk list.
# 
# drivers/usb/input/hid-core.c
#   2004/03/08 13:15:58+01:00 vojtech@suse.cz +4 -0
#   input: Add a Chic gamepad into badpad quirk list.
# 
# ChangeSet
#   2004/03/08 12:51:07+01:00 sebek64@post.cz 
#   input: Fix a memory leak in ns558.c
# 
# drivers/input/gameport/ns558.c
#   2004/03/08 12:51:01+01:00 sebek64@post.cz +1 -0
#   input: Fix a memory leak in ns558.c
# 
# ChangeSet
#   2004/03/08 11:20:44+01:00 home@mdiehl.de 
#   input: Add support for devices which need some padding at the
#          end of a HID report.
# 
# drivers/usb/input/hid.h
#   2004/03/08 11:20:39+01:00 home@mdiehl.de +1 -1
#   input: Add support for devices which need some padding at the
#          end of a HID report.
# 
# drivers/usb/input/hid-core.c
#   2004/03/08 11:20:39+01:00 home@mdiehl.de +26 -10
#   input: Add support for devices which need some padding at the
#          end of a HID report.
# 
# ChangeSet
#   2004/03/08 10:12:10+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# Documentation/kernel-parameters.txt
#   2004/03/08 10:12:08+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/08 10:09:44+01:00 vojtech@suse.cz 
#   input: Update the Wacom driver to latest version
#          from Ping Cheng from Wacom.
# 
# drivers/usb/input/wacom.c
#   2004/03/08 10:09:39+01:00 vojtech@suse.cz +143 -34
#   input: Update the Wacom driver to latest version
#          from Ping Cheng from Wacom.
# 
# drivers/usb/input/hid-core.c
#   2004/03/08 10:09:39+01:00 vojtech@suse.cz +7 -1
#   input: Update the Wacom driver to latest version
#          from Ping Cheng from Wacom.
# 
# ChangeSet
#   2004/03/05 09:29:47+01:00 rmk@arm.linux.org.uk 
#   input: Fix i8042 PS/2 mouse on ARM.
# 
# include/asm-arm/arch-shark/irqs.h
#   2004/03/05 09:29:42+01:00 rmk@arm.linux.org.uk +2 -1
#   input: Fix i8042 PS/2 mouse on ARM.
# 
# include/asm-arm/arch-ebsa285/irqs.h
#   2004/03/05 09:29:42+01:00 rmk@arm.linux.org.uk +2 -2
#   input: Fix i8042 PS/2 mouse on ARM.
# 
# drivers/input/serio/i8042-io.h
#   2004/03/05 09:29:42+01:00 rmk@arm.linux.org.uk +3 -0
#   input: Fix i8042 PS/2 mouse on ARM.
# 
# ChangeSet
#   2004/03/04 10:58:18+01:00 warp@mercury.d2dc.net 
#   input: HID needs to distinguish between two types of A4Tech
#          two-wheel mice.
# 
# drivers/usb/input/hid.h
#   2004/03/04 10:58:13+01:00 warp@mercury.d2dc.net +10 -9
#   input: HID needs to distinguish between two types of A4Tech
#          two-wheel mice.
# 
# drivers/usb/input/hid-input.c
#   2004/03/04 10:58:13+01:00 warp@mercury.d2dc.net +4 -3
#   input: HID needs to distinguish between two types of A4Tech
#          two-wheel mice.
# 
# drivers/usb/input/hid-core.c
#   2004/03/04 10:58:13+01:00 warp@mercury.d2dc.net +2 -2
#   input: HID needs to distinguish between two types of A4Tech
#          two-wheel mice.
# 
# ChangeSet
#   2004/03/04 09:21:42+01:00 john@fremlin.de 
#   input: Add a NEC USB gamepad to badpad blacklist.
# 
# drivers/usb/input/hid-core.c
#   2004/03/04 09:21:37+01:00 john@fremlin.de +4 -0
#   input: Add a NEC USB gamepad to badpad blacklist.
# 
# ChangeSet
#   2004/03/03 17:01:21-08:00 david-b@pacbell.net 
#   [PATCH] USB: HCD names, for better troubleshooting
#   
#   See the attached patch -- which restores the behavior of usbcore
#   to what it had before "struct device.name" went away, in the
#   (typical) case of PCI devices.
#   
#   It makes the root hubs say what hardware they're actually using,
#   in the reasonably typical case that PCI names are in use, rather
#   than being just generic (and hence almost useless) strings.  This
#   sort of information can really help when troubleshooting.
# 
# drivers/usb/core/hcd-pci.c
#   2004/02/28 04:16:01-08:00 david-b@pacbell.net +4 -0
#   USB: HCD names, for better troubleshooting
# 
# ChangeSet
#   2004/03/03 12:54:26-08:00 greg@kroah.com 
#   [PATCH] USB: remove intf->act_altsetting altogether from the USB core and usb.h
# 
# include/linux/usb.h
#   2004/03/03 04:48:13-08:00 greg@kroah.com +0 -5
#   USB: remove intf->act_altsetting altogether from the USB core and usb.h
# 
# drivers/usb/core/message.c
#   2004/03/03 04:48:13-08:00 greg@kroah.com +0 -3
#   USB: remove intf->act_altsetting altogether from the USB core and usb.h
# 
# ChangeSet
#   2004/03/03 12:54:08-08:00 greg@kroah.com 
#   [PATCH] USB: remove act_altsetting usages in more USB drivers
# 
# drivers/usb/input/usbmouse.c
#   2004/03/03 04:48:07-08:00 greg@kroah.com +1 -1
#   USB: remove act_altsetting usages in more USB drivers
# 
# drivers/usb/input/usbkbd.c
#   2004/03/03 04:48:07-08:00 greg@kroah.com +1 -1
#   USB: remove act_altsetting usages in more USB drivers
# 
# drivers/net/irda/stir4200.c
#   2004/03/03 04:48:07-08:00 greg@kroah.com +1 -2
#   USB: remove act_altsetting usages in more USB drivers
# 
# drivers/input/joystick/iforce/iforce-usb.c
#   2004/03/03 04:48:07-08:00 greg@kroah.com +1 -1
#   USB: remove act_altsetting usages in more USB drivers
# 
# ChangeSet
#   2004/03/03 12:53:48-08:00 greg@kroah.com 
#   [PATCH] USB: remove act_altsetting usages in the remaining drivers/usb/ drivers
# 
# drivers/usb/net/usbnet.c
#   2004/03/03 04:47:59-08:00 greg@kroah.com +1 -1
#   USB: remove act_altsetting usages in the remaining drivers/usb/ drivers
# 
# drivers/usb/input/mtouchusb.c
#   2004/03/03 04:47:59-08:00 greg@kroah.com +1 -1
#   USB: remove act_altsetting usages in the remaining drivers/usb/ drivers
# 
# drivers/usb/input/hid-core.c
#   2004/03/03 04:47:59-08:00 greg@kroah.com +1 -1
#   USB: remove act_altsetting usages in the remaining drivers/usb/ drivers
# 
# drivers/usb/input/ati_remote.c
#   2004/03/03 04:47:59-08:00 greg@kroah.com +1 -1
#   USB: remove act_altsetting usages in the remaining drivers/usb/ drivers
# 
# ChangeSet
#   2004/03/03 12:53:25-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Convert usbtest to the new altsetting regime
#   
#   This patch converts the usbtest driver to the new way altsettings work.
#   The largest change is to remove the assumptions that altsetting numbers
#   lie in the correct range (a debugging message is logged if they don't but
#   execution doesn't stop) and that the array is sorted by number.
# 
# drivers/usb/misc/usbtest.c
#   2004/03/01 03:40:11-08:00 stern@rowland.harvard.edu +10 -14
#   USB: Convert usbtest to the new altsetting regime
# 
# ChangeSet
#   2004/03/03 12:53:03-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Convert usb-storage to use cur_altsetting
#   
#   I'm beginning the process of converting device drivers to use
#   cur_altsetting with usb-storage, the one I know best.  Only a few changes
#   are needed (and the first one isn't even really necessary).
# 
# drivers/usb/storage/usb.c
#   2004/03/01 03:40:11-08:00 stern@rowland.harvard.edu +6 -5
#   USB: Convert usb-storage to use cur_altsetting
# 
# ChangeSet
#   2004/03/03 12:52:40-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Small improvements for devio.c
#   
#   devio.c doesn't need to be changed to support the new altsetting
#   mechanism, but while looking through it I noticed a couple of places that
#   could be improved slightly.  Here they are, just removal of some redundant
#   tests (all altsettings for the same interface are guaranteed to have the
#   same bInterfaceNumber) and function calls.
# 
# drivers/usb/core/devio.c
#   2004/03/01 03:40:11-08:00 stern@rowland.harvard.edu +6 -15
#   USB: Small improvements for devio.c
# 
# ChangeSet
#   2004/03/03 12:52:13-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Convert usbcore to use cur_altsetting
#   
#   This patch continues the work of as209 by converting the rest of usbcore
#   to use cur_altsetting in place of act_altsetting.  The changes required
#   are fairly small, just in the sysfs attributes and hub configuration.
# 
# drivers/usb/core/hub.c
#   2004/03/01 03:40:11-08:00 stern@rowland.harvard.edu +6 -6
#   USB: Convert usbcore to use cur_altsetting
# 
# drivers/usb/core/driverfs.c
#   2004/03/01 03:40:11-08:00 stern@rowland.harvard.edu +2 -6
#   USB: Convert usbcore to use cur_altsetting
# 
# ChangeSet
#   2004/03/03 12:49:44-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Improve handling of altsettings
#   
#   On Sat, 21 Feb 2004, Greg KH wrote:
#   
#   > > One thing that would be good, whether this change gets made or not, is to
#   > > remove all assumptions from drivers about the order in which interfaces
#   > > are stored (use usb_ifnum_to_if()) and the order in which altsettings are
#   > > stored (replace intf.act_altsetting with a pointer and create
#   > > usb_altnum_to_alt() analogous to usb_ifnum_to_if()).  There are plenty of
#   > > drivers that will need to be fixed up.
#   >
#   > I'd be glad to take patches to fix up any drivers that still have this
#   > problem right now.
#   
#   Here's a start.  This patch begins the conversion process by adding
#   usbcore support for cur_altsetting and deprecating act_altsetting.
#   
#   So long as we assumed that altsetting numbers range from 0 to
#   num_altsetting-1 and that the number matches its index in the altsetting
#   array, there was no harm in using act_altsetting.  But without that
#   assumption act_altsetting is merely an invitation to errors.  Although the
#   kerneldoc says that act_altsetting is the _index_ of the active
#   altsetting, it's all too easy to confuse it with the _number_ of the
#   active altsetting.  Using cur_altsetting instead (a pointer rather than a
#   number) will prevent that confusion.
#   
#   Until all the drivers have been converted to use cur_altsetting, the core
#   will have to maintain act_altsetting in parallel with it.  Eventually we
#   will be able to remove act_altsetting, but fixing all the drivers will
#   take a while.
#   
#   Included in this patch:
#   
#   	Add cur_altsetting to struct usb_interface and deprecate
#   	act_altsetting.
#   
#   	Add comments and kerneldoc explaining the changes.  Also remove
#   	the comments in front of struct usb_host_config (they seem to
#   	have been left behind when usb_ch9.h was split out) and add
#   	kerneldoc for that structure.
#   
#   	Add usb_altnum_to_altsetting() to help look up altsettings based
#   	on their number.
#   
#   	Convert the usb_set_interface(), usb_set_configuration(), and
#   	usb_reset_configuration() routines to support cur_altsetting
#   	and act_altsetting in parallel.  Convert a few others to use
#   	cur_altsetting rather than act_altsetting.
#   
#   	Rename a few local variables to make their meaning a little
#   	clearer.  It would be nice to change struct usb_host_interface
#   	to something like usb_host_altsetting, but that's a patch for
#   	another time.
# 
# include/linux/usb.h
#   2004/03/01 03:01:40-08:00 stern@rowland.harvard.edu +56 -20
#   USB: Improve handling of altsettings
# 
# drivers/usb/core/usb.c
#   2004/03/01 03:01:40-08:00 stern@rowland.harvard.edu +35 -7
#   USB: Improve handling of altsettings
# 
# drivers/usb/core/message.c
#   2004/03/01 03:01:40-08:00 stern@rowland.harvard.edu +44 -24
#   USB: Improve handling of altsettings
# 
# ChangeSet
#   2004/03/03 11:16:57-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Don't add/del interfaces, register/unregister them
#   
#   On Fri, 27 Feb 2004, Greg KH wrote:
#   
#   > On Wed, Feb 25, 2004 at 10:05:37AM -0500, Alan Stern wrote:
#   >
#   > > Why would anyone want to do this, you ask?  Well the USB subsystem does it
#   > > already.  Each USB device can have several configurations, only one of
#   > > which is active at any time.  Corresponding to each configuration is a set
#   > > of struct devices, and they (together with their embedded kobjects) are
#   > > allocated and initialized when the USB device is first detected.  The
#   > > struct devices are add()'ed and del()'ed as configurations are activated
#   > > and deactivated, leading to just the sort of call sequence shown above.
#   >
#   > Then we need to fix this.
#   
#   The driver model does not support repeated device_add(), device_del(),
#   device_add(), device_del(), ... calls for the same device.  But that's
#   what happens to an interface's embedded struct device when we change
#   configurations.
#   
#   Accordingly, this patch changes the device_add()/device_del() calls for
#   interfaces to device_register()/device_unregister().  When the interface
#   is unregistered the new code waits for the release method to run, so that
#   it will be safe to re-register the interface should the former
#   configuration be reinstated.
#   
#   Greg, please check this out to make sure I haven't made some dumb mistake.
#   It works on my system and it fixes a memory leak in the USB system.
# 
# include/linux/usb.h
#   2004/02/27 08:46:19-08:00 stern@rowland.harvard.edu +3 -0
#   USB: Don't add/del interfaces, register/unregister them
# 
# drivers/usb/core/message.c
#   2004/02/27 08:46:19-08:00 stern@rowland.harvard.edu +14 -2
#   USB: Don't add/del interfaces, register/unregister them
# 
# drivers/usb/core/config.c
#   2004/02/27 08:46:19-08:00 stern@rowland.harvard.edu +2 -7
#   USB: Don't add/del interfaces, register/unregister them
# 
# ChangeSet
#   2004/03/03 10:16:35-08:00 sailer@scs.ch 
#   [PATCH] USB: USB OSS audio driver workaround for buggy descriptors
# 
# drivers/usb/class/audio.c
#   2004/02/27 04:10:57-08:00 sailer@scs.ch +13 -9
#   USB: USB OSS audio driver workaround for buggy descriptors
# 
# ChangeSet
#   2004/03/03 10:00:13-08:00 david-b@pacbell.net 
#   [PATCH] USB Gadget: make usb gadget strings talk utf-8
#   
#   Teach gadget/usbstring to expect UTF-8 strings, not ISO-8859/1 ones.
#   This just gets rid of an API issue:  no hacks needed for non-Western
#   languages, and multi-language support will be lots easier.
#   
#   Current drivers won't notice the API change, they use US-ASCII (which
#   is a strict superset of both encodings).
#   
#   Future drivers may want to teach utf8_to_utf16le() about the four-byte
#   encodings, so they can emit surrogate pairs for those Unicode characters.
# 
# include/linux/usb_gadget.h
#   2004/02/28 01:58:35-08:00 david-b@pacbell.net +1 -1
#   USB Gadget: make usb gadget strings talk utf-8
# 
# drivers/usb/gadget/usbstring.c
#   2004/02/27 07:51:38-08:00 david-b@pacbell.net +78 -14
#   USB Gadget: make usb gadget strings talk utf-8
# 
# ChangeSet
#   2004/03/03 17:17:09+01:00 jbglaw@lug-owl.de 
#   input: Add driver for DEC VSXXX mice.
# 
# drivers/input/mouse/vsxxxaa.c
#   2004/03/03 17:17:04+01:00 jbglaw@lug-owl.de +550 -0
# 
# drivers/input/mouse/vsxxxaa.c
#   2004/03/03 17:17:04+01:00 jbglaw@lug-owl.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/mouse/vsxxxaa.c
# 
# drivers/input/mouse/Makefile
#   2004/03/03 17:17:04+01:00 jbglaw@lug-owl.de +1 -0
#   input: Add driver for DEC VSXXX mice.
# 
# drivers/input/mouse/Kconfig
#   2004/03/03 17:17:04+01:00 jbglaw@lug-owl.de +13 -0
#   input: Add driver for DEC VSXXX mice.
# 
# ChangeSet
#   2004/03/03 17:16:24+01:00 jbglaw@lug-owl.de 
#   input: Add DEC LK201/LK401 keyboard support
# 
# drivers/input/keyboard/lkkbd.c
#   2004/03/03 17:16:19+01:00 jbglaw@lug-owl.de +625 -0
# 
# drivers/input/keyboard/lkkbd.c
#   2004/03/03 17:16:19+01:00 jbglaw@lug-owl.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/keyboard/lkkbd.c
# 
# drivers/input/keyboard/Makefile
#   2004/03/03 17:16:19+01:00 jbglaw@lug-owl.de +1 -0
#   input: Add DEC LK201/LK401 keyboard support
# 
# drivers/input/keyboard/Kconfig
#   2004/03/03 17:16:19+01:00 jbglaw@lug-owl.de +13 -0
#   input: Add DEC LK201/LK401 keyboard support
# 
# ChangeSet
#   2004/03/03 15:14:01+01:00 vojtech@suse.cz 
#   input: i8042.c:
#     Assume the chip always is in XLATE mode, even when it doesn't
#     have the XLATE bit set - apparently IBM PS/2 model 70 behaves
#     this way.
# 
# drivers/input/serio/i8042.c
#   2004/03/03 15:13:56+01:00 vojtech@suse.cz +0 -8
#   input: i8042.c:
#     Assume the chip always is in XLATE mode, even when it doesn't
#     have the XLATE bit set - apparently IBM PS/2 model 70 behaves
#     this way.
# 
# ChangeSet
#   2004/03/03 11:50:22+01:00 vojtech@suse.cz 
#   input: Only do hotplug on PS/2 HW when the HW sends 0xaa. This
#          avoids problems with broken USB->PS/2 legacy emulation
#          in certain BIOSes.
# 
# drivers/input/serio/serio.c
#   2004/03/03 11:50:17+01:00 vojtech@suse.cz +3 -0
#   input: Only do hotplug on PS/2 HW when the HW sends 0xaa. This
#          avoids problems with broken USB->PS/2 legacy emulation
#          in certain BIOSes.
# 
# ChangeSet
#   2004/03/03 11:49:20+01:00 vojtech@suse.cz 
#   input: Workaround i8042 chips with broken MUX mode.
# 
# drivers/input/serio/i8042.c
#   2004/03/03 11:49:15+01:00 vojtech@suse.cz +5 -0
#   input: Workaround i8042 chips with broken MUX mode.
# 
# ChangeSet
#   2004/03/03 10:13:59+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/input/serio/i8042.c
#   2004/03/03 10:13:56+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/03 09:59:51+01:00 vojtech@suse.cz 
#   input: Manual merge with Dmitry.
# 
# drivers/input/keyboard/atkbd.c
#   2004/03/03 09:59:46+01:00 vojtech@suse.cz +4 -6
#   input: Manual merge with Dmitry.
# 
# drivers/input/serio/i8042.c
#   2004/03/03 09:57:37+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# Documentation/kernel-parameters.txt
#   2004/03/03 09:57:36+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/03 00:36:59-05:00 dtor_core@ameritech.net 
#   Input: use __obsolete_setup to document removed (renamed)
#          options so users will have a clue why the options
#          do not work anymore
# 
# drivers/input/serio/i8042.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +7 -0
#   Use __obsolete_setup
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +6 -0
#   Use __obsolete_setup
# 
# drivers/input/mouse/logibm.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +2 -0
#   Use __obsolete_setup
# 
# drivers/input/mouse/inport.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +2 -0
#   Use __obsolete_setup
# 
# drivers/input/mouse/98busmouse.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +2 -0
#   Use __obsolete_setup
# 
# drivers/input/keyboard/atkbd.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +4 -0
#   Use __obsolete_setup
# 
# drivers/input/joystick/turbografx.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +4 -0
#   Use __obsolete_setup
# 
# drivers/input/joystick/gamecon.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +6 -0
#   Use __obsolete_setup
# 
# drivers/input/joystick/db9.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +4 -0
#   Use __obsolete_setup
# 
# drivers/input/joystick/analog.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +2 -0
#   Use __obsolete_setup
# 
# drivers/input/joystick/amijoy.c
#   2004/03/02 19:36:23-05:00 dtor_core@ameritech.net +2 -0
#   Use __obsolete_setup
# 
# ChangeSet
#   2004/03/03 00:35:47-05:00 dtor_core@ameritech.net 
#   Setup: introduce __obsolete_setup macro to denote truly obsolete
#          parameters. Whenever such parameter is specified kernel
#          will complain that "Parameter %s is obsolete, ignored"
# 
# init/main.c
#   2004/03/02 19:35:30-05:00 dtor_core@ameritech.net +5 -2
#   If there is no setup function for kernel parameter assume that
#   the parameter is obsolete and complain
# 
# include/linux/init.h
#   2004/03/02 19:35:30-05:00 dtor_core@ameritech.net +17 -5
#   Introduce __obsolete_setup macro
# 
# ChangeSet
#   2004/03/03 00:34:38-05:00 dtor_core@ameritech.net 
#   Input: Convert joystick modules to the new way of handling parameters and
#          document them in kernel-parameters.txt
#   
#          The new names are:
#            amijoy.map=<a>,<b>
#            analog.map=<type1>,<type2>,...<type16>
#            db9.dev[2|3]=<parport#>,<type>
#            gamecon.map[2|3]=<parport#>,<pad1>,<pad2>,...<pad5>
#            turbografx.map[2|3]=<parport#>,<js1>,<js2>,...<js7>
#   
#          Also there is a tiny change to mousedev and tsdev descriptions in
#          kernel-parameters, but no name changes.
# 
# drivers/input/joystick/turbografx.c
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +25 -39
#   Convert to use module_param
# 
# drivers/input/joystick/gamecon.c
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +30 -46
#   Convert to use module_param
# 
# drivers/input/joystick/db9.c
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +25 -38
#   Convert to use module_param
# 
# drivers/input/joystick/analog.c
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +5 -21
#   Convert to use module_param
# 
# drivers/input/joystick/amijoy.c
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +5 -12
#   Convert to use module_param
# 
# Documentation/kernel-parameters.txt
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +29 -17
#   Document new parameter names
# 
# Documentation/input/joystick.txt
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +3 -3
#   Document new parameter names
# 
# Documentation/input/joystick-parport.txt
#   2004/03/02 19:34:21-05:00 dtor_core@ameritech.net +8 -8
#   Document new parameter names
# 
# ChangeSet
#   2004/03/03 00:32:43-05:00 dtor_core@ameritech.net 
#   Introduce module_param_array_named to allow for module options with
#   name different form corresponding array variable. Allows using short
#   (but descriptive) option names without hurting code readability.
#   
#   Modeled after module_param_named.
# 
# include/linux/moduleparam.h
#   2004/03/02 19:32:24-05:00 dtor_core@ameritech.net +6 -3
#   Add module_param_array_named
# 
# ChangeSet
#   2004/03/03 00:31:24-05:00 dtor_core@ameritech.net 
#   Psmouse: some hardware does not ACK "disable streaming mode" command.
#            Since we already have an idea that it's a mouse device that
#            is present (from its response to GET ID command), instead of
#            aborting, issue a warning and continue.
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/02 19:30:50-05:00 dtor_core@ameritech.net +1 -1
#   Work around broken hardware
# 
# ChangeSet
#   2004/03/03 00:30:04-05:00 dtor_core@ameritech.net 
#   Psmouse: whitespace fixes
# 
# drivers/input/mouse/psmouse-base.c
#   2004/03/02 19:29:39-05:00 dtor_core@ameritech.net +7 -7
#   Whitespace fixes
# 
# ChangeSet
#   2004/03/03 00:29:09-05:00 dtor_core@ameritech.net 
#   Input: Switch between strict/relaxed synaptics protocol checks based on
#          data in the first full data packet. Having strict checks helps
#          getting rid of bad data after losing sync, but not all harware
#          implements strict protocol.
# 
# drivers/input/mouse/synaptics.h
#   2004/03/02 19:28:53-05:00 dtor_core@ameritech.net +7 -0
#   Packet type added to synaptics structure
# 
# drivers/input/mouse/synaptics.c
#   2004/03/02 19:28:53-05:00 dtor_core@ameritech.net +41 -12
#   Dynamically switch between strict and relaxed protocol checks
# 
# ChangeSet
#   2004/03/03 00:27:15-05:00 dtor_core@ameritech.net 
#   Atkbd: Clean up unclean merge (remove old MODULE_PARMs)
# 
# drivers/input/keyboard/atkbd.c
#   2004/03/02 19:26:44-05:00 dtor_core@ameritech.net +1 -5
#   Clean up unclean merge
# 
# ChangeSet
#   2004/03/03 00:25:49-05:00 dtor_core@ameritech.net 
#   Atkbd: whitespace fixes
# 
# drivers/input/keyboard/atkbd.c
#   2004/03/02 19:20:19-05:00 dtor_core@ameritech.net +10 -10
#   Whitespace fixes
# 
# ChangeSet
#   2004/03/02 13:47:14+01:00 jbglaw@lug-owl.de 
#   input: Add serio entries for LK keyboards.
# 
# include/linux/serio.h
#   2004/03/02 13:47:09+01:00 jbglaw@lug-owl.de +2 -0
#   input: Add serio entries for LK keyboards.
# 
# ChangeSet
#   2004/03/01 15:58:31-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB Storage: Revision of as202, Genesys quirk patch
#   
#   In the slave_configure routine it's already too late for the host's
#   max_sector value to affect the scsi_device.  It's necessary to set the
#   queue value directly.  This revised patch takes care of that.
# 
# drivers/usb/storage/scsiglue.c
#   2004/02/25 01:49:27-08:00 stern@rowland.harvard.edu +13 -1
#   USB Storage: Revision of as202, Genesys quirk patch
# 
# ChangeSet
#   2004/03/01 15:04:41-08:00 jurgen@botz.org 
#   [PATCH] USB: visor patch for Samsung SPH-i500
#   
#   Hi... here is a patch for the vendor/device codes for the
#   Samsung SPH-i500 Palm phone.
# 
# drivers/usb/serial/visor.h
#   2004/02/16 03:34:06-08:00 jurgen@botz.org +1 -0
#   USB: visor patch for Samsung SPH-i500
# 
# drivers/usb/serial/visor.c
#   2004/02/16 03:34:06-08:00 jurgen@botz.org +3 -0
#   USB: visor patch for Samsung SPH-i500
# 
# ChangeSet
#   2004/03/01 13:55:09-08:00 brill@fs.math.uni-frankfurt.de 
#   [PATCH] USB Storage: unusual_devs.h entry submission
#   
#   here is an unusual_devs.h entry which makes two different USB MP3 players
#   work with Linux' USB storage driver. They share a core chip, the t33520 USB
#   flash card controller by Trumpion microelectronics. They also share the same
#   ID 0x090a:0x1001, which is a "generic" ID for t33520 devices using bulk-only
#   protocol (0x1002 is for CB).
#   
#   About the MP3 players:
#     - I own an apparently unbranded one (sold in masses on ebay.de) which
#       needs US_FL_MODE_XLATE (and used to need US_FL_START_STOP before its
#       removal).
#     - Theodore Kilgore (who created the 0x090a:0x1001 record in the
#       Linux-USB device overwiew) has a "Trumpion Digital Research MYMP3"
#       which needs US_FL_MODE_XLATE and an explicit US_PR_BULK.
#   Of course the different players report the same firmware rev. 1.00,
#   despite their obviously different behaviour. Ugh.
#   
#   There are more players with this ID, the "Kaser Yofun 100 MP-3" (also
#   rev. 1.00) being one. The proposed entry may or may not help them, but
#   it shouldn't break working ones in any case. It is not unlikely they too
#   will need US_FL_MODE_XLATE.
#   
#   Below you'll find my /proc/bus/usb/devices with mounted MP3 player and a
#   patch against 2.4.25-rc3. Please apply.
#   
#   
#   
#    ----------------8<-------------------------8<--------------------
#   
#   T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
#   B:  Alloc=  0/900 us ( 0%), #Int=  0, #Iso=  0
#   D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
#   P:  Vendor=0000 ProdID=0000 Rev= 0.00
#   S:  Product=USB UHCI Root Hub
#   S:  SerialNumber=e400
#   C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
#   I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
#   E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
#   T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#=  2 Spd=12  MxCh= 0
#   D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
#   P:  Vendor=090a ProdID=1001 Rev= 1.00
#   C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr= 60mA
#   I:  If#= 0 Alt= 0 #EPs= 3 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
#   E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
#   E:  Ad=02(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
#   E:  Ad=83(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
#   
#    ----------------8<-------------------------8<--------------------
# 
# drivers/usb/storage/unusual_devs.h
#   2004/02/17 17:51:03-08:00 brill@fs.math.uni-frankfurt.de +11 -0
#   USB Storage: unusual_devs.h entry submission
# 
# ChangeSet
#   2004/03/01 13:41:08-08:00 per.winkvist@uk.com 
#   [PATCH] USB Storage: unusual devs fix for Pentax cameras.
#   
#   Please apply the attached patches instead. People have tried it on several
#   different Pentax cameras (including 330 GS)
# 
# drivers/usb/storage/unusual_devs.h
#   2004/02/04 00:53:10-08:00 per.winkvist@uk.com +1 -7
#   USB Storage: unusual devs fix for Pentax cameras.
# 
# ChangeSet
#   2004/03/01 13:30:26-08:00 ahaas@airmail.net 
#   [PATCH] USB: C99 initializers for drivers/usb/serial/keyspan.h
#   
#   Here's a small patch changing the GNU-style initializers to C99
#   initializers. The patch is against the current BK.
# 
# drivers/usb/serial/keyspan.h
#   2004/02/25 23:25:09-08:00 ahaas@airmail.net +13 -13
#   USB: C99 initializers for drivers/usb/serial/keyspan.h
# 
# ChangeSet
#   2004/03/01 10:38:34-08:00 akpm@osdl.org 
#   [PATCH] USB ati_remote.c: don't be a namespace hog
#   
#   `debug', indeed.
# 
# drivers/usb/input/ati_remote.c
#   2004/02/29 17:38:20-08:00 akpm@osdl.org +1 -1
#   USB ati_remote.c: don't be a namespace hog
# 
# ChangeSet
#   2004/03/01 17:00:11+01:00 vojtech@suse.cz 
#   Merge bkbits:input into suse.cz:/home/vojtech/bk/input
# 
# drivers/usb/input/hid-core.c
#   2004/03/01 17:00:08+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/char/Kconfig
#   2004/03/01 17:00:08+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# Documentation/kernel-parameters.txt
#   2004/03/01 17:00:08+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/03/01 16:52:22+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/usb/input/hid-core.c
#   2004/03/01 16:52:18+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/char/Kconfig
#   2004/03/01 16:52:18+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# arch/arm26/Kconfig
#   2004/03/01 16:52:18+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# Documentation/kernel-parameters.txt
#   2004/03/01 16:52:18+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/27 17:36:56-08:00 thoffman@arnor.net 
#   [PATCH] USB: update driver for ATI USB/RF remotes
# 
# drivers/usb/input/ati_remote.c
#   2004/02/25 14:06:51-08:00 thoffman@arnor.net +80 -63
#   USB: update driver for ATI USB/RF remotes
# 
# ChangeSet
#   2004/02/27 12:53:52-08:00 greg@kroah.com 
#   [PATCH] USB: fix up the input Makefile after these last few drivers were added.
# 
# drivers/usb/input/Makefile
#   2004/02/27 04:51:51-08:00 greg@kroah.com +4 -4
#   USB: fix up the input Makefile after these last few drivers were added.
# 
# drivers/usb/Makefile
#   2004/02/27 04:51:51-08:00 greg@kroah.com +4 -0
#   USB: fix up the input Makefile after these last few drivers were added.
# 
# ChangeSet
#   2004/02/27 12:53:36-08:00 greg@kroah.com 
#   [PATCH] USB: fix build for older versions of gcc and the mtouchusb driver.
# 
# drivers/usb/input/mtouchusb.c
#   2004/02/27 04:51:48-08:00 greg@kroah.com +1 -1
#   USB: fix build for older versions of gcc and the mtouchusb driver.
# 
# ChangeSet
#   2004/02/27 12:53:21-08:00 tejohnson@yahoo.com 
#   [PATCH] USB: add new USB Touchscreen Driver
#   
#   I have attached a patch which contains a driver and documentation for
#   the MicroTouch (14-206) USB Capacitive Touchscreen controller.  It based
#   on some older code that I have been using for quite some time now (since
#   2.4.17).  This new version has been completely re-written, and now uses
#   Linux Input.  Greg, It would be great to possibly get it into 2.6.4.
#   Please let me know if I have it all wrong...
#   
#   Unfortunately, the X11 mouse driver only seems capable of handling
#   relative data rather than absolute.  Hopefully some one will create a
#   suitable X11 driver capable of accepting absolute data from Linux
#   Input.  If anyone is aware of one, please let me know.  Otherwise, I
#   will most likely begin some work on a patch for GPM.
#   
#   Calibration support will be on the way soon, but I'm not sure of the
#   best way to implement.  Perhaps some abstract functions could come
#   available in evdev which can call vendor specific commands for the
#   calibration within this driver (and perhaps others).
# 
# drivers/usb/input/mtouchusb.c
#   2004/02/26 15:31:35-08:00 tejohnson@yahoo.com +391 -0
#   USB: add new USB Touchscreen Driver
# 
# drivers/usb/input/mtouchusb.c
#   2004/02/26 15:31:35-08:00 tejohnson@yahoo.com +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/drivers/usb/input/mtouchusb.c
# 
# drivers/usb/input/Makefile
#   2004/02/26 15:32:30-08:00 tejohnson@yahoo.com +1 -0
#   USB: add new USB Touchscreen Driver
# 
# drivers/usb/input/Kconfig
#   2004/02/26 15:32:51-08:00 tejohnson@yahoo.com +12 -0
#   USB: add new USB Touchscreen Driver
# 
# drivers/usb/Makefile
#   2004/02/26 15:32:41-08:00 tejohnson@yahoo.com +1 -0
#   USB: add new USB Touchscreen Driver
# 
# Documentation/usb/mtouchusb.txt
#   2004/02/26 15:31:42-08:00 tejohnson@yahoo.com +85 -0
#   USB: add new USB Touchscreen Driver
# 
# Documentation/usb/mtouchusb.txt
#   2004/02/26 15:31:42-08:00 tejohnson@yahoo.com +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/Documentation/usb/mtouchusb.txt
# 
# ChangeSet
#   2004/02/27 12:53:04-08:00 u233@shaw.ca 
#   [PATCH] USB: kbtab.c (Jamstudio Tablet) with optional pressure
#   
#   I have altered kbtab.c a bit in anticipation of an XFree86 4.3 driver
#   that can accept the pressure data (as a third axis) by listening on the
#   event interface.
#   
#   I have set it so that if the option kb_pressure_click is -1 it  reports
#   pressure rather than clicks.
# 
# drivers/usb/input/kbtab.c
#   2004/02/24 01:07:11-08:00 u233@shaw.ca +6 -3
#   USB: kbtab.c (Jamstudio Tablet) with optional pressure
# 
# ChangeSet
#   2004/02/27 12:52:43-08:00 thoffman@arnor.net 
#   [PATCH] USB: add driver for ATI USB/RF remotes
#   
#   I've taken the old GATOS version of the ati_remote driver and done
#   some cleanup/rework of it while porting to 2.6 kernels.
# 
# drivers/usb/input/Makefile
#   2004/02/20 15:46:14-08:00 thoffman@arnor.net +1 -0
#   USB: add driver for ATI USB/RF remotes
# 
# drivers/usb/input/Kconfig
#   2004/02/20 15:48:54-08:00 thoffman@arnor.net +14 -0
#   USB: add driver for ATI USB/RF remotes
# 
# drivers/usb/input/ati_remote.c
#   2004/02/20 15:09:40-08:00 thoffman@arnor.net +834 -0
#   USB: add driver for ATI USB/RF remotes
# 
# drivers/usb/input/ati_remote.c
#   2004/02/20 15:09:40-08:00 thoffman@arnor.net +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/drivers/usb/input/ati_remote.c
# 
# ChangeSet
#   2004/02/27 12:42:07-08:00 greg@kroah.com 
#   USB: delete unneeded scanner documentation.
# 
# BitKeeper/deleted/.del-scanner.txt~180f704d4900732
#   2004/02/27 12:41:50-08:00 greg@kroah.com +0 -0
#   Delete: Documentation/usb/scanner.txt
# 
# ChangeSet
#   2004/02/27 12:12:45-08:00 david-b@pacbell.net 
#   [PATCH] USB: EHCI and full-speed ISO-OUT
#   
#   This is a minor update to the patch I sent out about a week ago.
#   The key change is to use the I/O watchdog while doing ISO streaming.
#   Bernd Porr reports that a VT8235 system needs that; it seems like
#   IDE activity can interfere with the delivery of USB IRQs.
#   
#   
#   EHCI periodic scheduling updates.
#   
#    - Initial version of full speed ISO transaction support.  This
#      should handle OUT transactions, such as those for usb speakers.
#      For now, it's controlled using an EXPERIMENTAL config option:
#   
#      * I've run into interesting differences in how different USB 2.0
#        hub silicon (the transaction translators) handle some older
#        audio devices.  Needs more investigation.
#   
#      * Interrupt transfer scheduling doesn't yet cope well with schedules
#        where every slot already has activity.  For now, don't plug in
#        devices like hubs, mice, or keyboards while EHCI is streaming.
#   
#    - Protect freelist for highspeed ITDs, using spinlock.  Could be
#      an issue for some drivers.
#   
#    - Kick in the I/O watchdog timer (5 msec) for periodic transfers.
#      In this case, IDE activity on a VT8235 lost the IRQs which should
#      have kept the ISO stream active.  Queues shorter than 5 msec are
#      not going to work on all USB hosts.
#   
#    - Simplified the ISO scheduler:  doesn't attempt to re-schedule
#      after lossage, or to short-circuit scanning.  (Rescheduling will
#      probably come back later ... for now, the "hard" error here is
#      highlighting problems that need attention.)
# 
# drivers/usb/host/ehci.h
#   2004/02/27 00:46:23-08:00 david-b@pacbell.net +6 -8
#   USB: EHCI and full-speed ISO-OUT
# 
# drivers/usb/host/ehci-sched.c
#   2004/02/27 00:46:23-08:00 david-b@pacbell.net +446 -77
#   USB: EHCI and full-speed ISO-OUT
# 
# drivers/usb/host/ehci-hcd.c
#   2004/02/27 00:46:23-08:00 david-b@pacbell.net +1 -7
#   USB: EHCI and full-speed ISO-OUT
# 
# drivers/usb/host/ehci-dbg.c
#   2004/02/27 00:46:23-08:00 david-b@pacbell.net +5 -1
#   USB: EHCI and full-speed ISO-OUT
# 
# drivers/usb/host/Kconfig
#   2004/02/27 00:46:23-08:00 david-b@pacbell.net +9 -0
#   USB: EHCI and full-speed ISO-OUT
# 
# ChangeSet
#   2004/02/27 12:12:28-08:00 david-b@pacbell.net 
#   [PATCH] USB Gadget: gadget config buffer utilities
#   
#   Adds two new gadget-side utility functions, to support a declarative
#   style of managing usb configuration descriptors.  The functions fill
#   buffers from null-terminated vectors of usb descriptors, which are
#   simple to build or update.
#   
#   The "ethernet" gadget driver currently has the most interesting config
#   descriptors.  This uses those functions to replace some complex code with
#   simpler static declarations; result, it's cleaner.  (And it'll be easier
#   to add RNDIS configurations later, too.)
#   
#   Memory savings (or cost, depending on config) was less than 50 bytes;
#   nothing worth worrying about.
# 
# drivers/usb/gadget/config.c
#   2004/02/23 22:51:29-08:00 david-b@pacbell.net +116 -0
#   USB Gadget: gadget config buffer utilities
# 
# include/linux/usb_gadget.h
#   2004/02/23 15:43:48-08:00 david-b@pacbell.net +11 -0
#   USB Gadget: gadget config buffer utilities
# 
# drivers/usb/gadget/ether.c
#   2004/02/23 15:43:48-08:00 david-b@pacbell.net +51 -74
#   USB Gadget: gadget config buffer utilities
# 
# drivers/usb/gadget/config.c
#   2004/02/23 22:51:29-08:00 david-b@pacbell.net +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/drivers/usb/gadget/config.c
# 
# drivers/usb/gadget/Makefile
#   2004/02/23 15:43:48-08:00 david-b@pacbell.net +1 -1
#   USB Gadget: gadget config buffer utilities
# 
# Documentation/DocBook/gadget.tmpl
#   2004/02/24 00:18:48-08:00 david-b@pacbell.net +1 -0
#   USB Gadget: gadget config buffer utilities
# 
# ChangeSet
#   2004/02/27 12:12:12-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet learns about Zaurus C-860
#   
#   New Zaurus ID, from Sven Trampel <Sven.Trampel@surf-club.de>
# 
# drivers/usb/net/usbnet.c
#   2004/02/26 10:37:44-08:00 david-b@pacbell.net +9 -0
#   USB: usbnet learns about Zaurus C-860
# 
# ChangeSet
#   2004/02/27 12:11:54-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB Storage: Remove Minolta Dimage 7i from unusual_devs.h
#   
#   On Fri, 27 Feb 2004, Lenar Lõhmus wrote:
#   
#   > Hi,
#   >
#   > Got this:
#   >
#   > usb 3-1: new full speed USB device using address 3
#   > usb-storage: This device (0686,400b,0001 S 06 P 50) has an unneeded SubClass entry in unusual_devs.h
#   > Please send a copy of this message to <linux-usb-devel@lists.sourceforge.net>
#   
#   Well, Martin Pool notwithstanding (see
#   
#   http://marc.theaimsgroup.com/?l=linux-usb-devel&m=107642806303815&w=2
#   
#   ), it sure looks like this doesn't need an unusual_devs.h entry.
#   
#   Greg, please apply this patch.
# 
# drivers/usb/storage/unusual_devs.h
#   2004/02/27 01:51:43-08:00 stern@rowland.harvard.edu +0 -6
#   USB Storage: Remove Minolta Dimage 7i from unusual_devs.h
# 
# ChangeSet
#   2004/02/27 12:11:31-08:00 jeffm@suse.com 
#   [PATCH] USB: Fix for kl5kusb105 driver
#   
#   I tried using the kl5kusb105 driver for a 3Com PalmConnect USB device I
#   had lying around.
#   
#   It oopses during device detection. There is a nested loop using the same
#   loop counter as the outer loop - causing the code after the nested loop
#   is first executed to have an invalid counter. The counter is then used
#   as an array index, causing a NULL deref.
#   
#   Fix attached.
# 
# drivers/usb/serial/kl5kusb105.c
#   2004/02/19 14:17:34-08:00 jeffm@suse.com +3 -2
#   USB: Fix for kl5kusb105 driver
# 
# ChangeSet
#   2004/02/27 12:11:07-08:00 michal_dobrzynski@mac.com 
#   [PATCH] USB: add IRTrans support to ftdi_sio driver
# 
# drivers/usb/serial/ftdi_sio.h
#   2004/02/23 04:14:03-08:00 michal_dobrzynski@mac.com +2 -0
#   USB: add IRTrans support to ftdi_sio driver
# 
# drivers/usb/serial/ftdi_sio.c
#   2004/02/23 04:14:03-08:00 michal_dobrzynski@mac.com +3 -0
#   USB: add IRTrans support to ftdi_sio driver
# 
# ChangeSet
#   2004/02/26 14:19:13-08:00 greg@kroah.com 
#   [PATCH] USB Storage: remove unneeded debug message
#   
#   Nothing in life is assured...
# 
# drivers/usb/storage/usb.c
#   2004/02/26 06:17:07-08:00 greg@kroah.com +0 -2
#   USB Storage: remove unneeded debug message
# 
# ChangeSet
#   2004/02/26 14:18:57-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: tighten sense-clearing code
#   
#   This patch tightens up the conditions under which an auto-sense will be
#   cleared.  It also fixes the comment associated with the code.
# 
# drivers/usb/storage/transport.c
#   2004/02/21 16:21:34-08:00 mdharm-usb@one-eyed-alien.net +7 -3
#   USB Storage: tighten sense-clearing code
# 
# ChangeSet
#   2004/02/26 14:18:38-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: Remove unneeded macro
#   
#   This one-liner removes an unneeded macro.
# 
# drivers/usb/storage/usb.h
#   2004/02/21 16:21:42-08:00 mdharm-usb@one-eyed-alien.net +0 -1
#   USB Storage: Remove unneeded macro
# 
# ChangeSet
#   2004/02/26 14:18:20-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: Fix for Fuji Finepix 1400
#   
#   This patch changes some error checking so that some bogus devices (like the
#   Fuji Finepix 1400) will work.
#   
#   This is basically relaxing a test on a field that the spec says "should
#   always be zero"
# 
# drivers/usb/storage/transport.c
#   2004/02/21 16:21:51-08:00 mdharm-usb@one-eyed-alien.net +8 -4
#   USB Storage: Fix for Fuji Finepix 1400
# 
# ChangeSet
#   2004/02/26 14:17:58-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: DSC-T1 unusual_devs.h entry
#   
#   Our friends at sony are at it again.  The DSC-T1 needs a new entry.  Note
#   that it's the same VID & PID as the last entry, but different version.
# 
# drivers/usb/storage/unusual_devs.h
#   2004/02/21 16:21:59-08:00 mdharm-usb@one-eyed-alien.net +8 -0
#   USB Storage: DSC-T1 unusual_devs.h entry
# 
# ChangeSet
#   2004/02/26 14:09:37-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Use list_splice instead of looping over list elements
#   
#   This patch is from Stephen Hemminger.  I modified it slightly to place the
#   new elements at the end of the complete_list instead of at the front.
#   
#   On Tue, 24 Feb 2004, Stephen Hemminger wrote:
#   
#   > Since the remove_list and complete_list now use the same element for
#   > linking, it is possible to use the list_splice inline to avoid
#   > having to loop over all the urb's
# 
# drivers/usb/host/uhci-hcd.c
#   2004/02/26 04:13:44-08:00 stern@rowland.harvard.edu +4 -9
#   USB: Use list_splice instead of looping over list elements
# 
# ChangeSet
#   2004/02/26 14:09:18-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Remove name obfuscation in UHCI
#   
#   On Mon, 23 Feb 2004, Stephen Hemminger wrote:
#   > Bulk and interrupt urb's share common irq processing, why does the
#   > code try to obfuscate it?
#   
#   Quite right; this is needless complexity.  (But note you left in a couple
#   of lines that should have been deleted.)
# 
# drivers/usb/host/uhci-hcd.c
#   2004/02/24 02:15:52-08:00 stern@rowland.harvard.edu +2 -10
#   USB: Remove name obfuscation in UHCI
# 
# ChangeSet
#   2004/02/26 14:09:03-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Return better result codes in UHCI
#   
#   This patch changes the result code returned by the UHCI driver for a
#   certain class of errors.  Under a number of circumstances a USB device is
#   obliged to send a response packet within a fairly short turn-around time,
#   typically 1 - 10 microseconds depending on the bus speed.  Failure to do
#   so is a protocol error and should be reported as such, not as a timeout,
#   which is really a higher-level concept.  I believe the EHCI driver already
#   does this.
#   
#   I trust nobody will object to the update this patch adds to
#   Documentation/usb/error-codes.txt, making this more explicit.
#   
#   In a vaguely related change, the patch corrects the terminology in a few
#   comments.  The parts of a control transfer are called "stages", not
#   "phases".
# 
# drivers/usb/host/uhci-hcd.h
#   2004/02/23 02:40:16-08:00 stern@rowland.harvard.edu +1 -1
#   USB: Return better result codes in UHCI
# 
# drivers/usb/host/uhci-hcd.c
#   2004/02/23 03:01:45-08:00 stern@rowland.harvard.edu +14 -15
#   USB: Return better result codes in UHCI
# 
# Documentation/usb/error-codes.txt
#   2004/02/23 03:06:03-08:00 stern@rowland.harvard.edu +3 -1
#   USB: Return better result codes in UHCI
# 
# ChangeSet
#   2004/02/26 14:08:39-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Enable interrupts in UHCI after PM resume
#   
#   On Mon, 23 Feb 2004, Chip Salzenberg wrote:
#   
#   > It works ... perfectly!  I can now suspend and resume my A30 with
#   > impunity, and the USB keyboard works fine after each resume.
#   >
#   > Thanks much, Alan.
#   >
#   > (Now if I could just get the alsa guys to fix snd-intel8x0...)
#   
#   This patch re-initializes the UHCI Interrupt Enable register following a
#   PM resume.  Apparently some systems clear the register during suspend,
#   which causes obvious problems later on.
# 
# drivers/usb/host/uhci-hcd.c
#   2004/02/22 07:23:59-08:00 stern@rowland.harvard.edu +9 -2
#   USB: Enable interrupts in UHCI after PM resume
# 
# ChangeSet
#   2004/02/26 14:08:22-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix a bug in the UHCI dequeueing code
#   
#   On Mon, 23 Feb 2004, Stephen Hemminger wrote:
#   
#   > Great, the kernel with this patch ran successfully all weekend.  Looks like no
#   > more races in the unlink path.
#   
#   Wonderful.  Thanks a lot for all your SMP testing, it's been a big help.
#   
#   
#   This patch corrects an error in the dequeueing code for UHCI.  Improper
#   locking caused it to hang in the oddball case where an URB was unlinked
#   even before it had been queued.
# 
# drivers/usb/host/uhci-hcd.c
#   2004/02/20 07:04:41-08:00 stern@rowland.harvard.edu +8 -8
#   USB: Fix a bug in the UHCI dequeueing code
# 
# ChangeSet
#   2004/02/26 14:08:02-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB Storage: update unusual_devs.h comments
#   
#   On Tue, 24 Feb 2004, Matthew Dharm wrote:
#   
#   > We should also put a comment into the unusual_devs.h file to make sure
#   > nobody tries to remove the protocol override in the future.
#   
#   How about this?
# 
# drivers/usb/storage/unusual_devs.h
#   2004/02/26 03:48:03-08:00 stern@rowland.harvard.edu +3 -0
#   USB Storage: update unusual_devs.h comments
# 
# ChangeSet
#   2004/02/26 14:07:42-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB Storage: unusual_devs.h update
#   
#   On Thu, 19 Feb 2004, Evan Felix wrote:
#   
#   > I plugged a Cyclades AlterPath BIO USb device into my linux 2.6.2 laptop
#   > and it asked me to send you this:
#   >
#   >
#   > hub 1-1.2:1.0: new USB device on port 3, assigned address 6
#   > hub 1-1.2.3:1.0: USB hub found
#   > hub 1-1.2.3:1.0: 4 ports detected
#   > hub 1-1.2.3:1.0: new USB device on port 1, assigned address 7
#   > hub 1-1.2.3:1.0: new USB device on port 2, assigned address 8
#   > Initializing USB Mass Storage driver...
#   > usb-storage: This device (05dc,0001,0001 S 06 P 50) has an unneeded
#   > SubClass entry in unusual_devs.h
#   >    Please send a copy of this message to
#   > <linux-usb-devel@lists.sourceforge.net>
#   > scsi0 : SCSI emulation for USB Mass Storage devices
#   >   Vendor: Lexar     Model: Jumpshot USB CF   Rev: 0001
#   >   Type:   Direct-Access                      ANSI SCSI revision: 02
#   
#   Thank you for sending this.  Greg, here's the patch.
# 
# drivers/usb/storage/unusual_devs.h
#   2004/02/20 06:19:45-08:00 stern@rowland.harvard.edu +1 -1
#   USB Storage: unusual_devs.h update
# 
# ChangeSet
#   2004/02/19 22:24:53+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/char/Kconfig
#   2004/02/19 22:24:48+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# Documentation/kernel-parameters.txt
#   2004/02/19 22:24:48+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/17 21:05:09+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/usb/input/hid-core.c
#   2004/02/17 21:04:55+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/09 15:17:33+01:00 vojtech@suse.cz 
#   Merge bkbits:input into suse.cz:/home/vojtech/bk/input
# 
# drivers/char/Kconfig
#   2004/02/09 15:17:29+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/09 10:07:39+01:00 vojtech@suse.cz 
#   input: Re-add a loop to set the old scancode bit in device key bitmap.
# 
# drivers/input/evdev.c
#   2004/02/09 10:07:32+01:00 vojtech@suse.cz +4 -1
#   input: Re-add a loop to set the old scancode bit in device key bitmap.
# 
# ChangeSet
#   2004/02/09 09:54:13+01:00 vojtech@suse.cz 
#   Manual merge.
# 
# drivers/char/keyboard.c
#   2004/02/09 09:54:07+01:00 vojtech@suse.cz +0 -1
#   Manual merge.
# 
# drivers/input/serio/i8042.c
#   2004/02/09 09:49:42+01:00 vojtech@suse.cz +0 -3
#   Auto merged
# 
# ChangeSet
#   2004/02/09 02:11:00+01:00 weicht@in.tum.de 
#   input: Fix a bug introduced by Andrew Morton's gcc3.2 fixes.
# 
# drivers/char/keyboard.c
#   2004/02/09 02:10:54+01:00 weicht@in.tum.de +1 -1
#   input: Fix a bug introduced by Andrew Morton's gcc3.2 fixes.
# 
# ChangeSet
#   2004/02/09 02:10:02+01:00 vojtech@suse.cz 
#   input: Fix a warning in i8042.c
# 
# drivers/input/serio/i8042.c
#   2004/02/09 02:09:55+01:00 vojtech@suse.cz +1 -1
#   input: Fix a warning in i8042.c
# 
# ChangeSet
#   2004/02/09 01:47:16+01:00 vojtech@suse.cz 
#   input: Fix "psmouse: Lost sync" problem. It was really losing sync.
# 
# drivers/input/serio/i8042.c
#   2004/02/09 01:47:09+01:00 vojtech@suse.cz +4 -2
#   input: Fix "psmouse: Lost sync" problem. It was really losing sync.
# 
# ChangeSet
#   2004/02/08 23:21:45+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/char/Makefile
#   2004/02/08 23:21:29+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/char/Kconfig
#   2004/02/08 23:21:29+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/05 10:21:19+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/char/Kconfig
#   2004/02/05 10:21:15+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/03 21:41:26+01:00 vojtech@suse.cz 
#   Merge bkbits:input into suse.cz:/home/vojtech/bk/input
# 
# Documentation/kernel-parameters.txt
#   2004/02/03 21:41:23+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/03 21:38:35+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# Documentation/kernel-parameters.txt
#   2004/02/03 21:38:32+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/01 11:58:02+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# Documentation/kernel-parameters.txt
#   2004/02/01 11:57:59+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/01/27 21:01:27+01:00 aris@cathedrallabs.org 
#   input: Remove the obsolete "busmouse.c" helper driver.
# 
# include/linux/miscdevice.h
#   2004/01/27 21:01:20+01:00 aris@cathedrallabs.org +0 -1
#   input: Remove the obsolete "busmouse.c" helper driver.
# 
# drivers/char/Makefile
#   2004/01/27 21:01:20+01:00 aris@cathedrallabs.org +0 -1
#   input: Remove the obsolete "busmouse.c" helper driver.
# 
# drivers/char/Kconfig
#   2004/01/27 21:01:20+01:00 aris@cathedrallabs.org +0 -24
#   input: Remove the obsolete "busmouse.c" helper driver.
# 
# arch/arm26/Kconfig
#   2004/01/27 21:01:20+01:00 aris@cathedrallabs.org +0 -5
#   input: Remove the obsolete "busmouse.c" helper driver.
# 
# ChangeSet
#   2004/01/26 18:35:00+01:00 panagiotis.issaris@mech.kuleuven.ac.be 
#   input: Credit to Panagiotis Issaris for Graphire 3 support.
# 
# drivers/usb/input/wacom.c
#   2004/01/26 18:34:54+01:00 panagiotis.issaris@mech.kuleuven.ac.be +3 -1
#   input: Credit to Panagiotis Issaris for Graphire 3 support.
# 
# ChangeSet
#   2004/01/26 13:59:12+01:00 deller@gmx.de 
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# drivers/input/serio/gscps2.c
#   2004/01/26 13:59:06+01:00 deller@gmx.de +470 -0
# 
# drivers/input/serio/gscps2.c
#   2004/01/26 13:59:06+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/serio/gscps2.c
# 
# drivers/input/serio/Makefile
#   2004/01/26 13:59:06+01:00 deller@gmx.de +1 -0
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# drivers/input/serio/Kconfig
#   2004/01/26 13:59:06+01:00 deller@gmx.de +16 -0
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# drivers/input/mouse/Kconfig
#   2004/01/26 13:59:06+01:00 deller@gmx.de +1 -0
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# drivers/input/misc/Makefile
#   2004/01/26 13:59:06+01:00 deller@gmx.de +0 -1
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# drivers/input/misc/Kconfig
#   2004/01/26 13:59:06+01:00 deller@gmx.de +0 -9
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# drivers/input/keyboard/hpps2atkbd.h
#   2004/01/26 13:59:06+01:00 deller@gmx.de +93 -85
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# drivers/input/keyboard/Kconfig
#   2004/01/26 13:59:06+01:00 deller@gmx.de +1 -0
#   input: Convert HP/PARISC Lasi/Dino PS/2 keyboard/mouse driver
#          from an input driver to a serio driver.
# 
# BitKeeper/deleted/.del-gsc_ps2.c~196a1c58604c6cc1
#   2004/01/26 13:58:06+01:00 vojtech@suse.cz +0 -0
#   Delete: drivers/input/misc/gsc_ps2.c
# 
# ChangeSet
#   2004/01/26 13:57:19+01:00 vojtech@suse.cz 
#   input: Create an extra option for enabling IBM RapidAccess keyboard
#          special features (atkbd.extra), instead of abusing the
#          atkbd.set option for this.
# 
# drivers/input/keyboard/atkbd.c
#   2004/01/26 13:57:13+01:00 vojtech@suse.cz +20 -15
#   input: Create an extra option for enabling IBM RapidAccess keyboard
#          special features (atkbd.extra), instead of abusing the
#          atkbd.set option for this.
# 
# Documentation/kernel-parameters.txt
#   2004/01/26 13:57:13+01:00 vojtech@suse.cz +10 -3
#   input: Create an extra option for enabling IBM RapidAccess keyboard
#          special features (atkbd.extra), instead of abusing the
#          atkbd.set option for this.
# 
# ChangeSet
#   2004/01/26 13:56:47+01:00 vojtech@suse.cz 
#   input: Add support for scroll wheel on MS Office and similar keyboards.
# 
# drivers/input/keyboard/atkbd.c
#   2004/01/26 13:56:40+01:00 vojtech@suse.cz +58 -7
#   input: Add support for scroll wheel on MS Office and similar keyboards.
# 
# ChangeSet
#   2004/01/26 13:29:36+01:00 vojtech@suse.cz 
#   input: Bail out in atkbd.c if scancode set is changed, don't
#          reinitialize scancode map. This is even more anoying than
#          a new keyboard device in the unlikely case of set change.
# 
# drivers/input/keyboard/atkbd.c
#   2004/01/26 13:29:30+01:00 vojtech@suse.cz +6 -32
#   input: Bail out in atkbd.c if scancode set is changed, don't
#          reinitialize scancode map. This is even more anoying than
#          a new keyboard device in the unlikely case of set change.
# 
# ChangeSet
#   2004/01/26 13:25:57+01:00 sebek64@post.cz 
#   input: Use request_region() instead of check_region() in ns558.c
#          it's both safer and correct.
# 
# drivers/input/gameport/ns558.c
#   2004/01/26 13:25:50+01:00 sebek64@post.cz +24 -11
#   input: Use request_region() instead of check_region() in ns558.c
#          it's both safer and correct.
# 
# ChangeSet
#   2004/01/26 13:25:24+01:00 vojtech@suse.cz 
#   input: Fix sunkbd.c to work with serport. Must sleep.
# 
# drivers/input/keyboard/sunkbd.c
#   2004/01/26 13:25:18+01:00 vojtech@suse.cz +11 -11
#   input: Fix sunkbd.c to work with serport. Must sleep.
# 
# ChangeSet
#   2004/01/26 13:23:40+01:00 jochen@jochen.org 
#   usb: Minor documentation fix reflecting new USB module names in acm.txt
# 
# Documentation/usb/acm.txt
#   2004/01/26 13:23:33+01:00 jochen@jochen.org +4 -4
#   usb: Minor documentation fix reflecting new USB module names in acm.txt
# 
# ChangeSet
#   2004/01/26 13:18:17+01:00 vojtech@suse.cz 
#   input: Add support for another a4tech 2-wheel USB mouse, with
#          a Cypress ID this time. Also rearrange the HID blacklist
#          a bit - it has grown too long.
# 
# drivers/usb/input/hid-input.c
#   2004/01/26 13:18:11+01:00 vojtech@suse.cz +4 -3
#   input: Add support for another a4tech 2-wheel USB mouse, with
#          a Cypress ID this time. Also rearrange the HID blacklist
#          a bit - it has grown too long.
# 
# drivers/usb/input/hid-core.c
#   2004/01/26 13:18:11+01:00 vojtech@suse.cz +29 -19
#   input: Add support for another a4tech 2-wheel USB mouse, with
#          a Cypress ID this time. Also rearrange the HID blacklist
#          a bit - it has grown too long.
# 
# ChangeSet
#   2004/01/26 13:17:44+01:00 vojtech@suse.cz 
#   input: It looks like the Saitek RumblePad needs a BADPAD entry.
# 
# drivers/usb/input/hid-core.c
#   2004/01/26 13:17:38+01:00 vojtech@suse.cz +4 -0
#   input: It looks like the Saitek RumblePad needs a BADPAD entry.
# 
# ChangeSet
#   2004/01/26 13:16:54+01:00 jamesl@appliedminds.com 
#   input: Add a new ioctl to hiddev, which allows multiple usages to
#          be set in a single request. Also fixes sizes of fields
#          in hiddev structs to use _uXX types.
# 
# include/linux/hiddev.h
#   2004/01/26 13:16:48+01:00 jamesl@appliedminds.com +43 -31
#   input: Add a new ioctl to hiddev, which allows multiple usages to
#          be set in a single request. Also fixes sizes of fields
#          in hiddev structs to use _uXX types.
# 
# drivers/usb/input/hiddev.c
#   2004/01/26 13:16:48+01:00 jamesl@appliedminds.com +55 -24
#   input: Add a new ioctl to hiddev, which allows multiple usages to
#          be set in a single request. Also fixes sizes of fields
#          in hiddev structs to use _uXX types.
# 
# ChangeSet
#   2004/01/26 13:15:32+01:00 jamesl@appliedminds.com 
#   input: Fix hid-core for devices that have less usages than values
#          in a hid report. We could iterate beyond the end of array of
#          usages before.
# 
# drivers/usb/input/hid-core.c
#   2004/01/26 13:13:50+01:00 jamesl@appliedminds.com +9 -2
#   input: Fix hid-core for devices that have less usages than values
#          in a hid report. We could iterate beyond the end of array of
#          usages before.
# 
diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Wed Mar 17 19:29:09 2004
+++ b/CREDITS	Wed Mar 17 19:29:09 2004
@@ -82,13 +82,13 @@
 S: USA
 
 N: Erik Andersen
-E: andersee@debian.org
-W: http://www.xmission.com/~andersen
-P: 1024/FC4CFFED 78 3C 6A 19 FA 5D 92 5A  FB AC 7B A5 A5 E1 FF 8E
+E: andersen@codepoet.org
+W: http://www.codepoet.org/
+P: 1024D/30D39057 1BC4 2742 E885 E4DE 9301  0C82 5F9B 643E 30D3 9057
 D: Maintainer of ide-cd and Uniform CD-ROM driver, 
 D: ATAPI CD-Changer support, Major 2.1.x CD-ROM update.
-S: 4538 South Carnegie Tech Street
-S: Salt Lake City, Utah 84120
+S: 352 North 525 East
+S: Springville, Utah 84663
 S: USA
 
 N: Michael Ang
@@ -673,11 +673,6 @@
 S: NN1 3QT
 S: United Kingdom
 
-N: Stephane Dalton
-E: sdalton@videotron.ca
-D: Tieman Voyager USB Braille display driver.
-S: Québec, Canada
-
 N: Uwe Dannowski
 E: Uwe.Dannowski@ira.uka.de
 W: http://i30www.ira.uka.de/~dannowsk/
@@ -796,11 +791,6 @@
 E: cort@fsmlabs.com
 W: http://www.fsmlabs.com/linuxppcbk.html
 D: PowerPC
-
-N: Stéphane Doyon
-E: s.doyon@videotron.ca
-D: Tieman Voyager USB Braille display driver.
-S: Québec, Canada
 
 N: Oleg Drokin
 E: green@ccssu.crimea.ua
diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
--- a/Documentation/DocBook/Makefile	Wed Mar 17 19:29:09 2004
+++ b/Documentation/DocBook/Makefile	Wed Mar 17 19:29:09 2004
@@ -47,7 +47,7 @@
 ###
 #External programs used
 KERNELDOC = scripts/kernel-doc
-DOCPROC   = scripts/docproc
+DOCPROC   = scripts/basic/docproc
 SPLITMAN  = $(PERL) $(srctree)/scripts/split-man
 MAKEMAN   = $(PERL) $(srctree)/scripts/makeman
 
@@ -149,12 +149,18 @@
       cmd_fig2eps = fig2dev -Leps $< $@
 
 %.eps: %.fig
+	@(which fig2dev > /dev/null 2>&1) || \
+	 (echo "*** You need to install transfig ***"; \
+	  exit 1)
 	$(call cmd,fig2eps)
 
 quiet_cmd_fig2png = FIG2PNG $@
       cmd_fig2png = fig2dev -Lpng $< $@
 
 %.png: %.fig
+	@(which fig2dev > /dev/null 2>&1) || \
+	 (echo "*** You need to install transfig ***"; \
+	  exit 1)
 	$(call cmd,fig2png)
 
 ###
diff -Nru a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
--- a/Documentation/DocBook/gadget.tmpl	Wed Mar 17 19:29:09 2004
+++ b/Documentation/DocBook/gadget.tmpl	Wed Mar 17 19:29:09 2004
@@ -454,6 +454,7 @@
 </para>
 
 !Edrivers/usb/gadget/usbstring.c
+!Edrivers/usb/gadget/config.c
 </sect1>
 
 </chapter>
diff -Nru a/Documentation/DocBook/parportbook.tmpl b/Documentation/DocBook/parportbook.tmpl
--- a/Documentation/DocBook/parportbook.tmpl	Wed Mar 17 19:29:09 2004
+++ b/Documentation/DocBook/parportbook.tmpl	Wed Mar 17 19:29:09 2004
@@ -2730,7 +2730,7 @@
 
 </book>
 <!-- Additional function to be documented:
-!Ddrivers/parport/init.c
+--! Ddrivers/parport/init.c (this file doesn't exist any more)
 -->
 <!-- Local Variables: -->
 <!-- sgml-indent-step: 1 -->
diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt
--- a/Documentation/devices.txt	Wed Mar 17 19:29:09 2004
+++ b/Documentation/devices.txt	Wed Mar 17 19:29:09 2004
@@ -1,8 +1,9 @@
 
 		       LINUX ALLOCATED DEVICES
-	     Maintained by H. Peter Anvin <device@lanana.org>
 
-		      Last revised: 3 June 2001
+	     Maintained by John Cagle <device@lanana.org>
+
+		      Last revised: 15 March 2004
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
@@ -85,6 +86,7 @@
 
   0		Unnamed devices (e.g. non-device mounts)
 		  0 = reserved as null device number
+		See block major 144, 145, 146 for expansion areas.
 
   1 char	Memory devices
 		  1 = /dev/mem		Physical memory access
@@ -98,7 +100,7 @@
 		  9 = /dev/urandom	Faster, less secure random number gen.
 		 10 = /dev/aio		Asyncronous I/O notification interface
 		 11 = /dev/kmsg		Writes to this come out as printk's
-    block	RAM disk
+  1 block	RAM disk
 		  0 = /dev/ram0		First RAM disk
 		  1 = /dev/ram1		Second RAM disk
 		    ...
@@ -127,7 +129,7 @@
 		master multiplex (/dev/ptmx) to acquire a PTY on
 		demand.
   
-    block	Floppy disks
+  2 block	Floppy disks
 		  0 = /dev/fd0		Controller 0, drive 0, autodetect
 		  1 = /dev/fd1		Controller 0, drive 1, autodetect
 		  2 = /dev/fd2		Controller 0, drive 2, autodetect
@@ -193,7 +195,7 @@
 		These are the old-style (BSD) PTY devices; Unix98
 		devices are on major 136 and above.
 
-    block	First MFM, RLL and IDE hard disk/CD-ROM interface
+  3 block	First MFM, RLL and IDE hard disk/CD-ROM interface
 		  0 = /dev/hda		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdb		Slave: whole disk (or CD-ROM)
 
@@ -225,6 +227,12 @@
 		number for BSD PTY devices.  As of Linux 2.1.115, this
 		is no longer supported.	 Use major numbers 2 and 3.
 
+  4 block	Aliases for dynamically allocated major devices to be used
+		when its not possible to create the real device nodes
+		because the root filesystem is mounted read-only.
+
+                  0 = /dev/root
+
   5 char	Alternate TTY devices
 		  0 = /dev/tty		Current TTY device
 		  1 = /dev/console	System console
@@ -258,7 +266,7 @@
 	
 		NOTE: These devices permit both read and write access.
 
-    block	Loopback devices
+  7 block	Loopback devices
 		  0 = /dev/loop0	First loopback device
 		  1 = /dev/loop1	Second loopback device
 		    ...
@@ -309,7 +317,7 @@
 		ioctl()'s can be used to rewind the tape regardless of
 		the device used to access it.
 
-    block	Metadisk (RAID) devices
+  9 block	Metadisk (RAID) devices
 		  0 = /dev/md0		First metadisk group
 		  1 = /dev/md1		Second metadisk group
 		    ...
@@ -355,6 +363,7 @@
 		149 = /dev/input/mouse	Linux/SGI Irix emulation mouse
 		150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard
 		151 = /dev/led		Front panel LEDs
+		152 = /dev/kpoll	Kernel Poll Driver
 		153 = /dev/mergemem	Memory merge device
 		154 = /dev/pmu		Macintosh PowerBook power manager
 		155 = /dev/isictl	MultiTech ISICom serial control
@@ -372,7 +381,7 @@
 		167 = /dev/specialix_sxctl Specialix serial control
 		168 = /dev/tcldrv	Technology Concepts serial control
 		169 = /dev/specialix_rioctl Specialix RIO serial control
-		170 = /dev/smapi	IBM Thinkpad SMAPI
+		170 = /dev/thinkpad/thinkpad	IBM Thinkpad devices
 		171 = /dev/srripc	QNX4 API IPC manager
 		172 = /dev/usemaclone	Semaphore clone device
 		173 = /dev/ipmikcs	Intelligent Platform Management
@@ -385,7 +394,7 @@
 		180 = /dev/vrbuttons	Vr41xx button input device
 		181 = /dev/toshiba	Toshiba laptop SMM support
 		182 = /dev/perfctr	Performance-monitoring counters
-		183 = /dev/intel_rng	Intel i8x0 random number generator
+		183 = /dev/hwrng	Generic random number generator
 		184 = /dev/cpu/microcode CPU microcode update interface
 		186 = /dev/atomicps	Atomic shapshot of process state data
 		187 = /dev/irnet	IrNET device
@@ -421,20 +430,27 @@
 		221 = /dev/mvista/hssdsi	Montavista PICMG hot swap system driver
 		222 = /dev/mvista/hasi		Montavista PICMG high availability
 		223 = /dev/input/uinput		User level driver support for input
-		240-255			Reserved for local use
+		224 = /dev/tpm		TCPA TPM driver
+		225 = /dev/pps		Pulse Per Second driver
+		226 = /dev/systrace	Systrace device
+		227 = /dev/mcelog	X86_64 Machine Check Exception driver
+		240-254			Reserved for local use
+		255			Reserved for MISC_DYNAMIC_MINOR
 
- 11 char	Raw keyboard device
+ 11 char	Raw keyboard device	(Linux/SPARC only)
 		  0 = /dev/kbd		Raw keyboard device
 
-		The raw keyboard device is used on Linux/SPARC only.
+ 11 char	Serial Mux device	(Linux/PA-RISC only)
+		  0 = /dev/ttyB0	First mux port
+		  1 = /dev/ttyB1	Second mux port
+		    ...
 
-    block	SCSI CD-ROM devices
-		  0 = /dev/sr0		First SCSI CD-ROM
-		  1 = /dev/sr1		Second SCSI CD-ROM
+ 11 block	SCSI CD-ROM devices
+		  0 = /dev/scd0		First SCSI CD-ROM
+		  1 = /dev/scd1		Second SCSI CD-ROM
 		    ...
 
-		The prefix /dev/scd instead of /dev/sr has been used
-		as well, and might make more sense.
+		The prefix /dev/sr (instead of /dev/scd) has been deprecated.
 
  12 char	QIC-02 tape
 		  2 = /dev/ntpqic11	QIC-11, no rewind-on-close
@@ -449,7 +465,7 @@
 		The device names specified are proposed -- if there
 		are "standard" names for these devices, please let me know.
 
-    block	MSCDEX CD-ROM callback support {2.6}
+ 12 block	MSCDEX CD-ROM callback support {2.6}
 		  0 = /dev/dos_cd0	First MSCDEX CD-ROM
 		  1 = /dev/dos_cd1	Second MSCDEX CD-ROM
 		    ...
@@ -468,7 +484,7 @@
 
 		Each device type has 5 bits (32 minors).
 
-    block	8-bit MFM/RLL/IDE controller
+ 13 block	8-bit MFM/RLL/IDE controller
 		  0 = /dev/xda		First XT disk whole disk
 		 64 = /dev/xdb		Second XT disk whole disk
 
@@ -492,7 +508,7 @@
 		 33 = /dev/patmgr1	Sequencer patch manager
 		 34 = /dev/midi02	Third MIDI port
 		 50 = /dev/midi03	Fourth MIDI port
-    block	BIOS harddrive callback support {2.6}
+ 14 block	BIOS harddrive callback support {2.6}
 		  0 = /dev/dos_hda	First BIOS harddrive whole disk
 		 64 = /dev/dos_hdb	Second BIOS harddrive whole disk
 		128 = /dev/dos_hdc	Third BIOS harddrive whole disk
@@ -508,33 +524,33 @@
 		128 = /dev/djs0		First digital joystick
 		129 = /dev/djs1		Second digital joystick
 		    ...
-    block	Sony CDU-31A/CDU-33A CD-ROM
+ 15 block	Sony CDU-31A/CDU-33A CD-ROM
 		  0 = /dev/sonycd	Sony CDU-31a CD-ROM
 
  16 char	Non-SCSI scanners
 		  0 = /dev/gs4500	Genius 4500 handheld scanner
-    block	GoldStar CD-ROM
+ 16 block	GoldStar CD-ROM
 		  0 = /dev/gscd		GoldStar CD-ROM
 
  17 char	Chase serial card
 		  0 = /dev/ttyH0	First Chase port
 		  1 = /dev/ttyH1	Second Chase port
 		    ...
-    block	Optics Storage CD-ROM
+ 17 block	Optics Storage CD-ROM
 		  0 = /dev/optcd	Optics Storage CD-ROM
 
  18 char	Chase serial card - alternate devices
 		  0 = /dev/cuh0		Callout device for ttyH0
 		  1 = /dev/cuh1		Callout device for ttyH1
 		    ...
-    block	Sanyo CD-ROM
+ 18 block	Sanyo CD-ROM
 		  0 = /dev/sjcd		Sanyo CD-ROM
 
  19 char	Cyclades serial card
 		  0 = /dev/ttyC0	First Cyclades port
 		    ...
 		 31 = /dev/ttyC31	32nd Cyclades port
-    block	"Double" compressed disk
+ 19 block	"Double" compressed disk
 		  0 = /dev/double0	First compressed disk
 		    ...
 		  7 = /dev/double7	Eighth compressed disk
@@ -549,7 +565,7 @@
 		  0 = /dev/cub0		Callout device for ttyC0
 		    ...
 		 31 = /dev/cub31	Callout device for ttyC31
-    block	Hitachi CD-ROM (under development)
+ 20 block	Hitachi CD-ROM (under development)
 		  0 = /dev/hitcd	Hitachi CD-ROM
 
  21 char	Generic SCSI access
@@ -562,7 +578,7 @@
 		the system and is counter to standard Linux
 		device-naming practice.
 
-    block	Acorn MFM hard drive interface
+ 21 block	Acorn MFM hard drive interface
 		  0 = /dev/mfma		First MFM drive whole disk
 		 64 = /dev/mfmb		Second MFM drive whole disk
 
@@ -574,7 +590,7 @@
 		  0 = /dev/ttyD0	First Digiboard port
 		  1 = /dev/ttyD1	Second Digiboard port
 		    ...
-    block	Second IDE hard disk/CD-ROM interface
+ 22 block	Second IDE hard disk/CD-ROM interface
 		  0 = /dev/hdc		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdd		Slave: whole disk (or CD-ROM)
 		
@@ -585,7 +601,7 @@
 		  0 = /dev/cud0		Callout device for ttyD0
 		  1 = /dev/cud1		Callout device for ttyD1
 		      ...
-    block	Mitsumi proprietary CD-ROM
+ 23 block	Mitsumi proprietary CD-ROM
 		  0 = /dev/mcd		Mitsumi CD-ROM
 
  24 char	Stallion serial card
@@ -601,7 +617,7 @@
 		192 = /dev/ttyE192	Stallion port 0 card 3
 		193 = /dev/ttyE193	Stallion port 1 card 3
 		    ...
-    block	Sony CDU-535 CD-ROM
+ 24 block	Sony CDU-535 CD-ROM
 		  0 = /dev/cdu535	Sony CDU-535 CD-ROM
 
  25 char	Stallion serial card - alternate devices
@@ -617,7 +633,7 @@
 		192 = /dev/cue192	Callout device for ttyE192
 		193 = /dev/cue193	Callout device for ttyE193
 		      ...
-    block	First Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 25 block	First Matsushita (Panasonic/SoundBlaster) CD-ROM
 		  0 = /dev/sbpcd0	Panasonic CD-ROM controller 0 unit 0
 		  1 = /dev/sbpcd1	Panasonic CD-ROM controller 0 unit 1
 		  2 = /dev/sbpcd2	Panasonic CD-ROM controller 0 unit 2
@@ -625,7 +641,7 @@
 
  26 char	Quanta WinVision frame grabber {2.6}
 		  0 = /dev/wvisfgrab	Quanta WinVision frame grabber
-    block	Second Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 26 block	Second Matsushita (Panasonic/SoundBlaster) CD-ROM
 		  0 = /dev/sbpcd4	Panasonic CD-ROM controller 1 unit 0
 		  1 = /dev/sbpcd5	Panasonic CD-ROM controller 1 unit 1
 		  2 = /dev/sbpcd6	Panasonic CD-ROM controller 1 unit 2
@@ -656,7 +672,7 @@
 		 37 = /dev/nrawqft1	Unit 1, no rewind-on-close, no file marks
 		 38 = /dev/nrawqft2	Unit 2, no rewind-on-close, no file marks
 		 39 = /dev/nrawqft3	Unit 3, no rewind-on-close, no file marks
-    block	Third Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 27 block	Third Matsushita (Panasonic/SoundBlaster) CD-ROM
 		  0 = /dev/sbpcd8	Panasonic CD-ROM controller 2 unit 0
 		  1 = /dev/sbpcd9	Panasonic CD-ROM controller 2 unit 1
 		  2 = /dev/sbpcd10	Panasonic CD-ROM controller 2 unit 2
@@ -667,16 +683,16 @@
 		  1 = /dev/staliomem1	Second Stallion card I/O memory
 		  2 = /dev/staliomem2	Third Stallion card I/O memory
 		  3 = /dev/staliomem3	Fourth Stallion card I/O memory
-    char	Atari SLM ACSI laser printer (68k/Atari)
+ 28 char	Atari SLM ACSI laser printer (68k/Atari)
 		  0 = /dev/slm0		First SLM laser printer
 		  1 = /dev/slm1		Second SLM laser printer
 		    ...
-    block	Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
+ 28 block	Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
 		  0 = /dev/sbpcd12	Panasonic CD-ROM controller 3 unit 0
 		  1 = /dev/sbpcd13	Panasonic CD-ROM controller 3 unit 1
 		  2 = /dev/sbpcd14	Panasonic CD-ROM controller 3 unit 2
 		  3 = /dev/sbpcd15	Panasonic CD-ROM controller 3 unit 3
-    block	ACSI disk (68k/Atari)
+ 28 block	ACSI disk (68k/Atari)
 		  0 = /dev/ada		First ACSI disk whole disk
 		 16 = /dev/adb		Second ACSI disk whole disk
 		 32 = /dev/adc		Third ACSI disk whole disk
@@ -693,23 +709,41 @@
 		    ...
 		 31 = /dev/fb31		32nd frame buffer
 
-    block	Aztech/Orchid/Okano/Wearnes CD-ROM
+ 29 block	Aztech/Orchid/Okano/Wearnes CD-ROM
 		  0 = /dev/aztcd	Aztech CD-ROM
 
  30 char	iBCS-2 compatibility devices
 		  0 = /dev/socksys	Socket access
 		  1 = /dev/spx		SVR3 local X interface
-		  2 = /dev/inet/arp	Network access
-		  2 = /dev/inet/icmp	Network access
-		  2 = /dev/inet/ip	Network access
-		  2 = /dev/inet/udp	Network access
-		  2 = /dev/inet/tcp	Network access
-
-		Additionally, iBCS-2 requires /dev/nfsd to be a link
-		to /dev/socksys, and /dev/X0R to be a link to
-		/dev/null.
+		 32 = /dev/inet/ip	Network access
+		 33 = /dev/inet/icmp
+		 34 = /dev/inet/ggp
+		 35 = /dev/inet/ipip
+		 36 = /dev/inet/tcp
+		 37 = /dev/inet/egp
+		 38 = /dev/inet/pup
+		 39 = /dev/inet/udp
+		 40 = /dev/inet/idp
+		 41 = /dev/inet/rawip
+
+		Additionally, iBCS-2 requires the following links:
+
+		/dev/ip -> /dev/inet/ip
+		/dev/icmp -> /dev/inet/icmp
+		/dev/ggp -> /dev/inet/ggp
+		/dev/ipip -> /dev/inet/ipip
+		/dev/tcp -> /dev/inet/tcp
+		/dev/egp -> /dev/inet/egp
+		/dev/pup -> /dev/inet/pup
+		/dev/udp -> /dev/inet/udp
+		/dev/idp -> /dev/inet/idp
+		/dev/rawip -> /dev/inet/rawip
+		/dev/inet/arp -> /dev/inet/udp
+		/dev/inet/rip -> /dev/inet/udp
+		/dev/nfsd -> /dev/socksys
+		/dev/X0R -> /dev/null (? apparently not required ?)
 
-    block	Philips LMS CM-205 CD-ROM
+ 30 block	Philips LMS CM-205 CD-ROM
 		  0 = /dev/cm205cd	Philips LMS CM-205 CD-ROM
 
 		/dev/lmscd is an older name for this device.  This
@@ -718,7 +752,7 @@
  31 char	MPU-401 MIDI
 		  0 = /dev/mpu401data	MPU-401 data port
 		  1 = /dev/mpu401stat	MPU-401 status port
-    block	ROM/flash memory card
+ 31 block	ROM/flash memory card
 		  0 = /dev/rom0		First ROM card (rw)
 		      ...
 		  7 = /dev/rom7		Eighth ROM card (rw)
@@ -741,14 +775,14 @@
 		  0 = /dev/ttyX0	First Specialix port
 		  1 = /dev/ttyX1	Second Specialix port
 		    ...
-    block	Philips LMS CM-206 CD-ROM
+ 32 block	Philips LMS CM-206 CD-ROM
 		  0 = /dev/cm206cd	Philips LMS CM-206 CD-ROM
 
  33 char	Specialix serial card - alternate devices
 		  0 = /dev/cux0		Callout device for ttyX0
 		  1 = /dev/cux1		Callout device for ttyX1
 		    ...
-    block	Third IDE hard disk/CD-ROM interface
+ 33 block	Third IDE hard disk/CD-ROM interface
 		  0 = /dev/hde		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdf		Slave: whole disk (or CD-ROM)
 
@@ -766,7 +800,7 @@
 		/dev/sc1 for /dev/scc0, /dev/sc2 for /dev/scc1, and so
 		on.
 
-    block	Fourth IDE hard disk/CD-ROM interface
+ 34 block	Fourth IDE hard disk/CD-ROM interface
 		  0 = /dev/hdg		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdh		Slave: whole disk (or CD-ROM)
 		
@@ -786,7 +820,7 @@
 		129 = /dev/smpte1	Second MIDI port, SMPTE timed
 		130 = /dev/smpte2	Third MIDI port, SMPTE timed
 		131 = /dev/smpte3	Fourth MIDI port, SMPTE timed
-    block	Slow memory ramdisk
+ 35 block	Slow memory ramdisk
 		  0 = /dev/slram	Slow memory ramdisk
 
  36 char	Netlink support
@@ -796,7 +830,7 @@
 		 16 = /dev/tap0		First Ethertap device
 		    ...
 		 31 = /dev/tap15	16th Ethertap device
-    block	MCA ESDI hard disk
+ 36 block	MCA ESDI hard disk
 		  0 = /dev/eda		First ESDI disk whole disk
 		 64 = /dev/edb		Second ESDI disk whole disk
 		    ...
@@ -814,7 +848,7 @@
 
 		Currently, only one IDE tape drive is supported.
 
-    block	Zorro II ramdisk
+ 37 block	Zorro II ramdisk
 		  0 = /dev/z2ram	Zorro II ramdisk
 
  38 char	Myricom PCI Myrinet board
@@ -826,7 +860,7 @@
 		and "user level packet I/O."  This board is also
 		accessible as a standard networking "eth" device.
 
-    block	Reserved for Linux/AP+
+ 38 block	Reserved for Linux/AP+
 
  39 char	ML-16P experimental I/O board
 		  0 = /dev/ml16pa-a0	First card, first analog channel
@@ -846,11 +880,11 @@
 		 50 = /dev/ml16pb-c1	Second card, second counter/timer
 		 51 = /dev/ml16pb-c2	Second card, third counter/timer
 		      ...
-    block	Reserved for Linux/AP+
+ 39 block	Reserved for Linux/AP+
 
  40 char	Matrox Meteor frame grabber {2.6}
 		  0 = /dev/mmetfgrab	Matrox Meteor frame grabber
-    block	Syquest EZ135 parallel port removable drive
+ 40 block	Syquest EZ135 parallel port removable drive
 		  0 = /dev/eza		Parallel EZ135 drive, whole disk
 
 		This device is obsolete and will be removed in a
@@ -861,14 +895,15 @@
 
  41 char	Yet Another Micro Monitor
 		  0 = /dev/yamm		Yet Another Micro Monitor
-    block	MicroSolutions BackPack parallel port CD-ROM
+ 41 block	MicroSolutions BackPack parallel port CD-ROM
 		  0 = /dev/bpcd		BackPack CD-ROM
 
 		This device is obsolete and will be removed in a
 		future version of Linux.  It has been replaced with
 		the parallel port ATAPI CD-ROM driver at major number 46.
 
- 42		Demo/sample use
+ 42 char	Demo/sample use
+ 42 block	Demo/sample use
 
 		This number is intended for use in sample code, as
 		well as a general "example" device number.  It
@@ -885,7 +920,7 @@
 		  0 = /dev/ttyI0	First virtual modem
 		    ...
 		 63 = /dev/ttyI63	64th virtual modem
-    block	Network block devices
+ 43 block	Network block devices
 		  0 = /dev/nb0		First network block device
 		  1 = /dev/nb1		Second network block device
 		    ...
@@ -901,7 +936,7 @@
 		  0 = /dev/cui0		Callout device for ttyI0
 		    ...
 		 63 = /dev/cui63	Callout device for ttyI63
-    block	Flash Translatio Layer (FTL) filesystems
+ 44 block	Flash Translation Layer (FTL) filesystems
 		  0 = /dev/ftla		FTL on first Memory Technology Device
 		 16 = /dev/ftlb		FTL on second Memory Technology Device
 		 32 = /dev/ftlc		FTL on third Memory Technology Device
@@ -925,7 +960,7 @@
 		191 = /dev/ippp63	64th SyncPPP device
 
 		255 = /dev/isdninfo	ISDN monitor interface
-    block	Parallel port IDE disk devices
+ 45 block	Parallel port IDE disk devices
 		  0 = /dev/pda		First parallel port IDE disk
 		 16 = /dev/pdb		Second parallel port IDE disk
 		 32 = /dev/pdc		Third parallel port IDE disk
@@ -939,7 +974,7 @@
 		  0 = /dev/ttyR0	First Rocketport port
 		  1 = /dev/ttyR1	Second Rocketport port
 		    ...
-    block	Parallel port ATAPI CD-ROM devices
+ 46 block	Parallel port ATAPI CD-ROM devices
 		  0 = /dev/pcd0		First parallel port ATAPI CD-ROM
 		  1 = /dev/pcd1		Second parallel port ATAPI CD-ROM
 		  2 = /dev/pcd2		Third parallel port ATAPI CD-ROM
@@ -949,7 +984,7 @@
 		  0 = /dev/cur0		Callout device for ttyR0
 		  1 = /dev/cur1		Callout device for ttyR1
 		    ...
-    block	Parallel port ATAPI disk devices
+ 47 block	Parallel port ATAPI disk devices
 		  0 = /dev/pf0		First parallel port ATAPI disk
 		  1 = /dev/pf1		Second parallel port ATAPI disk
 		  2 = /dev/pf2		Third parallel port ATAPI disk
@@ -962,7 +997,7 @@
 		  0 = /dev/ttyL0	First RISCom port
 		  1 = /dev/ttyL1	Second RISCom port
 		    ...
-    block	Mylex DAC960 PCI RAID controller; first controller
+ 48 block	Mylex DAC960 PCI RAID controller; first controller
 		  0 = /dev/rd/c0d0	First disk, whole disk
 		  8 = /dev/rd/c0d1	Second disk, whole disk
 		    ...
@@ -978,7 +1013,7 @@
 		  0 = /dev/cul0		Callout device for ttyL0
 		  1 = /dev/cul1		Callout device for ttyL1
 		    ...
-    block	Mylex DAC960 PCI RAID controller; second controller
+ 49 block	Mylex DAC960 PCI RAID controller; second controller
 		  0 = /dev/rd/c1d0	First disk, whole disk
 		  8 = /dev/rd/c1d1	Second disk, whole disk
 		    ...
@@ -988,17 +1023,17 @@
 
  50 char	Reserved for GLINT
 
-    block	Mylex DAC960 PCI RAID controller; third controller
+ 50 block	Mylex DAC960 PCI RAID controller; third controller
 		  0 = /dev/rd/c2d0	First disk, whole disk
 		  8 = /dev/rd/c2d1	Second disk, whole disk
 		    ...
 		248 = /dev/rd/c2d31	32nd disk, whole disk
 
- 51 char	Baycom radio modem
+ 51 char	Baycom radio modem OR Radio Tech BIM-XXX-RS232 radio modem
 		  0 = /dev/bc0		First Baycom radio modem
 		  1 = /dev/bc1		Second Baycom radio modem
 		    ...
-    block	Mylex DAC960 PCI RAID controller; fourth controller
+ 51 block	Mylex DAC960 PCI RAID controller; fourth controller
 		  0 = /dev/rd/c3d0	First disk, whole disk
 		  8 = /dev/rd/c3d1	Second disk, whole disk
 		    ...
@@ -1011,7 +1046,7 @@
 		  1 = /dev/dcbri1	Second DataComm card
 		  2 = /dev/dcbri2	Third DataComm card
 		  3 = /dev/dcbri3	Fourth DataComm card
-    block	Mylex DAC960 PCI RAID controller; fifth controller
+ 52 block	Mylex DAC960 PCI RAID controller; fifth controller
 		  0 = /dev/rd/c4d0	First disk, whole disk
 		  8 = /dev/rd/c4d1	Second disk, whole disk
 		    ...
@@ -1033,7 +1068,7 @@
 		Domain Interface and ICD is the commercial interface
 		by P&E.
 
-    block	Mylex DAC960 PCI RAID controller; sixth controller
+ 53 block	Mylex DAC960 PCI RAID controller; sixth controller
 		  0 = /dev/rd/c5d0	First disk, whole disk
 		  8 = /dev/rd/c5d1	Second disk, whole disk
 		    ...
@@ -1050,7 +1085,7 @@
 		<mseritan@ottonel.pub.ro> to transfer data from Holter
 		24-hour heart monitoring equipment.
 
-    block	Mylex DAC960 PCI RAID controller; seventh controller
+ 54 block	Mylex DAC960 PCI RAID controller; seventh controller
 		  0 = /dev/rd/c6d0	First disk, whole disk
 		  8 = /dev/rd/c6d1	Second disk, whole disk
 		    ...
@@ -1060,7 +1095,7 @@
 
  55 char	DSP56001 digital signal processor
 		  0 = /dev/dsp56k	First DSP56001
-    block	Mylex DAC960 PCI RAID controller; eigth controller
+ 55 block	Mylex DAC960 PCI RAID controller; eigth controller
 		  0 = /dev/rd/c7d0	First disk, whole disk
 		  8 = /dev/rd/c7d1	Second disk, whole disk
 		    ...
@@ -1074,7 +1109,7 @@
 		Additional devices will be added to this number, all
 		starting with /dev/adb.
 
-    block	Fifth IDE hard disk/CD-ROM interface
+ 56 block	Fifth IDE hard disk/CD-ROM interface
 		  0 = /dev/hdi		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdj		Slave: whole disk (or CD-ROM)
 
@@ -1086,7 +1121,7 @@
 		  1 = /dev/ttyP1	Second ESP port
 		    ...
 
-    block	Sixth IDE hard disk/CD-ROM interface
+ 57 block	Sixth IDE hard disk/CD-ROM interface
 		  0 = /dev/hdk		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdl		Slave: whole disk (or CD-ROM)
 
@@ -1097,12 +1132,12 @@
 		  0 = /dev/cup0		Callout device for ttyP0
 		  1 = /dev/cup1		Callout device for ttyP1
 		    ...
-    block	Reserved for logical volume manager
+ 58 block	Reserved for logical volume manager
 
  59 char	sf firewall package
 		  0 = /dev/firewall	Communication with sf kernel module
 
-    block	Generic PDA filesystem device
+ 59 block	Generic PDA filesystem device
 		  0 = /dev/pda0		First PDA device
 		  1 = /dev/pda1		Second PDA device
 		    ...
@@ -1115,14 +1150,30 @@
 
 		NAMING CONFLICT -- PROPOSED REVISED NAME /dev/rpda0 etc
 
- 60-63		LOCAL/EXPERIMENTAL USE
+ 60-63 char	LOCAL/EXPERIMENTAL USE
+ 60-63 block	LOCAL/EXPERIMENTAL USE
 		Allocated for local/experimental use.  For devices not
 		assigned official numbers, these ranges should be
-		used, in order to avoid conflicting with future assignments.
+		used in order to avoid conflicting with future assignments.
 
  64 char	ENskip kernel encryption package
 		  0 = /dev/enskip	Communication with ENskip kernel module
 
+ 64 block	Scramdisk/DriveCrypt encrypted devices
+		  0 = /dev/scramdisk/master    Master node for ioctls
+		  1 = /dev/scramdisk/1         First encrypted device
+		  2 = /dev/scramdisk/2         Second encrypted device
+		  ...
+		255 = /dev/scramdisk/255       255th encrypted device
+
+		The filename of the encrypted container and the passwords
+		are sent via ioctls (using the sdmount tool) to the master
+		node which then activates them via one of the
+		/dev/scramdisk/x nodes for loopback mounting (all handled
+		through the sdmount tool).
+
+		Requested by: andy@scramdisklinux.org
+
  65 char	Sundance "plink" Transputer boards
 		  0 = /dev/plink0	First plink device
 		  1 = /dev/plink1	Second plink device
@@ -1144,10 +1195,10 @@
 		This is a commercial driver; contact James Howes
 		<jth@prosig.demon.co.uk> for information.
 
-    block	SCSI disk devices (16-31)
-		  0 = /dev/sdq		16th SCSI disk whole disk
-		 16 = /dev/sdr		17th SCSI disk whole disk
-		 32 = /dev/sds		18th SCSI disk whole disk
+ 65 block	SCSI disk devices (16-31)
+		  0 = /dev/sdq		17th SCSI disk whole disk
+		 16 = /dev/sdr		18th SCSI disk whole disk
+		 32 = /dev/sds		19th SCSI disk whole disk
 		    ...
 		240 = /dev/sdaf		32nd SCSI disk whole disk
 
@@ -1160,7 +1211,7 @@
 		  1 = /dev/yppcpci1	Second YARC card
 		    ...
 
-    block	SCSI disk devices (32-47)
+ 66 block	SCSI disk devices (32-47)
 		  0 = /dev/sdag		33th SCSI disk whole disk
 		 16 = /dev/sdah		34th SCSI disk whole disk
 		 32 = /dev/sdai		35th SCSI disk whole disk
@@ -1176,7 +1227,7 @@
 
 		See http://www.coda.cs.cmu.edu for information about Coda.
 
-    block	SCSI disk devices (48-63)
+ 67 block	SCSI disk devices (48-63)
 		  0 = /dev/sdaw		49th SCSI disk whole disk
 		 16 = /dev/sdax		50th SCSI disk whole disk
 		 32 = /dev/sday		51st SCSI disk whole disk
@@ -1197,10 +1248,10 @@
 		ISDN CAPI 2.0 driver for use with CAPI 2.0
 		applications; currently supports the AVM B1 card.
 
-    block	SCSI disk devices (64-79)
-		  0 = /dev/sdbm		64th SCSI disk whole disk
-		 16 = /dev/sdbn		65th SCSI disk whole disk
-		 32 = /dev/sdbo		66th SCSI disk whole disk
+ 68 block	SCSI disk devices (64-79)
+		  0 = /dev/sdbm		65th SCSI disk whole disk
+		 16 = /dev/sdbn		66th SCSI disk whole disk
+		 32 = /dev/sdbo		67th SCSI disk whole disk
 		    ...
 		240 = /dev/sdcb		80th SCSI disk whole disk
 
@@ -1211,7 +1262,7 @@
  69 char	MA16 numeric accelerator card
 		  0 = /dev/ma16		Board memory access
 
-    block	SCSI disk devices (80-95)
+ 69 block	SCSI disk devices (80-95)
 		  0 = /dev/sdcc		81st SCSI disk whole disk
 		 16 = /dev/sdcd		82nd SCSI disk whole disk
 		 32 = /dev/sdce		83th SCSI disk whole disk
@@ -1231,7 +1282,7 @@
 		 65 = /dev/apsasync	Async command interface
 		128 = /dev/apsmon	Monitor interface
 
-    block	SCSI disk devices (96-111)
+ 70 block	SCSI disk devices (96-111)
 		  0 = /dev/sdcs		97th SCSI disk whole disk
 		 16 = /dev/sdct		98th SCSI disk whole disk
 		 32 = /dev/sdcu		99th SCSI disk whole disk
@@ -1260,7 +1311,7 @@
 		    ...
 		255 = /dev/ttyF255	IntelliPort II board 3, port 63
 
-    block	SCSI disk devices (112-127)
+ 71 block	SCSI disk devices (112-127)
 		  0 = /dev/sddi		113th SCSI disk whole disk
 		 16 = /dev/sddj		114th SCSI disk whole disk
 		 32 = /dev/sddk		115th SCSI disk whole disk
@@ -1289,7 +1340,7 @@
 		    ...
 		255 = /dev/cuf255	Callout device for ttyF255
 
-    block	Compaq Intelligent Drive Array, first controller
+ 72 block	Compaq Intelligent Drive Array, first controller
 		  0 = /dev/ida/c0d0	First logical drive whole disk
 		 16 = /dev/ida/c0d1	Second logical drive whole disk
 		    ...
@@ -1309,7 +1360,7 @@
 		 12 = /dev/ip2ipl3	Loadware device for board 3
 		 13 = /dev/ip2stat3	Status device for board 3
 
-    block	Compaq Intelligent Drive Array, second controller
+ 73 block	Compaq Intelligent Drive Array, second controller
 		  0 = /dev/ida/c1d0	First logical drive whole disk
 		 16 = /dev/ida/c1d1	Second logical drive whole disk
 		    ...
@@ -1327,7 +1378,7 @@
 		Currently for Dolphin Interconnect Solutions' PCI-SCI
 		bridge.
 
-    block	Compaq Intelligent Drive Array, third controller
+ 74 block	Compaq Intelligent Drive Array, third controller
 		  0 = /dev/ida/c2d0	First logical drive whole disk
 		 16 = /dev/ida/c2d1	Second logical drive whole disk
 		    ...
@@ -1344,7 +1395,7 @@
 		  8 = /dev/ttyW8	First IO8+ port, second card
 		    ...
 
-    block	Compaq Intelligent Drive Array, fourth controller
+ 75 block	Compaq Intelligent Drive Array, fourth controller
 		  0 = /dev/ida/c3d0	First logical drive whole disk
 		 16 = /dev/ida/c3d1	Second logical drive whole disk
 		    ...
@@ -1361,7 +1412,7 @@
 		  8 = /dev/cuw8		Callout device for ttyW8
 		    ...
 
-    block	Compaq Intelligent Drive Array, fifth controller
+ 76 block	Compaq Intelligent Drive Array, fifth controller
 		  0 = /dev/ida/c4d0	First logical drive whole disk
 		 16 = /dev/ida/c4d1	Second logical drive whole disk
 		    ...
@@ -1375,7 +1426,7 @@
  77 char	ComScire Quantum Noise Generator
 		  0 = /dev/qng		ComScire Quantum Noise Generator
 
-    block	Compaq Intelligent Drive Array, sixth controller
+ 77 block	Compaq Intelligent Drive Array, sixth controller
 		  0 = /dev/ida/c5d0	First logical drive whole disk
 		 16 = /dev/ida/c5d1	Second logical drive whole disk
 		    ...
@@ -1391,7 +1442,7 @@
 		  1 = /dev/ttyM1	Second PAM modem
 		    ...
 
-    block	Compaq Intelligent Drive Array, seventh controller
+ 78 block	Compaq Intelligent Drive Array, seventh controller
 		  0 = /dev/ida/c6d0	First logical drive whole disk
 		 16 = /dev/ida/c6d1	Second logical drive whole disk
 		    ...
@@ -1407,7 +1458,7 @@
 		  1 = /dev/cum1		Callout device for ttyM1
 		    ...
 
-    block	Compaq Intelligent Drive Array, eigth controller
+ 79 block	Compaq Intelligent Drive Array, eigth controller
 		  0 = /dev/ida/c7d0	First logical drive whole disk
 		 16 = /dev/ida/c7d1	Second logical drive whole disk
 		    ...
@@ -1421,7 +1472,7 @@
  80 char	Photometrics AT200 CCD camera
 		  0 = /dev/at200	Photometrics AT200 CCD camera
 
-    block	I2O hard disk
+ 80 block	I2O hard disk
 		  0 = /dev/i2o/hda	First I2O hard disk, whole disk
 		 16 = /dev/i2o/hdb	Second I2O hard disk, whole disk
 		    ...
@@ -1445,7 +1496,7 @@
 		    ...
 		255 = /dev/vbi31	Vertical blank interrupt
 
-    block	I2O hard disk
+ 81 block	I2O hard disk
 		  0 = /dev/i2o/hdq	17th I2O hard disk, whole disk
 		 16 = /dev/i2o/hdr	18th I2O hard disk, whole disk
 		    ...
@@ -1463,7 +1514,7 @@
 		The driver and documentation may be obtained from
 		http://www.proximity.com.au/~brian/winradio/
 
-    block	I2O hard disk
+ 82 block	I2O hard disk
 		  0 = /dev/i2o/hdag	33rd I2O hard disk, whole disk
 		 16 = /dev/i2o/hdah	34th I2O hard disk, whole disk
 		    ...
@@ -1480,7 +1531,7 @@
 		Devices for the driver contained in the VideoteXt package.
 		More information on http://home.pages.de/~videotext/
 
-    block	I2O hard disk
+ 83 block	I2O hard disk
 		  0 = /dev/i2o/hdaw	49th I2O hard disk, whole disk
 		 16 = /dev/i2o/hdax	50th I2O hard disk, whole disk
 		    ...
@@ -1494,7 +1545,7 @@
 		  0 = /dev/ihcp0	First Greensheet port
 		  1 = /dev/ihcp1	Second Greensheet port
 
-    block	I2O hard disk
+ 84 block	I2O hard disk
 		  0 = /dev/i2o/hdbm	65th I2O hard disk, whole disk
 		 16 = /dev/i2o/hdbn	66th I2O hard disk, whole disk
 		    ...
@@ -1510,7 +1561,7 @@
 		  2 = /dev/qcntl1	Second device pushed
 		    ...
 
-    block	I2O hard disk
+ 85 block	I2O hard disk
 		  0 = /dev/i2o/hdcc	81st I2O hard disk, whole disk
 		 16 = /dev/i2o/hdcd	82nd I2O hard disk, whole disk
 		    ...
@@ -1525,7 +1576,7 @@
 		  1 = /dev/sch1		Second SCSI media changer
 		    ...
 
-    block	I2O hard disk
+ 86 block	I2O hard disk
 		  0 = /dev/i2o/hdcs	97th I2O hard disk, whole disk
 		 16 = /dev/i2o/hdct	98th I2O hard disk, whole disk
 		    ...
@@ -1540,7 +1591,7 @@
 		  1 = /dev/controla1	Second device on chain
 		    ...
 
-    block	I2O hard disk
+ 87 block	I2O hard disk
 		  0 = /dev/i2o/hddi	113rd I2O hard disk, whole disk
 		 16 = /dev/i2o/hddj	114th I2O hard disk, whole disk
 		    ...
@@ -1555,7 +1606,7 @@
 		  1 = /dev/comx1	COMX channel 1
 		    ...
 
-    block	Seventh IDE hard disk/CD-ROM interface
+ 88 block	Seventh IDE hard disk/CD-ROM interface
 		  0 = /dev/hdm		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdn		Slave: whole disk (or CD-ROM)
 
@@ -1567,7 +1618,7 @@
 		  1 = /dev/i2c-1	Second I2C adapter
 		    ...
 
-    block	Eighth IDE hard disk/CD-ROM interface
+ 89 block	Eighth IDE hard disk/CD-ROM interface
 		  0 = /dev/hdo		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdp		Slave: whole disk (or CD-ROM)
 
@@ -1581,7 +1632,7 @@
 		 30 = /dev/mtd15	16th MTD (rw)
 		 31 = /dev/mtdr15	16th MTD (ro)
 
-    block	Ninth IDE hard disk/CD-ROM interface
+ 90 block	Ninth IDE hard disk/CD-ROM interface
 		  0 = /dev/hdq		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdr		Slave: whole disk (or CD-ROM)
 
@@ -1593,7 +1644,7 @@
 		  1 = /dev/can1		Second CAN-Bus controller
 		    ...
 
-    block	Tenth IDE hard disk/CD-ROM interface
+ 91 block	Tenth IDE hard disk/CD-ROM interface
 		  0 = /dev/hds		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdt		Slave: whole disk (or CD-ROM)
 
@@ -1602,7 +1653,7 @@
 
  92 char	Reserved for ith Kommunikationstechnik MIC ISDN card
 
-    block	PPDD encrypted disk driver
+ 92 block	PPDD encrypted disk driver
 		  0 = /dev/ppdd0	First encrypted disk
 		  1 = /dev/ppdd1	Second encrypted disk
 		    ...
@@ -1619,7 +1670,7 @@
 		129 = /dev/isccctl1	Second Smart Capture Card control
 		    ...
 
-    block	NAND Flash Translation Layer filesystem
+ 93 block	NAND Flash Translation Layer filesystem
 		  0 = /dev/nftla	First NFTL layer
 		 16 = /dev/nftlb	Second NFTL layer
 		    ...
@@ -1630,16 +1681,11 @@
 		  1 = /dev/dcxx1	Second capture card
 		    ...
 
-    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
+ 94 block	Inverse NAND Flash Translation Layer
+		  0 = /dev/inftla	First INFTL layer
+		 16 = /dev/inftlb	Second INFTL layer
 		    ...
+		240 = /dev/inftlp	16th INTFL layer
 
  95 char	IP filter
 		  0 = /dev/ipl		Filter control device/log file
@@ -1648,9 +1694,15 @@
 		  3 = /dev/ipauth	Authentication control device/log file
 		    ...		
 
-    block	IBM S/390 VM/ESA minidisk
-		  0 = /dev/mnda		First VM/ESA minidisk
-		  1 = /dev/mndb		Second VM/ESA minidisk
+ 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
 		    ...
 
  96 char	Parallel port ATAPI tape devices
@@ -1661,6 +1713,11 @@
 		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
+		    ...
+
  97 char	Parallel port generic ATAPI interface
 		  0 = /dev/pg0		First parallel port ATAPI device
 		  1 = /dev/pg1		Second parallel port ATAPI device
@@ -1670,7 +1727,7 @@
 		These devices support the same API as the generic SCSI
 		devices.
 
-    block	Packet writing for CD/DVD devices
+ 97 block	Packet writing for CD/DVD devices
 		  0 = /dev/pktcdvd0	First packet-writing module
 		  1 = /dev/pktcdvd1	Second packet-writing module
 		    ...
@@ -1682,7 +1739,7 @@
 
 		See http://stm.lbl.gov/comedi or http://www.llp.fu-berlin.de/.
 
-    block	User-mode virtual block device
+ 98 block	User-mode virtual block device
 		  0 = /dev/ubd0		First user-mode block device
 		  1 = /dev/ubd1		Second user-mode block device
 		    ...
@@ -1694,7 +1751,7 @@
 		  1 = /dev/parport1	Second parallel port
 		    ...
 
-    block	JavaStation flash disk
+ 99 block	JavaStation flash disk
 		  0 = /dev/jsfd		JavaStation flash disk
 
 100 char	Telephony for Linux
@@ -1708,7 +1765,7 @@
 		    ...
 		 16 = /dev/mdsp16	16th DSP board I/O controls
 
-    block	AMI HyperDisk RAID controller
+101 block	AMI HyperDisk RAID controller
 		  0 = /dev/amiraid/ar0	First array whole disk
 		 16 = /dev/amiraid/ar1	Second array whole disk
 		    ...
@@ -1727,7 +1784,7 @@
 		  2 = /dev/tlk2		Third Teletext decoder
 		  3 = /dev/tlk3		Fourth Teletext decoder
 
-    block	Compressed block device
+102 block	Compressed block device
 		  0 = /dev/cbd/a	First compressed block device, whole device
 		 16 = /dev/cbd/b	Second compressed block device, whole device
 		    ...
@@ -1747,12 +1804,12 @@
 		to the arla announce mailing list by sending a mail to
 		<arla-announce-request@stacken.kth.se>.
 
-    block	Audit device
+103 block	Audit device
 		  0 = /dev/audit	Audit device
 
 104 char	Flash BIOS support
 
-    block	Compaq Next Generation Drive Array, first controller
+104 block	Compaq Next Generation Drive Array, first controller
 		  0 = /dev/cciss/c0d0	First logical drive, whole disk
 		 16 = /dev/cciss/c0d1	Second logical drive, whole disk
 		    ...
@@ -1767,7 +1824,7 @@
 		  1 = /dev/ttyV1	Second VS-1000 port
 		    ...
 
-    block	Compaq Next Generation Drive Array, second controller
+105 block	Compaq Next Generation Drive Array, second controller
 		  0 = /dev/cciss/c1d0	First logical drive, whole disk
 		 16 = /dev/cciss/c1d1	Second logical drive, whole disk
 		    ...
@@ -1782,7 +1839,7 @@
 		  1 = /dev/cuv1		Second VS-1000 port
 		    ...
 
-    block	Compaq Next Generation Drive Array, third controller
+106 block	Compaq Next Generation Drive Array, third controller
 		  0 = /dev/cciss/c2d0	First logical drive, whole disk
 		 16 = /dev/cciss/c2d1	Second logical drive, whole disk
 		    ...
@@ -1795,7 +1852,7 @@
 107 char	3Dfx Voodoo Graphics device
 		  0 = /dev/3dfx		Primary 3Dfx graphics device
 
-    block	Compaq Next Generation Drive Array, fourth controller
+107 block	Compaq Next Generation Drive Array, fourth controller
 		  0 = /dev/cciss/c3d0	First logical drive, whole disk
 		 16 = /dev/cciss/c3d1	Second logical drive, whole disk
 		    ...
@@ -1808,7 +1865,7 @@
 108 char	Device independent PPP interface
 		  0 = /dev/ppp		Device independent PPP interface
 
-    block	Compaq Next Generation Drive Array, fifth controller
+108 block	Compaq Next Generation Drive Array, fifth controller
 		  0 = /dev/cciss/c4d0	First logical drive, whole disk
 		 16 = /dev/cciss/c4d1	Second logical drive, whole disk
 		    ...
@@ -1820,7 +1877,7 @@
 
 109 char	Reserved for logical volume manager
 
-    block	Compaq Next Generation Drive Array, sixth controller
+109 block	Compaq Next Generation Drive Array, sixth controller
 		  0 = /dev/cciss/c5d0	First logical drive, whole disk
 		 16 = /dev/cciss/c5d1	Second logical drive, whole disk
 		    ...
@@ -1835,7 +1892,7 @@
 		  1 = /dev/srnd1	Second miroMEDIA Surround board
 		    ...
 
-    block	Compaq Next Generation Drive Array, seventh controller
+110 block	Compaq Next Generation Drive Array, seventh controller
 		  0 = /dev/cciss/c6d0	First logical drive, whole disk
 		 16 = /dev/cciss/c6d1	Second logical drive, whole disk
 		    ...
@@ -1850,7 +1907,7 @@
 		  1 = /dev/av1		Second A/V card
 		    ...
 
-    block	Compaq Next Generation Drive Array, eigth controller
+111 block	Compaq Next Generation Drive Array, eigth controller
 		  0 = /dev/cciss/c7d0	First logical drive, whole disk
 		 16 = /dev/cciss/c7d1	Second logical drive, whole disk
 		    ...
@@ -1868,14 +1925,14 @@
 		There is currently a device-naming conflict between
 		these and PAM multimodems (major 78).
 
-    block	IBM iSeries virtual disk
+112 block	IBM iSeries virtual disk
 		  0 = /dev/iseries/vda	First virtual disk, whole disk
 		  8 = /dev/iseries/vdb	Second virtual disk, whole disk
 		    ...
 		200 = /dev/iseries/vdz	26th virtual disk, whole disk
 		208 = /dev/iseries/vdaa	27th virtual disk, whole disk
 		    ...
-		240 = /dev/iseries/vdaf	32nd virtual disk, whole disk
+		248 = /dev/iseries/vdaf	32nd virtual disk, whole disk
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
@@ -1886,7 +1943,7 @@
 		  1 = /dev/cum1		Callout device for ttyM1
 		    ...
 
-    block	IBM iSeries virtual CD-ROM
+113 block	IBM iSeries virtual CD-ROM
 
 		  0 = /dev/iseries/vcda	First virtual CD-ROM
 		  1 = /dev/iseries/vcdb	Second virtual CD-ROM
@@ -1905,13 +1962,69 @@
 		I/O access to the board, the /dev/isex0 nodes command
 		nodes used to control the board.
 
-115 char	Console driver speaker
-		  0 = /dev/speaker	Speaker device file
+114 block       IDE BIOS powered software RAID interfaces such as the
+                Promise Fastrak
+
+                  0 = /dev/ataraid/d0
+                  1 = /dev/ataraid/d0p1
+                  2 = /dev/ataraid/d0p2
+                  ...
+                 16 = /dev/ataraid/d1
+                 17 = /dev/ataraid/d1p1
+                 18 = /dev/ataraid/d1p2
+                  ...
+                255 = /dev/ataraid/d15p15
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+115 char	TI link cable devices (115 was formerly the console driver speaker)
+		  0 = /dev/tipar0    Parallel cable on first parallel port
+		  ...
+		  7 = /dev/tipar7    Parallel cable on seventh parallel port
+
+		  8 = /dev/tiser0    Serial cable on first serial port
+		  ...
+		 15 = /dev/tiser7    Serial cable on seventh serial port
+
+		 16 = /dev/tiusb0    First USB cable
+		  ...
+		 47 = /dev/tiusb31   32nd USB cable
 
-		Plays music using IBM BASIC style strings.
+115 block       NetWare (NWFS) Devices (0-255)
+
+                The NWFS (NetWare) devices are used to present a
+                collection of NetWare Mirror Groups or NetWare
+                Partitions as a logical storage segment for
+                use in mounting NetWare volumes.  A maximum of
+                256 NetWare volumes can be supported in a single
+                machine.
+
+                http://www.kernel.org/pub/linux/kernel/people/jmerkey/nwfs
+
+                0 = /dev/nwfs/v0    First NetWare (NWFS) Logical Volume
+                1 = /dev/nwfs/v1    Second NetWare (NWFS) Logical Volume
+                2 = /dev/nwfs/v2    Third NetWare (NWFS) Logical Volume
+                      ...
+                255 = /dev/nwfs/v255    Last NetWare (NWFS) Logical Volume
 
 116 char	Advanced Linux Sound Driver (ALSA)
 
+116 block       MicroMemory battery backed RAM adapter (NVRAM)
+                Supports 16 boards, 15 paritions each.
+                Requested by neilb at cse.unsw.edu.au.
+
+		 0 = /dev/umem/d0      Whole of first board
+		 1 = /dev/umem/d0p1    First partition of first board
+		 2 = /dev/umem/d0p2    Second partition of first board
+		15 = /dev/umem/d0p15   15th partition of first board
+
+		16 = /dev/umem/d1      Whole of second board
+		17 = /dev/umem/d1p1    First partition of second board
+		    ...
+		255= /dev/umem/d15p15  15th partition of 16th board.
+
 117 char	COSA/SRP synchronous serial card
 		  0 = /dev/cosa0c0	1st board, 1st channel
 		  1 = /dev/cosa0c1	1st board, 2nd channel
@@ -1920,6 +2033,32 @@
 		 17 = /dev/cosa1c1	2nd board, 2nd channel
 		    ...
 
+117 block       Enterprise Volume Management System (EVMS)
+
+                The EVMS driver uses a layered, plug-in model to provide
+                unparalleled flexibility and extensibility in managing
+                storage.  This allows for easy expansion or customization
+                of various levels of volume management.  Requested by
+                Mark Peloquin (peloquin at us.ibm.com).
+
+                Note: EVMS populates and manages all the devnodes in
+                /dev/evms.
+
+                http://sf.net/projects/evms
+
+                  0 = /dev/evms/block_device   EVMS block device
+                  1 = /dev/evms/legacyname1    First EVMS legacy device
+                  2 = /dev/evms/legacyname2    Second EVMS legacy device
+                    ...
+                    Both ranges can grow (down or up) until they meet.
+                    ...
+                254 = /dev/evms/EVMSname2      Second EVMS native device
+                255 = /dev/evms/EVMSname1      First EVMS native device
+
+                Note: legacyname(s) are derived from the normal legacy
+                device names.  For example, /dev/hda5 would become
+                /dev/evms/hda5.
+
 118 char	Solidum ???
 		  0 = /dev/solnp0
 		  1 = /dev/solnp1
@@ -1933,14 +2072,114 @@
 		  1 = /dev/vnet1	2nd virtual network
 		    ...
 
-120-127		LOCAL/EXPERIMENTAL USE
+120-127 char	LOCAL/EXPERIMENTAL USE
+120-127 block	LOCAL/EXPERIMENTAL USE
+		Allocated for local/experimental use.  For devices not
+		assigned official numbers, these ranges should be
+		used in order to avoid conflicting with future assignments.
 
-128-135	char	Unix98 PTY masters
+128-135 char	Unix98 PTY masters
 
 		These devices should not have corresponding device
 		nodes; instead they should be accessed through the
 		/dev/ptmx cloning interface.
 
+
+128 block       SCSI disk devices (128-143)
+                  0 = /dev/sddy         129th SCSI disk whole disk
+                 16 = /dev/sddz         130th SCSI disk whole disk
+                 32 = /dev/sdea         131th SCSI disk whole disk
+                    ...
+                240 = /dev/sden         144th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+
+129 block       SCSI disk devices (144-159)
+                  0 = /dev/sdeo         145th SCSI disk whole disk
+                 16 = /dev/sdep         146th SCSI disk whole disk
+                 32 = /dev/sdeq         147th SCSI disk whole disk
+                    ...
+                240 = /dev/sdfd         160th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+
+130 block       SCSI disk devices (160-175)
+                  0 = /dev/sdfe         161st SCSI disk whole disk
+                 16 = /dev/sdff         162nd SCSI disk whole disk
+                 32 = /dev/sdfg         163rd SCSI disk whole disk
+                    ...
+                240 = /dev/sdft         176th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+131 block       SCSI disk devices (176-191)
+                  0 = /dev/sdfu         177th SCSI disk whole disk
+                 16 = /dev/sdfv         178th SCSI disk whole disk
+                 32 = /dev/sdfw         179th SCSI disk whole disk
+                    ...
+                240 = /dev/sdgj         192nd SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+
+132 block       SCSI disk devices (192-207)
+                  0 = /dev/sdgk         193rd SCSI disk whole disk
+                 16 = /dev/sdgl         194th SCSI disk whole disk
+                 32 = /dev/sdgm         195th SCSI disk whole disk
+                    ...
+                240 = /dev/sdgz         208th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+
+133 block       SCSI disk devices (208-223)
+                  0 = /dev/sdha         209th SCSI disk whole disk
+                 16 = /dev/sdhb         210th SCSI disk whole disk
+                 32 = /dev/sdhc         211th SCSI disk whole disk
+                    ...
+                240 = /dev/sdhp         224th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+
+134 block       SCSI disk devices (224-239)
+                  0 = /dev/sdhq         225th SCSI disk whole disk
+                 16 = /dev/sdhr         226th SCSI disk whole disk
+                 32 = /dev/sdhs         227th SCSI disk whole disk
+                    ...
+                240 = /dev/sdif         240th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+
+135 block       SCSI disk devices (240-255)
+                  0 = /dev/sdig         241st SCSI disk whole disk
+                 16 = /dev/sdih         242nd SCSI disk whole disk
+                 32 = /dev/sdih         243rd SCSI disk whole disk
+                    ...
+                240 = /dev/sdiv         256th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+
 136-143 char	Unix98 PTY slaves
 		  0 = /dev/pts/0	First Unix98 pseudo-TTY
 		  1 = /dev/pts/1	Second Unix98 pesudo-TTY
@@ -1953,6 +2192,70 @@
 		*most* distributions the appropriate options are
 		"mode=0620,gid=<gid of the "tty" group>".)
 
+136 block	Mylex DAC960 PCI RAID controller; ninth controller
+		  0 = /dev/rd/c8d0	First disk, whole disk
+		  8 = /dev/rd/c8d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c8d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+137 block	Mylex DAC960 PCI RAID controller; tenth controller
+		  0 = /dev/rd/c9d0	First disk, whole disk
+		  8 = /dev/rd/c9d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c9d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+138 block	Mylex DAC960 PCI RAID controller; eleventh controller
+		  0 = /dev/rd/c10d0	First disk, whole disk
+		  8 = /dev/rd/c10d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c10d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+139 block	Mylex DAC960 PCI RAID controller; twelfth controller
+		  0 = /dev/rd/c11d0	First disk, whole disk
+		  8 = /dev/rd/c11d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c11d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+140 block	Mylex DAC960 PCI RAID controller; thirteenth controller
+		  0 = /dev/rd/c12d0	First disk, whole disk
+		  8 = /dev/rd/c12d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c12d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+141 block	Mylex DAC960 PCI RAID controller; fourteenth controller
+		  0 = /dev/rd/c13d0	First disk, whole disk
+		  8 = /dev/rd/c13d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c13d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+142 block	Mylex DAC960 PCI RAID controller; fifteenth controller
+		  0 = /dev/rd/c14d0	First disk, whole disk
+		  8 = /dev/rd/c14d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c14d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+143 block	Mylex DAC960 PCI RAID controller; sixteenth controller
+		  0 = /dev/rd/c15d0	First disk, whole disk
+		  8 = /dev/rd/c15d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c15d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
 144 char	Encapsulated PPP
 		  0 = /dev/pppox0	First PPP over Ethernet
 		    ...
@@ -1963,6 +2266,10 @@
 		The SST 5136-DN DeviceNet interface driver has been
 		relocated to major 183 due to an unfortunate conflict.
 
+144 block	Expansion Area #1 for more non-device (e.g. NFS) mounts
+		  0 = mounted device 256
+		255 = mounted device 511
+
 145 char	SAM9407-based soundcard
 		  0 = /dev/sam0_mixer
 		  1 = /dev/sam0_sequencer
@@ -1984,12 +2291,20 @@
 		addons, which are sam9407 specific.  OSS can be
 		operated simultaneously, taking care of the codec.
 
+145 block	Expansion Area #2 for more non-device (e.g. NFS) mounts
+		  0 = mounted device 512
+		255 = mounted device 767
+
 146 char	SYSTRAM SCRAMNet mirrored-memory network
 		  0 = /dev/scramnet0	First SCRAMNet device
 		  1 = /dev/scramnet1	Second SCRAMNet device
 		    ...
 
-147 char	Aueral Semiconductor Vortex Audio device
+146 block	Expansion Area #3 for more non-device (e.g. NFS) mounts
+		  0 = mounted device 768
+		255 = mounted device 1023
+
+147 char	Aureal Semiconductor Vortex Audio device
 		  0 = /dev/aureal0	First Aureal Vortex
 		  1 = /dev/aureal1	Second Aureal Vortex
 		    ...
@@ -2014,6 +2329,22 @@
 		  1 = /dev/dpti1	Second DPT I2O adapter
 		    ...
 
+152 char	EtherDrive Control Device
+		  0 = /dev/etherd/ctl	Connect/Disconnect an EtherDrive
+		  1 = /dev/etherd/err	Monitor errors
+		  2 = /dev/etherd/raw	Raw AoE packet monitor
+
+152 block	EtherDrive Block Devices
+		  0 = /dev/etherd/0	EtherDrive 0
+		    ...
+		255 = /dev/etherd/255	EtherDrive 255
+
+153 char	SPI Bus Interface (sometimes referred to as MicroWire)
+		  0 = /dev/spi0		First SPI device on the bus
+		  1 = /dev/spi1		Second SPI device on the bus
+		    ...
+		 15 = /dev/spi15	Sixteenth SPI device on the bus
+
 154 char	Specialix RIO serial card
 		  0 = /dev/ttySR0	First RIO port
 		    ...
@@ -2090,10 +2421,7 @@
 		  2 = /dev/raw/raw2	Second raw I/O device
 		    ...
 
-163 char	Radio Tech BIM-XXX-RS232 radio modem
-		  0 = /dev/bimrt0	First BIM radio modem
-		  1 = /dev/bimrt1	Second BIM radio modem
-		    ...
+163 char	UNASSIGNED (was Radio Tech BIM-XXX-RS232 radio modem - see 51)
 
 164 char	Chase Research AT/PCI-Fast serial card
 		  0 = /dev/ttyCH0	AT/PCI-Fast board 0, port 0
@@ -2205,6 +2533,9 @@
 		    ...
 		 63 = /dev/usb/scanner15 16th USB scanner
 		 64 = /dev/usb/rio500	Diamond Rio 500
+		 65 = /dev/usb/usblcd	USBLCD Interface (info@usblcd.de)
+		 66 = /dev/usb/cpad0	Synaptics cPad (mouse/LCD)
+
 
 181 char	Conrad Electronic parallel port radio clocks
 		  0 = /dev/pcfclock0	First Conrad radio clock
@@ -2325,9 +2656,10 @@
 		  0 = /dev/vx/rdsk/*/*		First volume
 		  1 = /dev/vx/rdsk/*/*		Second volume
 		    ...
-    block	Veritas volume manager (VxVM) volumes
+
+199 block	Veritas volume manager (VxVM) volumes
 		  0 = /dev/vx/dsk/*/*		First volume
-		  1 = /dev/vx/dsk/*/*		First volume
+		  1 = /dev/vx/dsk/*/*		Second volume
 		    ...
 
 		The namespace in these directories is maintained by
@@ -2345,7 +2677,7 @@
 		  0 = /dev/vx/rdmp/*		First multipath device
 		  1 = /dev/vx/rdmp/*		Second multipath device
 		    ...
-    block	Veritas VxVM dynamic multipathing driver
+201 block	Veritas VxVM dynamic multipathing driver
 		  0 = /dev/vx/dmp/*		First multipath device
 		  1 = /dev/vx/dmp/*		Second multipath device
 		    ...
@@ -2499,6 +2831,26 @@
 		  1 = /dev/addinum/cpci1500/1	Second CPCI1500 card
 		    ...
 
+212 char	LinuxTV.org DVB driver subsystem
+
+		  0 = /dev/dvb/adapter0/video0    first video decoder of first card
+		  1 = /dev/dvb/adapter0/audio0    first audio decoder of first card
+		  2 = /dev/dvb/adapter0/sec0      (obsolete/unused)
+		  3 = /dev/dvb/adapter0/frontend0 first frontend device of first card
+		  4 = /dev/dvb/adapter0/demux0    first demux device of first card
+		  5 = /dev/dvb/adapter0/dvr0      first digital video recoder device of first card
+		  6 = /dev/dvb/adapter0/ca0       first common access port of first card
+		  7 = /dev/dvb/adapter0/net0      first network device of first card
+		  8 = /dev/dvb/adapter0/osd0      first on-screen-display device of first card
+		  9 = /dev/dvb/adapter0/video1    second video decoder of first card
+		    ...
+		 64 = /dev/dvb/adapter1/video0    first video decoder of second card
+		    ...
+		128 = /dev/dvb/adapter2/video0    first video decoder of third card
+		    ...
+		196 = /dev/dvb/adapter3/video0    first video decoder of fourth card
+
+
 216 char	USB BlueTooth devices
 		  0 = /dev/ttyUB0		First USB BlueTooth device
 		  1 = /dev/ttyUB1		Second USB BlueTooth device
@@ -2605,9 +2957,14 @@
 
 231-239		UNASSIGNED
 
-240-254		LOCAL/EXPERIMENTAL USE
+240-254 char	LOCAL/EXPERIMENTAL USE
+240-254 block	LOCAL/EXPERIMENTAL USE
+		Allocated for local/experimental use.  For devices not
+		assigned official numbers, these ranges should be
+		used in order to avoid conflicting with future assignments.
 
-255		RESERVED
+255 char	RESERVED
+255 block	RESERVED
 
 		This major is reserved to assist the expansion to a
 		larger number space.  No device nodes with this major
diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt
--- a/Documentation/ide.txt	Wed Mar 17 19:29:09 2004
+++ b/Documentation/ide.txt	Wed Mar 17 19:29:09 2004
@@ -249,8 +249,6 @@
  "hdx=scsi"		: the return of the ide-scsi flag, this is useful for
  			  allowing ide-floppy, ide-tape, and ide-cdrom|writers
  			  to use ide-scsi emulation on a device specific option.
-				
- "hdxlun=xx"		: set the drive last logical unit
 
  "idebus=xx"		: inform IDE driver of VESA/PCI bus speed in MHz,
 			  where "xx" is between 20 and 66 inclusive,
diff -Nru a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt
--- a/Documentation/input/joystick-parport.txt	Wed Mar 17 19:29:10 2004
+++ b/Documentation/input/joystick-parport.txt	Wed Mar 17 19:29:10 2004
@@ -434,7 +434,7 @@
   Using gamecon.c you can connect up to five devices to one parallel port. It
 uses the following kernel/module command line:
 
-	gc=port,pad1,pad2,pad3,pad4,pad5
+	gamecon.map=port,pad1,pad2,pad3,pad4,pad5
 
   Where 'port' the number of the parport interface (eg. 0 for parport0).
 
@@ -457,15 +457,15 @@
 your controller plugged in before initializing.
 
   Should you want to use more than one of parallel ports at once, you can use
-gc_2 and gc_3 as additional command line parameters for two more parallel
-ports.
+gamecon.map2 and gamecon.map3 as additional command line parameters for two
+more parallel ports.
 
 3.2 db9.c
 ~~~~~~~~~
   Apart from making an interface, there is nothing difficult on using the
 db9.c driver. It uses the following kernel/module command line:
 
-	db9=port,type
+	db9.dev=port,type
 
   Where 'port' is the number of the parport interface (eg. 0 for parport0).
 
@@ -489,14 +489,14 @@
 	 10  | Amiga CD32 pad
 
   Should you want to use more than one of these joysticks/pads at once, you
-can use db9_2 and db9_3 as additional command line parameters for two
+can use db9.dev2 and db9.dev3 as additional command line parameters for two
 more joysticks/pads.
 
 3.3 turbografx.c
 ~~~~~~~~~~~~~~~~
   The turbografx.c driver uses a very simple kernel/module command line:
 
-	tgfx=port,js1,js2,js3,js4,js5,js6,js7
+	turbografx.map=port,js1,js2,js3,js4,js5,js6,js7
 
   Where 'port' is the number of the parport interface (eg. 0 for parport0).
 
@@ -504,8 +504,8 @@
 interface ports 1-7 have. For a standard multisystem joystick, this is 1.
 
   Should you want to use more than one of these interfaces at once, you can
-use tgfx_2 and tgfx_3 as additional command line parameters for two more
-interfaces.
+use turbografx.map2 and turbografx.map3 as additional command line parameters
+for two more interfaces.
 
 3.4 PC parallel port pinout
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff -Nru a/Documentation/input/joystick.txt b/Documentation/input/joystick.txt
--- a/Documentation/input/joystick.txt	Wed Mar 17 19:29:10 2004
+++ b/Documentation/input/joystick.txt	Wed Mar 17 19:29:10 2004
@@ -111,7 +111,7 @@
 	alias tty-ldisc-2 serport
 	alias char-major-13 input
 	above input joydev ns558 analog
-	options analog js=gamepad
+	options analog map=gamepad,none,2btn
 
 2.5 Verifying that it works
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -185,7 +185,7 @@
 module command line, when inserting analog.o into the kernel. The
 parameters are:
 
-	js=type,type,type,....
+	analog.map=<type1>,<type2>,<type3>,....
 
   'type' is type of the joystick from the table below, defining joysticks
 present on gameports in the system, starting with gameport0, second 'type'
@@ -419,7 +419,7 @@
   Amiga joysticks, connected to an Amiga, are supported by the amijoy.c
 driver. Since they can't be autodetected, the driver has a command line.
 
-	amijoy=a,b
+	amijoy.map=<a>,<b>
 
   a and b define the joysticks connected to the JOY0DAT and JOY1DAT ports of
 the Amiga.
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	Wed Mar 17 19:29:10 2004
+++ b/Documentation/kernel-parameters.txt	Wed Mar 17 19:29:10 2004
@@ -98,6 +98,10 @@
 				strictly ACPI specification compliant.
 
 			See also Documentation/pm.txt.
+
+	acpi_sleep=	[HW,ACPI] Sleep options
+			Format: { s3_bios, s3_mode }
+			See Documentation/power/video.txt
  
 	acpi_pic_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
 			Format: { level | edge }
@@ -158,7 +162,15 @@
 			Format: <host-scsi-id>,<target-scsi-id>,<max-rate>,<max-offset>
 			See also header of drivers/scsi/AM53C974.c.
 
-	amijoy=		[HW,JOY] Amiga joystick support 
+	amijoy.map=	[HW,JOY] Amiga joystick support
+			Map of devices attached to JOY0DAT and JOY1DAT
+			Format: <a>,<b>
+			See also Documentation/kernel/input/joystick.txt
+
+	analog.map=	[HW,JOY] Analog joystick and gamepad support
+			Specifies type or capabilities of an analog joystick
+			connected to one of 16 gameports
+			Format: <type1>,<type2>,..<type16>
 
 	apc=		[HW,SPARC] Power management functions (SPARCstation-4/5 + deriv.)
 			Format: noidle
@@ -181,11 +193,18 @@
 
 	atascsi=	[HW,SCSI] Atari SCSI
 
-	atkbd.set=	[HW] Select keyboard code set
-			Format: <int>
+	atkbd.extra=	[HW] Enable extra LEDs and keys on IBM RapidAccess, EzKey
+			and similar keyboards
+
+	atkbd.reset=	[HW] Reset keyboard during initialization
+
+	atkbd.set=	[HW] Select keyboard code set 
+			Format: <int> (2 = AT (default) 3 = PS/2)
+
+	atkbd.scroll=	[HW] Enable scroll wheel on MS Office and similar keyboards
+	
 	atkbd.softrepeat=
 			[HW] Use software keyboard repeat
-	atkbd.reset=	[HW] Reset keyboard during initialization
 
 	autotest	[IA64]
 
@@ -287,10 +306,11 @@
 	dasd=		[HW,NET]    
 			See header of drivers/s390/block/dasd_devmap.c.
 
-	db9=		[HW,JOY]
-	db9_2=
-	db9_3=
- 
+	db9.dev[2|3]=	[HW,JOY] Multisystem joystick support via parallel port
+			(one device per port)
+			Format: <port#>,<type>
+			See also Documentation/input/joystick-parport.txt
+
 	debug		[KNL] Enable kernel debugging (events log level).
 
 	decnet=		[HW,NET]
@@ -384,12 +404,14 @@
 	ftape=		[HW] Floppy Tape subsystem debugging options.
 			See Documentation/ftape.txt.
 
+	gamecon.map[2|3]=
+			[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
+			support via parallel port (up to 5 devices per port)
+			Format: <port#>,<pad1>,<pad2>,<pad3>,<pad4>,<pad5>
+			See also Documentation/input/joystick-parport.txt
+
 	gamma=		[HW,DRM]
 
-	gc=		[HW,JOY]
-	gc_2=		See Documentation/input/joystick-parport.txt.
-	gc_3=		
- 
 	gdth=		[HW,SCSI]
 			See header of drivers/scsi/gdth.c.
 
@@ -616,9 +638,9 @@
 
 	mga=		[HW,DRM]
 
-	mousedev.xres	[MOUSE] Horizontal screen resolution, used for devices
+	mousedev.xres=	[MOUSE] Horizontal screen resolution, used for devices
 			reporting absolute coordinates, such as tablets
-	mousedev.yres	[MOUSE] Vertical screen resolution, used for devices
+	mousedev.yres=	[MOUSE] Vertical screen resolution, used for devices
 			reporting absolute coordinates, such as tablets
 
 	mpu401=		[HW,OSS]
@@ -1163,10 +1185,6 @@
 			See header of drivers/scsi/t128.c.
 
 	tdfx=		[HW,DRM]
- 
-	tgfx=		[HW,JOY] TurboGraFX parallel port interface
-	tgfx_2=		See Documentation/input/joystick-parport.txt.
-	tgfx_3=
 
 	thash_entries=	[KNL,NET]
 			Set number of hash buckets for TCP connection
@@ -1189,8 +1207,13 @@
 	trix=		[HW,OSS] MediaTrix AudioTrix Pro
 			Format: <io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
  
-	tsdev.xres	[TS] Horizontal screen resolution.
-	tsdev.yres	[TS] Vertical screen resolution.
+	tsdev.xres=	[TS] Horizontal screen resolution.
+	tsdev.yres=	[TS] Vertical screen resolution.
+
+	turbografx.map[2|3]=
+			[HW,JOY] TurboGraFX parallel port interface
+			Format: <port#>,<js1>,<js2>,<js3>,<js4>,<js5>,<js6>,<js7>
+			See also Documentation/input/joystick-parport.txt
 
 	u14-34f=	[HW,SCSI] UltraStor 14F/34F SCSI host adapter
 			See header of drivers/scsi/u14-34f.c.
diff -Nru a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt
--- a/Documentation/networking/e100.txt	Wed Mar 17 19:29:10 2004
+++ b/Documentation/networking/e100.txt	Wed Mar 17 19:29:10 2004
@@ -1,7 +1,7 @@
 Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
 ==============================================================
 
-November 19, 2002
+March 15, 2004
 
 
 Contents
@@ -9,9 +9,6 @@
 
 - In This Release
 - Supported Adapters
-- Command Line Parameters
-- CPU Cycle Saver
-- Additional Configurations
 - Support
 
 
@@ -19,64 +16,13 @@
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
-Adapters, version 2.2.x.  This driver includes support for Itanium(TM)-based 
+Adapters, version 3.x.x.  This driver includes support for Itanium(TM)-based 
 systems.
 
 
 Supported Adapters
 ==================
 
-The following Intel network adapters are compatible with the drivers 
-in this release:
-
-Controller  Adapter Name                            Board IDs
-----------  ------------                            ---------
-
-82558       PRO/100+ PCI Adapter                    668081-xxx, 689661-xxx
-
-82558       PRO/100+ Management Adapter             691334-xxx, 701738-xxx,
-                                                    721383-xxx
-
-82558       PRO/100+ Dual Port Server Adapter       714303-xxx, 711269-xxx, 
-                                                    A28276-xxx
-
-82558       PRO/100+ PCI Server Adapter             710550-xxx
-
-82550       PRO/100 S Server Adapter                752438-xxx (82550)
-82559                                               A56831-xxx, A10563-xxx,
-                                                    A12171-xxx, A12321-xxx, 
-                                                    A12320-xxx, A12170-xxx
-                                                    748568-xxx (82559)
-                                                    748565-xxx (82559)
-
-
-82550       PRO/100 S Desktop Adapter               751767-xxx (82550)
-82559                                               748592-xxx, A12167-xxx, 
-                                                    A12318-xxx, A12317-xxx, 
-                                                    A12165-xxx
-                                                    748569-xxx (82559)
-
-
-
-82559       PRO/100+ Server Adapter                 729757-xxx
-
-82559       PRO/100 S Management Adapter            748566-xxx, 748564-xxx
-
-82550       PRO/100 S Dual Port Server Adapter      A56831-xxx
-
-82551       PRO/100 M Desktop Adapter               A80897-xxx
-
-            PRO/100 S Advanced Management Adapter   747842-xxx, 745171-xxx
-
-CNR         PRO/100 VE Desktop Adapter              A10386-xxx, A10725-xxx, 
-                                                    A23801-xxx, A19716-xxx
-
-
-            PRO/100 VM Desktop Adapter              A14323-xxx, A19725-xxx, 
-                                                    A23801-xxx, A22220-xxx, 
-                                                    A23796-xxx
-   
-
 To verify that your adapter is supported, find the board ID number on the 
 adapter. Look for a label that has a barcode and a number in the format 
 A12345-001. Match this to the list of numbers above.
@@ -89,143 +35,6 @@
 For the latest Intel PRO/100 network driver for Linux, see:
 
   http://downloadfinder.intel.com/scripts-df/support_intel.asp
-
-
-Command Line Parameters
-=======================
-
-If the driver is built as a module, the  following optional parameters are 
-used by entering them on the command line with the modprobe or insmod command
-using this syntax:
-
-     modprobe e100 [<option>=<VAL1>,<VAL2>,...]
-
-     insmod e100 [<option>=<VAL1>,<VAL2>,...] 
-
-For example, with two Intel PRO/100 PCI adapters, entering:
-	
-     modprobe e100 TxDescriptors=32,128
-
-loads the e100 driver with 32 TX resources for the first adapter and 128 TX 
-resources for the second adapter. This configuration favors the second 
-adapter. The driver supports up to 16 network adapters concurrently.
-
-The default value for each parameter is generally the recommended setting,
-unless otherwise noted.
-
-NOTE: Giving any command line option the value "-1" causes the driver to use 
-      the appropriate default value for that option, as if no value was 
-      specified.
-
-
-BundleMax
-Valid Range: 1-65535
-Default Value: 6
-   This parameter holds the maximum number of small packets (less than 128
-   bytes) in a bundle. Suggested values range from 2 to 10. See "CPU Cycle 
-   Saver."
-
-BundleSmallFr
-Valid Range: 0-1 (0=off, 1=on)
-Default Value: 0
-   The value 1 (on) causes small packets (less than 128 bytes) to be bundled. 
-   See "CPU Cycle Saver."
-
-e100_speed_duplex
-Valid Range: 0-4 (1=10half;2=10full;3=100half;4=100full)
-Default Value: 0
-   The default value of 0 sets the adapter to auto-negotiate. Other values
-   set the adapter to forced speed and duplex. 
-   Example usage: insmod e100.o e100_speed_duplex=4,4 (for two adapters)
-
-flow_control
-Valid Range: 0-1 (0=off, 1=on)
-Default Value: 0
-   This parameter controls the automatic generation(Tx) and response(Rx) to 
-   Ethernet PAUSE frames. flow_control should NOT be set to 1 when the 
-   adapter is connected to an interface that does not support Ethernet PAUSE 
-   frames and when the e100_speed_duplex parameter is NOT set to zero. 
-
-IntDelay
-Valid Range: 0-65535 (0=off)
-Default Value: 1536
-   This parameter holds the number of time units (in adapter terminology)
-   until the adapter generates an interrupt. The recommended value for 
-   IntDelay is 1536 (upon initialization). Suggested values range from 
-   512 to 2048. See "CPU Cycle Saver."
-
-IFS
-Valid Range: 0-1 (0=off, 1=on)
-Default Value: 1
-  Inter Frame Spacing (IFS) aims to reduce the number of Ethernet frame
-  collisions by altering the time between frame transmissions. When IFS is 
-  enabled the driver tries to find an optimal IFS value. It is used only at 
-  half duplex.
-
-RxDescriptors
-Valid Range: 8-1024
-Default Value: 64
-   This parameter defines the number of receive descriptors allocated by 
-   the driver. Increasing this value allows the driver to buffer more 
-   incoming packets before the driver is required to service an interrupt. 
-   The maximum value for Itanium-based systems is 64.
-
-TxDescriptors
-Valid Range: 19-1024
-Default Value: 64
-   This value is the number of transmit descriptors allocated by the driver. 
-   Increasing this value allows the protocol stack to queue more transmits at
-   the driver level. The maximum value for Itanium-based systems is 64.
-
-ucode
-Valid Range: 0-1 (0=off, 1=on)
-Default Value: 0 for 82558-based adapters
-               1 for 82559, 82550, and 82551-based adapters
-   On uploads the micro code to the adapter, which enables CPU Cycle Saver. 
-   See the section "CPU Cycle Saver" below.
-   Example usage: insmod e100.o ucode=1
-
-   Not available on 82557-based adapters.
-
-XsumRX
-Valid Range: 0-1 (0=off, 1=on)
-Default Value: 1
-   On allows Rx checksum offloading for TCP/UDP packets. Requires that the 
-   hardware support this feature.
-
-   Not available on 82557 and 82558-based adapters.
-
-
-CPU Cycle Saver
-================
-
-CPU Cycle Saver reduces CPU utilization by reducing the number of interrupts 
-that the adapter generates.
-
-When CPU Cycle Saver is turned off, the adapter generates one interrupt for 
-every frame that is received. This means that the operating system stops what
-it is doing and switches to the network driver in order to process the 
-receive.
-
-When CPU Cycle Saver is on, the adapter does not generate an interrupt for 
-every frame it receives. Instead, it waits until it receives several frames 
-before generating an interrupt. This reduces the amount of time spent 
-switching to and from the driver. 
-
-CPU Cycle Saver consists of these arguments: IntDelay, BundleMax and 
-BundleSmallFr. When IntDelay is increased, the adapter waits longer for 
-frames to arrive before generating the interrupt. By increasing BundleMax, 
-the network adapter waits for the number of small frames (less than 128 bytes)
-specified to arrive before generating the interrupt. When BundleSmallFr is 
-disabled, the adapter does not bundle small packets. Such small packets are 
-often, but not always, control packets that are better served immediately;
-therefore, BundleSmallFr is disabled by default.
-
-For most users, it is recommended that CPU Cycle Saver be used with the 
-default values specified in the Command Line Parameters section. However, in 
-some cases, performance problems may occur with CPU Cycle Saver. If such 
-problems are observed, we recommend turning off this feature by setting 
-ucode=0.
 
 
 Support
diff -Nru a/Documentation/power/tricks.txt b/Documentation/power/tricks.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/power/tricks.txt	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,25 @@
+	swsusp/S3 tricks
+	~~~~~~~~~~~~~~~~
+Pavel Machek <pavel@suse.cz>
+
+If you want to trick swsusp/S3 into working, you might want to try:
+
+* go with minimal config, turn off drivers like USB, AGP you don't
+  really need
+
+* use ext2. At least it has working fsck. [If something seemes to go
+  wrong, force fsck when you have a chance]
+
+* turn off modules
+
+* use vga text console, shut down X. [If you really want X, you might
+  want to try vesafb later]
+
+* try running as few processes as possible, preferably go to single
+  user mode.
+
+* due to video issues, swsusp should be easier to get working than
+  S3. Try that first.
+
+When you make it work, try to find out what exactly was it that broke
+suspend, and preferably fix that.
diff -Nru a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt
--- a/Documentation/s390/driver-model.txt	Wed Mar 17 19:29:09 2004
+++ b/Documentation/s390/driver-model.txt	Wed Mar 17 19:29:09 2004
@@ -250,7 +250,7 @@
 -----------
 
 The netiucv driver creates an attribute 'connection' under
-bus/iucv/drivers/NETIUCV. Piping to this attibute creates a new netiucv
+bus/iucv/drivers/netiucv. Piping to this attibute creates a new netiucv
 connection to the specified host.
 
 Netiucv connections show up under devices/iucv/ as "netiucv<ifnum>". The interface
diff -Nru a/Documentation/usb/acm.txt b/Documentation/usb/acm.txt
--- a/Documentation/usb/acm.txt	Wed Mar 17 19:29:09 2004
+++ b/Documentation/usb/acm.txt	Wed Mar 17 19:29:09 2004
@@ -28,7 +28,7 @@
 
 1. Usage
 ~~~~~~~~
-  The drivers/usb/acm.c drivers works with USB modems and USB ISDN terminal
+  The drivers/usb/class/cdc-acm.c drivers works with USB modems and USB ISDN terminal
 adapters that conform to the Universal Serial Bus Communication Device Class
 Abstract Control Model (USB CDC ACM) specification.
 
@@ -65,9 +65,9 @@
 
   To use the modems you need these modules loaded:
 
-	usbcore.o
-	usb-[uo]hci.o or uhci.o
-	acm.o
+	usbcore.ko
+	uhci-hcd.ko ohci-hcd.ko or ehci-hcd.ko
+	cdc-acm.ko
 
   After that, the modem[s] should be accessible. You should be able to use
 minicom, ppp and mgetty with them.
diff -Nru a/Documentation/usb/brlvger.txt b/Documentation/usb/brlvger.txt
--- a/Documentation/usb/brlvger.txt	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-Kernel Driver for the Tieman Voyager Braille Display (USB)
-
-Authors:
-Stéphane Dalton <sdalton@videotron.ca>
-Stéphane Doyon  <s.doyon@videotron.ca>
-
-Version 0.8, April 17, 2002
-
-The brlvger driver supports a Braille display (aka Braille terminal)
-model Voyager from Tieman.
-
-The driver has been in heavy use for about six months now (as of April
-17th 2002) by a very few users (about 3-4), who say it has worked very
-well for them.
-
-We have tested it with a Voyager 44, but it should also support
-the Voyager 70.
-
-This driver implements a character device which allows userspace programs
-access to the braille displays raw functions. You still need a userspace
-program to perform the screen-review functions and control the
-display. Get BRLTTY from http://mielke.cc/brltty/ (version 2.99.8 or
-later). It has a Voyager driver which interfaces with this kernel driver.
-
-The interface is through a character device, major 180, minor 128, called
-"brlvger" under devfs.
-
-Many thanks to the Tieman people: Corand van Strien, Ivar Illing, Daphne
-Vogelaar and Ingrid Vogel. They provided us with a Braille display (as
-well as programming information) so that we could write this driver. They
-replaced the display when it broke and they answered our technical
-questions. It is very motivating when companies take an interest in such
-projects and are so supportive.
-
-Thanks to Andor Demarteau <ademarte@students.cs.uu.nl> who got this whole
-project started and beta-tested all our early buggy attempts.
diff -Nru a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
--- a/Documentation/usb/error-codes.txt	Wed Mar 17 19:29:09 2004
+++ b/Documentation/usb/error-codes.txt	Wed Mar 17 19:29:09 2004
@@ -70,7 +70,9 @@
 			(That is, if drivers see this it's a bug.)
 
 -EPROTO (*)		a) bitstuff error
-			b) unknown USB error 
+			b) no response packet received within the
+			   prescribed bus turn-around time
+			c) unknown USB error 
 
 -EILSEQ (*)		CRC mismatch
 
diff -Nru a/Documentation/usb/mtouchusb.txt b/Documentation/usb/mtouchusb.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/usb/mtouchusb.txt	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,85 @@
+CHANGES
+
+- Created based off of scanner & INSTALL from the original touchscreen
+  driver on freshmeat (http://freshmeat.net/projects/3mtouchscreendriver)
+- Amended for linux-2.4.18, then 2.4.19
+
+- Complete rewrite using Linux Input in 2.6.3
+   Unfortunately no calibration support at this time
+
+
+DRIVER NOTES:
+
+Installation is simple, you only need to add Linux Input, Linux USB, and the 
+driver to the kernel.  The driver can also be optionally built as a module.
+
+If you have another MicroTouch device that you wish to experiment with
+or try using this driver with, but the Vendor and Product ID's are not 
+coded in, don't despair.  If the driver was compiled as a module, you can 
+pass options to the driver.  Simply try:
+
+  /sbin/modprobe mtouchusb vendor=0x#### product=0x****
+
+If it works, send me the iVendor & iProduct (or a patch) and I will add...
+
+This driver appears to be one of possible 2 Linux USB Input Touchscreen
+drivers.  Although 3M produces a binary only driver available for
+download, I persist in updating this driver since I would like to use the
+touchscreen for embedded apps using QTEmbedded, DirectFB, etc. So I feel the
+logical choice is to use Linux Imput.
+
+A little info about the MicroTouch USB controller (14-206):
+
+Y is inverted, and the device has a total possible resolution of 0 - 65535.
+
+Y is inverted by the driver by:
+
+        input.absmin[ABS_Y] =  MTOUCHUSB_MAX_YC;
+        input.absmax[ABS_Y] =  MTOUCHUSB_MIN_YC;
+
+absmin & absmax are also used to scale the data, sine it is rather high 
+resolution.
+
+    ---------------touch screen area-----------------
+    I                        MicroTouch (xmax,ymax) @I
+    I                      X                         I
+    I   ########visible monitor area##############   I
+    I   #@ (xmin,ymin)                           #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I Y #                                        #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I   #                                        #   I
+    I   #                           (xmax,ymax) @#   I
+    I   ##########################################   I
+    I                                                I
+    I@ MicroTouch (xmin,ymin)                        I
+    -------------------------------------------------
+
+Currently there is no way to calibrate the device via this driver.  Perhaps 
+at some point an abstract function will be placed into evdev so generic 
+functions like calibrations, resets, and vendor information can be requested 
+(And the drivers would handle the vendor specific tasks).
+
+ADDITIONAL INFORMATION/UPDATES:
+
+http://groomlakelabs.com/grandamp/code/microtouch/
+
+TODO:
+
+Implement a control urb again to handle requests to and from the device
+such as calibration, etc.
+
+DISCLAMER:
+
+I am not a MicroTouch/3M employee, nor have I ever been.  3M does not support 
+this driver!  If you want touch drivers only supported within X, please go to:
+
+http://www.3m.com/3MTouchSystems/downloads/
+
diff -Nru a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt
--- a/Documentation/usb/scanner.txt	Wed Mar 17 19:29:10 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,336 +0,0 @@
-Copyright (C) 1999, 2000 David E. Nelson <dnelson@jump.net>
-Updated 2003 by Henning Meier-Geinitz <henning@meier-geinitz.de>
-
-
-OVERVIEW
-
-This README addresses issues regarding how to configure the kernel to access a
-USB scanner.  Although the driver was originally conceived for USB HP
-scanners, it's general enough so that it can be used with most other USB
-scanners.  Also, one can pass the USB Vendor and Product IDs using module
-parameters for unknown scanners.
-
-There are two drivers for SCSI-over-USB scanners: 
-* The "hpusbscsi" module for Hewlett-Packard 53xx series, Hewlett-Packard 7400,
-  Minolta Scan Dual II, Minolta Elite II
-* The "microtek" module for the Microtek Scanmaker X6
-
-In addition to the kernel driver, user-space tools like SANE are necessary to
-actually use the scanner.  SANE ("Scanner Access Now Easy") provides drivers
-for a variety of USB scanners.  See the appropriate SANE man page for details,
-e.g. man sane-usb and man sane-hp (for HP scanners).
-
-NOTE: Just because a product is detected by this driver does not mean that
-applications exist that support the product.  It's in the hopes that this will
-allow developers a means to produce applications that will support the listed
-USB products.
-
-
-ADDITIONAL INFORMATION
-
-http://www.linux-usb.org/           (General information, mailing lists, links)
-http://www.mostang.com/sane/        (SANE user-space tools)
-http://www.meier-geinitz.de/kernel/ (USB scanner driver information and patches)
-
-
-REQUIREMENTS
-
-A host with a USB port.  Ideally, either a UHCI (Intel), OHCI (Compaq and
-others) or EHCI hardware should work.  
-
-Using "make menuconfig" or your preferred method for configuring the kernel,
-select "Support for USB", "OHCI HCD/UHCI HCD/EHCI HCD" depending on your
-hardware, "USB Scanner support", and "USB device filesystem".  Compile and
-install the modules (you may need to execute "depmod -a" to update the module
-dependencies).  If any of the USB sections were compiled into the kernel, a
-reboot is necessary.  NOTE: Updating the boot disk with "lilo" may also be
-required.  Testing was performed only as modules, YMMV.
-
-Up to 16 scanners can be connected/used simultaneously.  If devfs support is
-enabled, see next section.  Otherwise, the device files must be created
-manually if they don't exist yet, either by MAKEDEV or mknod.
-
-MAKEDEV method:
-  cd /dev
-  MAKEDEV usb
-  Check that the device files "/dev/usb/scanner0" - "/dev/usb/scanner15" have
-  been created.
-
-mknod method:
-  mknod /dev/usb/scanner0 c 180 48
-  mknod /dev/usb/scanner1 c 180 49
-                  . 
-                  .
-  mknod /dev/usb/scanner15 c 180 63
-
-Set appropriate permissions for /dev/usb/scanner[0-15] (don't forget
-about group and world permissions).  Both read and write permissions
-are required for proper operation.  For example:
-  chmod 666 /dev/usb/scanner0
-
-Load the appropriate modules (if compiled as modules):
-
-  modprobe ohci-hcd (or uhci-hcd, ehci-hcd)
-  modprobe scanner
-
-
-DEVFS
-
-The later versions of the Linux kernel (2.4.8'ish) included a dynamic
-device filesystem call "devfs".  With devfs, there is no need to
-create the device files as explained above; instead, they are
-dynamically created for you.  For USB Scanner, the device is created
-in /dev/usb/scannerX where X can range from 0 to 15 depending on the
-number of scanners connected to the system.
-
-To see if you have devfs, issue the command "cat /proc/filesytems".
-If devfs is listed you should be ready to go.  You should also have a
-process running called "devfsd".  In order to make sure, issue the
-command "ps aux | grep '[d]evfsd'".
-
-
-CONCLUSION
-
-That's it.  SANE should now be able to access the device.  To make sure the
-device was detected, use "cat /proc/bus/usb/devices".  Your scanner should be
-listed and the line starting with "I:" should look similar to this example:
-
-  I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=usbscanner
-
-The important part is "Driver=usbscanner".  If it reads "Driver=(none)", the
-USB scanner driver didn't recognize the scanner.  Have a look at the MODULE
-PARAMETERS section for what to do in this case.
-
-For more details on the format of "/proc/bus/usb/devices" see
-Documentation/usb/proc_usb_info.txt.
-
-
-MESSAGES
-
-usb_control/bulk_msg: timeout -- On occasions this message will appear
-in "/var/adm/messages", on the console, or both depending on how
-your system is configured.  This is a side effect that scanners are
-sometimes very slow at warming up and/or initializing.  In most cases,
-however, only several of these messages should appear and is generally
-considered to be normal.  
-
-excessive NAK's received -- This message should be considered abnormal
-and generally indicates that the USB system is unable to communicate
-with the scanner for some particular reason.
-
-probe_scanner: Undetected endpoint -- The USB Scanner driver is fairly
-general when it comes to communicating to scanners.  Unfortunately,
-some vendors have designed their scanners in one way or another that
-this driver doesn't account for.
-
-probe_scanner: Endpoint determination failed -- This means that the
-driver is unable to detect a supported configuration for means to
-communicate with the scanner.  See also "probe_scanner: Undetected
-endpoint".
-
-funky result -- Most of the time the data flow between the computer
-and the scanner goes smoothly.  However, due to whatever reason,
-whether it be solar flares or stray neutrons, sometimes the
-communications don't work as expected.  The driver tries to handle
-most types of errors but not all.  When this message is seen,
-something weird happened.  Please contact the mailing list (see
-CONTACT section for details).
-
-
-MODULE PARAMETERS
-
-If you have a device that you wish to experiment with or try using
-this driver with, but the Vendor and Product IDs are not coded in,
-don't despair.  If the driver was compiled as a module, you can pass
-options to the driver.  Simply add 
-
-  options scanner vendor=0x#### product=0x****
-
-to the /etc/modprobe.conf file replacing the #'s and the *'s with the
-correct IDs.  The IDs can be retrieved from the messages file or
-using "cat /proc/bus/usb/devices".
-
-If the default timeout is too low, i.e. there are frequent "timeout" messages,
-you may want to increase the timeout manually by using the parameter
-"read_timeout".  The time is given in seconds.  This is an example for
-modprobe.conf with a timeout of 60 seconds:
-
-  options scanner read_timeout=60
- 
-If the "scanner" module is already loaded into memory, it must be reloaded for
-the module parameters to take effect.  In essence, "rmmod scanner; modprobe
-scanner" must be performed.
-
-
-BUGS
-
-Just look at the list of fixes in the source files. 
-
-
-CONTACT
-
-For asking about problems and fixes, use the linux-usb-users mailing list. For
-patches, linux-usb-devel should be used. Information on both lists can be
-found on http://www.linux-usb.org/.
-
-
-CHANGES
-
-- Amended for linux-2.5.54
-- Added information about read_timeout
-- Added more details about /proc/bus/usb/devices
-- Added/updated links
-- Added pointers two "special" scanner drivers
-- Reordering, spell-checking, formatting
-- Used /dev/usb/scanner[0-15] instead of /dev/usbscanner[0-15]
-- Removed some basic USB configuration stuff
-- Added EHCI
-- Removed some more references to HP
-- Amended for linux-2.4.12
-- Updated devfs support
-- Amended for linux-2.3.99-pre6-3
-- Appended hp_scan.c to end of this README
-- Removed most references to HP
-- Updated uhci/ohci host controller info
-- Updated support for multiple scanner support
-- Updated supported scanners list
-- Updated usbdevfs info
-- Spellcheck
-
-
-HP TEST PROGRAM
-
-There is a small test program (hp_scan.c -- appended below) that can
-be used to test the scanner device if it's an HP scanner that supports
-SCL (Scanner Control Language).  Known HP scanner that support SCL are
-the 4100, 5200, 6200, the 6300 -- note that the 4200 is *not*
-supported since it does not understand SCL; it's also strongly
-suspected that the 3300 and the PhotoSmart S20 are not SCL compliant.
-Hp_scan.c's purpose is to test the driver without having to
-retrieve/configure SANE.  Hp_scan.c will scan the entire bed and put
-the output into a file called "out.dat" in the current directory.  The
-data in the file is raw data so it's not very useful for imaging.
-
---------------- snip -- hp_scan.c -- snip ---------------
-/*
-
-This is a really crude attempt at writing a short test program.  It's
-mostly only to be used to test connectivity with USB HP scanners that
-understand SCL.  Currently, the supported models are 4100C, 5200C,
-6200C, and the 6300C.  Note that the 4200C is *NOT* acceptable.
-
-Copyright (C) David E. Nelson <dnelson@jump.net>, 1999
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <error.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-/*
-   Gray Output produces about a 8945400 byte file.
-   Color Output produces a 26836200 byte file. 
-   
-   To compile: gcc -o hp_scan hp_scan.c
-*/
-
-// #define COLOR /* Undef to scan GrayScale */
-
-int send_cmd(int, const char *, int);
-int read_cmd(int, char *, int);
-
-int
-main(void) {
-
-	ssize_t cnt = 0, total_cnt = 0;
-
-	FILE *fpout;
-
-	int fp;
-	int data_size = 32768;
-
-	char *data;
-
-	static char reset_cmd[] = {'\x1b','E'};
-
-#ifdef COLOR
-	static char data_type_cmd[] = {'\x1b','*','a','5','T'}; /* Color */
-	static char data_width_cmd[] = {'\x1b','*','a','2','4','G'}; /* 24 Bit Color */
-#else
-	static char data_type_cmd[] = {'\x1b','*','a','4','T'}; /* Gray */
-	static char data_width_cmd[] = {'\x1b','*','a','8','G'}; /* 8 Bit Gray */
-#endif
-
-	static char query_cmd[] = {'\x1b', '*', 's', '2', '5', '7', 'E'};
-	static char start_scan_cmd[] = {'\x1b','*','f','0','S'};
-	
-	if(!(data=malloc(data_size))) {
-		perror("malloc failed");
-		exit (1);
-	}
-	
-	if((fp=open("/dev/usb/scanner0", O_RDWR)) < 0) {
-		perror("Unable to open scanner device");
-		exit (1);
-	}
-
-	if((fpout=fopen("out.dat", "w+")) == NULL) {
-		perror("Unable to open output file");
-		exit(1);
-	}
-
-	send_cmd(fp, reset_cmd, sizeof(reset_cmd));
-	send_cmd(fp, data_type_cmd, sizeof(data_type_cmd));
-	send_cmd(fp, data_width_cmd, sizeof(data_width_cmd));
-	send_cmd(fp, start_scan_cmd, sizeof(start_scan_cmd));
-
-	while ((cnt = read(fp, data, data_size)) > 0) {
-		printf("Read: %u\n", cnt); 
-		if(fwrite(data, sizeof(char), cnt, fpout) < 0) {
-			perror("Write to output file failed");
-			exit (1);
-		}
-		total_cnt += cnt;
-	}
-	if (cnt < 0) {
-		perror("Read from scanner failed");
-		exit (1);
-	}
-
-	printf("\nRead %lu bytes.\n", total_cnt);
-
-	send_cmd(fp, reset_cmd, sizeof(reset_cmd));
-
-	close(fp);
-	fclose(fpout);
-	return (0);
-}
-
-int
-send_cmd(int fp, const char * cmd, int length) {
-
-	int result;
-	int x;
-
-	if((result = write(fp, cmd, length)) != length) {
-		printf ("Write warning: %d bytes requested, %d written\n");
-	} else if (result < 0) {
-		perror ("send_cmd failure");
-		exit (1);
-	}
-	return (result);
-}
-	
-int
-read_cmd(int fp, char * response, int length) {
-
-	return read(fp, response, length);
-
-}
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Wed Mar 17 19:29:09 2004
+++ b/MAINTAINERS	Wed Mar 17 19:29:09 2004
@@ -1966,13 +1966,6 @@
 M:     roms@lpg.ticalc.org
 S:     Maintained
 
-TIEMAN VOYAGER USB BRAILLE DISPLAY DRIVER
-P:	Stephane Dalton
-M:	sdalton@videotron.ca
-P:	Stéphane Doyon
-M:	s.doyon@videotron.ca
-S:	Maintained
-
 TLAN NETWORK DRIVER
 P:	Samuel Chessman
 M:	chessman@tux.org
@@ -2150,14 +2143,6 @@
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 W:	http://pegasus2.sourceforge.net/
-S:	Maintained
-
-USB SCANNER DRIVER
-P:	Henning Meier-Geinitz
-M:	henning@meier-geinitz.de
-L:	linux-usb-users@lists.sourceforge.net
-L:	linux-usb-devel@lists.sourceforge.net
-W:	http://www.meier-geinitz.de/kernel/
 S:	Maintained
 
 USB SE401 DRIVER
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Wed Mar 17 19:29:09 2004
+++ b/Makefile	Wed Mar 17 19:29:09 2004
@@ -304,17 +304,10 @@
 # ===========================================================================
 # Rules shared between *config targets and build targets
 
-# Helpers built in scripts/
-
-scripts/docproc scripts/split-include : scripts ;
-
-.PHONY: scripts scripts/fixdep
-scripts:
-	$(Q)$(MAKE) $(build)=scripts
-
-scripts/fixdep:
-	$(Q)$(MAKE) $(build)=scripts $@
-
+# Basic helpers built in scripts/
+.PHONY: scripts_basic
+scripts_basic:
+	$(Q)$(MAKE) $(build)=scripts/basic
 
 # To make sure we do not include .config for any of the *config targets
 # catch them early, and hand them over to scripts/kconfig/Makefile
@@ -358,9 +351,9 @@
 # *config targets only - make sure prerequisites are updated, and descend
 # in scripts/kconfig to make the *config target
 
-%config: scripts/fixdep FORCE
+config: scripts_basic FORCE
 	$(Q)$(MAKE) $(build)=scripts/kconfig $@
-config : scripts/fixdep FORCE
+%config: scripts_basic FORCE
 	$(Q)$(MAKE) $(build)=scripts/kconfig $@
 
 else
@@ -368,6 +361,16 @@
 # Build targets only - this includes vmlinux, arch specific targets, clean
 # targets and others. In general all targets except *config targets.
 
+# Additional helpers built in scripts/
+# Carefully list dependencies so we do not try to build scripts twice
+# in parrallel
+.PHONY: scripts
+scripts: scripts_basic include/config/MARKER
+	$(Q)$(MAKE) $(build)=$(@)
+
+scripts_basic: include/linux/autoconf.h
+
+
 # That's our default target when none is given on the command line
 # Note that 'modules' will be added as a prerequisite as well, 
 # in the CONFIG_MODULES part below
@@ -400,7 +403,9 @@
 # with it and forgot to run make oldconfig
 include/linux/autoconf.h: .config
 	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
-
+else
+# Dummy target needed, because used as prerequisite
+include/linux/autoconf.h: ;
 endif
 
 include $(srctree)/arch/$(ARCH)/Makefile
@@ -633,9 +638,9 @@
 
 # 	Split autoconf.h into include/linux/config/*
 
-include/config/MARKER: scripts/split-include include/linux/autoconf.h
+include/config/MARKER: include/linux/autoconf.h
 	@echo '  SPLIT   include/linux/autoconf.h -> include/config/*'
-	@scripts/split-include include/linux/autoconf.h include/config
+	@scripts/basic/split-include include/linux/autoconf.h include/config
 	@touch $@
 
 # Generate some files
@@ -929,7 +934,7 @@
 
 # Documentation targets
 # ---------------------------------------------------------------------------
-%docs: scripts/docproc FORCE
+%docs: scripts FORCE
 	$(Q)$(MAKE) $(build)=Documentation/DocBook $@
 
 # Scripts to check various things for consistency
@@ -982,7 +987,7 @@
 	@set -e; \
 	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
 	$(cmd_$(1)); \
-	scripts/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
+	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
 	rm -f $(depfile); \
 	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
 
diff -Nru a/arch/arm/configs/a5k_defconfig b/arch/arm/configs/a5k_defconfig
--- a/arch/arm/configs/a5k_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/a5k_defconfig	Wed Mar 17 19:29:09 2004
@@ -317,9 +317,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_ALGOPCF is not set
 CONFIG_I2C_CHARDEV=y
 
diff -Nru a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
--- a/arch/arm/configs/badge4_defconfig	Wed Mar 17 19:29:10 2004
+++ b/arch/arm/configs/badge4_defconfig	Wed Mar 17 19:29:10 2004
@@ -690,9 +690,6 @@
 #
 CONFIG_I2C=m
 CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_PHILIPSPAR is not set
-CONFIG_I2C_ELV=m
-CONFIG_I2C_VELLEMAN=m
 # CONFIG_I2C_BIT_SA1100_GPIO is not set
 CONFIG_I2C_ALGOPCF=m
 CONFIG_I2C_ELEKTOR=m
@@ -735,7 +732,6 @@
 CONFIG_SA1100_WATCHDOG=m
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_60XX_WDT is not set
 # CONFIG_W83877F_WDT is not set
diff -Nru a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig
--- a/arch/arm/configs/cerfcube_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/cerfcube_defconfig	Wed Mar 17 19:29:09 2004
@@ -573,7 +573,6 @@
 CONFIG_SA1100_WATCHDOG=m
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_SCx200_WDT is not set
 # CONFIG_60XX_WDT is not set
diff -Nru a/arch/arm/configs/clps7500_defconfig b/arch/arm/configs/clps7500_defconfig
--- a/arch/arm/configs/clps7500_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/clps7500_defconfig	Wed Mar 17 19:29:09 2004
@@ -340,9 +340,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_ALGOPCF is not set
 # CONFIG_I2C_CHARDEV is not set
 
diff -Nru a/arch/arm/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig
--- a/arch/arm/configs/ebsa110_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/ebsa110_defconfig	Wed Mar 17 19:29:09 2004
@@ -475,7 +475,6 @@
 # CONFIG_ADVANTECH_WDT is not set
 # CONFIG_60XX_WDT is not set
 # CONFIG_MIXCOMWD is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MACHZ_WDT is not set
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
diff -Nru a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig
--- a/arch/arm/configs/footbridge_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/footbridge_defconfig	Wed Mar 17 19:29:09 2004
@@ -525,7 +525,6 @@
 # CONFIG_ACQUIRE_WDT is not set
 # CONFIG_60XX_WDT is not set
 # CONFIG_MIXCOMWD is not set
-# CONFIG_I810_TCO is not set
 CONFIG_21285_WATCHDOG=m
 CONFIG_977_WATCHDOG=m
 CONFIG_DS1620=y
diff -Nru a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
--- a/arch/arm/configs/neponset_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/neponset_defconfig	Wed Mar 17 19:29:09 2004
@@ -500,8 +500,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_SCx200_ACB is not set
 CONFIG_I2C_BIT_SA1100_GPIO=y
 # CONFIG_I2C_ALGOPCF is not set
@@ -536,7 +534,6 @@
 CONFIG_SA1100_WATCHDOG=m
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_SCx200_WDT is not set
 # CONFIG_60XX_WDT is not set
diff -Nru a/arch/arm/configs/netwinder_defconfig b/arch/arm/configs/netwinder_defconfig
--- a/arch/arm/configs/netwinder_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/netwinder_defconfig	Wed Mar 17 19:29:09 2004
@@ -617,7 +617,6 @@
 CONFIG_977_WATCHDOG=y
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_SCx200_WDT is not set
 # CONFIG_60XX_WDT is not set
diff -Nru a/arch/arm/configs/pfs168_mqtft_defconfig b/arch/arm/configs/pfs168_mqtft_defconfig
--- a/arch/arm/configs/pfs168_mqtft_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/pfs168_mqtft_defconfig	Wed Mar 17 19:29:09 2004
@@ -506,9 +506,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_ASSABET is not set
 CONFIG_I2C_PFS168=y
 # CONFIG_I2C_ALGOPCF is not set
diff -Nru a/arch/arm/configs/pfs168_mqvga_defconfig b/arch/arm/configs/pfs168_mqvga_defconfig
--- a/arch/arm/configs/pfs168_mqvga_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/pfs168_mqvga_defconfig	Wed Mar 17 19:29:09 2004
@@ -506,9 +506,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_ASSABET is not set
 CONFIG_I2C_PFS168=y
 # CONFIG_I2C_ALGOPCF is not set
diff -Nru a/arch/arm/configs/pfs168_sastn_defconfig b/arch/arm/configs/pfs168_sastn_defconfig
--- a/arch/arm/configs/pfs168_sastn_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/pfs168_sastn_defconfig	Wed Mar 17 19:29:09 2004
@@ -507,9 +507,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_ASSABET is not set
 # CONFIG_I2C_ALGOPCF is not set
 CONFIG_I2C_CHARDEV=y
diff -Nru a/arch/arm/configs/pfs168_satft_defconfig b/arch/arm/configs/pfs168_satft_defconfig
--- a/arch/arm/configs/pfs168_satft_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/pfs168_satft_defconfig	Wed Mar 17 19:29:09 2004
@@ -506,9 +506,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_ASSABET is not set
 CONFIG_I2C_PFS168=y
 # CONFIG_I2C_ALGOPCF is not set
diff -Nru a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig
--- a/arch/arm/configs/rpc_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/rpc_defconfig	Wed Mar 17 19:29:09 2004
@@ -462,9 +462,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_ALGOPCF is not set
 CONFIG_I2C_CHARDEV=y
diff -Nru a/arch/arm/configs/shannon_defconfig b/arch/arm/configs/shannon_defconfig
--- a/arch/arm/configs/shannon_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/shannon_defconfig	Wed Mar 17 19:29:09 2004
@@ -476,7 +476,6 @@
 CONFIG_SA1100_WATCHDOG=y
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_60XX_WDT is not set
 # CONFIG_W83877F_WDT is not set
diff -Nru a/arch/arm/configs/trizeps_defconfig b/arch/arm/configs/trizeps_defconfig
--- a/arch/arm/configs/trizeps_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm/configs/trizeps_defconfig	Wed Mar 17 19:29:09 2004
@@ -624,9 +624,6 @@
 #
 CONFIG_I2C=m
 CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_SCx200_I2C is not set
 # CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_BIT_SA1100_GPIO is not set
diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig
--- a/arch/arm26/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm26/Kconfig	Wed Mar 17 19:29:09 2004
@@ -198,11 +198,6 @@
 
 source "drivers/char/Kconfig"
 
-config KBDMOUSE
-	bool
-	depends on ARCH_ACORN && BUSMOUSE=y
-	default y
-
 source "drivers/media/Kconfig"
 
 source "fs/Kconfig"
diff -Nru a/arch/arm26/defconfig b/arch/arm26/defconfig
--- a/arch/arm26/defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/arm26/defconfig	Wed Mar 17 19:29:09 2004
@@ -185,9 +185,6 @@
 #
 CONFIG_I2C=y
 CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_PHILIPSPAR is not set
-# CONFIG_I2C_ELV is not set
-# CONFIG_I2C_VELLEMAN is not set
 CONFIG_I2C_ALGOPCF=y
 # CONFIG_I2C_ELEKTOR is not set
 CONFIG_I2C_CHARDEV=y
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/i386/Kconfig	Wed Mar 17 19:29:09 2004
@@ -1055,9 +1055,6 @@
 	prompt "PCI access mode"
 	depends on PCI && !X86_VISWS
 	default PCI_GOANY
-
-config PCI_GOBIOS
-	bool "BIOS"
 	---help---
 	  On PCI systems, the BIOS can be used to detect the PCI devices and
 	  determine their configuration. However, some old PCI motherboards
@@ -1072,6 +1069,9 @@
 	  If you choose "Any", the kernel will try MMCONFIG, then the
 	  direct access method and falls back to the BIOS if that doesn't
 	  work. If unsure, go with the default, which is "Any".
+
+config PCI_GOBIOS
+	bool "BIOS"
 
 config PCI_GOMMCONFIG
 	bool "MMConfig"
diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig
--- a/arch/i386/defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/i386/defconfig	Wed Mar 17 19:29:09 2004
@@ -66,7 +66,6 @@
 # CONFIG_MK6 is not set
 # CONFIG_MK7 is not set
 # CONFIG_MK8 is not set
-# CONFIG_MELAN is not set
 # CONFIG_MCRUSOE is not set
 # CONFIG_MWINCHIPC6 is not set
 # CONFIG_MWINCHIP2 is not set
@@ -141,7 +140,6 @@
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_RELAXED_AML is not set
 # CONFIG_X86_PM_TIMER is not set
 
 #
diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	Wed Mar 17 19:29:09 2004
+++ b/arch/i386/kernel/dmi_scan.c	Wed Mar 17 19:29:09 2004
@@ -525,7 +525,7 @@
 #ifdef	CONFIG_ACPI_BOOT
 extern int acpi_disabled, acpi_force;
 
-static __init __attribute__((unused)) int acpi_disable(struct dmi_blacklist *d) 
+static __init __attribute__((unused)) int disable_acpi(struct dmi_blacklist *d)
 { 
 	if (!acpi_force) { 
 		printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); 
@@ -933,7 +933,7 @@
 	 *	Boxes that need ACPI disabled
 	 */
 
-	{ acpi_disable, "IBM Thinkpad", {
+	{ disable_acpi, "IBM Thinkpad", {
 			MATCH(DMI_BOARD_VENDOR, "IBM"),
 			MATCH(DMI_BOARD_NAME, "2629H1G"),
 			NO_MATCH, NO_MATCH }},
diff -Nru a/arch/i386/kernel/vsyscall-int80.S b/arch/i386/kernel/vsyscall-int80.S
--- a/arch/i386/kernel/vsyscall-int80.S	Wed Mar 17 19:29:10 2004
+++ b/arch/i386/kernel/vsyscall-int80.S	Wed Mar 17 19:29:10 2004
@@ -1,5 +1,10 @@
 /*
  * Code for the vsyscall page.  This version uses the old int $0x80 method.
+ *
+ * NOTE:
+ * 1) __kernel_vsyscall _must_ be first in this page.
+ * 2) there are alignment constraints on this stub, see vsyscall-sigreturn.S
+ *    for details.
  */
 
 	.text
diff -Nru a/arch/i386/kernel/vsyscall-sigreturn.S b/arch/i386/kernel/vsyscall-sigreturn.S
--- a/arch/i386/kernel/vsyscall-sigreturn.S	Wed Mar 17 19:29:10 2004
+++ b/arch/i386/kernel/vsyscall-sigreturn.S	Wed Mar 17 19:29:10 2004
@@ -2,8 +2,8 @@
  * Common code for the sigreturn entry points on the vsyscall page.
  * So far this code is the same for both int80 and sysenter versions.
  * This file is #include'd by vsyscall-*.S to define them after the
- * vsyscall entry point.  The addresses we get for these entry points
- * by doing ".balign 32" must match in both versions of the page.
+ * vsyscall entry point.  The kernel assumes that the addresses of these
+ * routines are constant for all vsyscall implementations.
  */
 
 #include <asm/unistd.h>
@@ -15,7 +15,7 @@
 */
 
 	.text
-	.balign 32
+	.org	__kernel_vsyscall+32
 	.globl __kernel_sigreturn
 	.type __kernel_sigreturn,@function
 __kernel_sigreturn:
diff -Nru a/arch/i386/kernel/vsyscall-sysenter.S b/arch/i386/kernel/vsyscall-sysenter.S
--- a/arch/i386/kernel/vsyscall-sysenter.S	Wed Mar 17 19:29:09 2004
+++ b/arch/i386/kernel/vsyscall-sysenter.S	Wed Mar 17 19:29:09 2004
@@ -1,5 +1,10 @@
 /*
  * Code for the vsyscall page.  This version uses the sysenter instruction.
+ *
+ * NOTE:
+ * 1) __kernel_vsyscall _must_ be first in this page.
+ * 2) there are alignment constraints on this stub, see vsyscall-sigreturn.S
+ *    for details.
  */
 
 	.text
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/arch/ia64/Kconfig	Wed Mar 17 19:29:10 2004
@@ -39,24 +39,6 @@
 	default y
 
 choice
-	prompt "Processor type"
-	default ITANIUM
-
-config ITANIUM
-	bool "Itanium"
-	help
-	  Select your IA-64 processor type.  The default is Itanium.
-	  This choice is safe for all IA-64 systems, but may not perform
-	  optimally on systems with, say, Itanium 2 or newer processors.
-
-config MCKINLEY
-	bool "Itanium 2"
-	help
-	  Select this to configure for an Itanium 2 (McKinley) processor.
-
-endchoice
-
-choice
 	prompt "System type"
 	default IA64_GENERIC
 
@@ -97,6 +79,24 @@
 endchoice
 
 choice
+	prompt "Processor type"
+	default ITANIUM
+
+config ITANIUM
+	bool "Itanium"
+	help
+	  Select your IA-64 processor type.  The default is Itanium.
+	  This choice is safe for all IA-64 systems, but may not perform
+	  optimally on systems with, say, Itanium 2 or newer processors.
+
+config MCKINLEY
+	bool "Itanium 2"
+	help
+	  Select this to configure for an Itanium 2 (McKinley) processor.
+
+endchoice
+
+choice
 	prompt "Kernel page size"
 	default IA64_PAGE_SIZE_16KB
 
@@ -129,52 +129,6 @@
 
 endchoice
 
-config ACPI
-	bool
-	depends on !IA64_HP_SIM
-	default y
-	help
-	  ACPI/OSPM support for Linux is currently under development. As such,
-	  this support is preliminary and EXPERIMENTAL.  Configuring ACPI
-	  support enables kernel interfaces that allow higher level software
-	  (OSPM) to manipulate ACPI defined hardware and software interfaces,
-	  including the evaluation of ACPI control methods.  If unsure, choose
-	  N here.  Note, this option will enlarge your kernel by about 120K.
-
-	  This support requires an ACPI compliant platform (hardware/firmware).
-	  If both ACPI and Advanced Power Management (APM) support are
-	  configured, whichever is loaded first shall be used.
-
-	  This code DOES NOT currently provide a complete OSPM implementation
-	  -- it has not yet reached APM's level of functionality.  When fully
-	  implemented, Linux ACPI/OSPM will provide a more robust functional
-	  replacement for legacy configuration and power management
-	  interfaces, including the Plug-and-Play BIOS specification (PnP
-	  BIOS), the Multi-Processor Specification (MPS), and the Advanced
-	  Power Management specification (APM).
-
-	  Linux support for ACPI/OSPM is based on Intel Corporation's ACPI
-	  Component Architecture (ACPI CA). The latest ACPI CA source code,
-	  documentation, debug builds, and implementation status information
-	  can be downloaded from:
-	  <http://developer.intel.com/technology/iapc/acpi/downloads.htm>.
-
-	  The ACPI Sourceforge project may also be of interest:
-	  <http://sf.net/projects/acpi/>
-
-config ACPI_INTERPRETER
-	bool
-	depends on !IA64_HP_SIM
-	default y
-
-config ACPI_KERNEL_CONFIG
-	bool
-	depends on !IA64_HP_SIM
-	default y
-	help
-	  If you say `Y' here, Linux's ACPI support will use the
-	  hardware-level system descriptions found on IA-64 systems.
-
 config IA64_BRL_EMU
 	bool
 	depends on ITANIUM
@@ -238,40 +192,12 @@
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
 
-config IA64_MCA
-	bool "Machine Check Abort"
-	default y if !IA64_HP_SIM
-	help
-	  Say Y here to enable machine check support for IA-64.  If you're
-	  unsure, answer Y.
-
 config IA64_CYCLONE
 	bool "Support Cyclone(EXA) Time Source"
 	help
 		Say Y here to enable support for IBM EXA Cyclone time source.
 		If you're unsure, answer N.
 
-config PM
-	bool "Power Management support"
-	depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
-	default y
-	help
-	  "Power Management" means that parts of your computer are shut
-	  off or put into a power conserving "sleep" mode if they are not
-	  being used.  There are two competing standards for doing this: APM
-	  and ACPI.  If you want to use either one, say Y here and then also
-	  to the requisite support below.
-
-	  Power Management is most important for battery powered laptop
-	  computers; if you have a laptop, check out the Linux Laptop home
-	  page on the WWW at <http://www.linux-on-laptops.com/> and the
-	  Battery Powered Linux mini-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  Note that, even if you say N here, Linux on the x86 architecture
-	  will issue the hlt instruction if nothing is to be done, thereby
-	  sending the processor to sleep and saving power.
-
 config IOSAPIC
 	bool
 	depends on !IA64_HP_SIM
@@ -389,10 +315,89 @@
 
 source "fs/Kconfig.binfmt"
 
+endmenu
+
+menu "Power management and ACPI"
+
+config PM
+	bool "Power Management support"
+	depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1
+	default y
+	help
+	  "Power Management" means that parts of your computer are shut
+	  off or put into a power conserving "sleep" mode if they are not
+	  being used.  There are two competing standards for doing this: APM
+	  and ACPI.  If you want to use either one, say Y here and then also
+	  to the requisite support below.
+
+	  Power Management is most important for battery powered laptop
+	  computers; if you have a laptop, check out the Linux Laptop home
+	  page on the WWW at <http://www.linux-on-laptops.com/> and the
+	  Battery Powered Linux mini-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  Note that, even if you say N here, Linux on the x86 architecture
+	  will issue the hlt instruction if nothing is to be done, thereby
+	  sending the processor to sleep and saving power.
+
+config ACPI
+	bool
+	depends on !IA64_HP_SIM
+	default y
+	help
+	  ACPI/OSPM support for Linux is currently under development. As such,
+	  this support is preliminary and EXPERIMENTAL.  Configuring ACPI
+	  support enables kernel interfaces that allow higher level software
+	  (OSPM) to manipulate ACPI defined hardware and software interfaces,
+	  including the evaluation of ACPI control methods.  If unsure, choose
+	  N here.  Note, this option will enlarge your kernel by about 120K.
+
+	  This support requires an ACPI compliant platform (hardware/firmware).
+	  If both ACPI and Advanced Power Management (APM) support are
+	  configured, whichever is loaded first shall be used.
+
+	  This code DOES NOT currently provide a complete OSPM implementation
+	  -- it has not yet reached APM's level of functionality.  When fully
+	  implemented, Linux ACPI/OSPM will provide a more robust functional
+	  replacement for legacy configuration and power management
+	  interfaces, including the Plug-and-Play BIOS specification (PnP
+	  BIOS), the Multi-Processor Specification (MPS), and the Advanced
+	  Power Management specification (APM).
+
+	  Linux support for ACPI/OSPM is based on Intel Corporation's ACPI
+	  Component Architecture (ACPI CA). The latest ACPI CA source code,
+	  documentation, debug builds, and implementation status information
+	  can be downloaded from:
+	  <http://developer.intel.com/technology/iapc/acpi/downloads.htm>.
+
+	  The ACPI Sourceforge project may also be of interest:
+	  <http://sf.net/projects/acpi/>
+
+config ACPI_INTERPRETER
+	bool
+	depends on !IA64_HP_SIM
+	default y
+
+config ACPI_KERNEL_CONFIG
+	bool
+	depends on !IA64_HP_SIM
+	default y
+	help
+	  If you say `Y' here, Linux's ACPI support will use the
+	  hardware-level system descriptions found on IA-64 systems.
+
 if !IA64_HP_SIM
 
 source "drivers/acpi/Kconfig"
 
+endif
+
+endmenu
+
+if !IA64_HP_SIM
+
+menu "Bus options (PCI, PCMCIA)"
+
 config PCI
 	bool "PCI support"
 	help
@@ -416,9 +421,9 @@
 
 source "drivers/pcmcia/Kconfig"
 
-endif
-
 endmenu
+
+endif
 
 source "drivers/Kconfig"
 
diff -Nru a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
--- a/arch/ia64/configs/generic_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/configs/generic_defconfig	Wed Mar 17 19:29:09 2004
@@ -105,7 +105,6 @@
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_RELAXED_AML is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_LEGACY_PROC=y
@@ -239,7 +238,6 @@
 CONFIG_MD_RAID5=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=m
-CONFIG_DM_IOCTL_V4=y
 
 #
 # Fusion MPT device support
diff -Nru a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
--- a/arch/ia64/configs/sn2_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/configs/sn2_defconfig	Wed Mar 17 19:29:09 2004
@@ -17,6 +17,7 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_LOG_BUF_SHIFT=20
+CONFIG_HOTPLUG=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
@@ -30,7 +31,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
 
 #
 # Processor type and features
@@ -40,13 +47,14 @@
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_TIME_INTERPOLATION=y
+CONFIG_EFI=y
 # CONFIG_ITANIUM is not set
 CONFIG_MCKINLEY=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
-# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
 CONFIG_IA64_SGI_SN2=y
+# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -57,23 +65,23 @@
 CONFIG_IA64_L1_CACHE_SHIFT=7
 # CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set
 CONFIG_NUMA=y
-CONFIG_DISCONTIGMEM=y
 CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_DISCONTIGMEM=y
 CONFIG_IA64_MCA=y
+# CONFIG_IA64_CYCLONE is not set
 CONFIG_IOSAPIC=y
 # CONFIG_IA64_SGI_SN_SIM is not set
 CONFIG_FORCE_MAX_ZONEORDER=18
 # CONFIG_IA64_PAL_IDLE is not set
 CONFIG_SMP=y
+CONFIG_NR_CPUS=512
 # CONFIG_PREEMPT is not set
+CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
-CONFIG_HAVE_DEC_LOCK=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
-CONFIG_EFI=y
-# CONFIG_EFI_VARS is not set
-CONFIG_NR_CPUS=512
+CONFIG_EFI_VARS=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 
@@ -90,12 +98,10 @@
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_RELAXED_AML is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
-CONFIG_HOTPLUG=y
 
 #
 # PCI Hotplug Support
@@ -108,14 +114,14 @@
 # CONFIG_PCMCIA is not set
 
 #
-# Parallel port support
+# Device Drivers
 #
-# CONFIG_PARPORT is not set
 
 #
 # Generic Driver Options
 #
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -123,9 +129,13 @@
 # CONFIG_MTD is not set
 
 #
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -133,13 +143,15 @@
 # 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
-# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_CARMEL is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -150,21 +162,24 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
-# CONFIG_BLK_DEV_IDEDISK is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_IDEDISK_STROKE is not set
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=m
 # 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=y
 CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
+CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
@@ -174,19 +189,20 @@
 # 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 is not set
+CONFIG_BLK_DEV_CMD64X=m
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
 # CONFIG_BLK_DEV_CS5520 is not set
 # CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
+CONFIG_BLK_DEV_HPT34X=m
+CONFIG_HPT34X_AUTODMA=y
+CONFIG_BLK_DEV_HPT366=m
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SVWKS=m
 CONFIG_BLK_DEV_SGIIOC4=y
 # CONFIG_BLK_DEV_SIIMAGE is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
@@ -199,26 +215,6 @@
 # CONFIG_BLK_DEV_HD is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
 # SCSI device support
 #
 CONFIG_SCSI=y
@@ -228,31 +224,56 @@
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_REPORT_LUNS=y
-# CONFIG_SCSI_CONSTANTS is not set
+CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
 #
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID 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_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+CONFIG_AIC79XX_DEBUG_ENABLE=y
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
+CONFIG_SCSI_MEGARAID=m
+CONFIG_SCSI_SATA=y
+CONFIG_SCSI_SATA_SVW=m
+CONFIG_SCSI_ATA_PIIX=m
+CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_VIA=m
+CONFIG_SCSI_SATA_VITESSE=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
@@ -262,16 +283,58 @@
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
+CONFIG_SCSI_SYM53C8XX_2=m
+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_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 CONFIG_SCSI_QLOGIC_1280=y
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+CONFIG_SCSI_QLA22XX=y
+CONFIG_SCSI_QLA2300=y
+CONFIG_SCSI_QLA2322=y
+CONFIG_SCSI_QLA6312=y
+CONFIG_SCSI_QLA6322=y
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_RAID6 is not set
+CONFIG_MD_MULTIPATH=y
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=m
+CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_ISENSE=m
+CONFIG_FUSION_CTL=m
+# CONFIG_FUSION_LAN is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -280,41 +343,133 @@
 # Networking options
 #
 CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
+CONFIG_PACKET_MMAP=y
 CONFIG_NETLINK_DEV=y
 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_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_NAT=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_TOS=y
+CONFIG_IP_ROUTE_VERBOSE=y
 # CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
 CONFIG_ARPD=y
 # CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_TUNNEL=m
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NETFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=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_RECENT=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_HELPER=m
+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_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=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_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+# CONFIG_IP_NF_NAT_LOCAL is not set
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+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_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
+CONFIG_IPV6_SCTP__=m
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
+CONFIG_VLAN_8021Q=m
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
+CONFIG_NET_DIVERT=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -323,7 +478,30 @@
 #
 # QoS and/or fair queueing
 #
-# CONFIG_NET_SCHED is not set
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_INGRESS is not set
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_POLICE=y
 
 #
 # Network testing
@@ -335,29 +513,70 @@
 # 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_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
 # CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-# CONFIG_NET_ETHERNET is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+# 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_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_VIA_RHINE is not set
 
 #
 # Ethernet (1000 Mbit)
 #
-# 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_SIS190 is not set
-# CONFIG_SK98LIN is not set
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_SIS190=m
+CONFIG_SK98LIN=m
 CONFIG_TIGON3=y
 
 #
@@ -366,7 +585,14 @@
 # CONFIG_IXGB is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
 
 #
@@ -378,8 +604,9 @@
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_NET_FC is not set
+CONFIG_NET_FC=y
 # CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # Wan interfaces
@@ -400,11 +627,18 @@
 # Bluetooth support
 #
 # CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -465,31 +699,21 @@
 #
 # Serial drivers
 #
-# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_HCDP=y
+CONFIG_SERIAL_8250_ACPI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
 # Non-8250 serial port support
 #
+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 Algorithms
-#
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 
 #
 # Mice
@@ -507,7 +731,6 @@
 #
 # 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
@@ -522,6 +745,15 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -532,20 +764,60 @@
 # CONFIG_DVB is not set
 
 #
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
 # File systems
 #
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_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_FS_POSIX_ACL=y
 CONFIG_XFS_FS=y
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_POSIX_ACL is not set
+CONFIG_XFS_RT=y
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
+CONFIG_QUOTA=y
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
 
@@ -571,11 +843,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 # CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR 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
 
 #
@@ -584,6 +855,7 @@
 # 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
@@ -609,12 +881,12 @@
 CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -633,7 +905,7 @@
 # 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_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 CONFIG_EFI_PARTITION=y
@@ -682,32 +954,11 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
-# 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
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
 # Library routines
 #
 CONFIG_CRC32=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
 
 #
 # Profiling support
@@ -717,16 +968,12 @@
 #
 # Kernel hacking
 #
-# CONFIG_IA64_GRANULE_16MB is not set
-CONFIG_IA64_GRANULE_64MB=y
+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_IA64_EARLY_PRINTK=y
-# CONFIG_IA64_EARLY_PRINTK_UART is not set
-# CONFIG_IA64_EARLY_PRINTK_VGA is not set
-CONFIG_IA64_EARLY_PRINTK_SGI_SN=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
@@ -742,4 +989,21 @@
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+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 is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_ARC4 is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_TEST is not set
diff -Nru a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
--- a/arch/ia64/configs/zx1_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/configs/zx1_defconfig	Wed Mar 17 19:29:09 2004
@@ -101,7 +101,6 @@
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_RELAXED_AML is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_LEGACY_PROC=y
@@ -619,7 +618,6 @@
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_ELV is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
@@ -631,7 +629,6 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig
--- a/arch/ia64/defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/defconfig	Wed Mar 17 19:29:09 2004
@@ -19,6 +19,7 @@
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_SYSCTL=y
 CONFIG_LOG_BUF_SHIFT=16
+CONFIG_HOTPLUG=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
@@ -39,6 +40,7 @@
 CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
 CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
 
 #
 # Processor type and features
@@ -49,37 +51,24 @@
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
-# CONFIG_ITANIUM is not set
-CONFIG_MCKINLEY=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 is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
@@ -94,6 +83,14 @@
 CONFIG_BINFMT_MISC=y
 
 #
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_KERNEL_CONFIG=y
+
+#
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI_BOOT=y
@@ -106,12 +103,14 @@
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_ACPI_RELAXED_AML is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
-CONFIG_HOTPLUG=y
 
 #
 # PCI Hotplug Support
@@ -124,14 +123,14 @@
 # CONFIG_PCMCIA is not set
 
 #
-# Parallel port support
+# Device Drivers
 #
-# CONFIG_PARPORT is not set
 
 #
 # Generic Driver Options
 #
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -139,6 +138,11 @@
 # CONFIG_MTD is not set
 
 #
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
 # Plug and Play support
 #
 
@@ -153,6 +157,7 @@
 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_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -206,7 +211,7 @@
 # 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_SIIMAGE=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
@@ -217,38 +222,6 @@
 # CONFIG_BLK_DEV_HD is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=m
-CONFIG_MD_LINEAR=m
-CONFIG_MD_RAID0=m
-CONFIG_MD_RAID1=m
-CONFIG_MD_RAID5=m
-# CONFIG_MD_RAID6 is not set
-CONFIG_MD_MULTIPATH=m
-CONFIG_BLK_DEV_DM=m
-CONFIG_DM_IOCTL_V4=y
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_ISENSE is not set
-# CONFIG_FUSION_CTL is not set
-
-#
 # SCSI device support
 #
 CONFIG_SCSI=y
@@ -273,6 +246,12 @@
 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
@@ -316,6 +295,37 @@
 # CONFIG_SCSI_DEBUG is not set
 
 #
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID6 is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_CRYPT is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -471,6 +481,7 @@
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # Wan interfaces
@@ -491,11 +502,18 @@
 # Bluetooth support
 #
 # CONFIG_BT is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -558,7 +576,8 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 
 #
 # Mice
@@ -576,7 +595,6 @@
 #
 # 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
@@ -601,172 +619,80 @@
 #
 # I2C support
 #
-# CONFIG_I2C is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY 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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=y
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
 
 #
-# DOS/FAT/NT Filesystems
+# I2C Algorithms
 #
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-# CONFIG_NTFS_FS is not set
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
 
 #
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-# CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 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_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_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_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
 
 #
-# Network File Systems
+# Misc devices
 #
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_DIRECTIO=y
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-# 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
 
 #
-# Partition Types
+# Multimedia devices
 #
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_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=y
+# CONFIG_VIDEO_DEV is not set
 
 #
-# Native Language Support
+# Digital Video Broadcasting Devices
 #
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_737=y
-CONFIG_NLS_CODEPAGE_775=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_CODEPAGE_852=y
-CONFIG_NLS_CODEPAGE_855=y
-CONFIG_NLS_CODEPAGE_857=y
-CONFIG_NLS_CODEPAGE_860=y
-CONFIG_NLS_CODEPAGE_861=y
-CONFIG_NLS_CODEPAGE_862=y
-CONFIG_NLS_CODEPAGE_863=y
-CONFIG_NLS_CODEPAGE_864=y
-CONFIG_NLS_CODEPAGE_865=y
-CONFIG_NLS_CODEPAGE_866=y
-CONFIG_NLS_CODEPAGE_869=y
-CONFIG_NLS_CODEPAGE_936=y
-CONFIG_NLS_CODEPAGE_950=y
-CONFIG_NLS_CODEPAGE_932=y
-CONFIG_NLS_CODEPAGE_949=y
-CONFIG_NLS_CODEPAGE_874=y
-CONFIG_NLS_ISO8859_8=y
-# CONFIG_NLS_CODEPAGE_1250 is not set
-CONFIG_NLS_CODEPAGE_1251=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_2=y
-CONFIG_NLS_ISO8859_3=y
-CONFIG_NLS_ISO8859_4=y
-CONFIG_NLS_ISO8859_5=y
-CONFIG_NLS_ISO8859_6=y
-CONFIG_NLS_ISO8859_7=y
-CONFIG_NLS_ISO8859_9=y
-CONFIG_NLS_ISO8859_13=y
-CONFIG_NLS_ISO8859_14=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_KOI8_R=y
-CONFIG_NLS_KOI8_U=y
-CONFIG_NLS_UTF8=y
+# CONFIG_DVB is not set
 
 #
 # Graphics support
@@ -780,6 +706,7 @@
 # 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 is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
@@ -821,15 +748,23 @@
 # Advanced Linux Sound Architecture
 #
 CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
 CONFIG_SND_SEQUENCER=m
 # CONFIG_SND_SEQ_DUMMY is not set
-# CONFIG_SND_OSSEMUL is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_SEQUENCER_OSS is not set
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
 #
 # Generic devices
 #
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_VIRMIDI is not set
 # CONFIG_SND_MTPAV is not set
@@ -839,13 +774,19 @@
 #
 # PCI devices
 #
+CONFIG_SND_AC97_CODEC=m
 # CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 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_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
@@ -861,9 +802,11 @@
 # CONFIG_SND_ES1968 is not set
 # CONFIG_SND_MAESTRO3 is not set
 CONFIG_SND_FM801=m
+# CONFIG_SND_FM801_TEA575X is not set
 # CONFIG_SND_ICE1712 is not set
 # CONFIG_SND_ICE1724 is not set
 # CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_SONICVIBES is not set
 # CONFIG_SND_VIA82XX is not set
 # CONFIG_SND_VX222 is not set
@@ -887,16 +830,16 @@
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_DEVICEFS=y
 CONFIG_USB_BANDWIDTH=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
 
 #
 # USB Host Controller Drivers
 #
-CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_UHCI_HCD=y
 
 #
 # USB Device Class drivers
@@ -967,6 +910,7 @@
 # CONFIG_USB_BRLVGER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_TEST is not set
 
 #
 # USB Gadget Support
@@ -974,6 +918,162 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY 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_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+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_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_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=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+# CONFIG_NLS_CODEPAGE_1250 is not set
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+
+#
 # Library routines
 #
 CONFIG_CRC32=y
@@ -990,7 +1090,7 @@
 # CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_IA64_PRINT_HAZARDS=y
-# CONFIG_DISABLE_VHPT is not set
+CONFIG_DISABLE_VHPT=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -998,6 +1098,7 @@
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
 CONFIG_DEBUG_INFO=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Security options
@@ -1007,4 +1108,21 @@
 #
 # 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_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_ARC4 is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_TEST is not set
diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
--- a/arch/ia64/hp/common/sba_iommu.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/hp/common/sba_iommu.c	Wed Mar 17 19:29:09 2004
@@ -1055,13 +1055,13 @@
 	*dma_handle = virt_to_phys(addr);
 
 #ifdef ALLOW_IOV_BYPASS
-	ASSERT(to_pci_dev(dev)->consistent_dma_mask);
+	ASSERT(dev->coherent_dma_mask);
 	/*
  	** Check if the PCI device can DMA to ptr... if so, just return ptr
  	*/
-	if (likely((*dma_handle & ~to_pci_dev(dev)->consistent_dma_mask) == 0)) {
+	if (likely((*dma_handle & ~dev->coherent_dma_mask) == 0)) {
 		DBG_BYPASS("sba_alloc_coherent() bypass mask/addr: 0x%lx/0x%lx\n",
-		           to_pci_dev(dev)->consistent_dma_mask, *dma_handle);
+		           dev->coherent_dma_mask, *dma_handle);
 
 		return addr;
 	}
diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
--- a/arch/ia64/hp/sim/simscsi.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/hp/sim/simscsi.c	Wed Mar 17 19:29:09 2004
@@ -8,23 +8,23 @@
  * 02/01/15 David Mosberger	Updated for v2.5.1
  * 99/12/18 David Mosberger	Added support for READ10/WRITE10 needed by linux v2.3.33
  */
-#include <linux/config.h>
 #include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
-
-#include <scsi/scsi.h>
-
 #include <asm/irq.h>
 
-#include "../drivers/scsi/scsi.h"
-#include "../drivers/scsi/hosts.h"
-#include "simscsi.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
 
 #define DEBUG_SIMSCSI	0
 
+#define SIMSCSI_REQ_QUEUE_LEN	64
+#define DEFAULT_SIMSCSI_ROOT	"/var/ski-disks/sd"
+
 /* Simulator system calls: */
 
 #define SSC_OPEN			50
@@ -47,7 +47,7 @@
 static struct Scsi_Host *host;
 
 static void simscsi_interrupt (unsigned long val);
-DECLARE_TASKLET(simscsi_tasklet, simscsi_interrupt, 0);
+static DECLARE_TASKLET(simscsi_tasklet, simscsi_interrupt, 0);
 
 struct disk_req {
 	unsigned long addr;
@@ -66,7 +66,7 @@
 };
 
 static struct queue_entry {
-	Scsi_Cmnd *sc;
+	struct scsi_cmnd *sc;
 } queue[SIMSCSI_REQ_QUEUE_LEN];
 
 static int rd, wr;
@@ -99,7 +99,7 @@
 static void
 simscsi_interrupt (unsigned long val)
 {
-	Scsi_Cmnd *sc;
+	struct scsi_cmnd *sc;
 
 	while ((sc = queue[rd].sc) != 0) {
 		atomic_dec(&num_reqs);
@@ -111,30 +111,7 @@
 	}
 }
 
-int
-simscsi_detect (Scsi_Host_Template *templ)
-{
-	templ->proc_name = "simscsi";
-	host = scsi_register(templ, 0);
-	if(host == NULL)
-		return 0;
-
-	return 1;	/* fake one SCSI host adapter */
-}
-
-int
-simscsi_release (struct Scsi_Host *host)
-{
-	return 0;	/* this is easy...  */
-}
-
-const char *
-simscsi_info (struct Scsi_Host *host)
-{
-	return "simulated SCSI host adapter";
-}
-
-int
+static int
 simscsi_biosparam (struct scsi_device *sdev, struct block_device *n,
 		sector_t capacity, int ip[])
 {
@@ -145,7 +122,7 @@
 }
 
 static void
-simscsi_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset, unsigned long len)
+simscsi_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset, unsigned long len)
 {
 	struct disk_stat stat;
 	struct disk_req req;
@@ -171,7 +148,7 @@
 }
 
 static void
-simscsi_sg_readwrite (Scsi_Cmnd *sc, int mode, unsigned long offset)
+simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset)
 {
 	int list_len = sc->use_sg;
 	struct scatterlist *sl = (struct scatterlist *)sc->buffer;
@@ -208,7 +185,7 @@
  * Added 02/26/99 S.Eranian
  */
 static void
-simscsi_readwrite6 (Scsi_Cmnd *sc, int mode)
+simscsi_readwrite6 (struct scsi_cmnd *sc, int mode)
 {
 	unsigned long offset;
 
@@ -244,7 +221,7 @@
 }
 
 static void
-simscsi_readwrite10 (Scsi_Cmnd *sc, int mode)
+simscsi_readwrite10 (struct scsi_cmnd *sc, int mode)
 {
 	unsigned long offset;
 
@@ -256,8 +233,8 @@
 		simscsi_readwrite(sc, mode, offset, ((sc->cmnd[7] << 8) | sc->cmnd[8])*512);
 }
 
-int
-simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
+static int
+simscsi_queuecommand (struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
 {
 	unsigned int target_id = sc->device->id;
 	char fname[MAX_ROOT_LEN+16];
@@ -380,18 +357,16 @@
 	return 0;
 }
 
-int
-simscsi_host_reset (Scsi_Cmnd *sc)
+static int
+simscsi_host_reset (struct scsi_cmnd *sc)
 {
 	printk(KERN_ERR "simscsi_host_reset: not implemented\n");
 	return 0;
 }
 
-static Scsi_Host_Template driver_template = {
-	.name			= "simscsi",
-	.detect			= simscsi_detect,
-	.release		= simscsi_release,
-	.info			= simscsi_info,	
+static struct scsi_host_template driver_template = {
+	.name			= "simulated SCSI host adapter",
+	.proc_name		= "simscsi",
 	.queuecommand		= simscsi_queuecommand,
 	.eh_host_reset_handler	= simscsi_host_reset,
 	.bios_param		= simscsi_biosparam,
@@ -402,4 +377,28 @@
 	.cmd_per_lun		= SIMSCSI_REQ_QUEUE_LEN,
 	.use_clustering		= DISABLE_CLUSTERING,
 };
-#include "../drivers/scsi/scsi_module.c"
+
+static int __init
+simscsi_init(void)
+{
+	int error;
+
+	host = scsi_host_alloc(&driver_template, 0);
+	if (!host)
+		return -ENOMEM;
+
+	error = scsi_add_host(host, NULL);
+	if (!error)
+		scsi_scan_host(host);
+	return error;
+}
+
+static void __exit
+simscsi_exit(void)
+{
+	scsi_remove_host(host);
+	scsi_host_put(host);
+}
+
+module_init(simscsi_init);
+module_exit(simscsi_exit);
diff -Nru a/arch/ia64/hp/sim/simscsi.h b/arch/ia64/hp/sim/simscsi.h
--- a/arch/ia64/hp/sim/simscsi.h	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/*
- * Simulated SCSI driver.
- *
- * Copyright (C) 1999, 2002 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
- */
-#ifndef SIMSCSI_H
-#define SIMSCSI_H
-
-#define SIMSCSI_REQ_QUEUE_LEN	64
-
-#define DEFAULT_SIMSCSI_ROOT	"/var/ski-disks/sd"
-
-extern int simscsi_detect (Scsi_Host_Template *);
-extern int simscsi_release (struct Scsi_Host *);
-extern const char *simscsi_info (struct Scsi_Host *);
-extern int simscsi_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int simscsi_abort (Scsi_Cmnd *);
-extern int simscsi_reset (Scsi_Cmnd *, unsigned int);
-extern int simscsi_biosparam (struct scsi_device *, struct block_device *,
-		sector_t, int[]);
-
-#endif /* SIMSCSI_H */
diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
--- a/arch/ia64/kernel/Makefile	Wed Mar 17 19:29:10 2004
+++ b/arch/ia64/kernel/Makefile	Wed Mar 17 19:29:10 2004
@@ -6,13 +6,12 @@
 
 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		\
-	 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o
+	 salinfo.o semaphore.o setup.o signal.o sys_ia64.o time.o traps.o unaligned.o unwind.o mca.o mca_asm.o
 
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
 obj-$(CONFIG_IA64_BRL_EMU)	+= brl_emu.o
 obj-$(CONFIG_IA64_GENERIC)	+= acpi-ext.o
 obj-$(CONFIG_IA64_HP_ZX1)	+= acpi-ext.o
-obj-$(CONFIG_IA64_MCA)		+= mca.o mca_asm.o
 obj-$(CONFIG_IA64_PALINFO)	+= palinfo.o
 obj-$(CONFIG_IOSAPIC)		+= iosapic.o
 obj-$(CONFIG_MODULES)		+= module.o
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/kernel/acpi.c	Wed Mar 17 19:29:09 2004
@@ -626,6 +626,7 @@
 	return 0;
 }
 
+/* deprecated in favor of acpi_gsi_to_irq */
 int
 acpi_irq_to_vector (u32 gsi)
 {
@@ -633,6 +634,23 @@
 		return isa_irq_to_vector(gsi);
 
 	return gsi_to_vector(gsi);
+}
+
+int
+acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
+{
+	int vector;
+
+	if (has_8259 && gsi < 16)
+		*irq = isa_irq_to_vector(gsi);
+	else {
+		vector = gsi_to_vector(gsi);
+		if (vector == -1)
+			return -1;
+
+		*irq = vector;
+	}
+	return 0;
 }
 
 int
diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
--- a/arch/ia64/kernel/efi.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/kernel/efi.c	Wed Mar 17 19:29:09 2004
@@ -399,9 +399,7 @@
 	int pal_code_count = 0;
 	u64 mask, psr;
 	u64 vaddr;
-#ifdef CONFIG_IA64_MCA
 	int cpu;
-#endif
 
 	efi_map_start = __va(ia64_boot_param->efi_memmap);
 	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
@@ -463,13 +461,11 @@
 		ia64_set_psr(psr);		/* restore psr */
 		ia64_srlz_i();
 
-#ifdef CONFIG_IA64_MCA
 		cpu = smp_processor_id();
 
 		/* insert this TR into our list for MCA recovery purposes */
 		ia64_mca_tlb_list[cpu].pal_base = vaddr & mask;
 		ia64_mca_tlb_list[cpu].pal_paddr = pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL));
-#endif
 	}
 }
 
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/kernel/setup.c	Wed Mar 17 19:29:09 2004
@@ -355,10 +355,8 @@
 # endif
 #endif
 
-#ifdef CONFIG_IA64_MCA
 	/* enable IA-64 Machine Check Abort Handling */
 	ia64_mca_init();
-#endif
 
 	platform_setup(cmdline_p);
 	paging_init();
diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
--- a/arch/ia64/kernel/smpboot.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/kernel/smpboot.c	Wed Mar 17 19:29:09 2004
@@ -300,9 +300,7 @@
 	 */
 	ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
 
-#ifdef CONFIG_IA64_MCA
 	ia64_mca_cmc_vector_setup();	/* Setup vector on AP & enable */
-#endif
 
 #ifdef CONFIG_PERFMON
 	pfm_init_percpu();
diff -Nru a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
--- a/arch/ia64/mm/contig.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/mm/contig.c	Wed Mar 17 19:29:09 2004
@@ -46,6 +46,8 @@
 	printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	i = max_mapnr;
 	while (i-- > 0) {
+		if (!pfn_valid(i))
+			continue;
 		total++;
 		if (PageReserved(mem_map+i))
 			reserved++;
diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ia64/mm/discontig.c	Wed Mar 17 19:29:10 2004
@@ -499,6 +499,8 @@
 	for_each_pgdat(pgdat) {
 		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))
+				continue;
 			if (PageReserved(pgdat->node_mem_map+i))
 				reserved++;
 			else if (PageSwapCache(pgdat->node_mem_map+i))
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/mm/init.c	Wed Mar 17 19:29:09 2004
@@ -279,9 +279,7 @@
 {
 	unsigned long psr, pta, impl_va_bits;
 	extern void __init tlb_init (void);
-#ifdef CONFIG_IA64_MCA
 	int cpu;
-#endif
 
 #ifdef CONFIG_DISABLE_VHPT
 #	define VHPT_ENABLE_BIT	0
@@ -346,7 +344,6 @@
 	ia64_set_rr(HPAGE_REGION_BASE, HPAGE_SHIFT << 2);
 #endif
 
-#ifdef	CONFIG_IA64_MCA
 	cpu = smp_processor_id();
 
 	/* mca handler uses cr.lid as key to pick the right entry */
@@ -360,7 +357,6 @@
 	ia64_mca_tlb_list[cpu].ptce_count[1] = local_cpu_data->ptce_count[1];
 	ia64_mca_tlb_list[cpu].ptce_stride[0] = local_cpu_data->ptce_stride[0];
 	ia64_mca_tlb_list[cpu].ptce_stride[1] = local_cpu_data->ptce_stride[1];
-#endif
 }
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
@@ -459,8 +455,11 @@
 ia64_pfn_valid (unsigned long pfn)
 {
 	char byte;
+	struct page *pg = pfn_to_page(pfn);
 
-	return __get_user(byte, (char *) pfn_to_page(pfn)) == 0;
+	return     (__get_user(byte, (char *) pg) == 0)
+		&& ((((u64)pg & PAGE_MASK) == (((u64)(pg + 1) - 1) & PAGE_MASK))
+			|| (__get_user(byte, (char *) (pg + 1) - 1) == 0));
 }
 EXPORT_SYMBOL(ia64_pfn_valid);
 
diff -Nru a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
--- a/arch/ia64/sn/kernel/mca.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/sn/kernel/mca.c	Wed Mar 17 19:29:09 2004
@@ -1,17 +1,15 @@
 /*
- * File:	mca.c
- * Purpose:	SN specific MCA code.
- *
  * 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.
  *
- * Copyright (C) 2001-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
+#include <linux/vmalloc.h>
 #include <asm/sn/sgi.h>
 #include <asm/mca.h>
 #include <asm/sal.h>
@@ -30,41 +28,43 @@
 struct timer_list sn_cpei_timer;
 void sn_init_cpei_timer(void);
 
+/* Printing oemdata from mca uses data that is not passed through SAL, it is
+ * global.  Only one user at a time.
+ */
+static DECLARE_MUTEX(sn_oemdata_mutex);
+static u8 **sn_oemdata;
+static u64 *sn_oemdata_size, sn_oemdata_bufsize;
 
 /*
  * print_hook
  *
  * This function is the callback routine that SAL calls to log error
- * info for platform errors. 
+ * info for platform errors.  buf is appended to sn_oemdata, resizing as
+ * required.
  */
 static int
 print_hook(const char *fmt, ...)
 {
-	static int	newline=1;
-	char		buf[400], *p;
-	va_list		args;
-	int		len=0;
-
-
+	char buf[400];
+	int len;
+	va_list args;
 	va_start(args, fmt);
-	if (newline) {
-		strcpy(buf, "+ ");
-		len += 2;
-	}
-	len += vsnprintf(buf+len, sizeof(buf)-len, fmt, args);
-
-	/* Prefix each line with "+ " to be consistent with mca.c. */
-	p = buf;
-	while ((p=strchr(p, '\n')) && *++p != '\0') {
-		memmove(p+2, p, 1+strlen(p));
-		strncpy(p, "+ ", 2);
-		len += 2;
-	}
-	newline = (p != 0);
-
+	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
-	printk("%s", buf);
-	return len;
+	len = strlen(buf);
+	while (*sn_oemdata_size + len + 1 > sn_oemdata_bufsize) {
+		u8 *newbuf = vmalloc(sn_oemdata_bufsize += 1000);
+		if (!newbuf) {
+			printk(KERN_ERR "%s: unable to extend sn_oemdata\n", __FUNCTION__);
+			return 0;
+		}
+		memcpy(newbuf, *sn_oemdata, *sn_oemdata_size);
+		vfree(*sn_oemdata);
+		*sn_oemdata = newbuf;
+	}
+	memcpy(*sn_oemdata + *sn_oemdata_size, buf, len + 1);
+	*sn_oemdata_size += len;
+	return 0;
 }
 
 
@@ -95,6 +95,43 @@
 {
 	init_timer(&sn_cpei_timer);
 	sn_cpei_timer.expires = jiffies + CPEI_INTERVAL;
-        sn_cpei_timer.function = sn_cpei_timer_handler;
+	sn_cpei_timer.function = sn_cpei_timer_handler;
 	add_timer(&sn_cpei_timer);
 }
+
+static int
+sn_platform_plat_specific_err_print(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
+{
+	sal_log_plat_specific_err_info_t *psei = (sal_log_plat_specific_err_info_t *)sect_header;
+	if (!psei->valid.oem_data)
+		return 0;
+	down(&sn_oemdata_mutex);
+	sn_oemdata = oemdata;
+	sn_oemdata_size = oemdata_size;
+	ia64_sn_plat_specific_err_print(print_hook, (char *)psei);
+	up(&sn_oemdata_mutex);
+	return 0;
+}
+
+/* Callback when userspace salinfo wants to decode oem data via the platform
+ * kernel and/or prom.
+ */
+int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
+{
+	efi_guid_t guid = *(efi_guid_t *)sect_header;
+	*oemdata_size = 0;
+	sn_oemdata_bufsize = 0;
+	vfree(*oemdata);
+	*oemdata = NULL;
+	if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0)
+		return sn_platform_plat_specific_err_print(sect_header, oemdata, oemdata_size);
+	return 0;
+}
+
+static int __init sn_salinfo_init(void)
+{
+	salinfo_platform_oemdata = &sn_salinfo_platform_oemdata;
+	return 0;
+}
+
+module_init(sn_salinfo_init)
diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ia64/sn/kernel/setup.c	Wed Mar 17 19:29:09 2004
@@ -194,10 +194,7 @@
 	}
 }
 
-#ifdef CONFIG_IA64_MCA
 extern int platform_intr_list[];
-#endif
-
 extern nasid_t master_nasid;
 static int shub_1_1_found __initdata;
 
diff -Nru a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
--- a/arch/mips/configs/rm200_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/mips/configs/rm200_defconfig	Wed Mar 17 19:29:09 2004
@@ -323,7 +323,6 @@
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=m
-CONFIG_DM_IOCTL_V4=y
 
 #
 # Fusion MPT device support
diff -Nru a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
--- a/arch/parisc/kernel/process.c	Wed Mar 17 19:29:10 2004
+++ b/arch/parisc/kernel/process.c	Wed Mar 17 19:29:10 2004
@@ -325,7 +325,7 @@
 
 		/* Use same stack depth as parent */
 		cregs->ksp = ((unsigned long)(ti))
-			+ (pregs->gr[21] & (INIT_THREAD_SIZE - 1));
+			+ (pregs->gr[21] & (THREAD_SIZE - 1));
 		cregs->gr[30] = usp;
 		if (p->personality == PER_HPUX) {
 #ifdef CONFIG_HPUX
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc/boot/simple/Makefile	Wed Mar 17 19:29:09 2004
@@ -114,7 +114,7 @@
         misc-$(CONFIG_SPRUCE)		+= misc-spruce.o
 
 # SMP images should have a '.smp' suffix.
-         end-$(CONFIG_SMP)		+= .smp
+         end-$(CONFIG_SMP)             := $(end-y).smp
 
 # This is a treeboot that needs init functions until the
 # boot rom is sorted out (i.e. this is short lived)
diff -Nru a/arch/ppc/boot/utils/mkprep.c b/arch/ppc/boot/utils/mkprep.c
--- a/arch/ppc/boot/utils/mkprep.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc/boot/utils/mkprep.c	Wed Mar 17 19:29:09 2004
@@ -219,6 +219,8 @@
   pe.number_of_sectors = cpu_to_le32(2*18*80-1);
 #endif /* __i386__ */
 
+  memcpy(&block[0x1BE], &pe, sizeof(pe));
+
   write( out, block, sizeof(block) );
   write( out, entry, sizeof(*entry) );
   write( out, length, sizeof(*length) );
diff -Nru a/arch/ppc/configs/ash_defconfig b/arch/ppc/configs/ash_defconfig
--- a/arch/ppc/configs/ash_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc/configs/ash_defconfig	Wed Mar 17 19:29:09 2004
@@ -400,7 +400,6 @@
 # CONFIG_ADVANTECH_WDT is not set
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_SCx200_WDT is not set
 # CONFIG_60XX_WDT is not set
diff -Nru a/arch/ppc/configs/cedar_defconfig b/arch/ppc/configs/cedar_defconfig
--- a/arch/ppc/configs/cedar_defconfig	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc/configs/cedar_defconfig	Wed Mar 17 19:29:10 2004
@@ -366,7 +366,6 @@
 # CONFIG_ADVANTECH_WDT is not set
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_SCx200_WDT is not set
 # CONFIG_60XX_WDT is not set
diff -Nru a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
--- a/arch/ppc/configs/power3_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc/configs/power3_defconfig	Wed Mar 17 19:29:09 2004
@@ -177,7 +177,6 @@
 CONFIG_MD_RAID5=y
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
-CONFIG_DM_IOCTL_V4=y
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -622,13 +621,11 @@
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_ELV is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
 # CONFIG_I2C_KEYWEST is not set
 # CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PHILIPSPAR is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -636,7 +633,6 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
diff -Nru a/arch/ppc/configs/rainier_defconfig b/arch/ppc/configs/rainier_defconfig
--- a/arch/ppc/configs/rainier_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc/configs/rainier_defconfig	Wed Mar 17 19:29:09 2004
@@ -436,7 +436,6 @@
 # CONFIG_ADVANTECH_WDT is not set
 # CONFIG_EUROTECH_WDT is not set
 # CONFIG_IB700_WDT is not set
-# CONFIG_I810_TCO is not set
 # CONFIG_MIXCOMWD is not set
 # CONFIG_SCx200_WDT is not set
 # CONFIG_60XX_WDT is not set
diff -Nru a/arch/ppc/mm/cachemap.c b/arch/ppc/mm/cachemap.c
--- a/arch/ppc/mm/cachemap.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc/mm/cachemap.c	Wed Mar 17 19:29:10 2004
@@ -145,7 +145,7 @@
 	switch (direction) {
 	case DMA_NONE:
 		BUG();
-	case DMA_FROMDEVICE:	/* invalidate only */
+	case DMA_FROM_DEVICE:	/* invalidate only */
 		invalidate_dcache_range(start, end);
 		break;
 	case DMA_TODEVICE:		/* writeback only */
diff -Nru a/arch/ppc/platforms/proc_rtas.c b/arch/ppc/platforms/proc_rtas.c
--- a/arch/ppc/platforms/proc_rtas.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc/platforms/proc_rtas.c	Wed Mar 17 19:29:10 2004
@@ -20,6 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/time.h>
 #include <linux/string.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -194,18 +195,18 @@
 /* ****************************************************************** */
 /* MAIN                                                               */
 /* ****************************************************************** */
-void proc_rtas_init(void)
+static int __init proc_rtas_init(void)
 {
 	struct proc_dir_entry *entry;
 
 	rtas = find_devices("rtas");
 	if ((rtas == 0) || (_machine != _MACH_chrp)) {
-		return;
+		return 1;
 	}
 
 	proc_rtas = proc_mkdir("rtas", 0);
 	if (proc_rtas == 0)
-		return;
+		return 1;
 
 	/* /proc/rtas entries */
 
@@ -226,7 +227,10 @@
 
 	entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas);
 	if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
+
+	return 0;
 }
+__initcall(proc_rtas_init);
 
 /* ****************************************************************** */
 /* POWER-ON-TIME                                                      */
diff -Nru a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
--- a/arch/ppc/syslib/indirect_pci.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc/syslib/indirect_pci.c	Wed Mar 17 19:29:09 2004
@@ -44,8 +44,8 @@
 			cfg_type = 1;
 
 	PCI_CFG_OUT(hose->cfg_addr, 					 
-		 (0x80000000 | ((dev->bus->number - hose->bus_offset) << 16) 
-		  | (dev->devfn << 8) | ((offset & 0xfc) | cfg_type)));	
+		 (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+		  | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
 
 	/*
 	 * Note: the caller has already checked that offset is
@@ -83,8 +83,8 @@
 			cfg_type = 1;
 
 	PCI_CFG_OUT(hose->cfg_addr, 					 
-		 (0x80000000 | ((dev->bus->number - hose->bus_offset) << 16) 
-		  | (dev->devfn << 8) | ((offset & 0xfc) | cfg_type)));	
+		 (0x80000000 | ((bus->number - hose->bus_offset) << 16)
+		  | (devfn << 8) | ((offset & 0xfc) | cfg_type)));
 
 	/*
 	 * Note: the caller has already checked that offset is
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/Kconfig	Wed Mar 17 19:29:09 2004
@@ -174,14 +174,12 @@
 	depends on DISCONTIGMEM
 
 config PREEMPT
-	bool
+	bool "Preemptible Kernel"
+	depends on BROKEN
 	help
 	  This option reduces the latency of the kernel when reacting to
 	  real-time or interactive events by allowing a low priority process to
 	  be preempted even if it is in kernel mode executing a system call.
-	  Unfortunately the kernel code has some race conditions if both
-	  CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is
-	  currently disabled if you are building an SMP kernel.
 
 	  Say Y here if you are building a kernel for a desktop, embedded
 	  or real-time system.  Say N if you are unsure.
diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile
--- a/arch/ppc64/Makefile	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/Makefile	Wed Mar 17 19:29:09 2004
@@ -53,7 +53,7 @@
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 bootimage-$(CONFIG_PPC_PSERIES) := zImage
-bootimage-$(CONFIG_PPC_ISERIES) := vmlinux.sm
+bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
 BOOTIMAGE := $(bootimage-y)
 install: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
diff -Nru a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
--- a/arch/ppc64/configs/g5_defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/configs/g5_defconfig	Wed Mar 17 19:29:09 2004
@@ -278,7 +278,6 @@
 # CONFIG_MD_RAID6 is not set
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
-CONFIG_DM_IOCTL_V4=y
 # CONFIG_DM_CRYPT is not set
 
 #
@@ -613,7 +612,6 @@
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_ELV is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
@@ -626,7 +624,6 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
diff -Nru a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
--- a/arch/ppc64/configs/iSeries_defconfig	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/configs/iSeries_defconfig	Wed Mar 17 19:29:10 2004
@@ -47,6 +47,7 @@
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
 
 #
 # Platform support
@@ -56,6 +57,7 @@
 CONFIG_PPC=y
 CONFIG_PPC64=y
 # CONFIG_POWER4_ONLY is not set
+# CONFIG_IOMMU_VMERGE is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 CONFIG_MSCHUNKS=y
@@ -89,6 +91,7 @@
 # Generic Driver Options
 #
 CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -115,10 +118,10 @@
 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_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_DCSSBLK is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -150,6 +153,12 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
@@ -197,7 +206,6 @@
 CONFIG_MD_RAID6=y
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
-CONFIG_DM_IOCTL_V4=y
 CONFIG_DM_CRYPT=m
 
 #
@@ -437,6 +445,7 @@
 # CONFIG_TMS380TR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
 
 #
 # Wan interfaces
@@ -457,6 +466,10 @@
 # Bluetooth support
 #
 # CONFIG_BT is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -535,7 +548,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
@@ -556,6 +568,10 @@
 # CONFIG_I2C is not set
 
 #
+# Misc devices
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -742,7 +758,6 @@
 CONFIG_VIOCONS=y
 CONFIG_VIODASD=y
 CONFIG_VIOCD=y
-# CONFIG_VIOCD_AZTECH is not set
 # CONFIG_VIOTAPE is not set
 CONFIG_VIOPATH=y
 
@@ -787,6 +802,7 @@
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_TEST=m
 
diff -Nru a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
--- a/arch/ppc64/configs/pSeries_defconfig	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/configs/pSeries_defconfig	Wed Mar 17 19:29:10 2004
@@ -47,6 +47,7 @@
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
 
 #
 # Platform support
@@ -60,6 +61,7 @@
 # CONFIG_PPC_PMAC is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_POWER4_ONLY is not set
+# CONFIG_IOMMU_VMERGE is not set
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=32
@@ -106,6 +108,7 @@
 # Generic Driver Options
 #
 CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -132,10 +135,10 @@
 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_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_DCSSBLK is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -173,7 +176,7 @@
 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_AMD74XX=y
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
@@ -222,6 +225,12 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
@@ -273,7 +282,6 @@
 CONFIG_MD_RAID6=y
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
-CONFIG_DM_IOCTL_V4=y
 CONFIG_DM_CRYPT=m
 
 #
@@ -515,6 +523,7 @@
 # CONFIG_TMS380TR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
 
 #
 # Wan interfaces
@@ -535,6 +544,10 @@
 # Bluetooth support
 #
 # CONFIG_BT is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -633,7 +646,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
@@ -667,7 +679,6 @@
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_ELV is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
@@ -679,7 +690,6 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -707,6 +717,10 @@
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Misc devices
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -720,6 +734,7 @@
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
 # CONFIG_FB_CT65550 is not set
@@ -776,7 +791,7 @@
 #
 # USB support
 #
-CONFIG_USB=m
+CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
 #
@@ -789,8 +804,8 @@
 #
 # USB Host Controller Drivers
 #
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
 
 #
@@ -799,7 +814,7 @@
 # CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=m
+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
@@ -813,16 +828,10 @@
 #
 # USB Human Interface Devices (HID)
 #
-CONFIG_USB_HID=m
+CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_KBTAB is not set
@@ -1076,6 +1085,7 @@
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_TEST=m
 
diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig
--- a/arch/ppc64/defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/defconfig	Wed Mar 17 19:29:09 2004
@@ -47,6 +47,7 @@
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
 
 #
 # Platform support
@@ -60,6 +61,7 @@
 # CONFIG_PPC_PMAC is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_POWER4_ONLY is not set
+# CONFIG_IOMMU_VMERGE is not set
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=32
@@ -106,6 +108,7 @@
 # Generic Driver Options
 #
 CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -132,10 +135,10 @@
 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_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_DCSSBLK is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -173,7 +176,7 @@
 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_AMD74XX=y
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
@@ -222,6 +225,12 @@
 # CONFIG_SCSI_LOGGING is not set
 
 #
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+
+#
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
@@ -273,7 +282,6 @@
 CONFIG_MD_RAID6=y
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
-CONFIG_DM_IOCTL_V4=y
 CONFIG_DM_CRYPT=m
 
 #
@@ -515,6 +523,7 @@
 # CONFIG_TMS380TR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
 
 #
 # Wan interfaces
@@ -535,6 +544,10 @@
 # Bluetooth support
 #
 # CONFIG_BT is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -633,7 +646,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
@@ -667,7 +679,6 @@
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_ELV is not set
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
@@ -679,7 +690,6 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_VELLEMAN is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -707,6 +717,10 @@
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Misc devices
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -720,6 +734,7 @@
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
 # CONFIG_FB_CT65550 is not set
@@ -776,7 +791,7 @@
 #
 # USB support
 #
-CONFIG_USB=m
+CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
 #
@@ -789,8 +804,8 @@
 #
 # USB Host Controller Drivers
 #
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
 
 #
@@ -799,7 +814,7 @@
 # CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=m
+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
@@ -813,16 +828,10 @@
 #
 # USB Human Interface Devices (HID)
 #
-CONFIG_USB_HID=m
+CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_KBTAB is not set
@@ -1076,6 +1085,7 @@
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_TEST=m
 
diff -Nru a/arch/ppc64/kernel/HvLpConfig.c b/arch/ppc64/kernel/HvLpConfig.c
--- a/arch/ppc64/kernel/HvLpConfig.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/HvLpConfig.c	Wed Mar 17 19:29:10 2004
@@ -17,12 +17,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#ifndef _HVLPCONFIG_H
+#include <linux/module.h>
 #include <asm/iSeries/HvLpConfig.h>
-#endif
 
 HvLpIndex HvLpConfig_getLpIndex_outline(void)
 {
 	return HvLpConfig_getLpIndex();
 }
-
+EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline);
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/Makefile	Wed Mar 17 19:29:10 2004
@@ -5,11 +5,11 @@
 EXTRA_CFLAGS	+= -mno-minimal-toc
 extra-y		:= head.o vmlinux.lds.s
 
-obj-y               :=	setup.o entry.o traps.o irq.o idle.o \
+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 \
 			udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
-			ptrace32.o signal32.o pmc.o rtc.o init_task.o \
+			ptrace32.o signal32.o rtc.o init_task.o \
 			lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
 			iommu.o
 
@@ -29,7 +29,7 @@
 			     HvCall.o HvLpConfig.o LparData.o mf_proc.o \
 			     iSeries_setup.o ItLpQueue.o hvCall.o \
 			     mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
-			     proc_pmc.o iSeries_iommu.o
+			     iSeries_iommu.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 \
diff -Nru a/arch/ppc64/kernel/bitops.c b/arch/ppc64/kernel/bitops.c
--- a/arch/ppc64/kernel/bitops.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/bitops.c	Wed Mar 17 19:29:09 2004
@@ -3,6 +3,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
 
@@ -19,7 +20,7 @@
 	offset &= 63UL;
 	if (offset) {
 		tmp = *(p++);
-		tmp |= ~0UL >> (64-offset);
+		tmp |= ~0UL >> (64 - offset);
 		if (size < 64)
 			goto found_first;
 		if (~tmp)
@@ -40,12 +41,15 @@
 found_first:
 	tmp |= ~0UL << size;
 	if (tmp == ~0UL)	/* Are any bits zero? */
-		return result + size; /* Nope. */
+		return result + size;	/* Nope. */
 found_middle:
 	return result + ffz(tmp);
 }
 
-unsigned long find_next_bit(unsigned long *addr, unsigned long size, unsigned long offset)
+EXPORT_SYMBOL(find_next_zero_bit);
+
+unsigned long find_next_bit(unsigned long *addr, unsigned long size,
+			    unsigned long offset)
 {
 	unsigned long *p = addr + (offset >> 6);
 	unsigned long result = offset & ~63UL;
@@ -77,62 +81,67 @@
 
 found_first:
 	tmp &= (~0UL >> (64 - size));
-	if (tmp == 0UL)        /* Are any bits set? */
-		return result + size; /* Nope. */
+	if (tmp == 0UL)		/* Are any bits set? */
+		return result + size;	/* Nope. */
 found_middle:
 	return result + __ffs(tmp);
 }
 
-static __inline__ unsigned int ext2_ilog2(unsigned int x) 
+EXPORT_SYMBOL(find_next_bit);
+
+static inline unsigned int ext2_ilog2(unsigned int x)
 {
 	int lz;
 
-	asm("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+	asm("cntlzw %0,%1": "=r"(lz):"r"(x));
 	return 31 - lz;
 }
 
-static __inline__ unsigned int ext2_ffz(unsigned int x)
+static inline unsigned int ext2_ffz(unsigned int x)
 {
-	u32  tempRC;
+	u32 rc;
 	if ((x = ~x) == 0)
 		return 32;
-	tempRC = ext2_ilog2(x & -x);
-	return tempRC;
+	rc = ext2_ilog2(x & -x);
+	return rc;
 }
 
-unsigned long find_next_zero_le_bit(unsigned long *addr, unsigned long size, unsigned long offset)
+unsigned long find_next_zero_le_bit(unsigned long *addr, unsigned long size,
+				    unsigned long offset)
 {
-        unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
-        unsigned int result = offset & ~31;
-        unsigned int tmp;
-
-        if (offset >= size)
-                return size;
-        size -= result;
-        offset &= 31;
-        if (offset) {
-                tmp = cpu_to_le32p(p++);
-                tmp |= ~0U >> (32-offset); /* bug or feature ? */
-                if (size < 32)
-                        goto found_first;
-                if (tmp != ~0)
-                        goto found_middle;
-                size -= 32;
-                result += 32;
-        }
-        while (size >= 32) {
-                if ((tmp = cpu_to_le32p(p++)) != ~0)
-                        goto found_middle;
-                result += 32;
-                size -= 32;
-        }
-        if (!size)
-                return result;
-        tmp = cpu_to_le32p(p);
+	unsigned int *p = ((unsigned int *)addr) + (offset >> 5);
+	unsigned int result = offset & ~31;
+	unsigned int tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31;
+	if (offset) {
+		tmp = cpu_to_le32p(p++);
+		tmp |= ~0U >> (32 - offset);	/* bug or feature ? */
+		if (size < 32)
+			goto found_first;
+		if (tmp != ~0)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size >= 32) {
+		if ((tmp = cpu_to_le32p(p++)) != ~0)
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = cpu_to_le32p(p);
 found_first:
-        tmp |= ~0 << size;
-        if (tmp == ~0)          /* Are any bits zero? */
-                return result + size; /* Nope. */
+	tmp |= ~0 << size;
+	if (tmp == ~0)		/* Are any bits zero? */
+		return result + size;	/* Nope. */
 found_middle:
-        return result + ext2_ffz(tmp);
+	return result + ext2_ffz(tmp);
 }
+
+EXPORT_SYMBOL(find_next_zero_le_bit);
diff -Nru a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc64/kernel/dma.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Implements the generic device dma API for ppc64. Handles
+ * the pci and vio busses
+ */
+
+#include <linux/config.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+/* Include the busses we support */
+#include <linux/pci.h>
+#ifdef CONFIG_PPC_PSERIES
+#include <asm/vio.h>
+#endif
+#include <asm/scatterlist.h>
+#include <asm/bug.h>
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	if (dev->bus == &pci_bus_type)
+		return pci_dma_supported(to_pci_dev(dev), mask);
+#ifdef CONFIG_PPC_PSERIES
+	if (dev->bus == &vio_bus_type)
+		return vio_dma_supported(to_vio_dev(dev), mask);
+#endif
+	BUG();
+	return 0;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (dev->bus == &pci_bus_type)
+		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+#ifdef CONFIG_PPC_PSERIES
+	if (dev->bus == &vio_bus_type)
+		return vio_set_dma_mask(to_vio_dev(dev), dma_mask);
+#endif
+	BUG();
+	return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+		dma_addr_t *dma_handle, int flag)
+{
+	if (dev->bus == &pci_bus_type)
+		return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
+#ifdef CONFIG_PPC_PSERIES
+	if (dev->bus == &vio_bus_type)
+		return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle);
+#endif
+	BUG();
+	return 0;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+		dma_addr_t dma_handle)
+{
+	if (dev->bus == &pci_bus_type)
+		pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
+#ifdef CONFIG_PPC_PSERIES
+	else if (dev->bus == &vio_bus_type)
+		vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle);
+#endif
+	else
+		BUG();
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	if (dev->bus == &vio_bus_type)
+		return vio_map_single(to_vio_dev(dev), cpu_addr, size, (int)direction);
+#endif
+	BUG();
+	return (dma_addr_t)0;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	else if (dev->bus == &vio_bus_type)
+		vio_unmap_single(to_vio_dev(dev), dma_addr, size, (int)direction);
+#endif
+	else
+		BUG();
+}
+EXPORT_SYMBOL(dma_unmap_single);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+		unsigned long offset, size_t size,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	if (dev->bus == &vio_bus_type)
+		return vio_map_page(to_vio_dev(dev), page, offset, size, (int)direction);
+#endif
+	BUG();
+	return (dma_addr_t)0;
+}
+EXPORT_SYMBOL(dma_map_page);
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	else if (dev->bus == &vio_bus_type)
+		vio_unmap_page(to_vio_dev(dev), dma_address, size, (int)direction);
+#endif
+	else
+		BUG();
+}
+EXPORT_SYMBOL(dma_unmap_page);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	if (dev->bus == &vio_bus_type)
+		return vio_map_sg(to_vio_dev(dev), sg, nents, (int)direction);
+#endif
+	BUG();
+	return 0;
+}
+EXPORT_SYMBOL(dma_map_sg);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	else if (dev->bus == &vio_bus_type)
+		vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, (int)direction);
+#endif
+	else
+		BUG();
+}
+EXPORT_SYMBOL(dma_unmap_sg);
+
+void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		pci_dma_sync_single(to_pci_dev(dev), dma_handle, size, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	else if (dev->bus == &vio_bus_type)
+		vio_dma_sync_single(to_vio_dev(dev), dma_handle, size, (int)direction);
+#endif
+	else
+		BUG();
+}
+EXPORT_SYMBOL(dma_sync_single);
+
+void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+		enum dma_data_direction direction)
+{
+	if (dev->bus == &pci_bus_type)
+		pci_dma_sync_sg(to_pci_dev(dev), sg, nelems, (int)direction);
+#ifdef CONFIG_PPC_PSERIES
+	else if (dev->bus == &vio_bus_type)
+		vio_dma_sync_sg(to_vio_dev(dev), sg, nelems, (int)direction);
+#endif
+	else
+		BUG();
+}
+EXPORT_SYMBOL(dma_sync_sg);
diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
--- a/arch/ppc64/kernel/eeh.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/eeh.c	Wed Mar 17 19:29:09 2004
@@ -17,63 +17,348 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-/* Change Activity:
- * 2001/10/27 : engebret : Created.
- * End Change Activity 
- */
-
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/bootmem.h>
 #include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/seq_file.h>
 #include <asm/paca.h>
 #include <asm/processor.h>
 #include <asm/naca.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
+#include <asm/pgtable.h>
 #include "pci.h"
 
+#undef DEBUG
+
 #define BUID_HI(buid) ((buid) >> 32)
 #define BUID_LO(buid) ((buid) & 0xffffffff)
-#define CONFIG_ADDR(busno, devfn) (((((busno) & 0xff) << 8) | ((devfn) & 0xf8)) << 8)
+#define CONFIG_ADDR(busno, devfn) \
+		(((((busno) & 0xff) << 8) | ((devfn) & 0xf8)) << 8)
 
-unsigned long eeh_total_mmio_ffs;
-unsigned long eeh_false_positives;
 /* RTAS tokens */
 static int ibm_set_eeh_option;
 static int ibm_set_slot_reset;
 static int ibm_read_slot_reset_state;
 
-static int eeh_implemented;
+static int eeh_subsystem_enabled;
 #define EEH_MAX_OPTS 4096
 static char *eeh_opts;
 static int eeh_opts_last;
 
-unsigned char	slot_err_buf[RTAS_ERROR_LOG_MAX];
+/* System monitoring statistics */
+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);
 
-pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va);	/* from htab.c */
-static int eeh_check_opts_config(struct device_node *dn,
-				 int class_code, int vendor_id, int device_id,
+static int eeh_check_opts_config(struct device_node *dn, int class_code,
+				 int vendor_id, int device_id,
 				 int default_state);
 
-unsigned long eeh_token_to_phys(unsigned long token)
+/**
+ * The pci address cache subsystem.  This subsystem places
+ * PCI device address resources into a red-black tree, sorted
+ * according to the address range, so that given only an i/o
+ * address, the corresponding PCI device can be **quickly**
+ * found.
+ *
+ * Currently, the only customer of this code is the EEH subsystem;
+ * thus, this code has been somewhat tailored to suit EEH better.
+ * In particular, the cache does *not* hold the addresses of devices
+ * for which EEH is not enabled.
+ *
+ * (Implementation Note: The RB tree seems to be better/faster
+ * than any hash algo I could think of for this problem, even
+ * with the penalty of slow pointer chases for d-cache misses).
+ */
+struct pci_io_addr_range
+{
+	struct rb_node rb_node;
+	unsigned long addr_lo;
+	unsigned long addr_hi;
+	struct pci_dev *pcidev;
+	unsigned int flags;
+};
+
+static struct pci_io_addr_cache
+{
+	struct rb_root rb_root;
+	spinlock_t piar_lock;
+} pci_io_addr_cache_root;
+
+static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
+{
+	struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
+
+	while (n) {
+		struct pci_io_addr_range *piar;
+		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+		if (addr < piar->addr_lo) {
+			n = n->rb_left;
+		} else {
+			if (addr > piar->addr_hi) {
+				n = n->rb_right;
+			} else {
+				pci_dev_get(piar->pcidev);
+				return piar->pcidev;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * pci_get_device_by_addr - Get device, given only address
+ * @addr: mmio (PIO) phys address or i/o port number
+ *
+ * Given an mmio phys address, or a port number, find a pci device
+ * that implements this address.  Be sure to pci_dev_put the device
+ * when finished.  I/O port numbers are assumed to be offset
+ * from zero (that is, they do *not* have pci_io_addr added in).
+ * It is safe to call this function within an interrupt.
+ */
+static struct pci_dev *pci_get_device_by_addr(unsigned long addr)
+{
+	struct pci_dev *dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+	dev = __pci_get_device_by_addr(addr);
+	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+	return dev;
+}
+
+#ifdef DEBUG
+/*
+ * Handy-dandy debug print routine, does nothing more
+ * than print out the contents of our addr cache.
+ */
+static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
+{
+	struct rb_node *n;
+	int cnt = 0;
+
+	n = rb_first(&cache->rb_root);
+	while (n) {
+		struct pci_io_addr_range *piar;
+		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+		printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s %s\n",
+		       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
+		       piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev),
+		       pci_pretty_name(piar->pcidev));
+		cnt++;
+		n = rb_next(n);
+	}
+}
+#endif
+
+/* Insert address range into the rb tree. */
+static struct pci_io_addr_range *
+pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
+		      unsigned long ahi, unsigned int flags)
+{
+	struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
+	struct rb_node *parent = NULL;
+	struct pci_io_addr_range *piar;
+
+	/* Walk tree, find a place to insert into tree */
+	while (*p) {
+		parent = *p;
+		piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
+		if (alo < piar->addr_lo) {
+			p = &parent->rb_left;
+		} else if (ahi > piar->addr_hi) {
+			p = &parent->rb_right;
+		} else {
+			if (dev != piar->pcidev ||
+			    alo != piar->addr_lo || ahi != piar->addr_hi) {
+				printk(KERN_WARNING "PIAR: overlapping address range\n");
+			}
+			return piar;
+		}
+	}
+	piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+	if (!piar)
+		return NULL;
+
+	piar->addr_lo = alo;
+	piar->addr_hi = ahi;
+	piar->pcidev = dev;
+	piar->flags = flags;
+
+	rb_link_node(&piar->rb_node, parent, p);
+	rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root);
+
+	return piar;
+}
+
+static void __pci_addr_cache_insert_device(struct pci_dev *dev)
+{
+	struct device_node *dn;
+	int i;
+
+	dn = pci_device_to_OF_node(dev);
+	if (!dn) {
+		printk(KERN_WARNING "PCI: no pci dn found for dev=%s %s\n",
+			pci_name(dev), pci_pretty_name(dev));
+		pci_dev_put(dev);
+		return;
+	}
+
+	/* Skip any devices for which EEH is not enabled. */
+	if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
+	    dn->eeh_mode & EEH_MODE_NOCHECK) {
+#ifdef DEBUG
+		printk(KERN_INFO "PCI: skip building address cache for=%s %s\n",
+		       pci_name(dev), pci_pretty_name(dev));
+#endif
+		pci_dev_put(dev);
+		return;
+	}
+
+	/* Walk resources on this device, poke them into the tree */
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		unsigned long start = pci_resource_start(dev,i);
+		unsigned long end = pci_resource_end(dev,i);
+		unsigned int flags = pci_resource_flags(dev,i);
+
+		/* We are interested only bus addresses, not dma or other stuff */
+		if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+			continue;
+		if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
+			 continue;
+		pci_addr_cache_insert(dev, start, end, flags);
+	}
+}
+
+/**
+ * pci_addr_cache_insert_device - Add a device to the address cache
+ * @dev: PCI device whose I/O addresses we are interested in.
+ *
+ * In order to support the fast lookup of devices based on addresses,
+ * we maintain a cache of devices that can be quickly searched.
+ * This routine adds a device to that cache.
+ */
+void pci_addr_cache_insert_device(struct pci_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+	__pci_addr_cache_insert_device(dev);
+	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+	struct rb_node *n;
+
+restart:
+	n = rb_first(&pci_io_addr_cache_root.rb_root);
+	while (n) {
+		struct pci_io_addr_range *piar;
+		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+		if (piar->pcidev == dev) {
+			rb_erase(n, &pci_io_addr_cache_root.rb_root);
+			kfree(piar);
+			goto restart;
+		}
+		n = rb_next(n);
+	}
+	pci_dev_put(dev);
+}
+
+/**
+ * pci_addr_cache_remove_device - remove pci device from addr cache
+ * @dev: device to remove
+ *
+ * Remove a device from the addr-cache tree.
+ * This is potentially expensive, since it will walk
+ * the tree multiple times (once per resource).
+ * But so what; device removal doesn't need to be that fast.
+ */
+void pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+	__pci_addr_cache_remove_device(dev);
+	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+/**
+ * pci_addr_cache_build - Build a cache of I/O addresses
+ *
+ * Build a cache of pci i/o addresses.  This cache will be used to
+ * find the pci device that corresponds to a given address.
+ * This routine scans all pci busses to build the cache.
+ * Must be run late in boot process, after the pci controllers
+ * have been scaned for devices (after all device resources are known).
+ */
+void __init pci_addr_cache_build(void)
+{
+	struct pci_dev *dev = NULL;
+
+	spin_lock_init(&pci_io_addr_cache_root.piar_lock);
+
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+		/* Ignore PCI bridges ( XXX why ??) */
+		if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
+			pci_dev_put(dev);
+			continue;
+		}
+		pci_addr_cache_insert_device(dev);
+	}
+
+#ifdef DEBUG
+	/* Verify tree built up above, echo back the list of addrs. */
+	pci_addr_cache_print(&pci_io_addr_cache_root);
+#endif
+}
+
+/**
+ * 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!
+ */
+static unsigned long eeh_token_to_phys(unsigned long token)
 {
-	if (REGION_ID(token) == EEH_REGION_ID) {
-		unsigned long vaddr = IO_TOKEN_TO_ADDR(token);
-		pte_t *ptep = find_linux_pte(ioremap_mm.pgd, vaddr);
-		unsigned long pa = pte_pfn(*ptep) << PAGE_SHIFT;
-		return pa | (vaddr & (PAGE_SIZE-1));
-	} else
+	pte_t *ptep;
+	unsigned long pa, vaddr;
+
+	if (REGION_ID(token) == EEH_REGION_ID)
+		vaddr = IO_TOKEN_TO_ADDR(token);
+	else
 		return token;
+
+	ptep = find_linux_pte(ioremap_mm.pgd, vaddr);
+	pa = pte_pfn(*ptep) << PAGE_SHIFT;
+
+	return pa | (vaddr & (PAGE_SIZE-1));
 }
 
-/* Check for an eeh failure at the given token address.
+/**
+ * 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.
  * The given value has been read and it should be 1's (0xff, 0xffff or
  * 0xffffffff).
  *
  * Probe to determine if an error actually occurred.  If not return val.
  * Otherwise panic.
+ *
+ * Note this routine might be called in an interrupt context ...
  */
 unsigned long eeh_check_failure(void *token, unsigned long val)
 {
@@ -81,81 +366,97 @@
 	struct pci_dev *dev;
 	struct device_node *dn;
 	unsigned long ret, rets[2];
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+	/* dont want this on the stack */
+	static unsigned char slot_err_buf[RTAS_ERROR_LOG_MAX];
+	unsigned long flags;
 
-	/* IO BAR access could get us here...or if we manually force EEH
-	 * operation on even if the hardware won't support it.
-	 */
-	if (!eeh_implemented || ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE)
+	__get_cpu_var(total_mmio_ffs)++;
+
+	if (!eeh_subsystem_enabled)
 		return val;
 
-	/* Finding the phys addr + pci device is quite expensive.
-	 * However, the RTAS call is MUCH slower.... :(
-	 */
+	/* Finding the phys addr + pci device; this is pretty quick. */
 	addr = eeh_token_to_phys((unsigned long)token);
-	dev = pci_find_dev_by_addr(addr);
-	if (!dev) {
-		printk("EEH: no pci dev found for addr=0x%lx\n", addr);
+	dev = pci_get_device_by_addr(addr);
+	if (!dev)
 		return val;
-	}
+
 	dn = pci_device_to_OF_node(dev);
 	if (!dn) {
-		printk("EEH: no pci dn found for addr=0x%lx\n", addr);
+		pci_dev_put(dev);
 		return val;
 	}
 
 	/* 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)
+	if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
+	    dn->eeh_mode & EEH_MODE_NOCHECK) {
+		pci_dev_put(dev);
 		return val;
+	}
 
+	if (!dn->eeh_config_addr) {
+		pci_dev_put(dev);
+		return val;
+	}
 
-	/* Now test for an EEH failure.  This is VERY expensive.
+	/*
+	 * Now test for an EEH failure.  This is VERY expensive.
 	 * Note that the eeh_config_addr may be a parent device
 	 * in the case of a device behind a bridge, or it may be
 	 * function zero of a multi-function device.
 	 * In any case they must share a common PHB.
 	 */
-	if (dn->eeh_config_addr) {
-		ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
-				dn->eeh_config_addr, BUID_HI(dn->phb->buid),
-				BUID_LO(dn->phb->buid));
-		if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
-			unsigned long	slot_err_ret;
-
-			memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX);
-			slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"),
-						 8, 1, NULL, dn->eeh_config_addr,
-						 BUID_HI(dn->phb->buid),
-						 BUID_LO(dn->phb->buid), NULL, 0,
-						 __pa(slot_err_buf), RTAS_ERROR_LOG_MAX,
-						 2 /* Permanent Error */);
-
-			if (slot_err_ret == 0)
-				log_error(slot_err_buf, ERR_TYPE_RTAS_LOG, 1 /* Fatal */);
-
-			/*
-			 * XXX We should create a separate sysctl for this.
-			 *
-			 * Since the panic_on_oops sysctl is used to halt
-			 * the system in light of potential corruption, we
-			 * can use it here.
-			 */
-			if (panic_on_oops)
-				panic("EEH: MMIO failure (%ld) on device:\n%s\n",
-				      rets[0], pci_name(dev));
-			else
-				printk("EEH: MMIO failure (%ld) on device:\n%s\n",
-				       rets[0], pci_name(dev));
+	ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
+			dn->eeh_config_addr, BUID_HI(dn->phb->buid),
+			BUID_LO(dn->phb->buid));
+
+	if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
+		unsigned long slot_err_ret;
+
+		spin_lock_irqsave(&lock, flags);
+		memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX);
+		slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"),
+					 8, 1, NULL, dn->eeh_config_addr,
+					 BUID_HI(dn->phb->buid),
+					 BUID_LO(dn->phb->buid), NULL, 0,
+					 __pa(slot_err_buf),
+					 RTAS_ERROR_LOG_MAX,
+					 2 /* Permanent Error */);
+
+		if (slot_err_ret == 0)
+			log_error(slot_err_buf, ERR_TYPE_RTAS_LOG,
+				  1 /* Fatal */);
+
+		spin_unlock_irqrestore(&lock, flags);
+
+		/*
+		 * XXX We should create a separate sysctl for this.
+		 *
+		 * Since the panic_on_oops sysctl is used to halt
+		 * the system in light of potential corruption, we
+		 * can use it here.
+		 */
+		if (panic_on_oops) {
+			panic("EEH: MMIO failure (%ld) on device:%s %s\n",
+			      rets[0], pci_name(dev), pci_pretty_name(dev));
+		} else {
+			__get_cpu_var(ignored_failures)++;
+			printk(KERN_INFO "EEH: MMIO failure (%ld) on device:%s %s\n",
+			       rets[0], pci_name(dev), pci_pretty_name(dev));
 		}
+	} else {
+		__get_cpu_var(false_positives)++;
 	}
-	eeh_false_positives++;
-	return val;	/* good case */
 
+	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 adapters_enabled;
 };
 
 /* Enable eeh for the given device node. */
@@ -165,7 +466,7 @@
 	long ret;
 	char *status = get_property(dn, "status", 0);
 	u32 *class_code = (u32 *)get_property(dn, "class-code", 0);
-	u32 *vendor_id =(u32 *) get_property(dn, "vendor-id", 0);
+	u32 *vendor_id = (u32 *)get_property(dn, "vendor-id", 0);
 	u32 *device_id = (u32 *)get_property(dn, "device-id", 0);
 	u32 *regs;
 	int enable;
@@ -183,7 +484,8 @@
 	     *device_id == 0x0188 || *device_id == 0x0302))
 		return NULL;
 
-	/* Now decide if we are going to "Disable" EEH checking
+	/*
+	 * Now decide if we are going to "Disable" EEH checking
 	 * for this device.  We still run with the EEH hardware active,
 	 * but we won't be checking for ff's.  This means a driver
 	 * could return bad data (very bad!), an interrupt handler could
@@ -194,15 +496,19 @@
 	if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY)
 		enable = 0;
 
-	if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id, enable)) {
+	if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id,
+				   enable)) {
 		if (enable) {
-			printk(KERN_INFO "EEH: %s user requested to run without EEH.\n", dn->full_name);
+			printk(KERN_WARNING "EEH: %s user requested to run "
+			       "without EEH.\n", dn->full_name);
 			enable = 0;
 		}
 	}
 
-	if (!enable)
+	if (!enable) {
 		dn->eeh_mode = EEH_MODE_NOCHECK;
+		return NULL;
+	}
 
 	/* This device may already have an EEH parent. */
 	if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) {
@@ -212,7 +518,7 @@
 		return NULL;
 	}
 
-	/* Ok..see if this device supports EEH. */
+	/* Ok... see if this device supports EEH. */
 	regs = (u32 *)get_property(dn, "reg", 0);
 	if (regs) {
 		/* First register entry is addr (00BBSS00)  */
@@ -221,16 +527,27 @@
 				regs[0], info->buid_hi, info->buid_lo,
 				EEH_ENABLE);
 		if (ret == 0) {
-			info->adapters_enabled++;
+			eeh_subsystem_enabled = 1;
 			dn->eeh_mode |= EEH_MODE_SUPPORTED;
 			dn->eeh_config_addr = regs[0];
+#ifdef DEBUG
+			printk(KERN_DEBUG "EEH: %s: eeh enabled\n",
+			       dn->full_name);
+#endif
+		} else {
+			printk(KERN_WARNING "EEH: %s: rtas_call failed.\n",
+			       dn->full_name);
 		}
+	} else {
+		printk(KERN_WARNING "EEH: %s: unable to get reg property.\n",
+		       dn->full_name);
 	}
+
 	return NULL; 
 }
 
 /*
- * Initialize eeh by trying to enable it for all of the adapters in the system.
+ * Initialize EEH by trying to enable it for all of the adapters in the system.
  * As a side effect we can determine here if eeh is supported at all.
  * Note that we leave EEH on so failed config cycles won't cause a machine
  * check.  If a user turns off EEH for a particular adapter they are really
@@ -240,43 +557,35 @@
  * but for now disabling EEH for adapters is mostly to work around drivers that
  * directly access mmio space (without using the macros).
  *
- * The eeh-force-off/on option does literally what it says, so if Linux must
+ * The eeh-force-off option does literally what it says, so if Linux must
  * avoid enabling EEH this must be done.
  */
-void eeh_init(void)
+void __init eeh_init(void)
 {
 	struct device_node *phb;
 	struct eeh_early_enable_info info;
 	char *eeh_force_off = strstr(saved_command_line, "eeh-force-off");
-	char *eeh_force_on = strstr(saved_command_line, "eeh-force-on");
 
 	ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
 	ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
 	ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
 
-	/* Allow user to force eeh mode on or off -- even if the hardware
-	 * doesn't exist.  This allows driver writers to at least test use
-	 * of I/O macros even if we can't actually test for EEH failure.
-	 */
-	if (eeh_force_on > eeh_force_off)
-		eeh_implemented = 1;
-	else if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
+	if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
 		return;
 
-	if (eeh_force_off > eeh_force_on) {
-		/* User is forcing EEH off.  Be noisy if it is implemented. */
-		if (eeh_implemented)
-			printk(KERN_WARNING "EEH: WARNING: PCI Enhanced I/O Error Handling is user disabled\n");
-		eeh_implemented = 0;
+	if (eeh_force_off) {
+		printk(KERN_WARNING "EEH: WARNING: PCI Enhanced I/O Error "
+		       "Handling is user disabled\n");
 		return;
 	}
 
-
 	/* Enable EEH for all adapters.  Note that eeh requires buid's */
-	info.adapters_enabled = 0;
-	for (phb = of_find_node_by_name(NULL, "pci"); phb; phb = of_find_node_by_name(phb, "pci")) {
+	for (phb = of_find_node_by_name(NULL, "pci"); phb;
+	     phb = of_find_node_by_name(phb, "pci")) {
 		int len;
-		int *buid_vals = (int *) get_property(phb, "ibm,fw-phb-id", &len);
+		int *buid_vals;
+
+		buid_vals = (int *)get_property(phb, "ibm,fw-phb-id", &len);
 		if (!buid_vals)
 			continue;
 		if (len == sizeof(int)) {
@@ -286,35 +595,82 @@
 			info.buid_hi = buid_vals[0];
 			info.buid_lo = buid_vals[1];
 		} else {
-			printk("EEH: odd ibm,fw-phb-id len returned: %d\n", len);
+			printk(KERN_INFO "EEH: odd ibm,fw-phb-id len returned: %d\n", len);
 			continue;
 		}
 		traverse_pci_devices(phb, early_enable_eeh, NULL, &info);
 	}
-	if (info.adapters_enabled) {
+
+	if (eeh_subsystem_enabled)
 		printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n");
-		eeh_implemented = 1;
-	}
 }
 
-
-int eeh_set_option(struct pci_dev *dev, int option)
+/**
+ * eeh_add_device - perform EEH initialization for the indicated pci device
+ * @dev: pci device for which to set up EEH
+ *
+ * This routine can be used to perform EEH initialization for PCI
+ * devices that were added after system boot (e.g. hotplug, dlpar).
+ * Whether this actually enables EEH or not for this device depends
+ * on the type of the device, on earlier boot command-line
+ * arguments & etc.
+ */
+void eeh_add_device(struct pci_dev *dev)
 {
-	struct device_node *dn = pci_device_to_OF_node(dev);
-	struct pci_controller *phb = PCI_GET_PHB_PTR(dev);
+	struct device_node *dn;
+	struct pci_controller *phb;
+	struct eeh_early_enable_info info;
 
-	if (dn == NULL || phb == NULL || phb->buid == 0 || !eeh_implemented)
-		return -2;
+	if (!dev || !eeh_subsystem_enabled)
+		return;
 
-	return rtas_call(ibm_set_eeh_option, 4, 1, NULL,
-			 CONFIG_ADDR(dn->busno, dn->devfn),
-			 BUID_HI(phb->buid), BUID_LO(phb->buid), option);
+#ifdef DEBUG
+	printk(KERN_DEBUG "EEH: adding device %s %s\n", pci_name(dev),
+	       pci_pretty_name(dev));
+#endif
+	dn = pci_device_to_OF_node(dev);
+	if (NULL == dn)
+		return;
+
+	phb = PCI_GET_PHB_PTR(dev);
+	if (NULL == phb || 0 == phb->buid) {
+		printk(KERN_WARNING "EEH: Expected buid but found none\n");
+		return;
+	}
+
+	info.buid_hi = BUID_HI(phb->buid);
+	info.buid_lo = BUID_LO(phb->buid);
+
+	early_enable_eeh(dn, &info);
+	pci_addr_cache_insert_device (dev);
 }
+EXPORT_SYMBOL(eeh_add_device);
+
+/**
+ * eeh_remove_device - undo EEH setup for the indicated pci device
+ * @dev: pci device to be removed
+ *
+ * This routine should be when a device is removed from a running
+ * system (e.g. by hotplug or dlpar).
+ */
+void eeh_remove_device(struct pci_dev *dev)
+{
+	if (!dev || !eeh_subsystem_enabled)
+		return;
 
+	/* Unregister the device with the EEH/PCI address search system */
+#ifdef DEBUG
+	printk(KERN_DEBUG "EEH: remove device %s %s\n", pci_name(dev),
+	       pci_pretty_name(dev));
+#endif
+	pci_addr_cache_remove_device(dev);
+}
+EXPORT_SYMBOL(eeh_remove_device);
 
-/* If EEH is implemented, find the PCI device using given phys addr
+/*
+ * 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 not.
+ * 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)
@@ -322,43 +678,78 @@
 	struct pci_dev *dev;
 	struct device_node *dn;
 
-	if (!eeh_implemented)
+	if (!eeh_subsystem_enabled)
 		return vaddr;
-	dev = pci_find_dev_by_addr(addr);
+
+	dev = pci_get_device_by_addr(addr);
 	if (!dev)
 		return vaddr;
+
 	dn = pci_device_to_OF_node(dev);
-	if (!dn)
+	if (!dn) {
+		pci_dev_put(dev);
 		return vaddr;
-	if (dn->eeh_mode & EEH_MODE_NOCHECK)
+	}
+
+	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 eeh_proc_falsepositive_read(char *page, char **start, off_t off,
-			 int count, int *eof, void *data)
+static int proc_eeh_show(struct seq_file *m, void *v)
 {
-	int len;
-	len = sprintf(page, "eeh_false_positives=%ld\n"
-		      "eeh_total_mmio_ffs=%ld\n",
-		      eeh_false_positives, eeh_total_mmio_ffs);
-	return len;
+	unsigned int cpu;
+	unsigned long ffs = 0, positives = 0, failures = 0;
+
+	for_each_cpu(cpu) {
+		ffs += per_cpu(total_mmio_ffs, cpu);
+		positives += per_cpu(false_positives, cpu);
+		failures += per_cpu(ignored_failures, cpu);
+	}
+
+	if (0 == eeh_subsystem_enabled) {
+		seq_printf(m, "EEH Subsystem is globally disabled\n");
+		seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs);
+	} else {
+		seq_printf(m, "EEH Subsystem is enabled\n");
+		seq_printf(m, "eeh_total_mmio_ffs=%ld\n"
+			   "eeh_false_positives=%ld\n"
+			   "eeh_ignored_failures=%ld\n",
+			   ffs, positives, failures);
+	}
+
+	return 0;
 }
 
-/* Implementation of /proc/ppc64/eeh
- * For now it is one file showing false positives.
- */
+static int proc_eeh_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_eeh_show, NULL);
+}
+
+static struct file_operations proc_eeh_operations = {
+	.open		= proc_eeh_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static int __init eeh_init_proc(void)
 {
-	struct proc_dir_entry *ent = create_proc_entry("ppc64/eeh", S_IRUGO, 0);
-	if (ent) {
-		ent->nlink = 1;
-		ent->data = NULL;
-		ent->read_proc = (void *)eeh_proc_falsepositive_read;
+	struct proc_dir_entry *e;
+
+	if (systemcfg->platform & PLATFORM_PSERIES) {
+		e = create_proc_entry("ppc64/eeh", 0, NULL);
+		if (e)
+			e->proc_fops = &proc_eeh_operations;
 	}
-	return 0;
+
+        return 0;
 }
+__initcall(eeh_init_proc);
 
 /*
  * Test if "dev" should be configured on or off.
@@ -386,10 +777,12 @@
 	strs[nstrs++] = classname;
 	strs[nstrs++] = "";	/* yes, this matches the empty string */
 
-	/* Now see if any string matches the eeh_opts list.
+	/*
+	 * 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 (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;
@@ -399,7 +792,8 @@
 	return ret;
 }
 
-/* Handle kernel eeh-on & eeh-off cmd line options for eeh.
+/*
+ * Handle kernel eeh-on & eeh-off cmd line options for eeh.
  *
  * We support:
  *	eeh-off=loc1,loc2,loc3...
@@ -420,7 +814,8 @@
  * so eeh-off means eeh by default is off.
  */
 
-/* This is implemented as a null separated list of strings.
+/*
+ * 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.
@@ -428,10 +823,10 @@
  * 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 */
@@ -446,15 +841,17 @@
 		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++;	/* ignore empties.  Don't treat as "all-on" or "all-off" */
+			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_INFO "EEH: sorry...too many eeh cmd line options\n");
+				printk(KERN_WARNING "EEH: sorry...too many "
+				       "eeh cmd line options\n");
 				return 1;
 			}
 			eeh_opts[eeh_opts_last++] = state ? '+' : '-';
@@ -463,6 +860,7 @@
 			eeh_opts[eeh_opts_last++] = '\0';
 		}
 	}
+
 	return 1;
 }
 
@@ -476,6 +874,5 @@
 	return eeh_parm(str, 1);
 }
 
-__initcall(eeh_init_proc);
 __setup("eeh-off", eehoff_parm);
 __setup("eeh-on", eehon_parm);
diff -Nru a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c
--- a/arch/ppc64/kernel/iSeries_VpdInfo.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/iSeries_VpdInfo.c	Wed Mar 17 19:29:09 2004
@@ -27,6 +27,7 @@
 /************************************************************************/
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/types.h>
 #include <asm/resource.h>
@@ -105,6 +106,7 @@
 	strcpy(&LocationPtr->CardLocation[0], &DevNode->CardLocation[0]);
 	return LocationPtr;
 }
+EXPORT_SYMBOL(iSeries_GetLocationData);
 
 /*
  * Formats the device information.
diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
--- a/arch/ppc64/kernel/iSeries_pci.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/iSeries_pci.c	Wed Mar 17 19:29:10 2004
@@ -26,6 +26,7 @@
 #include <linux/list.h> 
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/ide.h>
 #include <linux/pci.h>
 
@@ -472,6 +473,7 @@
 	}
 	return dest;
 }
+EXPORT_SYMBOL(iSeries_memset_io);
 
 void *iSeries_memcpy_toio(void *dest, void *source, size_t count)
 {
@@ -485,6 +487,7 @@
 	}
 	return dest;
 }
+EXPORT_SYMBOL(iSeries_memcpy_toio);
 
 void *iSeries_memcpy_fromio(void *dest, void *source, size_t count)
 {
@@ -498,6 +501,7 @@
 	}
 	return dest;
 }
+EXPORT_SYMBOL(iSeries_memcpy_fromio);
 
 /*
  * Look down the chain to find the matching Device Device
@@ -708,6 +712,7 @@
 
 	return (u8)ret.value;
 }
+EXPORT_SYMBOL(iSeries_Read_Byte);
 
 u16 iSeries_Read_Word(void *IoAddress)
 {
@@ -737,6 +742,7 @@
 
 	return swab16((u16)ret.value);
 }
+EXPORT_SYMBOL(iSeries_Read_Word);
 
 u32 iSeries_Read_Long(void *IoAddress)
 {
@@ -766,6 +772,7 @@
 
 	return swab32((u32)ret.value);
 }
+EXPORT_SYMBOL(iSeries_Read_Long);
 
 /*
  * Write MM I/O Instructions for the iSeries
@@ -799,6 +806,7 @@
 		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
 	} while (CheckReturnCode("WWB", DevNode, rc) != 0);
 }
+EXPORT_SYMBOL(iSeries_Write_Byte);
 
 void iSeries_Write_Word(u16 data, void *IoAddress)
 {
@@ -825,6 +833,7 @@
 		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
 	} while (CheckReturnCode("WWW", DevNode, rc) != 0);
 }
+EXPORT_SYMBOL(iSeries_Write_Word);
 
 void iSeries_Write_Long(u32 data, void *IoAddress)
 {
@@ -851,6 +860,7 @@
 		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
 	} while (CheckReturnCode("WWL", DevNode, rc) != 0);
 }
+EXPORT_SYMBOL(iSeries_Write_Long);
 
 void pcibios_name_device(struct pci_dev *dev)
 {
diff -Nru a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c
--- a/arch/ppc64/kernel/iSeries_pci_reset.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/iSeries_pci_reset.c	Wed Mar 17 19:29:10 2004
@@ -29,6 +29,7 @@
 /************************************************************************/
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/irq.h>
 
@@ -100,3 +101,4 @@
 	}
 	return DeviceNode->ReturnCode;
 }
+EXPORT_SYMBOL(iSeries_Device_ToggleReset);
diff -Nru a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c
--- a/arch/ppc64/kernel/iSeries_proc.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/iSeries_proc.c	Wed Mar 17 19:29:09 2004
@@ -1,131 +1,162 @@
 /*
-  * iSeries_proc.c
-  * Copyright (C) 2001  Kyle A. Lucke IBM Corporation
-  * 
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-  * the Free Software Foundation; either version 2 of the License, or
-  * (at your option) any later version.
-  * 
-  * This program is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  * GNU General Public License for more details.
-  * 
-  * You should have received a copy of the GNU General Public License
-  * along with this program; if not, write to the Free Software
-  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-  */
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
+ * iSeries_proc.c
+ * Copyright (C) 2001  Kyle A. Lucke IBM Corporation
+ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
 #include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/paca.h>
+#include <asm/processor.h>
+#include <asm/time.h>
+#include <asm/naca.h>
+#include <asm/iSeries/ItLpPaca.h>
+#include <asm/iSeries/ItLpQueue.h>
+#include <asm/iSeries/HvCallXm.h>
+#include <asm/iSeries/IoHriMainStore.h>
+#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/iSeries_proc.h>
 
-static struct proc_dir_entry *iSeries_proc_root;
-static int iSeries_proc_initializationDone;
-static spinlock_t iSeries_proc_lock;
-
-struct iSeries_proc_registration {
-	struct iSeries_proc_registration *next;
-	iSeriesProcFunction functionMember;
+static int __init iseries_proc_create(void)
+{
+	struct proc_dir_entry *e = proc_mkdir("iSeries", 0);
+	if (!e)
+		return 1;
+
+	return 0;
+}
+core_initcall(iseries_proc_create);
+
+static char *event_types[9] = {
+	"Hypervisor\t\t",
+	"Machine Facilities\t",
+	"Session Manager\t",
+	"SPD I/O\t\t",
+	"Virtual Bus\t\t",
+	"PCI I/O\t\t",
+	"RIO I/O\t\t",
+	"Virtual Lan\t\t",
+	"Virtual I/O\t\t"
 };
 
-struct iSeries_proc_registration preallocated[16];
+static int proc_lpevents_show(struct seq_file *m, void *v)
+{
+	unsigned int i;
+
+	seq_printf(m, "LpEventQueue 0\n");
+	seq_printf(m, "  events processed:\t%lu\n",
+		   (unsigned long)xItLpQueue.xLpIntCount);
 
-#define MYQUEUETYPE(T) struct MYQueue##T
-#define MYQUEUE(T) \
-MYQUEUETYPE(T) \
-{ \
-	struct T *head; \
-	struct T *tail; \
-}
-#define MYQUEUECTOR(q) do { (q)->head = NULL; (q)->tail = NULL; } while(0)
-#define MYQUEUEENQ(q, p) \
-do { \
-	(p)->next = NULL; \
-	if ((q)->head != NULL) { \
-		(q)->head->next = (p); \
-		(q)->head = (p); \
-	} else { \
-		(q)->tail = (q)->head = (p); \
-	} \
-} while(0)
-
-#define MYQUEUEDEQ(q,p) \
-do { \
-	(p) = (q)->tail; \
-	if ((p) != NULL) { \
-		(q)->tail = (p)->next; \
-		(p)->next = NULL; \
-	} \
-	if ((q)->tail == NULL) \
-		(q)->head = NULL; \
-} while(0)
-
-MYQUEUE(iSeries_proc_registration);
-typedef MYQUEUETYPE(iSeries_proc_registration) aQueue;
-
-static aQueue iSeries_free;
-static aQueue iSeries_queued;
-
-void iSeries_proc_early_init(void)
-{
-	int i = 0;
-	unsigned long flags;
-
-	iSeries_proc_initializationDone = 0;
-	spin_lock_init(&iSeries_proc_lock);
-	MYQUEUECTOR(&iSeries_free);
-	MYQUEUECTOR(&iSeries_queued);
-
-	spin_lock_irqsave(&iSeries_proc_lock, flags);
-	for (i = 0; i < 16; ++i)
-		MYQUEUEENQ(&iSeries_free, preallocated + i);
-	spin_unlock_irqrestore(&iSeries_proc_lock, flags);
-}
-
-static int iSeries_proc_create(void)
-{
-	unsigned long flags;
-	struct iSeries_proc_registration *reg;
-
-	printk("iSeries_proc: Creating /proc/iSeries\n");
-
-	spin_lock_irqsave(&iSeries_proc_lock, flags);
-	iSeries_proc_root = proc_mkdir("iSeries", 0);
-	if (!iSeries_proc_root)
-		goto out;
-
-	MYQUEUEDEQ(&iSeries_queued, reg);
-	while (reg != NULL) {
-		(*(reg->functionMember))(iSeries_proc_root);
-		MYQUEUEDEQ(&iSeries_queued, reg);
-	}
+	for (i = 0; i < 9; ++i)
+		seq_printf(m, "    %s %10lu\n", event_types[i],
+			   (unsigned long)xItLpQueue.xLpIntCountByType[i]);
+
+	seq_printf(m, "\n  events processed by processor:\n");
+
+	for_each_online_cpu(i)
+		seq_printf(m, "    CPU%02d  %10u\n", i, paca[i].lpEvent_count);
 
-	iSeries_proc_initializationDone = 1;
-out:
-	spin_unlock_irqrestore(&iSeries_proc_lock, flags);
 	return 0;
 }
 
-arch_initcall(iSeries_proc_create);
+static int proc_lpevents_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_lpevents_show, NULL);
+}
+
+static struct file_operations proc_lpevents_operations = {
+	.open		= proc_lpevents_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
-void iSeries_proc_callback(iSeriesProcFunction initFunction)
+static unsigned long startTitan = 0;
+static unsigned long startTb = 0;
+
+static int proc_titantod_show(struct seq_file *m, void *v)
 {
-	unsigned long flags;
+	unsigned long tb0, titan_tod;
+
+	tb0 = get_tb();
+	titan_tod = HvCallXm_loadTod();
 
-	spin_lock_irqsave(&iSeries_proc_lock, flags);
-	if (iSeries_proc_initializationDone)
-		(*initFunction)(iSeries_proc_root);
-	else {
-		struct iSeries_proc_registration *reg = NULL;
-
-		MYQUEUEDEQ(&iSeries_free, reg);
-		if (reg != NULL) {
-			reg->functionMember = initFunction;
-			MYQUEUEENQ(&iSeries_queued, reg);
-		} else
-			printk("Couldn't get a queue entry\n");
+	seq_printf(m, "Titan\n" );
+	seq_printf(m, "  time base =          %016lx\n", tb0);
+	seq_printf(m, "  titan tod =          %016lx\n", titan_tod);
+	seq_printf(m, "  xProcFreq =          %016x\n",
+		   xIoHriProcessorVpd[0].xProcFreq);
+	seq_printf(m, "  xTimeBaseFreq =      %016x\n",
+		   xIoHriProcessorVpd[0].xTimeBaseFreq);
+	seq_printf(m, "  tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy);
+	seq_printf(m, "  tb_ticks_per_usec  = %lu\n", tb_ticks_per_usec);
+
+	if (!startTitan) {
+		startTitan = titan_tod;
+		startTb = tb0;
+	} else {
+		unsigned long titan_usec = (titan_tod - startTitan) >> 12;
+		unsigned long tb_ticks = (tb0 - startTb);
+		unsigned long titan_jiffies = titan_usec / (1000000/HZ);
+		unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ);
+		unsigned long titan_jiff_rem_usec = titan_usec - titan_jiff_usec;
+		unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy;
+		unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy;
+		unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks;
+		unsigned long tb_jiff_rem_usec = tb_jiff_rem_ticks / tb_ticks_per_usec;
+		unsigned long new_tb_ticks_per_jiffy = (tb_ticks * (1000000/HZ))/titan_usec;
+
+		seq_printf(m, "  titan elapsed = %lu uSec\n", titan_usec);
+		seq_printf(m, "  tb elapsed    = %lu ticks\n", tb_ticks);
+		seq_printf(m, "  titan jiffies = %lu.%04lu \n", titan_jiffies,
+			   titan_jiff_rem_usec);
+		seq_printf(m, "  tb jiffies    = %lu.%04lu\n", tb_jiffies,
+			   tb_jiff_rem_usec);
+		seq_printf(m, "  new tb_ticks_per_jiffy = %lu\n",
+			   new_tb_ticks_per_jiffy);
 	}
-	spin_unlock_irqrestore(&iSeries_proc_lock, flags);
+
+	return 0;
+}
+
+static int proc_titantod_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_titantod_show, NULL);
+}
+
+static struct file_operations proc_titantod_operations = {
+	.open		= proc_titantod_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init iseries_proc_init(void)
+{
+	struct proc_dir_entry *e;
+
+	e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
+	if (e)
+		e->proc_fops = &proc_lpevents_operations;
+
+	e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
+	if (e)
+		e->proc_fops = &proc_titantod_operations;
+
+	return 0;
 }
+__initcall(iseries_proc_init);
diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
--- a/arch/ppc64/kernel/iSeries_setup.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/iSeries_setup.c	Wed Mar 17 19:29:10 2004
@@ -51,7 +51,6 @@
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/IoHriMainStore.h>
 #include <asm/iSeries/iSeries_proc.h>
-#include <asm/proc_pmc.h>
 #include <asm/iSeries/mf.h>
 
 /* Function Prototypes */
@@ -393,12 +392,9 @@
 
 	iSeries_setup_dprofile();
 
-	iSeries_proc_early_init();
 	mf_init();
 	mf_initialized = 1;
 	mb();
-
-	iSeries_proc_callback(&pmc_proc_init);
 }
 
 /*
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/irq.c	Wed Mar 17 19:29:09 2004
@@ -66,7 +66,7 @@
 		.lock = SPIN_LOCK_UNLOCKED
 	}
 };
-	
+
 int ppc_spurious_interrupts = 0;
 unsigned long lpEvent_count = 0;
 
@@ -183,6 +183,7 @@
 	return -ENOENT;
 }
 
+
 int request_irq(unsigned int irq,
 	irqreturn_t (*handler)(int, void *, struct pt_regs *),
 	unsigned long irqflags, const char * devname, void *dev_id)
@@ -195,25 +196,25 @@
 	if (!handler)
 		/* We could implement really free_irq() instead of that... */
 		return do_free_irq(irq, dev_id);
-	
+
 	action = (struct irqaction *)
 		kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 	if (!action) {
 		printk(KERN_ERR "kmalloc() failed for irq %d !\n", irq);
 		return -ENOMEM;
 	}
-	
+
 	action->handler = handler;
-	action->flags = irqflags;					
+	action->flags = irqflags;
 	action->mask = 0;
 	action->name = devname;
 	action->dev_id = dev_id;
 	action->next = NULL;
-	
+
 	retval = setup_irq(irq, action);
 	if (retval)
 		kfree(action);
-		
+
 	return 0;
 }
 
@@ -342,13 +343,13 @@
 		action = irq_desc[i].action;
 		if (!action || !action->handler)
 			goto skip;
-		seq_printf(p, "%3d: ", i);		
+		seq_printf(p, "%3d: ", i);
 #ifdef CONFIG_SMP
 		for (j = 0; j < NR_CPUS; j++) {
 			if (cpu_online(j))
 				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 		}
-#else		
+#else
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif /* CONFIG_SMP */
 		if (irq_desc[i].handler)		
@@ -373,8 +374,10 @@
 	int status = 0;
 	int retval = 0;
 
+#ifndef CONFIG_PPC_ISERIES
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
+#endif
 
 	do {
 		status |= action->flags;
@@ -383,7 +386,9 @@
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
+#ifndef CONFIG_PPC_ISERIES
 	local_irq_disable();
+#endif
 	return retval;
 }
 
@@ -577,13 +582,13 @@
 	irq_enter();
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
-	/* Debugging check for stack overflow: is there less than 8KB free? */
+	/* Debugging check for stack overflow: is there less than 4KB free? */
 	{
 		long sp;
 
 		sp = __get_SP() & (THREAD_SIZE-1);
 
-		if (unlikely(sp < (sizeof(struct thread_info) + 8192))) {
+		if (unlikely(sp < (sizeof(struct thread_info) + 4096))) {
 			printk("do_IRQ: stack overflow: %ld\n",
 				sp - sizeof(struct thread_info));
 			dump_stack();
@@ -670,7 +675,7 @@
 		return;
 
 	once++;
-	
+
 	ppc_md.init_IRQ();
 }
 
@@ -699,6 +704,7 @@
 {
 	int irq = (long)data, full_count = count, err;
 	cpumask_t new_value, tmp;
+	cpumask_t allcpus = CPU_MASK_ALL;
 
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
@@ -708,6 +714,14 @@
 		return err;
 
 	/*
+	 * We check for CPU_MASK_ALL in xics to send irqs to all cpus.
+	 * In some cases CPU_MASK_ALL is smaller than the cpumask (eg
+	 * NR_CPUS == 32 and cpumask is a long), so we mask it here to
+	 * be consistent.
+	 */
+	cpus_and(new_value, new_value, allcpus);
+
+	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
 	 * way to make the system unusable accidentally :-) At least
 	 * one online CPU still has to be targeted.
@@ -899,5 +913,38 @@
 	}
 	return NO_IRQ;
 }
+
+/*
+ * In most cases will get a hit on the very first slot checked in the
+ * virt_irq_to_real_map.  Only when there are a large number of
+ * IRQs will this be expensive.
+ */
+unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
+{
+	unsigned int virq;
+	unsigned int first_virq;
+
+	virq = real_irq;
+
+	if (virq > MAX_VIRT_IRQ)
+		virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+
+	first_virq = virq;
+
+	do {
+		if (virt_irq_to_real_map[virq] == real_irq)
+			return virq;
+
+		virq++;
+
+		if (virq >= MAX_VIRT_IRQ)
+			virq = 0;
+
+	} while (first_virq != virq);
+
+	return NO_IRQ;
+
+}
+
 
 #endif
diff -Nru a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
--- a/arch/ppc64/kernel/mf.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/mf.c	Wed Mar 17 19:29:10 2004
@@ -30,13 +30,13 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <asm/iSeries/HvLpConfig.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <asm/nvram.h>
 #include <asm/time.h>
 #include <asm/iSeries/ItSpCommArea.h>
-#include <asm/iSeries/iSeries_proc.h>
 #include <asm/uaccess.h>
 #include <linux/dma-mapping.h>
 #include <linux/bcd.h>
@@ -560,6 +560,7 @@
 	if ((rc != 0) && (hdlr != NULL))
 		(*hdlr)(userToken, rc);
 }
+EXPORT_SYMBOL(mf_allocateLpEvents);
 
 /*
  * Global kernel interface to unseed and deallocate events already in
@@ -590,6 +591,7 @@
 	if ((rc != 0) && (hdlr != NULL))
 		(*hdlr)(userToken, rc);
 }
+EXPORT_SYMBOL(mf_deallocateLpEvents);
 
 /*
  * Global kernel interface to tell the VSP object in the primary
@@ -680,8 +682,6 @@
 
 	/* initialization complete */
 	printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities initialized\n");
-
-	iSeries_proc_callback(&mf_proc_init);
 }
 
 void mf_setSide(char side)
diff -Nru a/arch/ppc64/kernel/mf_proc.c b/arch/ppc64/kernel/mf_proc.c
--- a/arch/ppc64/kernel/mf_proc.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/mf_proc.c	Wed Mar 17 19:29:09 2004
@@ -16,11 +16,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
+#include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/iSeries/mf.h>
 
-static struct proc_dir_entry *mf_proc_root = NULL;
-
 static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
 		int count, int *eof, void *data)
 {
@@ -187,27 +186,28 @@
 	return count;			
 }
 
-void mf_proc_init(struct proc_dir_entry *iSeries_proc)
+static int __init mf_proc_init(void)
 {
+	struct proc_dir_entry *mf_proc_root;
 	struct proc_dir_entry *ent;
 	struct proc_dir_entry *mf;
 	char name[2];
 	int i;
 
-	mf_proc_root = proc_mkdir("mf", iSeries_proc);
+	mf_proc_root = proc_mkdir("iSeries/mf", NULL);
 	if (!mf_proc_root)
-		return;
+		return 1;
 
 	name[1] = '\0';
 	for (i = 0; i < 4; i++) {
 		name[0] = 'A' + i;
 		mf = proc_mkdir(name, mf_proc_root);
 		if (!mf)
-			return;
+			return 1;
 
 		ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf);
 		if (!ent)
-			return;
+			return 1;
 		ent->nlink = 1;
 		ent->data = (void *)(long)i;
 		ent->read_proc = proc_mf_dump_cmdline;
@@ -218,7 +218,7 @@
 
 		ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);
 		if (!ent)
-			return;
+			return 1;
 		ent->nlink = 1;
 		ent->data = (void *)(long)i;
 #if 0
@@ -239,7 +239,7 @@
 
 	ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
 	if (!ent)
-		return;
+		return 1;
 	ent->nlink = 1;
 	ent->data = (void *)0;
 	ent->read_proc = proc_mf_dump_side;
@@ -247,9 +247,13 @@
 
 	ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
 	if (!ent)
-		return;
+		return 1;
 	ent->nlink = 1;
 	ent->data = (void *)0;
 	ent->read_proc = proc_mf_dump_src;
 	ent->write_proc = proc_mf_change_src;
+
+	return 0;
 }
+
+__initcall(mf_proc_init);
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/misc.S	Wed Mar 17 19:29:10 2004
@@ -624,7 +624,7 @@
 	.llong .sys_geteuid
 	.llong .sys_getegid		/* 50 */
 	.llong .sys_acct
-	.llong .sys32_umount
+	.llong .sys_umount
 	.llong .sys_ni_syscall		/* old lock syscall */
 	.llong .compat_sys_ioctl
 	.llong .compat_sys_fcntl		/* 55 */
diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
--- a/arch/ppc64/kernel/pSeries_lpar.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/pSeries_lpar.c	Wed Mar 17 19:29:10 2004
@@ -37,6 +37,12 @@
 #include <asm/hvcall.h>
 #include <asm/prom.h>
 
+/* in pSeries_hvCall.S */
+EXPORT_SYMBOL(plpar_hcall);
+EXPORT_SYMBOL(plpar_hcall_4out);
+EXPORT_SYMBOL(plpar_hcall_norets);
+EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
+
 long poll_pending(void)
 {
 	unsigned long dummy;
diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/pci.c	Wed Mar 17 19:29:10 2004
@@ -119,43 +119,6 @@
 	}
 }
 
-/* Given an mmio phys address, find a pci device that implements
- * this address.  This is of course expensive, but only used
- * for device initialization or error paths.
- * For io BARs it is assumed the pci_io_base has already been added
- * into addr.
- *
- * Bridges are ignored although they could be used to optimize the search.
- */
-struct pci_dev *pci_find_dev_by_addr(unsigned long addr)
-{
-	struct pci_dev *dev = NULL;
-	int i;
-	unsigned long ioaddr;
-
-	ioaddr = (addr > isa_io_base) ? addr - isa_io_base : 0;
-
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
-			continue;
-		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-			unsigned long start = pci_resource_start(dev,i);
-			unsigned long end = pci_resource_end(dev,i);
-			unsigned int flags = pci_resource_flags(dev,i);
-			if (start == 0 || ~start == 0 ||
-			    end == 0 || ~end == 0)
-				continue;
-			if ((flags & IORESOURCE_IO) &&
-			    (ioaddr >= start && ioaddr <= end))
-				return dev;
-			else if ((flags & IORESOURCE_MEM) &&
-				 (addr >= start && addr <= end))
-				return dev;
-		}
-	}
-	return NULL;
-}
-
 void 
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 			struct resource *res)
@@ -358,6 +321,10 @@
 
 	printk("PCI: Probing PCI hardware done\n");
 	//ppc64_boot_msg(0x41, "PCI Done");
+
+#ifdef CONFIG_PPC_PSERIES
+	pci_addr_cache_build();
+#endif
 
 	return 0;
 }
diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
--- a/arch/ppc64/kernel/pci.h	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/pci.h	Wed Mar 17 19:29:09 2004
@@ -37,11 +37,14 @@
 void *traverse_pci_devices(struct device_node *start, traverse_func pre, traverse_func post, void *data);
 void *traverse_all_pci_devices(traverse_func pre);
 
-struct pci_dev *pci_find_dev_by_addr(unsigned long addr);
 void pci_devs_phb_init(void);
 void pci_fix_bus_sysdata(void);
 struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
 #define PCI_GET_PHB_PTR(dev)    (((struct device_node *)(dev)->sysdata)->phb)
+
+/* PCI address cache management routines */
+void pci_addr_cache_insert_device(struct pci_dev *dev);
+void pci_addr_cache_remove_device(struct pci_dev *dev);
 
 #endif /* __PPC_KERNEL_PCI_H__ */
diff -Nru a/arch/ppc64/kernel/pmac_iommu.c b/arch/ppc64/kernel/pmac_iommu.c
--- a/arch/ppc64/kernel/pmac_iommu.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/pmac_iommu.c	Wed Mar 17 19:29:10 2004
@@ -289,8 +289,11 @@
 	 * things simple. Setup all PCI devices to point to this table
 	 */
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		dn = PCI_GET_DN(dev);
-
+		/* We must use pci_device_to_OF_node() to make sure that
+		 * we get the real "final" pointer to the device in the
+		 * pci_dev sysdata and not the temporary PHB one
+		 */
+		struct device_node *dn = pci_device_to_OF_node(dev);
 		if (dn)
 			dn->iommu_table = &iommu_table_pmac;
 	}
diff -Nru a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
--- a/arch/ppc64/kernel/pmc.c	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,167 +0,0 @@
-/*
- * pmc.c
- * Copyright (C) 2001 Dave Engebretsen & Mike Corrigan IBM Corporation
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * 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
- */
-
-/* Change Activity:
- * 2001/06/05 : engebret : Created.
- * End Change Activity 
- */
-
-#include <asm/proc_fs.h>
-#include <asm/paca.h>
-#include <asm/iSeries/ItLpPaca.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/processor.h>
-
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <asm/pmc.h>
-#include <asm/uaccess.h>
-#include <asm/naca.h>
-
-struct _pmc_sw pmc_sw_system = {
-	0  
-};
-
-struct _pmc_sw pmc_sw_cpu[NR_CPUS] = {
-	{0 }, 
-};
-
-/*
- * Provide enough storage for either system level counters or
- * one cpu's counters.
- */
-struct _pmc_sw_text pmc_sw_text;
-struct _pmc_hw_text pmc_hw_text;
-
-char *
-ppc64_pmc_stab(int file)
-{
-	int  n;
-	unsigned long stab_faults, stab_capacity_castouts, stab_invalidations; 
-	unsigned long i;
-
-	stab_faults = stab_capacity_castouts = stab_invalidations = n = 0;
-
-	if (file == -1) {
-		for (i = 0;  i < NR_CPUS; i++) {
-			if (!cpu_online(i))
-				continue;
-			stab_faults += pmc_sw_cpu[i].stab_faults;
-			stab_capacity_castouts += pmc_sw_cpu[i].stab_capacity_castouts;
-			stab_invalidations += pmc_sw_cpu[i].stab_invalidations;
-		}
-		n += sprintf(pmc_sw_text.buffer + n,    
-			     "Faults         0x%lx\n", stab_faults); 
-		n += sprintf(pmc_sw_text.buffer + n, 
-			     "Castouts       0x%lx\n", stab_capacity_castouts); 
-		n += sprintf(pmc_sw_text.buffer + n, 
-			     "Invalidations  0x%lx\n", stab_invalidations); 
-	} else {
-		n += sprintf(pmc_sw_text.buffer + n,
-			     "Faults         0x%lx\n", 
-			     pmc_sw_cpu[file].stab_faults);
-		
-		n += sprintf(pmc_sw_text.buffer + n,   
-			     "Castouts       0x%lx\n", 
-			     pmc_sw_cpu[file].stab_capacity_castouts);
-		
-		n += sprintf(pmc_sw_text.buffer + n,   
-			     "Invalidations  0x%lx\n", 
-			     pmc_sw_cpu[file].stab_invalidations);
-
-		for (i = 0; i < STAB_ENTRY_MAX; i++) {
-			if (pmc_sw_cpu[file].stab_entry_use[i]) {
-				n += sprintf(pmc_sw_text.buffer + n,   
-					     "Entry %02ld       0x%lx\n", i, 
-					     pmc_sw_cpu[file].stab_entry_use[i]);
-			}
-		}
-
-	}
-
-	return(pmc_sw_text.buffer); 
-}
-
-char *
-ppc64_pmc_htab(int file)
-{
-	int  n;
-	unsigned long htab_primary_overflows, htab_capacity_castouts;
-	unsigned long htab_read_to_write_faults; 
-
-	htab_primary_overflows = htab_capacity_castouts = 0;
-	htab_read_to_write_faults = n = 0;
-
-	if (file == -1) {
-		n += sprintf(pmc_sw_text.buffer + n,    
-			     "Primary Overflows  0x%lx\n", 
-			     pmc_sw_system.htab_primary_overflows); 
-		n += sprintf(pmc_sw_text.buffer + n, 
-			     "Castouts           0x%lx\n", 
-			     pmc_sw_system.htab_capacity_castouts); 
-	} else {
-		n += sprintf(pmc_sw_text.buffer + n,
-			     "Primary Overflows  N/A\n");
-
-		n += sprintf(pmc_sw_text.buffer + n,   
-			     "Castouts           N/A\n\n");
-
-	}
-	
-	return(pmc_sw_text.buffer); 
-}
-
-char *
-ppc64_pmc_hw(int file)
-{
-	int  n;
-
-	n = 0;
-	if (file == -1) {
-		n += sprintf(pmc_hw_text.buffer + n, "Not Implemented\n");
-	} else {
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "MMCR0  0x%lx\n", mfspr(MMCR0)); 
-		n += sprintf(pmc_hw_text.buffer + n, 
-			     "MMCR1  0x%lx\n", mfspr(MMCR1)); 
-#if 0
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "MMCRA  0x%lx\n", mfspr(MMCRA)); 
-#endif
-
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC1   0x%lx\n", mfspr(PMC1)); 
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC2   0x%lx\n", mfspr(PMC2)); 
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC3   0x%lx\n", mfspr(PMC3)); 
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC4   0x%lx\n", mfspr(PMC4)); 
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC5   0x%lx\n", mfspr(PMC5)); 
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC6   0x%lx\n", mfspr(PMC6)); 
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC7   0x%lx\n", mfspr(PMC7)); 
-		n += sprintf(pmc_hw_text.buffer + n,    
-			     "PMC8   0x%lx\n", mfspr(PMC8)); 
-	}
-
-	return(pmc_hw_text.buffer); 
-}
diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
--- a/arch/ppc64/kernel/ppc_ksyms.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/ppc_ksyms.c	Wed Mar 17 19:29:09 2004
@@ -40,13 +40,8 @@
 #include <asm/hw_irq.h>
 #include <asm/abs_addr.h>
 #include <asm/cacheflush.h>
-#include <asm/proc_fs.h>
 #ifdef CONFIG_PPC_ISERIES
-#include <asm/iSeries/iSeries_pci.h>
-#include <asm/iSeries/iSeries_proc.h>
-#include <asm/iSeries/mf.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvLpConfig.h>
+#include <asm/iSeries/HvCallSc.h>
 #endif
 
 extern int do_signal(sigset_t *, struct pt_regs *);
@@ -59,9 +54,6 @@
 EXPORT_SYMBOL(isa_io_base);
 EXPORT_SYMBOL(pci_io_base);
 
-EXPORT_SYMBOL(find_next_zero_bit);
-EXPORT_SYMBOL(find_next_zero_le_bit);
-
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strncpy);
 EXPORT_SYMBOL(strcat);
@@ -98,7 +90,6 @@
 EXPORT_SYMBOL(reloc_offset);
 
 #ifdef CONFIG_PPC_ISERIES
-EXPORT_SYMBOL(iSeries_proc_callback);
 EXPORT_SYMBOL(HvCall0);
 EXPORT_SYMBOL(HvCall1);
 EXPORT_SYMBOL(HvCall2);
@@ -107,11 +98,6 @@
 EXPORT_SYMBOL(HvCall5);
 EXPORT_SYMBOL(HvCall6);
 EXPORT_SYMBOL(HvCall7);
-EXPORT_SYMBOL(HvLpEvent_unregisterHandler);
-EXPORT_SYMBOL(HvLpEvent_registerHandler);
-EXPORT_SYMBOL(mf_allocateLpEvents);
-EXPORT_SYMBOL(mf_deallocateLpEvents);
-EXPORT_SYMBOL(HvLpConfig_getLpIndex_outline);
 #endif
 
 EXPORT_SYMBOL(_insb);
@@ -128,32 +114,6 @@
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_alloc_consistent);
-EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_map_single);
-EXPORT_SYMBOL(pci_unmap_single);
-EXPORT_SYMBOL(pci_map_sg);
-EXPORT_SYMBOL(pci_unmap_sg);
-#ifdef CONFIG_PPC_ISERIES
-EXPORT_SYMBOL(iSeries_GetLocationData);
-EXPORT_SYMBOL(iSeries_Device_ToggleReset);
-EXPORT_SYMBOL(iSeries_memset_io);
-EXPORT_SYMBOL(iSeries_memcpy_toio);
-EXPORT_SYMBOL(iSeries_memcpy_fromio);
-EXPORT_SYMBOL(iSeries_Read_Byte);
-EXPORT_SYMBOL(iSeries_Read_Word);
-EXPORT_SYMBOL(iSeries_Read_Long);
-EXPORT_SYMBOL(iSeries_Write_Byte);
-EXPORT_SYMBOL(iSeries_Write_Word);
-EXPORT_SYMBOL(iSeries_Write_Long);
-#endif /* CONFIG_PPC_ISERIES */
-#ifndef CONFIG_PPC_ISERIES
-EXPORT_SYMBOL(eeh_check_failure);
-EXPORT_SYMBOL(eeh_total_mmio_ffs);
-#endif /* CONFIG_PPC_ISERIES */
-#endif /* CONFIG_PCI */
-
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
@@ -203,4 +163,5 @@
 
 EXPORT_SYMBOL(tb_ticks_per_usec);
 EXPORT_SYMBOL(paca);
-EXPORT_SYMBOL(proc_ppc64);
+EXPORT_SYMBOL(cur_cpu_spec);
+EXPORT_SYMBOL(systemcfg);
diff -Nru a/arch/ppc64/kernel/proc_pmc.c b/arch/ppc64/kernel/proc_pmc.c
--- a/arch/ppc64/kernel/proc_pmc.c	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,810 +0,0 @@
-/*
- * proc_pmc.c
- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * 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
- */
-
-
-/* Change Activity:
- * 2001       : mikec    : Created
- * 2001/06/05 : engebret : Software event count support.
- * End Change Activity 
- */
-
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-
-#include <asm/proc_fs.h>
-#include <asm/paca.h>
-#include <asm/iSeries/ItLpPaca.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/iSeries/HvCallXm.h>
-#include <asm/iSeries/IoHriMainStore.h>
-#include <asm/processor.h>
-#include <asm/time.h>
-#include <asm/iSeries/LparData.h>
-#include <asm/pmc.h>
-#include <asm/uaccess.h>
-#include <asm/naca.h>
-#include <asm/rtas.h>
-
-
-static int proc_pmc_control_mode = 0;
-
-static struct proc_dir_entry *proc_ppc64_pmc_system_root = NULL;
-static struct proc_dir_entry *proc_ppc64_pmc_cpu_root[NR_CPUS] = {NULL, };
-
-static spinlock_t proc_ppc64_lock;
-int proc_ppc64_pmc_find_file(void *data);
-int proc_ppc64_pmc_read(char *page, char **start, off_t off,
-			int count, int *eof, char *buffer);
-int proc_ppc64_pmc_stab_read(char *page, char **start, off_t off,
-			     int count, int *eof, void *data);
-int proc_ppc64_pmc_htab_read(char *page, char **start, off_t off,
-			     int count, int *eof, void *data);
-int proc_ppc64_pmc_hw_read(char *page, char **start, off_t off, 
-			   int count, int *eof, void *data);
-
-static struct proc_dir_entry *pmc_proc_root = NULL;
-
-int proc_get_lpevents( char *page, char **start, off_t off, int count, int *eof, void *data);
-int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data);
-
-int proc_get_titanTod( char *page, char **start, off_t off, int count, int *eof, void *data);
-
-int proc_pmc_get_control( char *page, char **start, off_t off, int count, int *eof, void *data);
-
-int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc1(  struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc2(  struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc3(  struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc4(  struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc5(  struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc6(  struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc7(  struct file *file, const char *buffer, unsigned long count, void *data);
-int proc_pmc_set_pmc8(  struct file *file, const char *buffer, unsigned long count, void *data);
-
-#if 0
-int proc_ppc64_init(void)
-{
-	unsigned long i;
-	struct proc_dir_entry *ent = NULL;
-	char buf[256];
-
-	printk("proc_ppc64: Creating /proc/ppc64/pmc\n");
-
-	/*
-	 * Create the root, system, and cpu directories as follows:
-	 *   /proc/ppc64/pmc/system 
-	 *   /proc/ppc64/pmc/cpu0 
-	 */
-	spin_lock(&proc_ppc64_lock);
-	if (proc_ppc64.root == NULL) {
-		proc_ppc64_init();
-		if (!proc_ppc64.root) {
-			spin_unlock(&proc_ppc64_lock);
-			return;
-		}
-	}
-	spin_unlock(&proc_ppc64_lock);
-
-	/* Placeholder for rtas interfaces. */
-	if (proc_ppc64.rtas == NULL) {
-		return;
-	}
-
-	proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64.root);
-
-	proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root);
-	for (i = 0; i < NR_CPUS; i++) {
-		if (cpu_online(i)) {
-			sprintf(buf, "cpu%ld", i); 
-			proc_ppc64_pmc_cpu_root[i] =
-				proc_mkdir(buf, proc_ppc64_pmc_root);
-		}
-	}
-
-	/* Create directories for the software counters. */
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_online(i))
-			continue;
-		ent = create_proc_entry("stab", S_IRUGO | S_IWUSR, 
-					proc_ppc64_pmc_cpu_root[i]);
-		if (ent) {
-			ent->nlink = 1;
-			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
-			ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
-			ent->write_proc = NULL;
-		}
-
-		ent = create_proc_entry("htab", S_IRUGO | S_IWUSR, 
-					proc_ppc64_pmc_cpu_root[i]);
-		if (ent) {
-			ent->nlink = 1;
-			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
-			ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
-			ent->write_proc = NULL;
-		}
-	}
-
-	ent = create_proc_entry("stab", S_IRUGO | S_IWUSR, 
-				proc_ppc64_pmc_system_root);
-	if (ent) {
-		ent->nlink = 1;
-		ent->data = (void *)proc_ppc64_pmc_system_root;
-		ent->read_proc = (void *)proc_ppc64_pmc_stab_read;
-		ent->write_proc = NULL;
-	}
-
-	ent = create_proc_entry("htab", S_IRUGO | S_IWUSR, 
-				proc_ppc64_pmc_system_root);
-	if (ent) {
-		ent->nlink = 1;
-		ent->data = (void *)proc_ppc64_pmc_system_root;
-		ent->read_proc = (void *)proc_ppc64_pmc_htab_read;
-		ent->write_proc = NULL;
-	}
-
-	/* Create directories for the hardware counters. */
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!cpu_online(i))
-			continue;
-		ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR, 
-					proc_ppc64_pmc_cpu_root[i]);
-		if (ent) {
-			ent->nlink = 1;
-			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];
-			ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
-			ent->write_proc = NULL;
-		}
-	}
-
-	ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR, 
-				proc_ppc64_pmc_system_root);
-	if (ent) {
-		ent->nlink = 1;
-		ent->data = (void *)proc_ppc64_pmc_system_root;
-		ent->read_proc = (void *)proc_ppc64_pmc_hw_read;
-		ent->write_proc = NULL;
-	}
-}
-#endif
-
-/*
- * Find the requested 'file' given a proc token.
- *
- * Inputs: void * data: proc token
- * Output: int        : (0, ..., +N) = CPU number.
- *                      -1           = System.
- */
-int proc_ppc64_pmc_find_file(void *data)
-{
-	int i;
-
-	if ((unsigned long)data == 
-	   (unsigned long) proc_ppc64_pmc_system_root) {
-		return(-1); 
-	} else {
-		for (i = 0; i < NR_CPUS; i++) {
-			if (!cpu_online(i))
-				continue;
-			if ((unsigned long)data ==
-			   (unsigned long)proc_ppc64_pmc_cpu_root[i]) {
-				return(i); 
-			}
-		}
-	}
-
-	/* On error, just default to a type of system. */
-	printk("proc_ppc64_pmc_find_file: failed to find file token.\n"); 
-	return(-1); 
-}
-
-int 
-proc_ppc64_pmc_read(char *page, char **start, off_t off, 
-		    int count, int *eof, char *buffer)
-{
-	int buffer_size, n;
-
-	if (count < 0) return 0;
-
-	if (buffer == NULL) {
-		*eof = 1;
-		return 0;
-	}
-
-	/* Check for read beyond EOF */
-	buffer_size = n = strlen(buffer);
-	if (off >= buffer_size) {
-		*eof = 1;
-		return 0;
-	}
-	if (n > (buffer_size - off)) n = buffer_size - off;
-
-	/* Never return more than was requested */
-	if (n > count) {
-		n = count;
-	} else {
-		*eof = 1;
-	}
-
-	memcpy(page, buffer + off, n);
-
-	*start = page;
-
-	return n;
-}
-
-int 
-proc_ppc64_pmc_stab_read(char *page, char **start, off_t off, 
-			 int count, int *eof, void *data)
-{
-	int n, file;
-	char *buffer = NULL;
-
-	if (count < 0) return 0;
-	spin_lock(&proc_ppc64_lock);
-
-	/* Figure out which file is being request. */
-	file = proc_ppc64_pmc_find_file(data);
-
-	/* Update the counters and the text buffer representation. */
-	buffer = ppc64_pmc_stab(file);
-
-	/* Put the data into the requestor's buffer. */
-	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer); 
-
-	spin_unlock(&proc_ppc64_lock);
-	return n;
-}
-
-int 
-proc_ppc64_pmc_htab_read(char *page, char **start, off_t off, 
-			 int count, int *eof, void *data)
-{
-	int n, file;
-	char *buffer = NULL;
-
-	if (count < 0) return 0;
-	spin_lock(&proc_ppc64_lock);
-
-	/* Figure out which file is being request. */
-	file = proc_ppc64_pmc_find_file(data);
-
-	/* Update the counters and the text buffer representation. */
-	buffer = ppc64_pmc_htab(file);
-
-	/* Put the data into the requestor's buffer. */
-	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
-
-	spin_unlock(&proc_ppc64_lock);
-	return n;
-}
-
-int 
-proc_ppc64_pmc_hw_read(char *page, char **start, off_t off, 
-			     int count, int *eof, void *data)
-{
-	int n, file;
-	char *buffer = NULL;
-
-	if (count < 0) return 0;
-	spin_lock(&proc_ppc64_lock);
-
-	/* Figure out which file is being request. */
-	file = proc_ppc64_pmc_find_file(data);
-
-	/* Update the counters and the text buffer representation. */
-	buffer = ppc64_pmc_hw(file);
-
-	/* Put the data into the requestor's buffer. */
-	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);
-
-	spin_unlock(&proc_ppc64_lock);
-	return n;
-}
-
-/* 
- * DRENG the remainder of these functions still need work ...
- */
-void pmc_proc_init(struct proc_dir_entry *iSeries_proc)
-{
-    struct proc_dir_entry *ent = NULL;
-
-    ent = create_proc_entry("lpevents", S_IFREG|S_IRUGO, iSeries_proc);
-    if (!ent) return;
-    ent->nlink = 1;
-    ent->data = (void *)0;
-    ent->read_proc = proc_get_lpevents;
-    ent->write_proc = proc_reset_lpevents;
-
-    ent = create_proc_entry("titanTod", S_IFREG|S_IRUGO, iSeries_proc);
-    if (!ent) return;
-    ent->nlink = 1;
-    ent->data = (void *)0;
-    ent->size = 0;
-    ent->read_proc = proc_get_titanTod;
-    ent->write_proc = NULL;
-
-    pmc_proc_root = proc_mkdir("pmc", iSeries_proc);
-    if (!pmc_proc_root) return;
-
-    ent = create_proc_entry("control", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root);
-    if (!ent) return;
-    ent->nlink = 1;
-    ent->data = (void *)0;
-    ent->read_proc = proc_pmc_get_control;
-    ent->write_proc = proc_pmc_set_control;
-
-}
-
-static int pmc_calc_metrics( char *page, char **start, off_t off, int count, int *eof, int len)
-{
-	if ( len <= off+count)
-		*eof = 1;
-	*start = page+off;
-	len -= off;
-	if ( len > count )
-		len = count;
-	if ( len < 0 )
-		len = 0;
-	return len;
-}
-
-static char * lpEventTypes[9] = {
-	"Hypervisor\t\t",
-	"Machine Facilities\t",
-	"Session Manager\t",
-	"SPD I/O\t\t",
-	"Virtual Bus\t\t",
-	"PCI I/O\t\t",
-	"RIO I/O\t\t",
-	"Virtual Lan\t\t",
-	"Virtual I/O\t\t"
-	};
-	
-
-int proc_get_lpevents
-(char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-	unsigned i;
-	int len = 0;
-
-	len += sprintf( page+len, "LpEventQueue 0\n" );
-	len += sprintf( page+len, "  events processed:\t%lu\n",
-			(unsigned long)xItLpQueue.xLpIntCount );
-	for (i=0; i<9; ++i) {
-		len += sprintf( page+len, "    %s %10lu\n",
-			lpEventTypes[i],
-			(unsigned long)xItLpQueue.xLpIntCountByType[i] );
-	}
-	len += sprintf( page+len, "\n  events processed by processor:\n" );
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (cpu_online(i))
-			len += sprintf( page+len, "    CPU%02d  %10u\n",
-				i, paca[i].lpEvent_count );
-	}
-
-	return pmc_calc_metrics( page, start, off, count, eof, len );
-
-}
-
-int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	return count;
-}
-
-static unsigned long startTitan = 0;
-static unsigned long startTb = 0;
-
-
-int proc_get_titanTod
-(char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-	int len = 0;
-	unsigned long tb0, titan_tod;
-
-	tb0 = get_tb();
-	titan_tod = HvCallXm_loadTod();
-
-	len += sprintf( page+len, "Titan\n" );
-	len += sprintf( page+len, "  time base =          %016lx\n", tb0 );
-	len += sprintf( page+len, "  titan tod =          %016lx\n", titan_tod );
-	len += sprintf( page+len, "  xProcFreq =          %016x\n", xIoHriProcessorVpd[0].xProcFreq );
-	len += sprintf( page+len, "  xTimeBaseFreq =      %016x\n", xIoHriProcessorVpd[0].xTimeBaseFreq );
-	len += sprintf( page+len, "  tb_ticks_per_jiffy = %lu\n", tb_ticks_per_jiffy );
-	len += sprintf( page+len, "  tb_ticks_per_usec  = %lu\n", tb_ticks_per_usec );
-
-	if ( !startTitan ) {
-		startTitan = titan_tod;
-		startTb = tb0;
-	}
-	else {
-		unsigned long titan_usec = (titan_tod - startTitan) >> 12;
-		unsigned long tb_ticks = (tb0 - startTb);
-		unsigned long titan_jiffies = titan_usec / (1000000/HZ);
-		unsigned long titan_jiff_usec = titan_jiffies * (1000000/HZ);
-		unsigned long titan_jiff_rem_usec = titan_usec - titan_jiff_usec;
-		unsigned long tb_jiffies = tb_ticks / tb_ticks_per_jiffy;
-		unsigned long tb_jiff_ticks = tb_jiffies * tb_ticks_per_jiffy;
-		unsigned long tb_jiff_rem_ticks = tb_ticks - tb_jiff_ticks;
-		unsigned long tb_jiff_rem_usec = tb_jiff_rem_ticks / tb_ticks_per_usec;
-		unsigned long new_tb_ticks_per_jiffy = (tb_ticks * (1000000/HZ))/titan_usec;
-		
-		len += sprintf( page+len, "  titan elapsed = %lu uSec\n", titan_usec);
-		len += sprintf( page+len, "  tb elapsed    = %lu ticks\n", tb_ticks);
-		len += sprintf( page+len, "  titan jiffies = %lu.%04lu \n", titan_jiffies, titan_jiff_rem_usec );				
-		len += sprintf( page+len, "  tb jiffies    = %lu.%04lu\n", tb_jiffies, tb_jiff_rem_usec );
-		len += sprintf( page+len, "  new tb_ticks_per_jiffy = %lu\n", new_tb_ticks_per_jiffy );	
-
-	}
-	
-	return pmc_calc_metrics( page, start, off, count, eof, len );
-}
-	
-int proc_pmc_get_control
-(char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-	int len = 0;
-
-	if ( proc_pmc_control_mode == PMC_CONTROL_CPI ) {
-		unsigned long mach_cycles   = mfspr( PMC5 );
-		unsigned long inst_complete = mfspr( PMC4 );
-		unsigned long inst_dispatch = mfspr( PMC3 );
-		unsigned long thread_active_run = mfspr( PMC1 );
-		unsigned long thread_active  = mfspr( PMC2 );
-		unsigned long cpi = 0;
-		unsigned long cpithou = 0;
-		unsigned long remain;
-	
-		if ( inst_complete ) {
-			cpi = thread_active_run / inst_complete;
-			remain = thread_active_run % inst_complete;
-			if ( inst_complete > 1000000 ) 
-				cpithou = remain / ( inst_complete / 1000 );
-			else 
-				cpithou = ( remain * 1000 ) / inst_complete;
-		}
-		len += sprintf( page+len, "PMC CPI Mode\nRaw Counts\n" );
-		len += sprintf( page+len, "machine cycles           : %12lu\n", mach_cycles );
-		len += sprintf( page+len, "thread active cycles     : %12lu\n\n", thread_active );
-
-		len += sprintf( page+len, "instructions completed   : %12lu\n", inst_complete );
-		len += sprintf( page+len, "instructions dispatched  : %12lu\n", inst_dispatch );
-		len += sprintf( page+len, "thread active run cycles : %12lu\n", thread_active_run );
-
-		len += sprintf( page+len, "thread active run cycles/instructions completed\n" );
-		len += sprintf( page+len, "CPI = %lu.%03lu\n", cpi, cpithou );
-		
-	}
-	else if ( proc_pmc_control_mode == PMC_CONTROL_TLB ) {
-		len += sprintf( page+len, "PMC TLB Mode\n" );
-		len += sprintf( page+len, "I-miss count             : %12lu\n", mfspr( PMC1 ) );
-		len += sprintf( page+len, "I-miss latency           : %12lu\n", mfspr( PMC2 ) );
-		len += sprintf( page+len, "D-miss count             : %12lu\n", mfspr( PMC3 ) );
-		len += sprintf( page+len, "D-miss latency           : %12lu\n", mfspr( PMC4 ) );
-		len += sprintf( page+len, "IERAT miss count         : %12lu\n", mfspr( PMC5 ) );
-		len += sprintf( page+len, "D-reference count        : %12lu\n", mfspr( PMC6 ) );
-		len += sprintf( page+len, "miss PTEs searched       : %12lu\n", mfspr( PMC7 ) );
-		len += sprintf( page+len, "miss >8 PTEs searched    : %12lu\n", mfspr( PMC8 ) );
-	}
-	/* IMPLEMENT ME */
-	return pmc_calc_metrics( page, start, off, count, eof, len );
-}
-
-unsigned long proc_pmc_conv_int( const char *buf, unsigned count )
-{
-	const char * p;
-	char b0, b1;
-	unsigned v, multiplier, mult, i;
-	unsigned long val;
-	multiplier = 10;
-	p = buf;
-	if ( count >= 3 ) {
-		b0 = buf[0];
-		b1 = buf[1];
-		if ( ( b0 == '0' ) &&
-		     ( ( b1 == 'x' ) || ( b1 == 'X' ) ) ) {
-			p = buf + 2;
-			count -= 2;
-			multiplier = 16;
-		}
-			
-	}
-	val = 0;
-	for ( i=0; i<count; ++i ) {
-		b0 = *p++;
-		v = 0;
-		mult = multiplier;
-		if ( ( b0 >= '0' ) && ( b0 <= '9' ) ) 
-			v = b0 - '0';
-		else if ( multiplier == 16 ) {
-			if ( ( b0 >= 'a' ) && ( b0 <= 'f' ) )
-				v = b0 - 'a' + 10;
-			else if ( ( b0 >= 'A' ) && ( b0 <= 'F' ) )
-				v = b0 - 'A' + 10;
-			else 
-				mult = 1;
-		}
-		else
-			mult = 1;
-		val *= mult;
-		val += v;
-	}
-
-	return val;
-
-}
-
-static inline void proc_pmc_stop(void)
-{
-	/* Freeze all counters, leave everything else alone */
-	mtspr( MMCR0, mfspr( MMCR0 ) | 0x80000000 );
-}
-
-static inline void proc_pmc_start(void)
-{
-	/* Unfreeze all counters, leave everything else alone */
-	mtspr( MMCR0, mfspr( MMCR0 ) & ~0x80000000 );
-
-}
-
-static inline void proc_pmc_reset(void)
-{
-	/* Clear all the PMCs to zeros 
-	 * Assume a "stop" has already frozen the counters
-	 * Clear all the PMCs
-	 */
-	mtspr( PMC1, 0 );
-	mtspr( PMC2, 0 );
-	mtspr( PMC3, 0 );
-	mtspr( PMC4, 0 );
-	mtspr( PMC5, 0 );
-	mtspr( PMC6, 0 );
-	mtspr( PMC7, 0 );
-	mtspr( PMC8, 0 );
-
-}
-
-static inline void proc_pmc_cpi(void)
-{
-	/* Configure the PMC registers to count cycles and instructions */
-	/* so we can compute cpi */
-	/*
-	 * MMCRA[30]    = 1     Don't count in wait state (CTRL[31]=0)
-	 * MMCR0[6]     = 1     Freeze counters when any overflow
-	 * MMCR0[19:25] = 0x01  PMC1 counts Thread Active Run Cycles
-	 * MMCR0[26:31] = 0x05	PMC2 counts Thread Active Cycles
-	 * MMCR1[0:4]   = 0x07	PMC3 counts Instructions Dispatched
-	 * MMCR1[5:9]   = 0x03	PMC4 counts Instructions Completed
-	 * MMCR1[10:14] = 0x06	PMC5 counts Machine Cycles
-	 *
-	 */
-
-	proc_pmc_control_mode = PMC_CONTROL_CPI;
-	
-	/* Indicate to hypervisor that we are using the PMCs */
-	get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
-
-	/* Freeze all counters */
-	mtspr( MMCR0, 0x80000000 );
-	mtspr( MMCR1, 0x00000000 );
-	
-	/* Clear all the PMCs */
-	mtspr( PMC1, 0 );
-	mtspr( PMC2, 0 );
-	mtspr( PMC3, 0 );
-	mtspr( PMC4, 0 );
-	mtspr( PMC5, 0 );
-	mtspr( PMC6, 0 );
-	mtspr( PMC7, 0 );
-	mtspr( PMC8, 0 );
-
-	/* Freeze counters in Wait State (CTRL[31]=0) */
-	mtspr( MMCRA, 0x00000002 );
-
-	/* PMC3<-0x07, PMC4<-0x03, PMC5<-0x06 */
-	mtspr( MMCR1, 0x38cc0000 );
-
-	mb();
-	
-	/* PMC1<-0x01, PMC2<-0x05
-	 * Start all counters
-	 */
-	mtspr( MMCR0, 0x02000045 );
-	
-}
-
-static inline void proc_pmc_tlb(void)
-{
-	/* Configure the PMC registers to count tlb misses  */
-	/*
-	 * MMCR0[6]     = 1     Freeze counters when any overflow
-	 * MMCR0[19:25] = 0x55  Group count
-	 *   PMC1 counts  I misses
-	 *   PMC2 counts  I miss duration (latency)
-	 *   PMC3 counts  D misses
-	 *   PMC4 counts  D miss duration (latency)
-	 *   PMC5 counts  IERAT misses
-	 *   PMC6 counts  D references (including PMC7)
-	 *   PMC7 counts  miss PTEs searched
-	 *   PMC8 counts  miss >8 PTEs searched
-	 *   
-	 */
-
-	proc_pmc_control_mode = PMC_CONTROL_TLB;
-	
-	/* Indicate to hypervisor that we are using the PMCs */
-	get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
-
-	/* Freeze all counters */
-	mtspr( MMCR0, 0x80000000 );
-	mtspr( MMCR1, 0x00000000 );
-	
-	/* Clear all the PMCs */
-	mtspr( PMC1, 0 );
-	mtspr( PMC2, 0 );
-	mtspr( PMC3, 0 );
-	mtspr( PMC4, 0 );
-	mtspr( PMC5, 0 );
-	mtspr( PMC6, 0 );
-	mtspr( PMC7, 0 );
-	mtspr( PMC8, 0 );
-
-	mtspr( MMCRA, 0x00000000 );
-
-	mb();
-	
-	/* PMC1<-0x55
-	 * Start all counters
-	 */
-	mtspr( MMCR0, 0x02001540 );
-	
-}
-
-int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	char stkbuf[10];
-	if (count > 9) count = 9;
-	if (copy_from_user (stkbuf, buffer, count)) {
-		return -EFAULT;
-	}
-	stkbuf[count] = 0;
-
-	if      ( ! strncmp( stkbuf, "stop", 4 ) )
-		proc_pmc_stop();
-	else if ( ! strncmp( stkbuf, "start", 5 ) )
-		proc_pmc_start();
-	else if ( ! strncmp( stkbuf, "reset", 5 ) )
-		proc_pmc_reset();
-	else if ( ! strncmp( stkbuf, "cpi", 3 ) )
-		proc_pmc_cpi();
-	else if ( ! strncmp( stkbuf, "tlb", 3 ) )
-		proc_pmc_tlb();
-	
-	/* IMPLEMENT ME */
-	return count;
-}
-
-int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	v = v & ~0x04000000;	/* Don't allow interrupts for now */
-	if ( v & ~0x80000000 ) 	/* Inform hypervisor we are using PMCs */
-		get_paca()->xLpPacaPtr->xPMCRegsInUse = 1;
-	else
-		get_paca()->xLpPacaPtr->xPMCRegsInUse = 0;
-	mtspr( MMCR0, v );
-	
-	return count;	
-}
-
-int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( MMCR1, v );
-
-	return count;
-}
-
-int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	v = v & ~0x00008000;	/* Don't allow interrupts for now */
-	mtspr( MMCRA, v );
-
-	return count;
-}
-
-
-int proc_pmc_set_pmc1( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC1, v );
-
-	return count;
-}
-
-int proc_pmc_set_pmc2( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC2, v );
-
-	return count;
-}
-
-int proc_pmc_set_pmc3( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC3, v );
-
-	return count;
-}
-
-int proc_pmc_set_pmc4( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC4, v );
-
-	return count;
-}
-
-int proc_pmc_set_pmc5( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC5, v );
-
-	return count;
-}
-
-int proc_pmc_set_pmc6( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC6, v );
-
-	return count;
-}
-
-int proc_pmc_set_pmc7( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC7, v );
-
-	return count;
-}
-
-int proc_pmc_set_pmc8( struct file *file, const char *buffer, unsigned long count, void *data )
-{
-	unsigned long v;
-	v = proc_pmc_conv_int( buffer, count );
-	mtspr( PMC8, v );
-
-	return count;
-}
-
diff -Nru a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c
--- a/arch/ppc64/kernel/proc_ppc64.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/proc_ppc64.c	Wed Mar 17 19:29:10 2004
@@ -18,15 +18,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-
-/*
- * Change Activity:
- * 2001       : mikec    : Created
- * 2001/06/05 : engebret : Software event count support.
- * 2003/02/13 : bergner  : Move PMC code to pmc.c
- * End Change Activity 
- */
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -34,7 +25,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 
-#include <asm/proc_fs.h>
 #include <asm/naca.h>
 #include <asm/paca.h>
 #include <asm/systemcfg.h>
@@ -42,10 +32,6 @@
 #include <asm/uaccess.h>
 #include <asm/prom.h>
 
-struct proc_ppc64_t proc_ppc64;
-
-void proc_ppc64_create_paca(int num);
-
 static loff_t  page_map_seek( struct file *file, loff_t off, int whence);
 static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos);
 static int     page_map_mmap( struct file *file, struct vm_area_struct *vma );
@@ -59,7 +45,7 @@
 #ifdef CONFIG_PPC_PSERIES
 /* routines for /proc/ppc64/ofdt */
 static ssize_t ofdt_write(struct file *, const char __user *, size_t, loff_t *);
-static void proc_ppc64_create_ofdt(struct proc_dir_entry *);
+static void proc_ppc64_create_ofdt(void);
 static int do_remove_node(char *);
 static int do_add_node(char *, size_t);
 static void release_prop_list(const struct property *);
@@ -70,77 +56,19 @@
 };
 #endif
 
-int __init proc_ppc64_init(void)
-{
-
-
-	if (proc_ppc64.root == NULL) {
-		printk(KERN_INFO "proc_ppc64: Creating /proc/ppc64/\n");
-		proc_ppc64.root = proc_mkdir("ppc64", 0);
-		if (!proc_ppc64.root)
-			return 0;
-	} else {
-		return 0;
-	}
-
-	proc_ppc64.naca = create_proc_entry("naca", S_IRUSR, proc_ppc64.root);
-	if ( proc_ppc64.naca ) {
-		proc_ppc64.naca->nlink = 1;
-		proc_ppc64.naca->data = naca;
-		proc_ppc64.naca->size = 4096;
-		proc_ppc64.naca->proc_fops = &page_map_fops;
-	}
-	
-	proc_ppc64.systemcfg = create_proc_entry("systemcfg", S_IFREG|S_IRUGO, proc_ppc64.root);
-	if ( proc_ppc64.systemcfg ) {
-		proc_ppc64.systemcfg->nlink = 1;
-		proc_ppc64.systemcfg->data = systemcfg;
-		proc_ppc64.systemcfg->size = 4096;
-		proc_ppc64.systemcfg->proc_fops = &page_map_fops;
-	}
-
-	/* /proc/ppc64/paca/XX -- raw paca contents.  Only readable to root */
-	proc_ppc64.paca = proc_mkdir("paca", proc_ppc64.root);
-	if (proc_ppc64.paca) {
-		unsigned long i;
-
-		for (i = 0; i < NR_CPUS; i++) {
-			if (!cpu_online(i))
-				continue;
-			proc_ppc64_create_paca(i);
-		}
-	}
-
-#ifdef CONFIG_PPC_PSERIES
-	/* Placeholder for rtas interfaces. */
-	if (proc_ppc64.rtas == NULL)
-		proc_ppc64.rtas = proc_mkdir("rtas", proc_ppc64.root);
-
-	if (proc_ppc64.rtas)
-		proc_symlink("rtas", 0, "ppc64/rtas");
-
-	proc_ppc64_create_ofdt(proc_ppc64.root);
-#endif
-
-	return 0;
-}
-
-
 /*
- * NOTE: since paca data is always in flux the values will never be a consistant set.
- * In theory it could be made consistent if we made the corresponding cpu
- * copy the page for us (via an IPI).  Probably not worth it.
- *
+ * NOTE: since paca data is always in flux the values will never be a
+ * consistant set.
  */
-void proc_ppc64_create_paca(int num)
+static void __init proc_create_paca(struct proc_dir_entry *dir, int num)
 {
 	struct proc_dir_entry *ent;
 	struct paca_struct *lpaca = paca + num;
 	char buf[16];
 
 	sprintf(buf, "%02x", num);
-	ent = create_proc_entry(buf, S_IRUSR, proc_ppc64.paca);
-	if ( ent ) {
+	ent = create_proc_entry(buf, S_IRUSR, dir);
+	if (ent) {
 		ent->nlink = 1;
 		ent->data = lpaca;
 		ent->size = 4096;
@@ -148,6 +76,67 @@
 	}
 }
 
+/*
+ * Create the ppc64 and ppc64/rtas directories early. This allows us to
+ * assume that they have been previously created in drivers.
+ */
+static int __init proc_ppc64_create(void)
+{
+	struct proc_dir_entry *root;
+
+	root = proc_mkdir("ppc64", 0);
+	if (!root)
+		return 1;
+
+	if (!(systemcfg->platform & PLATFORM_PSERIES))
+		return 0;
+
+	if (!proc_mkdir("rtas", root))
+		return 1;
+
+	if (!proc_symlink("rtas", 0, "ppc64/rtas"))
+		return 1;
+
+	return 0;
+}
+core_initcall(proc_ppc64_create);
+
+static int __init proc_ppc64_init(void)
+{
+	unsigned long i;
+	struct proc_dir_entry *pde;
+
+	pde = create_proc_entry("ppc64/naca", S_IRUSR, NULL);
+	if (!pde)
+		return 1;
+	pde->nlink = 1;
+	pde->data = naca;
+	pde->size = 4096;
+	pde->proc_fops = &page_map_fops;
+
+	pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL);
+	if (!pde)
+		return 1;
+	pde->nlink = 1;
+	pde->data = systemcfg;
+	pde->size = 4096;
+	pde->proc_fops = &page_map_fops;
+
+	/* /proc/ppc64/paca/XX -- raw paca contents.  Only readable to root */
+	pde = proc_mkdir("ppc64/paca", NULL);
+	if (!pde)
+		return 1;
+	for_each_cpu(i)
+		proc_create_paca(pde, i);
+
+#ifdef CONFIG_PPC_PSERIES
+	if ((systemcfg->platform & PLATFORM_PSERIES))
+		proc_ppc64_create_ofdt();
+#endif
+
+	return 0;
+}
+__initcall(proc_ppc64_init);
 
 static loff_t page_map_seek( struct file *file, loff_t off, int whence)
 {
@@ -204,11 +193,11 @@
 
 #ifdef CONFIG_PPC_PSERIES
 /* create /proc/ppc64/ofdt write-only by root */
-static void proc_ppc64_create_ofdt(struct proc_dir_entry *parent)
+static void proc_ppc64_create_ofdt(void)
 {
 	struct proc_dir_entry *ent;
 
-	ent = create_proc_entry("ofdt", S_IWUSR, parent);
+	ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
 	if (ent) {
 		ent->nlink = 1;
 		ent->data = NULL;
@@ -423,5 +412,3 @@
 
 }
 #endif	/* defined(CONFIG_PPC_PSERIES) */
-
-fs_initcall(proc_ppc64_init);
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/process.c	Wed Mar 17 19:29:09 2004
@@ -34,6 +34,7 @@
 #include <linux/prctl.h>
 #include <linux/ptrace.h>
 #include <linux/kallsyms.h>
+#include <linux/version.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -193,8 +194,8 @@
 
 	printk("NIP: %016lX XER: %016lX LR: %016lX\n",
 	       regs->nip, regs->xer, regs->link);
-	printk("REGS: %p TRAP: %04lx    %s\n",
-	       regs, regs->trap, print_tainted());
+	printk("REGS: %p TRAP: %04lx   %s  (%s)\n",
+	       regs, regs->trap, print_tainted(), UTS_RELEASE);
 	printk("MSR: %016lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
 	       regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
 	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/prom.c	Wed Mar 17 19:29:09 2004
@@ -61,6 +61,14 @@
 #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
@@ -908,9 +916,11 @@
 			*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(RELOC("package-to-path"), 3, 1, node,
-                             path, 255) <= 0) {
+                             path, sizeof(path)-1) <= 0) {
                         prom_print(RELOC("package-to-path failed\n"));
                 } else {
                         prom_print(RELOC("opened "));
@@ -1687,6 +1697,11 @@
 		/* 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 ((long) call_prom(RELOC("package-to-path"), 3, 1,
 				    node, path, 250) < 0)
 			continue;
@@ -1794,8 +1809,7 @@
 	return new_start;
 }
 
-__init
-static unsigned long
+static unsigned long __init
 inspect_node(phandle node, struct device_node *dad,
 	     unsigned long mem_start, unsigned long mem_end,
 	     struct device_node ***allnextpp)
@@ -1843,6 +1857,22 @@
 				  valp, mem_end - mem_start);
 		if (pp->length < 0)
 			continue;
+		if (pp->length > MAX_PROPERTY_LENGTH) {
+			char path[128];
+
+			prom_print(RELOC("WARNING: ignoring large property "));
+			/* It seems OF doesn't null-terminate the path :-( */
+			memset(path, 0, sizeof(path));
+			if (call_prom(RELOC("package-to-path"), 3, 1, node,
+                            path, sizeof(path)-1) > 0)
+				prom_print(path);
+			prom_print(namep);
+			prom_print(RELOC(" length 0x"));
+			prom_print_hex(pp->length);
+			prom_print_nl();
+
+			continue;
+		}
 		mem_start = DOUBLEWORD_ALIGN(mem_start + pp->length);
 		*prev_propp = PTRUNRELOC(pp);
 		prev_propp = &pp->next;
@@ -2853,40 +2883,12 @@
 	struct device_node *parent, *child;
 
 	parent = of_get_parent(np);
-
 	if (!parent)
 		return -EINVAL;
 
-	/* Make sure we are not recursively removing
-	 * more than one level of nodes.  We need to
-	 * allow this so we can remove a slot containing
-	 * an IOA.
-	 */
-	for (child = of_get_next_child(np, NULL);
-	     child != NULL;
-	     child = of_get_next_child(np, child)) {
-		struct device_node *grandchild;
-
-		if ((grandchild = of_get_next_child(child, NULL))) {
-			/* Too deep */
-			of_node_put(grandchild);
-			of_node_put(child);
-			return -EBUSY;
-		}
-	}
-
-	/* Now that we're reasonably sure that we won't
-	 * overflow our stack, remove any children of np.
-	 */
-	for (child = of_get_next_child(np, NULL);
-	     child != NULL;
-	     child = of_get_next_child(np, child)) {
-		int rc;
-
-		if ((rc = of_remove_node(child))) {
-			of_node_put(child);
-			return rc;
-		}
+	if ((child = of_get_next_child(np, NULL))) {
+		of_node_put(child);
+		return -EBUSY;
 	}
 
 	write_lock(&devtree_lock);
@@ -2964,6 +2966,53 @@
 #endif /* CONFIG_PROC_DEVICETREE */
 
 /*
+ * Fix up n_intrs and intrs fields in a new device node
+ *
+ */
+static int of_finish_dynamic_node_interrupts(struct device_node *node)
+{
+	int intrcells, intlen, i;
+	unsigned *irq, *ints, virq;
+	struct device_node *ic;
+
+	ints = (unsigned int *)get_property(node, "interrupts", &intlen);
+	intrcells = prom_n_intr_cells(node);
+	intlen /= intrcells * sizeof(unsigned int);
+	node->n_intrs = intlen;
+	node->intrs = kmalloc(sizeof(struct interrupt_info) * intlen,
+			      GFP_KERNEL);
+	if (!node->intrs)
+		return -ENOMEM;
+
+	for (i = 0; i < intlen; ++i) {
+		int n, j;
+		node->intrs[i].line = 0;
+		node->intrs[i].sense = 1;
+		n = map_interrupt(&irq, &ic, node, ints, intrcells);
+		if (n <= 0)
+			continue;
+		virq = virt_irq_create_mapping(irq[0]);
+		if (virq == NO_IRQ) {
+			printk(KERN_CRIT "Could not allocate interrupt "
+			       "number for %s\n", node->full_name);
+			return -ENOMEM;
+		}
+		node->intrs[i].line = openpic_to_irq(virq);
+		if (n > 1)
+			node->intrs[i].sense = irq[1];
+		if (n > 2) {
+			printk(KERN_DEBUG "hmmm, got %d intr cells for %s:", n,
+			       node->full_name);
+			for (j = 0; j < n; ++j)
+				printk(" %d", irq[j]);
+			printk("\n");
+		}
+		ints += intrcells;
+	}
+	return 0;
+}
+
+/*
  * Fix up the uninitialized fields in a new device node:
  * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields
  *
@@ -2978,11 +3027,8 @@
 {
 	struct device_node *parent = of_get_parent(node);
 	u32 *regs;
-	unsigned int *ints;
-	int intlen, intrcells;
-	int i, j, n, err = 0;
-	unsigned int *irq, virq;
-	struct device_node *ic;
+	int err = 0;
+	phandle *ibm_phandle;
  
 	node->name = get_property(node, "name", 0);
 	node->type = get_property(node, "device_type", 0);
@@ -2998,6 +3044,10 @@
 	if (systemcfg->platform == PLATFORM_POWERMAC)
 		return -ENODEV;
 
+	/* fix up new node's linux_phandle field */
+	if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL)))
+		node->linux_phandle = *ibm_phandle;
+
 	/* do the work of interpret_pci_props */
 	if (parent->type && !strcmp(parent->type, "pci")) {
 		struct address_range *adr;
@@ -3027,45 +3077,9 @@
 	}
 
 	/* now do the work of finish_node_interrupts */
-
-	ints = (unsigned int *) get_property(node, "interrupts", &intlen);
-	if (!ints) {
-		err = -ENODEV;
-		goto out;
-	}
-
-	intrcells = prom_n_intr_cells(node);
-	intlen /= intrcells * sizeof(unsigned int);
-	node->n_intrs = intlen;
-	node->intrs = kmalloc(sizeof(struct interrupt_info) * intlen,
-			      GFP_KERNEL);
-	if (!node->intrs) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	for (i = 0; i < intlen; ++i) {
-		node->intrs[i].line = 0;
-		node->intrs[i].sense = 1;
-		n = map_interrupt(&irq, &ic, node, ints, intrcells);
-		if (n <= 0)
-			continue;
-		virq = virt_irq_create_mapping(irq[0]);
-		if (virq == NO_IRQ) {
-			printk(KERN_CRIT "Could not allocate interrupt "
-			       "number for %s\n", node->full_name);
-		} else
-			node->intrs[i].line = openpic_to_irq(virq);
-		if (n > 1)
-			node->intrs[i].sense = irq[1];
-		if (n > 2) {
-			printk(KERN_DEBUG "hmmm, got %d intr cells for %s:", n,
-			       node->full_name);
-			for (j = 0; j < n; ++j)
-				printk(" %d", irq[j]);
-			printk("\n");
-		}
-		ints += intrcells;
+	if (get_property(node, "interrupts", 0)) {
+		err = of_finish_dynamic_node_interrupts(node);
+		if (err) goto out;
 	}
 
        /* now do the rough equivalent of update_dn_pci_info, this
diff -Nru a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
--- a/arch/ppc64/kernel/ras.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/ras.c	Wed Mar 17 19:29:09 2004
@@ -36,7 +36,6 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/proc_fs.h>
 #include <linux/random.h>
 #include <linux/sysrq.h>
 
diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
--- a/arch/ppc64/kernel/rtas-proc.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/rtas-proc.c	Wed Mar 17 19:29:09 2004
@@ -28,7 +28,6 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
-#include <asm/proc_fs.h>
 #include <asm/machdep.h> /* for ppc_md */
 #include <asm/time.h>
 
@@ -117,8 +116,6 @@
 
 
 /* Globals */
-extern struct proc_dir_entry *proc_rtas;
-
 static struct rtas_sensors sensors;
 static struct device_node *rtas_node = NULL;
 static unsigned long power_on_time = 0; /* Save the time the user set */
@@ -201,50 +198,49 @@
 int check_location_string (char *c, char * buf);
 int check_location (char *c, int idx, char * buf);
 
-/* ****************************************************************** */
-/* MAIN                                                               */
-/* ****************************************************************** */
-void proc_rtas_init(void)
+static int __init proc_rtas_init(void)
 {
 	struct proc_dir_entry *entry;
 
+	if (!(systemcfg->platform & PLATFORM_PSERIES))
+		return 1;
+
 	rtas_node = of_find_node_by_name(NULL, "rtas");
-	if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) {
-		return;
-	}
-	
-	if (proc_ppc64.rtas == NULL) {
-		proc_ppc64_init();
-	}
-
-	if (proc_ppc64.rtas == NULL) {
-		printk(KERN_ERR "Failed to create /proc/rtas in proc_rtas_init\n");
-		return;
-	}
-
-	/* /proc/rtas entries */
-
-	entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_ppc64.rtas);
-	if (entry) entry->proc_fops = &ppc_rtas_progress_operations;
-
-	entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_ppc64.rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_clock_operations;
-
-	entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_ppc64.rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_poweron_operations;
-
-	create_proc_read_entry("sensors", S_IRUGO, proc_ppc64.rtas, 
-			ppc_rtas_sensor_read, NULL);
-	
-	entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_ppc64.rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations;
+	if (rtas_node == NULL)
+		return 1;
 
-	entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_ppc64.rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
+	entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
+	if (entry)
+		entry->proc_fops = &ppc_rtas_progress_operations;
+
+	entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL);
+	if (entry)
+		entry->proc_fops = &ppc_rtas_clock_operations;
+
+	entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL);
+	if (entry)
+		entry->proc_fops = &ppc_rtas_poweron_operations;
+
+	create_proc_read_entry("ppc64/rtas/sensors", S_IRUGO, NULL,
+			       ppc_rtas_sensor_read, NULL);
+
+	entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO,
+				  NULL);
+	if (entry)
+		entry->proc_fops = &ppc_rtas_tone_freq_operations;
+
+	entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL);
+	if (entry)
+		entry->proc_fops = &ppc_rtas_tone_volume_operations;
+
+	entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL);
+	if (entry)
+		entry->proc_fops = &ppc_rtas_rmo_buf_ops;
 
-	entry = create_proc_entry("rmo_buffer", S_IRUSR, proc_ppc64.rtas);
-	if (entry) entry->proc_fops = &ppc_rtas_rmo_buf_ops;
+	return 0;
 }
+
+__initcall(proc_rtas_init);
 
 /* ****************************************************************** */
 /* POWER-ON-TIME                                                      */
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/rtas.c	Wed Mar 17 19:29:09 2004
@@ -19,7 +19,6 @@
 #include <linux/init.h>
 
 #include <asm/prom.h>
-#include <asm/proc_fs.h>
 #include <asm/rtas.h>
 #include <asm/semaphore.h>
 #include <asm/machdep.h>
@@ -259,6 +258,33 @@
 }
 
 int
+rtas_set_power_level(int powerdomain, int level, int *setlevel)
+{
+	int token = rtas_token("set-power-level");
+	unsigned int wait_time;
+	long returned_level;
+	int rc;
+
+	if (token == RTAS_UNKNOWN_SERVICE)
+		return RTAS_UNKNOWN_OP;
+
+	while (1) {
+		rc = (int) rtas_call(token, 2, 2, &returned_level, powerdomain,
+					level);
+		if (rc == RTAS_BUSY)
+			udelay(1);
+		else if (rtas_is_extended_busy(rc)) {
+			wait_time = rtas_extended_busy_delay_time(rc);
+			udelay(wait_time * 1000);
+		}
+		else
+			break;
+	}
+	*setlevel = (int) returned_level;
+	return rc;
+}
+
+int
 rtas_get_sensor(int sensor, int index, int *state)
 {
 	int token = rtas_token("get-sensor-state");
@@ -426,6 +452,7 @@
 {
 	struct rtas_args args;
 	unsigned long flags;
+	int nargs;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -433,14 +460,15 @@
 	if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
 		return -EFAULT;
 
-	if (args.nargs > ARRAY_SIZE(args.args)
+	nargs = args.nargs;
+	if (nargs > ARRAY_SIZE(args.args)
 	    || args.nret > ARRAY_SIZE(args.args)
-	    || args.nargs + args.nret > ARRAY_SIZE(args.args))
+	    || nargs + args.nret > ARRAY_SIZE(args.args))
 		return -EINVAL;
 
 	/* Copy in args. */
 	if (copy_from_user(args.args, uargs->args,
-			   args.nargs * sizeof(rtas_arg_t)) != 0)
+			   nargs * sizeof(rtas_arg_t)) != 0)
 		return -EFAULT;
 
 	spin_lock_irqsave(&rtas.lock, flags);
@@ -449,14 +477,15 @@
 	enter_rtas((void *)__pa((unsigned long)&get_paca()->xRtas));
 	args = get_paca()->xRtas;
 
+	args.rets  = (rtas_arg_t *)&(args.args[nargs]);
 	if (args.rets[0] == -1)
 		log_rtas_error(&args);
 
 	spin_unlock_irqrestore(&rtas.lock, flags);
 
 	/* Copy out args. */
-	if (copy_to_user(uargs->args + args.nargs,
-			 args.args + args.nargs,
+	if (copy_to_user(uargs->args + nargs,
+			 args.args + nargs,
 			 args.nret * sizeof(rtas_arg_t)) != 0)
 		return -EFAULT;
 
@@ -472,4 +501,5 @@
 EXPORT_SYMBOL(rtas_extended_busy_delay_time);
 EXPORT_SYMBOL(rtas_get_sensor);
 EXPORT_SYMBOL(rtas_get_power_level);
+EXPORT_SYMBOL(rtas_set_power_level);
 EXPORT_SYMBOL(rtas_set_indicator);
diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c
--- a/arch/ppc64/kernel/rtas_flash.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/rtas_flash.c	Wed Mar 17 19:29:10 2004
@@ -15,7 +15,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <asm/proc_fs.h>
+#include <linux/proc_fs.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 #include <asm/rtas.h>
@@ -106,10 +106,10 @@
 };
 
 static spinlock_t flash_file_open_lock = SPIN_LOCK_UNLOCKED;
-static struct proc_dir_entry *firmware_flash_pde = NULL;
-static struct proc_dir_entry *firmware_update_pde = NULL;
-static struct proc_dir_entry *validate_pde = NULL;
-static struct proc_dir_entry *manage_pde = NULL;
+static struct proc_dir_entry *firmware_flash_pde;
+static struct proc_dir_entry *firmware_update_pde;
+static struct proc_dir_entry *validate_pde;
+static struct proc_dir_entry *manage_pde;
 
 /* Do simple sanity checks on the flash image. */
 static int flash_list_valid(struct flash_block_list *flist)
@@ -501,7 +501,7 @@
 }
 
 static ssize_t validate_flash_write(struct file *file, const char *buf,
-				size_t count, loff_t *off)
+				    size_t count, loff_t *off)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
 	struct rtas_validate_flash_t *args_buf;
@@ -567,18 +567,18 @@
 	return 0;
 }
 
-static inline void remove_flash_pde(struct proc_dir_entry *dp)
+static void remove_flash_pde(struct proc_dir_entry *dp)
 {
 	if (dp) {
 		if (dp->data != NULL)
 			kfree(dp->data);
-		remove_proc_entry(dp->name, proc_ppc64.rtas);
+		remove_proc_entry(dp->name, NULL);
 	}
 }
 
-static inline int initialize_flash_pde_data(const char *rtas_call_name, 
-		                            size_t buf_size,
-					    struct proc_dir_entry *dp)
+static int initialize_flash_pde_data(const char *rtas_call_name,
+				     size_t buf_size,
+				     struct proc_dir_entry *dp)
 {
 	int *status;
 	int token;
@@ -591,7 +591,8 @@
 
 	memset(dp->data, 0, buf_size);
 
-	/* This code assumes that the status int is the first member of the
+	/*
+	 * This code assumes that the status int is the first member of the
 	 * struct 
 	 */
 	status = (int *) dp->data;
@@ -604,12 +605,12 @@
 	return 0;
 }
 
-static inline struct proc_dir_entry * create_flash_pde(const char *filename, 
-					struct file_operations *fops)
+static struct proc_dir_entry *create_flash_pde(const char *filename,
+					       struct file_operations *fops)
 {
 	struct proc_dir_entry *ent = NULL;
 
-	ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, proc_ppc64.rtas);
+	ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL);
 	if (ent != NULL) {
 		ent->nlink = 1;
 		ent->proc_fops = fops;
@@ -644,50 +645,79 @@
 {
 	int rc;
 
-	if (!proc_ppc64.rtas) {
-		printk(KERN_WARNING "rtas proc dir does not already exist");
-		return -ENOENT;
+	if (rtas_token("ibm,update-flash-64-and-reboot") ==
+		       RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_ERR "rtas_flash: no firmware flash support\n");
+		return 1;
 	}
 
-	firmware_flash_pde = create_flash_pde(FIRMWARE_FLASH_NAME, 
+	firmware_flash_pde = create_flash_pde("ppc64/rtas/"
+					      FIRMWARE_FLASH_NAME,
 					      &rtas_flash_operations);
+	if (firmware_flash_pde == NULL) {
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+
 	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",
 			 	       sizeof(struct rtas_update_flash_t), 
 				       firmware_flash_pde);
 	if (rc != 0)
-		return rc;
-	
-	firmware_update_pde = create_flash_pde(FIRMWARE_UPDATE_NAME, 
+		goto cleanup;
+
+	firmware_update_pde = create_flash_pde("ppc64/rtas/"
+					       FIRMWARE_UPDATE_NAME,
 					       &rtas_flash_operations);
+	if (firmware_update_pde == NULL) {
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+
 	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",
 			 	       sizeof(struct rtas_update_flash_t), 
 				       firmware_update_pde);
 	if (rc != 0)
-		return rc;
-	
-	validate_pde = create_flash_pde(VALIDATE_FLASH_NAME, 
+		goto cleanup;
+
+	validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME,
 			      		&validate_flash_operations);
+	if (validate_pde == NULL) {
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+
 	rc = initialize_flash_pde_data("ibm,validate-flash-image",
 		                       sizeof(struct rtas_validate_flash_t), 
 				       validate_pde);
 	if (rc != 0)
-		return rc;
-	
-	manage_pde = create_flash_pde(MANAGE_FLASH_NAME, 
+		goto cleanup;
+
+	manage_pde = create_flash_pde("ppc64/rtas" MANAGE_FLASH_NAME,
 				      &manage_flash_operations);
+	if (manage_pde == NULL) {
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+
 	rc = initialize_flash_pde_data("ibm,manage-flash-image",
 			               sizeof(struct rtas_manage_flash_t),
 				       manage_pde);
 	if (rc != 0)
-		return rc;
-	
+		goto cleanup;
+
 	return 0;
+
+cleanup:
+	remove_flash_pde(firmware_flash_pde);
+	remove_flash_pde(firmware_update_pde);
+	remove_flash_pde(validate_pde);
+	remove_flash_pde(manage_pde);
+
+	return rc;
 }
 
 void __exit rtas_flash_cleanup(void)
 {
-	if (!proc_ppc64.rtas)
-		return;
 	remove_flash_pde(firmware_flash_pde);
 	remove_flash_pde(firmware_update_pde);
 	remove_flash_pde(validate_pde);
diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
--- a/arch/ppc64/kernel/rtasd.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/rtasd.c	Wed Mar 17 19:29:09 2004
@@ -26,7 +26,6 @@
 #include <asm/prom.h>
 #include <asm/nvram.h>
 #include <asm/atomic.h>
-#include <asm/proc_fs.h>
 
 #if 0
 #define DEBUG(A...)	printk(KERN_ERR A)
@@ -47,7 +46,6 @@
 static unsigned int rtas_error_log_max;
 static unsigned int rtas_error_log_buffer_max;
 
-extern spinlock_t proc_ppc64_lock;
 extern volatile int no_more_logging;
 
 volatile int error_log_cnt = 0;
@@ -445,20 +443,18 @@
 {
 	struct proc_dir_entry *entry;
 
-	if (proc_ppc64.rtas == NULL) {
-		proc_ppc64_init();
+	/* No RTAS, only warn if we are on a pSeries box  */
+	if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
+		if (systemcfg->platform & PLATFORM_PSERIES);
+			printk(KERN_ERR "rtasd: no RTAS on system\n");
+		return 1;
 	}
 
-	if (proc_ppc64.rtas == NULL) {
-		printk(KERN_ERR "rtas_init: /proc/ppc64/rtas does not exist.");
-		return -EIO;
-	}
-
-	entry = create_proc_entry("error_log", S_IRUSR, proc_ppc64.rtas);
+	entry = create_proc_entry("ppc64/error_log", S_IRUSR, NULL);
 	if (entry)
 		entry->proc_fops = &proc_rtas_log_operations;
 	else
-		printk(KERN_ERR "Failed to create rtas/error_log proc entry\n");
+		printk(KERN_ERR "Failed to create error_log proc entry\n");
 
 	if (kernel_thread(rtasd, 0, CLONE_FS) < 0)
 		printk(KERN_ERR "Failed to start RTAS daemon\n");
diff -Nru a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c
--- a/arch/ppc64/kernel/scanlog.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/kernel/scanlog.c	Wed Mar 17 19:29:10 2004
@@ -28,7 +28,6 @@
 #include <asm/uaccess.h>
 #include <asm/rtas.h>
 #include <asm/prom.h>
-#include <asm/proc_fs.h>
 
 #define MODULE_VERS "1.0"
 #define MODULE_NAME "scanlog"
@@ -212,16 +211,7 @@
 		return -EIO;
 	}
 
-	if (proc_ppc64.rtas == NULL) {
-		proc_ppc64_init();
-	}
-
-	if (proc_ppc64.rtas == NULL) {
-		printk(KERN_ERR "Failed to create /proc/rtas in scanlog_init\n");
-		return -EIO;
-	}
-
-        ent = create_proc_entry("scan-log-dump",  S_IRUSR, proc_ppc64.rtas);
+        ent = create_proc_entry("ppc64/rtas/scan-log-dump",  S_IRUSR, NULL);
 	if (ent) {
 		ent->proc_fops = &scanlog_fops;
 		/* Ideally we could allocate a buffer < 4G */
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/sys_ppc32.c	Wed Mar 17 19:29:09 2004
@@ -2577,17 +2577,6 @@
 	return sys_umask((int)mask);
 }
 
-
-/* Note: it is necessary to treat flags as an unsigned int,
- * with the corresponding cast to a signed int to insure that the 
- * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
- * and the register representation of a signed int (msr in 64-bit mode) is performed.
- */
-asmlinkage long sys32_umount(char * name, u32 flags)
-{
-	return sys_umount(name, (int)flags);
-}
-
 struct __sysctl_args32 {
 	u32 name;
 	int nlen;
diff -Nru a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
--- a/arch/ppc64/kernel/vio.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/vio.c	Wed Mar 17 19:29:09 2004
@@ -580,5 +580,4 @@
 	.match = vio_bus_match,
 };
 
-EXPORT_SYMBOL(plpar_hcall_norets);
-EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
+EXPORT_SYMBOL(vio_bus_type);
diff -Nru a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
--- a/arch/ppc64/kernel/viopath.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/viopath.c	Wed Mar 17 19:29:09 2004
@@ -28,7 +28,6 @@
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include <asm/uaccess.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -37,9 +36,10 @@
 #include <linux/proc_fs.h>
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
+#include <linux/seq_file.h>
 
-#include <asm/hardirq.h>	/* for is_atomic */
-
+#include <asm/hardirq.h>
+#include <asm/uaccess.h>
 #include <asm/iSeries/LparData.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvLpConfig.h>
@@ -184,21 +184,21 @@
 	return ' ';
 }
 
-/* Handle reads from the proc file system
- */
-static int proc_read(char *buf, char **start, off_t offset,
-		     int blen, int *eof, void *data)
+static int proc_viopath_show(struct seq_file *m, void *v)
 {
+	char *buf;
+	dma_addr_t handle;
 	HvLpEvent_Rc hvrc;
 	DECLARE_MUTEX_LOCKED(Semaphore);
-	dma_addr_t dmaa =
-	    dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE, DMA_FROM_DEVICE);
-	int len = PAGE_SIZE;
 
-	if (len > blen)
-		len = blen;
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return 0;
+	memset(buf, 0, PAGE_SIZE);
+
+	handle = dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE,
+				DMA_FROM_DEVICE);
 
-	memset(buf, 0x00, len);
 	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
 			HvLpEvent_Type_VirtualIo,
 			viomajorsubtype_config | vioconfigget,
@@ -206,50 +206,54 @@
 			viopath_sourceinst(viopath_hostLp),
 			viopath_targetinst(viopath_hostLp),
 			(u64)(unsigned long)&Semaphore, VIOVERSION << 16,
-			((u64)dmaa) << 32, len, 0, 0);
+			((u64)handle) << 32, PAGE_SIZE, 0, 0);
+
 	if (hvrc != HvLpEvent_Rc_Good)
-		printk("viopath hv error on op %d\n", (int) hvrc);
+		printk("viopath hv error on op %d\n", (int)hvrc);
 
 	down(&Semaphore);
 
-	dma_unmap_single(iSeries_vio_dev, dmaa, PAGE_SIZE, DMA_FROM_DEVICE);
+	dma_unmap_single(iSeries_vio_dev, handle, PAGE_SIZE, DMA_FROM_DEVICE);
+	kfree(buf);
+
+	buf[PAGE_SIZE] = '\0';
+	seq_printf(m, "%s", buf);
+
+	seq_printf(m, "SRLNBR=%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]));
 
-	sprintf(buf + strlen(buf), "SRLNBR=");
-	buf[strlen(buf)] = e2a(xItExtVpdPanel.mfgID[2]);
-	buf[strlen(buf)] = e2a(xItExtVpdPanel.mfgID[3]);
-	buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[1]);
-	buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[2]);
-	buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[3]);
-	buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[4]);
-	buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[5]);
-	buf[strlen(buf)] = '\n';
-	*eof = 1;
-	return strlen(buf);
+	return 0;
 }
 
-/* Handle writes to our proc file system
- */
-static int proc_write(struct file *file, const char *buffer,
-		      unsigned long count, void *data)
+static int proc_viopath_open(struct inode *inode, struct file *file)
 {
-	/* Doesn't do anything today!!!
-	 */
-	return count;
+	return single_open(file, proc_viopath_show, NULL);
 }
 
-/* setup our proc file system entries
- */
-static void vio_proc_init(struct proc_dir_entry *iSeries_proc)
+static struct file_operations proc_viopath_operations = {
+	.open		= proc_viopath_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init vio_proc_init(void)
 {
-	struct proc_dir_entry *ent;
-	ent = create_proc_entry("config", S_IFREG | S_IRUSR, iSeries_proc);
-	if (!ent)
-		return;
-	ent->nlink = 1;
-	ent->data = NULL;
-	ent->read_proc = proc_read;
-	ent->write_proc = proc_write;
+	struct proc_dir_entry *e;
+
+	e = create_proc_entry("iSeries/config", 0, NULL);
+	if (e)
+		e->proc_fops = &proc_viopath_operations;
+
+        return 0;
 }
+__initcall(vio_proc_init);
 
 /* See if a given LP is active.  Allow for invalid lps to be passed in
  * and just return invalid
@@ -433,13 +437,8 @@
 	viopath_ourLp = HvLpConfig_getLpIndex();
 	viopath_hostLp = HvCallCfg_getHostingLpIndex(viopath_ourLp);
 
-	/* If we have a valid hosting LP, create a proc file system entry
-	 * for config information
-	 */
-	if (viopath_hostLp != HvLpIndexInvalid) {
-		iSeries_proc_callback(&vio_proc_init);
+	if (viopath_hostLp != HvLpIndexInvalid)
 		vio_setHandler(viomajorsubtype_config, handleConfig);
-	}
 }
 EXPORT_SYMBOL(vio_set_hostlp);
 
diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
--- a/arch/ppc64/kernel/xics.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/kernel/xics.c	Wed Mar 17 19:29:09 2004
@@ -327,6 +327,8 @@
 	}
 }
 
+extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq);
+
 int xics_get_irq(struct pt_regs *regs)
 {
 	unsigned int cpu = smp_processor_id();
@@ -349,6 +351,8 @@
 		irq = -1;
 	} else {
 		irq = real_irq_to_virt(vec);
+		if (irq == NO_IRQ)
+			irq = real_irq_to_virt_slowpath(vec);
 		if (irq == NO_IRQ) {
 			printk(KERN_ERR "Interrupt 0x%x (real) is invalid,"
 			       " disabling it.\n", vec);
diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
--- a/arch/ppc64/mm/hash_utils.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/mm/hash_utils.c	Wed Mar 17 19:29:09 2004
@@ -39,7 +39,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/naca.h>
-#include <asm/pmc.h>
 #include <asm/machdep.h>
 #include <asm/lmb.h>
 #include <asm/abs_addr.h>
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	Wed Mar 17 19:29:09 2004
+++ b/arch/ppc64/mm/init.c	Wed Mar 17 19:29:09 2004
@@ -36,7 +36,6 @@
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
-#include <linux/proc_fs.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -76,8 +75,6 @@
 
 unsigned long klimit = (unsigned long)_end;
 
-HPTE *Hash=0;
-unsigned long Hash_size=0;
 unsigned long _SDR1=0;
 unsigned long _ASR=0;
 
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	Wed Mar 17 19:29:10 2004
+++ b/arch/ppc64/xmon/xmon.c	Wed Mar 17 19:29:10 2004
@@ -56,9 +56,6 @@
 #define setjmp xmon_setjmp
 #define longjmp xmon_longjmp
 
-/* Max number of stack frames we are willing to produce on a backtrace. */
-#define MAXFRAMECOUNT 50
-
 /* Breakpoint stuff */
 struct bpt {
 	unsigned long address;
@@ -85,7 +82,6 @@
 static void prdump(unsigned long, long);
 static int ppc_inst_dump(unsigned long, long);
 void print_address(unsigned long);
-static int getsp(void);
 static void backtrace(struct pt_regs *);
 static void excprint(struct pt_regs *);
 static void prregs(struct pt_regs *);
@@ -177,7 +173,8 @@
   S	print special registers\n\
   t	print backtrace\n\
   T	Enable/Disable PPCDBG flags\n\
-  x	exit monitor\n\
+  x	exit monitor and recover\n\
+  X	exit monitor and dont recover\n\
   u	dump segment table or SLB\n\
   ?	help\n"
   "\
@@ -344,6 +341,9 @@
 #endif /* CONFIG_SMP */
 	set_msrd(msr);		/* restore interrupt enable */
 
+	if (cmd == 'X')
+		return 0;
+
 	return 1;
 }
 
@@ -563,6 +563,7 @@
 			break;
 		case 's':
 		case 'x':
+		case 'X':
 		case EOF:
 			return cmd;
 		case '?':
@@ -897,93 +898,75 @@
 	return ret;
 }
 
-static void
-backtrace(struct pt_regs *excp)
+/*
+ * Most of our exceptions are in the form:
+ *    bl handler
+ *    b .ret_from_exception
+ * and this currently fails to catch them.
+ */
+static inline int exception_frame(unsigned long ip)
 {
-	unsigned long sp;
-	unsigned long lr;
-	unsigned long stack[3];
+	extern void *ret_from_syscall_1, *ret_from_syscall_2, *ret_from_except;
+
+	if ((ip == (unsigned long)ret_from_syscall_1) ||
+	    (ip == (unsigned long)ret_from_syscall_2) ||
+	    (ip == (unsigned long)ret_from_except))
+		return 1;
+
+	return 0;
+}
+
+static int xmon_depth_to_print = 64;
+
+static void xmon_show_stack(unsigned long sp)
+{
+	unsigned long ip;
+	unsigned long newsp;
+	int count = 0;
 	struct pt_regs regs;
-	int framecount;
-	char *funcname;
-	/* declare these as raw ptrs so we don't get func descriptors */
-	extern void *ret_from_except, *ret_from_syscall_1;
 
-	if (excp != NULL) {
-	        lr = excp->link;
-		sp = excp->gpr[1];
-	} else {
-	        /* Use care not to call any function before this point
-		 so the saved lr has a chance of being good. */
-	        asm volatile ("mflr %0" : "=r" (lr) :);
-		sp = getsp();
-	}
-	scanhex(&sp);
-	scannl();
-	for (framecount = 0;
-	     sp != 0 && framecount < MAXFRAMECOUNT;
-	     sp = stack[0], framecount++) {
-		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
-			break;
-#if 0
-		if (lr != 0) {
-		    stack[2] = lr;	/* fake out the first saved lr.  It may not be saved yet. */
-		    lr = 0;
+	do {
+		if (sp < PAGE_OFFSET) {
+			printf("SP in userspace\n");
+			break;
 		}
-#endif
-		printf("%.16lx  %.16lx", sp, stack[2]);
-		/* TAI -- for now only the ones cast to unsigned long will match.
-		 * Need to test the rest...
-		 */
-		if ((stack[2] == (unsigned long)ret_from_except &&
-		            (funcname = "ret_from_except"))
-		    || (stack[2] == (unsigned long)ret_from_syscall_1 &&
-		            (funcname = "ret_from_syscall_1"))
-#if 0
-		    || stack[2] == (unsigned) &ret_from_syscall_2
-		    || stack[2] == (unsigned) &do_signal_ret
-#endif
-		    ) {
-			printf("  %s\n", funcname);
+
+		if (!mread((sp + 16), &ip, sizeof(unsigned long)))
+			break;
+
+		printf("[%016lx] [%016lx] ", sp, ip);
+		xmon_print_symbol("%s\n", ip);
+
+		if (exception_frame(ip)) {
 			if (mread(sp+112, &regs, sizeof(regs)) != sizeof(regs))
 				break;
-			printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112);
-			printf("                  %.16lx", regs.nip);
-			if (regs.nip & 0xffffffff00000000UL)
-				xmon_print_symbol("  %s", regs.nip);
-			printf("\n");
-                        if (regs.gpr[1] < sp) {
-                            printf("<Stack drops into userspace %.16lx>\n", regs.gpr[1]);
-                            break;
-			}
 
-			sp = regs.gpr[1];
-			if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
-				break;
-		} else {
-			if (stack[2])
-				xmon_print_symbol("  %s", stack[2]);
-			printf("\n");
-		}
-		if (stack[0] && stack[0] <= sp) {
-			if ((stack[0] & 0xffffffff00000000UL) == 0)
-				printf("<Stack drops into 32-bit userspace %.16lx>\n", stack[0]);
-			else
-				printf("<Corrupt stack.  Next backchain is %.16lx>\n", stack[0]);
-			break;
+                        printf("  exception: %lx %s regs %lx\n", regs.trap,
+			       getvecname(regs.trap), sp+112);
 		}
-	}
-	if (framecount >= MAXFRAMECOUNT)
-		printf("<Punt. Too many stack frames>\n");
+
+		if (!mread(sp, &newsp, sizeof(unsigned long)))
+			break;
+		if (newsp < sp)
+			break;
+
+		sp = newsp;
+	} while (count++ < xmon_depth_to_print);
 }
 
-int
-getsp()
+static void backtrace(struct pt_regs *excp)
 {
-	int x;
+	unsigned long sp;
+
+	if (excp == NULL)
+		sp = __get_SP();
+	else
+		sp = excp->gpr[1];
+
+	scanhex(&sp);
+	scannl();
 
-	asm("mr %0,1" : "=r" (x) :);
-	return x;
+	xmon_show_stack(sp);
 }
 
 spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED;
diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig
--- a/arch/s390/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/Kconfig	Wed Mar 17 19:29:09 2004
@@ -96,23 +96,10 @@
 	  Even if you don't know what to do here, say Y.
 
 config NR_CPUS
-	int "Maximum number of CPUs (2-32)"
-	range 2 32
-	depends on SMP && ARCH_S390X = 'n'
-	default "32"
-	help
-	  This allows you to specify the maximum number of CPUs which this
-	  kernel will support.  The maximum supported value is 32 and the
-	  minimum value which makes sense is 2.
-
-	  This is purely to save memory - each supported CPU adds
-	  approximately eight kilobytes to the kernel image.
-	
-config NR_CPUS
 	int "Maximum number of CPUs (2-64)"
 	range 2 64
-	depends on SMP && ARCH_S390X
-	default "64"
+	depends on SMP
+	default "32"
 	help
 	  This allows you to specify the maximum number of CPUs which this
 	  kernel will support.  The maximum supported value is 64 and the
diff -Nru a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
--- a/arch/s390/appldata/appldata_base.c	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/appldata/appldata_base.c	Wed Mar 17 19:29:09 2004
@@ -233,8 +233,8 @@
 				.buffer_addr = virt_to_phys((void *) buffer)
 	};
 
-        if (!MACHINE_IS_VM)
-                return -ENOSYS;
+	if (!MACHINE_IS_VM)
+		return -ENOSYS;
 	ry = -1;
 	asm volatile(
 			"diag %1,%0,0xDC\n\t"
@@ -336,9 +336,9 @@
 		P_ERROR("Timer CPU interval has to be > 0!\n");
 		return -EINVAL;
 	}
-	per_cpu_interval = (u64) (interval*1000 / num_online_cpus()) * TOD_MICRO;
 
 	spin_lock(&appldata_timer_lock);
+	per_cpu_interval = (u64) (interval*1000 / num_online_cpus()) * TOD_MICRO;
 	appldata_interval = interval;
 	if (appldata_timer_active) {
 		for (i = 0; i < num_online_cpus(); i++) {
@@ -395,6 +395,10 @@
 
 	spin_lock_bh(&appldata_ops_lock);
 	if ((buf[0] == '1') && (ops->active == 0)) {
+		if (!try_module_get(ops->owner)) {
+			spin_unlock_bh(&appldata_ops_lock);
+			return -ENODEV;
+		}
 		ops->active = 1;
 		ops->callback(ops->data);	// init record
 		rc = appldata_diag(ops->record_nr,
@@ -403,6 +407,7 @@
 		if (rc != 0) {
 			P_ERROR("START DIAG 0xDC for %s failed, "
 				"return code: %d\n", ops->name, rc);
+			module_put(ops->owner);
 			ops->active = 0;
 		} else {
 			P_INFO("Monitoring %s data enabled, "
@@ -419,6 +424,7 @@
 			P_INFO("Monitoring %s data disabled, "
 				"DIAG 0xDC stopped.\n", ops->name);
 		}
+		module_put(ops->owner);
 	}
 	spin_unlock_bh(&appldata_ops_lock);
 out:
@@ -440,30 +446,26 @@
 {
 	struct list_head *lh;
 	struct appldata_ops *tmp_ops;
-	int rc, i;
+	int i;
 
-	rc = 0;
 	i = 0;
 
 	if ((ops->size > APPLDATA_MAX_REC_SIZE) ||
 		(ops->size < 0)){
 		P_ERROR("Invalid size of %s record = %i, maximum = %i!\n",
 			ops->name, ops->size, APPLDATA_MAX_REC_SIZE);
-		rc = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 	if ((ops->ctl_nr == CTL_APPLDATA) ||
 	    (ops->ctl_nr == CTL_APPLDATA_TIMER) ||
 	    (ops->ctl_nr == CTL_APPLDATA_INTERVAL)) {
 		P_ERROR("ctl_nr %i already in use!\n", ops->ctl_nr);
-		rc = -EBUSY;
-		goto out;
+		return -EBUSY;
 	}
 	ops->ctl_table = kmalloc(4*sizeof(struct ctl_table), GFP_KERNEL);
 	if (ops->ctl_table == NULL) {
 		P_ERROR("Not enough memory for %s ctl_table!\n", ops->name);
-		rc = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 	memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table));
 
@@ -477,18 +479,16 @@
 			ops->ctl_nr);
 		if (strncmp(tmp_ops->name, ops->name,
 				APPLDATA_PROC_NAME_LENGTH) == 0) {
-			spin_unlock_bh(&appldata_ops_lock);
 			P_ERROR("Name \"%s\" already registered!\n", ops->name);
 			kfree(ops->ctl_table);
-			rc = -EBUSY;
-			goto out;
+			spin_unlock_bh(&appldata_ops_lock);
+			return -EBUSY;
 		}
 		if (tmp_ops->ctl_nr == ops->ctl_nr) {
-			spin_unlock_bh(&appldata_ops_lock);
 			P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr);
 			kfree(ops->ctl_table);
-			rc = -EBUSY;
-			goto out;
+			spin_unlock_bh(&appldata_ops_lock);
+			return -EBUSY;
 		}
 	}
 	list_add(&ops->list, &appldata_ops_list);
@@ -512,9 +512,9 @@
 
 	ops->sysctl_header = register_sysctl_table(ops->ctl_table,1);
 	ops->ctl_table[2].de->owner = ops->owner;
+
 	P_INFO("%s-ops registered!\n", ops->name);
-out:
-	return rc;
+	return 0;
 }
 
 /*
@@ -524,26 +524,11 @@
  */
 void appldata_unregister_ops(struct appldata_ops *ops)
 {
-	int rc;
-
-	unregister_sysctl_table(ops->sysctl_header);
-	kfree(ops->ctl_table);
-	if (ops->active == 1) {
-		ops->active = 0;
-		rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
-				(unsigned long) ops->data, ops->size);
-		if (rc != 0) {
-			P_ERROR("STOP DIAG 0xDC for %s failed, "
-				"return code: %d\n", ops->name, rc);
-		} else {
-			P_INFO("Monitoring %s data disabled, "
-				"DIAG 0xDC stopped.\n", ops->name);
-		}
-
-	}
 	spin_lock_bh(&appldata_ops_lock);
 	list_del(&ops->list);
 	spin_unlock_bh(&appldata_ops_lock);
+	unregister_sysctl_table(ops->sysctl_header);
+	kfree(ops->ctl_table);
 	P_INFO("%s-ops unregistered!\n", ops->name);
 }
 /********************** module-ops management <END> **************************/
diff -Nru a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
--- a/arch/s390/appldata/appldata_mem.c	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/appldata/appldata_mem.c	Wed Mar 17 19:29:09 2004
@@ -27,6 +27,15 @@
 
 /*
  * Memory data
+ *
+ * This is accessed as binary data by z/VM. If changes to it can't be avoided,
+ * the structure version (product ID, see appldata_base.c) needs to be changed
+ * as well and all documentation and z/VM applications using it must be
+ * updated.
+ *
+ * The record layout is documented in the Linux for zSeries Device Drivers
+ * book:
+ * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
 struct appldata_mem_data {
 	u64 timestamp;
@@ -54,9 +63,7 @@
 	u64 freeswap;		/* free swap space */
 
 // New in 2.6 -->
-	u64 pgalloc_high;	/* page allocations */
-	u64 pgalloc_normal;
-	u64 pgalloc_dma;
+	u64 pgalloc;		/* page allocations */
 	u64 pgfault;		/* page faults (major+minor) */
 	u64 pgmajfault;		/* page faults (major only) */
 // <-- New in 2.6
@@ -71,9 +78,7 @@
 	P_DEBUG("pgpgout    = %8lu KB\n", mem_data->pgpgout);
 	P_DEBUG("pswpin     = %8lu Pages\n", mem_data->pswpin);
 	P_DEBUG("pswpout    = %8lu Pages\n", mem_data->pswpout);
-	P_DEBUG("pgalloc_high   = %8lu \n", mem_data->pgalloc_high);
-	P_DEBUG("pgalloc_normal = %8lu \n", mem_data->pgalloc_normal);
-	P_DEBUG("pgalloc_dma    = %8lu \n", mem_data->pgalloc_dma);
+	P_DEBUG("pgalloc    = %8lu \n", mem_data->pgalloc);
 	P_DEBUG("pgfault    = %8lu \n", mem_data->pgfault);
 	P_DEBUG("pgmajfault = %8lu \n", mem_data->pgmajfault);
 	P_DEBUG("sharedram  = %8lu KB\n", mem_data->sharedram);
@@ -109,14 +114,10 @@
 	mem_data->pgpgout    = ps.pgpgout >> 1;
 	mem_data->pswpin     = ps.pswpin;
 	mem_data->pswpout    = ps.pswpout;
-	mem_data->pgalloc_high   = ps.pgalloc_high;
-	mem_data->pgalloc_normal = ps.pgalloc_normal;
-	mem_data->pgalloc_dma    = ps.pgalloc_dma;
+	mem_data->pgalloc    = ps.pgalloc_high + ps.pgalloc_normal +
+			       ps.pgalloc_dma;
 	mem_data->pgfault    = ps.pgfault;
 	mem_data->pgmajfault = ps.pgmajfault;
-
-P_DEBUG("pgalloc_high = %lu, pgalloc_normal = %lu, pgalloc_dma = %lu, pgfree = %lu\n",
-	ps.pgalloc_high, ps.pgalloc_normal, ps.pgalloc_dma, ps.pgfree);
 
 	si_meminfo(&val);
 	mem_data->sharedram = val.sharedram;
diff -Nru a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c
--- a/arch/s390/appldata/appldata_net_sum.c	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/appldata/appldata_net_sum.c	Wed Mar 17 19:29:09 2004
@@ -26,6 +26,14 @@
 
 /*
  * Network data
+ *
+ * This is accessed as binary data by z/VM. If changes to it can't be avoided,
+ * the structure version (product ID, see appldata_base.c) needs to be changed
+ * as well and all documentation and z/VM applications using it must be updated.
+ *
+ * The record layout is documented in the Linux for zSeries Device Drivers
+ * book:
+ * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
 struct appldata_net_sum_data {
 	u64 timestamp;
diff -Nru a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c
--- a/arch/s390/appldata/appldata_os.c	Wed Mar 17 19:29:10 2004
+++ b/arch/s390/appldata/appldata_os.c	Wed Mar 17 19:29:10 2004
@@ -28,6 +28,15 @@
 
 /*
  * OS data
+ *
+ * This is accessed as binary data by z/VM. If changes to it can't be avoided,
+ * the structure version (product ID, see appldata_base.c) needs to be changed
+ * as well and all documentation and z/VM applications using it must be
+ * updated.
+ *
+ * The record layout is documented in the Linux for zSeries Device Drivers
+ * book:
+ * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
 struct appldata_os_per_cpu {
 	u32 per_cpu_user;	/* timer ticks spent in user mode   */
diff -Nru a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
--- a/arch/s390/kernel/asm-offsets.c	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/kernel/asm-offsets.c	Wed Mar 17 19:29:09 2004
@@ -22,6 +22,10 @@
 	DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),);
 	DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),);
 	BLANK();
+	DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid),);
+	DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address),);
+	DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id),);
+	BLANK();
 	DEFINE(__TI_task, offsetof(struct thread_info, task),);
 	DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain),);
 	DEFINE(__TI_flags, offsetof(struct thread_info, flags),);
diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
--- a/arch/s390/kernel/compat_linux.c	Wed Mar 17 19:29:10 2004
+++ b/arch/s390/kernel/compat_linux.c	Wed Mar 17 19:29:10 2004
@@ -828,11 +828,6 @@
 	return err;
 }
 
-asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
-{
-	return sys_sysfs(option, arg1, arg2);
-}
-
 struct ncp_mount_data32 {
         int version;
         unsigned int ncp_fd;
@@ -1718,33 +1713,6 @@
 	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
-asmlinkage int sys32_utimes(char __user *filename,
-			struct compat_timeval __user *tvs)
-{
-	char *kfilename;
-	struct timeval ktvs[2];
-	mm_segment_t old_fs;
-	int ret;
-
-	kfilename = getname(filename);
-	ret = PTR_ERR(kfilename);
-	if (!IS_ERR(kfilename)) {
-		if (tvs) {
-			if (get_tv32(&ktvs[0], tvs) ||
-			    get_tv32(&ktvs[1], 1+tvs))
-				return -EFAULT;
-		}
-
-		old_fs = get_fs();
-		set_fs(KERNEL_DS);
-		ret = sys_utimes(kfilename, &ktvs[0]);
-		set_fs(old_fs);
-
-		putname(kfilename);
-	}
-	return ret;
-}
-
 /* These are here just in case some old sparc32 binary calls it. */
 asmlinkage int sys32_pause(void)
 {
@@ -1753,17 +1721,6 @@
 	return -ERESTARTNOHAND;
 }
 
-
-asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
-{
-	return sys_prctl(option,
-			 (unsigned long) arg2,
-			 (unsigned long) arg3,
-			 (unsigned long) arg4,
-			 (unsigned long) arg5);
-}
-
-
 asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf,
 				 compat_size_t count, u32 poshi, u32 poslo)
 {
@@ -1895,13 +1852,6 @@
 		ret = -EFAULT;
 
 	return ret;
-}
-
-asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
-{
-	return sys_setpriority((int) which,
-			       (int) who,
-			       (int) niceval);
 }
 
 struct __sysctl_args32 {
diff -Nru a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
--- a/arch/s390/kernel/compat_linux.h	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/kernel/compat_linux.h	Wed Mar 17 19:29:09 2004
@@ -144,6 +144,11 @@
 			 PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | \
 			 PSW32_MASK_PSTATE)
 
+#define PSW32_MASK_MERGE(CURRENT,NEW) \
+        (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
+         ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
+
+
 typedef struct
 {
 	_psw_t32	psw;
diff -Nru a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
--- a/arch/s390/kernel/compat_signal.c	Wed Mar 17 19:29:10 2004
+++ b/arch/s390/kernel/compat_signal.c	Wed Mar 17 19:29:10 2004
@@ -53,8 +53,6 @@
 
 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
-int do_signal32(struct pt_regs *regs, sigset_t *oldset);
-
 int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
 {
 	int err;
@@ -123,7 +121,7 @@
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
-		if (do_signal32(regs, &saveset))
+		if (do_signal(regs, &saveset))
 			return -EINTR;
 	}
 }
@@ -158,7 +156,7 @@
         while (1) {
                 set_current_state(TASK_INTERRUPTIBLE);
                 schedule();
-                if (do_signal32(regs, &saveset))
+                if (do_signal(regs, &saveset))
                         return -EINTR;
         }
 }                                                         
@@ -294,8 +292,8 @@
 	_s390_regs_common32 regs32;
 	int err, i;
 
-	regs32.psw.mask = PSW32_USER_BITS |
-		((__u32)(regs->psw.mask >> 32) & PSW32_MASK_CC);
+	regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS,
+					   (__u32)(regs->psw.mask >> 32));
 	regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
 	for (i = 0; i < NUM_GPRS; i++)
 		regs32.gprs[i] = (__u32) regs->gprs[i];
@@ -320,8 +318,8 @@
 	err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
 	if (err)
 		return err;
-	regs->psw.mask = PSW_USER32_BITS |
-		(__u64)(regs32.psw.mask & PSW32_MASK_CC) << 32;
+	regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
+				        (__u64)regs32.psw.mask << 32);
 	regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
 	for (i = 0; i < NUM_GPRS; i++)
 		regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -482,7 +480,6 @@
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (__u64) frame;
 	regs->psw.addr = (__u64) ka->sa.sa_handler;
-	regs->psw.mask = PSW_USER32_BITS;
 
 	regs->gprs[2] = map_signal(sig);
 	regs->gprs[3] = (__u64) &frame->sc;
@@ -539,7 +536,6 @@
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (__u64) frame;
 	regs->psw.addr = (__u64) ka->sa.sa_handler;
-	regs->psw.mask = PSW_USER32_BITS;
 
 	regs->gprs[2] = map_signal(sig);
 	regs->gprs[3] = (__u64) &frame->info;
@@ -556,36 +552,12 @@
  * OK, we're invoking a handler
  */	
 
-static void
+void
 handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
 	struct pt_regs * regs)
 {
 	struct k_sigaction *ka = &current->sighand->action[sig-1];
 
-	/* Are we from a system call? */
-	if (regs->trap == __LC_SVC_OLD_PSW) {
-		/* If so, check system call restarting.. */
-		switch (regs->gprs[2]) {
-			case -ERESTART_RESTARTBLOCK:
-				current_thread_info()->restart_block.fn =
-					do_no_restart_syscall;
-				clear_thread_flag(TIF_RESTART_SVC);
-			case -ERESTARTNOHAND:
-				regs->gprs[2] = -EINTR;
-				break;
-
-			case -ERESTARTSYS:
-				if (!(ka->sa.sa_flags & SA_RESTART)) {
-					regs->gprs[2] = -EINTR;
-					break;
-				}
-			/* fallthrough */
-			case -ERESTARTNOINTR:
-				regs->gprs[2] = regs->orig_gpr2;
-				regs->psw.addr -= regs->ilc;
-		}
-	}
-
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame32(sig, ka, info, oldset, regs);
@@ -604,53 +576,3 @@
 	}
 }
 
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- *
- * Note that we go through the signals twice: once to check the signals that
- * the kernel can handle, and then we build all the user-level signal handling
- * stack-frames in one go after that.
- */
-int do_signal32(struct pt_regs *regs, sigset_t *oldset)
-{
-	siginfo_t info;
-	int signr;
-
-	/*
-	 * We want the common case to go fast, which
-	 * is why we may in certain cases get here from
-	 * kernel mode. Just return without doing anything
-	 * if so.
-	 */
-	if (!user_mode(regs))
-		return 1;
-
-	if (!oldset)
-		oldset = &current->blocked;
-
-	signr = get_signal_to_deliver(&info, regs, NULL);
-	if (signr > 0) {
-		/* Whee!  Actually deliver the signal.  */
-		handle_signal32(signr, &info, oldset, regs);
-		return 1;
-	}
-
-	/* Did we come from a system call? */
-	if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
-		/* Restart the system call - no handlers present */
-		if (regs->gprs[2] == -ERESTARTNOHAND ||
-		    regs->gprs[2] == -ERESTARTSYS ||
-		    regs->gprs[2] == -ERESTARTNOINTR) {
-			regs->gprs[2] = regs->orig_gpr2;
-			regs->psw.addr -= regs->ilc;
-		}
-		/* Restart the system call with a new system call number */
-		if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) {
-			regs->gprs[2] = __NR_restart_syscall;
-			set_thread_flag(TIF_RESTART_SVC);
-		}
-	}
-	return 0;
-}
diff -Nru a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
--- a/arch/s390/kernel/compat_wrapper.S	Wed Mar 17 19:29:10 2004
+++ b/arch/s390/kernel/compat_wrapper.S	Wed Mar 17 19:29:10 2004
@@ -1097,6 +1097,7 @@
 	lgfr	%r3,%r3			# int
 	lgfr	%r4,%r4			# int
 	llgtr	%r5,%r5			# struct compat_timespec *
+	llgtr	%r6,%r6			# u32 *
 	jg	compat_sys_futex	# branch to system call
 
 	.globl	sys32_setxattr_wrapper
@@ -1338,3 +1339,17 @@
 	llgtr	%r3,%r3			# struct iocb *
 	llgtr	%r4,%r4			# struct io_event *
 	jg	sys_io_cancel
+
+	.globl compat_sys_statfs64_wrapper
+compat_sys_statfs64_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# compat_size_t
+	llgtr	%r4,%r4			# struct compat_statfs64 *
+	jg	compat_statfs64
+
+	.globl compat_sys_fstatfs64_wrapper
+compat_sys_fstatfs64_wrapper:
+	llgfr	%r2,%r2			# unsigned int fd
+	llgfr	%r3,%r3			# compat_size_t
+	llgtr	%r4,%r4			# struct compat_statfs64 *
+	jg	compat_fstatfs64
diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/kernel/entry.S	Wed Mar 17 19:29:09 2004
@@ -432,6 +432,9 @@
 pgm_per_std:
 	SAVE_ALL __LC_PGM_OLD_PSW,1
 	GET_THREAD_INFO
+	mvc	__THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID
+	mvc	__THREAD_per+__PER_address(4,%r9),__LC_PER_ADDRESS
+	mvc	__THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID
 	la	%r4,0x7f
 	l	%r3,__LC_PGM_ILC	 # load program interruption code
         nr      %r4,%r3                  # clear per-event-bit and ilc
@@ -445,7 +448,7 @@
 	la      %r2,SP_PTREGS(15)	 # address of register-save area
         l       %r1,BASED(.Lhandle_per)  # load adr. of per handler
         la      %r14,BASED(sysc_return)  # load adr. of system return
-        br      %r1			 # branch to handle_per_exception
+        br      %r1			 # branch to do_debugger_trap
 
 #
 # it was a single stepped SVC that is causing all the trouble
@@ -455,6 +458,9 @@
 	lh	%r7,0x8a	  # get svc number from lowcore
         stosm   24(%r15),0x03     # reenable interrupts
         GET_THREAD_INFO           # load pointer to task_struct to R9
+	mvc	__THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID
+	mvc	__THREAD_per+__PER_address(4,%r9),__LC_PER_ADDRESS
+	mvc	__THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID
         sla     %r7,2             # *4 and test for svc 0
 	bnz	BASED(pgm_svcstd) # svc number > 0 ?
 	# svc 0: system call number in %r1
@@ -473,18 +479,18 @@
 
 pgm_svcret:
 	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
-	bo	BASED(pgm_svcper_nosig)
+	bno	BASED(pgm_svcper_nosig)
 	la	%r2,SP_PTREGS(%r15) # load pt_regs
 	sr	%r3,%r3		  # clear *oldset
 	l	%r1,BASED(.Ldo_signal)
-	basr	%r4,%r1		  # call do_signal
+	basr	%r14,%r1	  # call do_signal
 	
 pgm_svcper_nosig:
         mvi     SP_TRAP+3(%r15),0x28     # set trap indication to pgm check
 	la      %r2,SP_PTREGS(15)        # address of register-save area
         l       %r1,BASED(.Lhandle_per)  # load adr. of per handler
         la      %r14,BASED(sysc_return)  # load adr. of system return
-        br      %r1                      # branch to handle_per_exception
+        br      %r1                      # branch to do_debugger_trap
 #
 # call trace before and after sys_call
 #
@@ -690,7 +696,7 @@
 .Ldo_softirq:  .long  do_softirq
 .Lentry_base:  .long  entry_base
 .Lext_hash:    .long  ext_int_hash
-.Lhandle_per:  .long  handle_per_exception
+.Lhandle_per:  .long  do_debugger_trap
 .Ljump_table:  .long  pgm_check_table
 .Lschedule:    .long  schedule
 .Lclone:       .long  sys_clone
diff -Nru a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
--- a/arch/s390/kernel/entry64.S	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/kernel/entry64.S	Wed Mar 17 19:29:09 2004
@@ -471,6 +471,9 @@
 pgm_per_std:
 	SAVE_ALL __LC_PGM_OLD_PSW,1
 	GET_THREAD_INFO
+	mvc	__THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID
+	mvc	__THREAD_per+__PER_address(8,%r9),__LC_PER_ADDRESS
+	mvc	__THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID
 	lghi    %r4,0x7f
 	lgf     %r3,__LC_PGM_ILC	 # load program interruption code
         nr      %r4,%r3			 # clear per-event-bit and ilc
@@ -483,7 +486,7 @@
 pgm_per_only:
         la      %r2,SP_PTREGS(15)	 # address of register-save area
         larl    %r14,sysc_return	 # load adr. of system return
-        jg      handle_per_exception
+        jg      do_debugger_trap
 
 #
 # it was a single stepped SVC that is causing all the trouble
@@ -493,6 +496,9 @@
 	llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
 	stosm   48(%r15),0x03     # reenable interrupts
         GET_THREAD_INFO           # load pointer to task_struct to R9
+	mvc	__THREAD_per+__PER_atmid(2,%r9),__LC_PER_ATMID
+	mvc	__THREAD_per+__PER_address(8,%r9),__LC_PER_ADDRESS
+	mvc	__THREAD_per+__PER_access_id(1,%r9),__LC_PER_ACCESS_ID
 	slag	%r7,%r7,2         # *4 and test for svc 0
 	jnz	pgm_svcstd
 	# svc 0: system call number in %r1
@@ -516,7 +522,7 @@
 
 pgm_svcret:
 	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
-	jo	pgm_svcper_nosig
+	jno	pgm_svcper_nosig
         la      %r2,SP_PTREGS(%r15) # load pt_regs
         sgr     %r3,%r3             # clear *oldset
 	brasl	%r14,do_signal
@@ -526,7 +532,7 @@
 	st      %r0,SP_TRAP(%r15)
         la      %r2,SP_PTREGS(15) # address of register-save area
         larl    %r14,sysc_return  # load adr. of system return
-        jg      handle_per_exception
+        jg      do_debugger_trap
 #
 # call trace before and after sys_call
 #
diff -Nru a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
--- a/arch/s390/kernel/ptrace.c	Wed Mar 17 19:29:10 2004
+++ b/arch/s390/kernel/ptrace.c	Wed Mar 17 19:29:10 2004
@@ -193,9 +193,9 @@
 		 */
 		if (addr == (addr_t) &dummy->regs.psw.mask &&
 #ifdef CONFIG_S390_SUPPORT
-		    (data & ~PSW_MASK_CC) != PSW_USER32_BITS &&
+		    data != PSW_MASK_MERGE(PSW_USER32_BITS, data) &&
 #endif
-		    (data & ~PSW_MASK_CC) != PSW_USER_BITS)
+		    data != PSW_MASK_MERGE(PSW_USER_BITS, data))
 			/* Invalid psw mask. */
 			return -EINVAL;
 #ifndef CONFIG_ARCH_S390X
@@ -331,7 +331,7 @@
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Fake a 31 bit psw mask. */
 			tmp = (__u32)(__KSTK_PTREGS(child)->psw.mask >> 32);
-			tmp = (tmp & PSW32_MASK_CC) | PSW32_USER_BITS;
+			tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp);
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Fake a 31 bit psw address. */
 			tmp = (__u32) __KSTK_PTREGS(child)->psw.addr |
@@ -402,11 +402,11 @@
 		 */
 		if (addr == (addr_t) &dummy32->regs.psw.mask) {
 			/* Build a 64 bit psw mask from 31 bit mask. */
-			if ((tmp & ~PSW32_MASK_CC) != PSW32_USER_BITS)
+			if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp))
 				/* Invalid psw mask. */
 				return -EINVAL;
-			__KSTK_PTREGS(child)->psw.mask = PSW_USER32_BITS |
-				((tmp & PSW32_MASK_CC) << 32);
+			__KSTK_PTREGS(child)->psw.mask =
+				PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32);
 		} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
 			/* Build a 64 bit psw address from 31 bit address. */
 			__KSTK_PTREGS(child)->psw.addr = 
diff -Nru a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
--- a/arch/s390/kernel/signal.c	Wed Mar 17 19:29:10 2004
+++ b/arch/s390/kernel/signal.c	Wed Mar 17 19:29:10 2004
@@ -148,9 +148,14 @@
 /* Returns non-zero on fault. */
 static int save_sigregs(struct pt_regs *regs, _sigregs *sregs)
 {
+	unsigned long old_mask = regs->psw.mask;
 	int err;
   
+	/* Copy a 'clean' PSW mask to the user to avoid leaking
+	   information about whether PER is currently on.  */
+	regs->psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask);
 	err = __copy_to_user(&sregs->regs, regs, sizeof(_s390_regs_common));
+	regs->psw.mask = old_mask;
 	if (err != 0)
 		return err;
 	/* 
@@ -165,13 +170,14 @@
 /* Returns positive number on error */
 static int restore_sigregs(struct pt_regs *regs, _sigregs *sregs)
 {
+	unsigned long old_mask = regs->psw.mask;
 	int err;
 
 	/* Alwys make any pending restarted system call return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
 	err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
-	regs->psw.mask = PSW_USER_BITS | (regs->psw.mask & PSW_MASK_CC);
+	regs->psw.mask = PSW_MASK_MERGE(old_mask, regs->psw.mask);
 	regs->psw.addr |= PSW_ADDR_AMODE;
 	if (err)
 		return err;
@@ -319,7 +325,6 @@
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
-	regs->psw.mask = PSW_USER_BITS;
 
 	regs->gprs[2] = map_signal(sig);
 	regs->gprs[3] = (unsigned long) &frame->sc;
@@ -378,7 +383,6 @@
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (unsigned long) frame;
 	regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
-	regs->psw.mask = PSW_USER_BITS;
 
 	regs->gprs[2] = map_signal(sig);
 	regs->gprs[3] = (unsigned long) &frame->info;
@@ -401,30 +405,6 @@
 {
 	struct k_sigaction *ka = &current->sighand->action[sig-1];
 
-	/* Are we from a system call? */
-	if (regs->trap == __LC_SVC_OLD_PSW) {
-		/* If so, check system call restarting.. */
-		switch (regs->gprs[2]) {
-			case -ERESTART_RESTARTBLOCK:
-				current_thread_info()->restart_block.fn =
-					do_no_restart_syscall;
-				clear_thread_flag(TIF_RESTART_SVC);
-			case -ERESTARTNOHAND:
-				regs->gprs[2] = -EINTR;
-				break;
-
-			case -ERESTARTSYS:
-				if (!(ka->sa.sa_flags & SA_RESTART)) {
-					regs->gprs[2] = -EINTR;
-					break;
-				}
-			/* fallthrough */
-			case -ERESTARTNOINTR:
-				regs->gprs[2] = regs->orig_gpr2;
-				regs->psw.addr -= regs->ilc;
-		}
-	}
-
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame(sig, ka, info, oldset, regs);
@@ -454,6 +434,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;
 
@@ -468,35 +449,62 @@
 
 	if (!oldset)
 		oldset = &current->blocked;
-#ifdef CONFIG_S390_SUPPORT 
-	if (test_thread_flag(TIF_31BIT)) {
-		extern asmlinkage int do_signal32(struct pt_regs *regs,
-						  sigset_t *oldset); 
-		return do_signal32(regs, oldset);
-        }
-#endif 
 
+	/* Are we from a system call? */
+	if (regs->trap == __LC_SVC_OLD_PSW) {
+		continue_addr = regs->psw.addr;
+		restart_addr = continue_addr - regs->ilc;
+		retval = regs->gprs[2];
+
+		/* Prepare for system call restart.  We do this here so that a
+		   debugger will see the already changed PSW. */
+		if (retval == -ERESTARTNOHAND ||
+		    retval == -ERESTARTSYS ||
+		    retval == -ERESTARTNOINTR) {
+			regs->gprs[2] = regs->orig_gpr2;
+			regs->psw.addr = restart_addr;
+		} else if (retval == -ERESTART_RESTARTBLOCK) {
+			regs->gprs[2] = -EINTR;
+		}
+	}
+
+	/* 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);
+
+	/* Depending on the signal settings we may need to revert the
+	   decision to restart the system call. */
+	if (signr > 0 && regs->psw.addr == restart_addr) {
+		if (retval == -ERESTARTNOHAND
+		    || (retval == -ERESTARTSYS
+			 && !(current->sighand->action[signr-1].sa.sa_flags
+			      & SA_RESTART))) {
+			regs->gprs[2] = -EINTR;
+			regs->psw.addr = continue_addr;
+		}
+	}
+
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
+#ifdef CONFIG_S390_SUPPORT
+		if (test_thread_flag(TIF_31BIT)) {
+			extern void handle_signal32(unsigned long sig,
+						    siginfo_t *info,
+						    sigset_t *oldset,
+						    struct pt_regs *regs);
+			handle_signal32(signr, &info, oldset, regs);
+			return 1;
+	        }
+#endif
 		handle_signal(signr, &info, oldset, regs);
 		return 1;
 	}
 
-	/* Did we come from a system call? */
-	if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
-		/* Restart the system call - no handlers present */
-		if (regs->gprs[2] == -ERESTARTNOHAND ||
-		    regs->gprs[2] == -ERESTARTSYS ||
-		    regs->gprs[2] == -ERESTARTNOINTR) {
-			regs->gprs[2] = regs->orig_gpr2;
-			regs->psw.addr -= regs->ilc;
-		}
-		/* Restart the system call with a new system call number */
-		if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) {
-			regs->gprs[2] = __NR_restart_syscall;
-			set_thread_flag(TIF_RESTART_SVC);
-		}
+	/* Restart a different system call. */
+	if (retval == -ERESTART_RESTARTBLOCK
+	    && regs->psw.addr == continue_addr) {
+		regs->gprs[2] = __NR_restart_syscall;
+		set_thread_flag(TIF_RESTART_SVC);
 	}
 	return 0;
 }
diff -Nru a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
--- a/arch/s390/kernel/sys_s390.c	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/kernel/sys_s390.c	Wed Mar 17 19:29:09 2004
@@ -245,52 +245,7 @@
 	return -EINVAL;
 }
 
-/*
- * Old cruft
- */
-asmlinkage int sys_uname(struct old_utsname * name)
-{
-	int err;
-	if (!name)
-		return -EFAULT;
-	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
-}
-
-#ifndef CONFIG_ARCH_S390X
-asmlinkage int sys_olduname(struct oldold_utsname * name)
-{
-	int error;
-
-	if (!name)
-		return -EFAULT;
-	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-		return -EFAULT;
-  
-  	down_read(&uts_sem);
-	
-	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	error |= __put_user(0,name->release+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	error |= __put_user(0,name->version+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-	error |= __put_user(0,name->machine+__OLD_UTS_LEN);
-	
-	up_read(&uts_sem);
-	
-	error = error ? -EFAULT : 0;
-
-	return error;
-}
-
-#else /* CONFIG_ARCH_S390X */
-
+#ifdef CONFIG_ARCH_S390X
 asmlinkage int s390x_newuname(struct new_utsname * name)
 {
 	int ret = sys_newuname(name);
diff -Nru a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
--- a/arch/s390/kernel/syscalls.S	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/kernel/syscalls.S	Wed Mar 17 19:29:09 2004
@@ -54,7 +54,7 @@
 SYSCALL(sys_times,sys_times,compat_sys_times_wrapper)
 NI_SYSCALL							/* old prof syscall */
 SYSCALL(sys_brk,sys_brk,sys32_brk_wrapper)			/* 45 */
-SYSCALL(sys_setgid16,sys_ni_syscall,sys32_setgid16)		/* old setgid16 syscall*/
+SYSCALL(sys_setgid16,sys_ni_syscall,sys32_setgid16_wrapper)	/* old setgid16 syscall*/
 SYSCALL(sys_getgid16,sys_ni_syscall,sys32_getgid16)		/* old getgid16 syscall*/
 SYSCALL(sys_signal,sys_signal,sys32_signal_wrapper)
 SYSCALL(sys_geteuid16,sys_ni_syscall,sys32_geteuid16)		/* old geteuid16 syscall */
@@ -273,3 +273,5 @@
 SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys32_clock_nanosleep_wrapper)
 NI_SYSCALL							/* reserved for vserver */
 SYSCALL(s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper)
+SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64_wrapper)
+SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64_wrapper)
diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
--- a/arch/s390/kernel/traps.c	Wed Mar 17 19:29:09 2004
+++ b/arch/s390/kernel/traps.c	Wed Mar 17 19:29:09 2004
@@ -308,7 +308,7 @@
 	return (void *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN);
 }
 
-static int do_debugger_trap(struct pt_regs *regs)
+int do_debugger_trap(struct pt_regs *regs)
 {
 	if ((regs->psw.mask & PSW_MASK_PSTATE) &&
 	    (current->ptrace & PT_PTRACED)) {
@@ -652,23 +652,3 @@
 #endif
 	}
 }
-
-
-void handle_per_exception(struct pt_regs *regs)
-{
-	if (regs->psw.mask & PSW_MASK_PSTATE) {
-		per_struct *per_info=&current->thread.per_info;
-		per_info->lowcore.words.perc_atmid=S390_lowcore.per_perc_atmid;
-		per_info->lowcore.words.address=S390_lowcore.per_address;
-		per_info->lowcore.words.access_id=S390_lowcore.per_access_id;
-	}
-	if (do_debugger_trap(regs)) {
-		/* I've seen this possibly a task structure being reused ? */
-		printk("Spurious per exception detected\n");
-		printk("switching off per tracing for this task.\n");
-		show_regs(regs);
-		/* Hopefully switching off per tracing will help us survive */
-		regs->psw.mask &= ~PSW_MASK_PER;
-	}
-}
-
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	Wed Mar 17 19:29:09 2004
+++ b/arch/sparc64/defconfig	Wed Mar 17 19:29:09 2004
@@ -384,7 +384,6 @@
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=m
-# CONFIG_DM_IOCTL_V4 is not set
 CONFIG_DM_CRYPT=m
 
 #
@@ -1075,12 +1074,10 @@
 CONFIG_I2C_ALI15X3=m
 CONFIG_I2C_AMD756=m
 CONFIG_I2C_AMD8111=m
-CONFIG_I2C_ELV=m
 CONFIG_I2C_I801=m
 CONFIG_I2C_I810=m
 CONFIG_I2C_ISA=m
 CONFIG_I2C_NFORCE2=m
-CONFIG_I2C_PHILIPSPAR=m
 CONFIG_I2C_PARPORT=m
 CONFIG_I2C_PARPORT_LIGHT=m
 CONFIG_I2C_PROSAVAGE=m
@@ -1089,7 +1086,6 @@
 CONFIG_I2C_SIS5595=m
 CONFIG_I2C_SIS630=m
 CONFIG_I2C_SIS96X=m
-CONFIG_I2C_VELLEMAN=m
 CONFIG_I2C_VIA=m
 CONFIG_I2C_VIAPRO=m
 CONFIG_I2C_VOODOO3=m
diff -Nru a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c
--- a/arch/sparc64/kernel/init_task.c	Wed Mar 17 19:29:10 2004
+++ b/arch/sparc64/kernel/init_task.c	Wed Mar 17 19:29:10 2004
@@ -24,14 +24,6 @@
 union thread_union init_thread_union = { INIT_THREAD_INFO(init_task) };
 
 /*
- * This is to make the init_thread+stack be the right size for >8k pagesize.
- * The definition of thread_union in sched.h makes it 16k wide.
- */
-#if PAGE_SHIFT != 13
-char init_task_stack[THREAD_SIZE - INIT_THREAD_SIZE] = { 0 };
-#endif
-
-/*
  * Initial task structure.
  *
  * All other task structs will be allocated on slabs in fork.c
diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
--- a/arch/x86_64/kernel/setup.c	Wed Mar 17 19:29:09 2004
+++ b/arch/x86_64/kernel/setup.c	Wed Mar 17 19:29:09 2004
@@ -596,8 +596,6 @@
 static void __init detect_ht(void)
 {
 #ifdef CONFIG_SMP
-	extern	int phys_proc_id[NR_CPUS];
-	
 	u32 	eax, ebx, ecx, edx;
 	int 	index_lsb, index_msb, tmp;
 	int	initial_apic_id;
@@ -1011,7 +1009,6 @@
 	
 #ifdef CONFIG_X86_HT
 	if (cpu_has_ht) {
-		extern int phys_proc_id[NR_CPUS];
 		seq_printf(m, "physical id\t: %d\n", phys_proc_id[c - cpu_data]);
 		seq_printf(m, "siblings\t: %d\n", smp_num_siblings);
 	}
diff -Nru a/drivers/block/carmel.c b/drivers/block/carmel.c
--- a/drivers/block/carmel.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/block/carmel.c	Wed Mar 17 19:29:10 2004
@@ -1,3 +1,14 @@
+/*
+ *  carmel.c: Driver for Promise SATA SX8 looks-like-I2O hardware
+ *
+ *  Copyright 2004 Red Hat, Inc.
+ *
+ *  Author/maintainer:  Jeff Garzik <jgarzik@pobox.com>
+ *
+ *  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.
+ */
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -21,7 +32,7 @@
 
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Promise SX8 (carmel) block driver");
+MODULE_DESCRIPTION("Promise SATA SX8 (carmel) block driver");
 
 #if 0
 #define CARM_DEBUG
@@ -1527,6 +1538,9 @@
 		struct gendisk *disk = host->port[i].disk;
 		if (disk) {
 			request_queue_t *q = disk->queue;
+
+			if (disk->flags & GENHD_FL_UP)
+				del_gendisk(disk);
 			if (q)
 				blk_cleanup_queue(q);
 			put_disk(disk);
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/block/cpqarray.c	Wed Mar 17 19:29:09 2004
@@ -16,7 +16,7 @@
  *    along with this program; if not, write to the Free Software
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *    Questions/Comments/Bugfixes to arrays@compaq.com
+ *    Questions/Comments/Bugfixes to Cpqarray-discuss@lists.sourceforge.net
  *
  */
 #include <linux/config.h>	/* CONFIG_PROC_FS */
@@ -46,13 +46,13 @@
 
 #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 
-#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.5)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,5)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 2.6.0)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,6,0)
 
 /* Embedded module documentation macros - see modules.h */
 /* Original author Chris Frantz - Compaq Computer Corporation */
 MODULE_AUTHOR("Compaq Computer Corporation");
-MODULE_DESCRIPTION("Driver for Compaq Smart2 Array Controllers");
+MODULE_DESCRIPTION("Driver for Compaq Smart2 Array Controllers version 2.6.0");
 MODULE_LICENSE("GPL");
 
 #include "cpqarray.h"
@@ -97,6 +97,34 @@
 	{ 0x40580E11, "Smart Array 431",	&smart4_access },
 };
 
+/* define the PCI info for the PCI cards this driver can control */
+const struct pci_device_id cpqarray_pci_device_id[] =
+{
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_COMPAQ_42XX,
+		0x0E11, 0x4058, 0, 0, 0},       /* SA431 */
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_COMPAQ_42XX,
+		0x0E11, 0x4051, 0, 0, 0},      /* SA4250ES */
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_COMPAQ_42XX,
+		0x0E11, 0x4050, 0, 0, 0},      /* SA4200 */
+	{ PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C1510,
+		0x0E11, 0x4048, 0, 0, 0},       /* LC2 */
+	{ PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C1510,
+		0x0E11, 0x4040, 0, 0, 0},      /* Integrated Array */
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4034, 0, 0, 0},       /* SA 221 */
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4033, 0, 0, 0},       /* SA 3100ES*/
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4032, 0, 0, 0},       /* SA 3200*/
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4031, 0, 0, 0},       /* SA 2SL*/
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_SMART2P,
+		0x0E11, 0x4030, 0, 0, 0},       /* SA 2P */
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, cpqarray_pci_device_id);
+
 static struct gendisk *ida_gendisk[MAX_CTLR][NWD];
 
 /* Debug... */
@@ -108,7 +136,7 @@
 /* Debug Extra Paranoid... */
 #define DBGPX(s) do { } while(0)
 
-static int cpqarray_pci_detect(void);
+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 int cpqarray_eisa_detect(void);
@@ -119,6 +147,9 @@
 static cmdlist_t * cmd_alloc(ctlr_info_t *h, int get_from_pool);
 static void cmd_free(ctlr_info_t *h, cmdlist_t *c, int got_from_pool);
 
+static void free_hba(int i);
+static int alloc_cpqarray_hba(void);
+
 static int sendcmd(
 	__u8	cmd,
 	int	ctlr,
@@ -145,6 +176,7 @@
 static void ida_timer(unsigned long tdata);
 static int ida_revalidate(struct gendisk *disk);
 static int revalidate_allvol(ctlr_info_t *host);
+static int cpqarray_register_ctlr(int ctlr, struct pci_dev *pdev);
 
 #ifdef CONFIG_PROC_FS
 static void ida_procinit(int i);
@@ -224,7 +256,7 @@
 		(unsigned long)h->board_id,
 		h->firm_rev[0], h->firm_rev[1], h->firm_rev[2], h->firm_rev[3],
 		(unsigned long)h->ctlr_sig, (unsigned long)h->vaddr,
-		(unsigned int) h->ioaddr, (unsigned int)h->intr,
+		(unsigned int) h->io_mem_addr, (unsigned int)h->intr,
 		h->log_drives, h->phys_drives,
 		h->Qdepth, h->maxQsinceinit);
 
@@ -281,150 +313,188 @@
 
 MODULE_PARM(eisa, "1-8i");
 
-static void __exit cpqarray_exit(void)
+/* This is a bit of a hack,
+ * necessary to support both eisa and pci
+ */
+int __init cpqarray_init(void)
+{
+	return (cpqarray_init_step2());
+}
+
+static void release_io_mem(ctlr_info_t *c)
 {
-	int i, j;
-	char buff[4]; 
+	/* if IO mem was not protected do nothing */
+	if( c->io_mem_addr == 0)
+		return;
+	release_region(c->io_mem_addr, c->io_mem_length);
+	c->io_mem_addr = 0;
+	c->io_mem_length = 0;
+}
 
-	for(i=0; i<nr_ctlr; i++) {
+static void __devexit cpqarray_remove_one(int i)
+{
+	int j;
+	char buff[4];
 
-		/* sendcmd will turn off interrupt, and send the flush... 
-		 * To write all data in the battery backed cache to disks    
-		 * no data returned, but don't want to send NULL to sendcmd */	
-		if( sendcmd(FLUSH_CACHE, i, buff, 4, 0, 0, 0))
-		{
-			printk(KERN_WARNING "Unable to flush cache on "
-				"controller %d\n", i);	
-		}
-		free_irq(hba[i]->intr, hba[i]);
-		iounmap(hba[i]->vaddr);
-		unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
-		del_timer(&hba[i]->timer);
-		blk_cleanup_queue(hba[i]->queue);
-		remove_proc_entry(hba[i]->devname, proc_array);
-		pci_free_consistent(hba[i]->pci_dev, 
-			NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool), 
+	/* sendcmd will turn off interrupt, and send the flush...
+	 * To write all data in the battery backed cache to disks
+	 * no data returned, but don't want to send NULL to sendcmd */
+	if( sendcmd(FLUSH_CACHE, i, buff, 4, 0, 0, 0))
+	{
+		printk(KERN_WARNING "Unable to flush cache on controller %d\n",
+				i);
+	}
+	free_irq(hba[i]->intr, hba[i]);
+	iounmap(hba[i]->vaddr);
+	unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
+	del_timer(&hba[i]->timer);
+	remove_proc_entry(hba[i]->devname, proc_array);
+	pci_free_consistent(hba[i]->pci_dev,
+			NR_CMDS * sizeof(cmdlist_t), (hba[i]->cmd_pool),
 			hba[i]->cmd_pool_dhandle);
-		kfree(hba[i]->cmd_pool_bits);
+	kfree(hba[i]->cmd_pool_bits);
+	for(j = 0; j < NWD; j++) {
+		if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
+			del_gendisk(ida_gendisk[i][j]);
+		devfs_remove("ida/c%dd%d",i,j);
+		put_disk(ida_gendisk[i][j]);
+	}
+	blk_cleanup_queue(hba[i]->queue);
+	release_io_mem(hba[i]);
+	free_hba(i);
+}
 
-		for (j = 0; j < NWD; j++) {
-			if (ida_gendisk[i][j]->flags & GENHD_FL_UP)
-				del_gendisk(ida_gendisk[i][j]);
-			devfs_remove("ida/c%dd%d",i,j);
-			put_disk(ida_gendisk[i][j]);
-		}
+static void __devexit cpqarray_remove_one_pci (struct pci_dev *pdev)
+{
+	int i;
+	ctlr_info_t *tmp_ptr;
+
+	if (pci_get_drvdata(pdev) == NULL) {
+		printk( KERN_ERR "cpqarray: Unable to remove device \n");
+		return;
 	}
-	devfs_remove("ida");
-	remove_proc_entry("cpqarray", proc_root_driver);
+
+	tmp_ptr = pci_get_drvdata(pdev);
+	i = tmp_ptr->ctlr;
+	if (hba[i] == NULL) {
+		printk(KERN_ERR "cpqarray: controller %d appears to have"
+			"already been removed \n", i);
+		return;
+        }
+	pci_set_drvdata(pdev, NULL);
+
+	cpqarray_remove_one(i);
 }
 
-/*
- *  This is it.  Find all the controllers and register them.  I really hate
- *  stealing all these major device numbers.
- *  returns the number of block devices registered.
+/* removing an instance that was not removed automatically..
+ * must be an eisa card.
  */
-static int __init cpqarray_init(void)
+static void __devexit cpqarray_remove_one_eisa (int i)
 {
-	request_queue_t *q;
-	int i,j;
-	int num_cntlrs_reg = 0;
-	/* detect controllers */
-	cpqarray_pci_detect();
-	cpqarray_eisa_detect();
-	
-	if (nr_ctlr == 0)
-		return -ENODEV;
+	if (hba[i] == NULL) {
+		printk(KERN_ERR "cpqarray: controller %d appears to have"
+			"already been removed \n", i);
+		return;
+        }
+	cpqarray_remove_one(i);
+}
 
-	printk(DRIVER_NAME "\n");
-	printk("Found %d controller(s)\n", nr_ctlr);
+/* pdev is NULL for eisa */
+static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+{
+	request_queue_t *q;
+	int j;
 
-	/* allocate space for disk structs */
 	/* 
 	 * register block devices
 	 * Find disks and fill in structs
 	 * Get an interrupt, set the Q depth and get into /proc
 	 */
-	for(i=0; i < nr_ctlr; i++) {
-	  	/* If this successful it should insure that we are the only */
-		/* instance of the driver */	
-		if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname))
-                        continue;
-
-		hba[i]->access.set_intr_mask(hba[i], 0);
-		if (request_irq(hba[i]->intr, do_ida_intr,
-			SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
 
-			printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", 
+	/* If this successful it should insure that we are the only */
+	/* instance of the driver */
+	if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname)) {
+		goto Enomem4;
+	}
+	hba[i]->access.set_intr_mask(hba[i], 0);
+	if (request_irq(hba[i]->intr, do_ida_intr,
+		SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
+	{
+		printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n",
 				hba[i]->intr, hba[i]->devname);
-			unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
-			continue;
-		}
-		num_cntlrs_reg++;
-		for (j=0; j<NWD; j++) {
-			ida_gendisk[i][j] = alloc_disk(1 << NWD_SHIFT);
-			if (!ida_gendisk[i][j])
-				goto Enomem2;
-		}
-		hba[i]->cmd_pool = (cmdlist_t *)pci_alloc_consistent(
-				hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t), 
-				&(hba[i]->cmd_pool_dhandle));
-		hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL);
+		goto Enomem3;
+	}
 		
-		if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool)
-			goto Enomem1;
-		memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
-		memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long));
-		printk(KERN_INFO "cpqarray: Finding drives on %s", 
-			hba[i]->devname);
-
-		spin_lock_init(&hba[i]->lock);
-		q = blk_init_queue(do_ida_request, &hba[i]->lock);
-		if (!q)
+	for (j=0; j<NWD; j++) {
+		ida_gendisk[i][j] = alloc_disk(1 << NWD_SHIFT);
+		if (!ida_gendisk[i][j])
+			goto Enomem2;
+	}
+
+	hba[i]->cmd_pool = (cmdlist_t *)pci_alloc_consistent(
+		hba[i]->pci_dev, NR_CMDS * sizeof(cmdlist_t),
+		&(hba[i]->cmd_pool_dhandle));
+	hba[i]->cmd_pool_bits = kmalloc(
+		((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long),
+		GFP_KERNEL);
+
+	if (!hba[i]->cmd_pool_bits || !hba[i]->cmd_pool)
 			goto Enomem1;
 
-		hba[i]->queue = q;
-		q->queuedata = hba[i];
+	memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
+	memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long));
+	printk(KERN_INFO "cpqarray: Finding drives on %s",
+		hba[i]->devname);
 
-		getgeometry(i);
-		start_fwbk(i); 
+	spin_lock_init(&hba[i]->lock);
+	q = blk_init_queue(do_ida_request, &hba[i]->lock);
+	if (!q)
+		goto Enomem1;
 
-		ida_procinit(i);
+	hba[i]->queue = q;
+	q->queuedata = hba[i];
 
+	getgeometry(i);
+	start_fwbk(i);
+
+	ida_procinit(i);
+
+	if (pdev)
 		blk_queue_bounce_limit(q, hba[i]->pci_dev->dma_mask);
 
-		/* This is a hardware imposed limit. */
-		blk_queue_max_hw_segments(q, SG_MAX);
+	/* This is a hardware imposed limit. */
+	blk_queue_max_hw_segments(q, SG_MAX);
 
-		/* This is a driver limit and could be eliminated. */
-		blk_queue_max_phys_segments(q, SG_MAX);
+	/* This is a driver limit and could be eliminated. */
+	blk_queue_max_phys_segments(q, SG_MAX);
 	
-		init_timer(&hba[i]->timer);
-		hba[i]->timer.expires = jiffies + IDA_TIMER;
-		hba[i]->timer.data = (unsigned long)hba[i];
-		hba[i]->timer.function = ida_timer;
-		add_timer(&hba[i]->timer);
-
-		/* Enable IRQ now that spinlock and rate limit timer are set up */
-		hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
-
-		for(j=0; j<NWD; j++) {
-			struct gendisk *disk = ida_gendisk[i][j];
-			drv_info_t *drv = &hba[i]->drv[j];
-			sprintf(disk->disk_name, "ida/c%dd%d", i, j);
-			disk->major = COMPAQ_SMART2_MAJOR + i;
-			disk->first_minor = j<<NWD_SHIFT;
-			disk->fops = &ida_fops; 
-			if (j && !drv->nr_blks)
-				continue;
-			blk_queue_hardsect_size(hba[i]->queue, drv->blk_size);
-			set_capacity(disk, drv->nr_blks);
-			disk->queue = hba[i]->queue;
-			disk->private_data = drv;
-			add_disk(disk);
-		}
+	init_timer(&hba[i]->timer);
+	hba[i]->timer.expires = jiffies + IDA_TIMER;
+	hba[i]->timer.data = (unsigned long)hba[i];
+	hba[i]->timer.function = ida_timer;
+	add_timer(&hba[i]->timer);
+
+	/* Enable IRQ now that spinlock and rate limit timer are set up */
+	hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
+
+	for(j=0; j<NWD; j++) {
+		struct gendisk *disk = ida_gendisk[i][j];
+		drv_info_t *drv = &hba[i]->drv[j];
+		sprintf(disk->disk_name, "ida/c%dd%d", i, j);
+		disk->major = COMPAQ_SMART2_MAJOR + i;
+		disk->first_minor = j<<NWD_SHIFT;
+		disk->fops = &ida_fops;
+		if (j && !drv->nr_blks)
+			continue;
+		blk_queue_hardsect_size(hba[i]->queue, drv->blk_size);
+		set_capacity(disk, drv->nr_blks);
+		disk->queue = hba[i]->queue;
+		disk->private_data = drv;
+		add_disk(disk);
 	}
+
 	/* done ! */
-	return num_cntlrs_reg ? 0 : -ENODEV;
+	return(i);
 
 Enomem1:
 	nr_ctlr = i; 
@@ -438,83 +508,105 @@
 		ida_gendisk[i][j] = NULL;
 	}
 	free_irq(hba[i]->intr, hba[i]);
+Enomem3:
 	unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);
-	num_cntlrs_reg--;
+Enomem4:
+	if (pdev)
+		pci_set_drvdata(pdev, NULL);
+	release_io_mem(hba[i]);
+	free_hba(i);
+
 	printk( KERN_ERR "cpqarray: out of memory");
 
-	if (!num_cntlrs_reg) {
-		remove_proc_entry("cpqarray", proc_root_driver);
-		return -ENODEV;
+	return -1;
+}
+
+static int __init cpqarray_init_one( struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	int i;
+
+	printk(KERN_DEBUG "cpqarray: Device 0x%x has been found at"
+			" bus %d dev %d func %d\n",
+			pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
+			PCI_FUNC(pdev->devfn));
+	i = alloc_cpqarray_hba();
+	if( i < 0 )
+		return (-1);
+	memset(hba[i], 0, sizeof(ctlr_info_t));
+	sprintf(hba[i]->devname, "ida%d", i);
+	hba[i]->ctlr = i;
+	/* Initialize the pdev driver private data */
+	pci_set_drvdata(pdev, hba[i]);
+
+	if (cpqarray_pci_init(hba[i], pdev) != 0) {
+		pci_set_drvdata(pdev, NULL);
+		release_io_mem(hba[i]);
+		free_hba(i);
+		return -1;
 	}
-	return 0;
+
+	return (cpqarray_register_ctlr(i, 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,
+};
+
 /*
- * Find the controller and initialize it
- *  Cannot use the class code to search, because older array controllers use
- *    0x018000 and new ones use 0x010400.  So I might as well search for each
- *    each device IDs, being there are only going to be three of them. 
- */
-static int cpqarray_pci_detect(void)
-{
-	struct pci_dev *pdev;
-
-#define IDA_BOARD_TYPES 3
-	static int ida_vendor_id[IDA_BOARD_TYPES] = { PCI_VENDOR_ID_DEC, 
-		PCI_VENDOR_ID_NCR, PCI_VENDOR_ID_COMPAQ };
-	static int ida_device_id[IDA_BOARD_TYPES] = { PCI_DEVICE_ID_COMPAQ_42XX,		PCI_DEVICE_ID_NCR_53C1510, PCI_DEVICE_ID_COMPAQ_SMART2P };
-	int brdtype;
+ *  This is it.  Find all the controllers and register them.
+ *  returns the number of block devices registered.
+ */
+int __init cpqarray_init_step2(void)
+{
+	int num_cntlrs_reg = 0;
+	int i;
+	int rc = 0;
+
+	/* detect controllers */
+	printk(DRIVER_NAME "\n");
+/* TODO: If it's an eisa only system, will rc return negative? */
+	rc = pci_register_driver(&cpqarray_pci_driver);
+	if (rc < 0)
+		return rc;
+	cpqarray_eisa_detect();
 	
-	/* search for all PCI board types that could be for this driver */
-	for(brdtype=0; brdtype<IDA_BOARD_TYPES; brdtype++)
-	{
-		pdev = pci_find_device(ida_vendor_id[brdtype],
-				       ida_device_id[brdtype], NULL);
-		while (pdev) {
-			printk(KERN_DEBUG "cpqarray: Device 0x%x has"
-				" been found at bus %d dev %d func %d\n",
-				ida_vendor_id[brdtype],
-				pdev->bus->number, PCI_SLOT(pdev->devfn),
-				PCI_FUNC(pdev->devfn));
-			if (nr_ctlr == 8) {
-				printk(KERN_WARNING "cpqarray: This driver"
-				" supports a maximum of 8 controllers.\n");
-				break;
-			}
-			
-/* if it is a PCI_DEVICE_ID_NCR_53C1510, make sure it's 				the Compaq version of the chip */ 
+	for (i=0; i < MAX_CTLR; i++) {
+		if (hba[i] != NULL)
+			num_cntlrs_reg++;
+	}
 
-			if (ida_device_id[brdtype] == PCI_DEVICE_ID_NCR_53C1510)			{	
-				unsigned short subvendor=pdev->subsystem_vendor;
-				if(subvendor !=  PCI_VENDOR_ID_COMPAQ)
-				{
-					printk(KERN_DEBUG 
-						"cpqarray: not a Compaq integrated array controller\n");
-					continue;
-				}
-			}
+	return(num_cntlrs_reg);
+}
 
-			hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);			if(hba[nr_ctlr]==NULL)
-			{
+/* Function to find the first free pointer into our hba[] array */
+/* Returns -1 if no free entries are left.  */
+static int alloc_cpqarray_hba(void)
+{
+	int i;
+
+	for(i=0; i< MAX_CTLR; i++) {
+		if (hba[i] == NULL) {
+			hba[i] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+			if(hba[i]==NULL) {
 				printk(KERN_ERR "cpqarray: out of memory.\n");
-				continue;
-			}
-			memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
-			if (cpqarray_pci_init(hba[nr_ctlr], pdev) != 0)
-			{
-				kfree(hba[nr_ctlr]);
-				continue;
+				return (-1);
 			}
-			sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
-			hba[nr_ctlr]->ctlr = nr_ctlr;
-			nr_ctlr++;
-
-			pdev = pci_find_device(ida_vendor_id[brdtype],
-					       ida_device_id[brdtype], pdev);
+			return (i);
 		}
 	}
+	printk(KERN_WARNING "cpqarray: This driver supports a maximum"
+		" of 8 controllers.\n");
+	return(-1);
+}
 
-	return nr_ctlr;
+static void free_hba(int i)
+{
+	kfree(hba[i]);
+	hba[i]=NULL;
 }
 
 /*
@@ -556,6 +648,13 @@
 
 	pci_read_config_dword(pdev, 0x2c, &board_id);
 
+	/* check to see if controller has been disabled */
+	if(!(command & 0x02)) {
+		printk(KERN_WARNING
+			"cpqarray: controller appears to be disabled\n");
+		return(-1);
+	}
+
 DBGINFO(
 	printk("vendor_id = %x\n", vendor_id);
 	printk("device_id = %x\n", device_id);
@@ -570,11 +669,28 @@
 );
 
 	c->intr = irq;
-	c->ioaddr = addr[0];
+
+	for(i=0; i<6; i++) {
+		if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO)
+		{ /* IO space */
+			c->io_mem_addr = addr[i];
+			c->io_mem_length = pci_resource_end(pdev, i)
+				- pci_resource_start(pdev, i) + 1;
+			if(!request_region( c->io_mem_addr, c->io_mem_length,
+				"cpqarray"))
+			{
+				printk( KERN_WARNING "cpqarray I/O memory range already in use addr %lx length = %ld\n", c->io_mem_addr, c->io_mem_length);
+				c->io_mem_addr = 0;
+				c->io_mem_length = 0;
+			}
+			break;
+		}
+	}
 
 	c->paddr = 0;
 	for(i=0; i<6; i++)
-		if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
+		if (!(pci_resource_flags(pdev, i) &
+				PCI_BASE_ADDRESS_SPACE_IO)) {
 			c->paddr = pci_resource_start (pdev, i);
 			break;
 		}
@@ -654,13 +770,13 @@
 	int i=0, j;
 	__u32 board_id;
 	int intr;
+	int ctlr;
+	int num_ctlr = 0;
 
 	while(i<8 && eisa[i]) {
-		if (nr_ctlr == 8) {
-			printk(KERN_WARNING "cpqarray: This driver supports"
-				" a maximum of 8 controllers.\n");
+		ctlr = alloc_cpqarray_hba();
+		if(ctlr == -1)
 			break;
-		}
 		board_id = inl(eisa[i]+0xC80);
 		for(j=0; j < NR_PRODUCTS; j++)
 			if (board_id == products[j].board_id) 
@@ -671,14 +787,21 @@
 				" to access the SMART Array controller %08lx\n",				 (unsigned long)board_id);
 			continue;
 		}
-		hba[nr_ctlr] = (ctlr_info_t *) kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
-		if(hba[nr_ctlr]==NULL)
+
+		memset(hba[ctlr], 0, sizeof(ctlr_info_t));
+		hba[ctlr]->io_mem_addr = eisa[i];
+		hba[ctlr]->io_mem_length = 0x7FF;
+		if(!request_region(hba[ctlr]->io_mem_addr,
+				hba[ctlr]->io_mem_length,
+				"cpqarray"))
 		{
-			printk(KERN_ERR "cpqarray: out of memory.\n");
+			printk(KERN_WARNING "cpqarray: I/O range already in "
+					"use addr = %lx length = %ld\n",
+					hba[ctlr]->io_mem_addr,
+					hba[ctlr]->io_mem_length);
+			free_hba(ctlr);
 			continue;
 		}
-		memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
-		hba[nr_ctlr]->ioaddr = eisa[i];
 
 		/*
 		 * Read the config register to find our interrupt
@@ -689,13 +812,13 @@
 		else if (intr & 4) intr = 14;
 		else if (intr & 8) intr = 15;
 		
-		hba[nr_ctlr]->intr = intr;
-		sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
-		hba[nr_ctlr]->product_name = products[j].product_name;
-		hba[nr_ctlr]->access = *(products[j].access);
-		hba[nr_ctlr]->ctlr = nr_ctlr;
-		hba[nr_ctlr]->board_id = board_id;
-		hba[nr_ctlr]->pci_dev = NULL; /* not PCI */
+		hba[ctlr]->intr = intr;
+		sprintf(hba[ctlr]->devname, "ida%d", nr_ctlr);
+		hba[ctlr]->product_name = products[j].product_name;
+		hba[ctlr]->access = *(products[j].access);
+		hba[ctlr]->ctlr = ctlr;
+		hba[ctlr]->board_id = board_id;
+		hba[ctlr]->pci_dev = NULL; /* not PCI */
 
 DBGINFO(
 	printk("i = %d, j = %d\n", i, j);
@@ -704,14 +827,19 @@
 	printk("board_id = %x\n", board_id);
 );
 
-		nr_ctlr++;
+		num_ctlr++;
 		i++;
+
+		if (cpqarray_register_ctlr(ctlr, NULL) == -1)
+			printk(KERN_WARNING
+				"cpqarray: Can't register EISA controller %d\n",
+				ctlr);
+
 	}
 
-	return nr_ctlr;
+	return num_ctlr;
 }
 
-
 /*
  * Open.  Make sure the device is really there.
  */
@@ -1719,6 +1847,25 @@
 	kfree(id_ctlr_buf);
 	return;
 
+}
+
+static void __exit cpqarray_exit(void)
+{
+	int i;
+
+	pci_unregister_driver(&cpqarray_pci_driver);
+
+	/* Double check that all controller entries have been removed */
+	for(i=0; i<MAX_CTLR; i++) {
+		if (hba[i] != NULL) {
+			printk(KERN_WARNING "cpqarray: Removing EISA "
+					"controller %d\n", i);
+			cpqarray_remove_one_eisa(i);
+		}
+	}
+
+	devfs_remove("ida");
+	remove_proc_entry("cpqarray", proc_root_driver);
 }
 
 module_init(cpqarray_init)
diff -Nru a/drivers/block/cpqarray.h b/drivers/block/cpqarray.h
--- a/drivers/block/cpqarray.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/block/cpqarray.h	Wed Mar 17 19:29:09 2004
@@ -92,7 +92,8 @@
 
 	void *vaddr;
 	unsigned long paddr;
-	unsigned long ioaddr;
+	unsigned long io_mem_addr;
+	unsigned long io_mem_length;
 	int	intr;
 	int	usage_count;
 	drv_info_t	drv[NWD];
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/block/genhd.c	Wed Mar 17 19:29:09 2004
@@ -184,7 +184,7 @@
 }
 
 /**
- * add_gendisk - add partitioning information to kernel list
+ * add_disk - add partitioning information to kernel list
  * @disk: per-device partitioning information
  *
  * This function registers the partitioning information in @disk
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/block/ll_rw_blk.c	Wed Mar 17 19:29:09 2004
@@ -47,7 +47,10 @@
 static LIST_HEAD(blk_plug_list);
 static spinlock_t blk_plug_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
-static wait_queue_head_t congestion_wqh[2];
+static wait_queue_head_t congestion_wqh[2] = {
+		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
+		__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
+	};
 
 /*
  * Controlling structure to kblockd
@@ -2084,6 +2087,15 @@
 	if (!q->merge_requests_fn(q, req, next))
 		return 0;
 
+	/*
+	 * At this point we have either done a back merge
+	 * or front merge. We need the smaller start_time of
+	 * the merged requests to be the current request
+	 * for accounting purposes.
+	 */
+	if (time_after(req->start_time, next->start_time))
+		req->start_time = next->start_time;
+
 	req->biotail->bi_next = next->bio;
 	req->biotail = next->biotail;
 
@@ -2825,8 +2837,6 @@
 
 int __init blk_dev_init(void)
 {
-	int i;
-
 	kblockd_workqueue = create_workqueue("kblockd");
 	if (!kblockd_workqueue)
 		panic("Failed to create kblockd\n");
@@ -2838,9 +2848,6 @@
 
 	blk_max_low_pfn = max_low_pfn;
 	blk_max_pfn = max_pfn;
-
-	for (i = 0; i < ARRAY_SIZE(congestion_wqh); i++)
-		init_waitqueue_head(&congestion_wqh[i]);
 	return 0;
 }
 
diff -Nru a/drivers/block/smart1,2.h b/drivers/block/smart1,2.h
--- a/drivers/block/smart1,2.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/block/smart1,2.h	Wed Mar 17 19:29:09 2004
@@ -156,27 +156,27 @@
  */
 static void smart2e_submit_command(ctlr_info_t *h, cmdlist_t *c)
 {
-	outl(c->busaddr, h->ioaddr + COMMAND_FIFO);
+	outl(c->busaddr, h->io_mem_addr + COMMAND_FIFO);
 }
 
 static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val)
 {
-	outl(val, h->ioaddr + INTR_MASK);
+	outl(val, h->io_mem_addr + INTR_MASK);
 }
 
 static unsigned long smart2e_fifo_full(ctlr_info_t *h)
 {
-	return inl(h->ioaddr + COMMAND_FIFO);
+	return inl(h->io_mem_addr + COMMAND_FIFO);
 }
 
 static unsigned long smart2e_completed(ctlr_info_t *h)
 {
-	return inl(h->ioaddr + COMMAND_COMPLETE_FIFO);
+	return inl(h->io_mem_addr + COMMAND_COMPLETE_FIFO);
 }
 
 static unsigned long smart2e_intr_pending(ctlr_info_t *h)
 {
-	return inl(h->ioaddr + INTR_PENDING);
+	return inl(h->io_mem_addr + INTR_PENDING);
 }
 
 static struct access_method smart2e_access = {
@@ -212,30 +212,30 @@
 	 */
 	c->hdr.size = 0;
 
-	outb(CHANNEL_CLEAR, h->ioaddr + SMART1_SYSTEM_DOORBELL);
+	outb(CHANNEL_CLEAR, h->io_mem_addr + SMART1_SYSTEM_DOORBELL);
 
-	outl(c->busaddr, h->ioaddr + SMART1_LISTADDR);
-	outw(c->size, h->ioaddr + SMART1_LISTLEN);
+	outl(c->busaddr, h->io_mem_addr + SMART1_LISTADDR);
+	outw(c->size, h->io_mem_addr + SMART1_LISTLEN);
 
-	outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
+	outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
 }
 
 static void smart1_intr_mask(ctlr_info_t *h, unsigned long val)
 {
 	if (val == 1) {
-		outb(0xFD, h->ioaddr + SMART1_SYSTEM_DOORBELL);
-		outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
-		outb(0x01, h->ioaddr + SMART1_INTR_MASK);
-		outb(0x01, h->ioaddr + SMART1_SYSTEM_MASK);
+		outb(0xFD, h->io_mem_addr + SMART1_SYSTEM_DOORBELL);
+		outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
+		outb(0x01, h->io_mem_addr + SMART1_INTR_MASK);
+		outb(0x01, h->io_mem_addr + SMART1_SYSTEM_MASK);
 	} else {
-		outb(0, h->ioaddr + 0xC8E);
+		outb(0, h->io_mem_addr + 0xC8E);
 	}
 }
 
 static unsigned long smart1_fifo_full(ctlr_info_t *h)
 {
 	unsigned char chan;
-	chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_CLEAR;
+	chan = inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_CLEAR;
 	return chan;
 }
 
@@ -244,13 +244,13 @@
 	unsigned char status;
 	unsigned long cmd;
 
-	if (inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) {
-		outb(CHANNEL_BUSY, h->ioaddr + SMART1_SYSTEM_DOORBELL);
+	if (inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) {
+		outb(CHANNEL_BUSY, h->io_mem_addr + SMART1_SYSTEM_DOORBELL);
 
-		cmd = inl(h->ioaddr + SMART1_COMPLETE_ADDR);
-		status = inb(h->ioaddr + SMART1_LISTSTATUS);
+		cmd = inl(h->io_mem_addr + SMART1_COMPLETE_ADDR);
+		status = inb(h->io_mem_addr + SMART1_LISTSTATUS);
 
-		outb(CHANNEL_CLEAR, h->ioaddr + SMART1_LOCAL_DOORBELL);
+		outb(CHANNEL_CLEAR, h->io_mem_addr + SMART1_LOCAL_DOORBELL);
 
 		/*
 		 * this is x86 (actually compaq x86) only, so it's ok
@@ -265,7 +265,7 @@
 static unsigned long smart1_intr_pending(ctlr_info_t *h)
 {
 	unsigned char chan;
-	chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY;
+	chan = inb(h->io_mem_addr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY;
 	return chan;
 }
 
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/cdrom/cdrom.c	Wed Mar 17 19:29:09 2004
@@ -646,6 +646,80 @@
 	return 0;
 }
 
+int cdrom_get_random_writable(struct cdrom_device_info *cdi,
+			      struct rwrt_feature_desc *rfd)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[24];
+	struct feature_header *fh;
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;	/* often 0x46 */
+	cgc.cmd[3] = CDF_RWRT;			/* often 0x0020 */
+	cgc.cmd[8] = sizeof(buffer);		/* often 0x18 */
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+		return ret;
+
+	fh = (struct feature_header *)&buffer[0];
+	if (be32_to_cpu(fh->data_len) >= (sizeof(struct feature_header)+
+					  sizeof(struct rwrt_feature_desc)))
+		memcpy(rfd, &buffer[sizeof(struct feature_header)],
+		       sizeof (*rfd));
+	else
+		memset(rfd, 0, sizeof(*rfd));
+
+	return 0;
+}
+
+int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[16];
+	struct feature_header *fh;
+	__u16 *feature_code;
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;	/* often 0x46 */
+	cgc.cmd[3] = CDF_HWDM;			/* often 0x0024 */
+	cgc.cmd[8] = sizeof(buffer);		/* often 0x10 */
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+		return ret;
+
+	fh = (struct feature_header *)&buffer[0];
+	ret = 1;
+	if (be32_to_cpu(fh->data_len) >= (sizeof(struct feature_header)+8)) {
+		feature_code = (__u16 *)&buffer[sizeof(struct feature_header)];
+		if (CDF_HWDM == be16_to_cpu(*feature_code))
+			ret = 0;
+	}
+	return ret;
+}
+
+
+int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+
+	*write = 0;
+
+	if ((ret = cdrom_get_random_writable(cdi, &rfd)))
+		return ret;
+
+	if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
+		*write = 1;
+
+	return 0;
+}
+
 static int cdrom_media_erasable(struct cdrom_device_info *cdi)
 {
 	disc_information di;
@@ -729,6 +803,23 @@
 	return buffer[3] & 0x80;
 }
 
+static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+
+	if ((ret = cdrom_has_defect_mgt(cdi)))
+		return ret;
+
+	if ((ret = cdrom_get_random_writable(cdi, &rfd)))
+		return ret;
+	else if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
+		ret = !rfd.curr;
+
+	cdinfo(CD_OPEN, "can open for random write\n");
+	return ret;
+}
+
 /*
  * returns 0 for ok to open write, non-0 to disallow
  */
@@ -740,6 +831,9 @@
 		ret = cdrom_mrw_open_write(cdi);
 	else if (CDROM_CAN(CDC_DVD_RAM))
 		ret = cdrom_dvdram_open_write(cdi);
+ 	else if (CDROM_CAN(CDC_RAM) &&
+ 		 !CDROM_CAN(CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_MRW))
+ 		ret = cdrom_ram_open_write(cdi);
 	else if (CDROM_CAN(CDC_MO_DRIVE))
 		ret = mo_open_write(cdi);
 
@@ -2785,6 +2879,7 @@
 EXPORT_SYMBOL(init_cdrom_command);
 EXPORT_SYMBOL(cdrom_get_media_event);
 EXPORT_SYMBOL(cdrom_is_mrw);
+EXPORT_SYMBOL(cdrom_is_random_writable);
 
 #ifdef CONFIG_SYSCTL
 
@@ -2888,6 +2983,10 @@
 	pos += sprintf(info+pos, "\nCan write MRW:\t");
 	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
 	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
+
+	pos += sprintf(info+pos, "\nCan write RAM:\t");
+	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
 
 	strcpy(info+pos,"\n\n");
 		
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/cdrom/cdu31a.c	Wed Mar 17 19:29:09 2004
@@ -3203,13 +3203,16 @@
 static char *load_mech[] __initdata =
     { "caddy", "tray", "pop-up", "unknown" };
 
-static void __init
+static int __init
 get_drive_configuration(unsigned short base_io,
 			unsigned char res_reg[], unsigned int *res_size)
 {
 	unsigned long retry_count;
 
 
+	if (!request_region(base_io, 4, "cdu31a"))
+		return 0;
+
 	/* Set the base address */
 	cdu31a_port = base_io;
 
@@ -3244,7 +3247,7 @@
 		/* If attention is never seen probably not a CDU31a present */
 		if (!is_attention()) {
 			res_reg[0] = 0x20;
-			return;
+			goto out_err;
 		}
 #endif
 
@@ -3254,11 +3257,17 @@
 		do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
 			       NULL,
 			       0, (unsigned char *) res_reg, res_size);
-		return;
+		if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0)
+			goto out_err;
+		return 1;
 	}
 
 	/* Return an error */
 	res_reg[0] = 0x20;
+out_err:
+	release_region(cdu31a_port, 4);
+	cdu31a_port = 0;
+	return 0;
 }
 
 #ifndef MODULE
@@ -3307,10 +3316,8 @@
 	char msg[255];
 	char buf[40];
 	int i;
-	int drive_found;
 	int tmp_irq;
 
-
 	/*
 	 * According to Alex Freed (freed@europa.orion.adobe.com), this is
 	 * required for the Fusion CD-16 package.  If the sound driver is
@@ -3323,51 +3330,32 @@
 		outb(0xe2, 0x9a01);
 	}
 
-	drive_found = 0;
-
 	/* Setting the base I/O address to 0xffff will disable it. */
-	if (cdu31a_port == 0xffff) {
-	} else if (cdu31a_port != 0) {
-		tmp_irq = cdu31a_irq;	/* Need IRQ 0 because we can't sleep here. */
-		cdu31a_irq = 0;
-
-		get_drive_configuration(cdu31a_port,
-					drive_config.exec_status,
-					&res_size);
-		if ((res_size > 2)
-		    && ((drive_config.exec_status[0] & 0xf0) == 0x00)) {
-			drive_found = 1;
-		}
+	if (cdu31a_port == 0xffff)
+		goto errout3;
 
+	if (cdu31a_port != 0) {
+		/* Need IRQ 0 because we can't sleep here. */
+		tmp_irq = cdu31a_irq;
+		cdu31a_irq = 0;
+		if (!get_drive_configuration(cdu31a_port,
+					    drive_config.exec_status,
+					    &res_size))
+			goto errout3;
 		cdu31a_irq = tmp_irq;
 	} else {
 		cdu31a_irq = 0;
-		i = 0;
-		while ((cdu31a_addresses[i].base != 0)
-		       && (!drive_found)) {
-			if (check_region(cdu31a_addresses[i].base, 4)) {
-				i++;
-				continue;
-			}
-			get_drive_configuration(cdu31a_addresses[i].base,
-						drive_config.exec_status,
-						&res_size);
-			if ((res_size > 2)
-			    && ((drive_config.exec_status[0] & 0xf0) ==
-				0x00)) {
-				drive_found = 1;
+		for (i = 0; cdu31a_addresses[i].base; i++) {
+			if (get_drive_configuration(cdu31a_addresses[i].base,
+						     drive_config.exec_status,
+						     &res_size)) {
 				cdu31a_irq = cdu31a_addresses[i].int_num;
-			} else {
-				i++;
+				break;
 			}
 		}
+		if (!cdu31a_port)
+			goto errout3;
 	}
-
-	if (!drive_found)
-		goto errout3;
-
-	if (!request_region(cdu31a_port, 4, "cdu31a"))
-		goto errout3;
 
 	if (register_blkdev(MAJOR_NR, "cdu31a"))
 		goto errout2;
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/cdrom/cm206.c	Wed Mar 17 19:29:10 2004
@@ -1389,7 +1389,7 @@
 
    Linus says it is too dangerous to use writes for probing, so we
    stick with pure reads for a while. Hope that 8 possible ranges,
-   check_region, 15 bits of one port and 6 of another make things
+   request_region, 15 bits of one port and 6 of another make things
    likely enough to accept the region on the first hit...
  */
 int __init probe_base_port(int base)
@@ -1400,13 +1400,15 @@
 	if (base)
 		b = e = base;
 	for (base = b; base <= e; base += 0x10) {
-		if (check_region(base, 0x10))
+		if (!request_region(base, 0x10,"cm206"))
 			continue;
 		for (i = 0; i < 3; i++)
 			fool = inw(base + 2);	/* empty possibly uart_receive_buffer */
 		if ((inw(base + 6) & 0xffef) != 0x0001 ||	/* line_status */
-		    (inw(base) & 0xad00) != 0)	/* data status */
+		    (inw(base) & 0xad00) != 0)	{ /* data status */
+		    	release_region(base,0x10);
 			continue;
+		}
 		return (base);
 	}
 	return 0;
@@ -1444,7 +1446,6 @@
 		return -EIO;
 	}
 	printk(" adapter at 0x%x", cm206_base);
-	request_region(cm206_base, 16, "cm206");
 	cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
 	if (!cd)
                goto out_base;
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/cdrom/sjcd.c	Wed Mar 17 19:29:09 2004
@@ -1700,7 +1700,7 @@
 	sprintf(sjcd_disk->disk_name, "sjcd");
 	sprintf(sjcd_disk->devfs_name, "sjcd");
 
-	if (check_region(sjcd_base, 4)) {
+	if (!request_region(sjcd_base, 4,"sjcd")) {
 		printk
 		    ("SJCD: Init failed, I/O port (%X) is already in use\n",
 		     sjcd_base);
diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
--- a/drivers/char/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/char/Kconfig	Wed Mar 17 19:29:09 2004
@@ -599,30 +599,6 @@
 	bool "Support for console on line printer"
 	depends on PC9800_OLDLP
 
-
-menu "Mice"
-
-config BUSMOUSE
-	tristate "Bus Mouse Support"
-	---help---
-	  Say Y here if your machine has a bus mouse as opposed to a serial
-	  mouse. Most people have a regular serial MouseSystem or
-	  Microsoft mouse (made by Logitech) that plugs into a COM port
-	  (rectangular with 9 or 25 pins). These people say N here. 
-
-	  If you have a laptop, you either have to check the documentation or
-	  experiment a bit to find out whether the trackball is a serial mouse
-	  or not; it's best to say Y here for you.
-
-	  This is the generic bus mouse driver code. If you have a bus mouse,
-	  you will have to say Y here and also to the specific driver for your
-	  mouse below.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called busmouse.
-
-endmenu
-
 config QIC02_TAPE
 	tristate "QIC-02 tape support"
 	help
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Wed Mar 17 19:29:10 2004
+++ b/drivers/char/Makefile	Wed Mar 17 19:29:10 2004
@@ -49,7 +49,6 @@
 obj-$(CONFIG_TIPAR) += tipar.o
 obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o
 
-obj-$(CONFIG_BUSMOUSE) += busmouse.o
 obj-$(CONFIG_DTLK) += dtlk.o
 obj-$(CONFIG_R3964) += n_r3964.o
 obj-$(CONFIG_APPLICOM) += applicom.o
diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
--- a/drivers/char/agp/hp-agp.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/char/agp/hp-agp.c	Wed Mar 17 19:29:10 2004
@@ -27,10 +27,6 @@
 #define HP_ZX1_TCNFG		0x318
 #define HP_ZX1_PDIR_BASE	0x320
 
-/* HP ZX1 LBA registers */
-#define HP_ZX1_AGP_STATUS	0x64
-#define HP_ZX1_AGP_COMMAND	0x68
-
 #define HP_ZX1_IOVA_BASE	GB(1UL)
 #define HP_ZX1_IOVA_SIZE	GB(1UL)
 #define HP_ZX1_GART_SIZE	(HP_ZX1_IOVA_SIZE / 2)
@@ -39,6 +35,9 @@
 #define HP_ZX1_PDIR_VALID_BIT	0x8000000000000000UL
 #define HP_ZX1_IOVA_TO_PDIR(va)	((va - hp_private.iova_base) >> hp_private.io_tlb_shift)
 
+#define AGP8X_MODE_BIT		3
+#define AGP8X_MODE		(1 << AGP8X_MODE_BIT)
+
 /* AGP bridge need not be PCI device, but DRM thinks it is. */
 static struct pci_dev fake_bridge_dev;
 
@@ -57,6 +56,7 @@
 static struct _hp_private {
 	volatile u8 *ioc_regs;
 	volatile u8 *lba_regs;
+	int lba_cap_offset;
 	u64 *io_pdir;		// PDIR for entire IOVA
 	u64 *gatt;		// PDIR just for GART (subset of above)
 	u64 gatt_entries;
@@ -109,6 +109,7 @@
 	hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
 
 	if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
+		/* Normal case when no AGP device in system */
 	    	hp->gatt = 0;
 		hp->gatt_entries = 0;
 		printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
@@ -156,12 +157,13 @@
 }
 
 static int __init
-hp_zx1_ioc_init (u64 ioc_hpa, u64 lba_hpa)
+hp_zx1_ioc_init (u64 hpa)
 {
 	struct _hp_private *hp = &hp_private;
 
-	hp->ioc_regs = ioremap(ioc_hpa, 1024);
-	hp->lba_regs = ioremap(lba_hpa, 256);
+	hp->ioc_regs = ioremap(hpa, 1024);
+	if (!hp->ioc_regs)
+		return -ENOMEM;
 
 	/*
 	 * If the IOTLB is currently disabled, we can take it over.
@@ -176,6 +178,51 @@
 }
 
 static int
+hp_zx1_lba_find_capability (volatile u8 *hpa, int cap)
+{
+	u16 status;
+	u8 pos, id;
+	int ttl = 48;
+
+	status = INREG16(hpa, PCI_STATUS);
+	if (!(status & PCI_STATUS_CAP_LIST))
+		return 0;
+	pos = INREG8(hpa, PCI_CAPABILITY_LIST);
+	while (ttl-- && pos >= 0x40) {
+		pos &= ~3;
+		id = INREG8(hpa, pos + PCI_CAP_LIST_ID);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pos = INREG8(hpa, pos + PCI_CAP_LIST_NEXT);
+	}
+	return 0;
+}
+
+static int __init
+hp_zx1_lba_init (u64 hpa)
+{
+	struct _hp_private *hp = &hp_private;
+	int cap;
+
+	hp->lba_regs = ioremap(hpa, 256);
+	if (!hp->lba_regs)
+		return -ENOMEM;
+
+	hp->lba_cap_offset = hp_zx1_lba_find_capability(hp->lba_regs, PCI_CAP_ID_AGP);
+
+	cap = INREG32(hp->lba_regs, hp->lba_cap_offset) & 0xff;
+	if (cap != PCI_CAP_ID_AGP) {
+		printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n",
+		       cap, hp->lba_cap_offset);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int
 hp_zx1_fetch_size(void)
 {
 	int size;
@@ -192,13 +239,8 @@
 	struct _hp_private *hp = &hp_private;
 
 	agp_bridge->gart_bus_addr = hp->gart_base;
-#if 0
-	/* ouch!! can't do that with a non-PCI AGP bridge... */
-	agp_bridge->capndx = pci_find_capability(agp_bridge->dev, PCI_CAP_ID_AGP);
-#else
-	agp_bridge->capndx = 0;
-#endif
-	agp_bridge->mode = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS);
+	agp_bridge->capndx = hp->lba_cap_offset;
+	agp_bridge->mode = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS);
 
 	if (hp->io_pdir_owner) {
 		OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_phys(hp->io_pdir));
@@ -217,9 +259,13 @@
 {
 	struct _hp_private *hp = &hp_private;
 
-	if (hp->io_pdir_owner)
-		OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0);
-	iounmap((void *) hp->ioc_regs);
+	if (hp->ioc_regs) {
+		if (hp->io_pdir_owner)
+			OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0);
+		iounmap((void *) hp->ioc_regs);
+	}
+	if (hp->lba_regs)
+		iounmap((void *) hp->lba_regs);
 }
 
 static void
@@ -350,14 +396,14 @@
 	struct _hp_private *hp = &hp_private;
 	u32 command;
 
-	command = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS);
+	command = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS);
 
 	command = agp_collect_device_status(mode, command);
 	command |= 0x00000100;
 
-	OUTREG32(hp->lba_regs, HP_ZX1_AGP_COMMAND, command);
+	OUTREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_COMMAND, command);
 
-	agp_device_command(command, 0);
+	agp_device_command(command, (mode & AGP8X_MODE) != 0);
 }
 
 struct agp_bridge_driver hp_zx1_driver = {
@@ -386,22 +432,32 @@
 hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa)
 {
 	struct agp_bridge_data *bridge;
-	int error;
+	int error = 0;
+
+	error = hp_zx1_ioc_init(ioc_hpa);
+	if (error)
+		goto fail;
 
-	error = hp_zx1_ioc_init(ioc_hpa, lba_hpa);
+	error = hp_zx1_lba_init(lba_hpa);
 	if (error)
-		return error;
+		goto fail;
 
 	bridge = agp_alloc_bridge();
-	if (!bridge)
-		return -ENOMEM;
+	if (!bridge) {
+		error = -ENOMEM;
+		goto fail;
+	}
 	bridge->driver = &hp_zx1_driver;
 
 	fake_bridge_dev.vendor = PCI_VENDOR_ID_HP;
 	fake_bridge_dev.device = PCI_DEVICE_ID_HP_PCIX_LBA;
 	bridge->dev = &fake_bridge_dev;
 
-	return agp_add_bridge(bridge);
+	error = agp_add_bridge(bridge);
+  fail:
+	if (error)
+		hp_zx1_cleanup();
+	return error;
 }
 
 static acpi_status __init
@@ -416,7 +472,7 @@
 
 	status = hp_acpi_csr_space(obj, &lba_hpa, &length);
 	if (ACPI_FAILURE(status))
-		return AE_OK;
+		return AE_OK; /* keep looking for another bridge */
 
 	/* Look for an enclosing IOC scope and find its CSR space */
 	handle = obj;
@@ -452,7 +508,7 @@
 		(char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
 
 	hp_zx1_gart_found = 1;
-	return AE_CTRL_TERMINATE;
+	return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */
 }
 
 static int __init
diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
--- a/drivers/char/hvc_console.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/char/hvc_console.c	Wed Mar 17 19:29:10 2004
@@ -131,31 +131,65 @@
 		     const unsigned char *buf, int count)
 {
 	struct hvc_struct *hp = tty->driver_data;
-	char *p;
-	int todo, written = 0;
+	char *tbuf, *p;
+	int tbsize, rsize, written = 0;
 	unsigned long flags;
 
-	spin_lock_irqsave(&hp->lock, flags);
-	while (count > 0 && (todo = N_OUTBUF - hp->n_outbuf) > 0) {
-		if (todo > count)
-			todo = count;
-		p = hp->outbuf + hp->n_outbuf;
-		if (from_user) {
-			todo -= copy_from_user(p, buf, todo);
-			if (todo == 0) {
+	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;
 			}
-		} else
-			memcpy(p, buf, todo);
-		count -= todo;
-		buf += todo;
-		hp->n_outbuf += todo;
-		written += todo;
-		hvc_push(hp);
+			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;
+
+			if (count < tbsize)
+				tbsize = count;
+		}
+
+		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;
+			hvc_push(hp);
+		}
+		spin_unlock_irqrestore(&hp->lock, flags);
 	}
-	spin_unlock_irqrestore(&hp->lock, flags);
 
 	return written;
 }
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/char/mem.c	Wed Mar 17 19:29:09 2004
@@ -102,10 +102,11 @@
 }
 #endif
 
-static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
+static ssize_t do_write_mem(void *p, unsigned long realp,
 			    const char * buf, size_t count, loff_t *ppos)
 {
 	ssize_t written;
+	unsigned long copied;
 
 	written = 0;
 #if defined(__sparc__) || (defined(__mc68000__) && defined(CONFIG_MMU))
@@ -120,8 +121,14 @@
 		written+=sz;
 	}
 #endif
-	if (copy_from_user(p, buf, count))
+	copied = copy_from_user(p, buf, count);
+	if (copied) {
+		ssize_t ret = written + (count - copied);
+
+		if (ret)
+			return ret;
 		return -EFAULT;
+	}
 	written += count;
 	*ppos += written;
 	return written;
@@ -171,7 +178,7 @@
 
 	if (!valid_phys_addr_range(p, &count))
 		return -EFAULT;
-	return do_write_mem(file, __va(p), p, buf, count, ppos);
+	return do_write_mem(__va(p), p, buf, count, ppos);
 }
 
 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
@@ -275,15 +282,19 @@
 	unsigned long p = *ppos;
 	ssize_t wrote = 0;
 	ssize_t virtr = 0;
+	ssize_t written;
 	char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
 
 	if (p < (unsigned long) high_memory) {
+
 		wrote = count;
 		if (count > (unsigned long) high_memory - p)
 			wrote = (unsigned long) high_memory - p;
 
-		wrote = do_write_mem(file, (void*)p, p, buf, wrote, ppos);
-
+		written = do_write_mem((void*)p, p, buf, wrote, ppos);
+		if (written != wrote)
+			return written;
+		wrote = written;
 		p += wrote;
 		buf += wrote;
 		count -= wrote;
@@ -292,15 +303,21 @@
 	if (count > 0) {
 		kbuf = (char *)__get_free_page(GFP_KERNEL);
 		if (!kbuf)
-			return -ENOMEM;
+			return wrote ? wrote : -ENOMEM;
 		while (count > 0) {
 			int len = count;
 
 			if (len > PAGE_SIZE)
 				len = PAGE_SIZE;
-			if (len && copy_from_user(kbuf, buf, len)) {
-				free_page((unsigned long)kbuf);
-				return -EFAULT;
+			if (len) {
+				written = copy_from_user(kbuf, buf, len);
+				if (written != len) {
+					ssize_t ret;
+
+					free_page((unsigned long)kbuf);
+					ret = wrote + virtr + (len - written);
+					return ret ? ret : -EFAULT;
+				}
 			}
 			len = vwrite(kbuf, (char *)p, len);
 			count -= len;
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/char/raw.c	Wed Mar 17 19:29:09 2004
@@ -17,6 +17,7 @@
 #include <linux/raw.h>
 #include <linux/capability.h>
 #include <linux/uio.h>
+#include <linux/cdev.h>
 
 #include <asm/uaccess.h>
 
@@ -260,11 +261,26 @@
 	.owner	=	THIS_MODULE,
 };
 
+static struct cdev raw_cdev = {
+	.kobj	=	{.name = "raw", },
+	.owner	=	THIS_MODULE,
+};
+
 static int __init raw_init(void)
 {
 	int i;
+	dev_t dev = MKDEV(RAW_MAJOR, 0);
+
+	if (register_chrdev_region(dev, MAX_RAW_MINORS, "raw"))
+		goto error;
+
+	cdev_init(&raw_cdev, &raw_fops);
+	if (cdev_add(&raw_cdev, dev, MAX_RAW_MINORS)) {
+		kobject_put(&raw_cdev.kobj);
+		unregister_chrdev_region(dev, MAX_RAW_MINORS);
+		goto error;
+	}
 
-	register_chrdev(RAW_MAJOR, "raw", &raw_fops);
 	devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
 		      S_IFCHR | S_IRUGO | S_IWUGO,
 		      "raw/rawctl");
@@ -273,6 +289,10 @@
 			      S_IFCHR | S_IRUGO | S_IWUGO,
 			      "raw/raw%d", i);
 	return 0;
+
+error:
+	printk(KERN_ERR "error register raw device\n");
+	return 1;
 }
 
 static void __exit raw_exit(void)
@@ -283,7 +303,8 @@
 		devfs_remove("raw/raw%d", i);
 	devfs_remove("raw/rawctl");
 	devfs_remove("raw");
-	unregister_chrdev(RAW_MAJOR, "raw");
+	cdev_del(&raw_cdev);
+	unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
 }
 
 module_init(raw_init);
diff -Nru a/drivers/char/sn_serial.c b/drivers/char/sn_serial.c
--- a/drivers/char/sn_serial.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/char/sn_serial.c	Wed Mar 17 19:29:10 2004
@@ -977,7 +977,7 @@
 		}
 		sn_func->sal_puts(s, count);
 	}
-	else
+	else {
 		/* Output '\r' before each '\n' */
 		while ((s1 = memchr(s, '\n', count)) != NULL) {
 			sn_sal_write(NULL, 0, s, s1 - s);
@@ -986,6 +986,7 @@
 			s = s1 + 1;
 		}
 		sn_sal_write(NULL, 0, s, count);
+	}
 }
 
 static struct tty_driver *
diff -Nru a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
--- a/drivers/char/watchdog/pcwd_usb.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/char/watchdog/pcwd_usb.c	Wed Mar 17 19:29:09 2004
@@ -589,7 +589,7 @@
 	}
 
 	/* get the active interface descriptor */
-	iface_desc = &interface->altsetting[interface->act_altsetting];
+	iface_desc = interface->cur_altsetting;
 
 	/* check out that we have a HID device */
 	if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig
--- a/drivers/ide/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/ide/Kconfig	Wed Mar 17 19:29:09 2004
@@ -559,6 +559,16 @@
 	  change PIO, DMA and UDMA speeds and to configure the chip to
 	  optimum performance.
 
+config BLK_DEV_ATIIXP
+	tristate "ATI IXP chipset IDE support"
+	depends on X86
+	help
+	  This driver adds explicit support for ATI IXP chipset.
+	  This allows the kernel to change PIO, DMA and UDMA speeds
+	  and to configure the chip to optimum performance.
+
+	  Say Y here if you have an ATI IXP chipset IDE controller.
+
 config BLK_DEV_CMD64X
 	tristate "CMD64{3|6|8|9} chipset support"
 	help
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/ide/ide-cd.c	Wed Mar 17 19:29:09 2004
@@ -554,53 +554,6 @@
 	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
 }
 
-
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte ide_cdrom_dump_status (ide_drive_t *drive, const char *msg, byte stat)
-{
-	unsigned long flags;
-
-	atapi_status_t status;
-	atapi_error_t error;
-
-	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 ");
-	else {
-		if (status.b.drdy)	printk("DriveReady ");
-		if (status.b.df)	printk("DeviceFault ");
-		if (status.b.dsc)	printk("SeekComplete ");
-		if (status.b.drq)	printk("DataRequest ");
-		if (status.b.corr)	printk("CorrectedError ");
-		if (status.b.idx)	printk("Index ");
-		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);
-	return error.all;
-}
-
 /*
  * ide_error() takes action based on the error returned by the drive.
  */
@@ -609,7 +562,7 @@
 	struct request *rq;
 	byte err;
 
-	err = ide_cdrom_dump_status(drive, msg, stat);
+	err = ide_dump_atapi_status(drive, msg, stat);
 	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
 		return ide_stopped;
 	/* retry only "normal" I/O: */
@@ -2930,6 +2883,8 @@
 		devinfo->mask |= CDC_MRW;
 	if (!CDROM_CONFIG_FLAGS(drive)->mrw_w)
 		devinfo->mask |= CDC_MRW_W;
+	if (!CDROM_CONFIG_FLAGS(drive)->ram)
+		devinfo->mask |= CDC_RAM;
 
 	devinfo->disk = drive->disk;
 	return register_cdrom(devinfo);
@@ -2966,7 +2921,7 @@
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
 	struct atapi_capabilities_page cap;
-	int nslots = 1, mrw_write = 0;
+	int nslots = 1, mrw_write = 0, ram_write = 0;
 
 	if (drive->media == ide_optical) {
 		CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
@@ -3002,6 +2957,9 @@
 			CDROM_CONFIG_FLAGS(drive)->ram = 1;
 		}
 	}
+	if (!cdrom_is_random_writable(cdi, &ram_write))
+		if (ram_write)
+			CDROM_CONFIG_FLAGS(drive)->ram = 1;
 
 	if (cap.lock == 0)
 		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
@@ -3412,7 +3370,7 @@
 	.supports_dsc_overlap	= 1,
 	.cleanup		= ide_cdrom_cleanup,
 	.do_request		= ide_do_rw_cdrom,
-	.sense			= ide_cdrom_dump_status,
+	.sense			= ide_dump_atapi_status,
 	.error			= ide_cdrom_error,
 	.abort			= ide_cdrom_abort,
 	.capacity		= ide_cdrom_capacity,
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/ide/ide-dma.c	Wed Mar 17 19:29:09 2004
@@ -883,16 +883,6 @@
 	return 1;
 }
 
-int ide_release_mmio_dma (ide_hwif_t *hwif)
-{
-	if ((hwif->dma_extra) && (hwif->channel == 0))
-		release_mem_region((hwif->dma_base + 16), hwif->dma_extra);
-	release_mem_region(hwif->dma_base, 8);
-	if (hwif->dma_base2)
-		release_mem_region(hwif->dma_base, 8);
-	return 1;
-}
-
 int ide_release_iomio_dma (ide_hwif_t *hwif)
 {
 	if ((hwif->dma_extra) && (hwif->channel == 0))
@@ -914,8 +904,6 @@
 		return 1;
 
 	ide_release_dma_engine(hwif);
-	if (hwif->mmio == 1)
-		return ide_release_mmio_dma(hwif);
 	return ide_release_iomio_dma(hwif);
 }
 
@@ -939,38 +927,6 @@
 	return 1;
 }
 
-int ide_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
-{
-	printk(KERN_INFO "    %s: MMIO-DMA at 0x%08lx-0x%08lx",
-		hwif->name, base, base + ports - 1);
-	if (!request_mem_region(base, ports, hwif->name))
-		goto fail;
-	hwif->dma_base = base;
-	if ((hwif->cds->extra) && (hwif->channel == 0)) {
-		if (!request_region(base+16, hwif->cds->extra, hwif->cds->name))
-			goto release_mem;
-		hwif->dma_extra = hwif->cds->extra;
-	}
-	
-	if(hwif->mate)
-		hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
-	else
-		hwif->dma_master = base;
-	if (hwif->dma_base2) {
-		if (!request_mem_region(hwif->dma_base2, ports, hwif->name))
-			goto release_io;
-	}
-	return 0;
-
-release_mem:
-	release_mem_region(base, ports);
-release_io:
-	release_region(base+16, hwif->cds->extra);
-fail:
-	printk(" -- Error, MMIO ports already in use.\n");
-	return 1;
-}
-
 int ide_mapped_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports)
 {
 	printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);
@@ -1022,8 +978,7 @@
 {
 	if (hwif->mmio == 2)
 		return ide_mapped_mmio_dma(hwif, base,ports);
-	if (hwif->mmio == 1)
-		return ide_mmio_dma(hwif, base, ports);
+	BUG_ON(hwif->mmio == 1);
 	return ide_iomio_dma(hwif, base, ports);
 }
 
diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
--- a/drivers/ide/ide-lib.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/ide/ide-lib.c	Wed Mar 17 19:29:10 2004
@@ -447,3 +447,55 @@
 
 EXPORT_SYMBOL_GPL(ide_set_xfer_rate);
 
+/**
+ *	ide_dump_atapi_status       -       print human readable atapi status
+ *	@drive: drive that status applies to
+ *	@msg: text message to print
+ *	@stat: status byte to decode
+ *
+ *	Error reporting, in human readable form (luxurious, but a memory hog).
+ */
+byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
+{
+	unsigned long flags;
+
+	atapi_status_t status;
+	atapi_error_t error;
+
+	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 ");
+	else {
+		if (status.b.drdy)	printk("DriveReady ");
+		if (status.b.df)	printk("DeviceFault ");
+		if (status.b.dsc)	printk("SeekComplete ");
+		if (status.b.drq)	printk("DataRequest ");
+		if (status.b.corr)	printk("CorrectedError ");
+		if (status.b.idx)	printk("Index ");
+		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);
+	return error.all;
+}
+
+EXPORT_SYMBOL(ide_dump_atapi_status);
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/ide/ide-probe.c	Wed Mar 17 19:29:09 2004
@@ -138,9 +138,6 @@
 	local_irq_enable();
 	ide_fix_driveid(id);
 
-	if (!drive->forced_lun)
-		drive->last_lun = id->last_lun & 0x7;
-
 #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
 	/*
 	 * EATA SCSI controllers do a hardware ATA emulation:
@@ -847,7 +844,6 @@
 int hwif_init (ide_hwif_t *hwif);
 int probe_hwif_init (ide_hwif_t *hwif)
 {
-	hwif->initializing = 1;
 	probe_hwif(hwif);
 	hwif_init(hwif);
 
@@ -863,7 +859,6 @@
 			}
 		}
 	}
-	hwif->initializing = 0;
 	return 0;
 }
 
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/ide/ide.c	Wed Mar 17 19:29:09 2004
@@ -518,11 +518,6 @@
 	addr = hwif->io_ports[IDE_CONTROL_OFFSET];
 	if (addr && !hwif_request_region(hwif, addr, 1))
 		goto control_region_busy;
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
-	addr = hwif->io_ports[IDE_IRQ_OFFSET];
-	if (addr && !hwif_request_region(hwif, addr, 1))
-		goto irq_region_busy;
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
 	hwif->straight8 = 0;
 	addr = hwif->io_ports[IDE_DATA_OFFSET];
 	if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) {
@@ -542,12 +537,6 @@
 	return 0;
 
 data_region_busy:
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
-	addr = hwif->io_ports[IDE_IRQ_OFFSET];
-	if (addr)
-		hwif_release_region(addr, 1);
-irq_region_busy:
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
 	addr = hwif->io_ports[IDE_CONTROL_OFFSET];
 	if (addr)
 		hwif_release_region(addr, 1);
@@ -577,20 +566,13 @@
 		return;
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
 		hwif_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
-	if (hwif->io_ports[IDE_IRQ_OFFSET])
-		hwif_release_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
-
 	if (hwif->straight8) {
 		hwif_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
 		return;
 	}
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		if (hwif->io_ports[i]) {
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+		if (hwif->io_ports[i])
 			hwif_release_region(hwif->io_ports[i], 1);
-		}
-	}
 }
 
 EXPORT_SYMBOL(ide_hwif_release_regions);
@@ -869,7 +851,6 @@
 #ifndef CONFIG_BLK_DEV_IDECS
 	hwif->irq			= old_hwif.irq;
 #endif /* CONFIG_BLK_DEV_IDECS */
-	hwif->initializing		= old_hwif.initializing;
 
 	hwif->dma_base			= old_hwif.dma_base;
 	hwif->dma_master		= old_hwif.dma_master;
@@ -1798,9 +1779,7 @@
 	if (strncmp(s,"hd",2) == 0 && s[2] == '=')	/* hd= is for hd.c   */
 		return 0;				/* driver and not us */
 
-	if (strncmp(s,"ide",3) &&
-	    strncmp(s,"idebus",6) &&
-	    strncmp(s,"hd",2))		/* hdx= & hdxlun= */
+	if (strncmp(s,"ide",3) && strncmp(s,"idebus",6) && strncmp(s,"hd",2))
 		return 0;
 
 	printk(KERN_INFO "ide_setup: %s", s);
@@ -1845,19 +1824,6 @@
 		drive = &hwif->drives[unit];
 		if (strncmp(s + 4, "ide-", 4) == 0) {
 			strlcpy(drive->driver_req, s + 4, sizeof(drive->driver_req));
-			goto done;
-		}
-		/*
-		 * Look for last lun option:  "hdxlun="
-		 */
-		if (s[3] == 'l' && s[4] == 'u' && s[5] == 'n') {
-			if (match_parm(&s[6], NULL, vals, 1) != 1)
-				goto bad_option;
-			if (vals[0] >= 0 && vals[0] <= 7) {
-				drive->last_lun = vals[0];
-				drive->forced_lun = 1;
-			} else
-				printk(" -- BAD LAST LUN! Expected value from 0 to 7");
 			goto done;
 		}
 		switch (match_parm(&s[3], hd_words, vals, 3)) {
diff -Nru a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
--- a/drivers/ide/pci/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/ide/pci/Makefile	Wed Mar 17 19:29:09 2004
@@ -3,6 +3,7 @@
 obj-$(CONFIG_BLK_DEV_AEC62XX)		+= aec62xx.o
 obj-$(CONFIG_BLK_DEV_ALI15X3)		+= alim15x3.o
 obj-$(CONFIG_BLK_DEV_AMD74XX)		+= amd74xx.o
+obj-$(CONFIG_BLK_DEV_ATIIXP)		+= atiixp.o
 obj-$(CONFIG_BLK_DEV_CMD64X)		+= cmd64x.o
 obj-$(CONFIG_BLK_DEV_CS5520)		+= cs5520.o
 obj-$(CONFIG_BLK_DEV_CS5530)		+= cs5530.o
diff -Nru a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ide/pci/atiixp.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,512 @@
+/*
+ *  linux/drivers/ide/pci/atiixp.c	Version 0.01-bart2	Feb. 26, 2004
+ *
+ *  Copyright (C) 2003 ATI Inc. <hyu@ati.com>
+ *  Copyright (C) 2004 Bartlomiej Zolnierkiewicz
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define ATIIXP_IDE_PIO_TIMING		0x40
+#define ATIIXP_IDE_MDMA_TIMING		0x44
+#define ATIIXP_IDE_PIO_CONTROL		0x48
+#define ATIIXP_IDE_PIO_MODE		0x4a
+#define ATIIXP_IDE_UDMA_CONTROL		0x54
+#define ATIIXP_IDE_UDMA_MODE		0x56
+
+typedef struct {
+	u8 command_width;
+	u8 recover_width;
+} atiixp_ide_timing;
+
+static atiixp_ide_timing pio_timing[] = {
+	{ 0x05, 0x0d },
+	{ 0x04, 0x07 },
+	{ 0x03, 0x04 },
+	{ 0x02, 0x02 },
+	{ 0x02, 0x00 },
+};
+
+static atiixp_ide_timing mdma_timing[] = {
+	{ 0x07, 0x07 },
+	{ 0x02, 0x01 },
+	{ 0x02, 0x00 },
+};
+
+static int save_mdma_mode[4];
+
+#define DISPLAY_ATIIXP_TIMINGS
+
+#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS)
+
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static u8 atiixp_proc;
+static struct pci_dev *bmide_dev;
+
+/**
+ *	atiixp_get_info		-	fill in /proc for ATIIXP IDE
+ *	@buffer: buffer to fill
+ *	@addr: address of user start in buffer
+ *	@offset: offset into 'file'
+ *	@count: buffer count
+ *
+ *	Output summary data on the tuning.
+ */
+
+static int atiixp_get_info(char *buffer, char **addr, off_t offset, int count)
+{
+	char *p = buffer;
+	struct pci_dev *dev = bmide_dev;
+	unsigned long bibma = pci_resource_start(dev, 4);
+	u32 mdma_timing = 0;
+	u16 udma_mode = 0, pio_mode = 0;
+	u8 c0, c1, udma_control = 0;
+
+	p += sprintf(p, "\n                          ATI ");
+	p += sprintf(p, "ATIIXP Ultra100 IDE Chipset.\n");
+
+	pci_read_config_byte(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_control);
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &udma_mode);
+	pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode);
+	pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &mdma_timing);
+
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+	c0 = inb(bibma + 0x02);
+	c1 = inb(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, "UDMA enabled:   %s              %s "
+			"            %s               %s\n",
+			(udma_control & 0x01) ? "yes" : "no ",
+			(udma_control & 0x02) ? "yes" : "no ",
+			(udma_control & 0x04) ? "yes" : "no ",
+			(udma_control & 0x08) ? "yes" : "no " );
+	p += sprintf(p, "UDMA mode:      %c                %c "
+			"              %c                 %c\n",
+			(udma_control & 0x01) ?
+			((udma_mode & 0x07) + 48) : 'X',
+			(udma_control & 0x02) ?
+			(((udma_mode >> 4) & 0x07) + 48) : 'X',
+			(udma_control & 0x04) ?
+			(((udma_mode >> 8) & 0x07) + 48) : 'X',
+			(udma_control & 0x08) ?
+			(((udma_mode >> 12) & 0x07) + 48) : 'X');
+	p += sprintf(p, "MDMA mode:      %c                %c "
+			"              %c                 %c\n",
+			(save_mdma_mode[0] && (c0 & 0x20)) ?
+			((save_mdma_mode[0] & 0xf) + 48) : 'X',
+			(save_mdma_mode[1] && (c0 & 0x40)) ?
+			((save_mdma_mode[1] & 0xf) + 48) : 'X',
+			(save_mdma_mode[2] && (c1 & 0x20)) ?
+			((save_mdma_mode[2] & 0xf) + 48) : 'X',
+			(save_mdma_mode[3] && (c1 & 0x40)) ?
+			((save_mdma_mode[3] & 0xf) + 48) : 'X');
+	p += sprintf(p, "PIO mode:       %c                %c "
+			"              %c                 %c\n",
+			(c0 & 0x20) ? 'X' : ((pio_mode & 0x07) + 48),
+			(c0 & 0x40) ? 'X' : (((pio_mode >> 4) & 0x07) + 48),
+			(c1 & 0x20) ? 'X' : (((pio_mode >> 8) & 0x07) + 48),
+			(c1 & 0x40) ? 'X' : (((pio_mode >> 12) & 0x07) + 48));
+
+	return p - buffer;	/* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+/**
+ *	atiixp_ratemask		-	compute rate mask for ATIIXP IDE
+ *	@drive: IDE drive to compute for
+ *
+ *	Returns the available modes for the ATIIXP IDE controller.
+ */
+
+static u8 atiixp_ratemask(ide_drive_t *drive)
+{
+	u8 mode = 3;
+
+	if (!eighty_ninty_three(drive))
+		mode = min(mode, (u8)1);
+	return mode;
+}
+
+/**
+ *	atiixp_dma_2_pio		-	return the PIO mode matching DMA
+ *	@xfer_rate: transfer speed
+ *
+ *	Returns the nearest equivalent PIO timing for the PIO or DMA
+ *	mode requested by the controller.
+ */
+
+static u8 atiixp_dma_2_pio(u8 xfer_rate) {
+	switch(xfer_rate) {
+		case XFER_UDMA_6:
+		case XFER_UDMA_5:
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+		case XFER_MW_DMA_2:
+		case XFER_PIO_4:
+			return 4;
+		case XFER_MW_DMA_1:
+		case XFER_PIO_3:
+			return 3;
+		case XFER_SW_DMA_2:
+		case XFER_PIO_2:
+			return 2;
+		case XFER_MW_DMA_0:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+		case XFER_PIO_SLOW:
+		default:
+			return 0;
+	}
+}
+
+static int atiixp_ide_dma_host_on(ide_drive_t *drive)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	u16 tmp16;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+	if (save_mdma_mode[drive->dn])
+		tmp16 &= ~(1 << drive->dn);
+	else
+		tmp16 |= (1 << drive->dn);
+	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	return __ide_dma_host_on(drive);
+}
+
+static int atiixp_ide_dma_host_off(ide_drive_t *drive)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	u16 tmp16;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+	tmp16 &= ~(1 << drive->dn);
+	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	return __ide_dma_host_off(drive);
+}
+
+/**
+ *	atiixp_tune_drive		-	tune a drive attached to a ATIIXP
+ *	@drive: drive to tune
+ *	@pio: desired PIO mode
+ *
+ *	Set the interface PIO mode.
+ */
+
+static void atiixp_tuneproc(ide_drive_t *drive, u8 pio)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	u32 pio_timing_data;
+	u16 pio_mode_data;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
+	pio_mode_data &= ~(0x07 << (drive->dn * 4));
+	pio_mode_data |= (pio << (drive->dn * 4));
+	pci_write_config_word(dev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
+
+	pci_read_config_dword(dev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+	pio_timing_data &= ~(0xff << timing_shift);
+	pio_timing_data |= (pio_timing[pio].recover_width << timing_shift) |
+		 (pio_timing[pio].command_width << (timing_shift + 4));
+	pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+}
+
+/**
+ *	atiixp_tune_chipset	-	tune a ATIIXP interface
+ *	@drive: IDE drive to tune
+ *	@xferspeed: speed to configure
+ *
+ *	Set a ATIIXP interface channel to the desired speeds. This involves
+ *	requires the right timing data into the ATIIXP configuration space
+ *	then setting the drive parameters appropriately
+ */
+
+static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed)
+{
+	struct pci_dev *dev = drive->hwif->pci_dev;
+	unsigned long flags;
+	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+	u32 tmp32;
+	u16 tmp16;
+	u8 speed, pio;
+
+	speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed);
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	save_mdma_mode[drive->dn] = 0;
+	if (speed >= XFER_UDMA_0) {
+		pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
+		tmp16 &= ~(0x07 << (drive->dn * 4));
+		tmp16 |= ((speed & 0x07) << (drive->dn * 4));
+		pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
+	} else {
+		if ((speed >= XFER_MW_DMA_0) && (speed <= XFER_MW_DMA_2)) {
+			save_mdma_mode[drive->dn] = speed;
+			pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
+			tmp32 &= ~(0xff << timing_shift);
+			tmp32 |= (mdma_timing[speed & 0x03].recover_width << timing_shift) |
+				(mdma_timing[speed & 0x03].command_width << (timing_shift + 4));
+			pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
+		}
+	}
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	if (speed >= XFER_SW_DMA_0)
+		pio = atiixp_dma_2_pio(speed);
+	else
+		pio = speed - XFER_PIO_0;
+
+	atiixp_tuneproc(drive, pio);
+
+	return ide_config_drive_speed(drive, speed);
+}
+
+/**
+ *	atiixp_config_drive_for_dma	-	configure drive for DMA
+ *	@drive: IDE drive to configure
+ *
+ *	Set up a ATIIXP interface channel for the best available speed.
+ *	We prefer UDMA if it is available and then MWDMA. If DMA is
+ *	not available we switch to PIO and return 0.
+ */
+
+static int atiixp_config_drive_for_dma(ide_drive_t *drive)
+{
+	u8 speed = ide_dma_speed(drive, atiixp_ratemask(drive));
+
+	/* If no DMA speed was available then disable DMA and use PIO. */
+	if (!speed) {
+		u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
+		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
+	}
+
+	(void) atiixp_speedproc(drive, speed);
+	return ide_dma_enable(drive);
+}
+
+/**
+ *	atiixp_dma_check	-	set up an IDE device
+ *	@drive: IDE drive to configure
+ *
+ *	Set up the ATIIXP interface for the best available speed on this
+ *	interface, preferring DMA to PIO.
+ */
+
+static int atiixp_dma_check(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct hd_driveid *id	= drive->id;
+	u8 tspeed, speed;
+
+	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) &&
+				    (!atiixp_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 (!atiixp_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 (!atiixp_config_drive_for_dma(drive))
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+		return hwif->ide_dma_on(drive);
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+no_dma_set:
+		tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
+		speed = atiixp_dma_2_pio(XFER_PIO_0 + tspeed) + XFER_PIO_0;
+		hwif->speedproc(drive, speed);
+		return hwif->ide_dma_off_quietly(drive);
+	}
+	/* IORDY not supported */
+	return 0;
+}
+
+/**
+ *	init_chipset_atiixp	-	set up the ATIIXP chipset
+ *	@dev: PCI device to set up
+ *	@name: Name of the device
+ *
+ *	Initialize the PCI device as required. For the ATIIXP this turns
+ *	out to be nice and simple
+ */
+
+static unsigned int __devinit init_chipset_atiixp(struct pci_dev *dev, const char *name)
+{
+#if defined(DISPLAY_ATIIXP_TIMINGS) && defined(CONFIG_PROC_FS)
+	if (!atiixp_proc) {
+		atiixp_proc = 1;
+		bmide_dev = dev;
+		ide_pci_create_host_proc("atiixp", atiixp_get_info);
+	}
+#endif /* DISPLAY_ATIIXP_TIMINGS && CONFIG_PROC_FS */
+	return 0;
+}
+
+/**
+ *	init_hwif_atiixp		-	fill in the hwif for the ATIIXP
+ *	@hwif: IDE interface
+ *
+ *	Set up the ide_hwif_t for the ATIIXP interface according to the
+ *	capabilities of the hardware.
+ */
+
+static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
+{
+	if (!hwif->irq)
+		hwif->irq = hwif->channel ? 15 : 14;
+
+	hwif->autodma = 0;
+	hwif->tuneproc = &atiixp_tuneproc;
+	hwif->speedproc = &atiixp_speedproc;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+
+	if (!hwif->dma_base)
+		return;
+
+	hwif->atapi_dma = 1;
+	hwif->ultra_mask = 0x3f;
+	hwif->mwdma_mask = 0x06;
+	hwif->swdma_mask = 0x04;
+
+	/* FIXME: proper cable detection needed */
+	hwif->udma_four = 1;
+	hwif->ide_dma_host_on = &atiixp_ide_dma_host_on;
+	hwif->ide_dma_host_off = &atiixp_ide_dma_host_off;
+	hwif->ide_dma_check = &atiixp_dma_check;
+	if (!noautodma)
+		hwif->autodma = 1;
+
+	hwif->drives[1].autodma = hwif->autodma;
+	hwif->drives[0].autodma = hwif->autodma;
+}
+
+static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
+	{	/* 0 */
+		.vendor		= PCI_VENDOR_ID_ATI,
+		.device		= PCI_DEVICE_ID_ATI_IXP_IDE,
+		.name		= "ATIIXP",
+		.init_chipset	= init_chipset_atiixp,
+		.init_hwif	= init_hwif_atiixp,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
+		.bootable	= ON_BOARD,
+	}
+};
+
+/**
+ *	atiixp_init_one	-	called when a ATIIXP is found
+ *	@dev: the atiixp device
+ *	@id: the matching pci id
+ *
+ *	Called when the PCI registration layer (or the IDE initialization)
+ *	finds a device matching our IDE device tables.
+ */
+
+static int __devinit atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	ide_pci_device_t *d = &atiixp_pci_info[id->driver_data];
+
+	if (dev->device != d->device)
+		BUG();
+	ide_setup_pci_device(dev, d);
+	return 0;
+}
+
+static struct pci_device_id atiixp_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ 0, },
+};
+
+static struct pci_driver driver = {
+	.name		= "ATIIXP IDE",
+	.id_table	= atiixp_pci_tbl,
+	.probe		= atiixp_init_one,
+};
+
+static int atiixp_ide_init(void)
+{
+	return ide_pci_register_driver(&driver);
+}
+
+module_init(atiixp_ide_init);
+
+MODULE_AUTHOR("HUI YU");
+MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
--- a/drivers/ide/pci/hpt366.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/ide/pci/hpt366.c	Wed Mar 17 19:29:09 2004
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/ide/pci/hpt366.c		Version 0.34	Sept 17, 2002
  *
- * Copyright (C) 1999-2002		Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 1999-2003		Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
  *
  * Thanks to HighPoint Technologies for their assistance, and hardware.
@@ -641,6 +641,31 @@
 	return __ide_dma_lostirq(drive);
 }
 
+/* returns 1 if DMA IRQ issued, 0 otherwise */
+static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	u16 bfifo		= 0;
+	u8 reginfo		= hwif->channel ? 0x56 : 0x52;
+	u8 dma_stat;
+
+	pci_read_config_word(hwif->pci_dev, reginfo, &bfifo);
+	if (bfifo & 0x1FF) {
+//		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
+		return 0;
+	}
+
+	dma_stat = hwif->INB(hwif->dma_status);
+	/* return 1 if INTR asserted */
+	if ((dma_stat & 4) == 4)
+		return 1;
+
+	if (!drive->waiting_for_dma)
+		printk(KERN_WARNING "%s: (%s) called while not waiting\n",
+				drive->name, __FUNCTION__);
+	return 0;
+}
+
 static int hpt374_ide_dma_end (ide_drive_t *drive)
 {
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
@@ -796,7 +821,7 @@
 	 */
 	pci_read_config_word(dev, 0x78, &freq);
 	freq &= 0x1FF;
-	if (freq < 0x9c) {
+	if (freq < 0xa0) {
 		pll = F_LOW_PCI_33;
 		if (hpt_minimum_revision(dev,8))
 			pci_set_drvdata(dev, (void *) thirty_three_base_hpt374);
@@ -872,7 +897,7 @@
 						       pll & ~0x100);
 				pci_write_config_byte(dev, 0x5b, 0x21);
 				if (hpt_minimum_revision(dev,8))
-					return -EOPNOTSUPP;
+					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))
@@ -1069,11 +1094,13 @@
 		hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
 	hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
 
-	if (hpt_minimum_revision(dev,8))
+	if (hpt_minimum_revision(dev,8)) {
+		hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
 		hwif->ide_dma_end = &hpt374_ide_dma_end;
-	else if (hpt_minimum_revision(dev,5))
+	} else if (hpt_minimum_revision(dev,5)) {
+		hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
 		hwif->ide_dma_end = &hpt374_ide_dma_end;
-	else if (hpt_minimum_revision(dev,3)) {
+	} else if (hpt_minimum_revision(dev,3)) {
 		hwif->ide_dma_begin = &hpt370_ide_dma_begin;
 		hwif->ide_dma_end = &hpt370_ide_dma_end;
 		hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
--- a/drivers/ide/pci/pdc202xx_new.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/ide/pci/pdc202xx_new.c	Wed Mar 17 19:29:10 2004
@@ -339,7 +339,6 @@
 	 */
 	if (hwif->present) {
 		u16 hunit = 0;
-		hwif->initializing = 1;
 		for (hunit = 0; hunit < MAX_DRIVES; ++hunit) {
 			ide_drive_t *hdrive = &hwif->drives[hunit];
 			if (hdrive->present) {
@@ -349,11 +348,9 @@
 					hwif->tuneproc(hdrive, 5);
 			}
 		}
-		hwif->initializing = 0;
 	}
 	if (mate->present) {
 		u16 munit = 0;
-		mate->initializing = 1;
 		for (munit = 0; munit < MAX_DRIVES; ++munit) {
 			ide_drive_t *mdrive = &mate->drives[munit];
 			if (mdrive->present) {
@@ -363,7 +360,6 @@
 					mate->tuneproc(mdrive, 5);
 			}
 		}
-		mate->initializing = 0;
 	}
 #else
 	hwif->tuneproc(drive, 5);
diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
--- a/drivers/ide/pci/pdc202xx_old.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/ide/pci/pdc202xx_old.c	Wed Mar 17 19:29:10 2004
@@ -618,7 +618,6 @@
 	 */
 	if (hwif->present) {
 		u16 hunit = 0;
-		hwif->initializing = 1;
 		for (hunit = 0; hunit < MAX_DRIVES; ++hunit) {
 			ide_drive_t *hdrive = &hwif->drives[hunit];
 			if (hdrive->present) {
@@ -628,11 +627,9 @@
 					hwif->tuneproc(hdrive, 5);
 			}
 		}
-		hwif->initializing = 0;
 	}
 	if (mate->present) {
 		u16 munit = 0;
-		mate->initializing = 1;
 		for (munit = 0; munit < MAX_DRIVES; ++munit) {
 			ide_drive_t *mdrive = &mate->drives[munit];
 			if (mdrive->present) {
@@ -642,7 +639,6 @@
 					mate->tuneproc(mdrive, 5);
 			}
 		}
-		mate->initializing = 0;
 	}
 #else
 	hwif->tuneproc(drive, 5);
diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c
--- a/drivers/input/evdev.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/evdev.c	Wed Mar 17 19:29:10 2004
@@ -209,7 +209,7 @@
 	struct evdev *evdev = list->evdev;
 	struct input_dev *dev = evdev->handle.dev;
 	struct input_absinfo abs;
-	int t, u, v;
+	int i, t, u, v;
 
 	if (!evdev->exist) return -ENODEV;
 
@@ -234,6 +234,9 @@
 			u = SET_INPUT_KEYCODE(dev, t, v);
 			clear_bit(u, dev->keybit);
 			set_bit(v, dev->keybit);
+			for (i = 0; i < dev->keycodemax; i++)
+				if (INPUT_KEYCODE(dev,i) == u)
+					set_bit(u, dev->keybit);
 			return 0;
 
 		case EVIOCSFF:
diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
--- a/drivers/input/gameport/ns558.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/gameport/ns558.c	Wed Mar 17 19:29:10 2004
@@ -77,7 +77,7 @@
  * No one should be using this address.
  */
 
-	if (check_region(io, 1))
+	if (!request_region(io, 1, "ns558-isa"))
 		return;
 
 /*
@@ -89,7 +89,8 @@
 	outb(~c & ~3, io);
 	if (~(u = v = inb(io)) & 3) {
 		outb(c, io);
-		return;
+		i = 0;
+		goto out;
 	}
 /*
  * After a trigger, there must be at least some bits changing.
@@ -99,7 +100,8 @@
 
 	if (u == v) {
 		outb(c, io);
-		return;
+		i = 0;
+		goto out;
 	}
 	wait_ms(3);
 /*
@@ -110,7 +112,8 @@
 	for (i = 0; i < 1000; i++)
 		if ((u ^ inb(io)) & 0xf) {
 			outb(c, io);
-			return;
+			i = 0;
+			goto out;
 		}
 /* 
  * And now find the number of mirrors of the port.
@@ -118,7 +121,9 @@
 
 	for (i = 1; i < 5; i++) {
 
-		if (check_region(io & (-1 << i), (1 << i)))	/* Don't disturb anyone */
+		release_region(io & (-1 << (i-1)), (1 << (i-1)));
+
+		if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))	/* Don't disturb anyone */
 			break;
 
 		outb(0xff, io & (-1 << i));
@@ -126,18 +131,25 @@
 			if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++;
 		wait_ms(3);
 
-		if (b > 300)					/* We allow 30% difference */
+		if (b > 300) {					/* We allow 30% difference */
+			release_region(io & (-1 << i), (1 << i));
 			break;
+		}
 	}
 
 	i--;
 
+	if (i != 4) {
+		if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
+			return;
+	}
+
 	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
 		printk(KERN_ERR "ns558: Memory allocation failed.\n");
-		return;
+		goto out;
 	}
-       	memset(port, 0, sizeof(struct ns558));
-	
+	memset(port, 0, sizeof(struct ns558));
+
 	port->type = NS558_ISA;
 	port->size = (1 << i);
 	port->gameport.io = io;
@@ -148,8 +160,6 @@
 	sprintf(port->phys, "isa%04x/gameport0", io & (-1 << i));
 	sprintf(port->name, "NS558 ISA");
 
-	request_region(io & (-1 << i), (1 << i), "ns558-isa");
-
 	gameport_register_port(&port->gameport);
 
 	printk(KERN_INFO "gameport: NS558 ISA at %#x", port->gameport.io);
@@ -157,6 +167,9 @@
 	printk(" speed %d kHz\n", port->gameport.speed);
 
 	list_add(&port->node, &ns558_list);
+	return;
+out:
+	release_region(io & (-1 << i), (1 << i));
 }
 
 #ifdef CONFIG_PNP
@@ -276,6 +289,7 @@
 #endif
 			case NS558_ISA:
 				release_region(port->gameport.io & ~(port->size - 1), port->size);
+				kfree(port);
 				break;
 		
 			default:
diff -Nru a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
--- a/drivers/input/joystick/amijoy.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/joystick/amijoy.c	Wed Mar 17 19:29:09 2004
@@ -32,6 +32,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
@@ -42,10 +43,15 @@
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Driver for Amiga joysticks");
-MODULE_PARM(amijoy, "1-2i");
 MODULE_LICENSE("GPL");
 
 static int amijoy[2] = { 0, 1 };
+static int amijoy_nargs;  
+module_param_array_named(map, amijoy, uint, amijoy_nargs, 0);
+MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
+
+__obsolete_setup("amijoy=");
+
 static int amijoy_used[2] = { 0, 0 };
 static struct input_dev amijoy_dev[2];
 static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
@@ -100,17 +106,6 @@
 	if (!--(*used))
 		free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
 }
-
-static int __init amijoy_setup(char *str)
-{
-	int i;
-	int ints[4];
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) amijoy[i] = ints[i+1];
-	return 1;
-}
-__setup("amijoy=", amijoy_setup);
 
 static int __init amijoy_init(void)
 {
diff -Nru a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
--- a/drivers/input/joystick/analog.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/joystick/analog.c	Wed Mar 17 19:29:10 2004
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/init.h>
@@ -50,9 +51,12 @@
 #define ANALOG_PORTS		16
 
 static char *js[ANALOG_PORTS];
+static int js_nargs;
 static int analog_options[ANALOG_PORTS];
-MODULE_PARM(js, "1-" __MODULE_STRING(ANALOG_PORTS) "s");
-MODULE_PARM_DESC(js, "Analog joystick options");
+module_param_array_named(map, js, charp, js_nargs, 0);
+MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities");
+
+__obsolete_setup("js=");
 
 /*
  * Times, feature definitions.
@@ -711,7 +715,7 @@
 	int i, j;
 	char *end;
 
-	for (i = 0; i < ANALOG_PORTS && js[i]; i++) {
+	for (i = 0; i < js_nargs; i++) {
 
 		for (j = 0; analog_types[j].name; j++)
 			if (!strcmp(analog_types[j].name, js[i])) {
@@ -741,24 +745,6 @@
 	.connect =	analog_connect,
 	.disconnect =	analog_disconnect,
 };
-
-#ifndef MODULE
-static int __init analog_setup(char *str)
-{
-	char *s = str;
-	int i = 0;
-
-	if (!str || !*str) return 0;
-
-	while ((str = s) && (i < ANALOG_PORTS)) {
-		if ((s = strchr(str,','))) *s++ = 0;
-		js[i++] = str;
-	}
-
-	return 1;
-}
-__setup("js=", analog_setup);
-#endif
 
 int __init analog_init(void)
 {
diff -Nru a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
--- a/drivers/input/joystick/db9.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/joystick/db9.c	Wed Mar 17 19:29:09 2004
@@ -33,6 +33,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/parport.h>
@@ -42,9 +43,24 @@
 MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(db9, "2i");
-MODULE_PARM(db9_2, "2i");
-MODULE_PARM(db9_3, "2i");
+static int db9[] __initdata = { -1, 0 };
+static int db9_nargs __initdata = 0;
+module_param_array_named(dev, db9, int, db9_nargs, 0);
+MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
+
+static int db9_2[] __initdata = { -1, 0 };
+static int db9_nargs_2 __initdata = 0;
+module_param_array_named(dev2, db9_2, int, db9_nargs_2, 0);
+MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
+
+static int db9_3[] __initdata = { -1, 0 };
+static int db9_nargs_3 __initdata = 0;
+module_param_array_named(dev3, db9_3, int, db9_nargs_3, 0);
+MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
+
+__obsolete_setup("db9=");
+__obsolete_setup("db9_2=");
+__obsolete_setup("db9_3=");
 
 #define DB9_MULTI_STICK		0x01
 #define DB9_MULTI2_STICK	0x02
@@ -76,10 +92,6 @@
 #define DB9_GENESIS6_DELAY	14
 #define DB9_REFRESH_TIME	HZ/100
 
-static int db9[] __initdata = { -1, 0 };
-static int db9_2[] __initdata = { -1, 0 };
-static int db9_3[] __initdata = { -1, 0 };
-
 struct db9 {
 	struct input_dev dev[DB9_MAX_DEVICES];
 	struct timer_list timer;
@@ -518,7 +530,7 @@
 	}
 }
 
-static struct db9 __init *db9_probe(int *config)
+static struct db9 __init *db9_probe(int *config, int nargs)
 {
 	struct db9 *db9;
 	struct parport *pp;
@@ -526,6 +538,12 @@
 
 	if (config[0] < 0)
 		return NULL;
+
+	if (nargs < 2) {
+		printk(KERN_ERR "db9.c: Device type must be specified.\n");
+		return NULL;
+	}
+
 	if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
 		printk(KERN_ERR "db9.c: bad config\n");
 		return NULL;
@@ -601,38 +619,11 @@
 	return db9;
 }
 
-#ifndef MODULE
-static int __init db9_setup(char *str)
-{
-	int i, ints[3];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) db9[i] = ints[i + 1];
-	return 1;
-}
-static int __init db9_setup_2(char *str)
-{
-	int i, ints[3];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) db9_2[i] = ints[i + 1];
-	return 1;
-}
-static int __init db9_setup_3(char *str)
-{
-	int i, ints[3];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 2; i++) db9_3[i] = ints[i + 1];
-	return 1;
-}
-__setup("db9=", db9_setup);
-__setup("db9_2=", db9_setup_2);
-__setup("db9_3=", db9_setup_3);
-#endif
-
 int __init db9_init(void)
 {
-	db9_base[0] = db9_probe(db9);
-	db9_base[1] = db9_probe(db9_2);
-	db9_base[2] = db9_probe(db9_3);
+	db9_base[0] = db9_probe(db9, db9_nargs);
+	db9_base[1] = db9_probe(db9_2, db9_nargs_2);
+	db9_base[2] = db9_probe(db9_3, db9_nargs_3);
 
 	if (db9_base[0] || db9_base[1] || db9_base[2])
 		return 0;
diff -Nru a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
--- a/drivers/input/joystick/gamecon.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/joystick/gamecon.c	Wed Mar 17 19:29:10 2004
@@ -35,6 +35,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/parport.h>
 #include <linux/input.h>
@@ -43,10 +44,26 @@
 MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(gc, "2-6i");
-MODULE_PARM(gc_2,"2-6i");
-MODULE_PARM(gc_3,"2-6i");
-MODULE_PARM(gc_psx_delay, "i");
+static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
+static int gc_nargs __initdata = 0;
+module_param_array_named(map, gc, int, gc_nargs, 0);
+MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
+
+static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
+static int gc_nargs_2 __initdata = 0;
+module_param_array_named(map2, gc_2, int, gc_nargs_2, 0);
+MODULE_PARM_DESC(map2, "Describers second set of devices");
+
+static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
+static int gc_nargs_3 __initdata = 0;
+module_param_array_named(map3, gc_3, int, gc_nargs_3, 0);
+MODULE_PARM_DESC(map3, "Describers third set of devices");
+
+__obsolete_setup("gc=");
+__obsolete_setup("gc_2=");
+__obsolete_setup("gc_3=");
+
+/* see also gs_psx_delay parameter in PSX support section */
 
 #define GC_SNES		1
 #define GC_NES		2
@@ -71,10 +88,6 @@
 
 static struct gc *gc_base[3];
 
-static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
-
 static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
 static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
@@ -232,6 +245,11 @@
 #define GC_PSX_LEN(x)	((x) & 0xf)	/* Low nibble is length in words */
 
 static int gc_psx_delay = GC_PSX_DELAY;
+module_param_named(psx_delay, gc_psx_delay, uint, 0);
+MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)");
+
+__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 };
@@ -468,7 +486,7 @@
 	}
 }
 
-static struct gc __init *gc_probe(int *config)
+static struct gc __init *gc_probe(int *config, int nargs)
 {
 	struct gc *gc;
 	struct parport *pp;
@@ -478,6 +496,11 @@
 	if (config[0] < 0)
 		return NULL;
 
+	if (nargs < 2) {
+		printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
+		return NULL;
+	}
+
 	pp = parport_find_number(config[0]);
 
 	if (!pp) {
@@ -507,7 +530,7 @@
 	gc->timer.data = (long) gc;
 	gc->timer.function = gc_timer;
 
-	for (i = 0; i < 5; i++) {
+	for (i = 0; i < nargs - 1; i++) {
 
 		if (!config[i + 1])
 			continue;
@@ -632,44 +655,11 @@
 	return gc;
 }
 
-#ifndef MODULE
-static int __init gc_setup(char *str)
-{
-	int i, ints[7];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 6; i++) gc[i] = ints[i + 1];
-	return 1;
-}
-static int __init gc_setup_2(char *str)
-{
-	int i, ints[7];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 6; i++) gc_2[i] = ints[i + 1];
-	return 1;
-}
-static int __init gc_setup_3(char *str)
-{
-	int i, ints[7];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 6; i++) gc_3[i] = ints[i + 1];
-	return 1;
-}
-static int __init gc_psx_setup(char *str)
-{
-        get_option(&str, &gc_psx_delay);
-        return 1;
-}
-__setup("gc=", gc_setup);
-__setup("gc_2=", gc_setup_2);
-__setup("gc_3=", gc_setup_3);
-__setup("gc_psx_delay=", gc_psx_setup);
-#endif
-
 int __init gc_init(void)
 {
-	gc_base[0] = gc_probe(gc);
-	gc_base[1] = gc_probe(gc_2);
-	gc_base[2] = gc_probe(gc_3);
+	gc_base[0] = gc_probe(gc, gc_nargs);
+	gc_base[1] = gc_probe(gc_2, gc_nargs_2);
+	gc_base[2] = gc_probe(gc_3, gc_nargs_3);
 
 	if (gc_base[0] || gc_base[1] || gc_base[2])
 		return 0;
diff -Nru a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
--- a/drivers/input/joystick/iforce/iforce-usb.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/joystick/iforce/iforce-usb.c	Wed Mar 17 19:29:10 2004
@@ -135,7 +135,7 @@
 	struct usb_endpoint_descriptor *epirq, *epout;
 	struct iforce *iforce;
 
-	interface = &intf->altsetting[intf->act_altsetting];
+	interface = intf->cur_altsetting;
 
 	epirq = &interface->endpoint[0].desc;
 	epout = &interface->endpoint[1].desc;
diff -Nru a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
--- a/drivers/input/joystick/turbografx.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/joystick/turbografx.c	Wed Mar 17 19:29:10 2004
@@ -35,15 +35,31 @@
 #include <linux/parport.h>
 #include <linux/input.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(tgfx, "2-8i");
-MODULE_PARM(tgfx_2, "2-8i");
-MODULE_PARM(tgfx_3, "2-8i");
+static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+static int tgfx_nargs __initdata = 0;
+module_param_array_named(map, tgfx, int, tgfx_nargs, 0);
+MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
+
+static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+static int tgfx_nargs_2 __initdata = 0;
+module_param_array_named(map2, tgfx_2, int, tgfx_nargs_2, 0);
+MODULE_PARM_DESC(map2, "Describes second set of devices");
+
+static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
+static int tgfx_nargs_3 __initdata = 0;
+module_param_array_named(map3, tgfx_3, int, tgfx_nargs_3, 0);
+MODULE_PARM_DESC(map3, "Describes third set of devices");
+
+__obsolete_setup("tgfx=");
+__obsolete_setup("tgfx_2=");
+__obsolete_setup("tgfx_3=");
 
 #define TGFX_REFRESH_TIME	HZ/100	/* 10 ms */
 
@@ -58,10 +74,6 @@
 #define TGFX_TOP		0x01
 #define TGFX_TOP2		0x08
 
-static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
-
 static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
 static char *tgfx_name = "TurboGraFX Multisystem joystick";
 
@@ -133,7 +145,7 @@
  * tgfx_probe() probes for tg gamepads.
  */
 
-static struct tgfx __init *tgfx_probe(int *config)
+static struct tgfx __init *tgfx_probe(int *config, int nargs)
 {
 	struct tgfx *tgfx;
 	struct parport *pp;
@@ -142,6 +154,11 @@
 	if (config[0] < 0)
 		return NULL;
 
+	if (nargs < 2) {
+		printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
+		return NULL;
+	}
+
 	pp = parport_find_number(config[0]);
 
 	if (!pp) {
@@ -171,7 +188,7 @@
 
 	tgfx->sticks = 0;
 
-	for (i = 0; i < 7; i++)
+	for (i = 0; i < nargs - 1; i++)
 		if (config[i+1] > 0 && config[i+1] < 6) {
 
 			tgfx->sticks |= (1 << i);
@@ -212,38 +229,11 @@
 	return tgfx;
 }
 
-#ifndef MODULE
-static int __init tgfx_setup(char *str)
-{
-	int i, ints[9];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 8; i++) tgfx[i] = ints[i + 1];
-	return 1;
-}
-static int __init tgfx_setup_2(char *str)
-{
-	int i, ints[9];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 8; i++) tgfx_2[i] = ints[i + 1];
-	return 1;
-}
-static int __init tgfx_setup_3(char *str)
-{
-	int i, ints[9];
-	get_options(str, ARRAY_SIZE(ints), ints);
-	for (i = 0; i <= ints[0] && i < 8; i++) tgfx_3[i] = ints[i + 1];
-	return 1;
-}
-__setup("tgfx=", tgfx_setup);
-__setup("tgfx_2=", tgfx_setup_2);
-__setup("tgfx_3=", tgfx_setup_3);
-#endif
-
 int __init tgfx_init(void)
 {
-	tgfx_base[0] = tgfx_probe(tgfx);
-	tgfx_base[1] = tgfx_probe(tgfx_2);
-	tgfx_base[2] = tgfx_probe(tgfx_3);
+	tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
+	tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
+	tgfx_base[2] = tgfx_probe(tgfx_3, tgfx_nargs_3);
 
 	if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
 		return 0;
diff -Nru a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
--- a/drivers/input/keyboard/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/keyboard/Kconfig	Wed Mar 17 19:29:10 2004
@@ -17,6 +17,7 @@
 	depends on INPUT && INPUT_KEYBOARD
 	select SERIO
 	select SERIO_I8042 if PC
+	select SERIO_GSCPS2 if GSC
 	help
 	  Say Y here if you want to use a standard AT or PS/2 keyboard. Usually
 	  you'll need this, unless you have a different type keyboard (USB, ADB
@@ -39,6 +40,19 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called sunkbd.
+
+config KEYBOARD_LKKBD
+	tristate "DECstation/VAXstation LK201/LK401 keyboard support"
+	depends on INPUT && INPUT_KEYBOARD
+	select SERIO
+	help
+	  Say Y here if you want to use a LK201 or LK401 style serial
+	  keyboard. This keyboard is also useable on PCs if you attach
+	  it with the inputattach program. The connector pinout is
+	  described within lkkbd.c.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called lkkbd.
 
 config KEYBOARD_XTKBD
 	tristate "XT Keyboard support"
diff -Nru a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
--- a/drivers/input/keyboard/Makefile	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/keyboard/Makefile	Wed Mar 17 19:29:10 2004
@@ -7,6 +7,7 @@
 obj-$(CONFIG_KEYBOARD_ATKBD)		+= atkbd.o
 obj-$(CONFIG_KEYBOARD_MAPLE)		+= maple_keyb.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
+obj-$(CONFIG_KEYBOARD_LKKBD)		+= lkkbd.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
 obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
--- a/drivers/input/keyboard/atkbd.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/keyboard/atkbd.c	Wed Mar 17 19:29:10 2004
@@ -30,21 +30,17 @@
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
-MODULE_PARM(atkbd_set, "1i");
-MODULE_PARM(atkbd_reset, "1i");
-MODULE_PARM(atkbd_softrepeat, "1i");
 MODULE_LICENSE("GPL");
 
 static int atkbd_set = 2;
 module_param_named(set, atkbd_set, int, 0);
-MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3, 4)");
+MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
+
 #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
 static int atkbd_reset;
 #else
 static int atkbd_reset = 1;
 #endif
-static int atkbd_softrepeat;
-
 module_param_named(reset, atkbd_reset, bool, 0);
 MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
 
@@ -52,6 +48,18 @@
 module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
 MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
 
+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");
+
+static int atkbd_extra;
+module_param_named(extra, atkbd_extra, bool, 0);
+MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
+
+__obsolete_setup("atkbd_set=");
+__obsolete_setup("atkbd_reset");
+__obsolete_setup("atkbd_softrepeat=");
+
 /*
  * Scancode to keycode tables. These are just the default setting, and
  * are loadable via an userland utility.
@@ -127,11 +135,11 @@
 #define ATKBD_CMD_EX_SETLEDS	0x20eb
 #define ATKBD_CMD_OK_GETID	0x02e8
 
+
 #define ATKBD_RET_ACK		0xfa
 #define ATKBD_RET_NAK		0xfe
 #define ATKBD_RET_BAT		0xaa
 #define ATKBD_RET_EMUL0		0xe0
-#define ATKBD_RET_EMULX		0x80
 #define ATKBD_RET_EMUL1		0xe1
 #define ATKBD_RET_RELEASE	0xf0
 #define ATKBD_RET_HANGUEL	0xf1
@@ -141,6 +149,22 @@
 #define ATKBD_KEY_UNKNOWN	  0
 #define ATKBD_KEY_NULL		255
 
+#define ATKBD_SCR_1		254
+#define ATKBD_SCR_2		253
+#define ATKBD_SCR_4		252
+#define ATKBD_SCR_8		251
+#define ATKBD_SCR_CLICK		250
+
+#define ATKBD_SPECIAL		250
+
+static unsigned char atkbd_scroll_keys[5][2] = {
+	{ ATKBD_SCR_1,     0x45 },
+	{ ATKBD_SCR_2,     0x29 },
+	{ ATKBD_SCR_4,     0x36 },
+	{ ATKBD_SCR_8,     0x27 },
+	{ ATKBD_SCR_CLICK, 0x60 },
+};
+
 /*
  * The atkbd control structure
  */
@@ -155,6 +179,7 @@
 	unsigned char cmdbuf[4];
 	unsigned char cmdcnt;
 	unsigned char set;
+	unsigned char extra;
 	unsigned char release;
 	int lastkey;
 	volatile signed char ack;
@@ -189,6 +214,7 @@
 {
 	struct atkbd *atkbd = serio->private;
 	unsigned int code = data;
+	int scroll = 0, click = -1;
 	int value;
 
 #ifdef ATKBD_DEBUG
@@ -202,7 +228,7 @@
 		atkbd->resend = 1;
 		goto out;
 	}
-	
+
 	if (!flags && data == ATKBD_RET_ACK)
 		atkbd->resend = 0;
 #endif
@@ -276,7 +302,7 @@
 		case ATKBD_KEY_UNKNOWN:
 			printk(KERN_WARNING "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n",
 				atkbd->release ? "released" : "pressed",
-				atkbd->translated ? "translated" : "raw", 
+				atkbd->translated ? "translated" : "raw",
 				atkbd->set, code, serio->phys);
 			if (atkbd->translated && atkbd->set == 2 && code == 0x7a)
 				printk(KERN_WARNING "atkbd.c: This is an XFree86 bug. It shouldn't access"
@@ -284,6 +310,21 @@
 			else
 				printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n",						code & 0x80 ? "e0" : "", code & 0x7f);
 			break;
+		case ATKBD_SCR_1:
+			scroll = 1 - atkbd->release * 2;
+			break;
+		case ATKBD_SCR_2:
+			scroll = 2 - atkbd->release * 4;
+			break;
+		case ATKBD_SCR_4:
+			scroll = 4 - atkbd->release * 8;
+			break;
+		case ATKBD_SCR_8:
+			scroll = 8 - atkbd->release * 16;
+			break;
+		case ATKBD_SCR_CLICK:
+			click = !atkbd->release;
+			break;
 		default:
 			value = atkbd->release ? 0 :
 				(1 + (!atkbd_softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
@@ -305,6 +346,13 @@
 			atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
 	}
 
+	if (scroll || click != -1) {
+		input_regs(&atkbd->dev, regs);
+		input_report_key(&atkbd->dev, BTN_MIDDLE, click);
+		input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
+		input_sync(&atkbd->dev);
+	}
+
 	atkbd->release = 0;
 out:
 	return IRQ_HANDLED;
@@ -353,7 +401,7 @@
 	if (receive && param)
 		for (i = 0; i < receive; i++)
 			atkbd->cmdbuf[(receive - 1) - i] = param[i];
-	
+
 	if (command & 0xff)
 		if (atkbd_sendbyte(atkbd, command & 0xff))
 			return (atkbd->cmdcnt = 0) - 1;
@@ -373,7 +421,7 @@
 			atkbd->cmdcnt = 0;
 			break;
 		}
-	
+
 		udelay(1);
 	}
 
@@ -420,7 +468,7 @@
 			         | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0);
 		        atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS);
 
-			if (atkbd->set == 4) {
+			if (atkbd->extra) {
 				param[0] = 0;
 				param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
 					 | (test_bit(LED_SLEEP,   dev->led) ? 0x02 : 0)
@@ -466,7 +514,7 @@
  */
 
 	if (atkbd_reset)
-		if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT)) 
+		if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
 			printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", atkbd->serio->phys);
 
 /*
@@ -529,20 +577,21 @@
 		return 3;
 	}
 
-	if (atkbd_set != 2) 
-		if (!atkbd_command(atkbd, param, ATKBD_CMD_OK_GETID)) {
-			atkbd->id = param[0] << 8 | param[1];
+	if (atkbd_extra) {
+		param[0] = 0x71;
+		if (!atkbd_command(atkbd, param, ATKBD_CMD_EX_ENABLE)) {
+			atkbd->extra = 1;
 			return 2;
 		}
-
-	if (atkbd_set == 4) {
-		param[0] = 0x71;
-		if (!atkbd_command(atkbd, param, ATKBD_CMD_EX_ENABLE))
-			return 4;
 	}
 
-	if (atkbd_set != 3) 
+	if (atkbd_set != 3)
+		return 2;
+
+	if (!atkbd_command(atkbd, param, ATKBD_CMD_OK_GETID)) {
+		atkbd->id = param[0] << 8 | param[1];
 		return 2;
+	}
 
 	param[0] = 3;
 	if (atkbd_command(atkbd, param, ATKBD_CMD_SSCANSET))
@@ -637,7 +686,7 @@
 
 	switch (serio->type & SERIO_TYPE) {
 
-		case SERIO_8042_XL: 
+		case SERIO_8042_XL:
 			atkbd->translated = 1;
 		case SERIO_8042:
 			if (serio->write)
@@ -650,7 +699,7 @@
 			kfree(atkbd);
 			return;
 	}
-			
+
 	if (atkbd->write) {
 		atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
 		atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
@@ -687,7 +736,7 @@
 			kfree(atkbd);
 			return;
 		}
-		
+
 		atkbd->set = atkbd_set_3(atkbd);
 		atkbd_enable(atkbd);
 
@@ -696,24 +745,32 @@
 		atkbd->id = 0xab00;
 	}
 
-	if (atkbd->set == 4) {
+	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 Extended keyboard");
+		sprintf(atkbd->name, "AT Set 2 Extra keyboard");
 	} else
 		sprintf(atkbd->name, "AT %s Set %d keyboard",
 			atkbd->translated ? "Translated" : "Raw", atkbd->set);
 
 	sprintf(atkbd->phys, "%s/input0", serio->phys);
 
+	if (atkbd_scroll) {
+		for (i = 0; i < 5; i++)
+			atkbd_set2_keycode[atkbd_scroll_keys[i][1]] = atkbd_scroll_keys[i][0];
+		atkbd->dev.evbit[0] |= BIT(EV_REL);
+		atkbd->dev.relbit[0] = BIT(REL_WHEEL);
+		set_bit(BTN_MIDDLE, atkbd->dev.keybit);
+	}
+
 	if (atkbd->translated) {
 		for (i = 0; i < 128; i++) {
 			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
 			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
 		}
-	} else if (atkbd->set == 2) {
-		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
-	} else {
+	} else if (atkbd->set == 3) {
 		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
+	} else {
+		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
 	}
 
 	atkbd->dev.name = atkbd->name;
@@ -724,7 +781,7 @@
 	atkbd->dev.id.version = atkbd->id;
 
 	for (i = 0; i < 512; i++)
-		if (atkbd->keycode[i] && atkbd->keycode[i] < 255)
+		if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
 			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
 
 	input_register_device(&atkbd->dev);
@@ -741,45 +798,28 @@
 {
 	struct atkbd *atkbd = serio->private;
 	struct serio_dev *dev = serio->dev;
-	int i;
+	unsigned char param[1];
 
-        if (!dev) {
-                printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
-                return -1;
-        }
+	if (!dev) {
+		printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
+		return -1;
+	}
 
 	if (atkbd->write) {
+		param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0)
+		         | (test_bit(LED_NUML,    atkbd->dev.led) ? 2 : 0)
+ 		         | (test_bit(LED_CAPSL,   atkbd->dev.led) ? 4 : 0);
+		
 		if (atkbd_probe(atkbd))
 			return -1;
-
-		atkbd->set = atkbd_set_3(atkbd);
+		if (atkbd->set != atkbd_set_3(atkbd))
+			return -1;
+		
 		atkbd_enable(atkbd);
-	} else {
-		atkbd->set = 2;
-		atkbd->id = 0xab00;
-	}
 
-	/*
-	 * Here we probably should check if the keyboard has the same set that
-         * it had before and bail out if it's different. But this will most likely
-         * cause new keyboard device be created... and for the user it will look
-         * like keyboard is lost
-	 */
-
-	if (atkbd->translated) {
-		for (i = 0; i < 128; i++) {
-			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
-			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
-		}
-	} else if (atkbd->set == 2) {
-		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
-	} else {
-		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
+		if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
+			return -1;
 	}
-
-	for (i = 0; i < 512; i++)
-		if (atkbd->keycode[i] && atkbd->keycode[i] < 255)
-			set_bit(atkbd->keycode[i], atkbd->dev.keybit);
 
 	return 0;
 }
diff -Nru a/drivers/input/keyboard/hpps2atkbd.h b/drivers/input/keyboard/hpps2atkbd.h
--- a/drivers/input/keyboard/hpps2atkbd.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/keyboard/hpps2atkbd.h	Wed Mar 17 19:29:09 2004
@@ -4,14 +4,9 @@
  * Copyright (c) 2004 Helge Deller <deller@gmx.de>
  * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
  * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
+ * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
  *
- * based on linux-2.4's hp_mouse.c & hp_keyb.c
- * 	Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
- *	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>
- *
- * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations
+ * HP PS/2 AT-compatible Keyboard, found in PA/RISC Workstations & Laptops
  *
  * 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
@@ -19,87 +14,100 @@
  */
 
 
-#define KBD_UNKNOWN 0
-
-/* Raw SET 2 scancode table */
+/* undefine if you have a RDI PRECISIONBOOK */
+#define STANDARD_KEYBOARD
 
-#if 0
-	/* conflicting keys between a RDI Precisionbook keyboard and a normal HP keyboard */
-        keytable[0x07] = KEY_F1;        /* KEY_F12      */
-        keytable[0x11] = KEY_LEFTCTRL;  /* KEY_LEFTALT  */
-        keytable[0x14] = KEY_CAPSLOCK;  /* KEY_LEFTCTRL */
-        keytable[0x61] = KEY_LEFT;      /* KEY_102ND    */
+#if defined(STANDARD_KEYBOARD)
+# define CONFLICT(x,y) x
+#else
+# define CONFLICT(x,y) y
 #endif
 
+/* sadly RDI (Tadpole) decided to ship a different keyboard layout
+   than HP for their PS/2 laptop keyboard which leads to conflicting
+   keycodes between a normal HP PS/2 keyboard and a RDI Precisionbook.
+                                HP:		RDI:            */
+#define C_07	CONFLICT(	KEY_F12,	KEY_F1		)
+#define C_11	CONFLICT(	KEY_LEFTALT,	KEY_LEFTCTRL	)
+#define C_14	CONFLICT(	KEY_LEFTCTRL,	KEY_CAPSLOCK	)
+#define C_58	CONFLICT(	KEY_CAPSLOCK,	KEY_RIGHTCTRL	)
+#define C_61	CONFLICT(	KEY_102ND,	KEY_LEFT	)
 
-static unsigned char atkbd_set2_keycode[512] = {
+/* Raw SET 2 scancode table */
 
-	/* 00 */  KBD_UNKNOWN,  KEY_F9,        KBD_UNKNOWN,   KEY_F5,        KEY_F3,        KEY_F1,       KEY_F2,        KEY_F1,
-	/* 08 */  KEY_ESC,      KEY_F10,       KEY_F8,        KEY_F6,        KEY_F4,        KEY_TAB,      KEY_GRAVE,     KEY_F2,
-	/* 10 */  KBD_UNKNOWN,  KEY_LEFTCTRL,  KEY_LEFTSHIFT, KBD_UNKNOWN,   KEY_CAPSLOCK,  KEY_Q,        KEY_1,         KEY_F3,
-	/* 18 */  KBD_UNKNOWN,  KEY_LEFTALT,   KEY_Z,         KEY_S,         KEY_A,         KEY_W,        KEY_2,         KEY_F4,
-	/* 20 */  KBD_UNKNOWN,  KEY_C,         KEY_X,         KEY_D,         KEY_E,         KEY_4,        KEY_3,         KEY_F5,
-	/* 28 */  KBD_UNKNOWN,  KEY_SPACE,     KEY_V,         KEY_F,         KEY_T,         KEY_R,        KEY_5,         KEY_F6,
-	/* 30 */  KBD_UNKNOWN,  KEY_N,         KEY_B,         KEY_H,         KEY_G,         KEY_Y,        KEY_6,         KEY_F7,
-	/* 38 */  KBD_UNKNOWN,  KEY_RIGHTALT,  KEY_M,         KEY_J,         KEY_U,         KEY_7,        KEY_8,         KEY_F8,
-	/* 40 */  KBD_UNKNOWN,  KEY_COMMA,     KEY_K,         KEY_I,         KEY_O,         KEY_0,        KEY_9,         KEY_F9,
-	/* 48 */  KBD_UNKNOWN,  KEY_DOT,       KEY_SLASH,     KEY_L,         KEY_SEMICOLON, KEY_P,        KEY_MINUS,     KEY_F10,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_APOSTROPHE,KBD_UNKNOWN,   KEY_LEFTBRACE, KEY_EQUAL,    KEY_F11,       KEY_SYSRQ,
-	/* 58 */  KEY_CAPSLOCK, KEY_RIGHTSHIFT,KEY_ENTER,     KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12,       KEY_SCROLLLOCK,
-	/* 60 */  KEY_DOWN,     KEY_LEFT,      KEY_PAUSE,     KEY_UP,        KEY_DELETE,    KEY_END,      KEY_BACKSPACE, KEY_INSERT,
-	/* 68 */  KBD_UNKNOWN,  KEY_KP1,       KEY_RIGHT,     KEY_KP4,       KEY_KP7,       KEY_PAGEDOWN, KEY_HOME,      KEY_PAGEUP,
-	/* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
-	/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-
-	/* These are offset for escaped keycodes: */
-
-	/* 00 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_F7,        KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 08 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_LEFTMETA,  KEY_RIGHTMETA, KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 10 */  KBD_UNKNOWN,  KEY_RIGHTALT,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_RIGHTCTRL, KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 18 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 20 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 28 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 30 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 38 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 40 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 48 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPSLASH,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 58 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPENTER,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 60 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 68 */  KBD_UNKNOWN,  KEY_END,       KBD_UNKNOWN,   KEY_LEFT,      KEY_HOME,      KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 70 */  KEY_INSERT,   KEY_DELETE,    KEY_DOWN,      KBD_UNKNOWN,   KEY_RIGHT,     KEY_UP,       KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 78 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_PAGEDOWN,  KBD_UNKNOWN,   KEY_SYSRQ,     KEY_PAGEUP,   KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN
+/* 00 */  KEY_RESERVED, KEY_F9,        KEY_RESERVED,  KEY_F5,        KEY_F3,        KEY_F1,       KEY_F2,        C_07,
+/* 08 */  KEY_ESC,      KEY_F10,       KEY_F8,        KEY_F6,        KEY_F4,        KEY_TAB,      KEY_GRAVE,     KEY_F2,
+/* 10 */  KEY_RESERVED, C_11,          KEY_LEFTSHIFT, KEY_RESERVED,  C_14,          KEY_Q,        KEY_1,         KEY_F3,
+/* 18 */  KEY_RESERVED, KEY_LEFTALT,   KEY_Z,         KEY_S,         KEY_A,         KEY_W,        KEY_2,         KEY_F4,
+/* 20 */  KEY_RESERVED, KEY_C,         KEY_X,         KEY_D,         KEY_E,         KEY_4,        KEY_3,         KEY_F5,
+/* 28 */  KEY_RESERVED, KEY_SPACE,     KEY_V,         KEY_F,         KEY_T,         KEY_R,        KEY_5,         KEY_F6,
+/* 30 */  KEY_RESERVED, KEY_N,         KEY_B,         KEY_H,         KEY_G,         KEY_Y,        KEY_6,         KEY_F7,
+/* 38 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_M,         KEY_J,         KEY_U,         KEY_7,        KEY_8,         KEY_F8,
+/* 40 */  KEY_RESERVED, KEY_COMMA,     KEY_K,         KEY_I,         KEY_O,         KEY_0,        KEY_9,         KEY_F9,
+/* 48 */  KEY_RESERVED, KEY_DOT,       KEY_SLASH,     KEY_L,         KEY_SEMICOLON, KEY_P,        KEY_MINUS,     KEY_F10,
+/* 50 */  KEY_RESERVED, KEY_RESERVED,  KEY_APOSTROPHE,KEY_RESERVED,  KEY_LEFTBRACE, KEY_EQUAL,    KEY_F11,       KEY_SYSRQ,
+/* 58 */  C_58,         KEY_RIGHTSHIFT,KEY_ENTER,     KEY_RIGHTBRACE,KEY_BACKSLASH, KEY_BACKSLASH,KEY_F12,       KEY_SCROLLLOCK,
+/* 60 */  KEY_DOWN,     C_61,          KEY_PAUSE,     KEY_UP,        KEY_DELETE,    KEY_END,      KEY_BACKSPACE, KEY_INSERT,
+/* 68 */  KEY_RESERVED, KEY_KP1,       KEY_RIGHT,     KEY_KP4,       KEY_KP7,       KEY_PAGEDOWN, KEY_HOME,      KEY_PAGEUP,
+/* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
+/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
+/* 80 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 88 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 90 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_SYSRQ,     KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 98 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_CAPSLOCK, KEY_RESERVED,  KEY_LEFTMETA,
+/* a0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RIGHTMETA,
+/* a8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_COMPOSE,
+/* b0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* b8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c8 */  KEY_RESERVED, KEY_RESERVED,  KEY_KPSLASH,   KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d8 */  KEY_RESERVED, KEY_RESERVED,  KEY_KPENTER,   KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e8 */  KEY_RESERVED, KEY_END,       KEY_RESERVED,  KEY_LEFT,      KEY_HOME,      KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* f0 */  KEY_INSERT,   KEY_DELETE,    KEY_DOWN,      KEY_RESERVED,  KEY_RIGHT,     KEY_UP,       KEY_RESERVED,  KEY_PAUSE,
+/* f8 */  KEY_RESERVED, KEY_RESERVED,  KEY_PAGEDOWN,  KEY_RESERVED,  KEY_SYSRQ,     KEY_PAGEUP,   KEY_RESERVED,  KEY_RESERVED,
+
+/* These are offset for escaped keycodes: */
+
+/* 00 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_F7,        KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 08 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_LEFTMETA,  KEY_RIGHTMETA, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 10 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_RESERVED,  KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 18 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 20 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 28 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 30 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 38 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 40 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 48 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 50 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 58 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 60 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 68 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 70 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 78 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 80 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 88 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 90 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 98 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* a0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* a8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* b0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* b8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* c8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* d8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* e8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* f0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* f8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED
+
+#undef STANDARD_KEYBOARD
+#undef CONFLICT
+#undef C_07
+#undef C_11
+#undef C_14
+#undef C_58
+#undef C_61
 
-};
diff -Nru a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/keyboard/lkkbd.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,625 @@
+/*
+ *  Copyright (C) 2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
+ */
+
+/*
+ * LK keyboard driver for Linux, based on sunkbd.c (C) by Vojtech Pavlik
+ */
+
+/*
+ * DEC LK201 and LK401 keyboard driver for Linux (primary for DECstations
+ * and VAXstations, but can also be used on any standard RS232 with an
+ * adaptor).
+ *
+ * DISCLAUNER: This works for _me_. If you break anything by using the
+ * information given below, I will _not_ be lieable!
+ *
+ * RJ11 pinout:		To DB9:		Or DB25:
+ * 	1 - RxD <---->	Pin 3 (TxD) <->	Pin 2 (TxD)
+ * 	2 - GND <---->	Pin 5 (GND) <->	Pin 7 (GND)
+ * 	4 - TxD <---->	Pin 2 (RxD) <->	Pin 3 (RxD)
+ * 	3 - +12V (from HDD drive connector), DON'T connect to DB9 or DB25!!!
+ *
+ * Pin numbers for DB9 and DB25 are noted on the plug (quite small:). For
+ * RJ11, it's like this:
+ *
+ *      __=__	Hold the plug in front of you, cable downwards,
+ *     /___/|	nose is hidden behind the plug. Now, pin 1 is at
+ *    |1234||	the left side, pin 4 at the right and 2 and 3 are
+ *    |IIII||	in between, of course:)
+ *    |    ||
+ *    |____|/
+ *      ||	So the adaptor consists of three connected cables
+ *      ||	for data transmission (RxD and TxD) and signal ground.
+ *		Additionally, you have to get +12V from somewhere.
+ * Most easily, you'll get that from a floppy or HDD power connector.
+ * It's the yellow cable there (black is ground and red is +5V).
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * email or by paper mail:
+ * Jan-Benedict Glaw, Lilienstraße 16, 33790 Hörste (near Halle/Westf.),
+ * Germany.
+ */
+
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/workqueue.h>
+
+
+MODULE_AUTHOR ("Jan-Benedict Glaw <jblaw@lug-owl.de>");
+MODULE_DESCRIPTION ("LK keyboard driver");
+MODULE_LICENSE ("GPL");
+
+/*
+ * Known parameters:
+ *	bell_volume
+ *	keyclick_volume
+ *	ctrlclick_volume
+ *
+ * Please notice that there's not yet an API to set these at runtime.
+ */
+static int bell_volume = 100; /* % */
+module_param (bell_volume, int, 0);
+MODULE_PARM_DESC (bell_volume, "Bell volume (in %). default is 100%");
+
+static int keyclick_volume = 100; /* % */
+module_param (keyclick_volume, int, 0);
+MODULE_PARM_DESC (keyclick_volume, "Keyclick volume (in %), default is 100%");
+
+static int ctrlclick_volume = 100; /* % */
+module_param (ctrlclick_volume, int, 0);
+MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%");
+
+
+
+#undef LKKBD_DEBUG
+#ifdef LKKBD_DEBUG
+#define DBG(x...) printk (x)
+#else
+#define DBG(x...) do {} while (0)
+#endif
+
+/* LED control */
+#define LK_LED_WAIT		0x81
+#define LK_LED_COMPOSE		0x82
+#define LK_LED_SHIFTLOCK	0x84
+#define LK_LED_SCROLLLOCK	0x88
+#define LK_CMD_LED_ON		0x13
+#define LK_CMD_LED_OFF		0x11
+
+/* Mode control */
+#define LK_MODE_DOWN		0x80
+#define LK_MODE_AUTODOWN	0x82
+#define LK_MODE_UPDOWN		0x86
+#define LK_CMD_SET_MODE(mode,div)	((mode) | ((div) << 3))
+
+/* Misc commands */
+#define LK_CMD_ENABLE_KEYCLICK	0x1b
+#define LK_CMD_DISABLE_KEYCLICK	0x99
+#define LK_CMD_DISABLE_BELL	0xa1
+#define LK_CMD_SOUND_BELL	0xa7
+#define LK_CMD_ENABLE_BELL	0x23
+#define LK_CMD_DISABLE_CTRCLICK	0xb9
+#define LK_CMD_ENABLE_CTRCLICK	0xbb
+#define LK_CMD_SET_DEFAULTS	0xd3
+#define LK_CMD_POWERCYCLE_RESET	0xfd
+#define LK_CMD_ENABLE_LK401	0xe9
+
+/* Misc responses from keyboard */
+#define LK_ALL_KEYS_UP		0xb3
+#define LK_METRONOME		0xb4
+#define LK_OUTPUT_ERROR		0xb5
+#define LK_INPUT_ERROR		0xb6
+#define LK_KBD_LOCKED		0xb7
+#define LK_KBD_TEST_MODE_ACK	0xb8
+#define LK_PREFIX_KEY_DOWN	0xb9
+#define LK_MODE_CHANGE_ACK	0xba
+#define LK_RESPONSE_RESERVED	0xbb
+
+#define LK_NUM_KEYCODES		256
+typedef u_int16_t lk_keycode_t;
+
+
+
+static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = {
+	[0x56] = KEY_F1,
+	[0x57] = KEY_F2,
+	[0x58] = KEY_F3,
+	[0x59] = KEY_F4,
+	[0x5a] = KEY_F5,
+	[0x64] = KEY_F6,
+	[0x65] = KEY_F7,
+	[0x66] = KEY_F8,
+	[0x67] = KEY_F9,
+	[0x68] = KEY_F10,
+	[0x71] = KEY_F11,
+	[0x72] = KEY_F12,
+	[0x73] = KEY_F13,
+	[0x74] = KEY_F14,
+	[0x7c] = KEY_F15,
+	[0x7d] = KEY_F16,
+	[0x80] = KEY_F17,
+	[0x81] = KEY_F18,
+	[0x82] = KEY_F19,
+	[0x83] = KEY_F20,
+	[0x8a] = KEY_FIND,
+	[0x8b] = KEY_INSERT,
+	[0x8c] = KEY_DELETE,
+	[0x8d] = KEY_SELECT,
+	[0x8e] = KEY_PAGEUP,
+	[0x8f] = KEY_PAGEDOWN,
+	[0x92] = KEY_KP0,
+	[0x94] = KEY_KPDOT,
+	[0x95] = KEY_KPENTER,
+	[0x96] = KEY_KP1,
+	[0x97] = KEY_KP2,
+	[0x98] = KEY_KP3,
+	[0x99] = KEY_KP4,
+	[0x9a] = KEY_KP5,
+	[0x9b] = KEY_KP6,
+	[0x9c] = KEY_KPCOMMA,
+	[0x9d] = KEY_KP7,
+	[0x9e] = KEY_KP8,
+	[0x9f] = KEY_KP9,
+	[0xa0] = KEY_KPMINUS,
+	[0xa1] = KEY_PROG1,
+	[0xa2] = KEY_PROG2,
+	[0xa3] = KEY_PROG3,
+	[0xa4] = KEY_PROG4,
+	[0xa7] = KEY_LEFT,
+	[0xa8] = KEY_RIGHT,
+	[0xa9] = KEY_DOWN,
+	[0xaa] = KEY_UP,
+	[0xab] = KEY_RIGHTSHIFT,
+	[0xac] = KEY_LEFTALT,
+	[0xad] = KEY_COMPOSE, /* Right Compose, that is. */
+	[0xae] = KEY_LEFTSHIFT, /* Same as KEY_RIGHTSHIFT on LK201 */
+	[0xaf] = KEY_LEFTCTRL,
+	[0xb0] = KEY_CAPSLOCK,
+	[0xb1] = KEY_COMPOSE, /* Left Compose, that is. */
+	[0xb2] = KEY_RIGHTALT,
+	[0xbc] = KEY_BACKSPACE,
+	[0xbd] = KEY_ENTER,
+	[0xbe] = KEY_TAB,
+	[0xbf] = KEY_ESC,
+	[0xc0] = KEY_1,
+	[0xc1] = KEY_Q,
+	[0xc2] = KEY_A,
+	[0xc3] = KEY_Z,
+	[0xc5] = KEY_2,
+	[0xc6] = KEY_W,
+	[0xc7] = KEY_S,
+	[0xc8] = KEY_X,
+	[0xc9] = KEY_102ND,
+	[0xcb] = KEY_3,
+	[0xcc] = KEY_E,
+	[0xcd] = KEY_D,
+	[0xce] = KEY_C,
+	[0xd0] = KEY_4,
+	[0xd1] = KEY_R,
+	[0xd2] = KEY_F,
+	[0xd3] = KEY_V,
+	[0xd4] = KEY_SPACE,
+	[0xd6] = KEY_5,
+	[0xd7] = KEY_T,
+	[0xd8] = KEY_G,
+	[0xd9] = KEY_B,
+	[0xdb] = KEY_6,
+	[0xdc] = KEY_Y,
+	[0xdd] = KEY_H,
+	[0xde] = KEY_N,
+	[0xe0] = KEY_7,
+	[0xe1] = KEY_U,
+	[0xe2] = KEY_J,
+	[0xe3] = KEY_M,
+	[0xe5] = KEY_8,
+	[0xe6] = KEY_I,
+	[0xe7] = KEY_K,
+	[0xe8] = KEY_COMMA,
+	[0xea] = KEY_9,
+	[0xeb] = KEY_O,
+	[0xec] = KEY_L,
+	[0xed] = KEY_DOT,
+	[0xef] = KEY_0,
+	[0xf0] = KEY_P,
+	[0xf2] = KEY_SEMICOLON,
+	[0xf3] = KEY_SLASH,
+	[0xf5] = KEY_EQUAL,
+	[0xf6] = KEY_RIGHTBRACE,
+	[0xf7] = KEY_BACKSLASH,
+	[0xf9] = KEY_MINUS,
+	[0xfa] = KEY_LEFTBRACE,
+	[0xfb] = KEY_APOSTROPHE,
+};
+
+#define CHECK_LED(LED, BITS) do {		\
+	if (test_bit (LED, lk->dev.led))	\
+		leds_on |= BITS;		\
+	else					\
+		leds_off |= BITS;		\
+	} while (0)
+
+/*
+ * Per-keyboard data
+ */
+struct lkkbd {
+	lk_keycode_t keycode[LK_NUM_KEYCODES];
+	int ignore_bytes;
+	struct input_dev dev;
+	struct serio *serio;
+	struct work_struct tq;
+	char name[64];
+	char phys[32];
+	char type;
+	int bell_volume;
+	int keyclick_volume;
+	int ctrlclick_volume;
+};
+
+/*
+ * Calculate volume parameter byte for a given volume.
+ */
+static unsigned char
+volume_to_hw (int volume_percent)
+{
+	unsigned char ret = 0;
+
+	if (volume_percent < 0)
+		volume_percent = 0;
+	if (volume_percent > 100)
+		volume_percent = 100;
+
+	if (volume_percent >= 0)
+		ret = 7;
+	if (volume_percent >= 13)	/* 12.5 */
+		ret = 6;
+	if (volume_percent >= 25)
+		ret = 5;
+	if (volume_percent >= 38)	/* 37.5 */
+		ret = 4;
+	if (volume_percent >= 50)
+		ret = 3;
+	if (volume_percent >= 63)	/* 62.5 */
+		ret = 2;		/* This is the default volume */
+	if (volume_percent >= 75)
+		ret = 1;
+	if (volume_percent >= 88)	/* 87.5 */
+		ret = 0;
+
+	ret |= 0x80;
+
+	return ret;
+}
+
+/*
+ * lkkbd_interrupt() is called by the low level driver when a character
+ * is received.
+ */
+static irqreturn_t
+lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
+		struct pt_regs *regs)
+{
+	struct lkkbd *lk = serio->private;
+	int i;
+
+	DBG (KERN_INFO "Got byte 0x%02x\n", data);
+
+	if (lk->ignore_bytes > 0) {
+		DBG (KERN_INFO "Ignoring a byte on %s\n",
+				lk->name);
+		lk->ignore_bytes--;
+		return IRQ_HANDLED;
+	}
+
+	switch (data) {
+		case LK_ALL_KEYS_UP:
+			input_regs (&lk->dev, regs);
+			for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++)
+				if (lk->keycode[i] != KEY_RESERVED)
+					input_report_key (&lk->dev, lk->keycode[i], 0);
+			input_sync (&lk->dev);
+			break;
+		case LK_METRONOME:
+			DBG (KERN_INFO "Got LK_METRONOME and don't "
+					"know how to handle...\n");
+			break;
+		case LK_OUTPUT_ERROR:
+			DBG (KERN_INFO "Got LK_OUTPUT_ERROR and don't "
+					"know how to handle...\n");
+			break;
+		case LK_INPUT_ERROR:
+			DBG (KERN_INFO "Got LK_INPUT_ERROR and don't "
+					"know how to handle...\n");
+			break;
+		case LK_KBD_LOCKED:
+			DBG (KERN_INFO "Got LK_KBD_LOCKED and don't "
+					"know how to handle...\n");
+			break;
+		case LK_KBD_TEST_MODE_ACK:
+			DBG (KERN_INFO "Got LK_KBD_TEST_MODE_ACK and don't "
+					"know how to handle...\n");
+			break;
+		case LK_PREFIX_KEY_DOWN:
+			DBG (KERN_INFO "Got LK_PREFIX_KEY_DOWN and don't "
+					"know how to handle...\n");
+			break;
+		case LK_MODE_CHANGE_ACK:
+			DBG (KERN_INFO "Got LK_MODE_CHANGE_ACK and ignored "
+					"it properly...\n");
+			break;
+		case LK_RESPONSE_RESERVED:
+			DBG (KERN_INFO "Got LK_RESPONSE_RESERVED and don't "
+					"know how to handle...\n");
+			break;
+		case 0x01:
+			DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n");
+			lk->ignore_bytes = 3;
+			schedule_work (&lk->tq);
+			break;
+
+		default:
+			if (lk->keycode[data] != KEY_RESERVED) {
+				input_regs (&lk->dev, regs);
+				if (!test_bit (lk->keycode[data], lk->dev.key))
+					input_report_key (&lk->dev, lk->keycode[data], 1);
+				else
+					input_report_key (&lk->dev, lk->keycode[data], 0);
+				input_sync (&lk->dev);
+                        } else
+                                printk (KERN_WARNING "%s: Unknown key with "
+						"scancode %02x on %s.\n",
+						__FILE__, data, lk->name);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * lkkbd_event() handles events from the input module.
+ */
+static int
+lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code,
+		int value)
+{
+	struct lkkbd *lk = dev->private;
+	unsigned char leds_on = 0;
+	unsigned char leds_off = 0;
+
+	switch (type) {
+		case EV_LED:
+			CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK);
+			CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE);
+			CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK);
+			CHECK_LED (LED_SLEEP, LK_LED_WAIT);
+			if (leds_on != 0) {
+				lk->serio->write (lk->serio, LK_CMD_LED_ON);
+				lk->serio->write (lk->serio, leds_on);
+			}
+			if (leds_off != 0) {
+				lk->serio->write (lk->serio, LK_CMD_LED_OFF);
+				lk->serio->write (lk->serio, leds_off);
+			}
+			return 0;
+
+		case EV_SND:
+			switch (code) {
+				case SND_CLICK:
+					if (value == 0) {
+						DBG ("%s: Deactivating key clicks\n", __FUNCTION__);
+						lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
+						lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
+					} else {
+						DBG ("%s: Activating key clicks\n", __FUNCTION__);
+						lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
+						lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
+						lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
+						lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume));
+					}
+					return 0;
+
+				case SND_BELL:
+					if (value != 0)
+						lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
+
+					return 0;
+			}
+			break;
+
+		default:
+			printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n",
+					__FUNCTION__, type, code, value);
+	}
+
+	return -1;
+}
+
+/*
+ * lkkbd_reinit() sets leds and beeps to a state the computer remembers they
+ * were in.
+ */
+static void
+lkkbd_reinit (void *data)
+{
+	struct lkkbd *lk = data;
+	int division;
+	unsigned char leds_on = 0;
+	unsigned char leds_off = 0;
+
+	/* Reset parameters */
+	lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS);
+
+	/* Set LEDs */
+	CHECK_LED (LED_CAPSL, LK_LED_SHIFTLOCK);
+	CHECK_LED (LED_COMPOSE, LK_LED_COMPOSE);
+	CHECK_LED (LED_SCROLLL, LK_LED_SCROLLLOCK);
+	CHECK_LED (LED_SLEEP, LK_LED_WAIT);
+	if (leds_on != 0) {
+		lk->serio->write (lk->serio, LK_CMD_LED_ON);
+		lk->serio->write (lk->serio, leds_on);
+	}
+	if (leds_off != 0) {
+		lk->serio->write (lk->serio, LK_CMD_LED_OFF);
+		lk->serio->write (lk->serio, leds_off);
+	}
+
+	/*
+	 * Try to activate extended LK401 mode. This command will
+	 * only work with a LK401 keyboard and grants access to
+	 * LAlt, RAlt, RCompose and RShift.
+	 */
+	lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401);
+
+	/* Set all keys to UPDOWN mode */
+	for (division = 1; division <= 14; division++)
+		lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN,
+					division));
+
+	/* Enable bell and set volume */
+	lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL);
+	lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume));
+
+	/* Enable/disable keyclick (and possibly set volume) */
+	if (test_bit (SND_CLICK, lk->dev.snd)) {
+		lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK);
+		lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume));
+		lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK);
+		lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume));
+	} else {
+		lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK);
+		lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK);
+	}
+
+	/* Sound the bell if needed */
+	if (test_bit (SND_BELL, lk->dev.snd))
+		lk->serio->write (lk->serio, LK_CMD_SOUND_BELL);
+}
+
+/*
+ * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
+ */
+static void
+lkkbd_connect (struct serio *serio, struct serio_dev *dev)
+{
+	struct lkkbd *lk;
+	int i;
+
+	if ((serio->type & SERIO_TYPE) != SERIO_RS232)
+		return;
+	if (!(serio->type & SERIO_PROTO))
+		return;
+	if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_LKKBD)
+		return;
+
+	if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
+		return;
+	memset (lk, 0, sizeof (struct lkkbd));
+
+	init_input_dev (&lk->dev);
+
+	lk->dev.evbit[0] = BIT (EV_KEY) | BIT (EV_LED) | BIT (EV_SND) | BIT (EV_REP);
+	lk->dev.ledbit[0] = BIT (LED_CAPSL) | BIT (LED_COMPOSE) | BIT (LED_SCROLLL) | BIT (LED_SLEEP);
+	lk->dev.sndbit[0] = BIT (SND_CLICK) | BIT (SND_BELL);
+
+	lk->serio = serio;
+
+	INIT_WORK (&lk->tq, lkkbd_reinit, lk);
+
+	lk->bell_volume = bell_volume;
+	lk->keyclick_volume = keyclick_volume;
+	lk->ctrlclick_volume = ctrlclick_volume;
+
+	lk->dev.keycode = lk->keycode;
+	lk->dev.keycodesize = sizeof (lk_keycode_t);
+	lk->dev.keycodemax = LK_NUM_KEYCODES;
+
+	lk->dev.event = lkkbd_event;
+	lk->dev.private = lk;
+
+	serio->private = lk;
+
+	if (serio_open (serio, dev)) {
+		kfree (lk);
+		return;
+	}
+
+	sprintf (lk->name, "LK keyboard");
+
+	memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES);
+	for (i = 0; i < LK_NUM_KEYCODES; i++)
+		set_bit (lk->keycode[i], lk->dev.keybit);
+
+	sprintf (lk->name, "%s/input0", serio->phys);
+
+	lk->dev.name = lk->name;
+	lk->dev.phys = lk->phys;
+	lk->dev.id.bustype = BUS_RS232;
+	lk->dev.id.vendor = SERIO_LKKBD;
+	lk->dev.id.product = 0;
+	lk->dev.id.version = 0x0100;
+
+	input_register_device (&lk->dev);
+
+	printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
+	lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
+}
+
+/*
+ * lkkbd_disconnect() unregisters and closes behind us.
+ */
+static void
+lkkbd_disconnect (struct serio *serio)
+{
+	struct lkkbd *lk = serio->private;
+
+	input_unregister_device (&lk->dev);
+	serio_close (serio);
+	kfree (lk);
+}
+
+static struct serio_dev lkkbd_dev = {
+	.interrupt = lkkbd_interrupt,
+	.connect = lkkbd_connect,
+	.disconnect = lkkbd_disconnect,
+};
+
+/*
+ * The functions for insering/removing us as a module.
+ */
+int __init
+lkkbd_init (void)
+{
+	serio_register_device (&lkkbd_dev);
+	return 0;
+}
+
+void __exit
+lkkbd_exit (void)
+{
+	serio_unregister_device (&lkkbd_dev);
+}
+
+module_init (lkkbd_init);
+module_exit (lkkbd_exit);
+
diff -Nru a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
--- a/drivers/input/keyboard/sunkbd.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/keyboard/sunkbd.c	Wed Mar 17 19:29:09 2004
@@ -77,6 +77,7 @@
 	struct input_dev dev;
 	struct serio *serio;
 	struct work_struct tq;
+	wait_queue_head_t wait;
 	char name[64];
 	char phys[32];
 	char type;
@@ -96,11 +97,13 @@
 
 	if (sunkbd->reset <= -1) {		/* If cp[i] is 0xff, sunkbd->reset will stay -1. */
 		sunkbd->reset = data;		/* The keyboard sends 0xff 0xff 0xID on powerup */
+		wake_up_interruptible(&sunkbd->wait);
 		goto out;
 	}
 
 	if (sunkbd->layout == -1) {
 		sunkbd->layout = data;
+		wake_up_interruptible(&sunkbd->wait);
 		goto out;
 	}
 
@@ -176,22 +179,19 @@
 
 static int sunkbd_initialize(struct sunkbd *sunkbd)
 {
-	int t;
-
-	t = 1000;
 	sunkbd->reset = -2;
 	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET);
-	while (sunkbd->reset < 0 && --t) mdelay(1);
-	if (!t) return -1;
+	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
+	if (sunkbd->reset <0)
+		return -1;
 
 	sunkbd->type = sunkbd->reset;
 
 	if (sunkbd->type == 4) {	/* Type 4 keyboard */
-		t = 250;
 		sunkbd->layout = -2;
 		sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT);
-		while (sunkbd->layout < 0 && --t) mdelay(1);
-		if (!t) return -1;
+		wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4);
+		if (sunkbd->layout < 0) return -1;
 		if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5;
 	}
 
@@ -206,9 +206,8 @@
 static void sunkbd_reinit(void *data)
 {
 	struct sunkbd *sunkbd = data;
-	int t = 1000;
 
-	while (sunkbd->reset < 0 && --t) mdelay(1);
+	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
 
 	sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED);
 	sunkbd->serio->write(sunkbd->serio, 
@@ -239,6 +238,7 @@
 	memset(sunkbd, 0, sizeof(struct sunkbd));
 
 	init_input_dev(&sunkbd->dev);
+	init_waitqueue_head(&sunkbd->wait);
 
 	sunkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_SND) | BIT(EV_REP);
 	sunkbd->dev.ledbit[0] = BIT(LED_CAPSL) | BIT(LED_COMPOSE) | BIT(LED_SCROLLL) | BIT(LED_NUML);
@@ -275,7 +275,7 @@
 		set_bit(sunkbd->keycode[i], sunkbd->dev.keybit);
 	clear_bit(0, sunkbd->dev.keybit);
 
-	sprintf(sunkbd->name, "%s/input", serio->phys);
+	sprintf(sunkbd->phys, "%s/input0", serio->phys);
 
 	sunkbd->dev.name = sunkbd->name;
 	sunkbd->dev.phys = sunkbd->phys;
diff -Nru a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
--- a/drivers/input/misc/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/misc/Kconfig	Wed Mar 17 19:29:09 2004
@@ -54,12 +54,3 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
-config INPUT_GSC
-	tristate "PA-RISC GSC PS/2 keyboard/mouse support"
-	depends on GSC && INPUT && INPUT_MISC
-	help
-	  Say Y here if you have a PS/2 keyboard and/or mouse attached
-	  to your PA-RISC box.	HP run the keyboard in AT mode rather than
-	  XT mode like everyone else, so we need our own driver.
-	  Furthermore, the GSC PS/2 controller shares IRQ between mouse and
-	  keyboard.
diff -Nru a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
--- a/drivers/input/misc/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/misc/Makefile	Wed Mar 17 19:29:09 2004
@@ -9,4 +9,3 @@
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_98SPKR)		+= 98spkr.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
-obj-$(CONFIG_INPUT_GSC)			+= gsc_ps2.o
diff -Nru a/drivers/input/misc/gsc_ps2.c b/drivers/input/misc/gsc_ps2.c
--- a/drivers/input/misc/gsc_ps2.c	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,712 +0,0 @@
-/*
- * drivers/input/misc/gsc_ps2.c
- *
- * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
- * 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-2000 Philipp Rumpf <prumpf@tux.org>
- *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
- *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
- *
- * HP PS/2 Keyboard, found in PA/RISC Workstations
- * very similar to AT keyboards, but without i8042
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * 
- * STATUS:
- * 11/09: lc: Only basic keyboard is supported, mouse still needs to be done.
- * 11/12: tv: switching iomapping; cleaning code; improving module stuff.
- * 11/13: lc & tv: leds aren't working. auto_repeat/meta are. Generaly good behavior.
- * 11/15: tv: 2AM: leds ARE working !
- * 11/16: tv: 3AM: escaped keycodes emulation *handled*, some keycodes are
- *	  still deliberately ignored (18), what are they used for ?
- * 11/21: lc: mouse is now working
- * 11/29: tv: first try for error handling in init sequence
- *
- * TODO:
- * Error handling in init sequence
- * SysRq handling
- * Pause key handling
- * Intellimouse & other rodents handling (at least send an error when
- * such a mouse is plugged : it will totally fault)
- * Mouse: set scaling / Dino testing
- * Bug chasing...
- *
- */
-
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>       /* interrupt.h wants struct pt_regs defined */
-#include <linux/interrupt.h>
-#include <linux/sched.h>        /* for request_irq/free_irq */        
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/kd.h>
-#include <linux/pci_ids.h>
-
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/parisc-device.h>
-
-/* Debugging stuff */
-#undef KBD_DEBUG
-#ifdef KBD_DEBUG
-	#define DPRINTK(fmt,args...) printk(KERN_DEBUG __FILE__ ":" fmt, ##args)
-#else 
-	#define DPRINTK(x,...)
-#endif
-
-
-/* 
- * Driver constants
- */
-
-/* PS/2 keyboard and mouse constants */
-#define AUX_RECONNECT		0xAA	/* PS/2 Mouse end of test successful */
-#define AUX_REPLY_ACK		0xFA
-#define AUX_ENABLE_DEV		0xF4	/* Enables aux device */
-
-/* Order of the mouse bytes coming to the host */
-#define PACKET_X		1
-#define PACKET_Y		2
-#define PACKET_CTRL		0
-
-#define GSC_MOUSE_OFFSET	0x0100	/* offset from keyboard to mouse port */
-#define GSC_DINO_OFFSET		0x800	/* offset for DINO controller versus LASI one */
-
-#define GSC_ID			0x00	/* ID and reset port offsets */
-#define GSC_RESET		0x00
-#define GSC_RCVDATA		0x04	/* receive and transmit port offsets */
-#define GSC_XMTDATA		0x04
-#define GSC_CONTROL		0x08	/* see: control register bits */
-#define GSC_STATUS		0x0C	/* see: status register bits */
-
-/* Control register bits */
-#define GSC_CTRL_ENBL		0x01	/* enable interface */
-#define GSC_CTRL_LPBXR		0x02	/* loopback operation */
-#define GSC_CTRL_DIAG		0x20	/* directly control clock/data line */
-#define GSC_CTRL_DATDIR		0x40	/* data line direct control */
-#define GSC_CTRL_CLKDIR		0x80	/* clock line direct control */
-
-/* Status register bits */
-#define GSC_STAT_RBNE		0x01	/* Receive Buffer Not Empty */
-#define GSC_STAT_TBNE		0x02	/* Transmit Buffer Not Empty */
-#define GSC_STAT_TERR		0x04	/* Timeout Error */
-#define GSC_STAT_PERR		0x08	/* Parity Error */
-#define GSC_STAT_CMPINTR	0x10	/* Composite Interrupt */
-#define GSC_STAT_DATSHD		0x40	/* Data Line Shadow */
-#define GSC_STAT_CLKSHD		0x80	/* Clock Line Shadow */
-
-/* Keycode map */
-#define KBD_ESCAPE0		0xe0
-#define KBD_ESCAPE1		0xe1
-#define KBD_RELEASE		0xf0
-#define KBD_ACK			0xfa
-#define KBD_RESEND		0xfe
-#define KBD_UNKNOWN		0
-
-#define KBD_TBLSIZE		512
-
-/* Mouse */
-#define MOUSE_LEFTBTN		0x1
-#define MOUSE_MIDBTN		0x4
-#define MOUSE_RIGHTBTN		0x2
-#define MOUSE_ALWAYS1		0x8
-#define MOUSE_XSIGN		0x10
-#define MOUSE_YSIGN		0x20
-#define MOUSE_XOVFLOW		0x40
-#define MOUSE_YOVFLOW		0x80
-
-/* Remnant of pc_keyb.h */
-#define KBD_CMD_SET_LEDS	0xED	/* Sets keyboard leds */
-#define KBD_CMD_SET_RATE	0xF3	/* Sets typematic rate */
-#define KBD_CMD_ENABLE		0xF4	/* Enables scanning */
-#define KBD_CMD_DISABLE		0xF5
-#define KBD_CMD_RESET		0xFF
-
-static unsigned char hpkeyb_keycode[KBD_TBLSIZE] =
-{
-	/* 00 */  KBD_UNKNOWN,  KEY_F9,        KBD_UNKNOWN,   KEY_F5,        KEY_F3,        KEY_F1,       KEY_F2,        KEY_F12,
-	/* 08 */  KBD_UNKNOWN,  KEY_F10,       KEY_F8,        KEY_F6,        KEY_F4,        KEY_TAB,      KEY_GRAVE,     KBD_UNKNOWN,
-	/* 10 */  KBD_UNKNOWN,  KEY_LEFTALT,   KEY_LEFTSHIFT, KBD_UNKNOWN,   KEY_LEFTCTRL,  KEY_Q,        KEY_1,         KBD_UNKNOWN,
-	/* 18 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_Z,         KEY_S,         KEY_A,         KEY_W,        KEY_2,         KBD_UNKNOWN,
-	/* 20 */  KBD_UNKNOWN,  KEY_C,         KEY_X,         KEY_D,         KEY_E,         KEY_4,        KEY_3,         KBD_UNKNOWN,
-	/* 28 */  KBD_UNKNOWN,  KEY_SPACE,     KEY_V,         KEY_F,         KEY_T,         KEY_R,        KEY_5,         KBD_UNKNOWN,
-	/* 30 */  KBD_UNKNOWN,  KEY_N,         KEY_B,         KEY_H,         KEY_G,         KEY_Y,        KEY_6,         KBD_UNKNOWN,
-	/* 38 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_M,         KEY_J,         KEY_U,         KEY_7,        KEY_8,         KBD_UNKNOWN,
-	/* 40 */  KBD_UNKNOWN,  KEY_COMMA,     KEY_K,         KEY_I,         KEY_O,         KEY_0,        KEY_9,         KBD_UNKNOWN,
-	/* 48 */  KBD_UNKNOWN,  KEY_DOT,       KEY_SLASH,     KEY_L,         KEY_SEMICOLON, KEY_P,        KEY_MINUS,     KBD_UNKNOWN,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_APOSTROPHE,KBD_UNKNOWN,   KEY_LEFTBRACE, KEY_EQUAL,    KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 58 */  KEY_CAPSLOCK, KEY_RIGHTSHIFT,KEY_ENTER,     KEY_RIGHTBRACE,KBD_UNKNOWN,   KEY_BACKSLASH,KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 60 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KEY_BACKSPACE, KBD_UNKNOWN,
-	/* 68 */  KBD_UNKNOWN,  KEY_KP1,       KBD_UNKNOWN,   KEY_KP4,       KEY_KP7,       KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
-	/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_F7,        KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_ESCAPE0,  KBD_ESCAPE1,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_RELEASE,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_ACK,       KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_RESEND,    KBD_UNKNOWN,
-/* These are offset for escaped keycodes */
-	/* 00 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 08 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 10 */  KBD_UNKNOWN,  KEY_RIGHTALT,  KBD_UNKNOWN,   KBD_UNKNOWN,   KEY_RIGHTCTRL, KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 18 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 20 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 28 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 30 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 38 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 40 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 48 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPSLASH,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 50 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 58 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_KPENTER,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 60 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 68 */  KBD_UNKNOWN,  KEY_END,       KBD_UNKNOWN,   KEY_LEFT,      KEY_HOME,      KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 70 */  KEY_INSERT,   KEY_DELETE,    KEY_DOWN,      KBD_UNKNOWN,   KEY_RIGHT,     KEY_UP,       KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 78 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KEY_PAGEDOWN,  KBD_UNKNOWN,   KEY_SYSRQ,     KEY_PAGEUP,   KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 80 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 88 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 90 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* 98 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* a8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* b8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* c8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* d8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e0 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* e8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f0 */  KBD_RELEASE,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,
-	/* f8 */  KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,   KBD_UNKNOWN,  KBD_UNKNOWN,   KBD_UNKNOWN
-};
-
-
-/* Keyboard struct */
-static struct {
-	struct input_dev dev;
-	char * addr;
-	unsigned int irq;
-	unsigned int scancode;
-	unsigned int escaped;
-	unsigned int released;
-	unsigned int initialized;
-}
-hpkeyb = {
-	.escaped = 0,
-	.released = 0,
-	.initialized = 0
-};
-
-/* Mouse struct */
-static struct {
-   	struct input_dev dev;
-	char * addr;
-	unsigned long irq;
-	unsigned long initialized;
-	int nbread;
-	unsigned char bytes[3];
-	unsigned long last;
-}
-hpmouse = {
-	.initialized = 0,
-	.nbread = 0
-};
-
-static spinlock_t gscps2_lock = SPIN_LOCK_UNLOCKED;
-
-
-/*
- * Various HW level routines
- */
-
-#define gscps2_readb_input(x)		readb(x+GSC_RCVDATA)
-#define gscps2_readb_control(x)		readb(x+GSC_CONTROL)
-#define gscps2_readb_status(x)		readb(x+GSC_STATUS)
-#define gscps2_writeb_control(x, y)	writeb(x, y+GSC_CONTROL)
-
-static inline void gscps2_writeb_output(u8 val, char * addr)
-{
-	int wait = 250;			/* Keyboard is expected to react within 250ms */
-
-	while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
-		if (!--wait)
-			return;		/* This should not happen */
-		mdelay(1);
-	}
-	writeb(val, addr+GSC_XMTDATA);
-}
-
-static inline unsigned char gscps2_wait_input(char * addr)
-{
-	int wait = 250;			/* Keyboard is expected to react within 250ms */
-
-	while (!(gscps2_readb_status(addr) & GSC_STAT_RBNE)) {
-		if (!--wait)
-			return 0;	/* This should not happen */
-		mdelay(1);
-	}
-	return gscps2_readb_input(addr);
-}
-
-static int gscps2_writeb_safe_output(u8 val)
-{
-	/* This function waits for keyboard's ACK */
-	u8 scanread = KBD_UNKNOWN;
-	int loop = 5;
-	
-	while (hpkeyb_keycode[scanread]!=KBD_ACK && --loop > 0) {	
-		gscps2_writeb_output(val, hpkeyb.addr);
-		mdelay(5);
-		scanread = gscps2_wait_input(hpkeyb.addr);
-	}
-	
-	if (loop <= 0)
-		return -1;
-	
-	return 0;
-}
-
-/* Reset the PS2 port */
-static void __init gscps2_reset(char * addr)
-{
-	/* reset the interface */
-	writeb(0xff, addr+GSC_RESET);
-	writeb(0x0 , addr+GSC_RESET);
-
-	/* enable it */
-	gscps2_writeb_control(gscps2_readb_control(addr) | GSC_CTRL_ENBL, addr);
-}
-
-
-/**
- * gscps2_kbd_docode() - PS2 Keyboard basic handler
- *
- * Receives a keyboard scancode, analyses it and sends it to the input layer.
- */
-
-static void gscps2_kbd_docode(struct pt_regs *regs)
-{
-	int scancode = gscps2_readb_input(hpkeyb.addr);
-	DPRINTK("rel=%d scancode=%d, esc=%d ", hpkeyb.released, scancode, hpkeyb.escaped);
-
-	/* Handle previously escaped scancodes */
-	if (hpkeyb.escaped == KBD_ESCAPE0)
-		scancode |= 0x100;	/* jump to the next 256 chars of the table */
-		
-	switch (hpkeyb_keycode[scancode]) {
-		case KBD_RELEASE:
-			DPRINTK("release\n");
-			hpkeyb.released = 1;
-			break;
-		case KBD_RESEND:
-			DPRINTK("resend request\n");
-			break;
-		case KBD_ACK:
-			DPRINTK("ACK\n");
-			break;
-		case KBD_ESCAPE0:
-		case KBD_ESCAPE1:
-			DPRINTK("escape code %d\n", hpkeyb_keycode[scancode]);
-			hpkeyb.escaped = hpkeyb_keycode[scancode];
-			break;
-		case KBD_UNKNOWN:
-			DPRINTK("received unknown scancode %d, escape %d.\n",
-				scancode, hpkeyb.escaped);	/* This is a DPRINTK atm since we do not handle escaped scancodes cleanly */
-			if (hpkeyb.escaped)
-			hpkeyb.escaped = 0;
-			if (hpkeyb.released)
-				hpkeyb.released = 0;
-			return;
-		default:
-			hpkeyb.scancode = scancode;
-			DPRINTK("sent=%d, rel=%d\n",hpkeyb.scancode, hpkeyb.released);
-			/*input_regs(regs);*/
-			input_report_key(&hpkeyb.dev, hpkeyb_keycode[hpkeyb.scancode], !hpkeyb.released);
-			input_sync(&hpkeyb.dev);
-			if (hpkeyb.escaped)
-				hpkeyb.escaped = 0;
-			if (hpkeyb.released) 
-				hpkeyb.released = 0;
-			break;	
-	}
-}
-
-
-/**
- * gscps2_mouse_docode() - PS2 Mouse basic handler
- *
- * Receives mouse codes, processes them by packets of three, and sends
- * correct events to the input layer.
- */
-
-static void gscps2_mouse_docode(struct pt_regs *regs)
-{
-	int xrel, yrel;
-
-	/* process BAT (end of basic tests) command */
-	if ((hpmouse.nbread == 1) && (hpmouse.bytes[0] == AUX_RECONNECT))
-		hpmouse.nbread--;
-
-	/* stolen from psmouse.c */
-	if (hpmouse.nbread && time_after(jiffies, hpmouse.last + HZ/2)) {
-		printk(KERN_DEBUG "%s:%d : Lost mouse synchronization, throwing %d bytes away.\n", __FILE__, __LINE__,
-				hpmouse.nbread);
-		hpmouse.nbread = 0;
-	}
-
-	hpmouse.last = jiffies;
-	hpmouse.bytes[hpmouse.nbread++] = gscps2_readb_input(hpmouse.addr);
-	
-	/* process packet */
-	if (hpmouse.nbread == 3) {
-		
-		if (!(hpmouse.bytes[PACKET_CTRL] & MOUSE_ALWAYS1))
-			DPRINTK("Mouse: error on packet always1 bit checking\n");
-			/* XXX should exit now, bad data on the line! */
-		
-		if ((hpmouse.bytes[PACKET_CTRL] & (MOUSE_XOVFLOW | MOUSE_YOVFLOW)))
-			DPRINTK("Mouse: position overflow\n");
-		
-		/*input_regs(regs);*/
-
-		input_report_key(&hpmouse.dev, BTN_LEFT, hpmouse.bytes[PACKET_CTRL] & MOUSE_LEFTBTN);
-		input_report_key(&hpmouse.dev, BTN_MIDDLE, hpmouse.bytes[PACKET_CTRL] & MOUSE_MIDBTN);
-		input_report_key(&hpmouse.dev, BTN_RIGHT, hpmouse.bytes[PACKET_CTRL] & MOUSE_RIGHTBTN);
-		
-		xrel = hpmouse.bytes[PACKET_X];
-		yrel = hpmouse.bytes[PACKET_Y];
-		
-		/* Data sent by mouse are 9-bit signed, the sign bit is in the control packet */
-		if (xrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_XSIGN))
-			xrel = xrel - 0x100;
-		if (yrel && (hpmouse.bytes[PACKET_CTRL] & MOUSE_YSIGN))
-			yrel = yrel - 0x100;
-		
-		input_report_rel(&hpmouse.dev, REL_X, xrel);
-		input_report_rel(&hpmouse.dev, REL_Y, -yrel);	/* Y axis is received upside-down */
-		
-		input_sync(&hpmouse.dev);
-		
-		hpmouse.nbread = 0;
-	}
-}
-
-
-/**
- * gscps2_interrupt() - Interruption service routine
- *
- * This processes the list of scancodes queued and sends appropriate
- * key value to the system.
- */
-
-static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *reg)
-{
-	/* process mouse actions */
-	while (gscps2_readb_status(hpmouse.addr) & GSC_STAT_RBNE)
-		gscps2_mouse_docode(reg);
-	
-	/* process keyboard scancode */
-	while (gscps2_readb_status(hpkeyb.addr) & GSC_STAT_RBNE)
-		gscps2_kbd_docode(reg);
-
-	return IRQ_HANDLED;
-}
-
-
-/**
- * gscps2_hpkeyb_event() - Event handler
- * @return: success/error report
- *
- * Currently only updates leds on keyboard
- */
-
-int gscps2_hpkeyb_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
-	DPRINTK("Calling %s, type=%d, code=%d, value=%d\n",
-			__FUNCTION__, type, code, value);
-
-	if (!hpkeyb.initialized)
-		return -1;
-
-	if (type == EV_LED) {
-		u8 leds[2];
-
-		if (gscps2_writeb_safe_output(KBD_CMD_SET_LEDS)) {
-			printk(KERN_ERR "gsckbd_leds: timeout\n");
-			return -1;
-		}
-		DPRINTK("KBD_CMD_SET_LEDS\n");
-
-		*leds = (test_bit(LED_SCROLLL, dev->led) ? LED_SCR : 0)
-			| (test_bit(LED_NUML,    dev->led) ? LED_NUM : 0)
-			| (test_bit(LED_CAPSL,   dev->led) ? LED_CAP : 0);
-		DPRINTK("Sending leds=%x\n", *leds);
-		
-		if (gscps2_writeb_safe_output(*leds)) {
-			printk(KERN_ERR "gsckbd_leds: timeout\n");
-			return -1;
-		}
-		DPRINTK("leds sent\n");
-		
-		if (gscps2_writeb_safe_output(KBD_CMD_ENABLE)) {
-			printk(KERN_ERR "gsckbd_leds: timeout\n");
-			return -1;
-		}
-		DPRINTK("End\n");
-
-		return 0;
-
-	}
-	return -1;
-}
-
-
-/**
- * gscps2_kbd_probe() - Probes keyboard device and init input_dev structure
- * @return: number of device initialized (1, 0 on error)
- */
-
-static int __init gscps2_kbd_probe(void)
-{
-	int i, res = 0;
-	unsigned long flags;
-
-	if (hpkeyb.initialized) {
-		printk(KERN_ERR "GSC PS/2 keyboard driver already registered\n");
-		return 0;
-	}
-	
-	spin_lock_irqsave(&gscps2_lock, flags);
- 
-	if (!gscps2_writeb_safe_output(KBD_CMD_SET_LEDS)	&&
-	    !gscps2_writeb_safe_output(0)			&&
-	    !gscps2_writeb_safe_output(KBD_CMD_ENABLE))
-		res = 1;
- 
-	spin_unlock_irqrestore(&gscps2_lock, flags);
-
-	if (!res)
-		printk(KERN_ERR "Keyboard initialization sequence failled\n");
-	
-	init_input_dev(&hpkeyb.dev);
-	
-	for (i = 0; i < KBD_TBLSIZE; i++)
-		if (hpkeyb_keycode[i] != KBD_UNKNOWN)
-			set_bit(hpkeyb_keycode[i], hpkeyb.dev.keybit);
-		
-	hpkeyb.dev.evbit[0]	= BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-	hpkeyb.dev.ledbit[0]	= BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
-	hpkeyb.dev.keycode	= hpkeyb_keycode;
-	hpkeyb.dev.keycodesize	= sizeof(unsigned char);
-	hpkeyb.dev.keycodemax	= KBD_TBLSIZE;
-	hpkeyb.dev.name		= "GSC Keyboard";
-	hpkeyb.dev.phys		= "hpkbd/input0";
-
-	hpkeyb.dev.event	= gscps2_hpkeyb_event;
-	
-	/* TODO These need some adjustement, are they really useful ? */
-	hpkeyb.dev.id.bustype	= BUS_GSC;
-	hpkeyb.dev.id.vendor	= PCI_VENDOR_ID_HP;
-	hpkeyb.dev.id.product	= 0x0001;
-	hpkeyb.dev.id.version	= 0x0010;
-	hpkeyb.initialized	= 1;
-
-	return 1;
-}
-
-
-/**
- * gscps2_mouse_probe() - Probes mouse device and init input_dev structure
- * @return: number of device initialized (1, 0 on error)
- *
- * Currently no check on initialization is performed
- */
-
-static int __init gscps2_mouse_probe(void)
-{
-	if (hpmouse.initialized) {
-		printk(KERN_ERR "GSC PS/2 Mouse driver already registered\n");
-		return 0;
-	}
-	
-	init_input_dev(&hpmouse.dev);
-	
-	hpmouse.dev.name	= "GSC Mouse";
-	hpmouse.dev.phys	= "hpmouse/input0";
-   	hpmouse.dev.evbit[0] 	= BIT(EV_KEY) | BIT(EV_REL);
-	hpmouse.dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-	hpmouse.dev.relbit[0] 	= BIT(REL_X) | BIT(REL_Y);
-	hpmouse.last 		= 0;
-
-	gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr);
-	/* Try it a second time, this will give status if the device is available */
-	gscps2_writeb_output(AUX_ENABLE_DEV, hpmouse.addr);
-	
-	/* TODO These need some adjustement, are they really useful ? */
-	hpmouse.dev.id.bustype	= BUS_GSC;
-	hpmouse.dev.id.vendor	= 0x0001;
-	hpmouse.dev.id.product	= 0x0001;
-	hpmouse.dev.id.version	= 0x0010;
-	hpmouse.initialized = 1;
-	return 1;	/* XXX: we don't check if initialization failed */
-}
-
-
-/**
- * gscps2_probe() - Probes PS2 devices
- * @return: success/error report
- */
-
-static int __init gscps2_probe(struct parisc_device *dev)
-{
-	u8 id;
-	char *addr, *name;
-	int ret = 0, device_found = 0;
-	unsigned long hpa = dev->hpa;
-
-	if (!dev->irq)
-		goto fail_pitifully;
-	
-	/* Offset for DINO PS/2. Works with LASI even */
-	if (dev->id.sversion == 0x96)
-		hpa += GSC_DINO_OFFSET;
-
-	addr = ioremap(hpa, 256);
-	
-	if (!hpmouse.initialized || !hpkeyb.initialized)
-		gscps2_reset(addr);
-
-	ret = -EINVAL;
-	id = readb(addr+GSC_ID) & 0x0f;
-	switch (id) {
-		case 0:				/* keyboard */
-			hpkeyb.addr = addr;
-			name = "keyboard";
-			device_found = gscps2_kbd_probe();
-			break;
-		case 1:				/* mouse */
-			hpmouse.addr = addr;
-			name = "mouse";
-			device_found = gscps2_mouse_probe();
-			break;
-		default:
-			printk(KERN_WARNING "%s: Unsupported PS/2 port (id=%d) ignored\n",
-		    		__FUNCTION__, id);
-			goto fail_miserably;
-	}
-
-	/* No valid device found */
-	ret = -ENODEV;
-	if (!device_found)
-		goto fail_miserably;
-
-	/* Here we claim only if we have a device attached */
-	/* Allocate the irq and memory region for that device */
-	ret = -EBUSY;
-	if (request_irq(dev->irq, gscps2_interrupt, 0, name, NULL))
-		goto fail_miserably;
-
-	if (!request_mem_region(hpa, GSC_STATUS + 4, name))
-		goto fail_request_mem;
-	
-	/* Finalize input struct and register it */
-	switch (id) {
-		case 0:				/* keyboard */
-			hpkeyb.irq = dev->irq;
-			input_register_device(&hpkeyb.dev);	
-			break;
-		case 1:				/* mouse */
-			hpmouse.irq = dev->irq;
-			input_register_device(&hpmouse.dev);
-			break;
-		default:
-			break;
-	}
-
-	printk(KERN_INFO "input: PS/2 %s port at 0x%08lx (irq %d) found and attached\n",
-			name, hpa, dev->irq);
-
-	return 0;
-	
-fail_request_mem: free_irq(dev->irq, NULL);
-fail_miserably: iounmap(addr);
-fail_pitifully:	return ret;
-}
-
-
-
-static struct parisc_device_id gscps2_device_tbl[] = {
-	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */
-/*	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 },  DINO PS/2 (XXX Not yet tested) */
-	{ 0, }	/* 0 terminated list */
-};
-
-static struct parisc_driver gscps2_driver = {
-	.name		= "GSC PS2",
-	.id_table	= gscps2_device_tbl,
-	.probe		= gscps2_probe,
-};
-
-static int __init gscps2_init(void)
-{
-	if (register_parisc_driver(&gscps2_driver))
-		return -EBUSY;
-	return 0;
-}
-
-static void __exit gscps2_exit(void)
-{
-	/* TODO this is probably not very good and needs to be checked */
-	if (hpkeyb.initialized) {
-		free_irq(hpkeyb.irq, gscps2_interrupt);
-		iounmap(hpkeyb.addr);
-		hpkeyb.initialized = 0;
-		input_unregister_device(&hpkeyb.dev);
-	}
-	if (hpmouse.initialized) {
-		free_irq(hpmouse.irq, gscps2_interrupt);
-		iounmap(hpmouse.addr);
-		hpmouse.initialized = 0;
-		input_unregister_device(&hpmouse.dev);
-	}
-	unregister_parisc_driver(&gscps2_driver);
-}
-
-
-MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>");
-MODULE_DESCRIPTION("GSC PS/2 keyboard/mouse driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
-
-
-module_init(gscps2_init);
-module_exit(gscps2_exit);
diff -Nru a/drivers/input/mouse/98busmouse.c b/drivers/input/mouse/98busmouse.c
--- a/drivers/input/mouse/98busmouse.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/mouse/98busmouse.c	Wed Mar 17 19:29:10 2004
@@ -74,6 +74,8 @@
 module_param_named(irq, pc98bm_irq, uint, 0);
 MODULE_PARM_DESC(irq, "IRQ number (13=default)");
 
+__obsolete_setup("pc98bm_irq=");
+
 static int pc98bm_used = 0;
 
 static irqreturn_t pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
--- a/drivers/input/mouse/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/mouse/Kconfig	Wed Mar 17 19:29:10 2004
@@ -17,6 +17,7 @@
 	depends on INPUT && INPUT_MOUSE
 	select SERIO
 	select SERIO_I8042 if PC
+	select SERIO_GSCPS2 if GSC
 	---help---
 	  Say Y here if you have a PS/2 mouse connected to your system. This
 	  includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
@@ -116,6 +117,19 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called rpcmouse.
+
+config MOUSE_VSXXXAA
+	tristate "DEC VSXXX-AA/GA mouse and tablet"
+	depends on INPUT && INPUT_MOUSE
+	select SERIO
+	help
+	  Say Y (or M) if you want to use a DEC VSXXX-AA (hockey
+	  puck) or a VSXXX-GA (rectangular) mouse. Theses mice are
+	  typically used on DECstations or VAXstations, but can also
+	  be used on any box capable of RS232 (with some adaptor
+	  described in the source file). This driver should, in theory,
+	  also work with the digitizer DEC produced, but it isn't tested
+	  with that (I don't have the hardware yet).
 
 config MOUSE_PC9800
 	tristate "NEC PC-9800 busmouse"
diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
--- a/drivers/input/mouse/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/mouse/Makefile	Wed Mar 17 19:29:09 2004
@@ -13,5 +13,6 @@
 obj-$(CONFIG_MOUSE_PC9800)	+= 98busmouse.o
 obj-$(CONFIG_MOUSE_PS2)		+= psmouse.o
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
+obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
 
 psmouse-objs  := psmouse-base.o logips2pp.o synaptics.o
diff -Nru a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c
--- a/drivers/input/mouse/inport.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/mouse/inport.c	Wed Mar 17 19:29:09 2004
@@ -85,6 +85,8 @@
 module_param_named(irq, inport_irq, uint, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
+__obsolete_setup("inport_irq=");
+
 static int inport_used;
 
 static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
diff -Nru a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c
--- a/drivers/input/mouse/logibm.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/mouse/logibm.c	Wed Mar 17 19:29:09 2004
@@ -75,6 +75,8 @@
 module_param_named(irq, logibm_irq, uint, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
+__obsolete_setup("logibm_irq=");
+
 static int logibm_used = 0;
 
 static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/mouse/psmouse-base.c	Wed Mar 17 19:29:09 2004
@@ -47,6 +47,12 @@
 module_param_named(resetafter, psmouse_resetafter, uint, 0);
 MODULE_PARM_DESC(resetafter, "Reset Synaptics Touchpad after so many bad packets (0 = never).");
 
+__obsolete_setup("psmouse_noext");
+__obsolete_setup("psmouse_resolution=");
+__obsolete_setup("psmouse_smartscroll=");
+__obsolete_setup("psmouse_resetafter=");
+__obsolete_setup("psmouse_rate=");
+
 static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2"};
 
 /*
@@ -163,14 +169,14 @@
 		       psmouse->name, psmouse->phys, psmouse->pktcnt);
 		psmouse->pktcnt = 0;
 	}
-	
+
 	psmouse->last = jiffies;
 	psmouse->packet[psmouse->pktcnt++] = data;
 
 	if (psmouse->packet[0] == PSMOUSE_RET_BAT) {
 		if (psmouse->pktcnt == 1)
 			goto out;
-		
+
 		if (psmouse->pktcnt == 2) {
 			if (psmouse->packet[1] == PSMOUSE_RET_ID) {
 				psmouse->state = PSMOUSE_IGNORE;
@@ -258,7 +264,7 @@
 			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 */
@@ -281,6 +287,24 @@
 	return 0;
 }
 
+
+/*
+ * psmouse_reset() resets the mouse into power-on state.
+ */
+int psmouse_reset(struct psmouse *psmouse)
+{
+	unsigned char param[2];
+
+	if (psmouse_command(psmouse, param, PSMOUSE_CMD_RESET_BAT))
+		return -1;
+
+	if (param[0] != PSMOUSE_RET_BAT && param[1] != PSMOUSE_RET_ID)
+		return -1;
+
+	return 0;
+}
+
+
 /*
  * Genius NetMouse magic init.
  */
@@ -365,6 +389,10 @@
  */
 			psmouse_max_proto = PSMOUSE_IMEX;
 		}
+/*
+ * Make sure that touchpad is in relative mode, gestures (taps) are enabled
+ */
+		synaptics_reset(psmouse);
 	}
 
 	if (psmouse_max_proto > PSMOUSE_IMEX && genius_detect(psmouse)) {
@@ -410,6 +438,7 @@
  * pass through port it could get disabled while probing for protocol
  * extensions.
  */
+		psmouse_reset(psmouse);
 		psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS);
 	}
 
@@ -442,7 +471,7 @@
  */
 
 	if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS))
-		return -1;
+		printk(KERN_WARNING "psmouse.c: Failed to reset mouse on %s\n", psmouse->serio->phys);
 
 /*
  * And here we try to determine if it has any extensions over the
@@ -497,7 +526,7 @@
 static void psmouse_initialize(struct psmouse *psmouse)
 {
 	unsigned char param[2];
-	
+
 /*
  * We set the mouse report rate, resolution and scaling.
  */
@@ -534,8 +563,8 @@
 static void psmouse_cleanup(struct serio *serio)
 {
 	struct psmouse *psmouse = serio->private;
-	unsigned char param[2];
-	psmouse_command(psmouse, param, PSMOUSE_CMD_RESET_BAT);
+
+	psmouse_reset(psmouse);
 }
 
 /*
@@ -546,7 +575,7 @@
 {
 	struct psmouse *psmouse = serio->private;
 
-	psmouse->state = PSMOUSE_IGNORE;
+	psmouse->state = PSMOUSE_CMD_MODE;
 
 	if (psmouse->ptport) {
 		if (psmouse->ptport->deactivate)
@@ -559,6 +588,8 @@
 	if (psmouse->disconnect)
 		psmouse->disconnect(psmouse);
 
+	psmouse->state = PSMOUSE_IGNORE;
+
 	input_unregister_device(&psmouse->dev);
 	serio_close(serio);
 	kfree(psmouse);
@@ -571,7 +602,7 @@
 static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
 {
 	struct psmouse *psmouse;
-	
+
 	if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
 	    (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
 		return;
@@ -586,7 +617,7 @@
 	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_NEW_DEVICE;
+	psmouse->state = PSMOUSE_CMD_MODE;
 	psmouse->serio = serio;
 	psmouse->dev.private = psmouse;
 
@@ -603,7 +634,7 @@
 		serio->private = NULL;
 		return;
 	}
-	
+
 	sprintf(psmouse->devname, "%s %s %s",
 		psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
 	sprintf(psmouse->phys, "%s/input0",
@@ -617,7 +648,7 @@
 	psmouse->dev.id.version = psmouse->model;
 
 	input_register_device(&psmouse->dev);
-	
+
 	printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
 
 	psmouse_initialize(psmouse);
@@ -637,14 +668,16 @@
 {
 	struct psmouse *psmouse = serio->private;
 	struct serio_dev *dev = serio->dev;
-	int old_type = psmouse->type;
+	int old_type;
 
-	if (!dev) {
+	if (!dev || !psmouse) {
 		printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
 
-	psmouse->state = PSMOUSE_NEW_DEVICE;
+	old_type = psmouse->type;
+
+	psmouse->state = PSMOUSE_CMD_MODE;
 	psmouse->type = psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = 0;
 	if (psmouse->reconnect) {
 	       if (psmouse->reconnect(psmouse))
diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
--- a/drivers/input/mouse/psmouse.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/input/mouse/psmouse.h	Wed Mar 17 19:29:10 2004
@@ -5,7 +5,7 @@
 #define PSMOUSE_CMD_SETRES	0x10e8
 #define PSMOUSE_CMD_GETINFO	0x03e9
 #define PSMOUSE_CMD_SETSTREAM	0x00ea
-#define PSMOUSE_CMD_POLL	0x03eb	
+#define PSMOUSE_CMD_POLL	0x03eb
 #define PSMOUSE_CMD_GETID	0x02f2
 #define PSMOUSE_CMD_SETRATE	0x10f3
 #define PSMOUSE_CMD_ENABLE	0x00f4
@@ -18,7 +18,7 @@
 #define PSMOUSE_RET_NAK		0xfe
 
 /* psmouse states */
-#define PSMOUSE_NEW_DEVICE	0
+#define PSMOUSE_CMD_MODE	0
 #define PSMOUSE_ACTIVATED	1
 #define PSMOUSE_IGNORE		2
 
@@ -65,6 +65,7 @@
 #define PSMOUSE_SYNAPTICS 	7
 
 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
+int psmouse_reset(struct psmouse *psmouse);
 
 extern int psmouse_smartscroll;
 extern unsigned int psmouse_rate;
diff -Nru a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
--- a/drivers/input/mouse/synaptics.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/mouse/synaptics.c	Wed Mar 17 19:29:09 2004
@@ -92,17 +92,6 @@
 	return 0;
 }
 
-static int synaptics_reset(struct psmouse *psmouse)
-{
-	unsigned char r[2];
-
-	if (psmouse_command(psmouse, r, PSMOUSE_CMD_RESET_BAT))
-		return -1;
-	if (r[0] == PSMOUSE_RET_BAT && r[1] == PSMOUSE_RET_ID)
-		return 0;
-	return -1;
-}
-
 /*
  * Read the model-id bytes from the touchpad
  * see also SYN_MODEL_* macros
@@ -197,7 +186,7 @@
 {
 	int retries = 0;
 
-	while ((retries++ < 3) && synaptics_reset(psmouse))
+	while ((retries++ < 3) && psmouse_reset(psmouse))
 		printk(KERN_ERR "synaptics reset failed\n");
 
 	if (synaptics_identify(psmouse))
@@ -368,9 +357,15 @@
 	clear_bit(REL_Y, dev->relbit);
 }
 
-static void synaptics_disconnect(struct psmouse *psmouse)
+void synaptics_reset(struct psmouse *psmouse)
 {
+	/* reset touchpad back to relative mode, gestures enabled */
 	synaptics_mode_cmd(psmouse, 0);
+}
+
+static void synaptics_disconnect(struct psmouse *psmouse)
+{
+	synaptics_reset(psmouse);
 	kfree(psmouse->private);
 }
 
@@ -435,6 +430,8 @@
 		goto init_fail;
 	}
 
+	priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
+
 	if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities))
        		synaptics_pt_create(psmouse);
 
@@ -602,19 +599,42 @@
 	input_sync(dev);
 }
 
-static int synaptics_validate_byte(struct psmouse *psmouse)
+static int synaptics_validate_byte(unsigned char packet[], int idx, unsigned char pkt_type)
 {
-	static unsigned char newabs_mask[] = { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
-	static unsigned char newabs_rslt[] = { 0x80, 0x00, 0x00, 0xC0, 0x00 };
-	static unsigned char oldabs_mask[] = { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
-	static unsigned char oldabs_rslt[] = { 0xC0, 0x00, 0x00, 0x80, 0x00 };
-	struct synaptics_data *priv = psmouse->private;
-	int idx = psmouse->pktcnt - 1;
+	static unsigned char newabs_mask[]	= { 0xC8, 0x00, 0x00, 0xC8, 0x00 };
+	static unsigned char newabs_rel_mask[]	= { 0xC0, 0x00, 0x00, 0xC0, 0x00 };
+	static unsigned char newabs_rslt[]	= { 0x80, 0x00, 0x00, 0xC0, 0x00 };
+	static unsigned char oldabs_mask[]	= { 0xC0, 0x60, 0x00, 0xC0, 0x60 };
+	static unsigned char oldabs_rslt[]	= { 0xC0, 0x00, 0x00, 0x80, 0x00 };
+
+	switch (pkt_type) {
+		case SYN_NEWABS:
+		case SYN_NEWABS_RELAXED:
+			return (packet[idx] & newabs_rel_mask[idx]) == newabs_rslt[idx];
 
-	if (SYN_MODEL_NEWABS(priv->model_id))
-		return (psmouse->packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
-	else
-		return (psmouse->packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
+		case SYN_NEWABS_STRICT:
+			return (packet[idx] & newabs_mask[idx]) == newabs_rslt[idx];
+
+		case SYN_OLDABS:
+			return (packet[idx] & oldabs_mask[idx]) == oldabs_rslt[idx];
+
+		default:
+			printk(KERN_ERR "synaptics: unknown packet type %d\n", pkt_type);
+			return 0;
+	}
+}
+
+static unsigned char synaptics_detect_pkt_type(struct psmouse *psmouse)
+{
+	int i;
+
+	for (i = 0; i < 5; i++)
+		if (!synaptics_validate_byte(psmouse->packet, i, SYN_NEWABS_STRICT)) {
+			printk(KERN_INFO "synaptics: using relaxed packet validation\n");
+			return SYN_NEWABS_RELAXED;
+		}
+
+	return SYN_NEWABS_STRICT;
 }
 
 void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
@@ -630,13 +650,17 @@
 			printk(KERN_NOTICE "Synaptics driver resynced.\n");
 		}
 
+		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
 			synaptics_process_packet(psmouse);
 		psmouse->pktcnt = 0;
 
-	} else if (psmouse->pktcnt && !synaptics_validate_byte(psmouse)) {
+	} else if (psmouse->pktcnt &&
+		   !synaptics_validate_byte(psmouse->packet, psmouse->pktcnt - 1, priv->pkt_type)) {
 		printk(KERN_WARNING "Synaptics driver lost sync at byte %d\n", psmouse->pktcnt);
 		psmouse->pktcnt = 0;
 		if (++priv->out_of_sync == psmouse_resetafter) {
diff -Nru a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
--- a/drivers/input/mouse/synaptics.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/mouse/synaptics.h	Wed Mar 17 19:29:09 2004
@@ -12,6 +12,7 @@
 extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
 extern int synaptics_detect(struct psmouse *psmouse);
 extern int synaptics_init(struct psmouse *psmouse);
+extern void synaptics_reset(struct psmouse *psmouse);
 
 /* synaptics queries */
 #define SYN_QUE_IDENTIFY		0x00
@@ -70,6 +71,12 @@
 #define SYN_PS_SET_MODE2		0x14
 #define SYN_PS_CLIENT_CMD		0x28
 
+/* synaptics packet types */
+#define SYN_NEWABS			0
+#define SYN_NEWABS_STRICT		1
+#define SYN_NEWABS_RELAXED		2
+#define SYN_OLDABS			3
+
 /*
  * A structure to describe the state of the touchpad hardware (buttons and pad)
  */
@@ -103,6 +110,7 @@
 	/* Data for normal processing */
 	unsigned int out_of_sync;		/* # of packets out of sync */
 	int old_w;				/* Previous w value */
+	unsigned char pkt_type;			/* packet type - old, new, etc */
 };
 
 #endif /* _SYNAPTICS_H */
diff -Nru a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/mouse/vsxxxaa.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,550 @@
+/*
+ * DEC VSXXX-AA and VSXXX-GA mouse driver.
+ *
+ * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
+ *
+ * The packet format was taken from a patch to GPM which is (C) 2001
+ * by	Karsten Merker <merker@linuxtag.org>
+ * and	Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Building an adaptor to DB9 / DB25 RS232
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * DISCLAIMER: Use this description AT YOUR OWN RISK! I'll not pay for
+ * anything if you break your mouse, your computer or whatever!
+ *
+ * In theory, this mouse is a simple RS232 device. In practice, it has got
+ * a quite uncommon plug and the requirement to additionally get a power
+ * supply at +5V and -12V.
+ *
+ * If you look at the socket/jack (_not_ at the plug), we use this pin
+ * numbering:
+ *    _______
+ *   / 7 6 5 \
+ *  | 4 --- 3 |
+ *   \  2 1  /
+ *    -------
+ * 
+ *	DEC socket	DB9	DB25	Note
+ *	1 (GND)		5	7	-
+ *	2 (RxD)		3	3	-
+ *	3 (TxD)		2	2	-
+ *	4 (-12V)	-	-	Somewhere from the PSU. At ATX, it's
+ *					the blue wire at pin 12 of the ATX
+ *					power connector. Please note that the
+ *					docs say this should be +12V! However,
+ *					I measured -12V...
+ *	5 (+5V)		-	-	PSU (red wire of ATX power connector
+ *					on pin 4, 6, 19 or 20) or HDD power
+ *					connector (also red wire)
+ *	6 (not conn.)	-	-	-
+ *	7 (dev. avail.)	-	-	The mouse shorts this one to pin 1.
+ *					This way, the host computer can detect
+ *					the mouse. To use it with the adaptor,
+ *					simply don't connect this pin.
+ *
+ * So to get a working adaptor, you need to connect the mouse with three
+ * wires to a RS232 port and two additional wires for +5V and -12V to the
+ * PSU.
+ *
+ * Flow specification for the link is 4800, 8o1.
+ */
+
+/*
+ * TODO list:
+ * - Automatically attach to a given serial port (no need for inputattach).
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/config.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
+MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver");
+MODULE_LICENSE ("GPL");
+
+#undef VSXXXAA_DEBUG
+#ifdef VSXXXAA_DEBUG
+#define DBG(x...) printk (x)
+#else
+#define DBG(x...) do {} while (0)
+#endif
+
+#define VSXXXAA_INTRO_MASK	0x80
+#define VSXXXAA_INTRO_HEAD	0x80
+#define IS_HDR_BYTE(x)		(((x) & VSXXXAA_INTRO_MASK)	\
+					== VSXXXAA_INTRO_HEAD)
+
+#define VSXXXAA_PACKET_MASK	0xe0
+#define VSXXXAA_PACKET_REL	0x80
+#define VSXXXAA_PACKET_ABS	0xc0
+#define VSXXXAA_PACKET_POR	0xa0
+#define MATCH_PACKET_TYPE(data, type)	(((data) & VSXXXAA_PACKET_MASK) == type)
+
+
+
+struct vsxxxaa {
+	struct input_dev dev;
+	struct serio *serio;
+#define BUFLEN 15 /* At least 5 is needed for a full tablet packet */
+	unsigned char buf[BUFLEN];
+	unsigned char count;
+	unsigned char version;
+	unsigned char country;
+	unsigned char type;
+	char phys[32];
+};
+
+static void
+vsxxxaa_drop_bytes (struct vsxxxaa *mouse, int num)
+{
+	if (num >= mouse->count)
+		mouse->count = 0;
+	else {
+		memmove (mouse->buf, mouse->buf + num - 1, BUFLEN - num);
+		mouse->count -= num;
+	}
+}
+
+static void
+vsxxxaa_queue_byte (struct vsxxxaa *mouse, unsigned char byte)
+{
+	if (mouse->count == BUFLEN) {
+		printk (KERN_ERR "%s on %s: Dropping a byte of full buffer.\n",
+				mouse->dev.name, mouse->dev.phys);
+		vsxxxaa_drop_bytes (mouse, 1);
+	}
+
+	mouse->buf[mouse->count++] = byte;
+}
+
+static void
+vsxxxaa_report_mouse (struct vsxxxaa *mouse)
+{
+	char *devtype;
+
+	switch (mouse->type) {
+		case 0x02:	devtype = "DEC mouse"; break;
+		case 0x04:	devtype = "DEC tablet"; break;
+		default:	devtype = "unknown DEC device"; break;
+	}
+
+	printk (KERN_INFO "Found %s version 0x%x from country 0x%x "
+			"on port %s\n", devtype, mouse->version,
+			mouse->country, mouse->dev.phys);
+}
+
+/*
+ * Returns number of bytes to be dropped, 0 if packet is okay.
+ */
+static int
+vsxxxaa_check_packet (struct vsxxxaa *mouse, int packet_len)
+{
+	int i;
+
+	/* First byte must be a header byte */
+	if (!IS_HDR_BYTE (mouse->buf[0])) {
+		DBG ("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]);
+		return 1;
+	}
+
+	/* Check all following bytes */
+	if (packet_len > 1) {
+		for (i = 1; i < packet_len; i++) {
+			if (IS_HDR_BYTE (mouse->buf[i])) {
+				printk (KERN_ERR "Need to drop %d bytes "
+						"of a broken packet.\n",
+						i - 1);
+				DBG (KERN_INFO "check: len=%d, b[%d]=0x%02x\n",
+						packet_len, i, mouse->buf[i]);
+				return i - 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static __inline__ int
+vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t len)
+{
+	return (mouse->count >= len) && MATCH_PACKET_TYPE (mouse->buf[0], type);
+}
+
+static void
+vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+{
+	struct input_dev *dev = &mouse->dev;
+	unsigned char *buf = mouse->buf;
+	int left, middle, right;
+	int dx, dy;
+
+	/*
+	 * Check for normal stream packets. This is three bytes,
+	 * with the first byte's 3 MSB set to 100.
+	 *
+	 * [0]:	1	0	0	SignX	SignY	Left	Middle	Right
+	 * [1]: 0	dx	dx	dx	dx	dx	dx	dx
+	 * [2]:	0	dy	dy	dy	dy	dy	dy	dy
+	 */
+
+	/*
+	 * Low 7 bit of byte 1 are abs(dx), bit 7 is
+	 * 0, bit 4 of byte 0 is direction.
+	 */
+	dx = buf[1] & 0x7f;
+	dx *= ((buf[0] >> 4) & 0x01)? -1: 1;
+
+	/*
+	 * Low 7 bit of byte 2 are abs(dy), bit 7 is
+	 * 0, bit 3 of byte 0 is direction.
+	 */
+	dy = buf[2] & 0x7f;
+	dy *= ((buf[0] >> 3) & 0x01)? -1: 1;
+
+	/*
+	 * Get button state. It's the low three bits
+	 * (for three buttons) of byte 0.
+	 */
+	left	= (buf[0] & 0x04)? 1: 0;
+	middle	= (buf[0] & 0x02)? 1: 0;
+	right	= (buf[0] & 0x01)? 1: 0;
+
+	vsxxxaa_drop_bytes (mouse, 3);
+
+	DBG (KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n",
+			mouse->dev.name, mouse->dev.phys, dx, dy,
+			left? "L": "l", middle? "M": "m", right? "R": "r");
+
+	/*
+	 * Report what we've found so far...
+	 */
+	input_regs (dev, regs);
+	input_report_key (dev, BTN_LEFT, left);
+	input_report_key (dev, BTN_MIDDLE, middle);
+	input_report_key (dev, BTN_RIGHT, right);
+	input_report_rel (dev, REL_X, dx);
+	input_report_rel (dev, REL_Y, dy);
+	input_sync (dev);
+}
+
+static void
+vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+{
+	struct input_dev *dev = &mouse->dev;
+	unsigned char *buf = mouse->buf;
+	int left, middle, right, extra;
+	int x, y;
+
+	/*
+	 * Tablet position / button packet
+	 *
+	 * [0]:	1	1	0	B4	B3	B2	B1	Pr
+	 * [1]:	0	0	X5	X4	X3	X2	X1	X0
+	 * [2]:	0	0	X11	X10	X9	X8	X7	X6
+	 * [3]:	0	0	Y5	Y4	Y3	Y2	Y1	Y0
+	 * [4]:	0	0	Y11	Y10	Y9	Y8	Y7	Y6
+	 */
+
+	/*
+	 * Get X/Y position
+	 */
+	x = ((buf[2] & 0x3f) << 6) | (buf[1] & 0x3f);
+	y = ((buf[4] & 0x3f) << 6) | (buf[3] & 0x3f);
+
+	/*
+	 * Get button state. It's bits <4..1> of byte 0.
+	 */
+	left	= (buf[0] & 0x02)? 1: 0;
+	middle	= (buf[0] & 0x04)? 1: 0;
+	right	= (buf[0] & 0x08)? 1: 0;
+	extra	= (buf[0] & 0x10)? 1: 0;
+
+	vsxxxaa_drop_bytes (mouse, 5);
+
+	DBG (KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n",
+			mouse->dev.name, mouse->dev.phys, x, y,
+			left? "L": "l", middle? "M": "m",
+			right? "R": "r", extra? "E": "e");
+
+	/*
+	 * Report what we've found so far...
+	 */
+	input_regs (dev, regs);
+	input_report_key (dev, BTN_LEFT, left);
+	input_report_key (dev, BTN_MIDDLE, middle);
+	input_report_key (dev, BTN_RIGHT, right);
+	input_report_key (dev, BTN_EXTRA, extra);
+	input_report_abs (dev, ABS_X, x);
+	input_report_abs (dev, ABS_Y, y);
+	input_sync (dev);
+}
+
+static void
+vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse, struct pt_regs *regs)
+{
+	struct input_dev *dev = &mouse->dev;
+	unsigned char *buf = mouse->buf;
+	int left, middle, right;
+	unsigned char error;
+
+	/*
+	 * Check for Power-On-Reset packets. These are sent out
+	 * after plugging the mouse in, or when explicitely
+	 * requested by sending 'T'.
+	 *
+	 * [0]:	1	0	1	0	R3	R2	R1	R0
+	 * [1]:	0	M2	M1	M0	D3	D2	D1	D0
+	 * [2]:	0	E6	E5	E4	E3	E2	E1	E0
+	 * [3]:	0	0	0	0	0	Left	Middle	Right
+	 *
+	 * M: manufacturer location code
+	 * R: revision code
+	 * E: Error code. I'm not sure about these, but gpm's sources,
+	 *    which support this mouse, too, tell about them:
+	 *	E = [0x00 .. 0x1f]: no error, byte #3 is button state
+	 *	E = 0x3d: button error, byte #3 tells which one.
+	 *	E = <else>: other error
+	 * D: <0010> == mouse, <0100> == tablet
+	 *
+	 */
+
+	mouse->version = buf[0] & 0x0f;
+	mouse->country = (buf[1] >> 4) & 0x07;
+	mouse->type = buf[1] & 0x07;
+	error = buf[2] & 0x7f;
+
+	/*
+	 * Get button state. It's the low three bits
+	 * (for three buttons) of byte 0. Maybe even the bit <3>
+	 * has some meaning if a tablet is attached.
+	 */
+	left	= (buf[0] & 0x04)? 1: 0;
+	middle	= (buf[0] & 0x02)? 1: 0;
+	right	= (buf[0] & 0x01)? 1: 0;
+
+	vsxxxaa_drop_bytes (mouse, 4);
+	vsxxxaa_report_mouse (mouse);
+
+	if (error <= 0x1f) {
+		/* No error. Report buttons */
+		input_regs (dev, regs);
+		input_report_key (dev, BTN_LEFT, left);
+		input_report_key (dev, BTN_MIDDLE, middle);
+		input_report_key (dev, BTN_RIGHT, right);
+		input_sync (dev);
+	} else {
+		printk (KERN_ERR "Your %s on %s reports an undefined error, "
+				"please check it...\n", mouse->dev.name,
+				mouse->dev.phys);
+	}
+
+	/*
+	 * If the mouse was hot-plugged, we need to
+	 * force differential mode now...
+	 */
+	printk (KERN_NOTICE "%s on %s: Forceing standard packet format and "
+			"streaming mode\n", mouse->dev.name, mouse->dev.phys);
+	mouse->serio->write (mouse->serio, 'S');
+	mouse->serio->write (mouse->serio, 'R');
+}
+
+static void
+vsxxxaa_parse_buffer (struct vsxxxaa *mouse, struct pt_regs *regs)
+{
+	unsigned char *buf = mouse->buf;
+	int stray_bytes;
+
+	/*
+	 * Parse buffer to death...
+	 */
+	do {
+		/*
+		 * Out of sync? Throw away what we don't understand. Each
+		 * packet starts with a byte whose bit 7 is set. Unhandled
+		 * packets (ie. which we don't know about or simply b0rk3d
+		 * data...) will get shifted out of the buffer after some
+		 * activity on the mouse.
+		 */
+		while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) {
+			printk (KERN_ERR "%s on %s: Dropping a byte to regain "
+					"sync with mouse data stream...\n",
+					mouse->dev.name, mouse->dev.phys);
+			vsxxxaa_drop_bytes (mouse, 1);
+		}
+
+		/*
+		 * Check for packets we know about.
+		 */
+
+		if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_REL, 3)) {
+			/* Check for broken packet */
+			stray_bytes = vsxxxaa_check_packet (mouse, 3);
+			if (stray_bytes > 0) {
+				printk (KERN_ERR "Dropping %d bytes now...\n",
+						stray_bytes);
+				vsxxxaa_drop_bytes (mouse, stray_bytes);
+				continue;
+			}
+
+			vsxxxaa_handle_REL_packet (mouse, regs);
+			continue; /* More to parse? */
+		}
+
+		if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_ABS, 5)) {
+			/* Check for broken packet */
+			stray_bytes = vsxxxaa_check_packet (mouse, 5);
+			if (stray_bytes > 0) {
+				printk (KERN_ERR "Dropping %d bytes now...\n",
+						stray_bytes);
+				vsxxxaa_drop_bytes (mouse, stray_bytes);
+				continue;
+			}
+
+			vsxxxaa_handle_ABS_packet (mouse, regs);
+			continue; /* More to parse? */
+		}
+
+		if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_POR, 4)) {
+			/* Check for broken packet */
+			stray_bytes = vsxxxaa_check_packet (mouse, 4);
+			if (stray_bytes > 0) {
+				printk (KERN_ERR "Dropping %d bytes now...\n",
+						stray_bytes);
+				vsxxxaa_drop_bytes (mouse, stray_bytes);
+				continue;
+			}
+
+			vsxxxaa_handle_POR_packet (mouse, regs);
+			continue; /* More to parse? */
+		}
+
+		break; /* No REL, ABS or POR packet found */
+	} while (1);
+}
+
+static irqreturn_t
+vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
+		struct pt_regs *regs)
+{
+	struct vsxxxaa *mouse = serio->private;
+
+	vsxxxaa_queue_byte (mouse, data);
+	vsxxxaa_parse_buffer (mouse, regs);
+
+	return IRQ_HANDLED;
+}
+
+static void
+vsxxxaa_disconnect (struct serio *serio)
+{
+	struct vsxxxaa *mouse = serio->private;
+
+	input_unregister_device (&mouse->dev);
+	serio_close (serio);
+	kfree (mouse);
+}
+
+static void
+vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
+{
+	struct vsxxxaa *mouse;
+
+	if ((serio->type & SERIO_TYPE) != SERIO_RS232)
+		return;
+
+	if ((serio->type & SERIO_PROTO) != SERIO_VSXXXAA)
+		return;
+
+	if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
+		return;
+
+	memset (mouse, 0, sizeof (struct vsxxxaa));
+
+	init_input_dev (&mouse->dev);
+	set_bit (EV_KEY, mouse->dev.evbit);		/* We have buttons */
+	set_bit (EV_REL, mouse->dev.evbit);		/* We can move */
+	set_bit (BTN_LEFT, mouse->dev.keybit);		/* We have 3 buttons */
+	set_bit (BTN_MIDDLE, mouse->dev.keybit);
+	set_bit (BTN_RIGHT, mouse->dev.keybit);
+	set_bit (BTN_EXTRA, mouse->dev.keybit);		/* ...and Tablet */
+	set_bit (REL_X, mouse->dev.relbit);		/* We can move in */
+	set_bit (REL_Y, mouse->dev.relbit);		/* two dimensions */
+	set_bit (ABS_X, mouse->dev.absbit);		/* DEC tablet support */
+	set_bit (ABS_Y, mouse->dev.absbit);
+
+	mouse->dev.absmin[ABS_X] = 0;
+	mouse->dev.absmax[ABS_X] = 1023;
+	mouse->dev.absmin[ABS_Y] = 0;
+	mouse->dev.absmax[ABS_Y] = 1023;
+
+	mouse->dev.private = mouse;
+	serio->private = mouse;
+
+	sprintf (mouse->phys, "%s/input0", serio->phys);
+	mouse->dev.phys = mouse->phys;
+	mouse->dev.name = "DEC VSXXX-AA/GA mouse or DEC tablet";
+	mouse->dev.id.bustype = BUS_RS232;
+	mouse->serio = serio;
+
+	if (serio_open (serio, dev)) {
+		kfree (mouse);
+		return;
+	}
+
+	/*
+	 * Request selftest and differential stream mode.
+	 */
+	mouse->serio->write (mouse->serio, 'T'); /* Test */
+	mouse->serio->write (mouse->serio, 'R'); /* Differential stream */
+
+	input_register_device (&mouse->dev);
+
+	printk (KERN_INFO "input: %s on %s\n", mouse->dev.name, serio->phys);
+}
+
+static struct serio_dev vsxxxaa_dev = {
+	.interrupt =	vsxxxaa_interrupt,
+	.connect =	vsxxxaa_connect,
+	.disconnect =	vsxxxaa_disconnect
+};
+
+int __init
+vsxxxaa_init (void)
+{
+	serio_register_device (&vsxxxaa_dev);
+	return 0;
+}
+
+void __exit
+vsxxxaa_exit (void)
+{
+	serio_unregister_device (&vsxxxaa_dev);
+}
+
+module_init (vsxxxaa_init);
+module_exit (vsxxxaa_exit);
+
diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
--- a/drivers/input/serio/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/serio/Kconfig	Wed Mar 17 19:29:09 2004
@@ -20,6 +20,7 @@
 	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
 	default y
 	select SERIO
+	depends on !PARISC
 	---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,
@@ -48,6 +49,7 @@
 config SERIO_CT82C710
 	tristate "ct82c710 Aux port controller"
 	depends on SERIO
+	depends on !PARISC
 	---help---
 	  Say Y here if you have a Texas Instruments TravelMate notebook
 	  equipped with the ct82c710 chip and want to use a mouse connected
@@ -104,6 +106,20 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called 98kbd-io.
+
+config SERIO_GSCPS2
+	tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
+	depends on GSC && SERIO
+	default y
+	help
+	  This driver provides support for the PS/2 ports on PA-RISC machines
+	  over which HP PS/2 keyboards and PS/2 mice may be connected.
+	  If you use these devices, you'll need to say Y here.
+
+	  It's safe to enable this driver, so if unsure, say Y.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gscps2.
 
 config SERIO_PCIPS2
 	tristate "PCI PS/2 keyboard and PS/2 mouse controller"
diff -Nru a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
--- a/drivers/input/serio/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/serio/Makefile	Wed Mar 17 19:29:09 2004
@@ -14,4 +14,5 @@
 obj-$(CONFIG_SERIO_AMBAKMI)	+= ambakmi.o
 obj-$(CONFIG_SERIO_Q40KBD)	+= q40kbd.o
 obj-$(CONFIG_SERIO_98KBD)	+= 98kbd-io.o
+obj-$(CONFIG_SERIO_GSCPS2)	+= gscps2.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
diff -Nru a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/input/serio/gscps2.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,470 @@
+/*
+ * drivers/input/serio/gscps2.c
+ *
+ * Copyright (c) 2004 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2002 Laurent Canet <canetl@esiee.fr>
+ * 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-2000 Philipp Rumpf <prumpf@tux.org>
+ *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
+ *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
+ *
+ * HP GSC PS/2 port driver, found in PA/RISC Workstations
+ *
+ * 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:
+ * - Dino testing (did HP ever shipped a machine on which this port
+ *                 was usable/enabled ?)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci_ids.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/parisc-device.h>
+
+MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>, Helge Deller <deller@gmx.de>");
+MODULE_DESCRIPTION("HP GSC PS/2 port driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
+
+#define PFX "gscps2.c: "
+
+/* 
+ * Driver constants
+ */
+
+/* various constants */
+#define ENABLE			1
+#define DISABLE			0
+
+#define GSC_DINO_OFFSET		0x0800	/* offset for DINO controller versus LASI one */
+
+/* PS/2 IO port offsets */
+#define GSC_ID			0x00	/* device ID offset (see: GSC_ID_XXX) */
+#define GSC_RESET		0x00	/* reset port offset */
+#define GSC_RCVDATA		0x04	/* receive port offset */
+#define GSC_XMTDATA		0x04	/* transmit port offset */
+#define GSC_CONTROL		0x08	/* see: Control register bits */
+#define GSC_STATUS		0x0C	/* see: Status register bits */
+
+/* Control register bits */
+#define GSC_CTRL_ENBL		0x01	/* enable interface */
+#define GSC_CTRL_LPBXR		0x02	/* loopback operation */
+#define GSC_CTRL_DIAG		0x20	/* directly control clock/data line */
+#define GSC_CTRL_DATDIR		0x40	/* data line direct control */
+#define GSC_CTRL_CLKDIR		0x80	/* clock line direct control */
+
+/* Status register bits */
+#define GSC_STAT_RBNE		0x01	/* Receive Buffer Not Empty */
+#define GSC_STAT_TBNE		0x02	/* Transmit Buffer Not Empty */
+#define GSC_STAT_TERR		0x04	/* Timeout Error */
+#define GSC_STAT_PERR		0x08	/* Parity Error */
+#define GSC_STAT_CMPINTR	0x10	/* Composite Interrupt = irq on any port */
+#define GSC_STAT_DATSHD		0x40	/* Data Line Shadow */
+#define GSC_STAT_CLKSHD		0x80	/* Clock Line Shadow */
+
+/* IDs returned by GSC_ID port register */
+#define GSC_ID_KEYBOARD		0	/* device ID values */
+#define GSC_ID_MOUSE		1
+
+
+static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
+
+#define BUFFER_SIZE 0x0f
+
+/* GSC PS/2 port device struct */
+struct gscps2port {
+	struct list_head node;
+	struct parisc_device *padev;
+	struct serio port;
+	spinlock_t lock;
+	char *addr;
+	u8 act, append; /* position in buffer[] */
+	struct {
+		u8 data;
+		u8 str;
+	} buffer[BUFFER_SIZE+1];
+	int id;
+	char name[32];
+};
+
+/*
+ * Various HW level routines
+ */
+
+#define gscps2_readb_input(x)		readb((x)+GSC_RCVDATA)
+#define gscps2_readb_control(x)		readb((x)+GSC_CONTROL)
+#define gscps2_readb_status(x)		readb((x)+GSC_STATUS)
+#define gscps2_writeb_control(x, y)	writeb((x), (y)+GSC_CONTROL)
+
+
+/*
+ * wait_TBE() - wait for Transmit Buffer Empty
+ */
+
+static int wait_TBE(char *addr)
+{
+	int timeout = 25000; /* device is expected to react within 250 msec */
+	while (gscps2_readb_status(addr) & GSC_STAT_TBNE) {
+		if (!--timeout)
+			return 0;	/* This should not happen */
+		udelay(10);
+	}
+	return 1;
+}
+
+
+/*
+ * gscps2_flush() - flush the receive buffer
+ */
+
+static void gscps2_flush(struct gscps2port *ps2port)
+{
+	while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
+		gscps2_readb_input(ps2port->addr);
+	ps2port->act = ps2port->append = 0;
+}
+
+/*
+ * gscps2_writeb_output() - write a byte to the port
+ *
+ * returns 1 on sucess, 0 on error
+ */
+
+static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
+{
+	unsigned long flags;
+	char *addr = ps2port->addr;
+
+	if (!wait_TBE(addr)) {
+		printk(KERN_DEBUG PFX "timeout - could not write byte %#x\n", data);
+		return 0;
+	}
+
+	while (gscps2_readb_status(ps2port->addr) & GSC_STAT_RBNE)
+		/* wait */;
+
+	spin_lock_irqsave(&ps2port->lock, flags);
+	writeb(data, addr+GSC_XMTDATA);
+	spin_unlock_irqrestore(&ps2port->lock, flags);
+
+	/* this is ugly, but due to timing of the port it seems to be necessary. */
+	mdelay(6);
+
+	/* make sure any received data is returned as fast as possible */
+	/* this is important e.g. when we set the LEDs on the keyboard */
+	gscps2_interrupt(0, NULL, NULL);
+
+	return 1;
+}
+
+
+/*
+ * gscps2_enable() - enables or disables the port
+ */
+
+static void gscps2_enable(struct gscps2port *ps2port, int enable)
+{
+	unsigned long flags;
+	u8 data;
+
+	/* now enable/disable the port */
+	spin_lock_irqsave(&ps2port->lock, flags);
+	gscps2_flush(ps2port);
+	data = gscps2_readb_control(ps2port->addr);
+	if (enable)
+		data |= GSC_CTRL_ENBL;
+	else
+		data &= ~GSC_CTRL_ENBL;
+	gscps2_writeb_control(data, ps2port->addr);
+	spin_unlock_irqrestore(&ps2port->lock, flags);
+	wait_TBE(ps2port->addr);
+	gscps2_flush(ps2port);
+}
+
+/*
+ * gscps2_reset() - resets the PS/2 port
+ */
+
+static void gscps2_reset(struct gscps2port *ps2port)
+{
+	char *addr = ps2port->addr;
+	unsigned long flags;
+
+	/* reset the interface */
+	spin_lock_irqsave(&ps2port->lock, flags);
+	gscps2_flush(ps2port);
+	writeb(0xff, addr+GSC_RESET);
+	gscps2_flush(ps2port);
+	spin_unlock_irqrestore(&ps2port->lock, flags);
+
+	/* enable it */
+	gscps2_enable(ps2port, ENABLE);
+}
+
+static LIST_HEAD(ps2port_list);
+
+/**
+ * gscps2_interrupt() - Interruption service routine
+ *
+ * This function reads received PS/2 bytes and processes them on 
+ * all interfaces.
+ * The problematic part here is, that the keyboard and mouse PS/2 port
+ * share the same interrupt and it's not possible to send data if any
+ * one of them holds input data. To solve this problem we try to receive
+ * the data as fast as possible and handle the reporting to the upper layer
+ * later.
+ */
+
+static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	struct gscps2port *ps2port;
+
+	list_for_each_entry(ps2port, &ps2port_list, node) {
+
+	  unsigned long flags;
+	  spin_lock_irqsave(&ps2port->lock, flags);
+
+	  while ( (ps2port->buffer[ps2port->append].str = 
+		   gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) {
+		ps2port->buffer[ps2port->append].data = 
+				gscps2_readb_input(ps2port->addr);
+		ps2port->append = ((ps2port->append+1) & BUFFER_SIZE);
+	  }
+
+	  spin_unlock_irqrestore(&ps2port->lock, flags);
+
+	} /* list_for_each_entry */
+
+	/* all data was read from the ports - now report the data to upper layer */
+
+	list_for_each_entry(ps2port, &ps2port_list, node) {
+
+	  while (ps2port->act != ps2port->append) {
+
+	    unsigned int rxflags;
+	    u8 data, status;
+
+	    /* Did new data arrived while we read existing data ?
+	       If yes, exit now and let the new irq handler start over again */
+	    if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR)
+		return IRQ_HANDLED;
+
+	    status = ps2port->buffer[ps2port->act].str;
+	    data   = ps2port->buffer[ps2port->act].data;
+
+	    ps2port->act = ((ps2port->act+1) & BUFFER_SIZE);
+	    rxflags =	((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
+			((status & GSC_STAT_PERR) ? SERIO_PARITY  : 0 );
+
+	    serio_interrupt(&ps2port->port, data, rxflags, regs);
+
+	  } /* while() */
+
+	} /* list_for_each_entry */
+
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * gscps2_write() - send a byte out through the aux interface.
+ */
+
+static int gscps2_write(struct serio *port, unsigned char data)
+{
+	struct gscps2port *ps2port = port->driver;
+
+	if (!gscps2_writeb_output(ps2port, data)) {
+		printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * gscps2_open() is called when a port is opened by the higher layer.
+ * It resets and enables the port.
+ */
+
+static int gscps2_open(struct serio *port)
+{
+	struct gscps2port *ps2port = port->driver;
+
+	gscps2_reset(ps2port);
+
+	gscps2_interrupt(0, NULL, NULL);
+
+	return 0;
+}
+
+/*
+ * gscps2_close() disables the port
+ */
+
+static void gscps2_close(struct serio *port)
+{
+	struct gscps2port *ps2port = port->driver;
+	gscps2_enable(ps2port, DISABLE);
+}
+
+static struct serio gscps2_serio_port =
+{
+	.name =		"GSC PS/2",
+	.idbus =	BUS_GSC,
+	.idvendor =	PCI_VENDOR_ID_HP,
+	.idproduct =	0x0001,
+	.idversion =	0x0010,
+	.type =		SERIO_8042,
+	.write =	gscps2_write,
+	.open =		gscps2_open,
+	.close =	gscps2_close,
+};
+
+/**
+ * gscps2_probe() - Probes PS2 devices
+ * @return: success/error report
+ */
+
+static int __init gscps2_probe(struct parisc_device *dev)
+{
+        struct gscps2port *ps2port;
+	unsigned long hpa = dev->hpa;
+	int ret;
+
+	if (!dev->irq)
+		return -ENODEV;
+	
+	/* Offset for DINO PS/2. Works with LASI even */
+	if (dev->id.sversion == 0x96)
+		hpa += GSC_DINO_OFFSET;
+
+	ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
+	if (!ps2port)
+		return -ENOMEM;
+
+	dev_set_drvdata(&dev->dev, ps2port);
+
+	memset(ps2port, 0, sizeof(struct gscps2port));
+	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;
+
+	list_add_tail(&ps2port->node, &ps2port_list);
+
+	ret = -EBUSY;
+	if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port))
+		goto fail_miserably;
+
+	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;
+		goto fail;
+	}
+
+#if 0
+	if (!request_mem_region(hpa, GSC_STATUS + 4, ps2port->port.name))
+		goto fail;
+#endif
+
+	printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
+		ps2port->name,
+		ps2port->addr,
+		ps2port->padev->irq,
+		ps2port->port.phys);
+
+	serio_register_port(&ps2port->port);
+	
+	return 0;
+	
+fail:
+	free_irq(dev->irq, ps2port);
+
+fail_miserably:
+	list_del(&ps2port->node);
+	iounmap(ps2port->addr);
+	release_mem_region(dev->hpa, GSC_STATUS + 4);
+	kfree(ps2port);
+	return ret;
+}
+
+/**
+ * gscps2_remove() - Removes PS2 devices
+ * @return: success/error report
+ */
+
+static int __devexit gscps2_remove(struct parisc_device *dev)
+{
+	struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
+
+	serio_unregister_port(&ps2port->port);
+	free_irq(dev->irq, ps2port);
+	gscps2_flush(ps2port);
+	list_del(&ps2port->node);
+	iounmap(ps2port->addr);
+#if 0
+	release_mem_region(dev->hpa, GSC_STATUS + 4); 
+#endif
+	dev_set_drvdata(&dev->dev, NULL);
+	kfree(ps2port);
+	return 0;
+}
+
+
+static struct parisc_device_id gscps2_device_tbl[] = {
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */
+#ifdef DINO_TESTED
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */ 
+#endif
+	{ 0, }	/* 0 terminated list */
+};
+
+static struct parisc_driver parisc_ps2_driver = {
+	.name		= "GSC PS/2",
+	.id_table	= gscps2_device_tbl,
+	.probe		= gscps2_probe,
+	.remove		= gscps2_remove,
+};
+
+static int __init gscps2_init(void)
+{
+	register_parisc_driver(&parisc_ps2_driver);
+	return 0;
+}
+
+static void __exit gscps2_exit(void)
+{
+	unregister_parisc_driver(&parisc_ps2_driver);
+}
+
+
+module_init(gscps2_init);
+module_exit(gscps2_exit);
+
diff -Nru a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
--- a/drivers/input/serio/i8042-io.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/serio/i8042-io.h	Wed Mar 17 19:29:09 2004
@@ -25,6 +25,9 @@
 #elif defined(__ia64__)
 # define I8042_KBD_IRQ isa_irq_to_vector(1)
 # define I8042_AUX_IRQ isa_irq_to_vector(12)
+#elif defined(__arm__)
+/* defined in include/asm-arm/arch-xxx/irqs.h */
+#include <asm/irq.h>
 #else
 # define I8042_KBD_IRQ	1
 # define I8042_AUX_IRQ	12
diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
--- a/drivers/input/serio/i8042.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/serio/i8042.c	Wed Mar 17 19:29:09 2004
@@ -52,6 +52,13 @@
 module_param_named(dumbkbd, i8042_dumbkbd, bool, 0);
 MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard");
 
+__obsolete_setup("i8042_noaux");
+__obsolete_setup("i8042_nomux");
+__obsolete_setup("i8042_unlock");
+__obsolete_setup("i8042_reset");
+__obsolete_setup("i8042_direct");
+__obsolete_setup("i8042_dumbkbd");
+
 #undef DEBUG
 #include "i8042.h"
 
@@ -379,6 +386,8 @@
 	unsigned int dfl;
 	int ret;
 
+	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
+
 	spin_lock_irqsave(&i8042_lock, flags);
 	str = i8042_read_status();
 	if (str & I8042_STR_OBF)
@@ -433,7 +442,6 @@
 irq_ret:
 	ret = 1;
 out:
-	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 	return IRQ_RETVAL(ret);
 }
 
@@ -522,6 +530,11 @@
 
 	if (i8042_enable_mux_mode(values, &mux_version))
 		return -1;
+	
+	/* Workaround for broken chips which seem to support MUX, but in reality don't. */
+	/* They all report version 12.10 */
+	if (mux_version == 0xCA)
+		return -1;
 
 	printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
 		(mux_version >> 4) & 0xf, mux_version & 0xf);
@@ -707,14 +720,6 @@
 		 else
 			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
 	}
-
-/*
- * If the chip is configured into nontranslated mode by the BIOS, don't
- * bother enabling translating and be happy.
- */
-
-	if (~i8042_ctr & I8042_CTR_XLATE)
-		i8042_direct = 1;
 
 /*
  * Set nontranslated mode for the kbd interface if requested by an option.
diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
--- a/drivers/input/serio/serio.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/input/serio/serio.c	Wed Mar 17 19:29:09 2004
@@ -195,6 +195,9 @@
                 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;
 		}
diff -Nru a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
--- a/drivers/isdn/capi/kcapi.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/isdn/capi/kcapi.c	Wed Mar 17 19:29:10 2004
@@ -1,4 +1,4 @@
-/* $Id: kcapi.c,v 1.1.2.4 2004/02/10 01:07:11 keil Exp $
+/* $Id: kcapi.c,v 1.1.2.7 2004/03/16 08:01:47 armin Exp $
  * 
  * Kernel CAPI 2.0 Module
  * 
@@ -31,7 +31,7 @@
 #include <linux/b1lli.h>
 #endif
 
-static char *revision = "$Revision: 1.1.2.4 $";
+static char *revision = "$Revision: 1.1.2.7 $";
 
 /* ------------------------------------------------------------- */
 
@@ -45,7 +45,7 @@
 /* ------------------------------------------------------------- */
 
 struct capi_notifier {
-	struct capi_notifier *next;
+	struct work_struct work;
 	unsigned int cmd;
 	u32 controller;
 	u16 applid;
@@ -69,7 +69,6 @@
 static int ncards;
 static struct sk_buff_head recv_queue;
 
-static struct work_struct tq_state_notify;
 static struct work_struct tq_recv_notify;
 
 /* -------- controller ref counting -------------------------------------- */
@@ -161,79 +160,6 @@
 	capi_ctr_put(card);
 }
 
-
-/* -------- Notifier handling --------------------------------- */
-
-static struct capi_notifier_list{
-	struct capi_notifier *head;
-	struct capi_notifier *tail;
-} notifier_list;
-
-static spinlock_t notifier_lock = SPIN_LOCK_UNLOCKED;
-
-static inline void notify_enqueue(struct capi_notifier *np)
-{
-	struct capi_notifier_list *q = &notifier_list;
-	unsigned long flags;
-
-	spin_lock_irqsave(&notifier_lock, flags);
-	if (q->tail) {
-		q->tail->next = np;
-		q->tail = np;
-	} else {
-		q->head = q->tail = np;
-	}
-	spin_unlock_irqrestore(&notifier_lock, flags);
-}
-
-static inline struct capi_notifier *notify_dequeue(void)
-{
-	struct capi_notifier_list *q = &notifier_list;
-	struct capi_notifier *np = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&notifier_lock, flags);
-	if (q->head) {
-		np = q->head;
-		if ((q->head = np->next) == 0)
- 			q->tail = 0;
-		np->next = 0;
-	}
-	spin_unlock_irqrestore(&notifier_lock, flags);
-	return np;
-}
-
-static int notify_push(unsigned int cmd, u32 controller,
-				u16 applid, u32 ncci)
-{
-	struct capi_notifier *np;
-
-	if (!try_module_get(THIS_MODULE)) {
-		printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__);
-		return -1;
-	}
-	np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC);
-	if (!np) {
-		module_put(THIS_MODULE);
-		return -1;
-	}
-	memset(np, 0, sizeof(struct capi_notifier));
-	np->cmd = cmd;
-	np->controller = controller;
-	np->applid = applid;
-	np->ncci = ncci;
-	notify_enqueue(np);
-	/*
-	 * The notifier will result in adding/deleteing
-	 * of devices. Devices can only removed in
-	 * user process, not in bh.
-	 */
-	__module_get(THIS_MODULE);
-	if (schedule_work(&tq_state_notify) == 0)
-		module_put(THIS_MODULE);
-	return 0;
-}
-
 /* -------- KCI_CONTRUP --------------------------------------- */
 
 static void notify_up(u32 contr)
@@ -242,7 +168,9 @@
 	struct capi20_appl *ap;
 	u16 applid;
 
-        printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
+	if (showcapimsgs & 1) {
+	        printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
+	}
 
 	for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 		ap = get_capi_appl_by_nr(applid);
@@ -258,7 +186,9 @@
 	struct capi20_appl *ap;
 	u16 applid;
 
-        printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
+	if (showcapimsgs & 1) {
+        	printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
+	}
 
 	for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 		ap = get_capi_appl_by_nr(applid);
@@ -267,31 +197,43 @@
 	}
 }
 
-/* ------------------------------------------------------------ */
-
-static inline void notify_doit(struct capi_notifier *np)
+static void notify_handler(void *data)
 {
+	struct capi_notifier *np = data;
+
 	switch (np->cmd) {
-		case KCI_CONTRUP:
-			notify_up(np->controller);
-			break;
-		case KCI_CONTRDOWN:
-			notify_down(np->controller);
-			break;
+	case KCI_CONTRUP:
+		notify_up(np->controller);
+		break;
+	case KCI_CONTRDOWN:
+		notify_down(np->controller);
+		break;
 	}
+
+	kfree(np);
 }
 
-static void notify_handler(void *dummy)
+/*
+ * The notifier will result in adding/deleteing of devices. Devices can
+ * only removed in user process, not in bh.
+ */
+static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci)
 {
-	struct capi_notifier *np;
+	struct capi_notifier *np = kmalloc(sizeof(*np), GFP_ATOMIC);
 
-	while ((np = notify_dequeue()) != 0) {
-		notify_doit(np);
-		kfree(np);
-		module_put(THIS_MODULE);
-	}
-	module_put(THIS_MODULE);
+	if (!np)
+		return -ENOMEM;
+
+	INIT_WORK(&np->work, notify_handler, np);
+	np->cmd = cmd;
+	np->controller = controller;
+	np->applid = applid;
+	np->ncci = ncci;
+
+	schedule_work(&np->work);
+	return 0;
 }
+
 	
 /* -------- Receiver ------------------------------------------ */
 
@@ -304,7 +246,7 @@
 		ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
 		if (!ap) {
 			printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)\n",
-			       ap->applid, capi_message2str(skb->data));
+				CAPIMSG_APPID(skb->data), capi_message2str(skb->data));
 			kfree_skb(skb);
 			continue;
 		}
@@ -565,7 +507,9 @@
 			continue;
 		register_appl(capi_cards[i], applid, &ap->rparam);
 	}
-	printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
+	if (showcapimsgs & 1) {
+		printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
+	}
 
 	return CAPI_NOERROR;
 }
@@ -584,7 +528,9 @@
 		release_appl(capi_cards[i], ap->applid);
 	}
 	capi_applications[ap->applid - 1] = NULL;
-	printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
+	if (showcapimsgs & 1) {
+		printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
+	}
 
 	return CAPI_NOERROR;
 }
@@ -981,7 +927,6 @@
 
 	skb_queue_head_init(&recv_queue);
 
-	INIT_WORK(&tq_state_notify, notify_handler, NULL);
 	INIT_WORK(&tq_recv_notify, recv_handler, NULL);
 
         kcapi_proc_init();
@@ -1001,6 +946,9 @@
 static void __exit kcapi_exit(void)
 {
         kcapi_proc_exit();
+
+	/* make sure all notifiers are finished */
+	flush_scheduled_work();
 }
 
 module_init(kcapi_init);
diff -Nru a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
--- a/drivers/isdn/hisax/hfc_usb.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/isdn/hisax/hfc_usb.c	Wed Mar 17 19:29:09 2004
@@ -1349,9 +1349,11 @@
 {
 	struct usb_device *dev= interface_to_usbdev(intf);
 	hfcusb_data *context;
-	struct usb_host_interface *iface = intf->altsetting + intf->act_altsetting;
+	struct usb_host_interface *iface = intf->cur_altsetting;
+	struct usb_host_interface *iface_used = NULL;
 	struct usb_host_endpoint *ep;
-	int i, idx, probe_alt_setting,vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
+	int ifnum = iface->desc.bInterfaceNumber;
+	int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
 	int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;
 
 //        usb_show_device(dev);
@@ -1366,7 +1368,7 @@
 
 #ifdef VERBOSE_USB_DEBUG	
 	printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",
-		intf->altsetting->desc.bInterfaceNumber, intf->act_altsetting, intf->minor);
+		ifnum, iface->desc.bAlternateSetting, intf->minor);
 #endif
 
 	if (vend_idx != 0xffff) {
@@ -1374,14 +1376,15 @@
 		printk(KERN_INFO "HFC-USB: found vendor idx:%d  name:%s\n",vend_idx,vdata[vend_idx].vend_name);
 #endif
 		/* if vendor and product ID is OK, start probing a matching alternate setting ... */
-		probe_alt_setting = 0;
+		alt_idx = 0;
 		small_match=0xffff;
 		// default settings
 		iso_packet_size=16;
 		packet_size=64;
 
-		while(probe_alt_setting < intf->num_altsetting) {
-			iface = intf->altsetting + probe_alt_setting;
+		while (alt_idx < intf->num_altsetting) {
+			iface = intf->altsetting + alt_idx;
+			probe_alt_setting = iface->desc.bAlternateSetting;
 			cfg_used=0;
 
 #ifdef VERBOSE_USB_DEBUG
@@ -1395,7 +1398,7 @@
 
 #ifdef VERBOSE_USB_DEBUG
 				printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",
-					probe_alt_setting, intf->act_altsetting,cfg_used);
+					ifnum, probe_alt_setting, cfg_used);
 #endif
 				// copy table
 				memcpy(cmptbl,vcf,16*sizeof(int));
@@ -1448,6 +1451,7 @@
 					if (cfg_used < small_match) {
 						small_match = cfg_used;
 						alt_used = probe_alt_setting;
+						iface_used = iface;
 					}
 #ifdef VERBOSE_USB_DEBUG
 					printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);
@@ -1457,15 +1461,14 @@
 				cfg_used++;
 			}
 
-			probe_alt_setting++;
-		}		/* (probe_alt_setting < intf->num_altsetting) */
+			alt_idx++;
+		}		/* (alt_idx < intf->num_altsetting) */
 #ifdef VERBOSE_USB_DEBUG
 		printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);
 #endif
 		// yiipiee, we found a valid config
 		if (small_match != 0xffff) {
-			intf->act_altsetting = alt_used;
-			iface = intf->altsetting + intf->act_altsetting;
+			iface = iface_used;
 
 			if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
 				return(-ENOMEM);  /* got no mem */
@@ -1542,8 +1545,8 @@
 
 			// now share our luck
 			context->dev = dev;						/* save device */
-			context->if_used = intf->altsetting->desc.bInterfaceNumber;	/* save used interface */
-			context->alt_used = intf->act_altsetting;			/* and alternate config */
+			context->if_used = ifnum;					/* save used interface */
+			context->alt_used = alt_used;					/* and alternate config */
 			context->ctrl_paksize = dev->descriptor.bMaxPacketSize0;	/* control size */
 			context->cfg_used=vcf[16];					// store used config
 			context->vend_idx=vend_idx;					// store found vendor
diff -Nru a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
--- a/drivers/net/hamradio/6pack.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/hamradio/6pack.c	Wed Mar 17 19:29:09 2004
@@ -3,15 +3,13 @@
  *		devices like TTY. It interfaces between a raw TTY and the
  *		kernel's AX.25 protocol layers.
  *
- * Version:	@(#)6pack.c	0.3.0	04/07/98
- *
  * Authors:	Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ *              Ralf Baechle DO1GRB <ralf@linux-mips.org>
  *
- * Quite a lot of stuff "stolen" by Jörg Reuter from slip.c, written by
+ * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
  *
  *		Laurence Culhane, <loz@holmes.demon.co.uk>
  *		Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- *
  */
 
 #include <linux/config.h>
@@ -31,20 +29,23 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
+#include <linux/spinlock.h>
 #include <linux/if_arp.h>
 #include <linux/init.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <asm/semaphore.h>
+#include <asm/atomic.h>
 
 #define SIXPACK_VERSION    "Revision: 0.3.0"
 
 /* sixpack priority commands */
-#define SIXP_SEOF	0x40	/* start and end of a 6pack frame */
-#define SIXP_TX_URUN	0x48	/* transmit overrun */
-#define SIXP_RX_ORUN	0x50	/* receive overrun */
-#define SIXP_RX_BUF_OVL	0x58	/* receive buffer overflow */
+#define SIXP_SEOF		0x40	/* start and end of a 6pack frame */
+#define SIXP_TX_URUN		0x48	/* transmit overrun */
+#define SIXP_RX_ORUN		0x50	/* receive overrun */
+#define SIXP_RX_BUF_OVL		0x58	/* receive buffer overflow */
 
-#define SIXP_CHKSUM	0xFF	/* valid checksum of a 6pack frame */
+#define SIXP_CHKSUM		0xFF	/* valid checksum of a 6pack frame */
 
 /* masks to get certain bits out of the status bytes sent by the TNC */
 
@@ -78,23 +79,20 @@
 #define SIXP_MTU			256	/* Default MTU */
 
 enum sixpack_flags {
-	SIXPF_INUSE,	/* Channel in use	*/
 	SIXPF_ERROR,	/* Parity, etc. error	*/
 };
 
 struct sixpack {
-	int			magic;
-
 	/* Various fields. */
-	struct tty_struct	*tty;		/* ptr to TTY structure		*/
-	struct net_device	*dev;		/* easy for intr handling	*/
+	struct tty_struct	*tty;		/* ptr to TTY structure	*/
+	struct net_device	*dev;		/* easy for intr handling  */
 
 	/* These are pointers to the malloc()ed frame buffers. */
-	unsigned char		*rbuff;		/* receiver buffer		*/
-	int			rcount;         /* received chars counter       */
-	unsigned char		*xbuff;		/* transmitter buffer		*/
-	unsigned char		*xhead;         /* pointer to next byte to XMIT */
-	int			xleft;          /* bytes left in XMIT queue     */
+	unsigned char		*rbuff;		/* receiver buffer	*/
+	int			rcount;         /* received chars counter  */
+	unsigned char		*xbuff;		/* transmitter buffer	*/
+	unsigned char		*xhead;         /* next byte to XMIT */
+	int			xleft;          /* bytes left in XMIT queue  */
 
 	unsigned char		raw_buf[4];
 	unsigned char		cooked_buf[400];
@@ -105,11 +103,11 @@
 	/* 6pack interface statistics. */
 	struct net_device_stats stats;
 
-	int			mtu;		/* Our mtu (to spot changes!)   */
-	int			buffsize;       /* Max buffers sizes            */
+	int			mtu;		/* Our mtu (to spot changes!) */
+	int			buffsize;       /* Max buffers sizes */
 
-	unsigned long		flags;		/* Flag values/ mode etc	*/
-	unsigned char		mode;		/* 6pack mode			*/
+	unsigned long		flags;		/* Flag values/ mode etc */
+	unsigned char		mode;		/* 6pack mode */
 
 	/* 6pack stuff */
 	unsigned char		tx_delay;
@@ -125,112 +123,293 @@
 
 	struct timer_list	tx_t;
 	struct timer_list	resync_t;
+
+	atomic_t		refcnt;
+	struct semaphore	dead_sem;
+	spinlock_t		lock;
 };
 
 #define AX25_6PACK_HEADER_LEN 0
-#define SIXPACK_MAGIC 0x5304
-
-typedef struct sixpack_ctrl {
-	struct sixpack	ctrl;			/* 6pack things			*/
-	struct net_device	dev;		/* the device			*/
-} sixpack_ctrl_t;
-static sixpack_ctrl_t **sixpack_ctrls;
-
-int sixpack_maxdev = SIXP_NRUNIT;	/* Can be overridden with insmod! */
-MODULE_PARM(sixpack_maxdev, "i");
-MODULE_PARM_DESC(sixpack_maxdev, "number of 6PACK devices");
 
 static void sp_start_tx_timer(struct sixpack *);
-static void sp_xmit_on_air(unsigned long);
-static void resync_tnc(unsigned long);
 static void sixpack_decode(struct sixpack *, unsigned char[], int);
 static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
 static int sixpack_init(struct net_device *dev);
 
-static void decode_prio_command(unsigned char, struct sixpack *);
-static void decode_std_command(unsigned char, struct sixpack *);
-static void decode_data(unsigned char, struct sixpack *);
+/*
+ * perform the persistence/slottime algorithm for CSMA access. If the
+ * persistence check was successful, write the data to the serial driver.
+ * Note that in case of DAMA operation, the data is not sent here.
+ */
+
+static void sp_xmit_on_air(unsigned long channel)
+{
+	struct sixpack *sp = (struct sixpack *) channel;
+	int actual;
+	static unsigned char random;
 
-static int tnc_init(struct sixpack *);
+	random = random * 17 + 41;
 
-/* Find a free 6pack channel, and link in this `tty' line. */
-static inline struct sixpack *sp_alloc(void)
+	if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
+		sp->led_state = 0x70;
+		sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
+		sp->tx_enable = 1;
+		actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, sp->status2);
+		sp->xleft -= actual;
+		sp->xhead += actual;
+		sp->led_state = 0x60;
+		sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
+		sp->status2 = 0;
+	} else
+		sp_start_tx_timer(sp);
+}
+
+/* ----> 6pack timer interrupt handler and friends. <---- */
+static void sp_start_tx_timer(struct sixpack *sp)
 {
-	sixpack_ctrl_t *spp = NULL;
-	int i;
+	int when = sp->slottime;
 
-	for (i = 0; i < sixpack_maxdev; i++) {
-		spp = sixpack_ctrls[i];
+	del_timer(&sp->tx_t);
+	sp->tx_t.data = (unsigned long) sp;
+	sp->tx_t.function = sp_xmit_on_air;
+	sp->tx_t.expires = jiffies + ((when + 1) * HZ) / 100;
+	add_timer(&sp->tx_t);
+}
 
-		if (spp == NULL)
-			break;
+/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
+static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
+{
+	unsigned char *msg, *p = icp;
+	int actual, count;
 
-		if (!test_and_set_bit(SIXPF_INUSE, &spp->ctrl.flags))
-			break;
+	if (len > sp->mtu) {	/* sp->mtu = AX25_MTU = max. PACLEN = 256 */
+		msg = "oversized transmit packet!";
+		goto out_drop;
 	}
 
-	/* Too many devices... */
-	if (i >= sixpack_maxdev)
-		return NULL;
+	if (p[0] > 5) {
+		msg = "invalid KISS command";
+		goto out_drop;
+	}
 
-	/* If no channels are available, allocate one */
-	if (!spp &&
-	    (sixpack_ctrls[i] = (sixpack_ctrl_t *)kmalloc(sizeof(sixpack_ctrl_t),
-						    GFP_KERNEL)) != NULL) {
-		spp = sixpack_ctrls[i];
+	if ((p[0] != 0) && (len > 2)) {
+		msg = "KISS control packet too long";
+		goto out_drop;
 	}
-	memset(spp, 0, sizeof(sixpack_ctrl_t));
 
-	/* Initialize channel control data */
-	set_bit(SIXPF_INUSE, &spp->ctrl.flags);
-	spp->ctrl.tty         = NULL;
-	sprintf(spp->dev.name, "sp%d", i);
-	spp->dev.base_addr    = i;
-	spp->dev.priv         = (void *) &spp->ctrl;
-	spp->dev.next         = NULL;
-	spp->dev.init         = sixpack_init;
-
-	if (spp != NULL) {
-		/* register device so that it can be ifconfig'ed       */
-		/* sixpack_init() will be called as a side-effect         */
-		/* SIDE-EFFECT WARNING: sixpack_init() CLEARS spp->ctrl ! */
-
-		if (register_netdev(&spp->dev) == 0) {
-			set_bit(SIXPF_INUSE, &spp->ctrl.flags);
-			spp->ctrl.dev = &spp->dev;
-			spp->dev.priv = (void *) &spp->ctrl;
-			SET_MODULE_OWNER(&spp->dev);
-			return &spp->ctrl;
-		} else {
-			clear_bit(SIXPF_INUSE, &spp->ctrl.flags);
-			printk(KERN_WARNING "sp_alloc() - register_netdev() failure.\n");
-		}
+	if ((p[0] == 0) && (len < 15)) {
+		msg = "bad AX.25 packet to transmit";
+		goto out_drop;
 	}
 
-	return NULL;
+	count = encode_sixpack(p, sp->xbuff, len, sp->tx_delay);
+	set_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
+
+	switch (p[0]) {
+	case 1:	sp->tx_delay = p[1];
+		return;
+	case 2:	sp->persistence = p[1];
+		return;
+	case 3:	sp->slottime = p[1];
+		return;
+	case 4:	/* ignored */
+		return;
+	case 5:	sp->duplex = p[1];
+		return;
+	}
+
+	if (p[0] != 0)
+		return;
+
+	/*
+	 * In case of fullduplex or DAMA operation, we don't take care about the
+	 * state of the DCD or of any timers, as the determination of the
+	 * correct time to send is the job of the AX.25 layer. We send
+	 * immediately after data has arrived.
+	 */
+	if (sp->duplex == 1) {
+		sp->led_state = 0x70;
+		sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
+		sp->tx_enable = 1;
+		actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, count);
+		sp->xleft = count - actual;
+		sp->xhead = sp->xbuff + actual;
+		sp->led_state = 0x60;
+		sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
+	} else {
+		sp->xleft = count;
+		sp->xhead = sp->xbuff;
+		sp->status2 = count;
+		if (sp->duplex == 0)
+			sp_start_tx_timer(sp);
+	}
+
+	return;
+
+out_drop:
+	sp->stats.tx_dropped++;
+	netif_start_queue(sp->dev);
+	printk(KERN_DEBUG "%s: %s - dropped.\n", sp->dev->name, msg);
+	return;
 }
 
+/* Encapsulate an IP datagram and kick it into a TTY queue. */
+
+static int sp_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct sixpack *sp = netdev_priv(dev);
+
+	spin_lock_bh(&sp->lock);
+	/* We were not busy, so we are now... :-) */
+	netif_stop_queue(dev);
+	sp->stats.tx_bytes += skb->len;
+	sp_encaps(sp, skb->data, skb->len);
+	spin_unlock_bh(&sp->lock);
+
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static int sp_open_dev(struct net_device *dev)
+{
+	struct sixpack *sp = netdev_priv(dev);
+
+	if (sp->tty == NULL)
+		return -ENODEV;
+	return 0;
+}
+
+/* Close the low-level part of the 6pack channel. */
+static int sp_close(struct net_device *dev)
+{
+	struct sixpack *sp = netdev_priv(dev);
+
+	spin_lock_bh(&sp->lock);
+	if (sp->tty) {
+		/* TTY discipline is running. */
+		clear_bit(TTY_DO_WRITE_WAKEUP, &sp->tty->flags);
+	}
+	netif_stop_queue(dev);
+	spin_unlock_bh(&sp->lock);
+
+	return 0;
+}
+
+/* Return the frame type ID */
+static int sp_header(struct sk_buff *skb, struct net_device *dev,
+	unsigned short type, void *daddr, void *saddr, unsigned len)
+{
+#ifdef CONFIG_INET
+	if (type != htons(ETH_P_AX25))
+		return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
+#endif
+	return 0;
+}
+
+static struct net_device_stats *sp_get_stats(struct net_device *dev)
+{
+	struct sixpack *sp = netdev_priv(dev);
+	return &sp->stats;
+}
+
+static int sp_set_dev_mac_address(struct net_device *dev, void *addr)
+{
+	struct sockaddr *sa = addr;
+	memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
+	return 0;
+}
+
+static int sp_rebuild_header(struct sk_buff *skb)
+{
+#ifdef CONFIG_INET
+	return ax25_rebuild_header(skb);
+#else
+	return 0;
+#endif
+}
+
+static void sp_setup(struct net_device *dev)
+{
+	static char ax25_bcast[AX25_ADDR_LEN] =
+		{'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
+	static char ax25_test[AX25_ADDR_LEN] =
+		{'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
+
+	/* Finish setting up the DEVICE info. */
+	dev->init		= sixpack_init;
+	dev->mtu		= SIXP_MTU;
+	dev->hard_start_xmit	= sp_xmit;
+	dev->open		= sp_open_dev;
+	dev->destructor		= free_netdev;
+	dev->stop		= sp_close;
+	dev->hard_header	= sp_header;
+	dev->get_stats	        = sp_get_stats;
+	dev->set_mac_address    = sp_set_dev_mac_address;
+	dev->hard_header_len	= AX25_MAX_HEADER_LEN;
+	dev->addr_len		= AX25_ADDR_LEN;
+	dev->type		= ARPHRD_AX25;
+	dev->tx_queue_len	= 10;
+	dev->rebuild_header	= sp_rebuild_header;
+	dev->tx_timeout		= NULL;
+
+	/* Only activated in AX.25 mode */
+	memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);
+	memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);
+
+	SET_MODULE_OWNER(dev);
+
+	/* New-style flags. */
+	dev->flags		= 0;
+}
+
+/* Find a free 6pack channel, and link in this `tty' line. */
+static inline struct sixpack *sp_alloc(void)
+{
+	struct sixpack *sp = NULL;
+	struct net_device *dev = NULL;
+
+	dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
+	if (!dev)
+		return NULL;
+
+	sp = netdev_priv(dev);
+	sp->dev = dev;
+
+	spin_lock_init(&sp->lock);
+
+	if (register_netdev(dev))
+		goto out_free;
+
+	return sp;
+
+out_free:
+	printk(KERN_WARNING "sp_alloc() - register_netdev() failure.\n");
+
+	free_netdev(dev);
+
+	return NULL;
+}
 
 /* Free a 6pack channel. */
 static inline void sp_free(struct sixpack *sp)
 {
-	/* Free all 6pack frame buffers. */
-	if (sp->rbuff)
-		kfree(sp->rbuff);
-	sp->rbuff = NULL;
-	if (sp->xbuff)
-		kfree(sp->xbuff);
-	sp->xbuff = NULL;
+	void * tmp;
 
-	if (!test_and_clear_bit(SIXPF_INUSE, &sp->flags))
-		printk(KERN_WARNING "%s: sp_free for already free unit.\n", sp->dev->name);
+	/* Free all 6pack frame buffers. */
+	if ((tmp = xchg(&sp->rbuff, NULL)) != NULL)
+		kfree(tmp);
+	if ((tmp = xchg(&sp->xbuff, NULL)) != NULL)
+		kfree(tmp);
 }
 
 
 /* Send one completely decapsulated IP datagram to the IP layer. */
 
-/* This is the routine that sends the received data to the kernel AX.25.
-   'cmd' is the KISS command. For AX.25 data, it is zero. */
+/*
+ * This is the routine that sends the received data to the kernel AX.25.
+ * 'cmd' is the KISS command. For AX.25 data, it is zero.
+ */
 
 static void sp_bump(struct sixpack *sp, char cmd)
 {
@@ -238,98 +417,60 @@
 	int count;
 	unsigned char *ptr;
 
-	count = sp->rcount+1;
+	count = sp->rcount + 1;
 
 	sp->stats.rx_bytes += count;
 
-	if ((skb = dev_alloc_skb(count)) == NULL) {
-		printk(KERN_DEBUG "%s: memory squeeze, dropping packet.\n", sp->dev->name);
-		sp->stats.rx_dropped++;
-		return;
-	}
+	if ((skb = dev_alloc_skb(count)) == NULL)
+		goto out_mem;
 
 	skb->dev = sp->dev;
 	ptr = skb_put(skb, count);
 	*ptr++ = cmd;	/* KISS command */
 
-	memcpy(ptr, (sp->cooked_buf)+1, count);
+	memcpy(ptr, sp->cooked_buf + 1, count);
 	skb->mac.raw = skb->data;
 	skb->protocol = htons(ETH_P_AX25);
 	netif_rx(skb);
 	sp->dev->last_rx = jiffies;
 	sp->stats.rx_packets++;
+
+	return;
+
+out_mem:
+	sp->stats.rx_dropped++;
 }
 
 
 /* ----------------------------------------------------------------------- */
 
-/* Encapsulate one AX.25 frame and stuff into a TTY queue. */
-static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
+/*
+ * We have a potential race on dereferencing tty->disc_data, because the tty
+ * layer provides no locking at all - thus one cpu could be running
+ * sixpack_receive_buf while another calls sixpack_close, which zeroes
+ * tty->disc_data and frees the memory that sixpack_receive_buf 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.
+ */
+static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+                                                                                
+static struct sixpack *sp_get(struct tty_struct *tty)
 {
-	unsigned char *p;
-	int actual, count;
-
-	if (len > sp->mtu) {	/* sp->mtu = AX25_MTU = max. PACLEN = 256 */
-		printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n", sp->dev->name);
-		sp->stats.tx_dropped++;
-		netif_start_queue(sp->dev);
-		return;
-	}
-
-	p = icp;
-
-	if (p[0] > 5) {
-		printk(KERN_DEBUG "%s: invalid KISS command -- dropped\n", sp->dev->name);
-		netif_start_queue(sp->dev);
-		return;
-	}
-
-	if ((p[0] != 0) && (len > 2)) {
-		printk(KERN_DEBUG "%s: KISS control packet too long -- dropped\n", sp->dev->name);
-		netif_start_queue(sp->dev);
-		return;
-	}
-
-	if ((p[0] == 0) && (len < 15)) {
-		printk(KERN_DEBUG "%s: bad AX.25 packet to transmit -- dropped\n", sp->dev->name);
-		netif_start_queue(sp->dev);
-		sp->stats.tx_dropped++;
-		return;
-	}
+	struct sixpack *sp;
 
-	count = encode_sixpack(p, (unsigned char *) sp->xbuff, len, sp->tx_delay);
-	sp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+	read_lock(&disc_data_lock);
+	sp = tty->disc_data;
+	if (sp)
+		atomic_inc(&sp->refcnt);
+	read_unlock(&disc_data_lock);
 
-	switch (p[0]) {
-		case 1:	sp->tx_delay = p[1];		return;
-		case 2:	sp->persistence = p[1];		return;
-		case 3: sp->slottime = p[1];		return;
-		case 4: /* ignored */			return;
-		case 5: sp->duplex = p[1];		return;
-	}
+	return sp;
+}
 
-	if (p[0] == 0) {
-		/* in case of fullduplex or DAMA operation, we don't take care
-		   about the state of the DCD or of any timers, as the determination
-		   of the correct time to send is the job of the AX.25 layer. We send
-		   immediately after data has arrived. */
-		if (sp->duplex == 1) {
-			sp->led_state = 0x70;
-			sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
-			sp->tx_enable = 1;
-			actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, count);
-			sp->xleft = count - actual;
-			sp->xhead = sp->xbuff + actual;
-			sp->led_state = 0x60;
-			sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
-		} else {
-			sp->xleft = count;
-			sp->xhead = sp->xbuff;
-			sp->status2 = count;
-			if (sp->duplex == 0)
-				sp_start_tx_timer(sp);
-		}
-	}
+static void sp_put(struct sixpack *sp)
+{
+	if (atomic_dec_and_test(&sp->refcnt))
+		up(&sp->dead_sem);
 }
 
 /*
@@ -338,22 +479,17 @@
  */
 static void sixpack_write_wakeup(struct tty_struct *tty)
 {
+	struct sixpack *sp = sp_get(tty);
 	int actual;
-	struct sixpack *sp = (struct sixpack *) tty->disc_data;
-
-	/* First make sure we're connected. */
-	if (!sp || sp->magic != SIXPACK_MAGIC ||
-	    !netif_running(sp->dev))
-		return;
 
 	if (sp->xleft <= 0)  {
 		/* Now serial buffer is almost free & we can start
 		 * transmission of another packet */
 		sp->stats.tx_packets++;
-		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 		sp->tx_enable = 0;
 		netif_wake_queue(sp->dev);
-		return;
+		goto out;
 	}
 
 	if (sp->tx_enable == 1) {
@@ -361,79 +497,34 @@
 		sp->xleft -= actual;
 		sp->xhead += actual;
 	}
-}
-
-/* ----------------------------------------------------------------------- */
-
-/* Encapsulate an IP datagram and kick it into a TTY queue. */
-
-static int sp_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct sixpack *sp = (struct sixpack *) dev->priv;
-
-	/* We were not busy, so we are now... :-) */
-	netif_stop_queue(dev);
-	sp->stats.tx_bytes += skb->len;
-	sp_encaps(sp, skb->data, skb->len);
-	dev_kfree_skb(skb);
-	return 0;
-}
-
-
-/* perform the persistence/slottime algorithm for CSMA access. If the persistence
-   check was successful, write the data to the serial driver. Note that in case
-   of DAMA operation, the data is not sent here. */
 
-static void sp_xmit_on_air(unsigned long channel)
-{
-	struct sixpack *sp = (struct sixpack *) channel;
-	int actual;
-	static unsigned char random;
-
-	random = random * 17 + 41;
-
-	if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
-		sp->led_state = 0x70;
-		sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
-		sp->tx_enable = 1;
-		actual = sp->tty->driver->write(sp->tty, 0, sp->xbuff, sp->status2);
-		sp->xleft -= actual;
-		sp->xhead += actual;
-		sp->led_state = 0x60;
-		sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
-		sp->status2 = 0;
-	} else
-		sp_start_tx_timer(sp);
+out:
+	sp_put(sp);
 }
 
+/* ----------------------------------------------------------------------- */
 
-/* Return the frame type ID */
-static int sp_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
-	  void *daddr, void *saddr, unsigned len)
+/* Open the low-level part of the 6pack channel. */
+static int sp_open(struct net_device *dev)
 {
-#ifdef CONFIG_INET
-	if (type != htons(ETH_P_AX25))
-		return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
-#endif
-	return 0;
-}
+	struct sixpack *sp = netdev_priv(dev);
+	char *rbuff, *xbuff = NULL;
+	int err = -ENOBUFS;
+	unsigned long len;
 
+	/* !!! length of the buffers. MTU is IP MTU, not PACLEN!  */
 
-static int sp_rebuild_header(struct sk_buff *skb)
-{
-#ifdef CONFIG_INET
-	return ax25_rebuild_header(skb);
-#else
-	return 0;
-#endif
-}
+	len = dev->mtu * 2;
 
+	rbuff = kmalloc(len + 4, GFP_KERNEL);
+	if (rbuff == NULL)
+		goto err_exit;
+
+	xbuff = kmalloc(len + 4, GFP_KERNEL);
+	if (xbuff == NULL)
+		goto err_exit;
 
-/* Open the low-level part of the 6pack channel. */
-static int sp_open(struct net_device *dev)
-{
-	struct sixpack *sp = (struct sixpack *) dev->priv;
-	unsigned long len;
+	spin_lock_bh(&sp->lock);
 
 	if (sp->tty == NULL)
 		return -ENODEV;
@@ -445,18 +536,8 @@
 	 * xbuff	Transmit buffer.
 	 */
 
-	/* !!! length of the buffers. MTU is IP MTU, not PACLEN!
-	 */
-
-	len = dev->mtu * 2;
-
-	if ((sp->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)
-		return -ENOMEM;
-
-	if ((sp->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL) {
-		kfree(sp->rbuff);
-		return -ENOMEM;
-	}
+	rbuff = xchg(&sp->rbuff, rbuff);
+	xbuff = xchg(&sp->xbuff, xbuff);
 
 	sp->mtu	     = AX25_MTU + 73;
 	sp->buffsize = len;
@@ -465,7 +546,7 @@
 	sp->rx_count_cooked = 0;
 	sp->xleft    = 0;
 
-	sp->flags   &= (1 << SIXPF_INUSE);      /* Clear ESCAPE & ERROR flags */
+	sp->flags	= 0;		/* Clear ESCAPE & ERROR flags */
 
 	sp->duplex = 0;
 	sp->tx_delay    = SIXP_TXDELAY;
@@ -482,49 +563,47 @@
 
 	init_timer(&sp->tx_t);
 	init_timer(&sp->resync_t);
-	return 0;
-}
 
+	spin_unlock_bh(&sp->lock);
 
-/* Close the low-level part of the 6pack channel. */
-static int sp_close(struct net_device *dev)
-{
-	struct sixpack *sp = (struct sixpack *) dev->priv;
-
-	if (sp->tty == NULL)
-		return -EBUSY;
+	err = 0;
 
-	sp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+err_exit:
+	if (xbuff)
+		kfree(xbuff);
+	if (rbuff)
+		kfree(rbuff);
 
-	netif_stop_queue(dev);
-	return 0;
+	return err;
 }
 
+
 static int sixpack_receive_room(struct tty_struct *tty)
 {
 	return 65536;  /* We can handle an infinite amount of data. :-) */
 }
 
-/* !!! receive state machine */
-
 /*
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
  * a block of 6pack data has been received, which can now be decapsulated
  * and sent on to some IP layer for further processing.
  */
-static void sixpack_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+static void sixpack_receive_buf(struct tty_struct *tty,
+	const unsigned char *cp, char *fp, int count)
 {
+	struct sixpack *sp;
 	unsigned char buf[512];
 	int count1;
 
-	struct sixpack *sp = (struct sixpack *) tty->disc_data;
+	if (!count)
+		return;
 
-	if (!sp || sp->magic != SIXPACK_MAGIC ||
-	    !netif_running(sp->dev) || !count)
+	sp = sp_get(tty);
+	if (!sp)
 		return;
 
-	memcpy(buf, cp, count<sizeof(buf)? count:sizeof(buf));
+	memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf));
 
 	/* Read the characters out of the buffer */
 
@@ -538,6 +617,67 @@
 		}
 	}
 	sixpack_decode(sp, buf, count1);
+
+	sp_put(sp);
+	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+	    && tty->driver->unthrottle)
+		tty->driver->unthrottle(tty);
+}
+
+/*
+ * Try to resync the TNC. Called by the resync timer defined in
+ * decode_prio_command
+ */
+
+static void resync_tnc(unsigned long channel)
+{
+	struct sixpack *sp = (struct sixpack *) channel;
+	struct net_device *dev = sp->dev;
+	static char resync_cmd = 0xe8;
+
+	printk(KERN_INFO "%s: resyncing TNC\n", dev->name);
+
+	/* clear any data that might have been received */
+
+	sp->rx_count = 0;
+	sp->rx_count_cooked = 0;
+
+	/* reset state machine */
+
+	sp->status = 1;
+	sp->status1 = 1;
+	sp->status2 = 0;
+	sp->tnc_ok = 0;
+
+	/* resync the TNC */
+
+	sp->led_state = 0x60;
+	sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
+	sp->tty->driver->write(sp->tty, 0, &resync_cmd, 1);
+
+
+	/* Start resync timer again -- the TNC might be still absent */
+
+	del_timer(&sp->resync_t);
+	sp->resync_t.data = (unsigned long) sp;
+	sp->resync_t.function = resync_tnc;
+	sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
+	add_timer(&sp->resync_t);
+}
+
+static inline int tnc_init(struct sixpack *sp)
+{
+	unsigned char inbyte = 0xe8;
+
+	sp->tty->driver->write(sp->tty, 0, &inbyte, 1);
+
+	del_timer(&sp->resync_t);
+	sp->resync_t.data = (unsigned long) sp;
+	sp->resync_t.function = resync_tnc;
+	sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
+	add_timer(&sp->resync_t);
+
+	return 0;
 }
 
 /*
@@ -549,37 +689,33 @@
  */
 static int sixpack_open(struct tty_struct *tty)
 {
-	struct sixpack *sp = (struct sixpack *) tty->disc_data;
-	int err;
+	struct sixpack *sp;
+	int err = 0;
 
-	/* First make sure we're not already connected. */
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
 
-	if (sp && sp->magic == SIXPACK_MAGIC)
-		return -EEXIST;
+	sp = sp_alloc();
+	if (!sp) {
+		err = -ENOMEM;
+		goto out;
+	}
 
-	/* OK.  Find a free 6pack channel to use. */
-	if ((sp = sp_alloc()) == NULL)
-		return -ENFILE;
 	sp->tty = tty;
-	tty->disc_data = sp;
-	if (tty->driver->flush_buffer)
-		tty->driver->flush_buffer(tty);
-
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
-	/* Restore default settings */
-	sp->dev->type = ARPHRD_AX25;
+	atomic_set(&sp->refcnt, 1);
+	init_MUTEX_LOCKED(&sp->dead_sem);
 
 	/* Perform the low-level 6pack initialization. */
 	if ((err = sp_open(sp->dev)))
-		return err;
+		goto out;
 
 	/* Done.  We have linked the TTY line to a channel. */
+	tty->disc_data = sp;
 
 	tnc_init(sp);
 
-	return sp->dev->base_addr;
+out:
+	return err;
 }
 
 
@@ -593,102 +729,93 @@
 {
 	struct sixpack *sp = (struct sixpack *) tty->disc_data;
 
-	/* First make sure we're connected. */
-	if (!sp || sp->magic != SIXPACK_MAGIC)
+	write_lock(&disc_data_lock);
+	sp = tty->disc_data;
+	tty->disc_data = 0;
+	write_unlock(&disc_data_lock);
+	if (sp == 0)
 		return;
 
-	rtnl_lock();
-	dev_close(sp->dev);
+	/*
+	 * We have now ensured that nobody can start using ap from now on, but
+	 * we have to wait for all existing users to finish.
+	 */
+	if (!atomic_dec_and_test(&sp->refcnt))
+		down(&sp->dead_sem);
 
 	del_timer(&sp->tx_t);
 	del_timer(&sp->resync_t);
 
-	tty->disc_data = 0;
-	sp->tty = NULL;
-
 	sp_free(sp);
-	unregister_netdevice(sp->dev);
-	rtnl_unlock();
+	unregister_netdev(sp->dev);
 }
 
-
-static struct net_device_stats *sp_get_stats(struct net_device *dev)
-{
-	struct sixpack *sp = (struct sixpack *) dev->priv;
-	return &sp->stats;
-}
-
-
 static int sp_set_mac_address(struct net_device *dev, void *addr)
 {
 	return copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN) ? -EFAULT : 0;
 }
 
-static int sp_set_dev_mac_address(struct net_device *dev, void *addr)
-{
-	struct sockaddr *sa = addr;
-	memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
-	return 0;
-}
-
-
 /* Perform I/O control on an active 6pack channel. */
-static int sixpack_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
+static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
+	unsigned int cmd, unsigned long arg)
 {
-	struct sixpack *sp = (struct sixpack *) tty->disc_data;
-	unsigned int tmp;
+	struct sixpack *sp = sp_get(tty);
+	unsigned int tmp, err;
 
-	/* First make sure we're connected. */
-	if (!sp || sp->magic != SIXPACK_MAGIC)
-		return -EINVAL;
+	if (!sp)
+		return -ENXIO;
 
 	switch(cmd) {
 	case SIOCGIFNAME:
-		return copy_to_user(arg, sp->dev->name, strlen(sp->dev->name) + 1) ? -EFAULT : 0;
+		err = copy_to_user((void *) arg, sp->dev->name,
+		                   strlen(sp->dev->name) + 1) ? -EFAULT : 0;
+		break;
 
 	case SIOCGIFENCAP:
-		return put_user(0, (int *)arg);
+		err = put_user(0, (int *)arg);
+		break;
 
 	case SIOCSIFENCAP:
-		if (get_user(tmp, (int *) arg))
-			return -EFAULT;
+		if (get_user(tmp, (int *) arg)) {
+			err = -EFAULT;
+			break;
+		}
 
 		sp->mode = tmp;
 		sp->dev->addr_len        = AX25_ADDR_LEN;	  /* sizeof an AX.25 addr */
 		sp->dev->hard_header_len = AX25_KISS_HEADER_LEN + AX25_MAX_HEADER_LEN + 3;
 		sp->dev->type            = ARPHRD_AX25;
 
-		return 0;
+		err = 0;
+		break;
 
 	 case SIOCSIFHWADDR:
-		return sp_set_mac_address(sp->dev, arg);
+		err = sp_set_mac_address(sp->dev, (void *) arg);
+		break;
 
 	/* Allow stty to read, but not set, the serial port */
 	case TCGETS:
 	case TCGETA:
-		return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg);
+		err = n_tty_ioctl(tty, (struct file *) file, cmd, arg);
+		break;
 
 	default:
 		return -ENOIOCTLCMD;
 	}
-}
 
-static int sp_open_dev(struct net_device *dev)
-{
-	struct sixpack *sp = (struct sixpack *) dev->priv;
-	if (sp->tty == NULL)
-		return -ENODEV;
-	return 0;
+	sp_put(sp);
+
+	return err;
 }
 
 /* Fill in our line protocol discipline */
 static struct tty_ldisc sp_ldisc = {
-	.magic	= TTY_LDISC_MAGIC,
+	.owner		= THIS_MODULE,
+	.magic		= TTY_LDISC_MAGIC,
 	.name		= "6pack",
 	.open		= sixpack_open,
-	.close	= sixpack_close,
-	.ioctl	= (int (*)(struct tty_struct *, struct file *,
-			unsigned int, unsigned long)) sixpack_ioctl,
+	.close		= sixpack_close,
+	.ioctl		= sixpack_ioctl,
 	.receive_buf	= sixpack_receive_buf,
 	.receive_room	= sixpack_receive_room,
 	.write_wakeup	= sixpack_write_wakeup,
@@ -696,34 +823,18 @@
 
 /* Initialize 6pack control device -- register 6pack line discipline */
 
-static char msg_banner[]  __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n";
-static char msg_nomem[]   __initdata = KERN_ERR  "6pack: can't allocate sixpack_ctrls[] array! No 6pack available.\n";
+static char msg_banner[]  __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION "\n";
 static char msg_regfail[] __initdata = KERN_ERR  "6pack: can't register line discipline (err = %d)\n";
 
 static int __init sixpack_init_driver(void)
 {
 	int status;
 
-	/* Do sanity checks on maximum device parameter. */
-	if (sixpack_maxdev < 4)
-		sixpack_maxdev = 4;
-
-	printk(msg_banner, sixpack_maxdev);
-
-	sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
-	if (sixpack_ctrls == NULL) {
-		printk(msg_nomem);
-		return -ENOMEM;
-	}
-
-	/* Clear the pointer array, we allocate devices when we need them */
-	memset(sixpack_ctrls, 0, sizeof(void*)*sixpack_maxdev); /* Pointers */
+	printk(msg_banner);
 
 	/* Register the provided line protocol discipline */
-	if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0) {
+	if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0)
 		printk(msg_regfail, status);
-		kfree(sixpack_ctrls);
-	}
 
 	return status;
 }
@@ -732,36 +843,16 @@
 
 static void __exit sixpack_exit_driver(void)
 {
-	int i;
-
-	if ((i = tty_register_ldisc(N_6PACK, NULL)))
-		printk(msg_unregfail, i);
+	int ret;
 
-	for (i = 0; i < sixpack_maxdev; i++) {
-		if (sixpack_ctrls[i]) {
-			/*
-			* VSV = if dev->start==0, then device
-			* unregistered while close proc.
-			*/
-			if (netif_running(&sixpack_ctrls[i]->dev))
-				 unregister_netdev(&sixpack_ctrls[i]->dev);
-
-			kfree(sixpack_ctrls[i]);
-		}
-	}
-	kfree(sixpack_ctrls);
+	if ((ret = tty_register_ldisc(N_6PACK, NULL)))
+		printk(msg_unregfail, ret);
 }
 
-
 /* Initialize the 6pack driver.  Called by DDI. */
 static int sixpack_init(struct net_device *dev)
 {
-	struct sixpack *sp = (struct sixpack *) dev->priv;
-
-	static char ax25_bcast[AX25_ADDR_LEN] =
-		{'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
-	static char ax25_test[AX25_ADDR_LEN] =
-		{'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
+	struct sixpack *sp = netdev_priv(dev);
 
 	if (sp == NULL)		/* Allocation failed ?? */
 		return -ENODEV;
@@ -769,52 +860,15 @@
 	/* Set up the "6pack Control Block". (And clear statistics) */
 
 	memset(sp, 0, sizeof (struct sixpack));
-	sp->magic  = SIXPACK_MAGIC;
 	sp->dev	   = dev;
 
-	/* Finish setting up the DEVICE info. */
-	dev->mtu		= SIXP_MTU;
-	dev->hard_start_xmit	= sp_xmit;
-	dev->open		= sp_open_dev;
-	dev->stop		= sp_close;
-	dev->hard_header	= sp_header;
-	dev->get_stats	        = sp_get_stats;
-	dev->set_mac_address    = sp_set_dev_mac_address;
-	dev->hard_header_len	= AX25_MAX_HEADER_LEN;
-	dev->addr_len		= AX25_ADDR_LEN;
-	dev->type		= ARPHRD_AX25;
-	dev->tx_queue_len	= 10;
-	dev->rebuild_header	= sp_rebuild_header;
-	dev->tx_timeout		= NULL;
-
-	memcpy(dev->broadcast, ax25_bcast, AX25_ADDR_LEN);	/* Only activated in AX.25 mode */
-	memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN);	/*    ""      ""       ""    "" */
-
-	/* New-style flags. */
-	dev->flags		= 0;
-
 	return 0;
 }
 
-
-
-
-/* ----> 6pack timer interrupt handler and friends. <---- */
-static void sp_start_tx_timer(struct sixpack *sp)
-{
-	int when = sp->slottime;
-
-	del_timer(&sp->tx_t);
-	sp->tx_t.data = (unsigned long) sp;
-	sp->tx_t.function = sp_xmit_on_air;
-	sp->tx_t.expires = jiffies + ((when+1)*HZ)/100;
-	add_timer(&sp->tx_t);
-}
-
-
 /* encode an AX.25 packet into 6pack */
 
-static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw, int length, unsigned char tx_delay)
+static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
+	int length, unsigned char tx_delay)
 {
 	int count = 0;
 	unsigned char checksum = 0, buf[400];
@@ -849,47 +903,28 @@
 	return raw_count;
 }
 
+/* decode 4 sixpack-encoded bytes into 3 data bytes */
 
-/* decode a 6pack packet */
-
-static void
-sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
-{
-	unsigned char inbyte;
-	int count1;
-
-	for (count1 = 0; count1 < count; count1++) {
-		inbyte = pre_rbuff[count1];
-		if (inbyte == SIXP_FOUND_TNC) {
-			printk(KERN_INFO "6pack: TNC found.\n");
-			sp->tnc_ok = 1;
-			del_timer(&sp->resync_t);
-		}
-		if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
-			decode_prio_command(inbyte, sp);
-		else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
-			decode_std_command(inbyte, sp);
-		else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
-			decode_data(inbyte, sp);
-	}
-}
-
-static int tnc_init(struct sixpack *sp)
+static void decode_data(unsigned char inbyte, struct sixpack *sp)
 {
-	unsigned char inbyte = 0xe8;
+	unsigned char *buf;
 
-	sp->tty->driver->write(sp->tty, 0, &inbyte, 1);
+	if (sp->rx_count != 3) {
+		sp->raw_buf[sp->rx_count++] = inbyte;
 
-	del_timer(&sp->resync_t);
-	sp->resync_t.data = (unsigned long) sp;
-	sp->resync_t.function = resync_tnc;
-	sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
-	add_timer(&sp->resync_t);
+		return;
+	}
 
-	return 0;
+	buf = sp->raw_buf;
+	sp->cooked_buf[sp->rx_count_cooked++] =
+		buf[0] | ((buf[1] << 2) & 0xc0);
+	sp->cooked_buf[sp->rx_count_cooked++] =
+		(buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
+	sp->cooked_buf[sp->rx_count_cooked++] =
+		(buf[2] & 0x03) | (inbyte << 2);
+	sp->rx_count = 0;
 }
 
-
 /* identify and execute a 6pack priority command byte */
 
 static void decode_prio_command(unsigned char cmd, struct sixpack *sp)
@@ -916,8 +951,7 @@
 				cmd &= !SIXP_RX_DCD_MASK;
 		}
 		sp->status = cmd & SIXP_PRIO_DATA_MASK;
-	}
-	else { /* output watchdog char if idle */
+	} else { /* output watchdog char if idle */
 		if ((sp->status2 != 0) && (sp->duplex == 1)) {
 			sp->led_state = 0x70;
 			sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
@@ -948,46 +982,6 @@
 	sp->status1 = cmd & SIXP_PRIO_DATA_MASK;
 }
 
-/* try to resync the TNC. Called by the resync timer defined in
-  decode_prio_command */
-
-static void resync_tnc(unsigned long channel)
-{
-	static char resync_cmd = 0xe8;
-	struct sixpack *sp = (struct sixpack *) channel;
-
-	printk(KERN_INFO "6pack: resyncing TNC\n");
-
-	/* clear any data that might have been received */
-
-	sp->rx_count = 0;
-	sp->rx_count_cooked = 0;
-
-	/* reset state machine */
-
-	sp->status = 1;
-	sp->status1 = 1;
-	sp->status2 = 0;
-	sp->tnc_ok = 0;
-
-	/* resync the TNC */
-
-	sp->led_state = 0x60;
-	sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
-	sp->tty->driver->write(sp->tty, 0, &resync_cmd, 1);
-
-
-	/* Start resync timer again -- the TNC might be still absent */
-
-	del_timer(&sp->resync_t);
-	sp->resync_t.data = (unsigned long) sp;
-	sp->resync_t.function = resync_tnc;
-	sp->resync_t.expires = jiffies + SIXP_RESYNC_TIMEOUT;
-	add_timer(&sp->resync_t);
-}
-
-
-
 /* identify and execute a standard 6pack command byte */
 
 static void decode_std_command(unsigned char cmd, struct sixpack *sp)
@@ -997,67 +991,70 @@
 
 	channel = cmd & SIXP_CHN_MASK;
 	switch (cmd & SIXP_CMD_MASK) {     /* normal command */
-		case SIXP_SEOF:
-			if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
-				if ((sp->status & SIXP_RX_DCD_MASK) ==
-					SIXP_RX_DCD_MASK) {
-					sp->led_state = 0x68;
-					sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
-				}
-			} else {
-				sp->led_state = 0x60;
-				/* fill trailing bytes with zeroes */
+	case SIXP_SEOF:
+		if ((sp->rx_count == 0) && (sp->rx_count_cooked == 0)) {
+			if ((sp->status & SIXP_RX_DCD_MASK) ==
+				SIXP_RX_DCD_MASK) {
+				sp->led_state = 0x68;
 				sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
-				rest = sp->rx_count;
-				if (rest != 0)
-					 for (i = rest; i <= 3; i++)
-						decode_data(0, sp);
-				if (rest == 2)
-					sp->rx_count_cooked -= 2;
-				else if (rest == 3)
-					sp->rx_count_cooked -= 1;
-				for (i = 0; i < sp->rx_count_cooked; i++)
-					checksum += sp->cooked_buf[i];
-				if (checksum != SIXP_CHKSUM) {
-					printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
-				} else {
-					sp->rcount = sp->rx_count_cooked-2;
-					sp_bump(sp, 0);
-				}
-				sp->rx_count_cooked = 0;
 			}
-			break;
-		case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
-			break;
-		case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
-			break;
-		case SIXP_RX_BUF_OVL:
-			printk(KERN_DEBUG "6pack: RX buffer overflow\n");
+		} else {
+			sp->led_state = 0x60;
+			/* fill trailing bytes with zeroes */
+			sp->tty->driver->write(sp->tty, 0, &sp->led_state, 1);
+			rest = sp->rx_count;
+			if (rest != 0)
+				 for (i = rest; i <= 3; i++)
+					decode_data(0, sp);
+			if (rest == 2)
+				sp->rx_count_cooked -= 2;
+			else if (rest == 3)
+				sp->rx_count_cooked -= 1;
+			for (i = 0; i < sp->rx_count_cooked; i++)
+				checksum += sp->cooked_buf[i];
+			if (checksum != SIXP_CHKSUM) {
+				printk(KERN_DEBUG "6pack: bad checksum %2.2x\n", checksum);
+			} else {
+				sp->rcount = sp->rx_count_cooked-2;
+				sp_bump(sp, 0);
+			}
+			sp->rx_count_cooked = 0;
+		}
+		break;
+	case SIXP_TX_URUN: printk(KERN_DEBUG "6pack: TX underrun\n");
+		break;
+	case SIXP_RX_ORUN: printk(KERN_DEBUG "6pack: RX overrun\n");
+		break;
+	case SIXP_RX_BUF_OVL:
+		printk(KERN_DEBUG "6pack: RX buffer overflow\n");
 	}
 }
 
-/* decode 4 sixpack-encoded bytes into 3 data bytes */
+/* decode a 6pack packet */
 
-static void decode_data(unsigned char inbyte, struct sixpack *sp)
+static void
+sixpack_decode(struct sixpack *sp, unsigned char pre_rbuff[], int count)
 {
-	unsigned char *buf;
+	unsigned char inbyte;
+	int count1;
 
-	if (sp->rx_count != 3)
-		sp->raw_buf[sp->rx_count++] = inbyte;
-	else {
-		buf = sp->raw_buf;
-		sp->cooked_buf[sp->rx_count_cooked++] =
-			buf[0] | ((buf[1] << 2) & 0xc0);
-		sp->cooked_buf[sp->rx_count_cooked++] =
-			(buf[1] & 0x0f) | ((buf[2] << 2) & 0xf0);
-		sp->cooked_buf[sp->rx_count_cooked++] =
-			(buf[2] & 0x03) | (inbyte << 2);
-		sp->rx_count = 0;
+	for (count1 = 0; count1 < count; count1++) {
+		inbyte = pre_rbuff[count1];
+		if (inbyte == SIXP_FOUND_TNC) {
+			printk(KERN_INFO "6pack: TNC found.\n");
+			sp->tnc_ok = 1;
+			del_timer(&sp->resync_t);
+		}
+		if ((inbyte & SIXP_PRIO_CMD_MASK) != 0)
+			decode_prio_command(inbyte, sp);
+		else if ((inbyte & SIXP_STD_CMD_MASK) != 0)
+			decode_std_command(inbyte, sp);
+		else if ((sp->status & SIXP_RX_DCD_MASK) == SIXP_RX_DCD_MASK)
+			decode_data(inbyte, sp);
 	}
 }
 
-
-MODULE_AUTHOR("Andreas Könsgen <ajk@ccac.rwth-aachen.de>");
+MODULE_AUTHOR("Ralf Baechle DO1GRB <ralf@linux-mips.org>");
 MODULE_DESCRIPTION("6pack driver for AX.25");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_6PACK);
diff -Nru a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
--- a/drivers/net/ibmveth.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/ibmveth.c	Wed Mar 17 19:29:09 2004
@@ -527,7 +527,10 @@
 	ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
 	if((rc = request_irq(netdev->irq, &ibmveth_interrupt, 0, netdev->name, netdev)) != 0) {
 		ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
-		h_free_logical_lan(adapter->vdev->unit_address);
+		do {
+			rc = h_free_logical_lan(adapter->vdev->unit_address);
+		} while H_isLongBusy(rc);
+
 		ibmveth_cleanup(adapter);
 		return rc;
 	}
@@ -556,7 +559,9 @@
 	cancel_delayed_work(&adapter->replenish_task);
 	flush_scheduled_work();
 
-	lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
+	do {
+		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
+	} while H_isLongBusy(lpar_rc);
 
 	if(lpar_rc != H_Success)
 	{
@@ -617,6 +622,8 @@
 	union ibmveth_buf_desc desc[IbmVethMaxSendFrags];
 	unsigned long lpar_rc;
 	int nfrags = 0, curfrag;
+	unsigned long correlator;
+	unsigned int retry_count;
 
 	if ((skb_shinfo(skb)->nr_frags + 1) > IbmVethMaxSendFrags) {
 		adapter->stats.tx_dropped++;
@@ -674,8 +681,8 @@
 	}
 
 	/* send the frame. Arbitrarily set retrycount to 1024 */
-	unsigned long correlator = 0;
-	unsigned int retry_count = 1024;
+	correlator = 0;
+	retry_count = 1024;
 	do {
 		lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
 					     desc[0].desc,
diff -Nru a/drivers/net/loopback.c b/drivers/net/loopback.c
--- a/drivers/net/loopback.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/loopback.c	Wed Mar 17 19:29:09 2004
@@ -123,7 +123,7 @@
  */
 static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_device_stats *stats = netdev_priv(dev);
+	struct net_device_stats *stats = dev->priv;
 
 	skb_orphan(skb);
 
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/natsemi.c	Wed Mar 17 19:29:09 2004
@@ -175,6 +175,8 @@
 #define DRV_VERSION	"1.07+LK1.0.17"
 #define DRV_RELDATE	"Sep 27, 2002"
 
+#define RX_OFFSET	2
+
 /* Updated to recommendations in pci-skeleton v2.03. */
 
 /* The user-configurable values.
@@ -1467,13 +1469,14 @@
 		struct sk_buff *skb;
 		int entry = np->dirty_rx % RX_RING_SIZE;
 		if (np->rx_skbuff[entry] == NULL) {
-			skb = dev_alloc_skb(np->rx_buf_sz);
+			unsigned int buflen = np->rx_buf_sz + RX_OFFSET;
+			skb = dev_alloc_skb(buflen);
 			np->rx_skbuff[entry] = skb;
 			if (skb == NULL)
 				break; /* Better luck next round. */
 			skb->dev = dev; /* Mark as being used by this device. */
 			np->rx_dma[entry] = pci_map_single(np->pci_dev,
-				skb->data, skb->len, PCI_DMA_FROMDEVICE);
+				skb->tail, buflen, PCI_DMA_FROMDEVICE);
 			np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]);
 		}
 		np->rx_ring[entry].cmd_status = cpu_to_le32(np->rx_buf_sz);
@@ -1543,6 +1546,7 @@
 static void drain_ring(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
+	unsigned int buflen = np->rx_buf_sz + RX_OFFSET;
 	int i;
 
 	/* Free all the skbuffs in the Rx queue. */
@@ -1551,7 +1555,7 @@
 		np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
 		if (np->rx_skbuff[i]) {
 			pci_unmap_single(np->pci_dev,
-				np->rx_dma[i], np->rx_skbuff[i]->len,
+				np->rx_dma[i], buflen,
 				PCI_DMA_FROMDEVICE);
 			dev_kfree_skb(np->rx_skbuff[i]);
 		}
@@ -1747,6 +1751,7 @@
 	int entry = np->cur_rx % RX_RING_SIZE;
 	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 + RX_OFFSET;
 
 	/* If the driver owns the next entry it's a new packet. Send it up. */
 	while (desc_status < 0) { /* e.g. & DescOwn */
@@ -1785,13 +1790,13 @@
 			/* Check if the packet is long enough to accept
 			 * without copying to a minimally-sized skbuff. */
 			if (pkt_len < rx_copybreak
-			    && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+			    && (skb = dev_alloc_skb(pkt_len + RX_OFFSET)) != NULL) {
 				skb->dev = dev;
 				/* 16 byte align the IP header */
-				skb_reserve(skb, 2);
+				skb_reserve(skb, RX_OFFSET);
 				pci_dma_sync_single_for_cpu(np->pci_dev,
 					np->rx_dma[entry],
-					np->rx_skbuff[entry]->len,
+					buflen,
 					PCI_DMA_FROMDEVICE);
 #if HAS_IP_COPYSUM
 				eth_copy_and_sum(skb,
@@ -1803,12 +1808,11 @@
 #endif
 				pci_dma_sync_single_for_device(np->pci_dev,
 					np->rx_dma[entry],
-					np->rx_skbuff[entry]->len,
+					buflen,
 					PCI_DMA_FROMDEVICE);
 			} else {
 				pci_unmap_single(np->pci_dev, np->rx_dma[entry],
-					np->rx_skbuff[entry]->len,
-					PCI_DMA_FROMDEVICE);
+					buflen, PCI_DMA_FROMDEVICE);
 				skb_put(skb = np->rx_skbuff[entry], pkt_len);
 				np->rx_skbuff[entry] = NULL;
 			}
diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
--- a/drivers/net/tulip/de2104x.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/net/tulip/de2104x.c	Wed Mar 17 19:29:10 2004
@@ -28,8 +28,8 @@
  */
 
 #define DRV_NAME		"de2104x"
-#define DRV_VERSION		"0.6"
-#define DRV_RELDATE		"Sep 1, 2003"
+#define DRV_VERSION		"0.7"
+#define DRV_RELDATE		"Mar 17, 2004"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -303,7 +303,6 @@
 	struct net_device_stats net_stats;
 
 	struct pci_dev		*pdev;
-	u32			macmode;
 
 	u16			setup_frame[DE_SETUP_FRAME_WORDS];
 
@@ -732,7 +731,7 @@
 	struct de_desc *txd;
 	struct de_desc *dummy_txd = NULL;
 
-	macmode = de->macmode & ~(AcceptAllMulticast | AcceptAllPhys);
+	macmode = dr32(MacMode) & ~(AcceptAllMulticast | AcceptAllPhys);
 
 	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
 		macmode |= AcceptAllMulticast | AcceptAllPhys;
@@ -805,10 +804,8 @@
 	dw32(TxPoll, NormalTxPoll);
 
 out:
-	if (macmode != de->macmode) {
-		dw32 (MacMode, macmode);
-		de->macmode = macmode;
-	}
+	if (macmode != dr32(MacMode))
+		dw32(MacMode, macmode);
 }
 
 static void de_set_rx_mode (struct net_device *dev)
@@ -923,6 +920,7 @@
 static void de_set_media (struct de_private *de)
 {
 	unsigned media = de->media_type;
+	u32 macmode = dr32(MacMode);
 
 	if (de_is_running(de))
 		BUG();
@@ -940,9 +938,9 @@
 	mdelay(10);
 
 	if (media == DE_MEDIA_TP_FD)
-		de->macmode |= FullDuplex;
+		macmode |= FullDuplex;
 	else
-		de->macmode &= ~FullDuplex;
+		macmode &= ~FullDuplex;
 	
 	if (netif_msg_link(de)) {
 		printk(KERN_INFO "%s: set link %s\n"
@@ -951,9 +949,11 @@
 		       de->dev->name, media_name[media],
 		       de->dev->name, dr32(MacMode), dr32(SIAStatus),
 		       dr32(CSR13), dr32(CSR14), dr32(CSR15),
-		       de->dev->name, de->macmode, de->media[media].csr13,
+		       de->dev->name, macmode, de->media[media].csr13,
 		       de->media[media].csr14, de->media[media].csr15);
 	}
+	if (macmode != dr32(MacMode))
+		dw32(MacMode, macmode);
 }
 
 static void de_next_media (struct de_private *de, u32 *media,
@@ -1173,18 +1173,18 @@
 	u32 status, tmp;
 
 	/*
-	 * Reset MAC.  Copied from de4x5.c.
+	 * Reset MAC.  de4x5.c and tulip.c examined for "advice"
+	 * in this area.
 	 */
 
-	tmp = dr32 (BusMode);
-	if (tmp == 0xffffffff)
-		return -ENODEV;
-	mdelay (1);
+	if (dr32(BusMode) == 0xffffffff)
+		return -EBUSY;
 
-	dw32 (BusMode, tmp | CmdReset);
+	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
+	dw32 (BusMode, CmdReset);
 	mdelay (1);
 
-	dw32 (BusMode, tmp);
+	dw32 (BusMode, de_bus_mode);
 	mdelay (1);
 
 	for (tmp = 0; tmp < 5; tmp++) {
@@ -1235,11 +1235,12 @@
 static int de_init_hw (struct de_private *de)
 {
 	struct net_device *dev = de->dev;
+	u32 macmode;
 	int rc;
 
 	de_adapter_wake(de);
 	
-	de->macmode = dr32(MacMode) & ~MacModeClear;
+	macmode = dr32(MacMode) & ~MacModeClear;
 
 	rc = de_reset_mac(de);
 	if (rc)
@@ -1250,7 +1251,7 @@
 	dw32(RxRingAddr, de->ring_dma);
 	dw32(TxRingAddr, de->ring_dma + (sizeof(struct de_desc) * DE_RX_RING_SIZE));
 
-	dw32(MacMode, RxTx | de->macmode);
+	dw32(MacMode, RxTx | macmode);
 
 	dr32(RxMissed); /* self-clearing */
 
@@ -1501,7 +1502,7 @@
 		break;
 	}
 	
-	if (de->macmode & FullDuplex)
+	if (dr32(MacMode) & FullDuplex)
 		ecmd->duplex = DUPLEX_FULL;
 	else
 		ecmd->duplex = DUPLEX_HALF;
diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
--- a/drivers/net/tulip/tulip_core.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/tulip/tulip_core.c	Wed Mar 17 19:29:09 2004
@@ -253,8 +253,9 @@
 static struct net_device_stats *tulip_get_stats(struct net_device *dev);
 static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
+#ifdef CONFIG_NET_POLL_CONTROLLER
 static void poll_tulip(struct net_device *dev);
-
+#endif
 
 static void tulip_set_power_state (struct tulip_private *tp,
 				   int sleep, int snooze)
diff -Nru a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
--- a/drivers/net/wireless/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/Kconfig	Wed Mar 17 19:29:09 2004
@@ -307,18 +307,18 @@
 	 It has basic support for Linux wireless extensions and initial
 	 micro support for ethtool.
 
-comment "Prism GT/Duette 802.11(a/b/g) PCI/PCMCIA support"
+comment "Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support"
 	depends on NET_RADIO && PCI
 config PRISM54
-	tristate 'Intersil Prism GT/Duette/Indigo PCI/PCMCIA' 
+	tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus' 
 	depends on PCI && NET_RADIO && EXPERIMENTAL && HOTPLUG
 	select FW_LOADER
 	---help---
 	  Enable PCI and Cardbus support for the following chipset based cards:
 
-	  ISL3880 - Prism GT		802.11 b/g
-	  ISL3877 - Prism Indigo	802.11 a
-	  ISL3890 - Prism Duette	802.11 a/b/g
+	  ISL3880 - Prism GT            802.11 b/g
+	  ISL3877 - Prism Indigo        802.11 a
+	  ISL3890 - Prism Duette        802.11 a/b/g
 	  
 	  For a complete list of supported cards visit <http://prism54.org>.
 	  Here is the latest confirmed list of supported cards:
@@ -335,8 +335,9 @@
 	  Peabird WLG-PCI PCI Card
 	  Sitecom WL-100i Cardbus Card
 	  Sitecom WL-110i PCI Card
-	  SMC2802W - EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card
-	  SMC2835W - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
+	  SMC2802W -    EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card
+	  SMC2835W -    EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
+	  SMC2835W-V2 - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
 	  Z-Com XG-900 PCI Card
 	  Zyxel G-100 Cardbus Card
 
diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
--- a/drivers/net/wireless/prism54/isl_ioctl.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/prism54/isl_ioctl.c	Wed Mar 17 19:29:09 2004
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
 #include <linux/pci.h>
+#include <linux/moduleparam.h>
 
 #include <asm/uaccess.h>
 
@@ -44,26 +45,26 @@
 static int init_conformance = CARD_DEFAULT_CONFORMANCE;
 static int init_mlme = CARD_DEFAULT_MLME_MODE;
 
-MODULE_PARM(init_mode, "i");
+module_param(init_mode, int, 0);
 MODULE_PARM_DESC(init_mode,
 		 "Set card mode:\n0: Auto\n1: Ad-Hoc\n2: Managed Client (Default)\n3: Master / Access Point\n4: Repeater (Not supported yet)\n5: Secondary (Not supported yet)\n6: Monitor");
 
-MODULE_PARM(init_channel, "i");
+module_param(init_channel, int, 0);
 MODULE_PARM_DESC(init_channel,
 		 "Check `iwpriv ethx channel` for available channels");
 
-MODULE_PARM(init_wep, "i");
-MODULE_PARM(init_filter, "i");
+module_param(init_wep, int, 0);
+module_param(init_filter, int, 0);
 
-MODULE_PARM(init_authen, "i");
+module_param(init_authen, int, 0);
 MODULE_PARM_DESC(init_authen,
 		 "Authentication method. Can be of seven types:\n0 0x0000: None\n1 0x0001: DOT11_AUTH_OS (Default)\n2 0x0002: DOT11_AUTH_SK\n3 0x0003: DOT11_AUTH_BOTH");
 
-MODULE_PARM(init_dot1x, "i");
+module_param(init_dot1x, int, 0);
 MODULE_PARM_DESC(init_dot1x,
 		 "\n0: None/not set	(Default)\n1: DOT11_DOT1X_AUTHENABLED\n2: DOT11_DOT1X_KEYTXENABLED");
 
-MODULE_PARM(init_mlme, "i");
+module_param(init_mlme, int, 0);
 MODULE_PARM_DESC(init_mlme,
 		 "Sets the MAC layer management entity (MLME) mode of operation,\n0: DOT11_MLME_AUTO (Default)\n1: DOT11_MLME_INTERMEDIATE\n2: DOT11_MLME_EXTENDED");
 
@@ -250,7 +251,7 @@
 struct iw_statistics *
 prism54_get_wireless_stats(struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	/* If the stats are being updated return old data */
 	if (down_trylock(&priv->stats_sem) == 0) {
@@ -277,7 +278,7 @@
 prism54_commit(struct net_device *ndev, struct iw_request_info *info,
 	       char *cwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	/* simply re-set the last set SSID, this should commit most stuff */
 
@@ -293,7 +294,7 @@
 prism54_get_name(struct net_device *ndev, struct iw_request_info *info,
 		 char *cwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	char *capabilities;
 	union oid_res_t r;
 	int rvalue;
@@ -324,7 +325,7 @@
 prism54_set_freq(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_freq *fwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	int rvalue;
 	u32 c = 0;
 
@@ -363,7 +364,7 @@
 prism54_get_freq(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_freq *fwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	union oid_res_t r;
 	int rvalue;
 
@@ -379,7 +380,7 @@
 prism54_set_mode(struct net_device *ndev, struct iw_request_info *info,
 		 __u32 * uwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	u32 mlmeautolevel = CARD_DEFAULT_MLME_MODE;
 
 	/* Let's see if the user passed a valid Linux Wireless mode */
@@ -420,7 +421,7 @@
 prism54_get_mode(struct net_device *ndev, struct iw_request_info *info,
 		 __u32 * uwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	BUG_ON((priv->iw_mode < IW_MODE_AUTO) || (priv->iw_mode >
 						  IW_MODE_MONITOR));
@@ -438,7 +439,7 @@
 prism54_set_sens(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	u32 sens;
 
 	/* by default  the card sets this to 20. */
@@ -452,7 +453,7 @@
 prism54_get_sens(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	union oid_res_t r;
 	int rvalue;
 
@@ -470,7 +471,7 @@
 		  struct iw_point *dwrq, char *extra)
 {
 	struct iw_range *range = (struct iw_range *) extra;
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	char *data;
 	int i, m, rvalue;
 	struct obj_frequencies *freq;
@@ -576,7 +577,7 @@
 prism54_set_wap(struct net_device *ndev, struct iw_request_info *info,
 		struct sockaddr *awrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	char bssid[6];
 	int rvalue;
 
@@ -598,7 +599,7 @@
 prism54_get_wap(struct net_device *ndev, struct iw_request_info *info,
 		struct sockaddr *awrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	union oid_res_t r;
 	int rvalue;
 
@@ -630,7 +631,7 @@
 {
 	struct iw_event iwe;	/* Temporary buffer */
 	short cap;
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	/* The first entry must be the MAC address */
 	memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);
@@ -721,7 +722,7 @@
 prism54_get_scan(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	int i, rvalue;
 	struct obj_bsslist *bsslist;
 	u32 noise = 0;
@@ -762,7 +763,7 @@
 prism54_set_essid(struct net_device *ndev, struct iw_request_info *info,
 		  struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct obj_ssid essid;
 
 	memset(essid.octets, 0, 33);
@@ -789,7 +790,7 @@
 prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
 		  struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct obj_ssid *essid;
 	union oid_res_t r;
 	int rvalue;
@@ -819,7 +820,7 @@
 prism54_set_nick(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	if (dwrq->length > IW_ESSID_MAX_SIZE)
 		return -E2BIG;
@@ -836,7 +837,7 @@
 prism54_get_nick(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	dwrq->length = 0;
 
@@ -856,7 +857,7 @@
 		 struct iw_param *vwrq, char *extra)
 {
 
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	u32 rate, profile;
 	char *data;
 	int ret, i;
@@ -924,7 +925,7 @@
 		 struct iw_request_info *info,
 		 struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	int rvalue;
 	char *data;
 	union oid_res_t r;
@@ -948,7 +949,7 @@
 prism54_set_rts(struct net_device *ndev, struct iw_request_info *info,
 		struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	return mgt_set_request(priv, DOT11_OID_RTSTHRESH, 0, &vwrq->value);
 }
@@ -957,7 +958,7 @@
 prism54_get_rts(struct net_device *ndev, struct iw_request_info *info,
 		struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	union oid_res_t r;
 	int rvalue;
 
@@ -972,7 +973,7 @@
 prism54_set_frag(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	return mgt_set_request(priv, DOT11_OID_FRAGTHRESH, 0, &vwrq->value);
 }
@@ -981,7 +982,7 @@
 prism54_get_frag(struct net_device *ndev, struct iw_request_info *info,
 		 struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	union oid_res_t r;
 	int rvalue;
 
@@ -1004,7 +1005,7 @@
 prism54_set_retry(struct net_device *ndev, struct iw_request_info *info,
 		  struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	u32 slimit = 0, llimit = 0;	/* short and long limit */
 	u32 lifetime = 0;
 	int rvalue = 0;
@@ -1048,7 +1049,7 @@
 prism54_get_retry(struct net_device *ndev, struct iw_request_info *info,
 		  struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	union oid_res_t r;
 	int rvalue = 0;
 	vwrq->disabled = 0;	/* It cannot be disabled */
@@ -1080,7 +1081,7 @@
 prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
 		   struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	int rvalue = 0, force = 0;
 	int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
 	union oid_res_t r;
@@ -1170,7 +1171,7 @@
 prism54_get_encode(struct net_device *ndev, struct iw_request_info *info,
 		   struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct obj_key *key;
 	u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 	u32 authen = 0, invoke = 0, exunencrypt = 0;
@@ -1218,7 +1219,7 @@
 prism54_get_txpower(struct net_device *ndev, struct iw_request_info *info,
 		    struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	union oid_res_t r;
 	int rvalue;
 
@@ -1238,7 +1239,7 @@
 prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info,
 		    struct iw_param *vwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	s32 u = vwrq->value;
 
 	/* intersil firmware operates in 0.25 dBm (1/4) */
@@ -1264,7 +1265,7 @@
 prism54_reset(struct net_device *ndev, struct iw_request_info *info,
 	      __u32 * uwrq, char *extra)
 {
-	islpci_reset(ndev->priv, 0);
+	islpci_reset(netdev_priv(ndev), 0);
 
 	return 0;
 }
@@ -1273,7 +1274,7 @@
 prism54_set_beacon(struct net_device *ndev, struct iw_request_info *info,
 		   __u32 * uwrq, char *extra)
 {
-	int rvalue = mgt_set_request((islpci_private *) ndev->priv,
+	int rvalue = mgt_set_request((islpci_private *) netdev_priv(ndev),
 				     DOT11_OID_BEACONPERIOD, 0, uwrq);
 
 	return (rvalue ? rvalue : -EINPROGRESS);
@@ -1287,7 +1288,7 @@
 	int rvalue;
 
 	rvalue =
-	    mgt_get_request((islpci_private *) ndev->priv,
+	    mgt_get_request((islpci_private *) netdev_priv(ndev),
 			    DOT11_OID_BEACONPERIOD, 0, NULL, &r);
 	*uwrq = r.u;
 
@@ -1337,7 +1338,7 @@
 prism54_add_mac(struct net_device *ndev, struct iw_request_info *info,
 		struct sockaddr *awrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	struct mac_entry *entry;
 	struct sockaddr *addr = (struct sockaddr *) extra;
@@ -1366,7 +1367,7 @@
 prism54_del_mac(struct net_device *ndev, struct iw_request_info *info,
 		struct sockaddr *awrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	struct mac_entry *entry;
 	struct list_head *ptr;
@@ -1396,7 +1397,7 @@
 prism54_get_mac(struct net_device *ndev, struct iw_request_info *info,
 		struct iw_point *dwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	struct mac_entry *entry;
 	struct list_head *ptr;
@@ -1427,7 +1428,7 @@
 prism54_set_policy(struct net_device *ndev, struct iw_request_info *info,
 		   __u32 * uwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 	u32 mlmeautolevel;
 
@@ -1460,7 +1461,7 @@
 prism54_get_policy(struct net_device *ndev, struct iw_request_info *info,
 		   __u32 * uwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_acl *acl = &priv->acl;
 
 	*uwrq = acl->policy;
@@ -1511,7 +1512,7 @@
 
 	/* Tell the card to kick every client */
 	mlme->id = cpu_to_le16(0);
-	rvalue = mgt_set_request(ndev->priv, DOT11_OID_DISASSOCIATE, 0, mlme);
+	rvalue = mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme);
 	kfree(mlme);
 
 	return rvalue;
@@ -1535,7 +1536,7 @@
 	/* Tell the card to only kick the corresponding bastard */
 	memcpy(mlme->address, addr->sa_data, ETH_ALEN);
 	mlme->id = cpu_to_le16(-1);
-	rvalue = mgt_set_request(ndev->priv, DOT11_OID_DISASSOCIATE, 0, mlme);
+	rvalue = mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme);
 
 	kfree(mlme);
 
@@ -1595,7 +1596,7 @@
 static void
 link_changed(struct net_device *ndev, u32 bitrate)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	if (le32_to_cpu(bitrate)) {
 		if (priv->iw_mode == IW_MODE_INFRA) {
@@ -1604,9 +1605,9 @@
 					NULL);
 			wireless_send_event(ndev, SIOCGIWAP, &uwrq, NULL);
 		} else
-			send_simple_event(ndev->priv, "Link established");
+			send_simple_event(netdev_priv(ndev), "Link established");
 	} else
-		send_simple_event(ndev->priv, "Link lost");
+		send_simple_event(netdev_priv(ndev), "Link lost");
 }
 
 /* Beacon/ProbeResp payload header */
@@ -1889,16 +1890,17 @@
 prism54_process_trap(void *data)
 {
 	struct islpci_mgmtframe *frame = data;
+	struct net_device *ndev = frame->ndev;
 	enum oid_num_t n = mgt_oidtonum(frame->header->oid);
 
-	prism54_process_trap_helper(frame->ndev->priv, n, frame->data);
+	prism54_process_trap_helper(netdev_priv(ndev), n, frame->data);
 	islpci_mgt_release(frame);
 }
 
 int
 prism54_set_mac_address(struct net_device *ndev, void *addr)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	int ret;
 
 	if (ndev->addr_len != 6)
@@ -1923,7 +1925,7 @@
 prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info,
 		__u32 * uwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	down_write(&priv->mib_sem);
 
@@ -1943,16 +1945,70 @@
 prism54_get_wpa(struct net_device *ndev, struct iw_request_info *info,
 		__u32 * uwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	*uwrq = priv->wpa;
 	return 0;
 }
 
 int
+prism54_set_maxframeburst(struct net_device *ndev, struct iw_request_info *info,
+		__u32 *uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	u32 max_burst;
+
+	max_burst = (*uwrq) ? *uwrq : CARD_DEFAULT_MAXFRAMEBURST;
+	mgt_set_request(priv, DOT11_OID_MAXFRAMEBURST, 0, &max_burst);
+
+	return -EINPROGRESS; /* Call commit handler */
+}
+
+int
+prism54_get_maxframeburst(struct net_device *ndev, struct iw_request_info *info,
+		__u32 *uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+	
+	rvalue = mgt_get_request(priv, DOT11_OID_MAXFRAMEBURST, 0, NULL, &r);
+	*uwrq = r.u;
+	
+	return rvalue;
+}
+
+int
+prism54_set_profile(struct net_device *ndev, struct iw_request_info *info,
+		__u32 *uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	u32 profile;
+
+	profile = (*uwrq) ? *uwrq : CARD_DEFAULT_PROFILE;
+	mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile);
+	
+	return -EINPROGRESS; /* Call commit handler */
+}
+
+int
+prism54_get_profile(struct net_device *ndev, struct iw_request_info *info,
+		__u32 *uwrq, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	union oid_res_t r;
+	int rvalue;
+
+	rvalue = mgt_get_request(priv, DOT11_OID_PROFILES, 0, NULL, &r);
+	*uwrq = r.u;
+
+	return rvalue;
+}
+
+int
 prism54_oid(struct net_device *ndev, struct iw_request_info *info,
 		__u32 *uwrq, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	
 	priv->priv_oid = *uwrq;
 	printk("%s: oid 0x%08X\n", ndev->name, *uwrq);
@@ -1964,7 +2020,7 @@
 prism54_get_oid(struct net_device *ndev, struct iw_request_info *info,
 		struct iw_point *data, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_mgmtframe *response = NULL;
 	int ret = -EIO, response_op = PIMFOR_OP_ERROR;
 	
@@ -1998,7 +2054,7 @@
 prism54_set_oid(struct net_device *ndev, struct iw_request_info *info,
 		struct iw_point *data, char *extra)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct islpci_mgmtframe *response = NULL;
 	int ret = 0, response_op = PIMFOR_OP_ERROR;
 	
diff -Nru a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h
--- a/drivers/net/wireless/prism54/isl_oid.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/prism54/isl_oid.h	Wed Mar 17 19:29:09 2004
@@ -1,7 +1,8 @@
 /*
- *  $Id: isl_oid.h,v 1.2 2004/01/30 16:24:00 ajfa Exp $
+ *  $Id: isl_oid.h,v 1.3 2004/03/09 09:05:27 mcgrof Exp $
  *  
  *  Copyright (C) 2003 Herbert Valerio Riedel <hvr@gnu.org>
+ *  Copyright (C) 2004 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>
  *
  *  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
@@ -142,15 +143,131 @@
 	DOT11_PRIV_TKIP = 1
 };
 
+/* Prism "Nitro" / Frameburst / "Packet Frame Grouping"
+ * Value is in microseconds. Represents the # microseconds
+ * the firmware will take to group frames before sending out then out 
+ * together with a CSMA contention. Without this all frames are
+ * sent with a CSMA contention. 
+ * Bibliography: 
+ * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Papers/Packet.Frame.Grouping.html
+ */
+enum dot11_maxframeburst_t { 
+	/* Values for DOT11_OID_MAXFRAMEBURST */
+	DOT11_MAXFRAMEBURST_OFF = 0, /* Card firmware default */
+	DOT11_MAXFRAMEBURST_MIXED_SAFE = 650, /* 802.11 a,b,g safe */
+	DOT11_MAXFRAMEBURST_IDEAL = 1300, /* Theoretical ideal level */
+	DOT11_MAXFRAMEBURST_MAX = 5000, /* Use this as max,
+		* Note: firmware allows for greater values. This is a
+		* recommended max. I'll update this as I find
+		* out what the real MAX is. Also note that you don't necessarily
+		* get better results with a greater value here.
+		*/
+};
+
+/* Support for 802.11 long and short frame preambles.
+ * Long	 preamble uses 128-bit sync field, 8-bit  CRC
+ * Short preamble uses 56-bit  sync field, 16-bit CRC
+ * 
+ * 802.11a -- not sure, both optionally ?
+ * 802.11b supports long and optionally short 
+ * 802.11g supports both */
+enum dot11_preamblesettings_t {
+	DOT11_PREAMBLESETTING_LONG = 0,
+		/* Allows *only* long 802.11 preambles */
+	DOT11_PREAMBLESETTING_SHORT = 1,
+		/* Allows *only* short 802.11 preambles */
+	DOT11_PREAMBLESETTING_DYNAMIC = 2
+		/* AutomatiGically set */
+};
+
+/* Support for 802.11 slot timing (time between packets).
+ *
+ * Long uses 802.11a slot timing  (9 usec ?)
+ * Short uses 802.11b slot timing (20 use ?) */
+enum dot11_slotsettings_t {
+	DOT11_SLOTSETTINGS_LONG = 0, 
+		/* Allows *only* long 802.11b slot timing */
+	DOT11_SLOTSETTINGS_SHORT = 1,
+		/* Allows *only* long 802.11a slot timing */
+	DOT11_SLOTSETTINGS_DYNAMIC = 2
+		/* AutomatiGically set */
+};
+
+/* All you need to know, ERP is "Extended Rate PHY".
+ * An Extended Rate PHY (ERP) STA or AP shall support three different 
+ * preamble and header formats:
+ * Long  preamble (refer to above)
+ * Short preamble (refer to above)
+ * OFDM  preamble ( ? )
+ *
+ * I'm assuming here Protection tells the AP
+ * to be careful, a STA which cannot handle the long pre-amble
+ * has joined.
+ */
+enum do11_nonerpstatus_t {
+	DOT11_ERPSTAT_NONEPRESENT = 0,
+	DOT11_ERPSTAT_USEPROTECTION = 1
+};
+
+/* (ERP is "Extended Rate PHY") Way to read NONERP is NON-ERP-*
+ * The key here is DOT11 NON ERP NEVER protects against
+ * NON ERP STA's. You *don't* want this unless
+ * you know what you are doing. It means you will only 
+ * get Extended Rate capabilities */
+enum dot11_nonerpprotection_t {
+	DOT11_NONERP_NEVER = 0,
+	DOT11_NONERP_ALWAYS = 1,
+	DOT11_NONERP_DYNAMIC = 2
+};
+
+/* Preset OID configuration for 802.11 modes 
+ * Note: DOT11_OID_CW[MIN|MAX] hold the values of the 
+ * DCS MIN|MAX backoff used */
+enum dot11_profile_t { /* And set/allowed values */
+	/* Allowed values for DOT11_OID_PROFILES */
+	DOT11_PROFILE_B_ONLY = 0,
+		/* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps 
+		 * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC
+		 * DOT11_OID_CWMIN: 31
+		 * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC
+		 * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_LONG
+		 */
+	DOT11_PROFILE_MIXED_G_WIFI = 1,
+		/* DOT11_OID_RATES: 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54Mbs
+		 * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC
+		 * DOT11_OID_CWMIN: 15
+		 * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC
+		 * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_DYNAMIC
+		 */
+	DOT11_PROFILE_MIXED_LONG = 2, /* "Long range" */
+		/* Same as Profile MIXED_G_WIFI */
+	DOT11_PROFILE_G_ONLY = 3,
+		/* Same as Profile MIXED_G_WIFI */
+	DOT11_PROFILE_TEST = 4,
+		/* Same as Profile MIXED_G_WIFI except:
+		 * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_SHORT
+		 * DOT11_OID_NONEPROTECTION: DOT11_NOERP_NEVER
+		 * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_SHORT
+		 */
+	DOT11_PROFILE_B_WIFI = 5,
+		/* Same as Profile B_ONLY */
+	DOT11_PROFILE_A_ONLY = 6,
+		/* Same as Profile MIXED_G_WIFI except:
+		 * DOT11_OID_RATES: 6, 9, 12, 18, 24, 36, 48, 54Mbs
+		 */
+	DOT11_PROFILE_MIXED_SHORT = 7
+		/* Same as MIXED_G_WIFI */
+};
+
+
 /* The dot11d conformance level configures the 802.11d conformance levels.
  * The following conformance levels exist:*/
 enum oid_inl_conformance_t {
 	OID_INL_CONFORMANCE_NONE = 0,	/* Perform active scanning */
 	OID_INL_CONFORMANCE_STRICT = 1,	/* Strictly adhere to 802.11d */
 	OID_INL_CONFORMANCE_FLEXIBLE = 2,	/* Use passed 802.11d info to
-						 * determine channel AND/OR just make 
-						 * assumption that active 
-						 * channels are valid  channels */
+		* determine channel AND/OR just make assumption that active 
+		* channels are valid  channels */
 };
 
 enum oid_inl_mode_t {
@@ -176,6 +293,7 @@
 	INL_PHYCAP_FAA = 0x80000000,	/* Means card supports the FAA switch */
 };
 
+
 enum oid_num_t {
 	GEN_OID_MACADDRESS = 0,
 	GEN_OID_LINKSTATE,
@@ -269,8 +387,8 @@
 	DOT11_OID_FRAMEABORTSPHY,
 
 	DOT11_OID_SLOTTIME,
-	DOT11_OID_CWMIN,
-	DOT11_OID_CWMAX,
+	DOT11_OID_CWMIN, /* MIN DCS backoff */
+	DOT11_OID_CWMAX, /* MAX DCS backoff */
 	DOT11_OID_ACKWINDOW,
 	DOT11_OID_ANTENNARX,
 	DOT11_OID_ANTENNATX,
diff -Nru a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
--- a/drivers/net/wireless/prism54/islpci_dev.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/prism54/islpci_dev.c	Wed Mar 17 19:29:09 2004
@@ -245,7 +245,7 @@
 islpci_open(struct net_device *ndev)
 {
 	u32 rc;
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	printk(KERN_DEBUG "%s: islpci_open()\n", ndev->name);
 
@@ -265,7 +265,7 @@
 static int
 islpci_close(struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 	printk(KERN_DEBUG "%s: islpci_close ()\n", ndev->name);
 
@@ -491,7 +491,7 @@
 struct net_device_stats *
 islpci_statistics(struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 
 #if VERBOSE > SHOW_ERROR_MESSAGES
 	DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics \n");
diff -Nru a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
--- a/drivers/net/wireless/prism54/islpci_eth.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/prism54/islpci_eth.c	Wed Mar 17 19:29:09 2004
@@ -63,6 +63,7 @@
 					 priv->pci_map_tx_address[index],
 					 skb->len, PCI_DMA_TODEVICE);
 			dev_kfree_skb_irq(skb);
+			skb = NULL;
 		}
 		/* increment the free data low queue pointer */
 		priv->free_data_tx++;
@@ -72,7 +73,7 @@
 int
 islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	isl38xx_control_block *cb = priv->control_block;
 	u32 index;
 	dma_addr_t pci_map_address;
@@ -238,6 +239,7 @@
  drop_free:
 	/* free the skbuf structure before aborting */
 	dev_kfree_skb(skb);
+	skb = NULL;
 
 	priv->statistics.tx_dropped++;
 	spin_unlock_irqrestore(&priv->slock, flags);
@@ -346,8 +348,10 @@
 	     skb->data[0], skb->data[1], skb->data[2], skb->data[3],
 	     skb->data[4], skb->data[5]);
 #endif
-	if (discard)
+	if (discard) {
 		dev_kfree_skb(skb);
+		skb = NULL;
+	}
 	else
 		netif_rx(skb);
 
@@ -388,6 +392,7 @@
 
 			/* free the skbuf structure before aborting */
 			dev_kfree_skb((struct sk_buff *) skb);
+			skb = NULL;
 			break;
 		}
 		/* update the fragment address */
@@ -411,7 +416,7 @@
 void
 islpci_eth_tx_timeout(struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	struct net_device_stats *statistics = &priv->statistics;
 
 	/* increment the transmit error counter */
diff -Nru a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
--- a/drivers/net/wireless/prism54/islpci_hotplug.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c	Wed Mar 17 19:29:09 2004
@@ -29,10 +29,10 @@
 #include "isl_oid.h"
 
 #define DRV_NAME	"prism54"
-#define DRV_VERSION	"1.0.2.2"
+#define DRV_VERSION	"1.1"
 
-MODULE_AUTHOR("W.Termorshuizen, R.Bastings, H.V.Riedel, prism54.org team");
-MODULE_DESCRIPTION("Intersil 802.11 Wireless LAN adapter");
+MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team <prism54-devel@prism54.org>");
+MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter");
 MODULE_LICENSE("GPL");
 
 /* In this order: vendor, device, subvendor, subdevice, class, class_mask,
@@ -97,6 +97,11 @@
 	 0, 0,
 	 (unsigned long) "SMC 2802Wv2"},
 	{
+	 PCIVENDOR_INTERSIL, PCIDEVICE_ISL3890,
+	 PCIVENDOR_SMC, 0xa835UL,
+	 0, 0,
+	 (unsigned long) "SMC 2835Wv2"},
+	{
 	 PCIVENDOR_INTERSIL, PCIDEVICE_ISL3877,
 	 PCI_ANY_ID, PCI_ANY_ID,
 	 0, 0,
@@ -133,7 +138,7 @@
 	islpci_private	*priv;
 	char		*modelp;
 
-	priv = ndev->priv;
+	priv = netdev_priv(ndev);
 	switch (priv->pdev->subsystem_device) {
 	case PCIDEVICE_ISL3877:
 		modelp = "PRISM Indigo";
@@ -159,6 +164,9 @@
 	case 0x2835UL:
 		modelp = "SMC2835W";
 		break;
+	case 0xa835UL:
+		modelp = "SMC2835W V2";
+		break;
 	/* Let's leave this one out for now since it seems bogus/wrong 
 	 * Even if the manufacturer did use 0x0000UL it may not be correct
 	 * by their part, therefore deserving no name ;) */
@@ -269,7 +277,7 @@
 		goto do_pci_release_regions;
 	}
 
-	priv = ndev->priv;
+	priv = netdev_priv(ndev);
 	islpci_set_state(priv, PRV_STATE_PREBOOT); /* we are attempting to boot */
 
 	/* card is in unknown state yet, might have some interrupts pending */
@@ -314,7 +322,7 @@
 prism54_remove(struct pci_dev *pdev)
 {
 	struct net_device *ndev = pci_get_drvdata(pdev);
-	islpci_private *priv = ndev ? ndev->priv : 0;
+	islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
 	BUG_ON(!priv);
 
 	if (!__in_cleanup_module) {
@@ -355,7 +363,7 @@
 prism54_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *ndev = pci_get_drvdata(pdev);
-	islpci_private *priv = ndev ? ndev->priv : 0;
+	islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
 	BUG_ON(!priv);
 
 	printk(KERN_NOTICE "%s: got suspend request (state %d)\n",
@@ -380,7 +388,7 @@
 prism54_resume(struct pci_dev *pdev)
 {
 	struct net_device *ndev = pci_get_drvdata(pdev);
-	islpci_private *priv = ndev ? ndev->priv : 0;
+	islpci_private *priv = ndev ? netdev_priv(ndev) : 0;
 	BUG_ON(!priv);
 
 	printk(KERN_NOTICE "%s: got resume request\n", ndev->name);
diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
--- a/drivers/net/wireless/prism54/islpci_mgt.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/prism54/islpci_mgt.c	Wed Mar 17 19:29:09 2004
@@ -22,6 +22,7 @@
 #include <linux/netdevice.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/moduleparam.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -38,7 +39,7 @@
         Global variable definition section
 ******************************************************************************/
 int pc_debug = VERBOSE;
-MODULE_PARM(pc_debug, "i");
+module_param(pc_debug, int, 0);
 
 /******************************************************************************
     Driver general functions
@@ -106,7 +107,7 @@
 int
 islpci_mgmt_rx_fill(struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	isl38xx_control_block *cb =    /* volatile not needed */
 		(isl38xx_control_block *) priv->control_block;
 	u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]);
@@ -165,7 +166,7 @@
 islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid,
 		    void *data, int length)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	isl38xx_control_block *cb =
 		(isl38xx_control_block *) priv->control_block;
 	void *p;
@@ -271,7 +272,7 @@
 int
 islpci_mgt_receive(struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	isl38xx_control_block *cb =
 		(isl38xx_control_block *) priv->control_block;
 	u32 curr_frag;
@@ -414,7 +415,7 @@
 void
 islpci_mgt_cleanup_transmit(struct net_device *ndev)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	isl38xx_control_block *cb =    /* volatile not needed */
 		(isl38xx_control_block *) priv->control_block;
 	u32 curr_frag;
@@ -451,7 +452,7 @@
 		       void *senddata, int sendlen,
 		       struct islpci_mgmtframe **recvframe)
 {
-	islpci_private *priv = ndev->priv;
+	islpci_private *priv = netdev_priv(ndev);
 	const long wait_cycle_jiffies = (ISL38XX_WAIT_CYCLE * 10 * HZ) / 1000;
 	long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies;
 	int err;
diff -Nru a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h
--- a/drivers/net/wireless/prism54/islpci_mgt.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/net/wireless/prism54/islpci_mgt.h	Wed Mar 17 19:29:09 2004
@@ -87,11 +87,13 @@
 #define CARD_DEFAULT_KEY4                       "default_key_4"
 #define CARD_DEFAULT_WEP                        0
 #define CARD_DEFAULT_FILTER                     0
-# define CARD_DEFAULT_WDS                        0
+#define CARD_DEFAULT_WDS                        0
 #define	CARD_DEFAULT_AUTHEN                     DOT11_AUTH_OS
 #define	CARD_DEFAULT_DOT1X			0
 #define CARD_DEFAULT_MLME_MODE			DOT11_MLME_AUTO
 #define CARD_DEFAULT_CONFORMANCE                OID_INL_CONFORMANCE_NONE
+#define CARD_DEFAULT_PROFILE			DOT11_PROFILE_MIXED_G_WIFI
+#define CARD_DEFAULT_MAXFRAMEBURST		DOT11_MAXFRAMEBURST_MIXED_SAFE
 
 /* PIMFOR package definitions */
 #define PIMFOR_ETHERTYPE                        0x8828
diff -Nru a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c
--- a/drivers/net/wireless/prism54/oid_mgt.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/net/wireless/prism54/oid_mgt.c	Wed Mar 17 19:29:10 2004
@@ -97,7 +97,7 @@
 	[DOT11_OID_ALOFT_CONFIG] = OID_UNKNOWN(0x1d000006),
 
 	[DOT11_OID_VDCFX] = {0x1b000000, 7, 0, 0},
-	[DOT11_OID_MAXFRAMEBURST] = OID_U32(0x1b000008),
+	[DOT11_OID_MAXFRAMEBURST] = OID_U32(0x1b000008), /* in microseconds */
 
 	[DOT11_OID_PSM] = OID_U32(0x14000000),
 	[DOT11_OID_CAMTIMEOUT] = OID_U32(0x14000001),
diff -Nru a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
--- a/drivers/pci/hotplug/rpaphp_core.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/pci/hotplug/rpaphp_core.c	Wed Mar 17 19:29:10 2004
@@ -31,6 +31,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <asm/eeh.h>       /* for eeh_add_device() */
 #include <asm/rtas.h>		/* rtas_call */
 #include <asm/pci-bridge.h>	/* for pci_controller */
 #include "../pci.h"		/* for pci_add_new_bus*/
diff -Nru a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
--- a/drivers/s390/block/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/block/Kconfig	Wed Mar 17 19:29:09 2004
@@ -48,12 +48,12 @@
 	  say "Y".
 
 config DASD_DIAG
-	tristate "Support for DIAG access to CMS reserved Disks"
+	tristate "Support for DIAG access to Disks"
 	depends on DASD && ARCH_S390X = 'n'
 	help
-	  Select this option if you want to use CMS reserved Disks under VM
-	  with the Diagnose250 command.  If you are not running under VM or
-	  unsure what it is, say "N".
+	  Select this option if you want to use Diagnose250 command to access
+	  Disks under VM.  If you are not running under VM or unsure what it is,
+	  say "N".
 
 config DASD_CMB
 	tristate "Compatibility interface for DASD channel measurement blocks"
diff -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
--- a/drivers/s390/block/dasd.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/block/dasd.c	Wed Mar 17 19:29:09 2004
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
  *
- * $Revision: 1.129 $
+ * $Revision: 1.133 $
  */
 
 #include <linux/config.h>
@@ -1655,11 +1655,24 @@
 {
 	struct gendisk *disk = inp->i_bdev->bd_disk;
 	struct dasd_device *device = disk->private_data;
-	int rc;
+	int old_count, rc;
+
+	/*
+	 * We use a negative value in open_count to indicate that
+	 * the device must not be used.
+	 */
+	do {
+		old_count = atomic_read(&device->open_count);
+		if (old_count < 0)
+			return -ENODEV;
+	} while (atomic_compare_and_swap(old_count, old_count + 1,
+					 &device->open_count));
+
+	if (!try_module_get(device->discipline->owner)) {
+		rc = -EINVAL;
+		goto unlock;
+	}
 
-	if (!try_module_get(device->discipline->owner))
-		return -EINVAL;
-	
 	if (dasd_probeonly) {
 		MESSAGE(KERN_INFO,
 			"No access to device %s due to probeonly mode",
@@ -1676,11 +1689,12 @@
 		goto out;
 	}
 
-	atomic_inc(&device->open_count);
 	return 0;
 
 out:
 	module_put(device->discipline->owner);
+unlock:
+	atomic_dec(&device->open_count);
 	return rc;
 }
 
@@ -1741,7 +1755,7 @@
 	ret = dasd_add_sysfs_files(cdev);
 	if (ret) {
 		printk(KERN_WARNING
-		       "dasd_generic_probe: could not add driverfs entries"
+		       "dasd_generic_probe: could not add sysfs entries "
 		       "for %s\n", cdev->dev.bus_id);
 	}
 
@@ -1757,8 +1771,15 @@
 {
 	struct dasd_device *device;
 
+	dasd_remove_sysfs_files(cdev);
 	device = dasd_device_from_cdev(cdev);
 	if (!IS_ERR(device)) {
+		/*
+		 * This device is removed unconditionally. Set open_count
+		 * to -1 to prevent dasd_open from opening it while it is
+		 * no quite down yet.
+		 */
+		atomic_set(&device->open_count,-1);
 		dasd_set_target_state(device, DASD_STATE_NEW);
 		/* dasd_delete_device destroys the device reference. */
 		dasd_delete_device(device);
@@ -1830,15 +1851,23 @@
 	struct dasd_device *device;
 
 	device = dasd_device_from_cdev(cdev);
-	if (atomic_read(&device->open_count) > 0) {
+	/*
+	 * We must make sure that this device is currently not in use
+	 * (current open_count == 0 ). We set open_count to -1 to indicate
+	 * that from now on set_offline is in progress and the device must
+	 * not be used otherwise.
+	 */
+	if (atomic_compare_and_swap(0, -1, &device->open_count)) {
 		printk (KERN_WARNING "Can't offline dasd device with open"
 			" count = %i.\n",
 			atomic_read(&device->open_count));
 		dasd_put_device(device);
 		return -EBUSY;
 	}
-	dasd_put_device(device);
-	dasd_generic_remove (cdev);
+	dasd_set_target_state(device, DASD_STATE_NEW);
+	/* dasd_delete_device destroys the device reference. */
+	dasd_delete_device(device);
+
 	return 0;
 }
 
diff -Nru a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
--- a/drivers/s390/block/dasd_devmap.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/block/dasd_devmap.c	Wed Mar 17 19:29:09 2004
@@ -11,7 +11,7 @@
  * functions may not be called from interrupt context. In particular
  * dasd_get_device is a no-no from interrupt context.
  *
- * $Revision: 1.25 $
+ * $Revision: 1.26 $
  */
 
 #include <linux/config.h>
@@ -680,6 +680,13 @@
 {
 	return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
 }
+
+void
+dasd_remove_sysfs_files(struct ccw_device *cdev)
+{
+	sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
+}
+
 
 int
 dasd_devmap_init(void)
diff -Nru a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
--- a/drivers/s390/block/dasd_diag.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/block/dasd_diag.c	Wed Mar 17 19:29:09 2004
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.33 $
+ * $Revision: 1.34 $
  */
 
 #include <linux/config.h>
@@ -173,7 +173,6 @@
 
 	if (!ip) {		/* no intparm: unsolicited interrupt */
 		MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt");
-		irq_exit();
 		return;
 	}
 	cqr = (struct dasd_ccw_req *)(addr_t) ip;
@@ -183,7 +182,6 @@
 			    " magic number of dasd_ccw_req 0x%08X doesn't"
 			    " match discipline 0x%08X",
 			    cqr->magic, *(int *) (&device->discipline->name));
-		irq_exit();
 		return;
 	}
 
diff -Nru a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
--- a/drivers/s390/block/dasd_int.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/block/dasd_int.h	Wed Mar 17 19:29:09 2004
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.54 $
+ * $Revision: 1.55 $
  */
 
 #ifndef DASD_INT_H
@@ -485,6 +485,8 @@
 void dasd_delete_device(struct dasd_device *);
 
 int dasd_add_sysfs_files(struct ccw_device *);
+void dasd_remove_sysfs_files(struct ccw_device *);
+
 struct dasd_device *dasd_device_from_cdev(struct ccw_device *);
 struct dasd_device *dasd_device_from_devindex(int);
 
diff -Nru a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
--- a/drivers/s390/char/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/char/Makefile	Wed Mar 17 19:29:09 2004
@@ -18,6 +18,6 @@
 
 tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o
 tape-$(CONFIG_PROC_FS) += tape_proc.o
-tape-objs := tape_core.o tape_std.o tape_char.o tape_class.o $(tape-y)
-obj-$(CONFIG_S390_TAPE) += tape.o
+tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y)
+obj-$(CONFIG_S390_TAPE) += tape.o tape_class.o
 obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o
diff -Nru a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
--- a/drivers/s390/char/sclp.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/char/sclp.c	Wed Mar 17 19:29:09 2004
@@ -335,8 +335,8 @@
 	unsigned long psw_mask;
 	unsigned long cr0, cr0_sync;
 
-	/* Need to irq_enter() to prevent BH from executing. */
-	irq_enter();
+	/* Prevent BH from executing. */
+	local_bh_disable();
 	/*
 	 * save cr0
 	 * enable service signal external interruption (cr0.22)
@@ -365,7 +365,7 @@
 
 	/* restore cr0 */
 	__ctl_load(cr0, 0, 0);
-	irq_exit();
+	__local_bh_enable();
 }
 
 /*
diff -Nru a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h
--- a/drivers/s390/char/tape.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/char/tape.h	Wed Mar 17 19:29:09 2004
@@ -199,8 +199,8 @@
 	struct list_head		node;
 
 	struct ccw_device *		cdev;
-	struct cdev *			nt;
-	struct cdev *			rt;
+	struct tape_class_device *	nt;
+	struct tape_class_device *	rt;
 
 	/* Device discipline information. */
 	struct tape_discipline *	discipline;
diff -Nru a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
--- a/drivers/s390/char/tape_char.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/s390/char/tape_char.c	Wed Mar 17 19:29:10 2004
@@ -48,38 +48,29 @@
 
 static int tapechar_major = TAPECHAR_MAJOR;
 
-struct cdev *
-tapechar_register_tape_dev(struct tape_device *device, char *name, int i)
-{
-	struct cdev *	cdev;
-	char		devname[11];
-
-	sprintf(devname, "%s%i", name, i / 2);
-	cdev = register_tape_dev(
-		&device->cdev->dev,
-		MKDEV(tapechar_major, i),
-		&tape_fops,
-		devname
-	);
-
-	return ((IS_ERR(cdev)) ? NULL : cdev);
-}
-
 /*
  * This function is called for every new tapedevice
  */
 int
 tapechar_setup_device(struct tape_device * device)
 {
-	device->nt = tapechar_register_tape_dev(
-			device,
-			"ntibm",
-			device->first_minor
+	char	device_name[20];
+
+	sprintf(device_name, "ntibm%i", device->first_minor / 2);
+	device->nt = register_tape_dev(
+		&device->cdev->dev,
+		MKDEV(tapechar_major, device->first_minor),
+		&tape_fops,
+		device_name,
+		"non-rewinding"
 	);
-	device->rt = tapechar_register_tape_dev(
-			device,
-			"rtibm",
-			device->first_minor + 1
+	device_name[0] = 'r';
+	device->rt = register_tape_dev(
+		&device->cdev->dev,
+		MKDEV(tapechar_major, device->first_minor + 1),
+		&tape_fops,
+		device_name,
+		"rewinding"
 	);
 
 	return 0;
@@ -500,9 +491,6 @@
 	tapechar_major = MAJOR(dev);
 	PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev));
 
-#ifdef TAPE390_INTERNAL_CLASS
-	tape_setup_class();
-#endif
 	return 0;
 }
 
@@ -512,9 +500,6 @@
 void
 tapechar_exit(void)
 {
-#ifdef TAPE390_INTERNAL_CLASS
-	tape_cleanup_class();
-#endif
 	PRINT_INFO("tape releases major %d for character devices\n",
 		tapechar_major);
 	unregister_chrdev_region(MKDEV(tapechar_major, 0), 256);
diff -Nru a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
--- a/drivers/s390/char/tape_class.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/s390/char/tape_class.c	Wed Mar 17 19:29:10 2004
@@ -1,4 +1,7 @@
 /*
+ * (C) Copyright IBM Corp. 2004
+ * tape_class.c ($Revision: 1.6 $)
+ *
  * Tape class device support
  *
  * Author: Stefan Bader <shbader@de.ibm.com>
@@ -6,11 +9,12 @@
  */
 #include "tape_class.h"
 
-#ifndef TAPE390_INTERNAL_CLASS
 MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
-MODULE_DESCRIPTION("Tape class");
+MODULE_DESCRIPTION(
+	"(C) Copyright IBM Corp. 2004   All Rights Reserved.\n"
+	"tape_class.c ($Revision: 1.6 $)"
+);
 MODULE_LICENSE("GPL");
-#endif
 
 struct class_simple *tape_class;
 
@@ -29,69 +33,94 @@
  * devname
  *	The pointer to the name of the character device.
  */
-struct cdev *register_tape_dev(
+struct tape_class_device *register_tape_dev(
 	struct device *		device,
 	dev_t			dev,
 	struct file_operations *fops,
-	char *			devname
-) {
-	struct cdev *	cdev;
+	char *			device_name,
+	char *			mode_name)
+{
+	struct tape_class_device *	tcd;
 	int		rc;
 	char *		s;
 
-	cdev = cdev_alloc();
-	if (!cdev)
+	tcd = kmalloc(sizeof(struct tape_class_device), GFP_KERNEL);
+	if (!tcd)
 		return ERR_PTR(-ENOMEM);
 
-	cdev->owner = fops->owner;
-	cdev->ops   = fops;
-	cdev->dev   = dev;
-
-	rc = cdev_add(cdev, cdev->dev, 1);
-	if (rc) {
-		cdev_del(cdev);
-		return ERR_PTR(rc);
+	memset(tcd, 0, sizeof(struct tape_class_device));
+	strncpy(tcd->device_name, device_name, TAPECLASS_NAME_LEN);
+	for (s = strchr(tcd->device_name, '/'); s; s = strchr(s, '/'))
+		*s = '!';
+	strncpy(tcd->mode_name, mode_name, TAPECLASS_NAME_LEN);
+	for (s = strchr(tcd->mode_name, '/'); s; s = strchr(s, '/'))
+		*s = '!';
+
+	tcd->char_device = cdev_alloc();
+	if (!tcd->char_device) {
+		rc = -ENOMEM;
+		goto fail_with_tcd;
 	}
-	class_simple_device_add(tape_class, cdev->dev, device, "%s", devname);
 
-	return cdev;
+	tcd->char_device->owner = fops->owner;
+	tcd->char_device->ops   = fops;
+	tcd->char_device->dev   = dev;
+
+	rc = cdev_add(tcd->char_device, tcd->char_device->dev, 1);
+	if (rc)
+		goto fail_with_cdev;
+
+	tcd->class_device = class_simple_device_add(
+				tape_class,
+				tcd->char_device->dev,
+				device,
+				"%s", tcd->device_name
+			);
+	sysfs_create_link(
+		&device->kobj,
+		&tcd->class_device->kobj,
+		tcd->mode_name
+	);
+
+	return tcd;
+
+fail_with_cdev:
+	cdev_del(&tcd->char_device);
+
+fail_with_tcd:
+	kfree(tcd);
+
+	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL(register_tape_dev);
 
-void unregister_tape_dev(struct cdev *cdev)
+void unregister_tape_dev(struct tape_class_device *tcd)
 {
-	if (cdev != NULL) {
-		class_simple_device_remove(cdev->dev);
-		cdev_del(cdev);
+	if (tcd != NULL && !IS_ERR(tcd)) {
+		sysfs_remove_link(
+			&tcd->class_device->dev->kobj,
+			tcd->mode_name
+		);
+		class_simple_device_remove(tcd->char_device->dev);
+		cdev_del(tcd->char_device);
+		kfree(tcd);
 	}
 }
 EXPORT_SYMBOL(unregister_tape_dev);
 
 
-#ifndef TAPE390_INTERNAL_CLASS
 static int __init tape_init(void)
-#else
-int tape_setup_class(void)
-#endif
 {
 	tape_class = class_simple_create(THIS_MODULE, "tape390");
+
 	return 0;
 }
 
-#ifndef TAPE390_INTERNAL_CLASS
 static void __exit tape_exit(void)
-#else
-void tape_cleanup_class(void)
-#endif
 {
 	class_simple_destroy(tape_class);
 	tape_class = NULL;
 }
 
-#ifndef TAPE390_INTERNAL_CLASS
 postcore_initcall(tape_init);
 module_exit(tape_exit);
-#else
-EXPORT_SYMBOL(tape_setup_class);
-EXPORT_SYMBOL(tape_cleanup_class);
-#endif
diff -Nru a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h
--- a/drivers/s390/char/tape_class.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/char/tape_class.h	Wed Mar 17 19:29:09 2004
@@ -1,4 +1,7 @@
 /*
+ * (C) Copyright IBM Corp. 2004   All Rights Reserved.
+ * tape_class.h ($Revision: 1.4 $)
+ *
  * Tape class device support
  *
  * Author: Stefan Bader <shbader@de.ibm.com>
@@ -7,11 +10,8 @@
 #ifndef __TAPE_CLASS_H__
 #define __TAPE_CLASS_H__
 
-#if 0
 #include <linux/init.h>
 #include <linux/module.h>
-#endif
-
 #include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/kobject.h>
@@ -21,34 +21,41 @@
 #include <linux/device.h>
 #include <linux/kdev_t.h>
 
-#define TAPE390_INTERNAL_CLASS
+#define TAPECLASS_NAME_LEN	32
+
+struct tape_class_device {
+	struct cdev *		char_device;
+	struct class_device *	class_device;
+	char			device_name[TAPECLASS_NAME_LEN];
+	char			mode_name[TAPECLASS_NAME_LEN];
+};
 
 /*
- * Register a tape device and return a pointer to the cdev structure.
+ * Register a tape device and return a pointer to the tape class device
+ * created by the call.
  *
  * device
  *	The pointer to the struct device of the physical (base) device.
- * drivername
- *	The pointer to the drivers name for it's character devices.
  * dev
  *	The intended major/minor number. The major number may be 0 to
  *	get a dynamic major number.
  * fops
  *	The pointer to the drivers file operations for the tape device.
- * devname
- *	The pointer to the name of the character device.
+ * device_name
+ *	Pointer to the logical device name (will also be used as kobject name
+ *	of the cdev). This can also be called the name of the tape class
+ *	device.
+ * mode_name
+ *	Points to the name of the tape mode. This creates a link with that
+ *	name from the physical device to the logical device (class).
  */
-struct cdev *register_tape_dev(
+struct tape_class_device *register_tape_dev(
 	struct device *		device,
 	dev_t			dev,
 	struct file_operations *fops,
-	char *			devname
+	char *			device_name,
+	char *			node_name
 );
-void unregister_tape_dev(struct cdev *cdev);
-
-#ifdef TAPE390_INTERNAL_CLASS
-int tape_setup_class(void);
-void tape_cleanup_class(void);
-#endif
+void unregister_tape_dev(struct tape_class_device *tcd);
 
 #endif /* __TAPE_CLASS_H__ */
diff -Nru a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
--- a/drivers/s390/cio/blacklist.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/cio/blacklist.c	Wed Mar 17 19:29:09 2004
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.29 $
+ *   $Revision: 1.31 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -72,7 +72,10 @@
 blacklist_busid(char **str, int *id0, int *id1, int *devno)
 {
 	int val, old_style;
- 
+	char *sav;
+
+	sav = *str;
+
 	/* check for leading '0x' */
 	old_style = 0;
 	if ((*str)[0] == '0' && (*str)[1] == 'x') {
@@ -80,44 +83,54 @@
 		old_style = 1;
 	}
 	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
-		return -EINVAL;
+		goto confused;
 	val = simple_strtoul(*str, str, 16);
 	if (old_style || (*str)[0] != '.') {
 		*id0 = *id1 = 0;
 		if (val < 0 || val > 0xffff)
-			return -EINVAL;
+			goto confused;
 		*devno = val;
+		if ((*str)[0] != ',' && (*str)[0] != '-' &&
+		    (*str)[0] != '\n' && (*str)[0] != '\0')
+			goto confused;
 		return 0;
 	}
 	/* New style x.y.z busid */
 	if (val < 0 || val > 0xff)
-		return -EINVAL;
+		goto confused;
 	*id0 = val;
 	(*str)++;
 	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
-		return -EINVAL;
+		goto confused;
 	val = simple_strtoul(*str, str, 16);
 	if (val < 0 || val > 0xff || (*str)++[0] != '.')
-		return -EINVAL;
+		goto confused;
 	*id1 = val;
 	if (!isxdigit((*str)[0]))	/* We require at least one hex digit */
-		return -EINVAL;
+		goto confused;
 	val = simple_strtoul(*str, str, 16);
 	if (val < 0 || val > 0xffff)
-		return -EINVAL;
+		goto confused;
 	*devno = val;
+	if ((*str)[0] != ',' && (*str)[0] != '-' &&
+	    (*str)[0] != '\n' && (*str)[0] != '\0')
+		goto confused;
 	return 0;
+confused:
+	strsep(str, ",\n");
+	printk(KERN_WARNING "Invalid cio_ignore parameter '%s'\n", sav);
+	return 1;
 }
 
 static inline int
 blacklist_parse_parameters (char *str, range_action action)
 {
 	unsigned int from, to, from_id0, to_id0, from_id1, to_id1;
-	char *sav;
 
-	sav = str;
 	while (*str != 0 && *str != '\n') {
 		range_action ra = action;
+		while(*str == ',')
+			str++;
 		if (*str == '!') {
 			ra = !action;
 			++str;
@@ -138,32 +151,37 @@
 			rc = blacklist_busid(&str, &from_id0,
 					     &from_id1, &from);
 			if (rc)
-				goto out_err;
+				continue;
 			to = from;
 			to_id0 = from_id0;
 			to_id1 = from_id1;
 			if (*str == '-') {
 				str++;
-				rc = blacklist_busid(&str, &to_id0, &to_id1,
-						     &to);
+				rc = blacklist_busid(&str, &to_id0,
+						     &to_id1, &to);
 				if (rc)
-					goto out_err;
+					continue;
+			}
+			if (*str == '-') {
+				printk(KERN_WARNING "invalid cio_ignore "
+					"parameter '%s'\n",
+					strsep(&str, ",\n"));
+				continue;
+			}
+			if ((from_id0 != to_id0) || (from_id1 != to_id1)) {
+				printk(KERN_WARNING "invalid cio_ignore range "
+					"%x.%x.%04x-%x.%x.%04x\n",
+					from_id0, from_id1, from,
+					to_id0, to_id1, to);
+				continue;
 			}
-			if ((from_id0 != to_id0) || (from_id1 != to_id1))
-				goto out_err;
 		}
 		/* FIXME: ignoring id0 and id1 here. */
 		pr_debug("blacklist_setup: adding range "
 			 "from 0.0.%04x to 0.0.%04x\n", from, to);
 		blacklist_range (ra, from, to);
-
-		if (*str == ',')
-			str++;
 	}
 	return 1;
-out_err:
-	printk(KERN_WARNING "blacklist_setup: error parsing \"%s\"\n", sav);
-	return 0;
 }
 
 /* Parsing the commandline for blacklist parameters, e.g. to blacklist
diff -Nru a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
--- a/drivers/s390/cio/css.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/s390/cio/css.h	Wed Mar 17 19:29:10 2004
@@ -82,6 +82,7 @@
 		unsigned int dosense:1;	    /* delayed SENSE required */
 		unsigned int doverify:1;    /* delayed path verification */
 		unsigned int donotify:1;    /* call notify function */
+		unsigned int recog_done:1;  /* dev. recog. complete */
 	} __attribute__((packed)) flags;
 	unsigned long intparm;	/* user interruption parameter */
 	struct qdio_irq *qdio_data;
diff -Nru a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
--- a/drivers/s390/cio/device.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/s390/cio/device.c	Wed Mar 17 19:29:10 2004
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.107 $
+ *   $Revision: 1.110 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -263,10 +263,10 @@
 
 	if (!cdev)
 		return -ENODEV;
-	if (!cdev->online)
+	if (!cdev->online || !cdev->drv)
 		return -EINVAL;
 
-	if (cdev->drv && cdev->drv->set_offline) {
+	if (cdev->drv->set_offline) {
 		ret = cdev->drv->set_offline(cdev);
 		if (ret != 0)
 			return ret;
@@ -292,7 +292,7 @@
 
 	if (!cdev)
 		return -ENODEV;
-	if (cdev->online)
+	if (cdev->online || !cdev->drv)
 		return -EINVAL;
 
 	spin_lock_irq(cdev->ccwlock);
@@ -307,8 +307,7 @@
 	}
 	if (cdev->private->state != DEV_STATE_ONLINE)
 		return -ENODEV;
-	if (!cdev->drv || !cdev->drv->set_online ||
-	    cdev->drv->set_online(cdev) == 0) {
+	if (!cdev->drv->set_online || cdev->drv->set_online(cdev) == 0) {
 		cdev->online = 1;
 		return 0;
 	}
@@ -327,7 +326,7 @@
 online_store (struct device *dev, const char *buf, size_t count)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
-	int i, force;
+	int i, force, ret;
 	char *tmp;
 
 	if (atomic_compare_and_swap(0, 1, &cdev->private->onoff))
@@ -347,29 +346,46 @@
 	if (i == 1) {
 		/* Do device recognition, if needed. */
 		if (cdev->id.cu_type == 0) {
-			ccw_device_recognition(cdev);
+			ret = ccw_device_recognition(cdev);
+			if (ret) {
+				printk(KERN_WARNING"Couldn't start recognition "
+				       "for device %s (ret=%d)\n",
+				       cdev->dev.bus_id, ret);
+				goto out;
+			}
 			wait_event(cdev->private->wait_q,
-				   dev_fsm_final_state(cdev));
+				   cdev->private->flags.recog_done);
 		}
-		ccw_device_set_online(cdev);
+		if (cdev->drv && cdev->drv->set_online)
+			ccw_device_set_online(cdev);
 	} else if (i == 0) {
 		if (cdev->private->state == DEV_STATE_DISCONNECTED)
 			ccw_device_remove_disconnected(cdev);
-		else
+		else if (cdev->drv && cdev->drv->set_offline)
 			ccw_device_set_offline(cdev);
 	}
 	if (force && cdev->private->state == DEV_STATE_BOXED) {
-		int ret;
 		ret = ccw_device_stlck(cdev);
-		if (ret)
+		if (ret) {
+			printk(KERN_WARNING"ccw_device_stlck for device %s "
+			       "returned %d!\n", cdev->dev.bus_id, ret);
 			goto out;
+		}
 		/* Do device recognition, if needed. */
 		if (cdev->id.cu_type == 0) {
-			ccw_device_recognition(cdev);
+			cdev->private->state = DEV_STATE_NOT_OPER;
+			ret = ccw_device_recognition(cdev);
+			if (ret) {
+				printk(KERN_WARNING"Couldn't start recognition "
+				       "for device %s (ret=%d)\n",
+				       cdev->dev.bus_id, ret);
+				goto out;
+			}
 			wait_event(cdev->private->wait_q,
-				   dev_fsm_final_state(cdev));
+				   cdev->private->flags.recog_done);
 		}
-		ccw_device_set_online(cdev);
+		if (cdev->drv && cdev->drv->set_online)
+			ccw_device_set_online(cdev);
 	}
 	out:
 	if (cdev->drv)
@@ -530,7 +546,9 @@
 		       __func__, sch->dev.bus_id);
 	put_device(&cdev->dev);
 out:
+	cdev->private->flags.recog_done = 1;
 	put_device(&sch->dev);
+	wake_up(&cdev->private->wait_q);
 }
 
 static void
@@ -555,10 +573,13 @@
 {
 	struct subchannel *sch;
 
-	if (css_init_done == 0)
+	if (css_init_done == 0) {
+		cdev->private->flags.recog_done = 1;
 		return;
+	}
 	switch (cdev->private->state) {
 	case DEV_STATE_NOT_OPER:
+		cdev->private->flags.recog_done = 1;
 		/* Remove device found not operational. */
 		if (!get_device(&cdev->dev))
 			break;
diff -Nru a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
--- a/drivers/s390/cio/device_fsm.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/cio/device_fsm.c	Wed Mar 17 19:29:09 2004
@@ -148,6 +148,7 @@
 	struct subchannel *sch;
 
 	sch = to_subchannel(cdev->dev.parent);
+	cdev->private->flags.recog_done = 1;
 	/*
 	 * Check if cu type and device type still match. If
 	 * not, it is certainly another device and we have to
@@ -217,6 +218,7 @@
 		__recover_lost_chpids(sch, old_lpm);
 	if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
 		if (state == DEV_STATE_NOT_OPER) {
+			cdev->private->flags.recog_done = 1;
 			cdev->private->state = DEV_STATE_DISCONNECTED;
 			return;
 		}
@@ -393,6 +395,7 @@
 	 * timeout (or if sense pgid during path verification detects the device
 	 * is locked, as may happen on newer devices).
 	 */
+	cdev->private->flags.recog_done = 0;
 	cdev->private->state = DEV_STATE_SENSE_ID;
 	ccw_device_sense_id_start(cdev);
 	return 0;
diff -Nru a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
--- a/drivers/s390/cio/device_ops.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/s390/cio/device_ops.c	Wed Mar 17 19:29:10 2004
@@ -79,7 +79,8 @@
 	if (cdev->private->state == DEV_STATE_NOT_OPER)
 		return -ENODEV;
 	if (cdev->private->state != DEV_STATE_ONLINE ||
-	    sch->schib.scsw.actl != 0 ||
+	    ((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
+	     !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
 	    cdev->private->flags.doverify)
 		return -EBUSY;
 	ret = cio_set_options (sch, flags);
@@ -347,7 +348,9 @@
 	cdev->handler = ccw_device_wake_up;
 	if (cdev->private->state != DEV_STATE_ONLINE)
 		ret = -ENODEV;
-	else if (sch->schib.scsw.actl != 0 || cdev->private->flags.doverify)
+	else if (((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
+		  !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
+		 cdev->private->flags.doverify)
 		ret = -EBUSY;
 	else
 		/* 0x00D9C4C3 == ebcdic "RDC" */
@@ -414,7 +417,9 @@
 	cdev->handler = ccw_device_wake_up;
 	if (cdev->private->state != DEV_STATE_ONLINE)
 		ret = -ENODEV;
-	else if (sch->schib.scsw.actl != 0 || cdev->private->flags.doverify)
+	else if (((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
+		  !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
+		 cdev->private->flags.doverify)
 		ret = -EBUSY;
 	else
 		/* 0x00D9C3C4 == ebcdic "RCD" */
@@ -441,12 +446,12 @@
 }
 
 /*
- * Try to issue an unconditional reserve on a boxed device.
+ * Try to break the lock on a boxed device.
  */
 int
 ccw_device_stlck(struct ccw_device *cdev)
 {
-	char buf[32];
+	void *buf, *buf2;
 	unsigned long flags;
 	struct subchannel *sch;
 	int ret;
@@ -462,16 +467,30 @@
 	CIO_TRACE_EVENT(2, "stl lock");
 	CIO_TRACE_EVENT(2, cdev->dev.bus_id);
 
+	buf = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	buf2 = kmalloc(32*sizeof(char), GFP_DMA|GFP_KERNEL);
+	if (!buf2) {
+		kfree(buf);
+		return -ENOMEM;
+	}
 	spin_lock_irqsave(&sch->lock, flags);
 	ret = cio_enable_subchannel(sch, 3);
 	if (ret)
 		goto out_unlock;
-	/* Setup ccw. This cmd code seems not to be in use elsewhere. */
+	/*
+	 * Setup ccw. We chain an unconditional reserve and a release so we
+	 * only break the lock.
+	 */
 	cdev->private->iccws[0].cmd_code = CCW_CMD_STLCK;
 	cdev->private->iccws[0].cda = (__u32) __pa(buf);
 	cdev->private->iccws[0].count = 32;
-	cdev->private->iccws[0].flags = CCW_FLAG_SLI;
-
+	cdev->private->iccws[0].flags = CCW_FLAG_CC;
+	cdev->private->iccws[1].cmd_code = CCW_CMD_RELEASE;
+	cdev->private->iccws[1].cda = (__u32) __pa(buf2);
+	cdev->private->iccws[1].count = 32;
+	cdev->private->iccws[1].flags = 0;
 	ret = cio_start(sch, cdev->private->iccws, 0);
 	if (ret) {
 		cio_disable_subchannel(sch); //FIXME: return code?
@@ -486,10 +505,13 @@
 	     (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
 	    (cdev->private->irb.scsw.cstat != 0))
 		ret = -EIO;
-
 	/* Clear irb. */
 	memset(&cdev->private->irb, 0, sizeof(struct irb));
 out_unlock:
+	if (buf)
+		kfree(buf);
+	if (buf2)
+		kfree(buf2);
 	spin_unlock_irqrestore(&sch->lock, flags);
 	return ret;
 }
diff -Nru a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
--- a/drivers/s390/cio/device_status.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/cio/device_status.c	Wed Mar 17 19:29:09 2004
@@ -99,7 +99,7 @@
 static inline int
 ccw_device_accumulate_esw_valid(struct irb *irb)
 {
-	if (irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
+	if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
 		return 0;
 	if (irb->scsw.stctl == 
 	    		(SCSW_STCTL_INTER_STATUS|SCSW_STCTL_STATUS_PEND) &&
diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
--- a/drivers/s390/cio/qdio.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/cio/qdio.c	Wed Mar 17 19:29:09 2004
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.74 $"
+#define VERSION_QDIO_C "$Revision: 1.78 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -545,6 +545,7 @@
 qdio_kick_outbound_q(struct qdio_q *q)
 {
 	int result;
+	char dbf_text[15];
 
 	QDIO_DBF_TEXT4(0,trace,"kickoutq");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -552,15 +553,75 @@
 	if (!q->siga_out)
 		return;
 
-	result=qdio_siga_output(q);
+	/* here's the story with cc=2 and busy bit set (thanks, Rick):
+	 * VM's CP could present us cc=2 and busy bit set on SIGA-write
+	 * during reconfiguration of their Guest LAN (only in HIPERS mode,
+	 * QDIO mode is asynchronous -- cc=2 and busy bit there will take
+	 * the queues down immediately; and not being under VM we have a
+	 * problem on cc=2 and busy bit set right away).
+	 *
+	 * Therefore qdio_siga_output will try for a short time constantly,
+	 * if such a condition occurs. If it doesn't change, it will
+	 * increase the busy_siga_counter and save the timestamp, and
+	 * schedule the queue for later processing (via mark_q, using the
+	 * queue tasklet). __qdio_outbound_processing will check out the
+	 * counter. If non-zero, it will call qdio_kick_outbound_q as often
+	 * as the value of the counter. This will attempt further SIGA
+	 * instructions. For each successful SIGA, the counter is
+	 * decreased, for failing SIGAs the counter remains the same, after
+	 * all.
+	 * After some time of no movement, qdio_kick_outbound_q will
+	 * finally fail and reflect corresponding error codes to call
+	 * the upper layer module and have it take the queues down.
+	 *
+	 * Note that this is a change from the original HiperSockets design
+	 * (saying cc=2 and busy bit means take the queues down), but in
+	 * these days Guest LAN didn't exist... excessive cc=2 with busy bit
+	 * conditions will still take the queues down, but the threshold is
+	 * higher due to the Guest LAN environment.
+	 */
 
-	if (!result)
-		return;
 
-	if (q->siga_error)
-		q->error_status_flags|=QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
-	q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
-	q->siga_error=result;
+	result=qdio_siga_output(q);
+
+		switch (result) {
+		case 0:
+		/* went smooth this time, reset timestamp */
+			QDIO_DBF_TEXT3(0,trace,"cc2reslv");
+			sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
+				atomic_read(&q->busy_siga_counter));
+			QDIO_DBF_TEXT3(0,trace,dbf_text);
+			q->timing.busy_start=0;
+			break;
+		case (2|QDIO_SIGA_ERROR_B_BIT_SET):
+			/* cc=2 and busy bit: */
+		atomic_inc(&q->busy_siga_counter);
+
+			/* if the last siga was successful, save
+			 * timestamp here */
+			if (!q->timing.busy_start)
+				q->timing.busy_start=NOW;
+
+			/* if we're in time, don't touch error_status_flags
+			 * and siga_error */
+			if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
+				qdio_mark_q(q);
+				break;
+			}
+			QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
+			sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
+				atomic_read(&q->busy_siga_counter));
+			QDIO_DBF_TEXT3(0,trace,dbf_text);
+			/* else fallthrough and report error */
+		default:
+			/* for plain cc=1, 2 or 3: */
+			if (q->siga_error)
+				q->error_status_flags|=
+					QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+			q->error_status_flags|=
+				QDIO_STATUS_LOOK_FOR_ERROR;
+			q->siga_error=result;
+		}
 }
 
 inline static void
@@ -599,6 +660,8 @@
 static inline void
 __qdio_outbound_processing(struct qdio_q *q)
 {
+	int siga_attempts;
+
 	QDIO_DBF_TEXT4(0,trace,"qoutproc");
 	QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
 
@@ -619,6 +682,14 @@
 	perf_stats.tl_runs++;
 #endif /* QDIO_PERFORMANCE_STATS */
 
+	/* see comment in qdio_kick_outbound_q */
+	siga_attempts=atomic_read(&q->busy_siga_counter);
+	while (siga_attempts) {
+		atomic_dec(&q->busy_siga_counter);
+		qdio_kick_outbound_q(q);
+		siga_attempts--;
+	}
+
 	if (qdio_has_outbound_q_moved(q))
 		qdio_kick_outbound_handler(q);
 
@@ -1368,6 +1439,10 @@
 			((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing:
 			 &qdio_inbound_processing);
 
+		/* actually this is not used for inbound queues. yet. */
+		atomic_set(&q->busy_siga_counter,0);
+		q->timing.busy_start=0;
+
 /*		for (j=0;j<QDIO_STATS_NUMBER;j++)
 			q->timing.last_transfer_times[j]=(qdio_get_micros()/
 							  QDIO_STATS_NUMBER)*j;
@@ -1432,6 +1507,9 @@
 		q->tasklet.func=(void(*)(unsigned long))
 			&qdio_outbound_processing;
 
+		atomic_set(&q->busy_siga_counter,0);
+		q->timing.busy_start=0;
+
 		/* fill in slib */
 		if (i>0) irq_ptr->output_qs[i-1]->slib->nsliba=
 				 (unsigned long)(q->slib);
@@ -2134,7 +2212,7 @@
 	QDIO_DBF_TEXT0(0,setup,dbf_text);
 
 	rc = qdio_shutdown(cdev, how);
-	if (rc == 0)
+	if ((rc == 0) || (rc == -EINPROGRESS))
 		rc = qdio_free(cdev);
 	return rc;
 }
@@ -2145,6 +2223,7 @@
 	struct qdio_irq *irq_ptr;
 	int i;
 	int result = 0;
+	int rc;
 	unsigned long flags;
 	int timeout;
 	char dbf_text[15];
@@ -2191,27 +2270,23 @@
 			result=-EINPROGRESS;
 	}
 
-	if (result)
-		goto out;
-
 	/* cleanup subchannel */
 	spin_lock_irqsave(get_ccwdev_lock(cdev),flags);
 	if (how&QDIO_FLAG_CLEANUP_USING_CLEAR) {
-		result = ccw_device_clear(cdev, QDIO_DOING_CLEANUP);
+		rc = ccw_device_clear(cdev, QDIO_DOING_CLEANUP);
 		timeout=QDIO_CLEANUP_CLEAR_TIMEOUT;
 	} else if (how&QDIO_FLAG_CLEANUP_USING_HALT) {
-		result = ccw_device_halt(cdev, QDIO_DOING_CLEANUP);
+		rc = ccw_device_halt(cdev, QDIO_DOING_CLEANUP);
 		timeout=QDIO_CLEANUP_HALT_TIMEOUT;
 	} else { /* default behaviour */
-		result = ccw_device_halt(cdev, QDIO_DOING_CLEANUP);
+		rc = ccw_device_halt(cdev, QDIO_DOING_CLEANUP);
 		timeout=QDIO_CLEANUP_HALT_TIMEOUT;
 	}
-	if (result == -ENODEV) {
+	if (rc == -ENODEV) {
 		/* No need to wait for device no longer present. */
 		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
-		result = 0; /* No error. */
 		spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
-	} else if (result == 0) {
+	} else if (rc == 0) {
 		qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);
 		ccw_device_set_timeout(cdev, timeout);
 		spin_unlock_irqrestore(get_ccwdev_lock(cdev),flags);
@@ -2223,6 +2298,7 @@
 		QDIO_PRINT_INFO("ccw_device_{halt,clear} returned %d for "
 				"device %s\n", result, cdev->dev.bus_id);
 		spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+		result = rc;
 		goto out;
 	}
 	if (irq_ptr->is_thinint_irq) {
diff -Nru a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
--- a/drivers/s390/cio/qdio.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/cio/qdio.h	Wed Mar 17 19:29:09 2004
@@ -1,7 +1,7 @@
 #ifndef _CIO_QDIO_H
 #define _CIO_QDIO_H
 
-#define VERSION_CIO_QDIO_H "$Revision: 1.22 $"
+#define VERSION_CIO_QDIO_H "$Revision: 1.23 $"
 
 //#define QDIO_DBF_LIKE_HELL
 
@@ -33,7 +33,8 @@
 
 #define TIQDIO_THININT_ISC 3
 #define TIQDIO_DELAY_TARGET 0
-#define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */
+#define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */
+#define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */
 #define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */
 #define IQDIO_GLOBAL_LAPS_INT 1 /* don't global summary */
 #define IQDIO_LOCAL_LAPS 4
@@ -599,7 +600,9 @@
 		int last_transfer_index; */
 
 		__u64 last_transfer_time;
+		__u64 busy_start;
 	} timing;
+	atomic_t busy_siga_counter;
         unsigned int queue_type;
 
 	/* leave this member at the end. won't be cleared in qdio_fill_qs */
diff -Nru a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
--- a/drivers/s390/net/ctcmain.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/net/ctcmain.c	Wed Mar 17 19:29:09 2004
@@ -1,5 +1,5 @@
 /*
- * $Id: ctcmain.c,v 1.56 2004/02/27 17:53:26 mschwide Exp $
+ * $Id: ctcmain.c,v 1.57 2004/03/02 15:34:01 mschwide Exp $
  *
  * CTC / ESCON network driver
  *
@@ -36,7 +36,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.56 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.57 $
  *
  */
 
@@ -319,7 +319,7 @@
 print_banner(void)
 {
 	static int printed = 0;
-	char vbuf[] = "$Revision: 1.56 $";
+	char vbuf[] = "$Revision: 1.57 $";
 	char *version = vbuf;
 
 	if (printed)
@@ -3043,26 +3043,13 @@
 		privptr->channel[direction]->protocol = privptr->protocol;
 		privptr->channel[direction]->max_bufsize = CTC_BUFSIZE_DEFAULT;
 	}
+	/* sysfs magic */
+	SET_NETDEV_DEV(dev, &cgdev->dev);
+
 	if (ctc_netdev_register(dev) != 0) {
 		ctc_free_netdevice(dev, 1);
 		goto out;
 	}
-	/* Create symlinks. */
-	if (sysfs_create_link(&cgdev->dev.kobj, &dev->class_dev.kobj,
-			      dev->name)) {
-		ctc_netdev_unregister(dev);
-		dev->priv = 0;
-		ctc_free_netdevice(dev, 1);
-		goto out;
-	}
-	if (sysfs_create_link(&dev->class_dev.kobj, &cgdev->dev.kobj,
-			      cgdev->dev.bus_id)) {
-		sysfs_remove_link(&cgdev->dev.kobj, dev->name);
-		ctc_netdev_unregister(dev);
-		dev->priv = 0;
-		ctc_free_netdevice(dev, 1);
-		goto out;
-	}
 
 	ctc_add_attributes(&cgdev->dev);
 
@@ -3118,8 +3105,6 @@
 		channel_free(priv->channel[WRITE]);
 
 	if (ndev) {
-		sysfs_remove_link(&ndev->class_dev.kobj, cgdev->dev.bus_id);
-		sysfs_remove_link(&cgdev->dev.kobj, ndev->name);
 		ctc_netdev_unregister(ndev);
 		ndev->priv = NULL;
 		ctc_free_netdevice(ndev, 1);
diff -Nru a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
--- a/drivers/s390/net/iucv.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/net/iucv.c	Wed Mar 17 19:29:09 2004
@@ -1,5 +1,5 @@
 /* 
- * $Id: iucv.c,v 1.24 2004/02/05 14:16:01 braunu Exp $
+ * $Id: iucv.c,v 1.26 2004/03/10 11:55:31 braunu Exp $
  *
  * IUCV network driver
  *
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.24 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.26 $
  *
  */
 
@@ -351,7 +351,7 @@
 static void
 iucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.24 $";
+	char vbuf[] = "$Revision: 1.26 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
@@ -670,10 +670,12 @@
 	ulong b2f0_result = 0x0deadbeef;
 
 	iucv_debug(1, "entering");
+	preempt_disable();
 	if (smp_processor_id() == 0)
 		iucv_declare_buffer_cpu0(&b2f0_result);
 	else
 		smp_call_function(iucv_declare_buffer_cpu0, &b2f0_result, 0, 1);
+	preempt_enable();
 	iucv_debug(1, "Address of EIB = %p", iucv_external_int_buffer);
 	if (b2f0_result == 0x0deadbeef)
 	    b2f0_result = 0xaa;
@@ -692,11 +694,13 @@
 {
 	iucv_debug(1, "entering");
 	if (declare_flag) {
+		preempt_disable();
 		if (smp_processor_id() == 0)
 			iucv_retrieve_buffer_cpu0(0);
 		else
 			smp_call_function(iucv_retrieve_buffer_cpu0, 0, 0, 1);
 		declare_flag = 0;
+		preempt_enable();
 	}
 	iucv_debug(1, "exiting");
 	return 0;
@@ -2216,10 +2220,12 @@
 	} u;
 
 	u.param = SetMaskFlag;
+	preempt_disable();
 	if (smp_processor_id() == 0)
 		iucv_setmask_cpu0(&u);
 	else
 		smp_call_function(iucv_setmask_cpu0, &u, 0, 1);
+	preempt_enable();
 
 	return u.result;
 }
@@ -2519,10 +2525,6 @@
 
 /**
  * Export all public stuff
- * FIXME: I have commented out all the functions that
- * 	  are not used in netiucv. Is anyone else
- * 	  using them or should some of them be made
- * 	  static / removed? pls review. Arnd
  */
 EXPORT_SYMBOL (iucv_bus);
 EXPORT_SYMBOL (iucv_root);
diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
--- a/drivers/s390/net/lcs.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/net/lcs.c	Wed Mar 17 19:29:09 2004
@@ -11,7 +11,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.67 $	 $Date: 2004/02/26 18:26:50 $
+ *    $Revision: 1.68 $	 $Date: 2004/03/02 15:34:01 $
  *
  * 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
@@ -58,7 +58,7 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.67 $"
+#define VERSION_LCS_C  "$Revision: 1.68 $"
 
 static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
 
@@ -1855,17 +1855,8 @@
 	if (register_netdev(dev) != 0)
 		goto out;
 	/* Create symlinks. */
-	if (sysfs_create_link(&ccwgdev->dev.kobj, &dev->class_dev.kobj,
-			      dev->name)) {
-		unregister_netdev(dev);
-		goto out;
-	}
-	if (sysfs_create_link(&dev->class_dev.kobj, &ccwgdev->dev.kobj,
-			      ccwgdev->dev.bus_id)) {
-		sysfs_remove_link(&ccwgdev->dev.kobj, dev->name);
-		unregister_netdev(dev);
-		goto out;
-	}
+	SET_NETDEV_DEV(dev, &ccwgdev->dev);
+
 	netif_stop_queue(dev);
 	lcs_stopcard(card);
 	return 0;
@@ -1891,8 +1882,6 @@
 	ret = lcs_stop_device(card->dev);
 	if (ret)
 		return ret;
-	sysfs_remove_link(&card->dev->class_dev.kobj, ccwgdev->dev.bus_id);
-	sysfs_remove_link(&ccwgdev->dev.kobj, card->dev->name);
 	unregister_netdev(card->dev);
 	return 0;
 }
@@ -1911,9 +1900,6 @@
 		return;
 	if (ccwgdev->state == CCWGROUP_ONLINE) {
 		lcs_stop_device(card->dev); /* Ignore rc. */
-		sysfs_remove_link(&card->dev->class_dev.kobj,
-				  ccwgdev->dev.bus_id);
-		sysfs_remove_link(&ccwgdev->dev.kobj, card->dev->name);
 		unregister_netdev(card->dev);
 	}
 	sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group);
diff -Nru a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
--- a/drivers/s390/net/netiucv.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/s390/net/netiucv.c	Wed Mar 17 19:29:09 2004
@@ -1,5 +1,5 @@
 /*
- * $Id: netiucv.c,v 1.38 2004/02/19 13:12:57 mschwide Exp $
+ * $Id: netiucv.c,v 1.45 2004/03/15 08:48:48 braunu Exp $
  *
  * IUCV network driver
  *
@@ -30,7 +30,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV network driver $Revision: 1.38 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.45 $
  *
  */
 
@@ -229,6 +229,7 @@
 	"StartWait",
 	"StopWait",
 	"Running",
+	"StartRetry",
 };
 
 /**
@@ -251,6 +252,7 @@
 	"Stop",
 	"Connection up",
 	"Connection down",
+	"Timer",
 };
 
 /**
@@ -345,11 +347,6 @@
 	CONN_STATE_TX,
 
 	/**
-	 * Terminating
-	 */
-	CONN_STATE_TERM,
-
-	/**
 	 * Error during registration.
 	 */
 	CONN_STATE_REGERR,
@@ -495,7 +492,7 @@
 netiucv_unpack_skb(struct iucv_connection *conn, struct sk_buff *pskb)
 {
 	struct net_device     *dev = conn->netdev;
-	struct netiucv_priv   *privptr = (struct netiucv_priv *)dev->priv;
+	struct netiucv_priv   *privptr = dev->priv;
 	__u16          offset = 0;
 
 	skb_put(pskb, NETIUCV_HDRLEN);
@@ -1214,7 +1211,7 @@
 static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	int          rc = 0;
-	struct netiucv_priv *privptr = (struct netiucv_priv *)dev->priv;
+	struct netiucv_priv *privptr = dev->priv;
 
 	/**
 	 * Some sanity checks ...
@@ -1290,7 +1287,6 @@
 /**
  * attributes in sysfs
  *****************************************************************************/
-#define CTRL_BUFSIZE 40
 
 static ssize_t
 user_show (struct device *dev, char *buf)
@@ -1300,7 +1296,57 @@
 	return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid));
 }
 
-static DEVICE_ATTR(user, 0444, user_show, NULL);
+static ssize_t
+user_write (struct device *dev, const char *buf, size_t count)
+{
+	struct netiucv_priv *priv = dev->driver_data;
+	struct net_device *ndev = priv->conn->netdev;
+	char    *p;
+	char    *tmp;
+	char 	username[10];
+	int 	i;
+
+	if (count>9) {
+		printk(KERN_WARNING
+			"netiucv: username too long (%d)!\n", (int)count);
+		return -EINVAL;
+	}
+
+	tmp = strsep((char **) &buf, "\n");
+	for (i=0, p=tmp; i<8 && *p; i++, p++) {
+		if (isalnum(*p) || (*p == '$'))
+			username[i]= *p;
+		else if (*p == '\n') {
+			/* trailing lf, grr */
+			break;
+		} else {
+			printk(KERN_WARNING
+				"netiucv: Invalid character in username!\n");
+			return -EINVAL;
+		}
+	}
+	while (i<9)
+		username[i++] = ' ';
+	username[9] = '\0';
+
+	if (memcmp(username, priv->conn->userid, 8) != 0) {
+		/* username changed */
+		if (ndev->flags & (IFF_UP | IFF_RUNNING)) {
+			printk(KERN_WARNING
+				"netiucv: device %s active, connected to %s\n",
+				dev->bus_id, priv->conn->userid);
+			printk(KERN_WARNING
+				"netiucv: user cannot be updated\n");
+			return -EBUSY;
+		}
+	}
+	memcpy(priv->conn->userid, username, 9);
+
+	return count;
+
+}
+
+static DEVICE_ATTR(user, 0644, user_show, user_write);
 
 static ssize_t
 buffer_show (struct device *dev, char *buf)
@@ -1317,26 +1363,30 @@
 	struct net_device *ndev = priv->conn->netdev;
 	char         *e;
 	int          bs1;
-	char         tmp[CTRL_BUFSIZE];
 
 	if (count >= 39)
 		return -EINVAL;
 
-	if (copy_from_user(tmp, buf, count))
-		 return -EFAULT;
-	tmp[count+1] = '\0';
-	bs1 = simple_strtoul(tmp, &e, 0);
+	bs1 = simple_strtoul(buf, &e, 0);
+
+	if (e && (!isspace(*e))) {
+		printk(KERN_WARNING
+			"netiucv: Invalid character in buffer!\n");
+		return -EINVAL;
+	}
+	if (bs1 > NETIUCV_BUFSIZE_MAX) {
+		printk(KERN_WARNING
+			"netiucv: Given buffer size %d too large.\n",
+			bs1);
 
-	if ((bs1 > NETIUCV_BUFSIZE_MAX) ||
-	    (e && (!isspace(*e))))
 		return -EINVAL;
+	}
 	if ((ndev->flags & IFF_RUNNING) &&
 	    (bs1 < (ndev->mtu + NETIUCV_HDRLEN + 2)))
 		return -EINVAL;
 	if (bs1 < (576 + NETIUCV_HDRLEN + NETIUCV_HDRLEN))
 		return -EINVAL;
 
-
 	priv->conn->max_buffsize = bs1;
 	if (!(ndev->flags & IFF_RUNNING))
 		ndev->mtu = bs1 - NETIUCV_HDRLEN - NETIUCV_HDRLEN;
@@ -1606,20 +1656,10 @@
 	ret = netiucv_add_files(dev);
 	if (ret)
 		goto out_unreg;
-	ret = sysfs_create_link(&dev->kobj, &ndev->class_dev.kobj, ndev->name);
-	if (ret) 
-		goto out_rm_files;
-	ret = sysfs_create_link(&ndev->class_dev.kobj, &dev->kobj, dev->bus_id);
-	if (ret)
-		goto out_rm_link;
 	dev->driver_data = priv;
 	priv->dev = dev;
 	return 0;
 
-out_rm_link:
-	sysfs_remove_link(&dev->kobj, ndev->name);
-out_rm_files:
-	netiucv_remove_files(dev);
 out_unreg:
 	device_unregister(dev);
 	return ret;
@@ -1628,12 +1668,7 @@
 static void
 netiucv_unregister_device(struct device *dev)
 {
-	struct netiucv_priv *priv = dev->driver_data;
-	struct net_device *ndev = priv->conn->netdev;
-
 	pr_debug("%s() called\n", __FUNCTION__);
-	sysfs_remove_link(&ndev->class_dev.kobj, dev->bus_id);
-	sysfs_remove_link(&dev->kobj, ndev->name);
 	netiucv_remove_files(dev);
 	device_unregister(dev);
 }
@@ -1814,7 +1849,7 @@
 {
 	char *p;
 	char username[10];
-	int i;
+	int i, ret;
 	struct net_device *dev;
 
 	if (count>9) {
@@ -1846,30 +1881,37 @@
 		return -ENODEV;
 	}
 	
-	if (register_netdev(dev)) {
-		printk(KERN_WARNING
-		       "netiucv: Could not register '%s'\n", dev->name);
-		netiucv_free_netdevice(dev);
-		return -ENODEV;
+	if ((ret = netiucv_register_device(dev, ifno)))
+		goto out_free_ndev;
+	/* sysfs magic */
+	SET_NETDEV_DEV(dev, (struct device*)((struct netiucv_priv*)dev->priv)->dev);
+	if ((ret = register_netdev(dev))) {
+		netiucv_unregister_device((struct device*)((struct netiucv_priv*)dev->priv)->dev);
+		goto out_free_ndev;
 	}
 	printk(KERN_INFO "%s: '%s'\n", dev->name, netiucv_printname(username));
-	netiucv_register_device(dev, ifno);
 	ifno++;
 	
 	return count;
+
+out_free_ndev:
+	printk(KERN_WARNING
+		       "netiucv: Could not register '%s'\n", dev->name);
+	netiucv_free_netdevice(dev);
+	return ret;
 }
 
 DRIVER_ATTR(connection, 0200, NULL, conn_write);
 
 static struct device_driver netiucv_driver = {
-	.name = "NETIUCV",
+	.name = "netiucv",
 	.bus  = &iucv_bus,
 };
 
 static void
 netiucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.38 $";
+	char vbuf[] = "$Revision: 1.45 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
diff -Nru a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c
--- a/drivers/s390/net/qeth.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/s390/net/qeth.c	Wed Mar 17 19:29:10 2004
@@ -6404,6 +6404,8 @@
 
 	QETH_DBF_CARD3(0, trace, "rgnd", card);
 
+	/* sysfs magic */
+	SET_NETDEV_DEV(card->dev, &card->gdev->dev);
 	result = register_netdev(card->dev);
 
 	return result;
@@ -6681,10 +6683,6 @@
 						   hard_start_xmit */
 
 	if (atomic_read(&card->is_registered)) {
-		/* Remove sysfs symlinks. */
-		sysfs_remove_link(&card->gdev->dev.kobj, card->dev_name);
-		sysfs_remove_link(&card->dev->class_dev.kobj,
-				  CARD_BUS_ID(card));
 		QETH_DBF_TEXT2(0, trace, "unregdev");
 		qeth_unregister_netdev(card);
 		qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME);
@@ -10694,17 +10692,6 @@
 	if (qeth_init_netdev(card))
 		goto out_remove;
 
-	if (sysfs_create_link(&card->gdev->dev.kobj, &card->dev->class_dev.kobj,
-			      card->dev_name)) {
-		qeth_unregister_netdev(card);
-		goto out_remove;
-	}
-	if (sysfs_create_link(&card->dev->class_dev.kobj, &card->gdev->dev.kobj,
-			      CARD_BUS_ID(card))) {
-		sysfs_remove_link(&card->gdev->dev.kobj, card->dev_name);
-		qeth_unregister_netdev(card);
-		goto out_remove;
-	}
 	return 0;		/* success */
 
 out_remove:
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/scsi/ide-scsi.c	Wed Mar 17 19:29:09 2004
@@ -78,6 +78,7 @@
 #define PC_DMA_IN_PROGRESS		0	/* 1 while DMA in progress */
 #define PC_WRITING			1	/* Data direction */
 #define PC_TRANSFORM			2	/* transform SCSI commands */
+#define PC_TIMEDOUT			3	/* command timed out */
 #define PC_DMA_OK			4	/* Use DMA */
 
 /*
@@ -307,6 +308,41 @@
 	return ide_do_drive_cmd(drive, rq, ide_preempt);
 }
 
+ide_startstop_t idescsi_atapi_error (ide_drive_t *drive, const char *msg, byte stat)
+{
+	struct request *rq;
+	byte err;
+
+	err = ide_dump_atapi_status(drive, msg, stat);
+
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+		return ide_stopped;
+
+	if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
+		/* force an abort */
+		HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
+
+	rq->errors++;
+	DRIVER(drive)->end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
+ide_startstop_t idescsi_atapi_abort (ide_drive_t *drive, const char *msg)
+{
+	struct request *rq;
+
+	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+	       return ide_stopped;
+
+#if IDESCSI_DEBUG_LOG
+	printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n",
+			((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
+#endif
+	rq->errors |= ERROR_MAX;
+	DRIVER(drive)->end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
 static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
 {
 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
@@ -334,7 +370,13 @@
 		kfree(rq);
 		pc = opc;
 		rq = pc->rq;
-		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
+		pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
+					((test_bit(PC_TIMEDOUT, &pc->flags)?DID_TIME_OUT:DID_OK) << 16);
+	} else if (test_bit(PC_TIMEDOUT, &pc->flags)) {
+		if (log)
+			printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
+					drive->name, pc->scsi_cmd->serial_number);
+		pc->scsi_cmd->result = DID_TIME_OUT << 16;
 	} else if (rq->errors >= ERROR_MAX) {
 		pc->scsi_cmd->result = DID_ERROR << 16;
 		if (log)
@@ -374,6 +416,19 @@
 	return IDE_MAX(WAIT_CMD, pc->timeout - jiffies);
 }
 
+static int idescsi_expiry(ide_drive_t *drive)
+{
+	idescsi_scsi_t *scsi = drive->driver_data;
+	idescsi_pc_t   *pc   = scsi->pc;
+
+#if IDESCSI_DEBUG_LOG
+	printk(KERN_WARNING "idescsi_expiry called for %lu at %lu\n", pc->scsi_cmd->serial_number, jiffies);
+#endif
+	set_bit(PC_TIMEDOUT, &pc->flags);
+
+	return 0;					/* we do not want the ide subsystem to retry */
+}
+
 /*
  *	Our interrupt handler.
  */
@@ -393,6 +448,15 @@
 	printk (KERN_INFO "ide-scsi: Reached idescsi_pc_intr interrupt handler\n");
 #endif /* IDESCSI_DEBUG_LOG */
 
+	if (test_bit(PC_TIMEDOUT, &pc->flags)){
+#if IDESCSI_DEBUG_LOG
+		printk(KERN_WARNING "idescsi_pc_intr: got timed out packet  %lu at %lu\n",
+				pc->scsi_cmd->serial_number, jiffies);
+#endif
+		/* end this request now - scsi should retry it*/
+		idescsi_end_request (drive, 1, 0);
+		return ide_stopped;
+	}
 	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
 #if IDESCSI_DEBUG_LOG
 		printk ("ide-scsi: %s: DMA complete\n", drive->name);
@@ -442,7 +506,7 @@
 				pc->actually_transferred += temp;
 				pc->current_position += temp;
 				idescsi_discard_data(drive, bcount.all - temp);
-				ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
+				ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
 				return ide_started;
 			}
 #if IDESCSI_DEBUG_LOG
@@ -467,7 +531,8 @@
 	pc->actually_transferred += bcount.all;
 	pc->current_position += bcount.all;
 
-	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);	/* And set the interrupt handler again */
+	/* And set the interrupt handler again */
+	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
 	return ide_started;
 }
 
@@ -492,7 +557,7 @@
 	if (HWGROUP(drive)->handler != NULL)
 		BUG();
 	/* Set the interrupt routine */
-	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL);
+	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
 	/* Send the actual packet */
 	atapi_output_bytes(drive, scsi->pc->c, 12);
 	if (test_bit (PC_DMA_OK, &pc->flags)) {
@@ -540,7 +605,7 @@
 		if (HWGROUP(drive)->handler != NULL)
 			BUG();
 		ide_set_handler(drive, &idescsi_transfer_pc,
-				get_timeout(pc), NULL);
+				get_timeout(pc), idescsi_expiry);
 		/* Issue the packet command */
 		HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
@@ -633,6 +698,8 @@
 	.cleanup		= idescsi_cleanup,
 	.do_request		= idescsi_do_request,
 	.end_request		= idescsi_end_request,
+	.error                  = idescsi_atapi_error,
+	.abort                  = idescsi_atapi_abort,
 	.drives			= LIST_HEAD_INIT(idescsi_driver.drives),
 };
 
@@ -852,66 +919,132 @@
 	return 1;
 }
 
-static int idescsi_abort (Scsi_Cmnd *cmd)
+static int idescsi_eh_abort (Scsi_Cmnd *cmd)
 {
-	int countdown = 8;
-	unsigned long flags;
-	idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
-	ide_drive_t *drive = scsi->drive;
+	idescsi_scsi_t *scsi  = scsihost_to_idescsi(cmd->device->host);
+	ide_drive_t    *drive = scsi->drive;
+	int		busy;
+	int             ret   = FAILED;
 
-	printk (KERN_ERR "ide-scsi: abort called for %lu\n", cmd->serial_number);
-	while (countdown--) {
-		/* is cmd active?
-		 *  need to lock so this stuff doesn't change under us */
-		spin_lock_irqsave(&ide_lock, flags);
-		if (scsi->pc && scsi->pc->scsi_cmd && 
-				scsi->pc->scsi_cmd->serial_number == cmd->serial_number) {
-			/* yep - let's give it some more time - 
-			 * we can do that, we're in _our_ error kernel thread */
-			spin_unlock_irqrestore(&ide_lock, flags);
-			scsi_sleep(HZ);
-			continue;
-		}
-		/* no, but is it queued in the ide subsystem? */
-		if (elv_queue_empty(drive->queue)) {
-			spin_unlock_irqrestore(&ide_lock, flags);
-			return SUCCESS;
-		}
-		spin_unlock_irqrestore(&ide_lock, flags);
-		schedule_timeout(HZ/10);
+	/* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
+
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number);
+
+	if (!drive) {
+		printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_abort\n");
+		WARN_ON(1);
+		goto no_drive;
+	}
+
+	/* First give it some more time, how much is "right" is hard to say :-( */
+
+	busy = ide_wait_not_busy(HWIF(drive), 100);	/* FIXME - uses mdelay which causes latency? */
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");
+
+	spin_lock_irq(&ide_lock);
+
+	/* If there is no pc running we're done (our interrupt took care of it) */
+	if (!scsi->pc) {
+		ret = SUCCESS;
+		goto ide_unlock;
 	}
-	return FAILED;
+
+	/* It's somewhere in flight. Does ide subsystem agree? */
+	if (scsi->pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
+	    elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != scsi->pc->rq) {
+		/*
+		 * FIXME - not sure this condition can ever occur
+		 */
+		printk (KERN_ERR "ide-scsi: cmd aborted!\n");
+
+		idescsi_free_bio(scsi->pc->rq->bio);
+		if (scsi->pc->rq->flags & REQ_SENSE)
+			kfree(scsi->pc->buffer);
+		kfree(scsi->pc->rq);
+		kfree(scsi->pc);
+		scsi->pc = NULL;
+
+		ret = SUCCESS;
+	}
+
+ide_unlock:
+	spin_unlock_irq(&ide_lock);
+no_drive:
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");
+
+	return ret;
 }
 
-static int idescsi_reset (Scsi_Cmnd *cmd)
+static int idescsi_eh_reset (Scsi_Cmnd *cmd)
 {
-	unsigned long flags;
 	struct request *req;
-	idescsi_scsi_t *idescsi = scsihost_to_idescsi(cmd->device->host);
-	ide_drive_t *drive = idescsi->drive;
+	idescsi_scsi_t *scsi  = scsihost_to_idescsi(cmd->device->host);
+	ide_drive_t    *drive = scsi->drive;
+	int             ready = 0;
+	int             ret   = SUCCESS;
+
+	/* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
+
+	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
+		printk (KERN_WARNING "ide-scsi: reset called for %lu\n", cmd->serial_number);
+
+	if (!drive) {
+		printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_reset\n");
+		WARN_ON(1);
+		return FAILED;
+	}
+
+	spin_lock_irq(&ide_lock);
+
+	if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
+		printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
+		spin_unlock(&ide_lock);
+		return FAILED;
+	}
+
+	/* kill current request */
+	blkdev_dequeue_request(req);
+	end_that_request_last(req);
+	idescsi_free_bio(req->bio);
+	if (req->flags & REQ_SENSE)
+		kfree(scsi->pc->buffer);
+	kfree(scsi->pc);
+	scsi->pc = NULL;
+	kfree(req);
 
-	printk (KERN_ERR "ide-scsi: reset called for %lu\n", cmd->serial_number);
-	/* first null the handler for the drive and let any process
-	 * doing IO (on another CPU) run to (partial) completion
-	 * the lock prevents processing new requests */
-	spin_lock_irqsave(&ide_lock, flags);
-	while (HWGROUP(drive)->handler) {
-		HWGROUP(drive)->handler = NULL;
-		schedule_timeout(1);
-	}
 	/* now nuke the drive queue */
 	while ((req = elv_next_request(drive->queue))) {
 		blkdev_dequeue_request(req);
 		end_that_request_last(req);
 	}
-	/* FIXME - this will probably leak memory */
+
 	HWGROUP(drive)->rq = NULL;
-	if (drive_to_idescsi(drive))
-		drive_to_idescsi(drive)->pc = NULL;
-	spin_unlock_irqrestore(&ide_lock, flags);
-	/* finally, reset the drive (and its partner on the bus...) */
-	ide_do_reset (drive);	
-	return SUCCESS;
+	HWGROUP(drive)->handler = NULL;
+	HWGROUP(drive)->busy = 1;		/* will set this to zero when ide reset finished */
+	spin_unlock_irq(&ide_lock);
+
+	ide_do_reset(drive);
+
+	/* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */
+
+	do {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		spin_unlock_irq(cmd->device->host->host_lock);
+		schedule_timeout(HZ/20);
+		spin_lock_irq(cmd->device->host->host_lock);
+	} while ( HWGROUP(drive)->handler );
+
+	ready = drive_is_ready(drive);
+	HWGROUP(drive)->busy--;
+	if (!ready) {
+		printk (KERN_ERR "ide-scsi: reset failed!\n");
+		ret = FAILED;
+	}
+
+	return ret;
 }
 
 static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev,
@@ -935,8 +1068,8 @@
 	.slave_configure        = idescsi_slave_configure,
 	.ioctl			= idescsi_ioctl,
 	.queuecommand		= idescsi_queue,
-	.eh_abort_handler	= idescsi_abort,
-	.eh_device_reset_handler = idescsi_reset,
+	.eh_abort_handler	= idescsi_eh_abort,
+	.eh_host_reset_handler  = idescsi_eh_reset,
 	.bios_param		= idescsi_bios,
 	.can_queue		= 40,
 	.this_id		= -1,
@@ -967,7 +1100,16 @@
 		return 1;
 
 	host->max_id = 1;
-	host->max_lun = 1;
+
+#if IDESCSI_DEBUG_LOG
+	if (drive->id->last_lun)
+		printk(KERN_NOTICE "%s: id->last_lun=%u\n", drive->name, drive->id->last_lun);
+#endif
+	if ((drive->id->last_lun & 0x7) != 7)
+		host->max_lun = (drive->id->last_lun & 0x7) + 1;
+	else
+		host->max_lun = 1;
+
 	drive->driver_data = host;
 	idescsi = scsihost_to_idescsi(host);
 	idescsi->drive = drive;
diff -Nru a/drivers/scsi/libata.h b/drivers/scsi/libata.h
--- a/drivers/scsi/libata.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/scsi/libata.h	Wed Mar 17 19:29:09 2004
@@ -26,7 +26,7 @@
 #define __LIBATA_H__
 
 #define DRV_NAME	"libata"
-#define DRV_VERSION	"1.01"	/* must be exactly four chars */
+#define DRV_VERSION	"1.02"	/* must be exactly four chars */
 
 struct ata_scsi_args {
 	struct ata_port		*ap;
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/scsi/sata_sil.c	Wed Mar 17 19:29:09 2004
@@ -35,7 +35,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_sil"
-#define DRV_VERSION	"0.53"
+#define DRV_VERSION	"0.54"
 
 enum {
 	sil_3112		= 0,
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/scsi/sr.c	Wed Mar 17 19:29:09 2004
@@ -698,7 +698,7 @@
 static void get_capabilities(struct scsi_cd *cd)
 {
 	unsigned char *buffer;
-	int rc, n, mrw_write = 0, mrw = 1;
+	int rc, n, mrw_write = 0, mrw = 1,ram_write=0;
 	struct scsi_mode_data data;
 	struct scsi_request *SRpnt;
 	unsigned char cmd[MAX_COMMAND_SIZE];
@@ -783,6 +783,11 @@
 	if (!mrw_write)
 		cd->cdi.mask |= CDC_MRW_W;
 
+	if (cdrom_is_random_writable(&cd->cdi, &ram_write))
+		cd->cdi.mask |= CDC_RAM;
+	if (!ram_write)
+		cd->cdi.mask |= CDC_RAM;
+
 	n = data.header_length + data.block_descriptor_length;
 	cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
 	cd->readcd_known = 1;
@@ -832,8 +837,8 @@
 	/*
 	 * if DVD-RAM of MRW-W, we are randomly writeable
 	 */
-	if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W)) !=
-			(CDC_DVD_RAM | CDC_MRW_W)) {
+	if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM)) !=
+			(CDC_DVD_RAM | CDC_MRW_W | CDC_RAM)) {
 		cd->device->writeable = 1;
 		set_disk_ro(cd->disk, 0);
 	}
diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c
--- a/drivers/serial/21285.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/serial/21285.c	Wed Mar 17 19:29:10 2004
@@ -15,6 +15,7 @@
 #include <linux/console.h>
 #include <linux/serial_core.h>
 #include <linux/serial.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -543,3 +544,4 @@
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.37 $");
+MODULE_ALIAS_CHARDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c
--- a/drivers/serial/amba.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/serial/amba.c	Wed Mar 17 19:29:09 2004
@@ -39,6 +39,7 @@
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -758,3 +759,4 @@
 MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
 MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV(SERIAL_AMBA_MAJOR, SERIAL_AMBA_MINOR);
diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c
--- a/drivers/serial/anakin.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/serial/anakin.c	Wed Mar 17 19:29:09 2004
@@ -30,6 +30,7 @@
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
+#include <linux/device.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -541,3 +542,4 @@
 MODULE_AUTHOR("Tak-Shing Chan <chan@aleph1.co.uk>");
 MODULE_SUPPORTED_DEVICE("ttyAN");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV(SERIAL_ANAKIN_MAJOR, SERIAL_ANAKIN_MINOR);
diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
--- a/drivers/serial/clps711x.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/serial/clps711x.c	Wed Mar 17 19:29:09 2004
@@ -34,6 +34,7 @@
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/spinlock.h>
+#include <linux/device.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -611,3 +612,4 @@
 MODULE_AUTHOR("Deep Blue Solutions Ltd");
 MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.42 $");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);
diff -Nru a/drivers/serial/mux.c b/drivers/serial/mux.c
--- a/drivers/serial/mux.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/serial/mux.c	Wed Mar 17 19:29:10 2004
@@ -25,6 +25,7 @@
 #include <linux/console.h>
 #include <linux/slab.h>
 #include <linux/delay.h> /* for udelay */
+#include <linux/device.h>
 #include <asm/io.h>
 #include <asm/parisc-device.h>
 
@@ -535,3 +536,4 @@
 MODULE_AUTHOR("Ryan Bradetich");
 MODULE_DESCRIPTION("Serial MUX driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(MUX_MAJOR);
diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
--- a/drivers/serial/sa1100.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/serial/sa1100.c	Wed Mar 17 19:29:09 2004
@@ -953,3 +953,4 @@
 MODULE_AUTHOR("Deep Blue Solutions Ltd");
 MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.50 $");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_SA1100_MAJOR);
diff -Nru a/drivers/usb/Kconfig b/drivers/usb/Kconfig
--- a/drivers/usb/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/Kconfig	Wed Mar 17 19:29:09 2004
@@ -6,32 +6,36 @@
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
 config USB
-	tristate "Support for USB"
+	tristate "Support for Host-side USB"
 	depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610
 	---help---
 	  Universal Serial Bus (USB) is a specification for a serial bus
 	  subsystem which offers higher speeds and more features than the
 	  traditional PC serial port.  The bus supplies power to peripherals
 	  and allows for hot swapping.  Up to 127 USB peripherals can be
-	  connected to a single USB port in a tree structure.  The USB port is
-	  the root of the tree, the peripherals are the leaves and the inner
-	  nodes are special USB devices called hubs.  Many newer PC's have USB
-	  ports and newer peripherals such as scanners, keyboards, mice,
-	  modems, and printers support the USB protocol and can be connected
-	  to the PC via those ports.
+	  connected to a single USB host in a tree structure.
+	  
+	  The USB host is the root of the tree, the peripherals are the
+	  leaves and the inner nodes are special USB devices called hubs.
+	  Most PCs now have USB host ports, used to connect peripherals
+	  such as scanners, keyboards, mice, modems, cameras, disks,
+	  flash memory, network links, and printers to the PC.
 
-	  Say Y here if your computer has a USB port and you want to use USB
-	  devices.  You then need to say Y to at least one of "UHCI HCD support"
-	  or "OHCI HCD support" below (the type of interface that the USB hardware
-	  in your computer provides to the operating system) and then choose
-	  from amongst the drivers for USB peripherals.  You may want to check
-	  out the information provided in <file:Documentation/usb/> and
-	  especially the links given in <file:Documentation/usb/usb-help.txt>.
+	  Say Y here if your computer has a host-side USB port and you want
+	  to use USB devices.  You then need to say Y to at least one of the
+	  Host Controller Driver (HCD) options below.  Choose a USB 1.1
+	  controller, such as "UHCI HCD support" or "OHCI HCD support",
+	  and "EHCI HCD (USB 2.0) support" except for older systems that
+	  do not have USB 2.0 support.  It doesn't normally hurt to select
+	  them all if you are not certain.
 
-	  If you have a new USB 2.0 High Speed system, you should also choose
-	  "EHCI HCD (USB 2.0) support" as well as at least one of UHCI or OHCI.
+	  If your system has a device-side USB port, used in the peripheral
+	  side of the USB protocol, see the "USB Gadget" framework instead.
 
-	  It doesn't normally hurt to select them all if you are not certain.
+	  After choosing your HCD, then select drivers for the USB peripherals
+	  you'll be using.  You may want to check out the information provided
+	  in <file:Documentation/usb/> and especially the links given in
+	  <file:Documentation/usb/usb-help.txt>.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbcore.
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/Makefile	Wed Mar 17 19:29:10 2004
@@ -20,10 +20,15 @@
 obj-$(CONFIG_USB_STORAGE)	+= storage/
 
 obj-$(CONFIG_USB_AIPTEK)	+= input/
+obj-$(CONFIG_USB_ATI_REMOTE)	+= input/
 obj-$(CONFIG_USB_HID)		+= input/
 obj-$(CONFIG_USB_KBD)		+= input/
+obj-$(CONFIG_USB_KBTAB)		+= input/
 obj-$(CONFIG_USB_MOUSE)		+= input/
+obj-$(CONFIG_USB_MTOUCH)	+= input/
+obj-$(CONFIG_USB_POWERMATE)	+= input/
 obj-$(CONFIG_USB_WACOM)		+= input/
+obj-$(CONFIG_USB_XPAD)		+= input/
 
 obj-$(CONFIG_USB_DABUSB)	+= media/
 obj-$(CONFIG_USB_DSBR)		+= media/
@@ -50,7 +55,6 @@
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
 obj-$(CONFIG_USB_AUERSWALD)	+= misc/
-obj-$(CONFIG_USB_BRLVGER)	+= misc/
 obj-$(CONFIG_USB_EMI26)		+= misc/
 obj-$(CONFIG_USB_LCD)		+= misc/
 obj-$(CONFIG_USB_LEGOTOWER)	+= misc/
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/class/audio.c	Wed Mar 17 19:29:10 2004
@@ -3,7 +3,7 @@
 /*
  *	audio.c  --  USB Audio Class driver
  *
- *	Copyright (C) 1999, 2000, 2001
+ *	Copyright (C) 1999, 2000, 2001, 2003, 2004
  *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
  *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
@@ -101,6 +101,11 @@
  *              Fix SNDCTL_DSP_STEREO API violation
  * 2003-04-08:	Oliver Neukum (oliver@neukum.name):
  *		Setting a configuration is done by usbcore and must not be overridden
+ * 2004-02-27:  Workaround for broken synch descriptors
+ * 2004-03-07:	Alan Stern <stern@rowland.harvard.edu>
+ *		Add usb_ifnum_to_if() and usb_altnum_to_altsetting() support.
+ *		Use the in-memory descriptors instead of reading them from the device.
+ * 
  */
 
 /*
@@ -141,8 +146,8 @@
  *
  * How does the parsing work? First, all interfaces are searched
  * for an AudioControl class interface. If found, the config descriptor
- * that belongs to the current configuration is fetched from the device.
- * Then the HEADER descriptor is fetched. It contains a list of
+ * that belongs to the current configuration is searched and
+ * the HEADER descriptor is found. It contains a list of
  * all AudioStreaming and MIDIStreaming devices. This list is then walked,
  * and all AudioStreaming interfaces are classified into input and output
  * interfaces (according to the endpoint0 direction in altsetting1) (MIDIStreaming
@@ -1512,7 +1517,6 @@
 static int set_format_in(struct usb_audiodev *as)
 {
 	struct usb_device *dev = as->state->usbdev;
-	struct usb_host_config *config = dev->actconfig;
 	struct usb_host_interface *alts;
 	struct usb_interface *iface;
 	struct usbin *u = &as->usbin;
@@ -1522,9 +1526,9 @@
 	unsigned char data[3];
 	int fmtnr, ret;
 
-	if (u->interface < 0 || u->interface >= config->desc.bNumInterfaces)
+	iface = usb_ifnum_to_if(dev, u->interface);
+	if (!iface)
 		return 0;
-	iface = config->interface[u->interface];
 
 	fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate);
 	if (fmtnr < 0) {
@@ -1533,7 +1537,7 @@
 	}
 
 	fmt = as->fmtin + fmtnr;
-	alts = &iface->altsetting[fmt->altsetting];
+	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
 	u->format = fmt->format;
 	u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf);
 	u->syncpipe = u->syncinterval = 0;
@@ -1542,18 +1546,20 @@
 		    alts->endpoint[1].desc.bmAttributes != 0x01 ||
 		    alts->endpoint[1].desc.bSynchAddress != 0 ||
 		    alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress & 0x7f)) {
-			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
+			printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims adaptive in "
+			       "but has invalid synch pipe; treating as asynchronous in\n",
 			       dev->devnum, u->interface, fmt->altsetting);
-			return -1;
+		} else {
+			u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
+			u->syncinterval = alts->endpoint[1].desc.bRefresh;
 		}
-		u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
-		u->syncinterval = alts->endpoint[1].desc.bRefresh;
 	}
 	if (d->srate < fmt->sratelo)
 		d->srate = fmt->sratelo;
 	if (d->srate > fmt->sratehi)
 		d->srate = fmt->sratehi;
-	dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", alts->desc.bInterfaceNumber, fmt->altsetting));
+	dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n",
+			u->interface, fmt->altsetting));
 	if (usb_set_interface(dev, alts->desc.bInterfaceNumber, fmt->altsetting) < 0) {
 		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
 		       dev->devnum, u->interface, fmt->altsetting);
@@ -1600,7 +1606,6 @@
 static int set_format_out(struct usb_audiodev *as)
 {
 	struct usb_device *dev = as->state->usbdev;
-	struct usb_host_config *config = dev->actconfig;
 	struct usb_host_interface *alts;
 	struct usb_interface *iface;	
 	struct usbout *u = &as->usbout;
@@ -1610,9 +1615,9 @@
 	unsigned char data[3];
 	int fmtnr, ret;
 
-	if (u->interface < 0 || u->interface >= config->desc.bNumInterfaces)
+	iface = usb_ifnum_to_if(dev, u->interface);
+	if (!iface)
 		return 0;
-	iface = config->interface[u->interface];
 
 	fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate);
 	if (fmtnr < 0) {
@@ -1622,7 +1627,7 @@
 
 	fmt = as->fmtout + fmtnr;
 	u->format = fmt->format;
-	alts = &iface->altsetting[fmt->altsetting];
+	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
 	u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf);
 	u->syncpipe = u->syncinterval = 0;
 	if ((alts->endpoint[0].desc.bmAttributes & 0x0c) == 0x04) {
@@ -1637,18 +1642,20 @@
 		    alts->endpoint[1].desc.bmAttributes != 0x01 ||
 		    alts->endpoint[1].desc.bSynchAddress != 0 ||
 		    alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress | 0x80)) {
-			printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
+			printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims asynch out "
+			       "but has invalid synch pipe; treating as adaptive out\n",
 			       dev->devnum, u->interface, fmt->altsetting);
-			return -1;
+		} else {
+			u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
+			u->syncinterval = alts->endpoint[1].desc.bRefresh;
 		}
-		u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
-		u->syncinterval = alts->endpoint[1].desc.bRefresh;
 	}
 	if (d->srate < fmt->sratelo)
 		d->srate = fmt->sratelo;
 	if (d->srate > fmt->sratehi)
 		d->srate = fmt->sratehi;
-	dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", alts->desc.bInterfaceNumber, fmt->altsetting));
+	dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n",
+			u->interface, fmt->altsetting));
 	if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
 		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
 		       dev->devnum, u->interface, fmt->altsetting);
@@ -2697,7 +2704,6 @@
 	struct usb_audiodev *as = (struct usb_audiodev *)file->private_data;
 	struct usb_audio_state *s;
 	struct usb_device *dev;
-	struct usb_interface *iface;
 
 	lock_kernel();
 	s = as->state;
@@ -2707,19 +2713,15 @@
 	down(&open_sem);
 	if (file->f_mode & FMODE_WRITE) {
 		usbout_stop(as);
-		if (dev && as->usbout.interface >= 0) {
-			iface = dev->actconfig->interface[as->usbout.interface];
-			usb_set_interface(dev, iface->altsetting->desc.bInterfaceNumber, 0);
-		}
+		if (dev && as->usbout.interface >= 0)
+			usb_set_interface(dev, as->usbout.interface, 0);
 		dmabuf_release(&as->usbout.dma);
 		usbout_release(as);
 	}
 	if (file->f_mode & FMODE_READ) {
 		usbin_stop(as);
-		if (dev && as->usbin.interface >= 0) {
-			iface = dev->actconfig->interface[as->usbin.interface];
-			usb_set_interface(dev, iface->altsetting->desc.bInterfaceNumber, 0);
-		}
+		if (dev && as->usbin.interface >= 0)
+			usb_set_interface(dev, as->usbin.interface, 0);
 		dmabuf_release(&as->usbin.dma);
 		usbin_release(as);
 	}
@@ -2824,12 +2826,11 @@
 {
 	struct usb_device *dev = s->usbdev;
 	struct usb_audiodev *as;
-	struct usb_host_config *config = dev->actconfig;
 	struct usb_host_interface *alts;
 	struct usb_interface *iface;
 	struct audioformat *fp;
 	unsigned char *fmt, *csep;
-	unsigned int i, j, k, format;
+	unsigned int i, j, k, format, idx;
 
 	if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL)))
 		return;
@@ -2870,9 +2871,10 @@
 	/* search for input formats */
 	if (asifin >= 0) {
 		as->usbin.flags = FLG_CONNECTED;
-		iface = config->interface[asifin];
-		for (i = 0; i < iface->num_altsetting; i++) {
-			alts = &iface->altsetting[i];
+		iface = usb_ifnum_to_if(dev, asifin);
+		for (idx = 0; idx < iface->num_altsetting; idx++) {
+			alts = &iface->altsetting[idx];
+			i = alts->desc.bAlternateSetting;
 			if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2)
 				continue;
 			if (alts->desc.bNumEndpoints < 1) {
@@ -2951,14 +2953,15 @@
 	/* search for output formats */
 	if (asifout >= 0) {
 		as->usbout.flags = FLG_CONNECTED;
-		iface = config->interface[asifout];
-		for (i = 0; i < iface->num_altsetting; i++) {
-			alts = &iface->altsetting[i];
+		iface = usb_ifnum_to_if(dev, asifout);
+		for (idx = 0; idx < iface->num_altsetting; idx++) {
+			alts = &iface->altsetting[idx];
+			i = alts->desc.bAlternateSetting;
 			if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2)
 				continue;
 			if (alts->desc.bNumEndpoints < 1) {
 				/* altsetting 0 should never have iso EPs */
-				if (alts->desc.bAlternateSetting != 0)
+				if (i != 0)
 				printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", 
 				       dev->devnum, asifout, i);
 				continue;
@@ -3655,8 +3658,8 @@
 static struct usb_audio_state *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
 {
 	struct usb_audio_state *s;
-	struct usb_host_config *config = dev->actconfig;
 	struct usb_interface *iface;
+	struct usb_host_interface *alt;
 	unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES];
 	unsigned char *p1;
 	unsigned int i, j, k, numifin = 0, numifout = 0;
@@ -3685,54 +3688,63 @@
 		       dev->devnum, ctrlif);
 	for (i = 0; i < p1[7]; i++) {
 		j = p1[8+i];
-		if (j >= config->desc.bNumInterfaces) {
+		iface = usb_ifnum_to_if(dev, j);
+		if (!iface) {
 			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u does not exist\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
-		iface = config->interface[j];
-		if (iface->altsetting[0].desc.bInterfaceClass != USB_CLASS_AUDIO) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n",
-			       dev->devnum, ctrlif, j);
+		if (iface->num_altsetting == 1) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif);
 			continue;
 		}
-		if (iface->altsetting[0].desc.bInterfaceSubClass == 3) {
-			printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n",
+		alt = usb_altnum_to_altsetting(iface, 0);
+		if (!alt) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 0\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
-		if (iface->altsetting[0].desc.bInterfaceSubClass != 2) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n",
+		if (alt->desc.bInterfaceClass != USB_CLASS_AUDIO) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
-		if (iface->num_altsetting == 0) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has no working interface.\n", dev->devnum, ctrlif);
+		if (alt->desc.bInterfaceSubClass == 3) {
+			printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n",
+			       dev->devnum, ctrlif, j);
 			continue;
 		}
-		if (iface->num_altsetting == 1) {
-			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif);
+		if (alt->desc.bInterfaceSubClass != 2) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n",
+			       dev->devnum, ctrlif, j);
 			continue;
 		}
-		if (iface->altsetting[0].desc.bNumEndpoints > 0) {
+		if (alt->desc.bNumEndpoints > 0) {
 			/* Check all endpoints; should they all have a bandwidth of 0 ? */
-			for (k = 0; k < iface->altsetting[0].desc.bNumEndpoints; k++) {
-				if (iface->altsetting[0].endpoint[k].desc.wMaxPacketSize > 0) {
+			for (k = 0; k < alt->desc.bNumEndpoints; k++) {
+				if (alt->endpoint[k].desc.wMaxPacketSize > 0) {
 					printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k);
 					break;
 				}
 			}
-			if (k < iface->altsetting[0].desc.bNumEndpoints)
+			if (k < alt->desc.bNumEndpoints)
 				continue;
 		}
-		if (iface->altsetting[1].desc.bNumEndpoints < 1) {
+
+		alt = usb_altnum_to_altsetting(iface, 1);
+		if (!alt) {
+			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 1\n",
+			       dev->devnum, ctrlif, j);
+			continue;
+		}
+		if (alt->desc.bNumEndpoints < 1) {
 			printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n",
 			       dev->devnum, ctrlif, j);
 			continue;
 		}
 		/* note: this requires the data endpoint to be ep0 and the optional sync
 		   ep to be ep1, which seems to be the case */
-		if (iface->altsetting[1].endpoint[0].desc.bEndpointAddress & USB_DIR_IN) {
+		if (alt->endpoint[0].desc.bEndpointAddress & USB_DIR_IN) {
 			if (numifin < USB_MAXINTERFACES) {
 				ifin[numifin++] = j;
 				usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
@@ -3779,12 +3791,9 @@
 			   const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev (intf);
-	struct usb_host_config *config = dev->actconfig;	
 	struct usb_audio_state *s;
 	unsigned char *buffer;
-	unsigned char buf[8];
-	unsigned int i, buflen;
-	int ret;
+	unsigned int buflen;
 
 #if 0
 	printk(KERN_DEBUG "usbaudio: Probing if %i: IC %x, ISC %x\n", ifnum,
@@ -3796,26 +3805,8 @@
 	 * audiocontrol interface found
 	 * find which configuration number is active
 	 */
-	i = dev->actconfig - config;
-
-	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buf, 8);
-	if (ret < 0) {
-		printk(KERN_ERR "usbaudio: cannot get first 8 bytes of config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
-		return -EIO;
-	}
-	if (buf[1] != USB_DT_CONFIG || buf[0] < 9) {
-		printk(KERN_ERR "usbaudio: invalid config descriptor %d of device %d\n", i, dev->devnum);
-		return -EIO;
-	}
-	buflen = buf[2] | (buf[3] << 8);
-	if (!(buffer = kmalloc(buflen, GFP_KERNEL)))
-		return -ENOMEM;
-	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen);
-	if (ret < 0) {
-		kfree(buffer);
-		printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret);
-		return -EIO;
-	}
+	buffer = dev->rawdescriptors[dev->actconfig - dev->config];
+	buflen = dev->actconfig->desc.wTotalLength;
 	s = usb_audio_parsecontrol(dev, buffer, buflen, intf->altsetting->desc.bInterfaceNumber);
 	if (s) {
 		usb_set_intfdata (intf, s);
diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
--- a/drivers/usb/class/bluetty.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/class/bluetty.c	Wed Mar 17 19:29:10 2004
@@ -1025,7 +1025,7 @@
 	int num_bulk_in = 0;
 	int num_bulk_out = 0;
 
-	interface = &intf->altsetting[0];
+	interface = intf->cur_altsetting;
 	control_out_endpoint = interface->desc.bInterfaceNumber;
 
 	/* find the endpoints that we need */
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/class/cdc-acm.c	Wed Mar 17 19:29:09 2004
@@ -595,12 +595,12 @@
 			 * is there it's not for call management ... so use
 			 * the cdc union descriptor whenever there is one.
 			 */
-			ifcom = intf->altsetting + 0;
+			ifcom = intf->cur_altsetting;
 			if (intf == cfacm->interface[j]) {
-				ifdata = cfacm->interface[j + 1]->altsetting + 0;
+				ifdata = cfacm->interface[j + 1]->cur_altsetting;
 				data = cfacm->interface[j + 1];
 			} else if (intf == cfacm->interface[j + 1]) {
-				ifdata = cfacm->interface[j]->altsetting + 0;
+				ifdata = cfacm->interface[j]->cur_altsetting;
 				data = cfacm->interface[j];
 			} else
 				continue;
diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
--- a/drivers/usb/class/usb-midi.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/class/usb-midi.c	Wed Mar 17 19:29:09 2004
@@ -39,9 +39,6 @@
 #include <linux/init.h>
 #include <asm/semaphore.h>
 
-/** This declaration is missing from linux/usb.h **/
-extern int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size);
-
 #include "usb-midi.h"
 
 /* ------------------------------------------------------------------------- */
@@ -1519,15 +1516,17 @@
 static int get_alt_setting( struct usb_device *d, int ifnum )
 {
 	int alts, alt=0;
+	struct usb_interface *iface;
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *ep;
 	int epin, epout;
 	int i;
 
-	alts = d->actconfig->interface[ifnum]->num_altsetting;
+	iface = usb_ifnum_to_if( d, ifnum );
+	alts = iface->num_altsetting;
 
 	for ( alt=0 ; alt<alts ; alt++ ) {
-		interface = &d->actconfig->interface[ifnum]->altsetting[alt];
+		interface = &iface->altsetting[alt];
 		epin = -1;
 		epout = -1;
 
@@ -1542,7 +1541,7 @@
 				epout = i;
 			}
 			if ( epin >= 0 && epout >= 0 ) {
-				return alt;
+				return interface->desc.bAlternateSetting;
 			}
 		}
 	}
@@ -1780,12 +1779,13 @@
  *  Called by usb_midi_probe();
  **/
 
-static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s)
+static int detect_yamaha_device( struct usb_device *d,
+		struct usb_interface *iface, unsigned int ifnum,
+		struct usb_midi_state *s)
 {
-	struct usb_host_config *c = d->actconfig;
 	struct usb_host_interface *interface;
 	struct usb_midi_device *u;
-	unsigned char buf[USB_DT_CONFIG_SIZE], *buffer;
+	unsigned char *buffer;
 	int bufSize;
 	int i;
 	int alts=-1;
@@ -1795,13 +1795,13 @@
 		return -EINVAL;
 	}
 
-	for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) {
-		interface = c->interface[ifnum]->altsetting + i;
+	for ( i=0 ; i < iface->num_altsetting; i++ ) {
+		interface = iface->altsetting + i;
 
 		if ( interface->desc.bInterfaceClass != 255 ||
 		     interface->desc.bInterfaceSubClass != 0 )
 			continue;
-		alts = i;
+		alts = interface->desc.bAlternateSetting;
 	}
 	if ( alts == -1 ) {
 		return -EINVAL;
@@ -1810,30 +1810,11 @@
 	printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n",
 	       d->descriptor.idVendor, d->descriptor.idProduct, ifnum);
 
-	ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE );
-	if ( ret < 0 ) {
-		printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret);
-		return -EINVAL;
-	}
-	if ( buf[1] != USB_DT_CONFIG || buf[0] < USB_DT_CONFIG_SIZE ) {
-		printk(KERN_INFO "usb-midi: config not as expected.\n");
-		return -EINVAL;
-	}
-	bufSize = buf[2] | buf[3]<<8;
-	buffer = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL);
-	if ( !buffer ) {
-		printk(KERN_INFO "usb-midi: Could not allocate memory.\n");
-		return -EINVAL;
-	}
-	ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buffer, bufSize );
-	if ( ret < 0 ) {
-		printk(KERN_INFO "usb-midi: Could not get full config (error=%d).\n", ret);
-		kfree(buffer);
-		return -EINVAL;
-	}
+	i = d->actconfig - d->config;
+	buffer = d->rawdescriptors[i];
+	bufSize = d->actconfig->desc.wTotalLength;
 
 	u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1);
-	kfree(buffer);
 	if ( u == NULL ) {
 		return -EINVAL;
 	}
@@ -1878,24 +1859,25 @@
  *  Returns 0 on success, negative on failure.
  * Called by usb_midi_probe();
  **/
-static int detect_midi_subclass(struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s)
+static int detect_midi_subclass(struct usb_device *d,
+		struct usb_interface *iface, unsigned int ifnum,
+		struct usb_midi_state *s)
 {
-	struct usb_host_config *c = d->actconfig;
 	struct usb_host_interface *interface;
 	struct usb_midi_device *u;
-	unsigned char buf[USB_DT_CONFIG_SIZE], *buffer;
+	unsigned char *buffer;
 	int bufSize;
 	int i;
 	int alts=-1;
 	int ret;
 
-	for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) {
-		interface = c->interface[ifnum]->altsetting + i;
+	for ( i=0 ; i < iface->num_altsetting; i++ ) {
+		interface = iface->altsetting + i;
 
 		if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO ||
 		     interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING )
 			continue;
-		alts = i;
+		alts = interface->desc.bAlternateSetting;
 	}
 	if ( alts == -1 ) {
 		return -EINVAL;
@@ -1915,30 +1897,11 @@
 	   descriptor they modify or extend.
 	*/
 
-	ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE );
-	if ( ret < 0 ) {
-		printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret);
-		return -EINVAL;
-	}
-	if ( buf[1] != USB_DT_CONFIG || buf[0] < USB_DT_CONFIG_SIZE ) {
-		printk(KERN_INFO "usb-midi: config not as expected.\n");
-		return -EINVAL;
-	}
-	bufSize = buf[2] | buf[3]<<8;
-	buffer = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL);
-	if ( !buffer ) {
-		printk(KERN_INFO "usb-midi: Could not allocate memory.\n");
-		return -EINVAL;
-	}
-	ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buffer, bufSize );
-	if ( ret < 0 ) {
-		printk(KERN_INFO "usb-midi: Could not get full config (error=%d).\n", ret);
-		kfree(buffer);
-		return -EINVAL;
-	}
+	i = d->actconfig - d->config;
+	buffer = d->rawdescriptors[i];
+	bufSize = d->actconfig->desc.wTotalLength;
 
 	u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0);
-	kfree(buffer);
 	if ( u == NULL ) {
 		return -EINVAL;
 	}
@@ -2002,7 +1965,7 @@
 {
 	struct usb_midi_state *s;
 	struct usb_device *dev = interface_to_usbdev(intf);
-	int ifnum = intf->altsetting->desc.bInterfaceNumber;
+	int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 
 	s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL);
 	if ( !s )
@@ -2018,9 +1981,9 @@
 
 	if (
 		detect_by_hand( dev, ifnum, s ) &&
-		detect_midi_subclass( dev, ifnum, s ) &&
+		detect_midi_subclass( dev, intf, ifnum, s ) &&
 		detect_vendor_specific_device( dev, ifnum, s ) &&
-		detect_yamaha_device( dev, ifnum, s) ) {
+		detect_yamaha_device( dev, intf, ifnum, s) ) {
 		kfree(s);
 		return -EIO;
 	}
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/class/usblp.c	Wed Mar 17 19:29:09 2004
@@ -133,6 +133,7 @@
 	wait_queue_head_t	wait;			/* Zzzzz ... */
 	int			readcount;		/* Counter for reads */
 	int			ifnum;			/* Interface number */
+	struct usb_interface	*intf;			/* The interface */
 	/* Alternate-setting numbers and endpoints for each protocol
 	 * (7/1/{index=1,2,3}) that the device supports: */
 	struct {
@@ -609,8 +610,10 @@
 	while (writecount < count) {
 		if (!usblp->wcomplete) {
 			barrier();
-			if (file->f_flags & O_NONBLOCK)
+			if (file->f_flags & O_NONBLOCK) {
+				writecount += transfer_length;
 				return writecount ? writecount : -EAGAIN;
+			}
 
 			timeout = USBLP_WRITE_TIMEOUT;
 			add_wait_queue(&usblp->wait, &wait);
@@ -670,7 +673,8 @@
 
 		usblp->writeurb->transfer_buffer_length = transfer_length;
 
-		if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount, transfer_length)) {
+		if (copy_from_user(usblp->writeurb->transfer_buffer, 
+				   buffer + writecount, transfer_length)) {
 			up(&usblp->sem);
 			return writecount ? writecount : -EFAULT;
 		}
@@ -837,7 +841,8 @@
 	usblp->dev = dev;
 	init_MUTEX (&usblp->sem);
 	init_waitqueue_head(&usblp->wait);
-	usblp->ifnum = intf->altsetting->desc.bInterfaceNumber;
+	usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+	usblp->intf = intf;
 
 	usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!usblp->writeurb) {
@@ -973,7 +978,7 @@
 	struct usb_endpoint_descriptor *epd, *epwrite, *epread;
 	int p, i, e;
 
-	if_alt = usblp->dev->actconfig->interface[usblp->ifnum];
+	if_alt = usblp->intf;
 
 	for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
 		usblp->protocol[p].alt_setting = -1;
@@ -1022,7 +1027,8 @@
 			epread = NULL;
 		}
 
-		usblp->protocol[ifd->desc.bInterfaceProtocol].alt_setting = i;
+		usblp->protocol[ifd->desc.bInterfaceProtocol].alt_setting =
+				ifd->desc.bAlternateSetting;
 		usblp->protocol[ifd->desc.bInterfaceProtocol].epwrite = epwrite;
 		usblp->protocol[ifd->desc.bInterfaceProtocol].epread = epread;
 	}
diff -Nru a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
--- a/drivers/usb/core/buffer.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/core/buffer.c	Wed Mar 17 19:29:10 2004
@@ -51,8 +51,8 @@
  * @hcd: the bus whose buffer pools are to be initialized
  * Context: !in_interrupt()
  *
- * Call this as part of initializing a host controller that uses the pci dma
- * memory allocators.  It initializes some pools of dma-consistent memory that
+ * Call this as part of initializing a host controller that uses the dma
+ * memory allocators.  It initializes some pools of dma-coherent memory that
  * will be shared by all drivers using that controller, or returns a negative
  * errno value on error.
  *
@@ -115,6 +115,12 @@
 	struct usb_hcd		*hcd = bus->hcpriv;
 	int 			i;
 
+	/* some USB hosts just use PIO */
+	if (!bus->controller->dma_mask) {
+		*dma = ~(dma_addr_t) 0;
+		return kmalloc (size, mem_flags);
+	}
+
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 		if (size <= pool_max [i])
 			return dma_pool_alloc (hcd->pool [i], mem_flags, dma);
@@ -134,6 +140,12 @@
 
 	if (!addr)
 		return;
+
+	if (!bus->controller->dma_mask) {
+		kfree (addr);
+		return;
+	}
+
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 		if (size <= pool_max [i]) {
 			dma_pool_free (hcd->pool [i], addr, dma);
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/config.c	Wed Mar 17 19:29:09 2004
@@ -72,13 +72,10 @@
 	return buffer - buffer0;
 }
 
-static void usb_release_intf(struct device *dev)
+static void usb_free_intf(struct usb_interface *intf)
 {
-	struct usb_interface *intf;
 	int j;
 
-	intf = to_usb_interface(dev);
-
 	if (intf->altsetting) {
 		for (j = 0; j < intf->num_altsetting; j++) {
 			struct usb_host_interface *as = &intf->altsetting[j];
@@ -235,8 +232,6 @@
 			return -ENOMEM;
 		}
 		memset(interface, 0, sizeof(struct usb_interface));
-		interface->dev.release = usb_release_intf;
-		device_initialize(&interface->dev);
 	}
 
 	/* Go through the descriptors, checking their length and counting the
@@ -374,7 +369,7 @@
 			struct usb_interface *ifp = cf->interface[i];
 
 			if (ifp)
-				put_device(&ifp->dev);
+				usb_free_intf(ifp);
 		}
 	}
 	kfree(dev->config);
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/devio.c	Wed Mar 17 19:29:09 2004
@@ -430,19 +430,14 @@
 
 static int findintfif(struct usb_device *dev, unsigned int ifn)
 {
-	unsigned int i, j;
-        struct usb_interface *iface;
-	struct usb_host_interface *alts;
+	unsigned int i;
 
 	if (ifn & ~0xff)
 		return -EINVAL;
 	for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
-		iface = dev->actconfig->interface[i];
-		for (j = 0; j < iface->num_altsetting; j++) {
-                        alts = &iface->altsetting[j];
-			if (alts->desc.bInterfaceNumber == ifn)
-				return i;
-		}
+		if (dev->actconfig->interface[i]->
+				altsetting[0].desc.bInterfaceNumber == ifn)
+			return i;
 	}
 	return -ENOENT; 
 }
@@ -688,9 +683,7 @@
 		return -EFAULT;
 	if ((ret = findintfif(ps->dev, gd.interface)) < 0)
 		return ret;
-	interface = usb_ifnum_to_if(ps->dev, gd.interface);
-	if (!interface)
-		return -EINVAL;
+	interface = ps->dev->actconfig->interface[ret];
 	if (!interface->driver)
 		return -ENODATA;
 	strcpy(gd.driver, interface->driver->name);
@@ -744,9 +737,7 @@
 		return -EFAULT;
 	if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
 		return ret;
-	interface = usb_ifnum_to_if(ps->dev, setintf.interface);
-	if (!interface)
-		return -EINVAL;
+	interface = ps->dev->actconfig->interface[ret];
 	if (interface->driver) {
 		if ((ret = checkintf(ps, ret)))
 			return ret;
diff -Nru a/drivers/usb/core/driverfs.c b/drivers/usb/core/driverfs.c
--- a/drivers/usb/core/driverfs.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/driverfs.c	Wed Mar 17 19:29:09 2004
@@ -166,13 +166,9 @@
 static ssize_t								\
 show_##field (struct device *dev, char *buf)				\
 {									\
-	struct usb_interface *intf;					\
-	int alt;							\
+	struct usb_interface *intf = to_usb_interface (dev);		\
 									\
-	intf = to_usb_interface (dev);					\
-	alt = intf->act_altsetting;					\
-									\
-	return sprintf (buf, format_string, intf->altsetting[alt].desc.field); \
+	return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
 }									\
 static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
 
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/hcd-pci.c	Wed Mar 17 19:29:09 2004
@@ -147,8 +147,12 @@
 	hcd->driver = driver;
 	hcd->description = driver->description;
 	hcd->self.bus_name = pci_name(dev);
+#ifdef CONFIG_PCI_NAMES
+	hcd->product_desc = dev->pretty_name;
+#else
 	if (hcd->product_desc == NULL)
 		hcd->product_desc = "USB Host Controller";
+#endif
 	hcd->self.controller = &dev->dev;
 
 	if ((retval = hcd_buffer_create (hcd)) != 0) {
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/hcd.c	Wed Mar 17 19:29:09 2004
@@ -1213,7 +1213,7 @@
 			break;
 	}
 	if (tmp != &urb->urb_list) {
-		retval = -EINVAL;
+		retval = -EIDRM;
 		goto done;
 	}
 
@@ -1294,7 +1294,7 @@
 	spin_unlock (&hcd_data_lock);
 	spin_unlock_irqrestore (&urb->lock, flags);
 bye:
-	if (retval && sys && sys->driver)
+	if (retval != -EIDRM && sys && sys->driver)
 		dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
 	return retval;
 }
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/hub.c	Wed Mar 17 19:29:09 2004
@@ -560,7 +560,7 @@
 	struct usb_hub *hub;
 	unsigned long flags;
 
-	desc = intf->altsetting + intf->act_altsetting;
+	desc = intf->cur_altsetting;
 	dev = interface_to_usbdev(intf);
 
 	/* Some hubs have a subclass of 1, which AFAICT according to the */
@@ -1344,15 +1344,15 @@
 
 	for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
 		struct usb_interface *intf = dev->actconfig->interface[i];
-		struct usb_interface_descriptor *as;
+		struct usb_interface_descriptor *desc;
 
-		as = &intf->altsetting[intf->act_altsetting].desc;
-		ret = usb_set_interface(dev, as->bInterfaceNumber,
-			as->bAlternateSetting);
+		desc = &intf->cur_altsetting->desc;
+		ret = usb_set_interface(dev, desc->bInterfaceNumber,
+			desc->bAlternateSetting);
 		if (ret < 0) {
 			err("failed to set active alternate setting "
 				"for dev %s interface %d (error=%d)",
-				dev->devpath, i, ret);
+				dev->devpath, desc->bInterfaceNumber, ret);
 			return ret;
 		}
 	}
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/message.c	Wed Mar 17 19:29:09 2004
@@ -783,16 +783,22 @@
  */
 void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
 {
-	struct usb_host_interface *hintf =
-			&intf->altsetting[intf->act_altsetting];
+	struct usb_host_interface *alt = intf->cur_altsetting;
 	int i;
 
-	for (i = 0; i < hintf->desc.bNumEndpoints; ++i) {
+	for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
 		usb_disable_endpoint(dev,
-				hintf->endpoint[i].desc.bEndpointAddress);
+				alt->endpoint[i].desc.bEndpointAddress);
 	}
 }
 
+static void release_interface(struct device *dev)
+{
+	struct usb_interface *interface = to_usb_interface(dev);
+
+	complete(interface->released);
+}
+
 /*
  * usb_disable_device - Disable all the endpoints for a USB device
  * @dev: the device whose endpoints are being disabled
@@ -822,12 +828,16 @@
 	if (dev->actconfig) {
 		for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
 			struct usb_interface	*interface;
+			struct completion	intf_completion;
 
 			/* remove this interface */
 			interface = dev->actconfig->interface[i];
 			dev_dbg (&dev->dev, "unregistering interface %s\n",
 				interface->dev.bus_id);
-			device_del(&interface->dev);
+			init_completion (&intf_completion);
+			interface->released = &intf_completion;
+			device_unregister (&interface->dev);
+			wait_for_completion (&intf_completion);
 		}
 		dev->actconfig = 0;
 		if (dev->state == USB_STATE_CONFIGURED)
@@ -876,12 +886,11 @@
 void usb_enable_interface(struct usb_device *dev,
 		struct usb_interface *intf)
 {
-	struct usb_host_interface *hintf =
-			&intf->altsetting[intf->act_altsetting];
+	struct usb_host_interface *alt = intf->cur_altsetting;
 	int i;
 
-	for (i = 0; i < hintf->desc.bNumEndpoints; ++i)
-		usb_enable_endpoint(dev, &hintf->endpoint[i].desc);
+	for (i = 0; i < alt->desc.bNumEndpoints; ++i)
+		usb_enable_endpoint(dev, &alt->endpoint[i].desc);
 }
 
 /**
@@ -920,6 +929,7 @@
 int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 {
 	struct usb_interface *iface;
+	struct usb_host_interface *alt;
 	int ret;
 	int manual = 0;
 
@@ -929,14 +939,15 @@
 		return -EINVAL;
 	}
 
-	if (alternate < 0 || alternate >= iface->num_altsetting)
+	alt = usb_altnum_to_altsetting(iface, alternate);
+	if (!alt) {
+		warn("selecting invalid altsetting %d", alternate);
 		return -EINVAL;
+	}
 
 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
-				   iface->altsetting[alternate]
-				   	.desc.bAlternateSetting,
-				   interface, NULL, 0, HZ * 5);
+				   alternate, interface, NULL, 0, HZ * 5);
 
 	/* 9.4.10 says devices don't need this and are free to STALL the
 	 * request if the interface only has one alternate setting.
@@ -957,7 +968,7 @@
 	/* prevent submissions using previous endpoint settings */
 	usb_disable_interface(dev, iface);
 
-	iface->act_altsetting = alternate;
+	iface->cur_altsetting = alt;
 
 	/* If the interface only has one altsetting and the device didn't
 	 * accept the request, we attempt to carry out the equivalent action
@@ -965,13 +976,11 @@
 	 * new altsetting.
 	 */
 	if (manual) {
-		struct usb_host_interface *iface_as =
-				&iface->altsetting[alternate];
 		int i;
 
-		for (i = 0; i < iface_as->desc.bNumEndpoints; i++) {
+		for (i = 0; i < alt->desc.bNumEndpoints; i++) {
 			unsigned int epaddr =
-				iface_as->endpoint[i].desc.bEndpointAddress;
+				alt->endpoint[i].desc.bEndpointAddress;
 			unsigned int pipe =
 	__create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)
 	| (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
@@ -1045,8 +1054,19 @@
 	/* re-init hc/hcd interface/endpoint state */
 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
 		struct usb_interface *intf = config->interface[i];
+		struct usb_host_interface *alt;
+
+		alt = usb_altnum_to_altsetting(intf, 0);
 
-		intf->act_altsetting = 0;
+		/* No altsetting 0?  We'll assume the first altsetting.
+		 * We could use a GetInterface call, but if a device is
+		 * so non-compliant that it doesn't have altsetting 0
+		 * then I wouldn't trust its reply anyway.
+		 */
+		if (!alt)
+			alt = &intf->altsetting[0];
+
+		intf->cur_altsetting = alt;
 		usb_enable_interface(dev, intf);
 	}
 	return 0;
@@ -1135,25 +1155,34 @@
 		 */
 		for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
 			struct usb_interface *intf = cp->interface[i];
-			struct usb_interface_descriptor *desc;
+			struct usb_host_interface *alt;
 
-			intf->act_altsetting = 0;
-			desc = &intf->altsetting [0].desc;
-			usb_enable_interface(dev, intf);
+			alt = usb_altnum_to_altsetting(intf, 0);
 
+			/* No altsetting 0?  We'll assume the first altsetting.
+			 * We could use a GetInterface call, but if a device is
+			 * so non-compliant that it doesn't have altsetting 0
+			 * then I wouldn't trust its reply anyway.
+			 */
+			if (!alt)
+				alt = &intf->altsetting[0];
+
+			intf->cur_altsetting = alt;
+			usb_enable_interface(dev, intf);
 			intf->dev.parent = &dev->dev;
 			intf->dev.driver = NULL;
 			intf->dev.bus = &usb_bus_type;
 			intf->dev.dma_mask = dev->dev.dma_mask;
+			intf->dev.release = release_interface;
 			sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
 				 dev->bus->busnum, dev->devpath,
 				 configuration,
-				 desc->bInterfaceNumber);
+				 alt->desc.bInterfaceNumber);
 			dev_dbg (&dev->dev,
 				"registering %s (config #%d, interface %d)\n",
 				intf->dev.bus_id, configuration,
-				desc->bInterfaceNumber);
-			device_add (&intf->dev);
+				alt->desc.bInterfaceNumber);
+			device_register (&intf->dev);
 			usb_create_driverfs_intf_files (intf);
 		}
 	}
diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/urb.c	Wed Mar 17 19:29:09 2004
@@ -116,7 +116,8 @@
  * describing that request to the USB subsystem.  Request completion will
  * be indicated later, asynchronously, by calling the completion handler.
  * The three types of completion are success, error, and unlink
- * (also called "request cancellation").
+ * (a software-induced fault, also called "request cancelation").  
+ *
  * URBs may be submitted in interrupt context.
  *
  * The caller must have correctly initialized the URB before submitting
@@ -127,12 +128,23 @@
  *
  * Successful submissions return 0; otherwise this routine returns a
  * negative error number.  If the submission is successful, the complete()
- * callback from the urb will be called exactly once, when the USB core and
- * host controller driver are finished with the urb.  When the completion
+ * callback from the URB will be called exactly once, when the USB core and
+ * Host Controller Driver (HCD) are finished with the URB.  When the completion
  * function is called, control of the URB is returned to the device
  * driver which issued the request.  The completion handler may then
  * immediately free or reuse that URB.
  *
+ * With few exceptions, USB device drivers should never access URB fields
+ * provided by usbcore or the HCD until its complete() is called.
+ * The exceptions relate to periodic transfer scheduling.  For both
+ * interrupt and isochronous urbs, as part of successful URB submission
+ * urb->interval is modified to reflect the actual transfer period used
+ * (normally some power of two units).  And for isochronous urbs,
+ * urb->start_frame is modified to reflect when the URB's transfers were
+ * scheduled to start.  Not all isochronous transfer scheduling policies
+ * will work, but most host controller drivers should easily handle ISO
+ * queues going from now until 10-200 msec into the future.
+ *
  * For control endpoints, the synchronous usb_control_msg() call is
  * often used (in non-interrupt context) instead of this call.
  * That is often used through convenience wrappers, for the requests
@@ -143,15 +155,17 @@
  *
  * URBs may be submitted to endpoints before previous ones complete, to
  * minimize the impact of interrupt latencies and system overhead on data
- * throughput.  This is required for continuous isochronous data streams,
+ * throughput.  With that queuing policy, an endpoint's queue would never
+ * be empty.  This is required for continuous isochronous data streams,
  * and may also be required for some kinds of interrupt transfers. Such
- * queueing also maximizes bandwidth utilization by letting USB controllers
+ * queuing also maximizes bandwidth utilization by letting USB controllers
  * start work on later requests before driver software has finished the
- * completion processing for earlier requests.
+ * completion processing for earlier (successful) requests.
  *
- * Bulk and Isochronous URBs may always be queued.  At this writing, all
- * mainstream host controller drivers support queueing for control and
- * interrupt transfer requests.
+ * As of Linux 2.6, all USB endpoint transfer queues support depths greater
+ * than one.  This was previously a HCD-specific behavior, except for ISO
+ * transfers.  Non-isochronous endpoint queues are inactive during cleanup
+ * after faults (transfer errors or cancelation).
  *
  * Reserved Bandwidth Transfers:
  *
@@ -389,7 +403,7 @@
  * When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this
  * request is synchronous.  Success is indicated by returning zero,
  * at which time the urb will have been unlinked and its completion
- * handler will have been called with urb->status -ENOENT.  Failure is
+ * handler will have been called with urb->status == -ENOENT.  Failure is
  * indicated by any other return value.
  *
  * The synchronous cancelation mode may not be used
@@ -400,8 +414,37 @@
  * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
  * request is asynchronous.  Success is indicated by returning -EINPROGRESS,
  * at which time the urb will normally not have been unlinked.
- * The completion function will see urb->status -ECONNRESET.  Failure
+ * The completion function will see urb->status == -ECONNRESET.  Failure
  * is indicated by any other return value.
+ *
+ * Unlinking and Endpoint Queues:
+ *
+ * Host Controller Driver (HCDs) place all the URBs for a particular
+ * endpoint in a queue.  Normally the queue advances as the controller
+ * hardware processes each request.  But when an URB terminates with any
+ * fault (such as an error, or being unlinked) its queue stops, at least
+ * until that URB's completion routine returns.  It is guaranteed that
+ * the queue will not restart until all its unlinked URBs have been fully
+ * retired, with their completion routines run, even if that's not until
+ * some time after the original completion handler returns.
+ *
+ * This means that USB device drivers can safely build deep queues for
+ * large or complex transfers, and clean them up reliably after any sort
+ * of aborted transfer by unlinking all pending URBs at the first fault.
+ *
+ * Note that an URB terminating early because a short packet was received
+ * will count as an error if and only if the URB_SHORT_NOT_OK flag is set.
+ * Also, that all unlinks performed in any URB completion handler must
+ * be asynchronous.
+ *
+ * Queues for isochronous endpoints are treated differently, because they
+ * advance at fixed rates.  Such queues do not stop when an URB is unlinked.
+ * An unlinked URB may leave a gap in the stream of packets.  It is undefined
+ * whether such gaps can be filled in.
+ *
+ * When control URBs terminates with an error, it is likely that the
+ * status stage of the transfer will not take place, even if it is merely
+ * a soft error resulting from a short-packet with URB_SHORT_NOT_OK set.
  */
 int usb_unlink_urb(struct urb *urb)
 {
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/core/usb.c	Wed Mar 17 19:29:09 2004
@@ -189,7 +189,7 @@
 }
 
 /**
- * usb_ifnum_to_if - get the interface object with a given interface number (usbcore-internal)
+ * usb_ifnum_to_if - get the interface object with a given interface number
  * @dev: the device whose current configuration is considered
  * @ifnum: the desired interface
  *
@@ -220,6 +220,33 @@
 }
 
 /**
+ * usb_altnum_to_altsetting - get the altsetting structure with a given
+ *	alternate setting number.
+ * @intf: the interface containing the altsetting in question
+ * @altnum: the desired alternate setting number
+ *
+ * This searches the altsetting array of the specified interface for
+ * an entry with the correct bAlternateSetting value and returns a pointer
+ * to that entry, or null.
+ *
+ * Note that altsettings need not be stored sequentially by number, so
+ * it would be incorrect to assume that the first altsetting entry in
+ * the array corresponds to altsetting zero.  This routine helps device
+ * drivers avoid such mistakes.
+ */
+struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
+		unsigned int altnum)
+{
+	int i;
+
+	for (i = 0; i < intf->num_altsetting; i++) {
+		if (intf->altsetting[i].desc.bAlternateSetting == altnum)
+			return &intf->altsetting[i];
+	}
+	return NULL;
+}
+
+/**
  * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
  * @dev: the device whose current configuration+altsettings is considered
  * @epnum: the desired endpoint, masked with USB_DIR_IN as appropriate.
@@ -247,7 +274,7 @@
 
 		/* only endpoints in current altsetting are active */
 		intf = config->interface[i];
-		alt = intf->altsetting + intf->act_altsetting;
+		alt = intf->cur_altsetting;
 
 		for (k = 0; k < alt->desc.bNumEndpoints; k++)
 			if (epnum == alt->endpoint[k].desc.bEndpointAddress)
@@ -421,7 +448,7 @@
 	if (id == NULL)
 		return NULL;
 
-	intf = &interface->altsetting [interface->act_altsetting];
+	intf = interface->cur_altsetting;
 	dev = interface_to_usbdev(interface);
 
 	/* It is important to check that id->driver_info is nonzero,
@@ -624,7 +651,7 @@
 	scratch += length;
 
 	if (usb_dev->descriptor.bDeviceClass == 0) {
-		int alt = intf->act_altsetting;
+		struct usb_host_interface *alt = intf->cur_altsetting;
 
 		/* 2.4 only exposed interface zero.  in 2.5, hotplug
 		 * agents are called for all interfaces, and can use
@@ -633,9 +660,9 @@
 		envp [i++] = scratch;
 		length += snprintf (scratch, buffer_size - length,
 			    "INTERFACE=%d/%d/%d",
-			    intf->altsetting[alt].desc.bInterfaceClass,
-			    intf->altsetting[alt].desc.bInterfaceSubClass,
-			    intf->altsetting[alt].desc.bInterfaceProtocol);
+			    alt->desc.bInterfaceClass,
+			    alt->desc.bInterfaceSubClass,
+			    alt->desc.bInterfaceProtocol);
 		if ((buffer_size - length <= 0) || (i >= num_envp))
 			return -ENOMEM;
 		++length;
@@ -1598,6 +1625,7 @@
 EXPORT_SYMBOL(usb_match_id);
 EXPORT_SYMBOL(usb_find_interface);
 EXPORT_SYMBOL(usb_ifnum_to_if);
+EXPORT_SYMBOL(usb_altnum_to_altsetting);
 
 EXPORT_SYMBOL(usb_reset_device);
 EXPORT_SYMBOL(usb_disconnect);
diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
--- a/drivers/usb/gadget/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/gadget/Kconfig	Wed Mar 17 19:29:09 2004
@@ -3,6 +3,15 @@
 #    (a) a peripheral controller, and
 #    (b) the gadget driver using it.
 #
+# NOTE:  Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
+#
+#  - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
+#  - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
+#  - Some systems have both kinds of of controller.
+#
+# With help from a special transceiver and a "Mini-AB" jack, systems with
+# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
+#
 menu "USB Gadget Support"
 
 config USB_GADGET
@@ -11,7 +20,7 @@
 	   USB is a master/slave protocol, organized with one master
 	   host (such as a PC) controlling up to 127 peripheral devices.
 	   The USB hardware is asymmetric, which makes it easier to set up:
-	   you can't connect two "to-the-host" connectors to each other.
+	   you can't connect a "to-the-host" connector to a peripheral.
 
 	   Linux can run in the host, or in the peripheral.  In both cases
 	   you need a low level bus controller driver, and some software
@@ -43,6 +52,7 @@
 config USB_GADGET_NET2280
 	boolean "NetChip 2280"
 	depends on PCI
+	select USB_GADGET_DUALSPEED
 	help
 	   NetChip 2280 is a PCI based USB peripheral controller which
 	   supports both full and high speed USB 2.0 data transfers.  
@@ -126,6 +136,13 @@
 
 endchoice
 
+config USB_GADGET_DUALSPEED
+	bool
+	depends on USB_GADGET
+	default n
+	help
+	  Means that gadget drivers should include extra descriptors
+	  and code to handle dual-speed controllers.
 
 #
 # USB Gadget Drivers
diff -Nru a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
--- a/drivers/usb/gadget/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/gadget/Makefile	Wed Mar 17 19:29:09 2004
@@ -8,8 +8,8 @@
 #
 # USB gadget drivers
 #
-g_zero-objs			:= zero.o usbstring.o
-g_ether-objs			:= ether.o usbstring.o
+g_zero-objs			:= zero.o usbstring.o config.o
+g_ether-objs			:= ether.o usbstring.o config.o
 g_serial-objs			:= serial.o usbstring.o
 gadgetfs-objs			:= inode.o usbstring.o
 g_file_storage-objs		:= file_storage.o usbstring.o
diff -Nru a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/gadget/config.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,116 @@
+/*
+ * usb/gadget/config.c -- simplify building config descriptors
+ *
+ * Copyright (C) 2003 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/device.h>
+
+#include <linux/usb_ch9.h>
+
+
+/**
+ * usb_descriptor_fillbuf - fill buffer with descriptors
+ * @buf: Buffer to be filled
+ * @buflen: Size of buf
+ * @src: Array of descriptor pointers, terminated by null pointer.
+ *
+ * Copies descriptors into the buffer, returning the length or a
+ * negative error code if they can't all be copied.  Useful when
+ * assembling descriptors for an associated set of interfaces used
+ * as part of configuring a composite device; or in other cases where
+ * sets of descriptors need to be marshaled.
+ */
+int
+usb_descriptor_fillbuf(void *buf, unsigned buflen,
+		const struct usb_descriptor_header **src)
+{
+	u8	*dest = buf;
+
+	if (!src)
+		return -EINVAL;
+
+	/* fill buffer from src[] until null descriptor ptr */
+	for (; 0 != *src; src++) {
+		unsigned		len = (*src)->bLength;
+
+		if (len > buflen)
+			return -EINVAL;
+		memcpy(dest, *src, len);
+		buflen -= len;
+		dest += len;
+	}
+	return dest - (u8 *)buf;
+}
+
+
+/**
+ * usb_gadget_config_buf - builts a complete configuration descriptor
+ * @config: Header for the descriptor, including characteristics such
+ *	as power requirements and number of interfaces.
+ * @desc: Null-terminated vector of pointers to the descriptors (interface,
+ *	endpoint, etc) defining all functions in this device configuration.
+ * @buf: Buffer for the resulting configuration descriptor.
+ * @length: Length of buffer.  If this is not big enough to hold the
+ *	entire configuration descriptor, an error code will be returned.
+ *
+ * This copies descriptors into the response buffer, building a descriptor
+ * for that configuration.  It returns the buffer length or a negative
+ * status code.  The config.wTotalLength field is set to match the length
+ * of the result, but other descriptor fields (including power usage and
+ * interface count) must be set by the caller.
+ *
+ * Gadget drivers could use this when constructing a config descriptor
+ * in response to USB_REQ_GET_DESCRIPTOR.  They will need to patch the
+ * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
+ */
+int usb_gadget_config_buf(
+	const struct usb_config_descriptor	*config,
+	void					*buf,
+	unsigned				length,
+	const struct usb_descriptor_header	**desc
+)
+{
+	struct usb_config_descriptor		*cp = buf;
+	int					len;
+
+	/* config descriptor first */
+	if (length < USB_DT_CONFIG_SIZE || !desc)
+		return -EINVAL;
+	*cp = *config; 
+
+	/* then interface/endpoint/class/vendor/... */
+	len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
+			length - USB_DT_CONFIG_SIZE, desc);
+	if (len < 0)
+		return len;
+	len += USB_DT_CONFIG_SIZE;
+	if (len > 0xffff)
+		return -EINVAL;
+
+	/* patch up the config descriptor */
+	cp->bLength = USB_DT_CONFIG_SIZE;
+	cp->bDescriptorType = USB_DT_CONFIG;
+	cp->wTotalLength = cpu_to_le16(len);
+	cp->bmAttributes |= USB_CONFIG_ATT_ONE;
+	return len;
+}
+
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/gadget/ether.c	Wed Mar 17 19:29:10 2004
@@ -124,7 +124,6 @@
  * DRIVER_VERSION_NUM ... alerts the host side driver to differences
  * EP_*_NAME ... which endpoints do we use for which purpose?
  * EP_*_NUM ... numbers for them (often limited by hardware)
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
  * WAKEUP ... if hardware supports remote wakeup AND we will issue the
  * 	usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
  *
@@ -162,7 +161,6 @@
 #define EP_IN_NUM	2
 static const char EP_STATUS_NAME [] = "ep-f";
 #define EP_STATUS_NUM	3
-#define HIGHSPEED
 /* supports remote wakeup, but this driver doesn't */
 
 extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
@@ -311,7 +309,7 @@
 #define DEFAULT_QLEN	2	/* double buffering by default */
 #endif
 
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 
 static unsigned qmult = 5;
 module_param (qmult, uint, S_IRUGO|S_IWUSR);
@@ -324,7 +322,7 @@
 /* also defer IRQs on highspeed TX */
 #define TX_DELAY	DEFAULT_QLEN
 
-#else	/* !HIGHSPEED ... full speed: */
+#else	/* full speed (low speed doesn't do bulk) */
 #define qlen(gadget) DEFAULT_QLEN
 #endif
 
@@ -607,7 +605,26 @@
 	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
-#ifdef	HIGHSPEED
+static const struct usb_descriptor_header *fs_function [] = {
+#ifdef DEV_CONFIG_CDC
+	/* "cdc" mode descriptors */
+	(struct usb_descriptor_header *) &control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+#ifdef	EP_STATUS_NUM
+	(struct usb_descriptor_header *) &fs_status_desc,
+#endif
+	(struct usb_descriptor_header *) &data_nop_intf,
+#endif /* DEV_CONFIG_CDC */
+	/* minimalist core */
+	(struct usb_descriptor_header *) &data_intf,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	0,
+};
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 
 /*
  * usb 2.0 devices need to expose both high speed and full speed
@@ -660,6 +677,25 @@
 	.bNumConfigurations =	1,
 };
 
+static const struct usb_descriptor_header *hs_function [] = {
+#ifdef DEV_CONFIG_CDC
+	/* "cdc" mode descriptors */
+	(struct usb_descriptor_header *) &control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &union_desc,
+	(struct usb_descriptor_header *) &ether_desc,
+#ifdef	EP_STATUS_NUM
+	(struct usb_descriptor_header *) &hs_status_desc,
+#endif
+	(struct usb_descriptor_header *) &data_nop_intf,
+#endif /* DEV_CONFIG_CDC */
+	/* minimalist core */
+	(struct usb_descriptor_header *) &data_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	0,
+};
+
 
 /* maxpacket and other transfer characteristics vary by speed. */
 #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
@@ -669,7 +705,7 @@
 /* if there's no high speed support, maxpacket doesn't change. */
 #define ep_desc(g,hs,fs) fs
 
-#endif	/* !HIGHSPEED */
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
 /*-------------------------------------------------------------------------*/
 
@@ -704,86 +740,25 @@
 static int
 config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
 {
-	const unsigned	config_len = USB_DT_CONFIG_SIZE
-#ifdef DEV_CONFIG_CDC
-				+ 2 * USB_DT_INTERFACE_SIZE
-				+ sizeof header_desc
-				+ sizeof union_desc
-				+ sizeof ether_desc
-#ifdef	EP_STATUS_NUM
-				+ USB_DT_ENDPOINT_SIZE
-#endif
-#endif /* DEV_CONFIG_CDC */
-				+ USB_DT_INTERFACE_SIZE
-				+ 2 * USB_DT_ENDPOINT_SIZE;
+	int				len;
+	const struct usb_descriptor_header **function = fs_function;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int				hs = (speed == USB_SPEED_HIGH);
 
-#ifdef HIGHSPEED
-	int		hs;
-#endif
-	/* a single configuration must always be index 0 */
-	if (index > 0)
-		return -EINVAL;
-	if (config_len > USB_BUFSIZ)
-		return -EDOM;
-
-	/* config (or other speed config) */
-	memcpy (buf, &eth_config, USB_DT_CONFIG_SIZE);
-	buf [1] = type;
-	((struct usb_config_descriptor *) buf)->wTotalLength
-		= __constant_cpu_to_le16 (config_len);
-	buf += USB_DT_CONFIG_SIZE;
-#ifdef	HIGHSPEED
-	hs = (speed == USB_SPEED_HIGH);
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
-#endif
-
-#ifdef DEV_CONFIG_CDC
-	/* control interface, class descriptors, optional status endpoint */
-	memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-
-	memcpy (buf, &header_desc, sizeof header_desc);
-	buf += sizeof header_desc;
-	memcpy (buf, &union_desc, sizeof union_desc);
-	buf += sizeof union_desc;
-	memcpy (buf, &ether_desc, sizeof ether_desc);
-	buf += sizeof ether_desc;
-
-#ifdef	EP_STATUS_NUM
-#ifdef	HIGHSPEED
 	if (hs)
-		memcpy (buf, &hs_status_desc, USB_DT_ENDPOINT_SIZE);
-	else
-#endif	/* HIGHSPEED */
-		memcpy (buf, &fs_status_desc, USB_DT_ENDPOINT_SIZE);
-	buf += USB_DT_ENDPOINT_SIZE;
-#endif	/* EP_STATUS_NUM */
-
-	/* default data altsetting has no endpoints */
-	memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-#endif /* DEV_CONFIG_CDC */
-
-	/* the "real" data interface has two endpoints */
-	memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-#ifdef HIGHSPEED
-	if (hs) {
-		memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	} else
+		function = hs_function;
 #endif
-	{
-		memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	}
 
-	return config_len;
+	/* a single configuration must always be index 0 */
+	if (index > 0)
+		return -EINVAL;
+	len = usb_gadget_config_buf (&eth_config, buf, USB_BUFSIZ, function);
+	if (len < 0)
+		return len;
+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+	return len;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -992,7 +967,7 @@
 
 		switch (gadget->speed) {
 		case USB_SPEED_FULL:	speed = "full"; break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_SPEED_HIGH:	speed = "high"; break;
 #endif
 		default: 		speed = "?"; break;
@@ -1163,15 +1138,19 @@
 			value = min (ctrl->wLength, (u16) sizeof device_desc);
 			memcpy (req->buf, &device_desc, value);
 			break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget->is_dualspeed)
+				break;
 			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
+			if (!gadget->is_dualspeed)
+				break;
 			// FALLTHROUGH
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			value = config_buf (gadget->speed, req->buf,
 					ctrl->wValue >> 8,
@@ -1675,7 +1654,7 @@
 #endif
 	req->length = length;
 
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	/* throttle highspeed IRQ rate back slightly */
 	req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
 		? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0)
@@ -1798,7 +1777,7 @@
 #endif
 
 	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef	HIGHSPEED
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 	/* assumes ep0 uses the same value for both speeds ... */
 	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
 #endif
@@ -1894,7 +1873,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_gadget_driver eth_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
 #else
 	.speed		= USB_SPEED_FULL,
diff -Nru a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/gadget/gadget_chips.h	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,57 @@
+/*
+ * USB device controllers have lots of quirks.  Use these macros in
+ * gadget drivers or other code that needs to deal with them, and which
+ * autoconfigures instead of using early binding to the hardware.
+ *
+ * This could eventually work like the ARM mach_is_*() stuff, driven by
+ * some config file that gets updated as new hardware is supported.
+ *
+ * NOTE:  some of these controller drivers may not be available yet.
+ */
+#ifdef CONFIG_USB_GADGET_NET2280
+#define	gadget_is_net2280(g)	!strcmp("net2280", (g)->name)
+#else
+#define	gadget_is_net2280(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_PXA
+#define	gadget_is_pxa(g)	!strcmp("pxa2xx_udc", (g)->name)
+#else
+#define	gadget_is_pxa(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_GOKU
+#define	gadget_is_goku(g)	!strcmp("goku_udc", (g)->name)
+#else
+#define	gadget_is_goku(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_SUPERH
+#define	gadget_is_sh(g)		!strcmp("sh_udc", (g)->name)
+#else
+#define	gadget_is_sh(g)		0
+#endif
+
+#ifdef CONFIG_USB_GADGET_SA1100
+#define	gadget_is_sa1100(g)	!strcmp("sa1100_udc", (g)->name)
+#else
+#define	gadget_is_sa1100(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_MQ11XX
+#define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
+#else
+#define	gadget_is_mq11xx(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_OMAP
+#define	gadget_is_omap(g)	!strcmp("omap_udc", (g)->name)
+#else
+#define	gadget_is_omap(g)	0
+#endif
+
+// CONFIG_USB_GADGET_AT91RM9200
+// CONFIG_USB_GADGET_SX2
+// CONFIG_USB_GADGET_AU1X00
+// ...
+
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/gadget/net2280.c	Wed Mar 17 19:29:09 2004
@@ -2663,7 +2663,7 @@
 
 /* tear down the binding between this driver and the pci device */
 
-static void __exit net2280_remove (struct pci_dev *pdev)
+static void net2280_remove (struct pci_dev *pdev)
 {
 	struct net2280		*dev = pci_get_drvdata (pdev);
 
@@ -2736,6 +2736,7 @@
 	spin_lock_init (&dev->lock);
 	dev->pdev = pdev;
 	dev->gadget.ops = &net2280_ops;
+	dev->gadget.is_dualspeed = 1;
 
 	/* the "gadget" abstracts/virtualizes the controller */
 	strcpy (dev->gadget.dev.bus_id, "gadget");
@@ -2884,7 +2885,7 @@
 	.id_table =	pci_ids,
 
 	.probe =	net2280_probe,
-	.remove =	__exit_p(net2280_remove),
+	.remove =	net2280_remove,
 
 	/* FIXME add power management support */
 };
diff -Nru a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
--- a/drivers/usb/gadget/usbstring.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/gadget/usbstring.c	Wed Mar 17 19:29:09 2004
@@ -16,24 +16,89 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
+#include <asm/unaligned.h>
+
+
+static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
+{
+	int	count = 0;
+	u8	c;
+	u16	uchar;
+
+	/* this insists on correct encodings, though not minimal ones.
+	 * BUT it currently rejects legit 4-byte UTF-8 code points,
+	 * which need surrogate pairs.  (Unicode 3.1 can use them.)
+	 */
+	while (len != 0 && (c = (u8) *s++) != 0) {
+		if (unlikely(c & 0x80)) {
+			// 2-byte sequence:
+			// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
+			if ((c & 0xe0) == 0xc0) {
+				uchar = (c & 0x1f) << 6;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0xc0)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c;
+
+			// 3-byte sequence (most CJKV characters):
+			// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
+			} else if ((c & 0xf0) == 0xe0) {
+				uchar = (c & 0x0f) << 12;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0xc0)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c << 6;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0xc0)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c;
+
+				/* no bogus surrogates */
+				if (0xd800 <= uchar && uchar <= 0xdfff)
+					goto fail;
+
+			// 4-byte sequence (surrogate pairs, currently rare):
+			// 11101110wwwwzzzzyy + 110111yyyyxxxxxx
+			//     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
+			// (uuuuu = wwww + 1)
+			// FIXME accept the surrogate code points (only)
+
+			} else
+				goto fail;
+		} else
+			uchar = c;
+		put_unaligned (cpu_to_le16 (uchar), cp++);
+		count++;
+		len--;
+	}
+	return count;
+fail:
+	return -1;
+}
+
 
 /**
  * usb_gadget_get_string - fill out a string descriptor 
- * @table: of c strings using iso latin/1 characters
+ * @table: of c strings encoded using UTF-8
  * @id: string id, from low byte of wValue in get string descriptor
  * @buf: at least 256 bytes
  *
- * Finds the iso latin/1 string matching the ID, and converts it into a
+ * Finds the UTF-8 string matching the ID, and converts it into a
  * string descriptor in utf16-le.
  * Returns length of descriptor (always even) or negative errno
  *
- * If your driver needs stings in multiple languages, you'll need to
- * to use some alternate solution for languages where the ISO 8859/1
- * (latin/1) character set can't be used.  For example, they can't be
- * used with Chinese (Big5, GB2312, etc), Japanese, Korean, or many other
- * languages.  You'd likely "switch (wIndex) { ... }"  in your ep0
- * string descriptor logic, using this routine in cases where "western
- * european" characters suffice for the strings being returned.
+ * If your driver needs stings in multiple languages, you'll probably
+ * "switch (wIndex) { ... }"  in your ep0 string descriptor logic,
+ * using this routine after choosing which set of UTF-8 strings to use.
+ * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
+ * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
+ * characters (which are also widely used in C strings).
  */
 int
 usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
@@ -59,13 +124,12 @@
 
 	/* string descriptors have length, tag, then UTF16-LE text */
 	len = min ((size_t) 126, strlen (s->s));
+	memset (buf + 2, 0, 2 * len);	/* zero all the bytes */
+	len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
+	if (len < 0)
+		return -EINVAL;
 	buf [0] = (len + 1) * 2;
 	buf [1] = USB_DT_STRING;
-	memset (buf + 2, 0, 2 * len);	/* zero all the high bytes */
-	while (len) {
-		buf [2 * len] = s->s [len - 1];
-		len--;
-	}
 	return buf [0];
 }
 
diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
--- a/drivers/usb/gadget/zero.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/gadget/zero.c	Wed Mar 17 19:29:09 2004
@@ -1,7 +1,7 @@
 /*
  * zero.c -- Gadget Zero, for USB development
  *
- * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2004 David Brownell
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -103,6 +103,11 @@
 /*-------------------------------------------------------------------------*/
 
 /*
+ * driver assumes self-powered hardware, and
+ * has no way for users to trigger remote wakeup.
+ */
+
+/*
  * hardware-specific configuration, controlled by which device
  * controller driver was configured.
  *
@@ -110,11 +115,6 @@
  * DRIVER_VERSION_NUM ... alerts the host side driver to differences
  * EP_*_NAME ... which endpoints do we use for which purpose?
  * EP_*_NUM ... numbers for them (often limited by hardware)
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
- * MAX_USB_POWER ... define if we use other than 100 mA bus current
- * SELFPOWER ... if we can run on bus power, zero
- * WAKEUP ... if hardware supports remote wakeup AND we will issue the
- * 	usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
  *
  * add other defines for other portability issues, like hardware that
  * for some reason doesn't handle full speed bulk maxpacket of 64.
@@ -138,9 +138,6 @@
 #define EP_OUT_NUM	2
 static const char EP_IN_NAME [] = "ep-b";
 #define EP_IN_NUM	2
-#define HIGHSPEED
-/* specific hardware configs could be bus-powered */
-/* supports remote wakeup, but this driver doesn't */
 #endif
 
 /*
@@ -161,8 +158,6 @@
 #define EP_OUT_NUM	12
 static const char EP_IN_NAME [] = "ep11in-bulk";
 #define EP_IN_NUM	11
-/* doesn't support bus-powered operation */
-/* supports remote wakeup, but this driver doesn't */
 #endif
 
 /*
@@ -183,8 +178,6 @@
 #define EP_OUT_NUM	1
 static const char EP_IN_NAME [] = "ep2in-bulk";
 #define EP_IN_NUM	2
-/* doesn't support bus-powered operation */
-/* doesn't support remote wakeup? */
 #endif
 
 /*
@@ -199,7 +192,6 @@
 #define EP_OUT_NUM	1
 static const char EP_IN_NAME [] = "ep2-bulk";
 #define EP_IN_NUM	2
-/* doesn't support remote wakeup */
 #endif
 
 /*-------------------------------------------------------------------------*/
@@ -208,30 +200,6 @@
 #	error Configure some USB peripheral controller driver!
 #endif
 
-/* power usage is config specific.
- * hardware that supports remote wakeup defaults to disabling it.
- */
-
-#ifndef	SELFPOWER
-/* default: say we're self-powered */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* else:
- * - SELFPOWER value must be zero
- * - MAX_USB_POWER may be nonzero.
- */
-#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
-
 /*-------------------------------------------------------------------------*/
 
 /* big enough to hold our biggest descriptor */
@@ -290,8 +258,8 @@
 /*
  * Normally the "loopback" configuration is second (index 1) so
  * it's not the default.  Here's where to change that order, to
- * work better with hosts (like Linux ... for now!) where config
- * changes are problematic.
+ * work better with hosts where config changes are problematic.
+ * Or controllers (like superh) that only support one config.
  */
 static int loopdefault = 0;
 
@@ -301,7 +269,7 @@
 
 /* Thanks to NetChip Technologies for donating this product ID.
  *
- * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
 #define DRIVER_VENDOR_NUM	0x0525		/* NetChip */
@@ -353,8 +321,8 @@
 	.bNumInterfaces =	1,
 	.bConfigurationValue =	CONFIG_SOURCE_SINK,
 	.iConfiguration =	STRING_SOURCE_SINK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,	/* self-powered */
 };
 
 static const struct usb_config_descriptor
@@ -366,8 +334,8 @@
 	.bNumInterfaces =	1,
 	.bConfigurationValue =	CONFIG_LOOPBACK,
 	.iConfiguration =	STRING_LOOPBACK,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,	/* self-powered */
 };
 
 /* one interface in each configuration */
@@ -414,7 +382,21 @@
 	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
-#ifdef	HIGHSPEED
+static const struct usb_descriptor_header *fs_source_sink_function [] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	0,
+};
+
+static const struct usb_descriptor_header *fs_loopback_function [] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	0,
+};
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 
 /*
  * usb 2.0 devices need to expose both high speed and full speed
@@ -425,22 +407,20 @@
  * for the config descriptor.
  */
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 hs_source_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
+static struct usb_endpoint_descriptor
 hs_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_OUT_NUM,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
 };
@@ -456,6 +436,20 @@
 	.bNumConfigurations =	2,
 };
 
+static const struct usb_descriptor_header *hs_source_sink_function [] = {
+	(struct usb_descriptor_header *) &source_sink_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	0,
+};
+
+static const struct usb_descriptor_header *hs_loopback_function [] = {
+	(struct usb_descriptor_header *) &loopback_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	0,
+};
+
 /* maxpacket and other transfer characteristics vary by speed. */
 #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
 
@@ -464,13 +458,14 @@
 /* if there's no high speed support, maxpacket doesn't change. */
 #define ep_desc(g,hs,fs) fs
 
-#endif	/* !HIGHSPEED */
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
+static char				manufacturer [40];
 static char				serial [40];
 
 /* static strings, in iso 8859/1 */
 static struct usb_string		strings [] = {
-	{ STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE " with " CHIP, },
+	{ STRING_MANUFACTURER, manufacturer, },
 	{ STRING_PRODUCT, longname, },
 	{ STRING_SERIAL, serial, },
 	{ STRING_LOOPBACK, loopback, },
@@ -502,60 +497,42 @@
  * device?)
  */
 static int
-config_buf (enum usb_device_speed speed,
+config_buf (struct usb_gadget *gadget,
 		u8 *buf, u8 type, unsigned index)
 {
-	int		is_source_sink;
-	const unsigned	config_len = USB_DT_CONFIG_SIZE
-				+ USB_DT_INTERFACE_SIZE
-				+ 2 * USB_DT_ENDPOINT_SIZE;
-#ifdef HIGHSPEED
-	int		hs;
+	int				is_source_sink;
+	int				len;
+	const struct usb_descriptor_header **function;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	int				hs = (gadget->speed == USB_SPEED_HIGH);
 #endif
+
 	/* two configurations will always be index 0 and index 1 */
 	if (index > 1)
 		return -EINVAL;
-	if (config_len > USB_BUFSIZ)
-		return -EDOM;
 	is_source_sink = loopdefault ? (index == 1) : (index == 0);
 
-	/* config (or other speed config) */
-	if (is_source_sink)
-		memcpy (buf, &source_sink_config, USB_DT_CONFIG_SIZE);
-	else
-		memcpy (buf, &loopback_config, USB_DT_CONFIG_SIZE);
-	buf [1] = type;
-	((struct usb_config_descriptor *) buf)->wTotalLength
-		= __constant_cpu_to_le16 (config_len);
-	buf += USB_DT_CONFIG_SIZE;
-
-	/* one interface */
-	if (is_source_sink)
-		memcpy (buf, &source_sink_intf, USB_DT_INTERFACE_SIZE);
-	else
-		memcpy (buf, &loopback_intf, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-
-	/* the endpoints in that interface (at that speed) */
-#ifdef HIGHSPEED
-	hs = (speed == USB_SPEED_HIGH);
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
-	if (hs) {
-		memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	} else
+	if (hs)
+		function = is_source_sink
+			? hs_source_sink_function
+			: hs_loopback_function;
+	else
 #endif
-	{
-		memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-	}
-
-	return config_len;
+		function = is_source_sink
+			? fs_source_sink_function
+			: fs_loopback_function;
+
+	len = usb_gadget_config_buf (is_source_sink
+					? &source_sink_config
+					: &loopback_config,
+			buf, USB_BUFSIZ, function);
+	if (len < 0)
+		return len;
+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+	return len;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1019,17 +996,21 @@
 			value = min (ctrl->wLength, (u16) sizeof device_desc);
 			memcpy (req->buf, &device_desc, value);
 			break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget->is_dualspeed)
+				break;
 			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
+			if (!gadget->is_dualspeed)
+				break;
 			// FALLTHROUGH
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
-			value = config_buf (gadget->speed, req->buf,
+			value = config_buf (gadget, req->buf,
 					ctrl->wValue >> 8,
 					ctrl->wValue & 0xff);
 			if (value >= 0)
@@ -1212,14 +1193,26 @@
 	dev->req->complete = zero_setup_complete;
 
 	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
-#ifdef HIGHSPEED
+
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	/* assume ep0 uses the same value for both speeds ... */
 	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+	/* and that all endpoints are dual-speed */
+	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 #endif
 
 	gadget->ep0->driver_data = dev;
 
 	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
+	INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
+		EP_OUT_NAME, EP_IN_NAME);
+
+	snprintf (manufacturer, sizeof manufacturer,
+		UTS_SYSNAME " " UTS_RELEASE " with %s",
+		gadget->name);
+
 	return 0;
 
 enomem:
@@ -1230,7 +1223,7 @@
 /*-------------------------------------------------------------------------*/
 
 static struct usb_gadget_driver zero_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
 #else
 	.speed		= USB_SPEED_FULL,
diff -Nru a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
--- a/drivers/usb/host/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/host/Kconfig	Wed Mar 17 19:29:10 2004
@@ -29,6 +29,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ehci-hcd.
 
+config USB_EHCI_SPLIT_ISO
+	bool "Full speed ISO transactions (EXPERIMENTAL)"
+	depends on USB_EHCI_HCD && EXPERIMENTAL
+	default n
+	---help---
+	  This code is new and hasn't been used with many different
+	  EHCI or USB 2.0 transaction translator implementations.
+	  It should work for ISO-OUT transfers, like audio.
+
 config USB_OHCI_HCD
 	tristate "OHCI HCD support"
 	depends on USB
diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- a/drivers/usb/host/ehci-dbg.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/host/ehci-dbg.c	Wed Mar 17 19:29:10 2004
@@ -579,7 +579,11 @@
 				break;
 			case Q_TYPE_SITD:
 				temp = scnprintf (next, size,
-					" sitd/%p", p.sitd);
+					" sitd%d-%04x/%p",
+					p.sitd->stream->interval,
+					le32_to_cpup (&p.sitd->hw_uframe)
+						& 0x0000ffff,
+					p.sitd);
 				tag = Q_NEXT_TYPE (p.sitd->hw_next);
 				p = p.sitd->sitd_next;
 				break;
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/host/ehci-hcd.c	Wed Mar 17 19:29:09 2004
@@ -106,8 +106,6 @@
 #undef EHCI_VERBOSE_DEBUG
 #undef EHCI_URB_TRACE
 
-// #define have_split_iso
-
 #ifdef DEBUG
 #define EHCI_STATS
 #endif
@@ -676,6 +674,7 @@
 
 	/* the IO watchdog guards against hardware or driver bugs that
 	 * misplace IRQs, and should let us run completely without IRQs.
+	 * such lossage has been observed on both VT6202 and VT8235. 
 	 */
 	if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0))
 		timer_action (ehci, TIMER_IO_WATCHDOG);
@@ -796,13 +795,8 @@
 	case PIPE_ISOCHRONOUS:
 		if (urb->dev->speed == USB_SPEED_HIGH)
 			return itd_submit (ehci, urb, mem_flags);
-#ifdef have_split_iso
 		else
 			return sitd_submit (ehci, urb, mem_flags);
-#else
-		dbg ("no split iso support yet");
-		return -ENOSYS;
-#endif /* have_split_iso */
 	}
 }
 
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/host/ehci-sched.c	Wed Mar 17 19:29:09 2004
@@ -53,14 +53,10 @@
 		return &periodic->fstn->fstn_next;
 	case Q_TYPE_ITD:
 		return &periodic->itd->itd_next;
-#ifdef have_split_iso
-	case Q_TYPE_SITD:
+	// case Q_TYPE_SITD:
+	default:
 		return &periodic->sitd->sitd_next;
-#endif /* have_split_iso */
 	}
-	dbg ("BAD shadow %p tag %d", periodic->ptr, tag);
-	// BUG ();
-	return 0;
 }
 
 /* returns true after successful unlink */
@@ -133,7 +129,6 @@
 			hw_p = &q->itd->hw_next;
 			q = &q->itd->itd_next;
 			break;
-#ifdef have_split_iso
 		case Q_TYPE_SITD:
 			/* is it in the S-mask?  (count SPLIT, DATA) */
 			if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
@@ -154,7 +149,6 @@
 			hw_p = &q->sitd->hw_next;
 			q = &q->sitd->sitd_next;
 			break;
-#endif /* have_split_iso */
 		default:
 			BUG ();
 		}
@@ -229,7 +223,8 @@
 				if (same_tt (dev, here.itd->urb->dev)) {
 					u16		mask;
 
-					mask = le32_to_cpu (here.sitd->hw_uframe);
+					mask = le32_to_cpu (here.sitd
+								->hw_uframe);
 					/* FIXME assumes no gap for IN! */
 					mask |= mask >> 8;
 					if (mask & uf_mask)
@@ -237,7 +232,7 @@
 				}
 				type = Q_NEXT_TYPE (here.qh->hw_next);
 				here = here.sitd->sitd_next;
-				break;
+				continue;
 			// case Q_TYPE_FSTN:
 			default:
 				ehci_dbg (ehci,
@@ -698,12 +693,27 @@
 		// BUG_ON (!list_empty(&stream->td_list));
 
 		while (!list_empty (&stream->free_list)) {
-			struct ehci_itd	*itd;
+			struct list_head	*entry;
 
-			itd = list_entry (stream->free_list.next,
-				struct ehci_itd, itd_list);
-			list_del (&itd->itd_list);
-			dma_pool_free (ehci->itd_pool, itd, itd->itd_dma);
+			entry = stream->free_list.next;
+			list_del (entry);
+
+			/* knows about ITD vs SITD */
+			if (stream->highspeed) {
+				struct ehci_itd		*itd;
+
+				itd = list_entry (entry, struct ehci_itd,
+						itd_list);
+				dma_pool_free (ehci->itd_pool, itd,
+						itd->itd_dma);
+			} else {
+				struct ehci_sitd	*sitd;
+
+				sitd = list_entry (entry, struct ehci_sitd,
+						sitd_list);
+				dma_pool_free (ehci->sitd_pool, sitd,
+						sitd->sitd_dma);
+			}
 		}
 
 		is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
@@ -858,6 +868,7 @@
 	int			i;
 	unsigned		num_itds;
 	struct ehci_iso_sched	*sched;
+	unsigned long		flags;
 
 	sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
 	if (unlikely (sched == 0))
@@ -871,6 +882,7 @@
 		num_itds = urb->number_of_packets;
 
 	/* allocate/init ITDs */
+	spin_lock_irqsave (&ehci->lock, flags);
 	for (i = 0; i < num_itds; i++) {
 
 		/* free_list.next might be cache-hot ... but maybe
@@ -884,8 +896,14 @@
 			list_del (&itd->itd_list);
 			itd_dma = itd->itd_dma;
 		} else
+			itd = 0;
+
+		if (!itd) {
+			spin_unlock_irqrestore (&ehci->lock, flags);
 			itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
 					&itd_dma);
+			spin_lock_irqsave (&ehci->lock, flags);
+		}
 
 		if (unlikely (0 == itd)) {
 			iso_sched_free (stream, sched);
@@ -895,6 +913,7 @@
 		itd->itd_dma = itd_dma;
 		list_add (&itd->itd_list, &sched->td_list);
 	}
+	spin_unlock_irqrestore (&ehci->lock, flags);
 
 	/* temporarily store schedule info in hcpriv */
 	urb->hcpriv = sched;
@@ -909,11 +928,11 @@
 	struct ehci_hcd		*ehci,
 	u32			mod,
 	u32			uframe,
-	u32			end,
 	u8			usecs,
 	u32			period
 )
 {
+	uframe %= period;
 	do {
 		/* can't commit more than 80% periodic == 100 usec */
 		if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7)
@@ -922,8 +941,7 @@
 
 		/* we know urb->interval is 2^N uframes */
 		uframe += period;
-		uframe %= mod;
-	} while (uframe != end);
+	} while (uframe < mod);
 	return 1;
 }
 
@@ -933,7 +951,6 @@
 	u32			mod,
 	struct ehci_iso_stream	*stream,
 	u32			uframe,
-	u32			end,
 	struct ehci_iso_sched	*sched,
 	u32			period_uframes
 )
@@ -952,12 +969,20 @@
 	 */
 
 	/* check bandwidth */
+	uframe %= period_uframes;
 	do {
 		u32		max_used;
 
 		frame = uframe >> 3;
 		uf = uframe & 7;
 
+		/* tt must be idle for start(s), any gap, and csplit.
+		 * assume scheduling slop leaves 10+% for control/bulk.
+		 */
+		if (!tt_no_collision (ehci, period_uframes << 3,
+				stream->udev, frame, mask))
+			return 0;
+
 		/* check starts (OUT uses more than one) */
 		max_used = 100 - stream->usecs;
 		for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) {
@@ -969,25 +994,19 @@
 		if (stream->c_usecs) {
 			max_used = 100 - stream->c_usecs;
 			do {
-				/* tt is busy in the gap before CSPLIT */
 				tmp = 1 << uf;
-				mask |= tmp;
 				tmp <<= 8;
-				if (stream->raw_mask & tmp)
-					break;
+				if ((stream->raw_mask & tmp) == 0)
+					continue;
+				if (periodic_usecs (ehci, frame, uf)
+						> max_used)
+					return 0;
 			} while (++uf < 8);
-			if (periodic_usecs (ehci, frame, uf) > max_used)
-				return 0;
 		}
 
 		/* we know urb->interval is 2^N uframes */
 		uframe += period_uframes;
-		uframe %= mod;
-	} while (uframe != end);
-
-	/* tt must be idle for start(s), any gap, and csplit */
-	if (!tt_no_collision (ehci, period_uframes, stream->udev, frame, mask))
-		return 0;
+	} while (uframe < mod);
 
 	stream->splits = stream->raw_mask << (uframe & 7);
 	cpu_to_le32s (&stream->splits);
@@ -1014,7 +1033,7 @@
 	struct ehci_iso_stream	*stream
 )
 {
-	u32			now, start, end, max, period;
+	u32			now, start, max, period;
 	int			status;
 	unsigned		mod = ehci->periodic_size << 3;
 	struct ehci_iso_sched	*sched = urb->hcpriv;
@@ -1036,8 +1055,6 @@
 
 	/* when's the last uframe this urb could start? */
 	max = now + mod;
-	max -= sched->span;
-	max -= 8 * SCHEDULE_SLOP;
 
 	/* typical case: reuse current schedule. stream is still active,
 	 * and no gaps from host falling behind (irq delays etc)
@@ -1046,9 +1063,11 @@
 		start = stream->next_uframe;
 		if (start < now)
 			start += mod;
-		if (likely (start < max))
+		if (likely ((start + sched->span) < max))
 			goto ready;
-		/* else fell behind; try to reschedule */
+		/* else fell behind; someday, try to reschedule */
+		status = -EL2NSYNC;
+		goto fail;
 	}
 
 	/* need to schedule; when's the next (u)frame we could start?
@@ -1059,63 +1078,40 @@
 	 */
 	start = SCHEDULE_SLOP * 8 + (now & ~0x07);
 	start %= mod;
-	end = start;
+	stream->next_uframe = start;
 
 	/* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
 
 	period = urb->interval;
 	if (!stream->highspeed)
 		period <<= 3;
-	if (max > (start + period))
-		max = start + period;
 
-	/* hack:  account for itds already scheduled to this endpoint */
-	if (list_empty (&stream->td_list))
-		end = max;
-
-	/* within [start..max] find a uframe slot with enough bandwidth */
-	end %= mod;
-	do {
+	/* find a uframe slot with enough bandwidth */
+	for (; start < (stream->next_uframe + period); start++) {
 		int		enough_space;
 
 		/* check schedule: enough space? */
 		if (stream->highspeed)
-			enough_space = itd_slot_ok (ehci, mod, start, end,
+			enough_space = itd_slot_ok (ehci, mod, start,
 					stream->usecs, period);
 		else {
 			if ((start % 8) >= 6)
 				continue;
 			enough_space = sitd_slot_ok (ehci, mod, stream,
-					start, end, sched, period);
+					start, sched, period);
 		}
 
-		/* (re)schedule it here if there's enough bandwidth */
+		/* schedule it here if there's enough bandwidth */
 		if (enough_space) {
-			start %= mod;
-			if (unlikely (!list_empty (&stream->td_list))) {
-				/* host fell behind ... maybe irq latencies
-				 * delayed this request queue for too long.
-				 */
-				stream->rescheduled++;
-				dev_dbg (&urb->dev->dev,
-					"iso%d%s %d.%d skip %d.%d\n",
-					stream->bEndpointAddress & 0x0f,
-					(stream->bEndpointAddress & USB_DIR_IN)
-						? "in" : "out",
-					stream->next_uframe >> 3,
-					stream->next_uframe & 0x7,
-					start >> 3, start & 0x7);
-			}
-			stream->next_uframe = start;
+			stream->next_uframe = start % mod;
 			goto ready;
 		}
-
-	} while (++start < max);
+	}
 
 	/* no room in the schedule */
-	ehci_dbg (ehci, "iso %ssched full %p (now %d end %d max %d)\n",
+	ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n",
 		list_empty (&stream->td_list) ? "" : "re",
-		urb, now, end, max);
+		urb, now, max);
 	status = -ENOSPC;
 
 fail:
@@ -1260,6 +1256,7 @@
 	iso_sched_free (stream, iso_sched);
 	urb->hcpriv = 0;
 
+	timer_action (ehci, TIMER_IO_WATCHDOG);
 	if (unlikely (!ehci->periodic_sched++))
 		return enable_periodic (ehci);
 	return 0;
@@ -1404,18 +1401,392 @@
 	return status;
 }
 
-#ifdef have_split_iso
+#ifdef CONFIG_USB_EHCI_SPLIT_ISO
 
 /*-------------------------------------------------------------------------*/
 
 /*
- * "Split ISO TDs" ... used for USB 1.1 devices going through
- * the TTs in USB 2.0 hubs.
- *
- * FIXME not yet implemented
+ * "Split ISO TDs" ... used for USB 1.1 devices going through the
+ * TTs in USB 2.0 hubs.  These need microframe scheduling.
  */
 
-#endif /* have_split_iso */
+static inline void
+sitd_sched_init (
+	struct ehci_iso_sched	*iso_sched,
+	struct ehci_iso_stream	*stream,
+	struct urb		*urb
+)
+{
+	unsigned	i;
+	dma_addr_t	dma = urb->transfer_dma;
+
+	/* how many frames are needed for these transfers */
+	iso_sched->span = urb->number_of_packets * stream->interval;
+
+	/* figure out per-frame sitd fields that we'll need later
+	 * when we fit new sitds into the schedule.
+	 */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		struct ehci_iso_packet	*packet = &iso_sched->packet [i];
+		unsigned		length;
+		dma_addr_t		buf;
+		u32			trans;
+
+		length = urb->iso_frame_desc [i].length & 0x03ff;
+		buf = dma + urb->iso_frame_desc [i].offset;
+
+		trans = SITD_STS_ACTIVE;
+		if (((i + 1) == urb->number_of_packets)
+				&& !(urb->transfer_flags & URB_NO_INTERRUPT))
+			trans |= SITD_IOC;
+		trans |= length << 16;
+		packet->transaction = cpu_to_le32 (trans);
+
+		/* might need to cross a buffer page within a td */
+		packet->bufp = buf;
+		buf += length;
+		packet->buf1 = buf & ~0x0fff;
+		if (packet->buf1 != (buf & ~(u64)0x0fff))
+			packet->cross = 1;
+
+		/* OUT uses multiple start-splits */ 
+		if (stream->bEndpointAddress & USB_DIR_IN)
+			continue;
+		length = 1 + (length / 188);
+		packet->buf1 |= length;
+		if (length > 1) /* BEGIN vs ALL */
+			packet->buf1 |= 1 << 3;
+	}
+}
+
+static int
+sitd_urb_transaction (
+	struct ehci_iso_stream	*stream,
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	int			mem_flags
+)
+{
+	struct ehci_sitd	*sitd;
+	dma_addr_t		sitd_dma;
+	int			i;
+	struct ehci_iso_sched	*iso_sched;
+	unsigned long		flags;
+
+	iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
+	if (iso_sched == 0)
+		return -ENOMEM;
+
+	sitd_sched_init (iso_sched, stream, urb);
+
+	/* allocate/init sITDs */
+	spin_lock_irqsave (&ehci->lock, flags);
+	for (i = 0; i < urb->number_of_packets; i++) {
+
+		/* NOTE:  for now, we don't try to handle wraparound cases
+		 * for IN (using sitd->hw_backpointer, like a FSTN), which
+		 * means we never need two sitds for full speed packets.
+		 */
+
+		/* free_list.next might be cache-hot ... but maybe
+		 * the HC caches it too. avoid that issue for now.
+		 */
+
+		/* prefer previously-allocated sitds */
+		if (!list_empty(&stream->free_list)) {
+			sitd = list_entry (stream->free_list.prev,
+					 struct ehci_sitd, sitd_list);
+			list_del (&sitd->sitd_list);
+			sitd_dma = sitd->sitd_dma;
+		} else
+			sitd = 0;
+
+		if (!sitd) {
+			spin_unlock_irqrestore (&ehci->lock, flags);
+			sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
+					&sitd_dma);
+			spin_lock_irqsave (&ehci->lock, flags);
+		}
+
+		if (!sitd) {
+			iso_sched_free (stream, iso_sched);
+			spin_unlock_irqrestore (&ehci->lock, flags);
+			return -ENOMEM;
+		}
+		memset (sitd, 0, sizeof *sitd);
+		sitd->sitd_dma = sitd_dma;
+		list_add (&sitd->sitd_list, &iso_sched->td_list);
+	}
+
+	/* temporarily store schedule info in hcpriv */
+	urb->hcpriv = iso_sched;
+	urb->error_count = 0;
+
+	spin_unlock_irqrestore (&ehci->lock, flags);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static inline void
+sitd_patch (
+	struct ehci_iso_stream	*stream,
+	struct ehci_sitd	*sitd,
+	struct ehci_iso_sched	*iso_sched,
+	unsigned		index
+)
+{
+	struct ehci_iso_packet	*uf = &iso_sched->packet [index];
+	u64			bufp = uf->bufp;
+
+	sitd->hw_next = EHCI_LIST_END;
+	sitd->hw_fullspeed_ep = stream->address;
+	sitd->hw_uframe = stream->splits;
+	sitd->hw_results = uf->transaction;
+	sitd->hw_backpointer = EHCI_LIST_END;
+
+	bufp = uf->bufp;
+	sitd->hw_buf [0] = cpu_to_le32 (bufp);
+	sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
+
+	sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
+	if (uf->cross) {
+		bufp += 4096;
+		sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
+	}
+	sitd->index = index;
+}
+
+static inline void
+sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
+{
+	/* note: sitd ordering could matter (CSPLIT then SSPLIT) */
+	sitd->sitd_next = ehci->pshadow [frame];
+	sitd->hw_next = ehci->periodic [frame];
+	ehci->pshadow [frame].sitd = sitd;
+	sitd->frame = frame;
+	wmb ();
+	ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD;
+}
+
+/* fit urb's sitds into the selected schedule slot; activate as needed */
+static int
+sitd_link_urb (
+	struct ehci_hcd		*ehci,
+	struct urb		*urb,
+	unsigned		mod,
+	struct ehci_iso_stream	*stream
+)
+{
+	int			packet;
+	unsigned		next_uframe;
+	struct ehci_iso_sched	*sched = urb->hcpriv;
+	struct ehci_sitd	*sitd;
+
+	next_uframe = stream->next_uframe;
+
+	if (list_empty(&stream->td_list)) {
+		/* usbfs ignores TT bandwidth */
+		hcd_to_bus (&ehci->hcd)->bandwidth_allocated
+				+= stream->bandwidth;
+		ehci_vdbg (ehci,
+			"sched dev%s ep%d%s-iso [%d] %dms/%04x\n",
+			urb->dev->devpath, stream->bEndpointAddress & 0x0f,
+			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
+			(next_uframe >> 3) % ehci->periodic_size,
+			stream->interval, le32_to_cpu (stream->splits));
+		stream->start = jiffies;
+	}
+	hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs++;
+
+	/* fill sITDs frame by frame */
+	for (packet = 0, sitd = 0;
+			packet < urb->number_of_packets;
+			packet++) {
+
+		/* ASSERT:  we have all necessary sitds */
+		BUG_ON (list_empty (&sched->td_list));
+
+		/* ASSERT:  no itds for this endpoint in this frame */
+
+		sitd = list_entry (sched->td_list.next,
+				struct ehci_sitd, sitd_list);
+		list_move_tail (&sitd->sitd_list, &stream->td_list);
+		sitd->stream = iso_stream_get (stream);
+		sitd->urb = usb_get_urb (urb);
+
+		sitd_patch (stream, sitd, sched, packet);
+		sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
+				sitd);
+
+		next_uframe += stream->interval << 3;
+		stream->depth += stream->interval << 3;
+	}
+	stream->next_uframe = next_uframe % mod;
+
+	/* don't need that schedule data any more */
+	iso_sched_free (stream, sched);
+	urb->hcpriv = 0;
+
+	timer_action (ehci, TIMER_IO_WATCHDOG);
+	if (!ehci->periodic_sched++)
+		return enable_periodic (ehci);
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define	SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
+			| SITD_STS_XACT | SITD_STS_MMF | SITD_STS_STS)
+
+static unsigned
+sitd_complete (
+	struct ehci_hcd		*ehci,
+	struct ehci_sitd	*sitd,
+	struct pt_regs		*regs
+) {
+	struct urb				*urb = sitd->urb;
+	struct usb_iso_packet_descriptor	*desc;
+	u32					t;
+	int					urb_index = -1;
+	struct ehci_iso_stream			*stream = sitd->stream;
+	struct usb_device			*dev;
+
+	urb_index = sitd->index;
+	desc = &urb->iso_frame_desc [urb_index];
+	t = le32_to_cpup (&sitd->hw_results);
+
+	/* report transfer status */
+	if (t & SITD_ERRS) {
+		urb->error_count++;
+		if (t & SITD_STS_DBE)
+			desc->status = usb_pipein (urb->pipe)
+				? -ENOSR  /* hc couldn't read */
+				: -ECOMM; /* hc couldn't write */
+		else if (t & SITD_STS_BABBLE)
+			desc->status = -EOVERFLOW;
+		else /* XACT, MMF, etc */
+			desc->status = -EPROTO;
+	} else {
+		desc->status = 0;
+		desc->actual_length = desc->length - SITD_LENGTH (t);
+	}
+
+	usb_put_urb (urb);
+	sitd->urb = 0;
+	sitd->stream = 0;
+	list_move (&sitd->sitd_list, &stream->free_list);
+	stream->depth -= stream->interval << 3;
+	iso_stream_put (ehci, stream);
+
+	/* handle completion now? */
+	if ((urb_index + 1) != urb->number_of_packets)
+		return 0;
+
+	/* ASSERT: it's really the last sitd for this urb
+	list_for_each_entry (sitd, &stream->td_list, sitd_list)
+		BUG_ON (sitd->urb == urb);
+	 */
+
+	/* give urb back to the driver */
+	dev = usb_get_dev (urb->dev);
+	ehci_urb_done (ehci, urb, regs);
+	urb = 0;
+
+	/* defer stopping schedule; completion can submit */
+	ehci->periodic_sched--;
+	if (!ehci->periodic_sched)
+		(void) disable_periodic (ehci);
+	hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--;
+
+	if (list_empty (&stream->td_list)) {
+		hcd_to_bus (&ehci->hcd)->bandwidth_allocated
+				-= stream->bandwidth;
+		ehci_vdbg (ehci,
+			"deschedule devp %s ep%d%s-iso\n",
+			dev->devpath, stream->bEndpointAddress & 0x0f,
+			(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
+	}
+	iso_stream_put (ehci, stream);
+	usb_put_dev (dev);
+
+	return 1;
+}
+
+
+static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+{
+	int			status = -EINVAL;
+	unsigned long		flags;
+	struct ehci_iso_stream	*stream;
+
+	// FIXME remove when csplits behave
+	if (usb_pipein(urb->pipe)) {
+		ehci_dbg (ehci, "no iso-IN split transactions yet\n");
+		return -ENOMEM;
+	}
+
+	/* Get iso_stream head */
+	stream = iso_stream_find (ehci, urb);
+	if (stream == 0) {
+		ehci_dbg (ehci, "can't get iso stream\n");
+		return -ENOMEM;
+	}
+	if (urb->interval != stream->interval) {
+		ehci_dbg (ehci, "can't change iso interval %d --> %d\n",
+			stream->interval, urb->interval);
+		goto done;
+	}
+
+#ifdef EHCI_URB_TRACE
+	ehci_dbg (ehci,
+		"submit %p dev%s ep%d%s-iso len %d\n",
+		urb, urb->dev->devpath,
+		usb_pipeendpoint (urb->pipe),
+		usb_pipein (urb->pipe) ? "in" : "out",
+		urb->transfer_buffer_length);
+#endif
+
+	/* allocate SITDs */
+	status = sitd_urb_transaction (stream, ehci, urb, mem_flags);
+	if (status < 0) {
+		ehci_dbg (ehci, "can't init sitds\n");
+		goto done;
+	}
+
+	/* schedule ... need to lock */
+	spin_lock_irqsave (&ehci->lock, flags);
+	status = iso_stream_schedule (ehci, urb, stream);
+ 	if (status == 0)
+		sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
+	spin_unlock_irqrestore (&ehci->lock, flags);
+
+done:
+	if (status < 0)
+		iso_stream_put (ehci, stream);
+	return status;
+}
+
+#else
+
+static inline int
+sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+{
+	ehci_dbg (ehci, "split iso support is disabled\n");
+	return -ENOSYS;
+}
+
+static inline unsigned
+sitd_complete (
+	struct ehci_hcd		*ehci,
+	struct ehci_sitd	*sitd,
+	struct pt_regs		*regs
+) {
+	ehci_err (ehci, "sitd_complete %p?\n", sitd);
+	return 0;
+}
+
+#endif /* USB_EHCI_SPLIT_ISO */
 
 /*-------------------------------------------------------------------------*/
 
@@ -1513,7 +1884,6 @@
 				modified = itd_complete (ehci, q.itd, regs);
 				q = *q_p;
 				break;
-#ifdef have_split_iso
 			case Q_TYPE_SITD:
 				if (q.sitd->hw_results & SITD_ACTIVE) {
 					q_p = &q.sitd->sitd_next;
@@ -1529,7 +1899,6 @@
 				modified = sitd_complete (ehci, q.sitd, regs);
 				q = *q_p;
 				break;
-#endif /* have_split_iso */
 			default:
 				dbg ("corrupt type %d frame %d shadow %p",
 					type, frame, q.ptr);
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/host/ehci.h	Wed Mar 17 19:29:10 2004
@@ -492,16 +492,16 @@
 /*
  * EHCI Specification 0.95 Section 3.4 
  * siTD, aka split-transaction isochronous Transfer Descriptor
- *       ... describe low/full speed iso xfers through TT in hubs
+ *       ... describe full speed iso xfers through TT in hubs
  * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
  */
 struct ehci_sitd {
 	/* first part defined by EHCI spec */
 	u32			hw_next;
 /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-	u32			hw_fullspeed_ep;	/* see EHCI table 3-9 */
-	u32			hw_uframe;		/* see EHCI table 3-10 */
-	u32			hw_results;		/* see EHCI table 3-11 */
+	u32			hw_fullspeed_ep;	/* EHCI table 3-9 */
+	u32			hw_uframe;		/* EHCI table 3-10 */
+	u32			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))
@@ -515,8 +515,8 @@
 
 #define SITD_ACTIVE	__constant_cpu_to_le32(SITD_STS_ACTIVE)
 
-	u32			hw_buf [2];		/* see EHCI table 3-12 */
-	u32			hw_backpointer;		/* see EHCI table 3-13 */
+	u32			hw_buf [2];		/* EHCI table 3-12 */
+	u32			hw_backpointer;		/* EHCI table 3-13 */
 	u32			hw_buf_hi [2];		/* Appendix B */
 
 	/* the rest is HCD-private */
@@ -551,8 +551,6 @@
 } __attribute__ ((aligned (32)));
 
 /*-------------------------------------------------------------------------*/
-
-#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags)
 
 #ifndef DEBUG
 #define STUB_DEBUG_FILES
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/host/uhci-hcd.c	Wed Mar 17 19:29:10 2004
@@ -781,7 +781,8 @@
 /*
  * Map status to standard result codes
  *
- * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
+ * <status> is (td->status & 0xF60000) [a.k.a. uhci_status_bits(td->status)]
+ * Note: status does not include the TD_CTRL_NAK bit.
  * <dir_out> is True for output TDs and False for input TDs.
  */
 static int uhci_map_status(int status, int dir_out)
@@ -792,22 +793,18 @@
 		return -EPROTO;
 	if (status & TD_CTRL_CRCTIMEO) {		/* CRC/Timeout */
 		if (dir_out)
-			return -ETIMEDOUT;
+			return -EPROTO;
 		else
 			return -EILSEQ;
 	}
-	if (status & TD_CTRL_NAK)			/* NAK */
-		return -ETIMEDOUT;
 	if (status & TD_CTRL_BABBLE)			/* Babble */
 		return -EOVERFLOW;
 	if (status & TD_CTRL_DBUFERR)			/* Buffer error */
 		return -ENOSR;
 	if (status & TD_CTRL_STALLED)			/* Stalled */
 		return -EPIPE;
-	if (status & TD_CTRL_ACTIVE)			/* Active */
-		return 0;
-
-	return -EINVAL;
+	WARN_ON(status & TD_CTRL_ACTIVE);		/* Active */
+	return 0;
 }
 
 /*
@@ -832,7 +829,7 @@
 		status |= TD_CTRL_LS;
 
 	/*
-	 * Build the TD for the control request
+	 * Build the TD for the control request setup packet
 	 */
 	td = uhci_alloc_td(uhci, urb->dev);
 	if (!td)
@@ -990,13 +987,13 @@
 
 	if (urbp->short_control_packet) {
 		tmp = head->prev;
-		goto status_phase;
+		goto status_stage;
 	}
 
 	tmp = head->next;
 	td = list_entry(tmp, struct uhci_td, list);
 
-	/* The first TD is the SETUP phase, check the status, but skip */
+	/* The first TD is the SETUP stage, check the status, but skip */
 	/*  the count */
 	status = uhci_status_bits(td_status(td));
 	if (status & TD_CTRL_ACTIVE)
@@ -1037,10 +1034,10 @@
 		}
 	}
 
-status_phase:
+status_stage:
 	td = list_entry(tmp, struct uhci_td, list);
 
-	/* Control status phase */
+	/* Control status stage */
 	status = td_status(td);
 
 #ifdef I_HAVE_BUGGY_APC_BACKUPS
@@ -1053,10 +1050,11 @@
 		return 0;
 #endif
 
+	status = uhci_status_bits(status);
 	if (status & TD_CTRL_ACTIVE)
 		return -EINPROGRESS;
 
-	if (uhci_status_bits(status))
+	if (status)
 		goto td_error;
 
 	return 0;
@@ -1273,12 +1271,6 @@
 }
 
 /*
- * Bulk and interrupt use common result
- */
-#define uhci_result_bulk uhci_result_common
-#define uhci_result_interrupt uhci_result_common
-
-/*
  * Isochronous transfers
  */
 static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end)
@@ -1403,7 +1395,8 @@
 		urb->iso_frame_desc[i].actual_length = actlength;
 		urb->actual_length += actlength;
 
-		status = uhci_map_status(uhci_status_bits(td_status(td)), usb_pipeout(urb->pipe));
+		status = uhci_map_status(uhci_status_bits(td_status(td)),
+				usb_pipeout(urb->pipe));
 		urb->iso_frame_desc[i].status = status;
 		if (status) {
 			urb->error_count++;
@@ -1508,12 +1501,9 @@
 		struct urb_priv *urbp = urb->hcpriv;
 
 		list_del_init(&urbp->urb_list);
-		spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
-		uhci_destroy_urb_priv (uhci, urb);
-
-		return ret;
-	}
-	ret = 0;
+		uhci_destroy_urb_priv(uhci, urb);
+	} else
+		ret = 0;
 
 out:
 	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
@@ -1541,11 +1531,9 @@
 	case PIPE_CONTROL:
 		ret = uhci_result_control(uhci, urb);
 		break;
-	case PIPE_INTERRUPT:
-		ret = uhci_result_interrupt(uhci, urb);
-		break;
 	case PIPE_BULK:
-		ret = uhci_result_bulk(uhci, urb);
+	case PIPE_INTERRUPT:
+		ret = uhci_result_common(uhci, urb);
 		break;
 	case PIPE_ISOCHRONOUS:
 		ret = uhci_result_isochronous(uhci, urb);
@@ -1649,10 +1637,12 @@
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned long flags;
-	struct urb_priv *urbp = urb->hcpriv;
+	struct urb_priv *urbp;
 
 	spin_lock_irqsave(&uhci->urb_list_lock, flags);
-
+	urbp = urb->hcpriv;
+	if (!urbp)			/* URB was never linked! */
+		goto done;
 	list_del_init(&urbp->urb_list);
 
 	uhci_unlink_generic(uhci, urb);
@@ -1665,6 +1655,7 @@
 	list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
 
 	spin_unlock(&uhci->urb_remove_list_lock);
+done:
 	spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
 	return 0;
 }
@@ -1861,17 +1852,12 @@
 
 static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
 {
-	struct list_head *tmp, *head;
-
 	spin_lock(&uhci->urb_remove_list_lock);
-	head = &uhci->urb_remove_list;
-	tmp = head->next;
-	while (tmp != head) {
-		struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
+	spin_lock(&uhci->complete_list_lock);
 
-		tmp = tmp->next;
-		uhci_moveto_complete(uhci, urbp);
-	}
+	/* Splice the urb_remove_list onto the end of the complete_list */
+	list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
+	spin_unlock(&uhci->complete_list_lock);
 	spin_unlock(&uhci->urb_remove_list_lock);
 }
 
@@ -2458,9 +2444,11 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
 	/* Don't try to suspend broken motherboards, reset instead */
-	if (suspend_allowed(uhci))
+	if (suspend_allowed(uhci)) {
 		suspend_hc(uhci);
-	else
+		uhci->saved_framenumber =
+				inw(uhci->io_addr + USBFRNUM) & 0x3ff;
+	} else
 		reset_hc(uhci);
 	return 0;
 }
@@ -2471,9 +2459,20 @@
 
 	pci_set_master(to_pci_dev(uhci_dev(uhci)));
 
-	if (uhci->state == UHCI_SUSPENDED)
+	if (uhci->state == UHCI_SUSPENDED) {
+
+		/*
+		 * Some systems don't maintain the UHCI register values
+		 * during a PM suspend/resume cycle, so reinitialize
+		 * the Frame Number, the Framelist Base Address, and the
+		 * Interrupt Enable registers.
+		 */
+		outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
+		outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+		outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
+				USBINTR_SP, uhci->io_addr + USBINTR);
 		uhci->resume_detect = 1;
-	else {
+	} else {
 		reset_hc(uhci);
 		start_hc(uhci);
 	}
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/host/uhci-hcd.h	Wed Mar 17 19:29:10 2004
@@ -141,7 +141,7 @@
 				 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
 
 #define uhci_maxerr(err)		((err) << TD_CTRL_C_ERR_SHIFT)
-#define uhci_status_bits(ctrl_sts)	((ctrl_sts) & 0xFE0000)
+#define uhci_status_bits(ctrl_sts)	((ctrl_sts) & 0xF60000)
 #define uhci_actual_length(ctrl_sts)	(((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
 
 /*
@@ -350,6 +350,7 @@
 	enum uhci_state state;			/* FIXME: needs a spinlock */
 	unsigned long state_end;		/* Time of next transition */
 	int resume_detect;			/* Need a Global Resume */
+	unsigned int saved_framenumber;		/* Save during PM suspend */
 
 	/* Main list of URB's currently controlled by this HC */
 	spinlock_t urb_list_lock;
diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
--- a/drivers/usb/image/hpusbscsi.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/image/hpusbscsi.c	Wed Mar 17 19:29:10 2004
@@ -42,7 +42,7 @@
 		    const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *altsetting =	intf->altsetting;
+	struct usb_host_interface *altsetting =	intf->cur_altsetting;
 	struct hpusbscsi *new;
 	int error = -ENOMEM;
 	int i;
diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
--- a/drivers/usb/image/mdc800.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/image/mdc800.c	Wed Mar 17 19:29:09 2004
@@ -431,7 +431,7 @@
 		err ("probe fails -> wrong Number of Configuration");
 		return -ENODEV;
 	}
-	intf_desc = &intf->altsetting[0];
+	intf_desc = intf->cur_altsetting;
 
 	if (
 			( intf_desc->desc.bInterfaceClass != 0xff )
@@ -469,13 +469,6 @@
 	}
 
 
-	usb_driver_claim_interface (&mdc800_usb_driver, intf, mdc800);
-	if (usb_set_interface (dev, intf_desc->desc.bInterfaceNumber, 0) < 0)
-	{
-		err ("MDC800 Configuration fails.");
-		return -ENODEV;
-	}
-
 	info ("Found Mustek MDC800 on USB.");
 
 	down (&mdc800->io_lock);
@@ -550,8 +543,6 @@
 		usb_unlink_urb (mdc800->irq_urb);
 		usb_unlink_urb (mdc800->write_urb);
 		usb_unlink_urb (mdc800->download_urb);
-
-		usb_driver_release_interface (&mdc800_usb_driver, intf);
 
 		mdc800->dev=0;
 		usb_set_intfdata(intf, NULL);
diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
--- a/drivers/usb/image/microtek.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/image/microtek.c	Wed Mar 17 19:29:10 2004
@@ -693,7 +693,6 @@
 			 const struct usb_device_id *id)
 {
 	int i;
-	int result;
 	int ep_out = -1;
 	int ep_in_set[3]; /* this will break if we have more than three endpoints
 			   which is why we check */
@@ -703,7 +702,7 @@
 	struct vendor_product const* p;
 	struct usb_device *dev = interface_to_usbdev (intf);
 
-	/* the altsettting 0 on the interface we're probing */
+	/* the current altsetting on the interface we're probing */
 	struct usb_host_interface *altsetting;
 
 	MTS_DEBUG_GOT_HERE();
@@ -724,8 +723,8 @@
 		MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n",
 			     p->name );
 
-	/* the altsettting 0 on the interface we're probing */
-	altsetting = &(intf->altsetting[0]);
+	/* the current altsetting on the interface we're probing */
+	altsetting = intf->cur_altsetting;
 
 
 	/* Check if the config is sane */
@@ -765,20 +764,6 @@
 	if ( ep_out == -1 ) {
 		MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );
 		return -ENODEV;
-	}
-
-	result = usb_set_interface(dev, altsetting->desc.bInterfaceNumber, 0);
-
-	MTS_DEBUG("usb_set_interface returned %d.\n",result);
-	switch( result )
-	{
-	case 0: /* no error */
-		break;
-
-	default:
-		MTS_DEBUG( "unknown error %d from usb_set_interface\n",
-			(int)result );
- 		return -ENODEV;
 	}
 	
 	
diff -Nru a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
--- a/drivers/usb/input/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/input/Kconfig	Wed Mar 17 19:29:10 2004
@@ -179,6 +179,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called powermate.
 
+config USB_MTOUCH
+	tristate "MicroTouch USB Touchscreen Driver"
+	depends on USB && INPUT
+	---help---
+	  Say Y here if you want to use a MicroTouch (Now 3M) USB 
+	  Touchscreen controller.
+
+	  See <file:Documentation/usb/mtouch.txt> for additional information.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mtouchusb.
+
 config USB_XPAD
 	tristate "X-Box gamepad support"
 	depends on USB && INPUT
@@ -192,3 +204,17 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called xpad.
+	  
+config USB_ATI_REMOTE
+	tristate "ATI USB RF remote control"
+	depends on USB && INPUT
+	---help---
+	  Say Y here if you want to use one of ATI's USB remote controls.
+	  These are RF remotes with USB receivers. They come with many of ATI's 
+	  All-In-Wonder video cards.  This driver provides mouse pointer, left
+          and right mouse buttons, and maps all the other remote buttons to
+	  keypress events.
+	  
+	  To compile this driver as a module, choose M here: the module will be
+	  called ati_remote.
+
diff -Nru a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
--- a/drivers/usb/input/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/Makefile	Wed Mar 17 19:29:09 2004
@@ -27,10 +27,12 @@
 endif
 
 obj-$(CONFIG_USB_AIPTEK)	+= aiptek.o
+obj-$(CONFIG_USB_ATI_REMOTE)	+= ati_remote.o
 obj-$(CONFIG_USB_HID)		+= hid.o
 obj-$(CONFIG_USB_KBD)		+= usbkbd.o
-obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o
-obj-$(CONFIG_USB_WACOM)		+= wacom.o
 obj-$(CONFIG_USB_KBTAB)		+= kbtab.o
+obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o
+obj-$(CONFIG_USB_MTOUCH)	+= mtouchusb.o
 obj-$(CONFIG_USB_POWERMATE)	+= powermate.o
+obj-$(CONFIG_USB_WACOM)		+= wacom.o
 obj-$(CONFIG_USB_XPAD)		+= xpad.o
diff -Nru a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
--- a/drivers/usb/input/aiptek.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/input/aiptek.c	Wed Mar 17 19:29:10 2004
@@ -43,7 +43,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb.h>
-
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
 /*
  * Version Information
  */
@@ -160,9 +161,9 @@
 	proximity = data[5] & 0x01;
 	input_report_key(dev, BTN_TOOL_PEN, proximity);
 
-	x = ((__u32) data[1]) | ((__u32) data[2] << 8);
-	y = ((__u32) data[3]) | ((__u32) data[4] << 8);
-	pressure = ((__u32) data[6]) | ((__u32) data[7] << 8);
+	x = le16_to_cpu(get_unaligned((u16 *) &data[1]));
+	y = le16_to_cpu(get_unaligned((u16 *) &data[3]));
+	pressure = le16_to_cpu(*(u16 *) &data[6]);
 	pressure -= aiptek->features->pressure_min;
 
 	if (pressure < 0) {
@@ -209,8 +210,10 @@
 		return 0;
 
 	aiptek->irq->dev = aiptek->usbdev;
-	if (usb_submit_urb(aiptek->irq, GFP_KERNEL))
+	if (usb_submit_urb(aiptek->irq, GFP_KERNEL)) {
+		aiptek->open--;
 		return -EIO;
+	}
 
 	return 0;
 }
@@ -234,19 +237,27 @@
 		(type << 8) + id, inter->desc.bInterfaceNumber, buf, size, HZ);
 }
 
-static void
+static int
 aiptek_command(struct usb_device *dev, struct usb_host_interface *inter,
 	       unsigned char command, unsigned char data)
 {
-	__u8 buf[3];
+	u8 *buf;
+	int err;
+	
+	buf = kmalloc(3, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
 
 	buf[0] = 4;
 	buf[1] = command;
 	buf[2] = data;
 
-	if (usb_set_report(dev, inter, 3, 2, buf, 3) != 3) {
+	if ((err = usb_set_report(dev, inter, 3, 2, buf, 3)) != 3) {
 		dbg("aiptek_command: 0x%x 0x%x\n", command, data);
 	}
+	
+	kfree(buf);
+	return err < 0 ? err : 0;
 }
 
 static int 
@@ -257,30 +268,32 @@
 	struct usb_host_interface *interface = intf->altsetting + 0;
 	struct usb_endpoint_descriptor *endpoint;
 	struct aiptek *aiptek;
+	int err = -ENOMEM;
 
 	if (!(aiptek = kmalloc(sizeof (struct aiptek), GFP_KERNEL)))
-		return -ENOMEM;
+		goto error_out_noalloc;
 
 	memset(aiptek, 0, sizeof (struct aiptek));
 
-	aiptek->data = usb_buffer_alloc(dev, 10, SLAB_ATOMIC, &aiptek->data_dma);
+	aiptek->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &aiptek->data_dma);
 	if (!aiptek->data) {
-		kfree(aiptek);
-		return -ENOMEM;
+		goto error_out_nobuf;
 	}
 
 	aiptek->irq = usb_alloc_urb(0, GFP_KERNEL);
 	if (!aiptek->irq) {
-		usb_buffer_free(dev, 10, aiptek->data, aiptek->data_dma);
-		kfree(aiptek);
-		return -ENOMEM;
+		goto error_out_nourb;
 	}
 
 	/* Resolution500LPI */
-	aiptek_command(dev, interface, 0x18, 0x04);
+	err = aiptek_command(dev, interface, 0x18, 0x04);
+	if (err)
+		goto error_out;
 
 	/* SwitchToTablet */
-	aiptek_command(dev, interface, 0x10, 0x01);
+	err = aiptek_command(dev, interface, 0x10, 0x01);
+	if (err)
+		goto error_out;
 
 	aiptek->features = aiptek_features + id->driver_info;
 
@@ -340,6 +353,16 @@
 
 	usb_set_intfdata(intf, aiptek);
 	return 0;
+
+error_out:
+	usb_free_urb(aiptek->irq);
+error_out_nourb:
+	usb_buffer_free(dev, 10, aiptek->data, aiptek->data_dma);
+error_out_nobuf:
+	kfree(aiptek);
+error_out_noalloc:
+	return err;
+	
 }
 
 static void
diff -Nru a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/ati_remote.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,851 @@
+/* 
+ *  USB ATI Remote support
+ *
+ *  Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
+ *  Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev
+ *
+ *  This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including
+ *  porting to the 2.6 kernel interfaces, along with other modification 
+ *  to better match the style of the existing usb/input drivers.  However, the
+ *  protocol and hardware handling is essentially unchanged from 2.1.1.
+ *  
+ *  The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by 
+ *  Vojtech Pavlik.
+ *
+ *  Changes:
+ *
+ *  Feb 2004: Torrey Hoffman <thoffman@arnor.net>
+ *            Version 2.2.0
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This 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
+ * 
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
+ *
+ * Hardware & software notes
+ *
+ * These remote controls are distributed by ATI as part of their 
+ * "All-In-Wonder" video card packages.  The receiver self-identifies as a 
+ * "USB Receiver" with manufacturer "X10 Wireless Technology Inc".
+ *
+ * It is possible to use multiple receivers and remotes on multiple computers 
+ * simultaneously by configuring them to use specific channels.
+ * 
+ * The RF protocol used by the remote supports 16 distinct channels, 1 to 16.  
+ * Actually, it may even support more, at least in some revisions of the 
+ * hardware.
+ *
+ * Each remote can be configured to transmit on one channel as follows:
+ *   - Press and hold the "hand icon" button.  
+ *   - When the red LED starts to blink, let go of the "hand icon" button. 
+ *   - When it stops blinking, input the channel code as two digits, from 01 
+ *     to 16, and press the hand icon again.
+ * 
+ * The timing can be a little tricky.  Try loading the module with debug=1
+ * to have the kernel print out messages about the remote control number
+ * and mask.  Note: debugging prints remote numbers as zero-based hexadecimal.
+ *
+ * The driver has a "channel_mask" parameter. This bitmask specifies which
+ * channels will be ignored by the module.  To mask out channels, just add 
+ * all the 2^channel_number values together.
+ *
+ * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote
+ * ignore signals coming from remote controls transmitting on channel 4, but 
+ * accept all other channels.
+ *
+ * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be 
+ * ignored.
+ *
+ * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this 
+ * parameter are unused.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+/*
+ * Module and Version Information, Module Parameters
+ */
+ 
+#define ATI_REMOTE_VENDOR_ID 	0x0bc7
+#define ATI_REMOTE_PRODUCT_ID 	0x004
+
+#define DRIVER_VERSION 	        "2.2.0"
+#define DRIVER_AUTHOR           "Torrey Hoffman <thoffman@arnor.net>"
+#define DRIVER_DESC             "ATI/X10 RF USB Remote Control"
+
+#define NAME_BUFSIZE      80    /* size of product name, path buffers */
+#define DATA_BUFSIZE      63    /* size of URB data buffers */
+#define ATI_INPUTNUM      1     /* Which input device to register as */
+
+unsigned long channel_mask = 0;
+module_param(channel_mask, ulong, 444);
+MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
+
+static int debug = 0;
+module_param(debug, int, 444);
+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)
+#undef err
+#define err(format, arg...) printk(KERN_ERR format , ## arg)
+ 
+static struct usb_device_id ati_remote_table[] = {
+	{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },
+	{}	/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, ati_remote_table);
+
+/* Get hi and low bytes of a 16-bits int */
+#define HI(a)	((unsigned char)((a) >> 8))
+#define LO(a)	((unsigned char)((a) & 0xff))
+
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+
+/* Device initialization strings */
+static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
+static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
+
+/* Acceleration curve for directional control pad */
+static char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+
+/* Duplicate event filtering time. 
+ * Sequential, identical KIND_FILTERED inputs with less than
+ * FILTER_TIME jiffies between them are dropped.  
+ * (HZ >> 4) == 1/16th of a second and works well for me.
+ */
+#define FILTER_TIME (HZ >> 4)
+
+struct ati_remote {
+	struct input_dev idev;		
+	struct usb_device *udev;
+	struct usb_interface *interface;
+		
+	struct urb *irq_urb;
+	struct urb *out_urb;
+	struct usb_endpoint_descriptor *endpoint_in;
+	struct usb_endpoint_descriptor *endpoint_out;
+	unsigned char *inbuf;
+	unsigned char *outbuf;
+	dma_addr_t inbuf_dma;
+	dma_addr_t outbuf_dma;
+
+	int open;                   /* open counter */
+	int present;                /* device plugged in? */
+	
+	unsigned char old_data[2];  /* Detect duplicate events */
+	unsigned long old_jiffies;
+	unsigned long acc_jiffies;  /* handle acceleration */
+	
+	char name[NAME_BUFSIZE];
+	char phys[NAME_BUFSIZE];
+
+	wait_queue_head_t wait;
+	int send_flags;
+};
+
+/* "Kinds" of messages sent from the hardware to the driver. */
+#define KIND_END        0
+#define KIND_LITERAL    1   /* Simply pass to input system */
+#define KIND_FILTERED   2   /* Add artificial key-up events, drop keyrepeats */
+#define KIND_LU         3   /* Directional keypad diagonals - left up, */
+#define KIND_RU         4   /*   right up,  */
+#define KIND_LD         5   /*   left down, */
+#define KIND_RD         6   /*   right down */
+#define KIND_ACCEL      7   /* Directional keypad - left, right, up, down.*/
+
+/* Translation table from hardware messages to input events. */
+static struct
+{
+	short kind;
+	unsigned char data1, data2;
+	int type;
+	unsigned int code;
+	int value;
+}  ati_remote_tbl[] = 
+{
+	/* Directional control pad axes */
+	{KIND_ACCEL,   0x35, 0x70, EV_REL, REL_X, -1},	 /* left */
+	{KIND_ACCEL,   0x36, 0x71, EV_REL, REL_X, 1},    /* right */
+	{KIND_ACCEL,   0x37, 0x72, EV_REL, REL_Y, -1},	 /* up */
+	{KIND_ACCEL,   0x38, 0x73, EV_REL, REL_Y, 1},    /* down */
+	/* Directional control pad diagonals */	
+	{KIND_LU,      0x39, 0x74, EV_REL, 0, 0},        /* left up */
+	{KIND_RU,      0x3a, 0x75, EV_REL, 0, 0},        /* right up */
+	{KIND_LD,      0x3c, 0x77, EV_REL, 0, 0},        /* left down */
+	{KIND_RD,      0x3b, 0x76, EV_REL, 0, 0},        /* right down */
+
+	/* "Mouse button" buttons */
+	{KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
+	{KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
+	{KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
+	{KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
+
+	/* Artificial "doubleclick" events are generated by the hardware. 
+	 * They are mapped to the "side" and "extra" mouse buttons here. */
+	{KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
+	{KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
+
+	/* keyboard. */
+	{KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1},
+	{KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1},
+	{KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1},
+	{KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1},
+	{KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1},
+	{KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1},
+	{KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1},
+	{KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1},
+	{KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1},
+	{KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1},
+	{KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1},
+	{KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1},
+	{KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1},
+	{KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1},
+	{KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1},
+	{KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1},
+
+	/* "special" keys */
+	{KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1},    /* "check" */
+	{KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1},       /* "menu" */
+	{KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1},      /* Power */
+	{KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_PROG1, 1},      /* TV */
+	{KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_PROG2, 1},      /* DVD */
+	{KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1},        /* WEB */
+	{KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1},  /* "book" */
+	{KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1},       /* "hand" */
+	{KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1},     /* "timer" */
+	{KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1},      /* "max" */
+	{KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1},       /* left */
+	{KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1},      /* right */
+	{KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1},       /* down */
+	{KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1},         /* up */
+	{KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_ENTER, 1},      /* "OK" */
+	{KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */
+	{KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1},   /* VOL - */
+	{KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1},       /* MUTE  */
+	{KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELUP, 1},  /* CH + */
+	{KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
+	{KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1},     /* ( o) red */
+	{KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAYCD, 1},     /* ( >) */
+	{KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1},     /* (<<) */
+	{KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1},    /* (>>) */
+	{KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1},       /* ([]) */ 
+	{KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1},      /* ('') */
+	
+	{KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0}
+};
+
+/* Local function prototypes */
+static void ati_remote_dump		(unsigned char *data, unsigned int actual_length);
+static void ati_remote_delete		(struct ati_remote *dev);
+static int ati_remote_open		(struct input_dev *inputdev);
+static void ati_remote_close		(struct input_dev *inputdev);
+static int ati_remote_sendpacket	(struct ati_remote *ati_remote, u16 cmd, unsigned char *data);
+static void ati_remote_irq_out		(struct urb *urb, struct pt_regs *regs);
+static void ati_remote_irq_in		(struct urb *urb, struct pt_regs *regs);
+static void ati_remote_input_report	(struct urb *urb, struct pt_regs *regs);
+static int ati_remote_initialize	(struct ati_remote *ati_remote);
+static int ati_remote_probe		(struct usb_interface *interface, const struct usb_device_id *id);
+static void ati_remote_disconnect	(struct usb_interface *interface);
+
+/* usb specific object to register with the usb subsystem */
+static struct usb_driver ati_remote_driver = {
+	.owner        = THIS_MODULE,
+	.name         = "ati_remote",
+	.probe        = ati_remote_probe,
+	.disconnect   = ati_remote_disconnect,
+	.id_table     = ati_remote_table,
+};
+
+/*
+ *	ati_remote_dump_input
+ */
+static void ati_remote_dump(unsigned char *data, unsigned int len)
+{
+	if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00))
+		warn("Weird byte 0x%02x\n", data[0]);
+	else if (len == 4)
+		warn("Weird key %02x %02x %02x %02x\n", 
+		     data[0], data[1], data[2], data[3]);
+	else
+		warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n",
+		     len, data[0], data[1], data[2], data[3], data[4], data[5]);
+}
+
+/*
+ *	ati_remote_open
+ */
+static int ati_remote_open(struct input_dev *inputdev)
+{
+	struct ati_remote *ati_remote = inputdev->private;
+
+	if (ati_remote->open++)
+		return 0;
+
+	/* On first open, submit the read urb which was set up previously. */
+	ati_remote->irq_urb->dev = ati_remote->udev;
+	if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
+		dev_err(&ati_remote->interface->dev, 
+			"%s: usb_submit_urb failed!\n", __FUNCTION__);
+		ati_remote->open--;
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ *	ati_remote_close
+ */
+static void ati_remote_close(struct input_dev *inputdev)
+{
+	struct ati_remote *ati_remote = inputdev->private;
+	
+	if (ati_remote == NULL) {
+		err("ati_remote: %s: object is NULL!\n", __FUNCTION__);
+		return;
+	}
+	
+	if (ati_remote->open <= 0)
+		dev_dbg(&ati_remote->interface->dev, "%s: Not open.\n", __FUNCTION__);
+	else
+		--ati_remote->open;
+	
+	/* If still present, disconnect will call delete. */
+	if (!ati_remote->present && !ati_remote->open)
+		ati_remote_delete(ati_remote);
+}
+
+/*
+ *		ati_remote_irq_out
+ */
+static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs)
+{
+	struct ati_remote *ati_remote = urb->context;
+	
+	if (urb->status) {
+		dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
+			__FUNCTION__, urb->status);
+		return;
+	}
+	
+	ati_remote->send_flags |= SEND_FLAG_COMPLETE;
+	wmb();
+	if (waitqueue_active(&ati_remote->wait))
+		wake_up(&ati_remote->wait);
+}
+
+/*
+ *	ati_remote_sendpacket
+ *		
+ *	Used to send device initialization strings
+ */
+static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int timeout = HZ;	/* 1 second */
+	int retval = 0;
+	
+	/* Set up out_urb */
+	memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd));
+	((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd);	
+
+	ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1;
+	ati_remote->out_urb->dev = ati_remote->udev;
+	ati_remote->send_flags = SEND_FLAG_IN_PROGRESS;
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&ati_remote->wait, &wait);
+
+	retval = usb_submit_urb(ati_remote->out_urb, GFP_KERNEL);
+	if (retval) {
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&ati_remote->wait, &wait);
+		dev_dbg(&ati_remote->interface->dev, 
+			 "sendpacket: usb_submit_urb failed: %d\n", retval);
+		return retval;
+	}
+
+	while (timeout && (ati_remote->out_urb->status == -EINPROGRESS) 
+	       && !(ati_remote->send_flags & SEND_FLAG_COMPLETE)) {
+		timeout = schedule_timeout(timeout);
+		rmb();
+	}
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&ati_remote->wait, &wait);
+	usb_unlink_urb(ati_remote->out_urb);
+	
+	return retval;
+}
+
+/*
+ *	ati_remote_event_lookup
+ */
+static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2)
+{
+	int i;
+
+	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
+		/* 
+		 * Decide if the table entry matches the remote input. 
+		 */
+		if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) &&
+		    ((((ati_remote_tbl[i].data1 >> 4) - 
+		       (d1 >> 4) + rem) & 0x0f) == 0x0f) && 
+		    (ati_remote_tbl[i].data2 == d2))
+			return i;
+		
+	}
+	return -1;
+}
+
+/*
+ *	ati_remote_report_input
+ */
+static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)	
+{
+	struct ati_remote *ati_remote = urb->context;
+	unsigned char *data= ati_remote->inbuf;
+	struct input_dev *dev = &ati_remote->idev; 
+	int index, acc;
+	int remote_num;
+	
+	/* Deal with strange looking inputs */
+	if ( (urb->actual_length != 4) || (data[0] != 0x14) || 
+		((data[3] & 0x0f) != 0x00) ) {
+		ati_remote_dump(data, urb->actual_length);
+		return;
+	}
+
+	/* Mask unwanted remote channels.  */
+	/* note: remote_num is 0-based, channel 1 on remote == 0 here */
+	remote_num = (data[3] >> 4) & 0x0f;
+        if (channel_mask & (1 << (remote_num + 1))) { 
+		dbginfo(&ati_remote->interface->dev,
+			"Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n",
+			remote_num, data[1], data[2], channel_mask);
+		return;
+	}
+
+	/* Look up event code index in translation table */
+	index = ati_remote_event_lookup(remote_num, data[1], data[2]);
+	if (index < 0) {
+		dev_warn(&ati_remote->interface->dev, 
+			 "Unknown input from channel 0x%02x: data %02x,%02x\n", 
+			 remote_num, data[1], data[2]);
+		return;
+	} 
+	dbginfo(&ati_remote->interface->dev, 
+		"channel 0x%02x; data %02x,%02x; index %d; keycode %d\n",
+		remote_num, data[1], data[2], index, ati_remote_tbl[index].code);
+	
+	if (ati_remote_tbl[index].kind == KIND_LITERAL) {
+		input_regs(dev, regs);
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code,
+			ati_remote_tbl[index].value);
+		input_sync(dev);
+		
+		ati_remote->old_jiffies = jiffies;
+		return;
+	}
+	
+	if (ati_remote_tbl[index].kind == KIND_FILTERED) {
+		/* Filter duplicate events which happen "too close" together. */
+		if ((ati_remote->old_data[0] == data[1]) && 
+	 		(ati_remote->old_data[1] == data[2]) && 
+	 		((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) {
+			ati_remote->old_jiffies = jiffies;			
+			return;
+		}		
+
+		input_regs(dev, regs);
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code, 1);
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code, 0);
+		input_sync(dev);
+
+		ati_remote->old_data[0] = data[1];
+		ati_remote->old_data[1] = data[2];
+		ati_remote->old_jiffies = jiffies;
+		return;
+	}			
+	
+	/* 
+	 * Other event kinds are from the directional control pad, and have an
+	 * acceleration factor applied to them.  Without this acceleration, the
+	 * control pad is mostly unusable.
+	 * 
+	 * If elapsed time since last event is > 1/4 second, user "stopped",
+	 * so reset acceleration. Otherwise, user is probably holding the control
+	 * pad down, so we increase acceleration, ramping up over two seconds to
+	 * a maximum speed.  The acceleration curve is #defined above.
+	 */
+	if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) {
+		acc = 1;
+		ati_remote->acc_jiffies = jiffies;
+	}
+	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3))  acc = accel[0];
+	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2))  acc = accel[1];
+	else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1))  acc = accel[2];
+	else if ((jiffies - ati_remote->acc_jiffies) < HZ )        acc = accel[3];
+	else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4];
+	else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1))  acc = accel[5];
+	else acc = accel[6];
+
+	input_regs(dev, regs);
+	switch (ati_remote_tbl[index].kind) {
+	case KIND_ACCEL:
+		input_event(dev, ati_remote_tbl[index].type,
+			ati_remote_tbl[index].code,
+			ati_remote_tbl[index].value * acc);
+		break;
+	case KIND_LU:
+		input_report_rel(dev, REL_X, -acc);
+		input_report_rel(dev, REL_Y, -acc);
+		break;
+	case KIND_RU:
+		input_report_rel(dev, REL_X, acc);
+		input_report_rel(dev, REL_Y, -acc);
+		break;
+	case KIND_LD:
+		input_report_rel(dev, REL_X, -acc);
+		input_report_rel(dev, REL_Y, acc);
+		break;
+	case KIND_RD:
+		input_report_rel(dev, REL_X, acc);
+		input_report_rel(dev, REL_Y, acc);
+		break;
+	default:
+		dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", 
+			ati_remote_tbl[index].kind);
+	}
+	input_sync(dev);
+
+	ati_remote->old_jiffies = jiffies;
+	ati_remote->old_data[0] = data[1];
+	ati_remote->old_data[1] = data[2];
+}
+
+/*
+ *	ati_remote_irq_in
+ */
+static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs)
+{
+	struct ati_remote *ati_remote = urb->context;
+	int retval;
+
+	switch (urb->status) {
+	case 0:			/* success */
+		ati_remote_input_report(urb, regs);
+		break;
+	case -ECONNRESET:	/* unlink */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n",
+			__FUNCTION__);
+		return;	
+	default:		/* error */
+		dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", 
+			__FUNCTION__, urb->status);
+	}
+	
+	retval = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (retval)
+		dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
+			__FUNCTION__, retval);
+}
+
+/*
+ *	ati_remote_delete
+ */
+static void ati_remote_delete(struct ati_remote *ati_remote)
+{
+	if (!ati_remote) return;
+
+	if (ati_remote->irq_urb)
+		usb_unlink_urb(ati_remote->irq_urb);
+
+	if (ati_remote->out_urb)
+		usb_unlink_urb(ati_remote->out_urb);
+
+	if (ati_remote->irq_urb)
+		usb_free_urb(ati_remote->irq_urb);
+	
+	if (ati_remote->out_urb)
+		usb_free_urb(ati_remote->out_urb);
+
+	if (ati_remote->inbuf)
+		usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, 
+				ati_remote->inbuf, ati_remote->inbuf_dma);
+		
+	if (ati_remote->outbuf)
+		usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, 
+				ati_remote->inbuf, ati_remote->outbuf_dma);
+	
+	kfree(ati_remote);
+}
+
+static void ati_remote_input_init(struct ati_remote *ati_remote)
+{
+	struct input_dev *idev = &(ati_remote->idev);
+	int i;
+
+	idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | 
+					  BIT(BTN_SIDE) | BIT(BTN_EXTRA) );
+	idev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
+		if (ati_remote_tbl[i].type == EV_KEY)
+			set_bit(ati_remote_tbl[i].code, idev->keybit);
+	
+	idev->private = ati_remote;
+	idev->open = ati_remote_open;
+	idev->close = ati_remote_close;
+	
+	idev->name = ati_remote->name;
+	idev->phys = ati_remote->phys;
+	
+	idev->id.bustype = BUS_USB;		
+	idev->id.vendor = ati_remote->udev->descriptor.idVendor;
+	idev->id.product = ati_remote->udev->descriptor.idProduct;
+	idev->id.version = ati_remote->udev->descriptor.bcdDevice;
+}
+
+static int ati_remote_initialize(struct ati_remote *ati_remote)
+{
+	struct usb_device *udev = ati_remote->udev;
+	int pipe, maxp;
+		
+	init_waitqueue_head(&ati_remote->wait);
+
+	/* Set up irq_urb */
+	pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress);
+	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
+	
+	usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, 
+			 maxp, ati_remote_irq_in, ati_remote, 
+			 ati_remote->endpoint_in->bInterval);
+	ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma;
+	ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	
+	/* Set up out_urb */
+	pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress);
+	maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+	maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
+
+	usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, 
+			 maxp, ati_remote_irq_out, ati_remote, 
+			 ati_remote->endpoint_out->bInterval);
+	ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma;
+	ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* send initialization strings */
+	if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) ||
+	    (ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
+		dev_err(&ati_remote->interface->dev, 
+			 "Initializing ati_remote hardware failed.\n");
+		return 1;
+	}
+	
+	return 0;
+}
+
+/*
+ *	ati_remote_probe
+ */
+static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct ati_remote *ati_remote = NULL;
+	struct usb_host_interface *iface_host;
+	int retval = -ENOMEM;
+	char path[64];
+	char *buf = NULL;
+
+	/* See if the offered device matches what we can accept */
+	if ((udev->descriptor.idVendor != ATI_REMOTE_VENDOR_ID) ||
+	    (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID)) {
+		return -ENODEV;
+	}
+
+	/* Allocate and clear an ati_remote struct */
+	if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
+		return -ENOMEM;
+	memset(ati_remote, 0x00, sizeof (struct ati_remote));
+
+	iface_host = interface->cur_altsetting;
+	if (iface_host->desc.bNumEndpoints != 2) {
+		err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__);
+		retval = -ENODEV;
+		goto error;
+	}
+
+	ati_remote->endpoint_in = &(iface_host->endpoint[0].desc);
+	ati_remote->endpoint_out = &(iface_host->endpoint[1].desc);
+	ati_remote->udev = udev;
+	ati_remote->interface = interface;
+
+	if (!(ati_remote->endpoint_in->bEndpointAddress & 0x80)) {
+		err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__);
+		retval = -ENODEV;
+		goto error;
+	}
+	if ((ati_remote->endpoint_in->bmAttributes & 3) != 3) {
+		err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__);
+		retval = -ENODEV;
+		goto error;
+	}
+	if (ati_remote->endpoint_in->wMaxPacketSize == 0) {
+		err("%s: endpoint_in message size==0? \n", __FUNCTION__);
+		retval = -ENODEV;
+		goto error;
+	}
+	if (!(buf = kmalloc(NAME_BUFSIZE, GFP_KERNEL)))
+		goto error;
+
+	/* Allocate URB buffers, URBs */
+	ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+					     &ati_remote->inbuf_dma);
+	if (!ati_remote->inbuf)
+		goto error;
+
+	ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+					      &ati_remote->outbuf_dma);
+	if (!ati_remote->outbuf)
+		goto error;
+
+	ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->irq_urb)
+		goto error;
+
+	ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ati_remote->out_urb)
+		goto error;
+
+	usb_make_path(udev, path, NAME_BUFSIZE);
+	sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM);
+	if (udev->descriptor.iManufacturer && 
+	    (usb_string(udev, udev->descriptor.iManufacturer, buf, 
+			NAME_BUFSIZE) > 0))
+		strcat(ati_remote->name, buf);
+
+	if (udev->descriptor.iProduct && 
+	    (usb_string(udev, udev->descriptor.iProduct, buf, NAME_BUFSIZE) > 0))
+		sprintf(ati_remote->name, "%s %s", ati_remote->name, buf);
+
+	if (!strlen(ati_remote->name))
+		sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)",
+			ati_remote->udev->descriptor.idVendor, 
+			ati_remote->udev->descriptor.idProduct);
+
+	/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
+	retval = ati_remote_initialize(ati_remote);
+	if (retval)
+		goto error;
+
+	/* Set up and register input device */
+	ati_remote_input_init(ati_remote);
+	input_register_device(&ati_remote->idev);
+
+	dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", 
+		 ati_remote->name, path);
+
+	usb_set_intfdata(interface, ati_remote);
+	ati_remote->present = 1;	
+	kfree(buf);
+	return 0;
+	
+error:
+	if (buf)
+		kfree(buf);
+
+	ati_remote_delete(ati_remote);
+	return retval;
+}
+
+/*
+ *	ati_remote_disconnect
+ */
+static void ati_remote_disconnect(struct usb_interface *interface)
+{
+	struct ati_remote *ati_remote;
+	
+	ati_remote = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+	if (!ati_remote) {
+		warn("%s - null device?\n", __FUNCTION__);
+		return;
+	}
+	
+	input_unregister_device(&ati_remote->idev);
+
+	/* Mark device as unplugged */
+	ati_remote->present = 0;
+
+	/* If device is still open, ati_remote_close will call delete. */
+	if (!ati_remote->open)
+		ati_remote_delete(ati_remote);
+}
+
+/*
+ *	ati_remote_init
+ */
+static int __init ati_remote_init(void)
+{
+	int result;
+	
+	result = usb_register(&ati_remote_driver);
+	if (result)
+		err("usb_register error #%d\n", result);
+	else
+		info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION);
+
+	return result;
+}
+
+/*
+ *	ati_remote_exit
+ */
+static void __exit ati_remote_exit(void)
+{
+	usb_deregister(&ati_remote_driver);
+}
+
+/* 
+ *	module specification 
+ */
+
+module_init(ati_remote_init);
+module_exit(ati_remote_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/hid-core.c	Wed Mar 17 19:29:09 2004
@@ -224,6 +224,9 @@
 	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 */
 
@@ -235,9 +238,13 @@
 	field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
 	for (i = 0; i < usages; i++) {
-		field->usage[i].hid = parser->local.usage[i];
+		int j = i;
+		/* Duplicate the last usage we parsed if we have excess values */
+		if (i >= parser->local.usage_index)
+			j = parser->local.usage_index - 1;
+		field->usage[i].hid = parser->local.usage[j];
 		field->usage[i].collection_index =
-			parser->local.collection_index[i];
+			parser->local.collection_index[j];
 	}
 
 	field->maxusage = usages;
@@ -1069,24 +1076,41 @@
 {
 	struct hid_report *report;
 	unsigned char dir;
+	int len;
 
 	report = hid->ctrl[hid->ctrltail].report;
 	dir = hid->ctrl[hid->ctrltail].dir;
 
-	if (dir == USB_DIR_OUT)
+	len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+	if (dir == USB_DIR_OUT) {
 		hid_output_report(report, hid->ctrlbuf);
-
-	hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-	hid->urbctrl->pipe = (dir == USB_DIR_OUT) ?  usb_sndctrlpipe(hid->dev, 0) : usb_rcvctrlpipe(hid->dev, 0);
+		hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0);
+		hid->urbctrl->transfer_buffer_length = len;
+	} else {
+		int maxpacket, padlen;
+
+		hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0);
+		maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0);
+		if (maxpacket > 0) {
+			padlen = (len + maxpacket - 1) / maxpacket;
+			padlen *= maxpacket;
+			if (padlen > HID_BUFFER_SIZE)
+				padlen = HID_BUFFER_SIZE;
+		} else
+			padlen = 0;
+		hid->urbctrl->transfer_buffer_length = padlen;
+	}
 	hid->urbctrl->dev = hid->dev;
 
 	hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
 	hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
 	hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
 	hid->cr->wIndex = cpu_to_le16(hid->ifnum);
-	hid->cr->wLength = cpu_to_le16(hid->urbctrl->transfer_buffer_length);
+	hid->cr->wLength = cpu_to_le16(len);
 
-	dbg("submitting ctrl urb");
+	dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
+	    hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+	    hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
 
 	if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
 		err("usb_submit_urb(ctrl) failed");
@@ -1262,9 +1286,25 @@
 	struct hid_report_enum *report_enum;
 	struct hid_report *report;
 	struct list_head *list;
-	int len;
 	int err, ret;
 
+	/*
+	 * The Set_Idle request is supposed to affect only the
+	 * "Interrupt In" pipe. Unfortunately, buggy devices such as
+	 * the BTC keyboard (ID 046e:5303) the request also affects
+	 * Get_Report requests on the control pipe.  In the worst
+	 * case, if the device was put on idle for an indefinite
+	 * amount of time (as we do below) and there are no input
+	 * events to report, the Get_Report requests will just hang
+	 * until we get a USB timeout.  To avoid this, we temporarily
+	 * establish a minimal idle time of 1ms.  This shouldn't hurt
+	 * bugfree devices and will cause a worst-case extra delay of
+	 * 1ms for buggy ones.
+	 */
+	usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
+			HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (1 << 8),
+			hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+
 	report_enum = hid->report_enum + HID_INPUT_REPORT;
 	list = report_enum->report_list.next;
 	while (list != &report_enum->report_list) {
@@ -1297,11 +1337,8 @@
 	list = report_enum->report_list.next;
 	while (list != &report_enum->report_list) {
 		report = (struct hid_report *) list;
-		len = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
-		if (len > hid->urbin->transfer_buffer_length)
-			hid->urbin->transfer_buffer_length = len < HID_BUFFER_SIZE ? len : HID_BUFFER_SIZE;
 		usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-			0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
+			HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
 			hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
 		list = list->next;
 	}
@@ -1313,11 +1350,12 @@
 #define USB_DEVICE_ID_WACOM_INTUOS	0x0020
 #define USB_DEVICE_ID_WACOM_PL		0x0030
 #define USB_DEVICE_ID_WACOM_INTUOS2	0x0040
+#define USB_DEVICE_ID_WACOM_VOLITO      0x0060
+#define USB_DEVICE_ID_WACOM_PTU         0x0003
 
 #define USB_VENDOR_ID_KBGEAR            0x084e
 #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO  0x1001
 
-
 #define USB_VENDOR_ID_AIPTEK		0x08ca
 #define USB_DEVICE_ID_AIPTEK_6000	0x0020
 
@@ -1356,22 +1394,52 @@
 #define USB_VENDOR_ID_A4TECH		0x09DA
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
 
+#define USB_VENDOR_ID_CYPRESS		0x04b4
+#define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
+
 #define USB_VENDOR_ID_BERKSHIRE		0x0c98
 #define USB_DEVICE_ID_BERKSHIRE_PCWD	0x1140
 
 #define USB_VENDOR_ID_ALPS		0x0433
 #define USB_DEVICE_ID_IBM_GAMEPAD	0x1101
 
+#define USB_VENDOR_ID_SAITEK		0x06a3
+#define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
+
+#define USB_VENDOR_ID_NEC		0x073e
+#define USB_DEVICE_ID_NEC_USB_GAME_PAD	0x0301
+
+#define USB_VENDOR_ID_CHIC		0x05fe
+#define USB_DEVICE_ID_CHIC_GAMEPAD	0x0014
+
 struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
 	unsigned quirks;
 } hid_blacklist[] = {
+
+	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_6000, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, 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 },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 3, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 4, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
@@ -1383,37 +1451,34 @@
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_6000, 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_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE },
+
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
-	{ 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_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD|HID_QUIRK_MULTI_INPUT },
-	{ 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_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK },
-	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
+
+	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_BACK },
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA },
+
 	{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
+	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+
 	{ 0, 0 }
 };
 
@@ -1445,7 +1510,7 @@
 
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 {
-	struct usb_host_interface *interface = intf->altsetting + intf->act_altsetting;
+	struct usb_host_interface *interface = intf->cur_altsetting;
 	struct usb_device *dev = interface_to_usbdev (intf);
 	struct hid_descriptor *hdesc;
 	struct hid_device *hid;
@@ -1518,12 +1583,17 @@
 			continue;
 
 		if (endpoint->bEndpointAddress & USB_DIR_IN) {
+			int len;
+
 			if (hid->urbin)
 				continue;
 			if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
 				goto fail;
 			pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-			usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
+			len = usb_maxpacket(dev, pipe, 0);
+			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->urbin->transfer_dma = hid->inbuf_dma;
 			hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
diff -Nru a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
--- a/drivers/usb/input/hid-ff.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/hid-ff.c	Wed Mar 17 19:29:09 2004
@@ -29,7 +29,7 @@
 
 #include <linux/input.h>
 
-#define DEBUG
+#undef DEBUG
 #include <linux/usb.h>
 
 #include "hid.h"
diff -Nru a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
--- a/drivers/usb/input/hid-input.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/hid-input.c	Wed Mar 17 19:29:09 2004
@@ -377,7 +377,8 @@
 
 	set_bit(usage->type, input->evbit);
 	if ((usage->type == EV_REL)
-			&& (device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
+			&& (device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_BACK
+				| HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA))
 			&& (usage->code == REL_WHEEL)) {
 		set_bit(REL_HWHEEL, bit);
 	}
@@ -431,21 +432,22 @@
 
 	input_regs(input, regs);
 
-	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK)
-			&& (usage->code == BTN_BACK)) {
+	if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA) && (usage->code == BTN_EXTRA))
+		|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_BACK) && (usage->code == BTN_BACK))) {
 		if (value)
 			hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
 		else
 			hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
 		return;
 	}
+
 	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON)
 			&& (usage->code == REL_WHEEL)) {
 		input_event(input, usage->type, REL_HWHEEL, value);
 		return;
 	}
 
-	if (usage->hat_min != usage->hat_max) {
+	if (usage->hat_min != usage->hat_max ) { /* FIXME: hat_max can be 0 and hat_min 1 */
 		value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
 		if (value < 0 || value > 8) value = 0;
 		input_event(input, usage->type, usage->code    , hid_hat_to_axis[value].x);
@@ -484,7 +486,7 @@
 		return;
 	}
 
-	if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
+	if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
 		return;
 
 	input_event(input, usage->type, usage->code, value);
@@ -567,8 +569,10 @@
 		while (list != &report_enum->report_list) {
 			report = (struct hid_report *) list;
 
-			if (!report->maxfield)
+			if (!report->maxfield) {
+				list = list->next;
 				continue;
+			}
 
 			if (!hidinput) {
 				hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
diff -Nru a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
--- a/drivers/usb/input/hid.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/hid.h	Wed Mar 17 19:29:09 2004
@@ -201,15 +201,16 @@
  * HID device quirks.
  */
 
-#define HID_QUIRK_INVERT		0x001
-#define HID_QUIRK_NOTOUCH		0x002
-#define HID_QUIRK_IGNORE		0x004
-#define HID_QUIRK_NOGET			0x008
-#define HID_QUIRK_HIDDEV		0x010
-#define HID_QUIRK_BADPAD		0x020
-#define HID_QUIRK_MULTI_INPUT		0x040
-#define HID_QUIRK_2WHEEL_MOUSE_HACK	0x080
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON	0x100
+#define HID_QUIRK_INVERT			0x001
+#define HID_QUIRK_NOTOUCH			0x002
+#define HID_QUIRK_IGNORE			0x004
+#define HID_QUIRK_NOGET				0x008
+#define HID_QUIRK_HIDDEV			0x010
+#define HID_QUIRK_BADPAD			0x020
+#define HID_QUIRK_MULTI_INPUT			0x040
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_BACK	0x080
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA	0x100
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x200
 
 /*
  * This is the global environment of the parser. This information is
@@ -309,7 +310,7 @@
 
 #define HID_REPORT_TYPES 3
 
-#define HID_BUFFER_SIZE		32
+#define HID_BUFFER_SIZE		64		/* use 64 for compatibility with all possible packetlen */
 #define HID_CONTROL_FIFO_SIZE	256		/* to init devices with >100 reports */
 #define HID_OUTPUT_FIFO_SIZE	64
 
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/hiddev.c	Wed Mar 17 19:29:09 2004
@@ -403,7 +403,8 @@
 	struct hiddev_collection_info cinfo;
 	struct hiddev_report_info rinfo;
 	struct hiddev_field_info finfo;
-	struct hiddev_usage_ref uref;
+	struct hiddev_usage_ref_multi uref_multi;
+	struct hiddev_usage_ref *uref = &uref_multi.uref;
 	struct hiddev_devinfo dinfo;
 	struct hid_report *report;
 	struct hid_field *field;
@@ -575,68 +576,98 @@
 		return 0;
 
 	case HIDIOCGUCODE:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+		if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
 			return -EFAULT;
 
-		rinfo.report_type = uref.report_type;
-		rinfo.report_id = uref.report_id;
+		rinfo.report_type = uref->report_type;
+		rinfo.report_id = uref->report_id;
 		if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 			return -EINVAL;
 
-		if (uref.field_index >= report->maxfield)
+		if (uref->field_index >= report->maxfield)
 			return -EINVAL;
 
-		field = report->field[uref.field_index];
-		if (uref.usage_index >= field->maxusage)
+		field = report->field[uref->field_index];
+		if (uref->usage_index >= field->maxusage)
 			return -EINVAL;
 
-		uref.usage_code = field->usage[uref.usage_index].hid;
+		uref->usage_code = field->usage[uref->usage_index].hid;
 
-		if (copy_to_user((void *) arg, &uref, sizeof(uref)))
+		if (copy_to_user((void *) arg, uref, sizeof(*uref)))
 			return -EFAULT;
 
 		return 0;
 
 	case HIDIOCGUSAGE:
 	case HIDIOCSUSAGE:
+	case HIDIOCGUSAGES:
+	case HIDIOCSUSAGES:
 	case HIDIOCGCOLLECTIONINDEX:
-		if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
-			return -EFAULT;
+		if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
+			if (copy_from_user(&uref_multi, (void *) arg, 
+					   sizeof(uref_multi)))
+				return -EFAULT;
+		} else {
+			if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
+				return -EFAULT;
+		}
 
-		if (cmd != HIDIOCGUSAGE && uref.report_type == HID_REPORT_TYPE_INPUT)
-				return -EINVAL;
+		if (cmd != HIDIOCGUSAGE && 
+		    cmd != HIDIOCGUSAGES &&
+		    uref->report_type == HID_REPORT_TYPE_INPUT)
+			return -EINVAL;
 
-		if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
-			field = hiddev_lookup_usage(hid, &uref);
+		if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
+			field = hiddev_lookup_usage(hid, uref);
 			if (field == NULL)
 				return -EINVAL;
 		} else {
-			rinfo.report_type = uref.report_type;
-			rinfo.report_id = uref.report_id;
+			rinfo.report_type = uref->report_type;
+			rinfo.report_id = uref->report_id;
 			if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
 				return -EINVAL;
 
-			if (uref.field_index >= report->maxfield)
+			if (uref->field_index >= report->maxfield)
 				return -EINVAL;
 
-			field = report->field[uref.field_index];
-			if (uref.usage_index >= field->maxusage)
+			field = report->field[uref->field_index];
+			if (uref->usage_index >= field->maxusage)
 				return -EINVAL;
+
+			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)
+					return -EINVAL;
+			}
 		}
 
 		switch (cmd) {
 			case HIDIOCGUSAGE:
-				uref.value = field->value[uref.usage_index];
-				if (copy_to_user((void *) arg, &uref, sizeof(uref)))
+				uref->value = field->value[uref->usage_index];
+				if (copy_to_user((void *) arg, uref, sizeof(*uref)))
 					return -EFAULT;
 				return 0;
 
 			case HIDIOCSUSAGE:
-				field->value[uref.usage_index] = uref.value;
+				field->value[uref->usage_index] = uref->value;
 				return 0;
 
 			case HIDIOCGCOLLECTIONINDEX:
-				return field->usage[uref.usage_index].collection_index;
+				return field->usage[uref->usage_index].collection_index;
+			case HIDIOCGUSAGES:
+				for (i = 0; i < uref_multi.num_values; i++)
+					uref_multi.values[i] = 
+					    field->value[uref->usage_index + i];
+				if (copy_to_user((void *) arg, &uref_multi, 
+						 sizeof(uref_multi)))
+					return -EFAULT;
+				return 0;
+			case HIDIOCSUSAGES:
+				for (i = 0; i < uref_multi.num_values; i++)
+					field->value[uref->usage_index + i] = 
+				  	    uref_multi.values[i];
+				return 0;
 		}
 
 		return 0;
diff -Nru a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
--- a/drivers/usb/input/kbtab.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/kbtab.c	Wed Mar 17 19:29:09 2004
@@ -4,6 +4,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
 
 /*
  * Version Information
@@ -65,8 +67,8 @@
 		goto exit;
 	}
 
-	kbtab->x = (data[2] << 8) + data[1];
-	kbtab->y = (data[4] << 8) + data[3];
+	kbtab->x = le16_to_cpu(get_unaligned((u16 *) &data[1]));
+	kbtab->y = le16_to_cpu(get_unaligned((u16 *) &data[3]));
 
 	kbtab->pressure = (data[5]);
 
@@ -74,12 +76,15 @@
 
 	input_report_abs(dev, ABS_X, kbtab->x);
 	input_report_abs(dev, ABS_Y, kbtab->y);
-	/*input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);*/
 
 	/*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/
 	input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
-	
-	input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0);
+
+	if( -1 == kb_pressure_click){ 
+		input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);
+	} else {
+		input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0);
+	};
 	
 	input_sync(dev);
 
@@ -105,8 +110,10 @@
 		return 0;
 
 	kbtab->irq->dev = kbtab->usbdev;
-	if (usb_submit_urb(kbtab->irq, GFP_KERNEL))
+	if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) {
+		kbtab->open--;
 		return -EIO;
+	}
 
 	return 0;
 }
@@ -130,7 +137,7 @@
 		return -ENOMEM;
 	memset(kbtab, 0, sizeof(struct kbtab));
 
-	kbtab->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kbtab->data_dma);
+	kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma);
 	if (!kbtab->data) {
 		kfree(kbtab);
 		return -ENOMEM;
diff -Nru a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/usb/input/mtouchusb.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,391 @@
+/******************************************************************************
+ * mtouchusb.c  --  Driver for Microtouch (Now 3M) USB Touchscreens
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl)
+ *  (http://freshmeat.net/projects/3mtouchscreendriver)
+ *
+ * History
+ *
+ *  0.3 & 0.4  2002 (TEJ) tejohnson@yahoo.com
+ *    Updated to 2.4.18, then 2.4.19
+ *    Old version still relied on stealing a minor
+ *
+ *  0.5  02/26/2004 (TEJ) tejohnson@yahoo.com
+ *    Complete rewrite using Linux Input in 2.6.3
+ *    Unfortunately no calibration support at this time
+ *
+ *****************************************************************************/
+
+#include <linux/config.h>
+
+#ifdef CONFIG_USB_DEBUG
+        #define DEBUG
+#else
+        #undef DEBUG
+#endif
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+
+#define MTOUCHUSB_MIN_XC                0xc8
+#define MTOUCHUSB_MAX_XC                0xff78
+#define MTOUCHUSB_XC_FUZZ               0x0
+#define MTOUCHUSB_XC_FLAT               0x0
+#define MTOUCHUSB_MIN_YC                0x0
+#define MTOUCHUSB_MAX_YC                0xff78
+#define MTOUCHUSB_YC_FUZZ               0x0
+#define MTOUCHUSB_YC_FLAT               0x0
+#define MTOUCHUSB_ASYC_REPORT           1
+#define MTOUCHUSB_REPORT_SIZE_DATA      11
+#define MTOUCHUSB_REQ_CTRLLR_ID         10
+
+#define MTOUCHUSB_GET_XC(data)          (data[4]<<8 | data[3])
+#define MTOUCHUSB_GET_YC(data)          (data[6]<<8 | data[5])
+#define MTOUCHUSB_GET_TOUCHED(data)     ((data[2] & 0x40) ? 1:0)
+
+#define DRIVER_VERSION "v0.1"
+#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com"
+#define DRIVER_DESC "Microtouch USB HID Touchscreen Driver"
+
+struct mtouch_usb {
+        unsigned char *data;
+        dma_addr_t data_dma;
+        struct urb *irq;
+        struct usb_device *udev;
+        struct input_dev input;
+        int open;
+        char name[128];
+        char phys[64];
+};
+
+static __s32 vendor=-1, product=-1;
+
+static struct usb_device_id mtouchusb_devices [] = {
+        { USB_DEVICE(0x0596, 0x0001) }, /* 3M (Formerly MicroTouch) 14-206 */
+        { }                             /* Terminating entry */
+};
+
+static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
+{
+        struct mtouch_usb *mtouch = urb->context;
+        int retval;
+
+        switch (urb->status) {
+                case 0:
+                        /* success */
+                        break;
+                case -ETIMEDOUT:
+                        /* this urb is timing out */
+                        dbg("%s - urb timed out - was the device unplugged?",
+                            __FUNCTION__);
+                        return;
+                case -ECONNRESET:
+                case -ENOENT:
+                case -ESHUTDOWN:
+                        /* this urb is terminated, clean up */
+                        dbg("%s - urb shutting down with status: %d",
+                            __FUNCTION__, urb->status);
+                        return;
+                default:
+                        dbg("%s - nonzero urb status received: %d",
+                            __FUNCTION__, urb->status);
+                        goto exit;
+        }
+
+        input_regs(&mtouch->input, regs);
+        input_report_key(&mtouch->input, BTN_TOUCH,
+                         MTOUCHUSB_GET_TOUCHED(mtouch->data));
+        input_report_abs(&mtouch->input, ABS_X,
+                         MTOUCHUSB_GET_XC(mtouch->data));
+        input_report_abs(&mtouch->input, ABS_Y,
+                         MTOUCHUSB_GET_YC(mtouch->data));
+        input_sync(&mtouch->input);
+
+exit:
+        retval = usb_submit_urb (urb, GFP_ATOMIC);
+        if (retval)
+                err ("%s - usb_submit_urb failed with result: %d",
+                     __FUNCTION__, retval);
+}
+
+static int mtouchusb_open (struct input_dev *input)
+{
+        struct mtouch_usb *mtouch = input->private;
+
+        if (mtouch->open++)
+                return 0;
+
+        mtouch->irq->dev = mtouch->udev;
+
+        if (usb_submit_urb (mtouch->irq, GFP_ATOMIC))
+                return -EIO;
+
+        return 0;
+}
+
+static void mtouchusb_close (struct input_dev *input)
+{
+        struct mtouch_usb *mtouch = input->private;
+
+        if (!--mtouch->open)
+                usb_unlink_urb (mtouch->irq);
+}
+
+static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
+{
+        dbg("%s - called", __FUNCTION__);
+
+        mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_SIZE_DATA,
+                                        SLAB_ATOMIC, &mtouch->data_dma);
+
+        if (!mtouch->data)
+                return -1;
+
+        return 0;
+}
+
+static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch)
+{
+        dbg("%s - called", __FUNCTION__);
+
+        if (mtouch->data)
+                usb_buffer_free(udev, MTOUCHUSB_REPORT_SIZE_DATA,
+                                mtouch->data, mtouch->data_dma);
+}
+
+static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+        struct mtouch_usb *mtouch;
+        struct usb_host_interface *interface;
+        struct usb_endpoint_descriptor *endpoint;
+        struct usb_device *udev = interface_to_usbdev (intf);
+        char path[64];
+        char *buf;
+        int nRet;
+        int ix;
+        char valid_device = 0;
+
+        dbg("%s - called", __FUNCTION__);
+        if (vendor != -1 && product != -1) {
+                info("%s - User specified USB Touch -- Vend:Prod - %x:%x",
+                     __FUNCTION__, vendor, product);
+        }
+
+        for (ix = 0; ix < sizeof (mtouchusb_devices) /
+             sizeof (struct usb_device_id); ix++) {
+                if ((udev->descriptor.idVendor ==
+                     mtouchusb_devices [ix].idVendor) &&
+                     (udev->descriptor.idProduct ==
+                     mtouchusb_devices [ix].idProduct)) {
+                        valid_device = 1;
+                        break;
+                }
+        }
+
+        if (udev->descriptor.idVendor == vendor &&
+            udev->descriptor.idProduct == product) {  /* User specified */
+                valid_device = 1;
+        }
+
+        if (!valid_device) {
+                err("%s - No valid device!", __FUNCTION__);
+                return -EIO;
+        }
+
+        if (udev->descriptor.bNumConfigurations != 1) {
+                err("%s -  Only one device configuration is supported.",
+                    __FUNCTION__);
+                return -EIO;
+        }
+
+        dbg("%s - setting interface", __FUNCTION__);
+        interface = intf->cur_altsetting;
+
+        dbg("%s - setting endpoint", __FUNCTION__);
+        endpoint = &interface->endpoint[0].desc;
+
+        if (interface->desc.bNumEndpoints != 1) {
+                err("%s - Only one endpoint is supported.", __FUNCTION__);
+                return -EIO;
+        }
+
+        if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) {
+                err("%s - Out of memory.", __FUNCTION__);
+                return -ENOMEM;
+        }
+
+        memset(mtouch, 0, sizeof(struct mtouch_usb));
+        mtouch->udev = udev;
+
+        dbg("%s - allocating buffers", __FUNCTION__);
+        if (mtouchusb_alloc_buffers(udev, mtouch)) {
+                mtouchusb_free_buffers(udev, mtouch);
+                kfree(mtouch);
+                return -ENOMEM;
+        }
+
+        mtouch->input.private = mtouch;
+        mtouch->input.open = mtouchusb_open;
+        mtouch->input.close = mtouchusb_close;
+
+        usb_make_path(udev, path, 64);
+        sprintf(mtouch->phys, "%s/input0", path);
+
+        mtouch->input.name = mtouch->name;
+        mtouch->input.phys = mtouch->phys;
+        mtouch->input.id.bustype = BUS_USB;
+        mtouch->input.id.vendor = udev->descriptor.idVendor;
+        mtouch->input.id.product = udev->descriptor.idProduct;
+        mtouch->input.id.version = udev->descriptor.bcdDevice;
+        mtouch->input.dev = &intf->dev;
+
+        mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+        mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+        mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+        /* Used to Scale Compensated Data and Flip Y */
+        mtouch->input.absmin[ABS_X] =  MTOUCHUSB_MIN_XC;
+        mtouch->input.absmax[ABS_X] =  MTOUCHUSB_MAX_XC;
+        mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
+        mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
+        mtouch->input.absmin[ABS_Y] =  MTOUCHUSB_MAX_YC;
+        mtouch->input.absmax[ABS_Y] =  MTOUCHUSB_MIN_YC;
+        mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
+        mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
+
+        if (!(buf = kmalloc(63, GFP_KERNEL))) {
+                kfree(mtouch);
+                return -ENOMEM;
+        }
+
+        if (udev->descriptor.iManufacturer &&
+            usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0)
+                        strcat(mtouch->name, buf);
+        if (udev->descriptor.iProduct &&
+            usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0)
+                        sprintf(mtouch->name, "%s %s", mtouch->name, buf);
+
+        if (!strlen(mtouch->name))
+                sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
+                        mtouch->input.id.vendor, mtouch->input.id.product);
+
+        kfree(buf);
+
+        nRet = usb_control_msg(mtouch->udev,
+                               usb_rcvctrlpipe(udev, 0x80),
+                               USB_REQ_GET_CONFIGURATION,
+                               USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+                               0,
+                               0x81,
+                               NULL,
+                               0,
+                               HZ * USB_CTRL_SET_TIMEOUT);
+        dbg("%s - usb_control_msg - USB_REQ_GET_CONFIGURATION - bytes|err: %d",
+            __FUNCTION__, nRet);
+
+        dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__);
+        mtouch->irq = usb_alloc_urb(0, GFP_KERNEL);
+        if (!mtouch->irq) {
+                dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__);
+                mtouchusb_free_buffers(udev, mtouch);
+                kfree(mtouch);
+                return -ENOMEM;
+        }
+
+        dbg("%s - usb_fill_int_urb", __FUNCTION__);
+        usb_fill_int_urb(mtouch->irq,
+                         mtouch->udev,
+                         usb_rcvintpipe(mtouch->udev, 0x81),
+                         mtouch->data,
+                         MTOUCHUSB_REPORT_SIZE_DATA,
+                         mtouchusb_irq,
+                         mtouch,
+                         endpoint->bInterval);
+
+        dbg("%s - input_register_device", __FUNCTION__);
+        input_register_device(&mtouch->input);
+
+        nRet = usb_control_msg(mtouch->udev,
+                               usb_rcvctrlpipe(udev, 0x80),
+                               MTOUCHUSB_ASYC_REPORT,
+                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               MTOUCHUSB_ASYC_REPORT,
+                               MTOUCHUSB_ASYC_REPORT,
+                               NULL,
+                               0,
+                               HZ * USB_CTRL_SET_TIMEOUT);
+        dbg("%s - usb_control_msg - MTOUCHUSB_ASYC_REPORT - bytes|err: %d",
+            __FUNCTION__, nRet);
+
+        printk(KERN_INFO "input: %s on %s\n", mtouch->name, path);
+        usb_set_intfdata(intf, mtouch);
+
+        return 0;
+}
+
+static void mtouchusb_disconnect(struct usb_interface *intf)
+{
+        struct mtouch_usb *mtouch = usb_get_intfdata (intf);
+
+        dbg("%s - called", __FUNCTION__);
+        usb_set_intfdata(intf, NULL);
+        if (mtouch) {
+                dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__);
+                usb_unlink_urb(mtouch->irq);
+                input_unregister_device(&mtouch->input);
+                usb_free_urb(mtouch->irq);
+                mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch);
+                kfree(mtouch);
+        }
+}
+
+MODULE_DEVICE_TABLE (usb, mtouchusb_devices);
+
+static struct usb_driver mtouchusb_driver = {
+        .owner =      THIS_MODULE,
+        .name =       "mtouchusb",
+        .probe =      mtouchusb_probe,
+        .disconnect = mtouchusb_disconnect,
+        .id_table =   mtouchusb_devices,
+};
+
+static int __init mtouchusb_init(void) {
+        dbg("%s - called", __FUNCTION__);
+        return usb_register(&mtouchusb_driver);
+}
+
+static void __exit mtouchusb_cleanup(void) {
+        dbg("%s - called", __FUNCTION__);
+        usb_deregister(&mtouchusb_driver);
+}
+
+module_init(mtouchusb_init);
+module_exit(mtouchusb_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+
diff -Nru a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
--- a/drivers/usb/input/pid.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/input/pid.c	Wed Mar 17 19:29:10 2004
@@ -200,6 +200,7 @@
 			    break;
 
 		if ( id == FF_EFFECTS_MAX) {
+			spin_unlock_irqrestore(&pid_private->lock,flags);
 // TEMP - We need to get ff_effects_max correctly first:  || id >= dev->ff_effects_max) {
 			dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n");
 			return -ENOMEM;
diff -Nru a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
--- a/drivers/usb/input/usbkbd.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/input/usbkbd.c	Wed Mar 17 19:29:10 2004
@@ -240,7 +240,7 @@
 	char path[64];
 	char *buf;
 
-	interface = &iface->altsetting[iface->act_altsetting];
+	interface = iface->cur_altsetting;
 
 	if (interface->desc.bNumEndpoints != 1)
 		return -ENODEV;
diff -Nru a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
--- a/drivers/usb/input/usbmouse.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/input/usbmouse.c	Wed Mar 17 19:29:10 2004
@@ -131,7 +131,7 @@
 	char path[64];
 	char *buf;
 
-	interface = &intf->altsetting[intf->act_altsetting];
+	interface = intf->cur_altsetting;
 
 	if (interface->desc.bNumEndpoints != 1) 
 		return -ENODEV;
diff -Nru a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
--- a/drivers/usb/input/wacom.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/input/wacom.c	Wed Mar 17 19:29:09 2004
@@ -1,14 +1,15 @@
 /*
  *  USB Wacom Graphire and Wacom Intuos tablet support
  *
- *  Copyright (c) 2000-2002 Vojtech Pavlik	<vojtech@ucw.cz>
+ *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
  *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
  *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
  *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
  *  Copyright (c) 2000 James E. Blair		<corvus@gnu.org>
  *  Copyright (c) 2000 Daniel Egger		<egger@suse.de>
  *  Copyright (c) 2001 Frederic Lepied		<flepied@mandrakesoft.com>
- *  Copyright (c) 2002 Ping Cheng		<pingc@wacom.com>
+ *  Copyright (c) 2004 Panagiotis Issaris	<panagiotis.issaris@mech.kuleuven.ac.be>
+ *  Copyright (c) 2002-2004 Ping Cheng		<pingc@wacom.com>
  *
  *  ChangeLog:
  *      v0.1 (vp)  - Initial release
@@ -48,6 +49,8 @@
  *	v1.30 (vp) - Merge 2.4 and 2.5 drivers
  *		   - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
  *		   - Cleanups here and there
+ *    v1.30.1 (pi) - Added Graphire3 support
+ *	v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
  */
 
 /*
@@ -63,6 +66,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb.h>
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
 
 /*
  * Version Information
@@ -106,7 +111,7 @@
 static int usb_set_report(struct usb_interface *intf, unsigned char type,
 				unsigned char id, void *buf, int size)
 {
-        return usb_control_msg(interface_to_usbdev(intf),
+	return usb_control_msg(interface_to_usbdev(intf),
 		usb_sndctrlpipe(interface_to_usbdev(intf), 0),
                 USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                 (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
@@ -137,14 +142,12 @@
 	}
 
 	if (data[0] != 2)
-		dbg("received unknown report #%d", data[0]);
+		dbg("wacom_pl_irq: received unknown report #%d", data[0]);
 
 	prox = data[1] & 0x40;
 
 	input_regs(dev, regs);
 	
-	input_report_key(dev, BTN_TOOL_PEN, prox);
-	
 	if (prox) {
 
 		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
@@ -152,15 +155,103 @@
 			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
 		pressure += (wacom->features->pressure_max + 1) / 2;
 
+		/*
+		 * if going from out of proximity into proximity select between the eraser
+		 * and the pen based on the state of the stylus2 button, choose eraser if
+		 * pressed else choose pen. if not a proximity change from out to in, send
+		 * an out of proximity for previous tool then a in for new tool.
+		 */
+		if (!wacom->tool[0]) {
+			/* Going into proximity select tool */
+			wacom->tool[1] = (data[4] & 0x20)? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		}
+		else {
+			/* was entered with stylus2 pressed */
+			if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20) ) {
+				/* report out proximity for previous tool */
+				input_report_key(dev, wacom->tool[1], 0);
+				input_sync(dev);
+				wacom->tool[1] = BTN_TOOL_PEN;
+				goto exit;
+			}
+		}
+		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+			/* Unknown tool selected default to pen tool */
+			wacom->tool[1] = BTN_TOOL_PEN;
+		}
+		input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
 		input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 7) | ((__u32)(data[1] & 0x03) << 14));
 		input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 7) | ((__u32)(data[4] & 0x03) << 14));
 		input_report_abs(dev, ABS_PRESSURE, pressure);
 
 		input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
 		input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
-		input_report_key(dev, BTN_STYLUS2, data[4] & 0x20);
+		/* Only allow the stylus2 button to be reported for the pen tool. */
+		input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
 	}
-	
+	else {
+		/* report proximity-out of a (valid) tool */
+		if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+			/* Unknown tool selected default to pen tool */
+			wacom->tool[1] = BTN_TOOL_PEN;
+		}
+		input_report_key(dev, wacom->tool[1], prox);
+	}
+
+	wacom->tool[0] = prox; /* Save proximity state */
+	input_sync(dev);
+
+exit:
+	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	if (retval)
+		err ("%s - usb_submit_urb failed with result %d",
+		     __FUNCTION__, retval);
+}
+
+static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct wacom *wacom = urb->context;
+	unsigned char *data = wacom->data;
+	struct input_dev *dev = &wacom->dev;
+	int retval;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		goto exit;
+	}
+
+	if (data[0] != 2)
+	{
+		printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
+	}
+
+	input_regs(dev, regs);
+	if (data[1] & 0x04)
+	{
+		input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
+		input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
+	}
+	else
+	{
+		input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
+		input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
+	}
+	input_report_abs(dev, ABS_X, data[3] << 8 | data[2]);
+	input_report_abs(dev, ABS_Y, data[5] << 8 | data[4]);
+	input_report_abs(dev, ABS_PRESSURE, (data[6]|data[7] << 8));
+	input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
+	input_report_key(dev, BTN_STYLUS2, data[1] & 0x10);
+
 	input_sync(dev);
 
 exit:
@@ -194,8 +285,8 @@
 
 	input_regs(dev, regs);
 	input_report_key(dev, BTN_TOOL_PEN, 1);
-	input_report_abs(dev, ABS_X, data[2] << 8 | data[1]);
-	input_report_abs(dev, ABS_Y, data[4] << 8 | data[3]);
+	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_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));
@@ -231,11 +322,15 @@
 		goto exit;
 	}
 
+	/* check if we can handle the data */
+	if (data[0] == 99)
+		goto exit;
+
 	if (data[0] != 2)
-		dbg("received unknown report #%d", data[0]);
+		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
 
-	x = data[2] | ((__u32)data[3] << 8);
-	y = data[4] | ((__u32)data[5] << 8);
+	x = le16_to_cpu(*(u16 *) &data[2]);
+	y = le16_to_cpu(*(u16 *) &data[4]);
 
 	input_regs(dev, regs);
 
@@ -249,13 +344,16 @@
 			input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
 			break;
 
-		case 2: /* Mouse */
+		case 2: /* Mouse with wheel */
+			input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
+			input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+			/* fall through */
+
+                case 3: /* Mouse without wheel */
 			input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24);
 			input_report_key(dev, BTN_LEFT, data[1] & 0x01);
 			input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
-			input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
 			input_report_abs(dev, ABS_DISTANCE, data[7]);
-			input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
 
 			input_report_abs(dev, ABS_X, x);
 			input_report_abs(dev, ABS_Y, y);
@@ -269,7 +367,7 @@
 		input_report_abs(dev, ABS_Y, y);
 	}
 
-	input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(u16 *) &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);
@@ -308,7 +406,7 @@
 	}
 
 	if (data[0] != 2)
-		dbg("received unknown report #%d", data[0]);
+		dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
 
 	input_regs(dev, regs);
 
@@ -317,18 +415,18 @@
 
 	if ((data[1] & 0xfc) == 0xc0) {						/* Enter report */
 
-		wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 4) +		/* serial number of the tool */
-			((__u32)data[4] << 16) + ((__u32)data[5] << 12) +
+		wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) +		/* serial number of the tool */
+			((__u32)data[4] << 20) + ((__u32)data[5] << 12) +
 			((__u32)data[6] << 4) + (data[7] >> 4);
 
 		switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
-			case 0x832:
+			case 0x812:
 			case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL;		break;	/* Inking pen */
 			case 0x822:
 			case 0x842:
 			case 0x852:
 			case 0x022: wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Pen */
-			case 0x812:
+			case 0x832:
 			case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH;		break;	/* Stroke pen */
 			case 0x007:
 		        case 0x09c:
@@ -337,7 +435,10 @@
 			case 0x82a:
 			case 0x85a:
 		        case 0x91a:
+			case 0xd1a:
 			case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER;		break;	/* Eraser */
+			case 0xd12:
+			case 0x912:
 			case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH;	break;	/* Airbrush */
 			default:    wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Unknown tool */
 		}
@@ -350,13 +451,14 @@
 
 	if ((data[1] & 0xfe) == 0x80) {						/* Exit report */
 		input_report_key(dev, wacom->tool[idx], 0);
+		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 		input_sync(dev);
 		goto exit;
 	}
 
-	input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]);
-	input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]);
-	input_report_abs(dev, ABS_DISTANCE, data[9] >> 4);
+	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_DISTANCE, data[9]);
 
 	if ((data[1] & 0xb8) == 0xa0) {						/* general pen packet */
 		input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
@@ -378,8 +480,8 @@
 		if (data[1] & 0x02) {						/* Rotation packet */
 
 			input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
-					 ((__u32)data[6] << 2) | ((data[7] >> 6) & 3):
-					 (-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1);
+					 ((__u32)data[6] << 3) | ((data[7] >> 5) & 7):
+					 (-(((__u32)data[6] << 3) | ((data[7] >> 5) & 7))) - 1);
 
 		} else {
 
@@ -391,17 +493,17 @@
 
 				input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
 				input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
-				input_report_abs(dev, ABS_THROTTLE,  (data[8] & 0x08) ?
+				input_report_abs(dev, ABS_THROTTLE,  -((data[8] & 0x08) ?
 						 ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
-						 -((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+						 -((__u32)data[6] << 2) | ((data[7] >> 6) & 3)));
 
 			} else {
 				if (wacom->tool[idx] == BTN_TOOL_MOUSE) {	/* 2D mouse packets */	
 					input_report_key(dev, BTN_LEFT,   data[8] & 0x04);
 					input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
 					input_report_key(dev, BTN_RIGHT,  data[8] & 0x10);
-					input_report_abs(dev, REL_WHEEL, 
-					    ((__u32)(data[8] & 0x01) - (__u32)((data[8] & 0x02) >> 1)));
+					input_report_rel(dev, REL_WHEEL, 
+					    (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1)));
 				}
 				else {     /* Lens cursor packets */
 					input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
@@ -414,6 +516,8 @@
 		}
 	}
 	
+	input_report_key(dev, wacom->tool[idx], 1);
+	input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 	input_sync(dev);
 
 exit:
@@ -429,22 +533,26 @@
 	{ "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 32, 1, wacom_graphire_irq },
  	{ "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 32, 1, wacom_graphire_irq },
 	{ "Wacom Graphire3",     8,  10208,  7424,  511, 32, 1, wacom_graphire_irq },
-  	{ "Wacom Intuos 4x5",   10,  12700, 10360, 1023, 15, 2, wacom_intuos_irq },
- 	{ "Wacom Intuos 6x8",   10,  20600, 16450, 1023, 15, 2, wacom_intuos_irq },
- 	{ "Wacom Intuos 9x12",  10,  30670, 24130, 1023, 15, 2, wacom_intuos_irq },
- 	{ "Wacom Intuos 12x12", 10,  30670, 31040, 1023, 15, 2, wacom_intuos_irq },
- 	{ "Wacom Intuos 12x18", 10,  45860, 31040, 1023, 15, 2, wacom_intuos_irq },
+	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 32, 1, wacom_graphire_irq },
+  	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 15, 2, wacom_intuos_irq },
+ 	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 15, 2, wacom_intuos_irq },
+ 	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 15, 2, wacom_intuos_irq },
+ 	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 15, 2, wacom_intuos_irq },
+ 	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 15, 2, wacom_intuos_irq },
  	{ "Wacom PL400",         8,   5408,  4056,  255, 32, 3, wacom_pl_irq },
  	{ "Wacom PL500",         8,   6144,  4608,  255, 32, 3, wacom_pl_irq },
  	{ "Wacom PL600",         8,   6126,  4604,  255, 32, 3, wacom_pl_irq },
  	{ "Wacom PL600SX",       8,   6260,  5016,  255, 32, 3, wacom_pl_irq },
  	{ "Wacom PL550",         8,   6144,  4608,  511, 32, 3, wacom_pl_irq },
  	{ "Wacom PL800",         8,   7220,  5780,  511, 32, 3, wacom_pl_irq },
-	{ "Wacom Intuos2 4x5",   10, 12700, 10360, 1023, 15, 2, wacom_intuos_irq },
-	{ "Wacom Intuos2 6x8",   10, 20600, 16450, 1023, 15, 2, wacom_intuos_irq },
-	{ "Wacom Intuos2 9x12",  10, 30670, 24130, 1023, 15, 2, wacom_intuos_irq },
-	{ "Wacom Intuos2 12x12", 10, 30670, 31040, 1023, 15, 2, wacom_intuos_irq },
-	{ "Wacom Intuos2 12x18", 10, 45860, 31040, 1023, 15, 2, wacom_intuos_irq },
+	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq },
+	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq },
+	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq },
+	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq },
+	{ "Wacom Volito",        8,   5104,  3712,  511, 32, 1, wacom_graphire_irq },
+	{ "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, 3, wacom_ptu_irq },
+	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq },
  	{ }
 };
 
@@ -454,6 +562,7 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
@@ -470,6 +579,9 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
 	{ }
 };
 
@@ -483,8 +595,10 @@
 		return 0;
 
 	wacom->irq->dev = wacom->usbdev;
-	if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+	if (usb_submit_urb(wacom->irq, GFP_KERNEL)) {
+		wacom->open--;
 		return -EIO;
+	}
 
 	return 0;
 }
@@ -509,7 +623,7 @@
 		return -ENOMEM;
 	memset(wacom, 0, sizeof(struct wacom));
 
-	wacom->data = usb_buffer_alloc(dev, 10, SLAB_ATOMIC, &wacom->data_dma);
+	wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
 	if (!wacom->data) {
 		kfree(wacom);
 		return -ENOMEM;
@@ -538,8 +652,9 @@
 			break;
 
 		case 2:
-			wacom->dev.evbit[0] |= BIT(EV_MSC);
+			wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
 			wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
+			wacom->dev.relbit[0] |= BIT(REL_WHEEL);
 			wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
  			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE)	| BIT(BTN_TOOL_BRUSH)
 							  | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
diff -Nru a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
--- a/drivers/usb/misc/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/misc/Kconfig	Wed Mar 17 19:29:10 2004
@@ -86,17 +86,6 @@
 	  a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.
 
-config USB_BRLVGER
-	tristate "Tieman Voyager USB Braille display support (EXPERIMENTAL)"
-	depends on USB && EXPERIMENTAL
-	help
-	  Say Y here if you want to use the Voyager USB Braille display from
-	  Tieman. See <file:Documentation/usb/brlvger.txt> for more
-	  information.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called brlvger.
-
 config USB_LCD
 	tristate "USB LCD driver support"
 	depends on USB
diff -Nru a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
--- a/drivers/usb/misc/Makefile	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/misc/Makefile	Wed Mar 17 19:29:09 2004
@@ -4,7 +4,6 @@
 #
 
 obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
-obj-$(CONFIG_USB_BRLVGER)	+= brlvger.o
 obj-$(CONFIG_USB_EMI62)		+= emi62.o
 obj-$(CONFIG_USB_EMI26)		+= emi26.o
 obj-$(CONFIG_USB_LCD)		+= usblcd.o
diff -Nru a/drivers/usb/misc/brlvger.c b/drivers/usb/misc/brlvger.c
--- a/drivers/usb/misc/brlvger.c	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,1016 +0,0 @@
-/*
- *      Tieman Voyager braille display USB driver.
- *
- *      Copyright 2001-2002 Stephane Dalton <sdalton@videotron.ca>
- *                      and Stéphane Doyon  <s.doyon@videotron.ca>
- *            Maintained by Stéphane Doyon  <s.doyon@videotron.ca>.
- */
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/* History:
- * 0.8 April 2002: Integration into the kernel tree.
- * 0.7 October 2001: First public release as a module, distributed with
- *     the BRLTTY package (beta versions around 2.99y).
- */
-
-#define DRIVER_VERSION "v0.8"
-#define DATE "April 2002"
-#define DRIVER_AUTHOR \
-	"Stephane Dalton <sdalton@videotron.ca> " \
-	"and Stéphane Doyon <s.doyon@videotron.ca>"
-#define DRIVER_DESC "Tieman Voyager braille display USB driver for Linux 2.4"
-#define DRIVER_SHORTDESC "Voyager"
-
-#define BANNER \
-	KERN_INFO DRIVER_SHORTDESC " " DRIVER_VERSION " (" DATE ")\n" \
-	KERN_INFO "   by " DRIVER_AUTHOR "\n"
-
-static const char longbanner[] = {
-	DRIVER_DESC ", " DRIVER_VERSION " (" DATE "), by " DRIVER_AUTHOR
-};
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/poll.h>
-#include <linux/brlvger.h>
-
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_LICENSE("GPL");
-
-/* Module parameters */
-
-static int debug = 1;
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level, 0-3");
-
-static int write_repeats = 2;
-MODULE_PARM(write_repeats, "i");
-MODULE_PARM_DESC(write_repeats, "Hack: repetitions for command to "
-		 "display braille pattern");
-		 /* to get rid of weird extra dots (perhaps only on
-		    early hardware versions?) */
-
-static int stall_tries = 3;
-MODULE_PARM(stall_tries, "i");
-MODULE_PARM_DESC(stall_tries, "Hack: retransmits of stalled USB "
-		 "control messages");
-                 /* broken early hardware versions? */
-
-#define BRLVGER_RAW_VOLTAGE 89
-/* from 0->300V to 255->200V, we are told 265V is normal operating voltage,
-   but we don't know the scale. Assuming it is linear. */
-static int raw_voltage = BRLVGER_RAW_VOLTAGE;
-MODULE_PARM(raw_voltage, "i");
-MODULE_PARM_DESC(raw_voltage, "Parameter for the call to SET_DISPLAY_VOLTAGE");
-
-
-/* protocol and display type defines */
-#define MAX_BRLVGER_CELLS 72
-#define MAX_INTERRUPT_DATA 8
-/* control message request types */
-#define BRLVGER_READ_REQ 0xC2
-#define BRLVGER_WRITE_REQ 0x42
-/* control message request codes */
-#define BRLVGER_SET_DISPLAY_ON 0
-#define BRLVGER_SET_DISPLAY_VOLTAGE 1
-#define BRLVGER_GET_SERIAL 3
-#define BRLVGER_GET_HWVERSION 4
-#define BRLVGER_GET_FWVERSION 5
-#define BRLVGER_GET_LENGTH 6
-#define BRLVGER_SEND_BRAILLE 7
-#define BRLVGER_BEEP 9
-#if 0 /* not used and not sure they're working */
-#define BRLVGER_GET_DISPLAY_VOLTAGE 2
-#define BRLVGER_GET_CURRENT 8
-#endif
-
-/* Prototypes */
-static int brlvger_probe (struct usb_interface *intf,
-			  const struct usb_device_id *id);
-static void brlvger_disconnect(struct usb_interface *intf);
-static int brlvger_open(struct inode *inode, struct file *file);
-static int brlvger_release(struct inode *inode, struct file *file);
-static ssize_t brlvger_write(struct file *file, const char __user *buffer,
-			     size_t count, loff_t *pos);
-static ssize_t brlvger_read(struct file *file, char __user *buffer,
-			    size_t count, loff_t *unused_pos);
-static int brlvger_ioctl(struct inode *inode, struct file *file,
-			 unsigned cmd, unsigned long arg);
-static unsigned brlvger_poll(struct file *file, poll_table *wait);
-static loff_t brlvger_llseek(struct file * file, loff_t offset, int orig);
-static void intr_callback(struct urb *urb, struct pt_regs *regs);
-struct brlvger_priv;
-static int brlvger_get_hw_version(struct brlvger_priv *priv,
-				  unsigned char *verbuf);
-static int brlvger_get_fw_version(struct brlvger_priv *priv,
-				  unsigned char *buf);
-static int brlvger_get_serial(struct brlvger_priv *priv,
-			      unsigned char *buf);
-static int brlvger_get_display_length(struct brlvger_priv *priv);
-static int brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on);
-static int brlvger_beep(struct brlvger_priv *priv, __u16 duration);
-static int brlvger_set_display_voltage(struct brlvger_priv *priv,
-				       __u16 voltage);
-static int mycontrolmsg(const char *funcname,
-                        struct brlvger_priv *priv, unsigned pipe_dir,
-                        __u8 request, __u8 requesttype, __u16 value,
-                        __u16 index, void *data, __u16 size);
-
-#define controlmsg(priv,pipe_dir,a,b,c,d,e,f) \
-     mycontrolmsg(__FUNCTION__, priv, pipe_dir, \
-                  a,b,c,d,e,f)
-#define sndcontrolmsg(priv,a,b,c,d,e,f) \
-    controlmsg(priv, 0, a,b,c,d,e,f)
-#define rcvcontrolmsg(priv,a,b,c,d,e,f) \
-    controlmsg(priv, USB_DIR_IN, a,b,c,d,e,f)
-
-/* ----------------------------------------------------------------------- */
-
-/* Data */
-
-/* key event queue size */
-#define MAX_INTERRUPT_BUFFER 10
-
-/* private state */
-struct brlvger_priv {
-	struct usb_device   *dev; /* USB device handle */
-	struct usb_endpoint_descriptor *in_interrupt;
-	struct urb *intr_urb;
-
-	int subminor; /* which minor dev #? */
-
-	unsigned char hwver[BRLVGER_HWVER_SIZE]; /* hardware version */
-	unsigned char fwver[BRLVGER_FWVER_SIZE]; /* firmware version */
-	unsigned char serialnum[BRLVGER_SERIAL_SIZE];
-
-	int llength; /* logical length */
-	int plength; /* physical length */
-
-	__u8 obuf[MAX_BRLVGER_CELLS];
-	__u8 intr_buff[MAX_INTERRUPT_DATA];
-	__u8 event_queue[MAX_INTERRUPT_BUFFER][MAX_INTERRUPT_DATA];
-	atomic_t intr_idx, read_idx;
-	spinlock_t intr_idx_lock; /* protects intr_idx */
-	wait_queue_head_t read_wait;
-
-	int opened;
-	struct semaphore open_sem; /* protects ->opened */
-	struct semaphore dev_sem; /* protects ->dev */
-};
-
-/* Globals */
-
-/* For blocking open */
-static DECLARE_WAIT_QUEUE_HEAD(open_wait);
-
-/* Some print macros */
-#ifdef dbg
-#undef dbg
-#endif
-#ifdef info
-#undef info
-#endif
-#ifdef err
-#undef err
-#endif
-#define info(args...) \
-    ({ printk(KERN_INFO "Voyager: " args); \
-       printk("\n"); })
-#define err(args...) \
-    ({ printk(KERN_ERR "Voyager: " args); \
-       printk("\n"); })
-#define dbgprint(fmt, args...) \
-    ({ printk(KERN_DEBUG "Voyager: %s: " fmt, __FUNCTION__ , ##args); \
-       printk("\n"); })
-#define dbg(args...) \
-    ({ if(debug >= 1) dbgprint(args); })
-#define dbg2(args...) \
-    ({ if(debug >= 2) dbgprint(args); })
-#define dbg3(args...) \
-    ({ if(debug >= 3) dbgprint(args); })
-
-/* ----------------------------------------------------------------------- */
-
-/* Driver registration */
-
-static struct usb_device_id brlvger_ids [] = {
-	{ USB_DEVICE(0x0798, 0x0001) },
-	{ }                     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, brlvger_ids);
-
-static struct file_operations brlvger_fops =
-{
-	.owner =	THIS_MODULE,
-	.llseek =	brlvger_llseek,
-	.read =		brlvger_read,
-	.write =	brlvger_write,
-	.ioctl =	brlvger_ioctl,
-	.open =		brlvger_open,
-	.release =	brlvger_release,
-	.poll =		brlvger_poll,
-};
-
-static struct usb_class_driver brlvger_class = {
-	.name =		"usb/brlvger%d",
-	.fops =		&brlvger_fops,
-	.mode =		S_IFCHR | S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP,
-	.minor_base =	BRLVGER_MINOR,
-};
-
-static struct usb_driver brlvger_driver =
-{
-	.owner =	THIS_MODULE,
-	.name =		"brlvger",
-	.probe =	brlvger_probe,
-	.disconnect =	brlvger_disconnect,
-	.id_table =	brlvger_ids,
-};
-
-static int
-__init brlvger_init (void)
-{
-	int retval;
-	printk(BANNER);
-
-	if(stall_tries < 1 || write_repeats < 1)
-	  return -EINVAL;
-
-	retval = usb_register(&brlvger_driver);
-	if (retval) {
-		err("USB registration failed");
-		goto out;
-	}
-
-out:
-	return retval;
-}
-
-static void
-__exit brlvger_cleanup (void)
-{
-	usb_deregister (&brlvger_driver);
-	dbg("Driver unregistered");
-}
-
-module_init (brlvger_init);
-module_exit (brlvger_cleanup);
-
-/* ----------------------------------------------------------------------- */
-
-/* Probe and disconnect functions */
-
-static int
-brlvger_probe (struct usb_interface *intf,
-	       const struct usb_device_id *id)
-{
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct brlvger_priv *priv = NULL;
-	int retval;
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_host_interface *actifsettings;
-	/* protects against reentrance: once we've found a free slot
-	   we reserve it.*/
-	static DECLARE_MUTEX(reserve_sem);
-
-	actifsettings = dev->actconfig->interface[0]->altsetting;
-
-	if( dev->descriptor.bNumConfigurations != 1
-			|| dev->config->desc.bNumInterfaces != 1 
-			|| actifsettings->desc.bNumEndpoints != 1 ) {
-		err ("Bogus braille display config info");
-		return -ENODEV;
-	}
-
-	endpoint = &actifsettings->endpoint [0].desc;
-	if (!(endpoint->bEndpointAddress & 0x80) ||
-		((endpoint->bmAttributes & 3) != 0x03)) {
-		err ("Bogus braille display config info, wrong endpoints");
-		return -ENODEV;
-	}
-
-	down(&reserve_sem);
-
-	retval = usb_register_dev(intf, &brlvger_class);
-	if (retval) {
-		err("Not able to get a minor for this device.");
-		goto error;
-	}
-
-	if( !(priv = kmalloc (sizeof *priv, GFP_KERNEL)) ){
-		err("No more memory");
-		goto error;
-	}
-
-	memset(priv, 0, sizeof(*priv));
-	atomic_set(&priv->intr_idx, 0);
-	atomic_set(&priv->read_idx, MAX_INTERRUPT_BUFFER-1);
-	spin_lock_init(&priv->intr_idx_lock);
-	init_waitqueue_head(&priv->read_wait);
-	/* opened is memset'ed to 0 */
-	init_MUTEX(&priv->open_sem);
-	init_MUTEX(&priv->dev_sem);
-
-	priv->subminor = intf->minor;
-
-	/* we found a interrupt in endpoint */
-	priv->in_interrupt = endpoint;
-
-	priv->dev = dev;
-
-	if(brlvger_get_hw_version(priv, priv->hwver) <0) {
-		err("Unable to get hardware version");
-		goto error;
-	}
-	dbg("Hw ver %d.%d", priv->hwver[0], priv->hwver[1]);
-	if(brlvger_get_fw_version(priv, priv->fwver) <0) {
-		err("Unable to get firmware version");
-		goto error;
-	}
-	dbg("Fw ver: %s", priv->fwver);
-
-	if(brlvger_get_serial(priv, priv->serialnum) <0) {
-		err("Unable to get serial number");
-		goto error;
-	}
-	dbg("Serial number: %s", priv->serialnum);
-
-	if( (priv->llength = brlvger_get_display_length(priv)) <0 ){
-		err("Unable to get display length");
-		goto error;
-	}
-	switch(priv->llength) {
-	case 48:
-		priv->plength = 44;
-		break;
-	case 72:
-		priv->plength = 70;
-		break;
-	default:
-		err("Unsupported display length: %d", priv->llength);
-		goto error;
-	};
-	dbg("Display length: %d", priv->plength);
-
-	usb_set_intfdata (intf, priv);
-	info( "Braille display %d is device major %d minor %d",
-				intf->minor, USB_MAJOR, BRLVGER_MINOR + intf->minor);
-
-	/* Tell anyone waiting on a blocking open */
-	wake_up_interruptible(&open_wait);
-
-	goto out;
-
- error:
-	if(priv) {
-		kfree( priv );
-		priv = NULL;
-	}
-
- out:
-	up(&reserve_sem);
-	if (priv) {
-		usb_set_intfdata (intf, priv);
-		return 0;
-	}
-	return -EIO;
-}
-
-static void
-brlvger_disconnect(struct usb_interface *intf)
-{
-	struct brlvger_priv *priv = usb_get_intfdata (intf);
-	int r;
-
-	usb_set_intfdata (intf, NULL);
-	if(priv){
-		info("Display %d disconnecting", priv->subminor);
-
-		usb_deregister_dev(intf, &brlvger_class);
-
-		down(&priv->open_sem);
-		down(&priv->dev_sem);
-		if(priv->opened) {
-			/* Disable interrupts */
-			if((r = usb_unlink_urb(priv->intr_urb)) <0)
-				err("usb_unlink_urb returns %d", r);
-			usb_free_urb(priv->intr_urb);
-			/* mark device as dead and prevent control
-			   messages to it */
-			priv->dev = NULL;
-			/* Tell anyone hung up on a read that it
-			   won't be coming */
-			wake_up_interruptible(&priv->read_wait);
-			up(&priv->dev_sem);
-			up(&priv->open_sem);
-		}else
-			/* no corresponding up()s */
-			kfree(priv);
-	}
-}
-
-/* ----------------------------------------------------------------------- */
-
-/* fops implementation */
-
-static int
-brlvger_open(struct inode *inode, struct file *file)
-{
-	int devnum = iminor(inode);
-	struct usb_interface *intf = NULL;
-	struct brlvger_priv *priv = NULL;
-	int n, ret;
-
-	if (devnum < 0)
-		return -ENXIO;
-
-	n = devnum - BRLVGER_MINOR;
-
-	do {
-		intf = usb_find_interface(&brlvger_driver, devnum);
-		if (!intf) {
-			if (file->f_flags & O_NONBLOCK) {
-				dbg3("Failing non-blocking open: "
-				     "device %d not connected", n);
-				return -EAGAIN;
-			}
-			/* Blocking open. One global wait queue will
-			   suffice. We wait until a device for the selected
-			   minor is connected. */
-			dbg2("Waiting for device %d to be connected", n);
-			ret = wait_event_interruptible(open_wait,
-						       (intf = usb_find_interface(&brlvger_driver, devnum)));
-			if (ret) {
-				dbg2("Interrupted wait for device %d", n);
-				return ret;
-			}
-		}
-	} while(!intf);
-	priv = usb_get_intfdata(intf);
-
-	/* We grabbed an existing device. */
-	if(down_interruptible(&priv->open_sem))
-		return -ERESTARTSYS;
-
-	/* Only one process can open each device, no sharing. */
-	ret = -EBUSY;
-	if(priv->opened)
-		goto out;
-
-	dbg("Opening display %d", priv->subminor);
-
-	/* Setup interrupt handler for receiving key input */
-	priv->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if(!priv->intr_urb) {
-		err("Unable to allocate URB");
-		goto out;
-	}
-	usb_fill_int_urb( priv->intr_urb, priv->dev,
-			usb_rcvintpipe(priv->dev,
-				       priv->in_interrupt->bEndpointAddress),
-			priv->intr_buff, sizeof(priv->intr_buff),
-			intr_callback, priv, priv->in_interrupt->bInterval);
-	if((ret = usb_submit_urb(priv->intr_urb, GFP_KERNEL)) <0){
-		err("Error %d while submitting URB", ret);
-		goto out;
-	}
-
-	/* Set voltage */
-	if(brlvger_set_display_voltage(priv, raw_voltage) <0) {
-		err("Unable to set voltage");
-		goto out;
-	}
-
-	/* Turn display on */
-	if((ret = brlvger_set_display_on_off(priv, 1)) <0) {
-		err("Error %d while turning display on", ret);
-		goto out;
-	}
-
-	/* Mark as opened, so disconnect cannot free priv. */
-	priv->opened = 1;
-
-	file->private_data = priv;
-
-	ret = 0;
-	goto out;
-
- out:
-	up(&priv->open_sem);
-	return ret;
-}
-
-static int
-brlvger_release(struct inode *inode, struct file *file)
-{
-	struct brlvger_priv *priv = file->private_data;
-	int r;
-
-	/* Turn display off. Safe even if disconnected. */
-	brlvger_set_display_on_off(priv, 0);
-
-	/* mutex with disconnect and with open */
-	down(&priv->open_sem);
-
-	if(!priv->dev) {
-		dbg("Releasing disconnected device %d", priv->subminor);
-		/* no up(&priv->open_sem) */
-		kfree(priv);
-	}else{
-		dbg("Closing display %d", priv->subminor);
-		/* Disable interrupts */
-		if((r = usb_unlink_urb(priv->intr_urb)) <0)
-			err("usb_unlink_urb returns %d", r);
-		usb_free_urb(priv->intr_urb);
-		priv->opened = 0;
-		up(&priv->open_sem);
-	}
-
-	return 0;
-}
-
-static ssize_t
-brlvger_write(struct file *file, const char __user *buffer,
-	      size_t count, loff_t *pos)
-{
-	struct brlvger_priv *priv = file->private_data;
-	char buf[MAX_BRLVGER_CELLS];
-	int ret;
-	size_t rs;
-	loff_t off;
-	__u16 written;
-
-	if(!priv->dev)
-		return -ENOLINK;
-
-	off = *pos;
-
-	if(off > priv->plength)
-		return -ESPIPE;;
-
-	rs = priv->plength - off;
-
-	if(count > rs)
-		count = rs;
-	written = count;
-
-	if (copy_from_user (buf, buffer, count ) )
-		return -EFAULT;
-
-	memset(priv->obuf, 0xaa, sizeof(priv->obuf));
-
-	/* Firmware supports multiples of 8cells, so some cells are absent
-	   and for some reason there actually are holes! euurkkk! */
-
-	if( priv->plength == 44 ) {
-		/* Two ghost cells at the beginning of the display, plus
-		   two more after the sixth physical cell. */
-		if(off > 5) {
-			off +=4;
-			memcpy(priv->obuf, buf, count);
-		}else{
-			int firstpart = 6 - off;
-			
-#ifdef WRITE_DEBUG
-			dbg3("off: %lld, rs: %d, count: %d, firstpart: %d",
-			     off, rs, count, firstpart);
-#endif
-
-			firstpart = (firstpart < count) ? firstpart : count;
-
-#ifdef WRITE_DEBUG
-			dbg3("off: %lld", off);
-			dbg3("firstpart: %d", firstpart);
-#endif
-
-			memcpy(priv->obuf, buf, firstpart);
-
-			if(firstpart != count) {
-				int secondpart = count - firstpart;
-#ifdef WRITE_DEBUG
-				dbg3("secondpart: %d", secondpart);
-#endif
-
-				memcpy(priv->obuf+(firstpart+2),
-				       buf+firstpart, secondpart);
-				written +=2;
-			}
-
-			off +=2;
-
-#ifdef WRITE_DEBUG
-			dbg3("off: %lld, rs: %d, count: %d, firstpart: %d, "
-				"written: %d", 	off, rs, count, firstpart, written);
-#endif
-		}
-	}else{
-		/* Two ghost cells at the beginningg of the display. */
-		memcpy(priv->obuf, buf, count);
-		off += 2;
-	}
-
-	{
-		int repeat = write_repeats;
-		/* Dirty hack: sometimes some of the dots are wrong and somehow
-		   right themselves if the command is repeated. */
-		while(repeat--) {
-			ret = sndcontrolmsg(priv,
-				BRLVGER_SEND_BRAILLE, BRLVGER_WRITE_REQ, 0,
-				off, priv->obuf, written);
-			if(ret <0)
-				return ret;
-		}
-	}
-
-	return count;
-}
-
-static int
-read_index(struct brlvger_priv *priv)
-{
-	int intr_idx, read_idx;
-
-	read_idx = atomic_read(&priv->read_idx);
-	read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
-
-	intr_idx = atomic_read(&priv->intr_idx);
-
-	return(read_idx == intr_idx ? -1 : read_idx);
-}
-
-static ssize_t
-brlvger_read(struct file *file, char __user *buffer,
-	     size_t count, loff_t *unused_pos)
-{
-	struct brlvger_priv *priv = file->private_data;
-	int read_idx;
-
-	if(count != MAX_INTERRUPT_DATA)
-		return -EINVAL;
-
-	if(!priv->dev)
-		return -ENOLINK;
-
-	if((read_idx = read_index(priv)) == -1) {
-		/* queue empty */
-		if (file->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-		else{
-			int r = wait_event_interruptible(priv->read_wait,
-							 (!priv->dev || (read_idx = read_index(priv)) != -1));
-			if(!priv->dev)
-				return -ENOLINK;
-			if(r)
-				return r;
-			if(read_idx == -1)
-				/* should not happen */
-				return 0;
-		}
-	}
-
-	if (copy_to_user (buffer, priv->event_queue[read_idx], count) )
-		return( -EFAULT);
-
-	atomic_set(&priv->read_idx, read_idx);
-	/* Multiple opens are not allowed. Yet on SMP, two processes could
-	   read at the same time (on a shared file descriptor); then it is not
-	   deterministic whether or not they will get duplicates of a key
-	   event. */
-	return MAX_INTERRUPT_DATA;
-}
-
-static int
-brlvger_ioctl(struct inode *inode, struct file *file,
-	      unsigned cmd, unsigned long arg)
-{
-	struct brlvger_priv *priv = file->private_data;
-
-	if(!priv->dev)
-		return -ENOLINK;
-
-	switch(cmd) {
-	case BRLVGER_GET_INFO: {
-		struct brlvger_info vi;
-
-		memset(&vi, 0, sizeof(vi));
-		strlcpy(vi.driver_version, DRIVER_VERSION,
-			sizeof(vi.driver_version));
-		strlcpy(vi.driver_banner, longbanner,
-			sizeof(vi.driver_banner));
-
-		vi.display_length = priv->plength;
-		
-		memcpy(&vi.hwver, priv->hwver, BRLVGER_HWVER_SIZE);
-		memcpy(&vi.fwver, priv->fwver, BRLVGER_FWVER_SIZE);
-		memcpy(&vi.serialnum, priv->serialnum, BRLVGER_SERIAL_SIZE);
-
-		if(copy_to_user((void __user *)arg, &vi, sizeof(vi)))
-			return -EFAULT;
-		return 0;
-	}
-	case BRLVGER_DISPLAY_ON:
-		return brlvger_set_display_on_off(priv, 1);
-	case BRLVGER_DISPLAY_OFF:
-		return brlvger_set_display_on_off(priv, 0);
-	case BRLVGER_BUZZ: {
-		__u16 duration;
-		if(get_user(duration, (__u16 *)arg))
-			return -EFAULT;
-		return brlvger_beep(priv, duration);
-	}
-
-#if 0 /* Underlying commands don't seem to work for some reason; not clear if
-	 we'd want to export these anyway. */
-	case BRLVGER_SET_VOLTAGE: {
-		__u16 voltage;
-		if(get_user(voltage, (__u16 *)arg))
-			return -EFAULT;
-		return brlvger_set_display_voltage(priv, voltage);
-	}
-	case BRLVGER_GET_VOLTAGE: {
-		__u8 voltage;
-		int r = brlvger_get_display_voltage(priv);
-		if(r <0)
-			return r;
-		voltage = r;
-		if(put_user(voltage, (__u8 *)arg))
-			return -EFAULT;
-		return 0;
-	}
-#endif
-	default:
-		return -EINVAL;
-	};
-}
-
-static loff_t
-brlvger_llseek(struct file *file, loff_t offset, int orig)
-{
-	struct brlvger_priv *priv = file->private_data;
-
-	if(!priv->dev)
-		return -ENOLINK;
-
-	switch (orig) {
-		case 0:
-			/*  nothing to do */
-			break;
-		case 1:
-			offset +=file->f_pos;
-			break;
-		case 2:
-			offset += priv->plength;
-		default:
-			return -EINVAL;
-	}
-
-	if((offset >= priv->plength) || (offset < 0))
-		return -EINVAL;
-
-	return (file->f_pos = offset);
-}
-
-static unsigned
-brlvger_poll(struct file *file, poll_table *wait) 
-{
-	struct brlvger_priv *priv = file->private_data;
-
-	if(!priv->dev)
-		return POLLERR | POLLHUP;
-
-	poll_wait(file, &priv->read_wait, wait);
-
-	if(!priv->dev)
-		return POLLERR | POLLHUP;
-	if(read_index(priv) != -1)
-		return POLLIN | POLLRDNORM;
-
-	return 0;
-}
-
-static void
-intr_callback(struct urb *urb, struct pt_regs *regs)
-{
-	struct brlvger_priv *priv = urb->context;
-	int intr_idx, read_idx;
-	int status;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	read_idx = atomic_read(&priv->read_idx);
-	spin_lock(&priv->intr_idx_lock);
-	intr_idx = atomic_read(&priv->intr_idx);
-	if(read_idx == intr_idx) {
-		dbg2("Queue full, dropping braille display input");
-		spin_unlock(&priv->intr_idx_lock);
-		goto exit;	/* queue full */
-	}
-
-	memcpy(priv->event_queue[intr_idx], urb->transfer_buffer,
-	       MAX_INTERRUPT_DATA);
-
-	intr_idx = (++intr_idx == MAX_INTERRUPT_BUFFER)? 0 : intr_idx;
-	atomic_set(&priv->intr_idx, intr_idx);
-	spin_unlock(&priv->intr_idx_lock);
-
-	wake_up_interruptible(&priv->read_wait);
-
-exit:
-	status = usb_submit_urb (urb, GFP_ATOMIC);
-	if (status)
-		err ("%s - usb_submit_urb failed with result %d",
-		     __FUNCTION__, status);
-}
-
-/* ----------------------------------------------------------------------- */
-
-/* Hardware access functions */
-
-static int
-mycontrolmsg(const char *funcname,
-	     struct brlvger_priv *priv, unsigned pipe_dir,
-	     __u8 request, __u8 requesttype, __u16 value,
-	     __u16 index, void *data, __u16 size)
-{
-	int ret=0, tries = stall_tries;
-
-	/* Make sure the device was not disconnected */
-	if(down_interruptible(&priv->dev_sem))
-		return -ERESTARTSYS;
-	if(!priv->dev) {
-		up(&priv->dev_sem);
-		return -ENOLINK;
-	}
-
-	/* Dirty hack for retransmission: stalls and fails all the time
-	   without this on the hardware we tested. */
-	while(tries--) {
-		ret = usb_control_msg(priv->dev,
-		    usb_sndctrlpipe(priv->dev,0) |pipe_dir,
-		    request, requesttype, value,
-		    index, data, size,
-		    HZ);
-		if(ret != -EPIPE)
-			break;
-		dbg2("Stalled, remaining %d tries", tries);
-	}
-	up(&priv->dev_sem);
-	if(ret <0) {
-		err("%s: usb_control_msg returns %d",
-				funcname, ret);
-		return -EIO;
-	}
-	return 0;
-}
-
-static int
-brlvger_get_hw_version(struct brlvger_priv *priv, unsigned char *verbuf)
-{
-	return rcvcontrolmsg(priv,
-	    BRLVGER_GET_HWVERSION, BRLVGER_READ_REQ, 0,
-	    0, verbuf, BRLVGER_HWVER_SIZE);
-	/* verbuf should be 2 bytes */
-}
-
-static int
-brlvger_get_fw_version(struct brlvger_priv *priv, unsigned char *buf)
-{
-	unsigned char rawbuf[(BRLVGER_FWVER_SIZE-1)*2+2];
-	int i, len;
-	int r = rcvcontrolmsg(priv,
-			      BRLVGER_GET_FWVERSION, BRLVGER_READ_REQ, 0,
-			      0, rawbuf, sizeof(rawbuf));
-	if(r<0)
-		return r;
-
-	/* If I guess correctly: succession of 16bit words, the string is
-           formed of the first byte of each of these words. First byte in
-           buffer indicates total length of data; not sure what second byte is
-           for. */
-	len = rawbuf[0]-2;
-	if(len<0)
-		len = 0;
-	else if(len+1 > BRLVGER_FWVER_SIZE)
-		len = BRLVGER_FWVER_SIZE-1;
-	for(i=0; i<len; i++)
-		buf[i] = rawbuf[2+2*i];
-	buf[i] = 0;
-	return 0;
-}
-
-static int
-brlvger_get_serial(struct brlvger_priv *priv, unsigned char *buf)
-{
-	unsigned char rawserial[BRLVGER_SERIAL_BIN_SIZE];
-	int i;
-	int r = rcvcontrolmsg(priv,
-			      BRLVGER_GET_SERIAL, BRLVGER_READ_REQ, 0,
-			      0, rawserial, sizeof(rawserial));
-	if(r<0)
-		return r;
-
-	for(i=0; i<BRLVGER_SERIAL_BIN_SIZE; i++) {
-#define NUM_TO_HEX(n) (((n)>9) ? (n)+'A' : (n)+'0')
-		buf[2*i] = NUM_TO_HEX(rawserial[i] >>4);
-		buf[2*i+1] = NUM_TO_HEX(rawserial[i] &0xf);
-	}
-	buf[2*i] = 0;
-	return 0;
-}
-
-static int
-brlvger_get_display_length(struct brlvger_priv *priv)
-{
-	unsigned char data[2];
-	int ret = rcvcontrolmsg(priv,
-	    BRLVGER_GET_LENGTH, BRLVGER_READ_REQ, 0,
-	    0, data, 2);
-	if(ret<0)
-		return ret;
-	return data[1];
-}
-
-static int
-brlvger_beep(struct brlvger_priv *priv, __u16 duration)
-{
-	return sndcontrolmsg(priv,
-	    BRLVGER_BEEP, BRLVGER_WRITE_REQ, duration,
-	    0, NULL, 0);
-}
-
-static int
-brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on)
-{
-	dbg2("Turning display %s", ((on) ? "on" : "off"));
-	return sndcontrolmsg(priv,
-	    BRLVGER_SET_DISPLAY_ON,	BRLVGER_WRITE_REQ, on,
-	    0, NULL, 0);
-}
-
-static int
-brlvger_set_display_voltage(struct brlvger_priv *priv, __u16 voltage)
-{
-	dbg("SET_DISPLAY_VOLTAGE to %u", voltage);
-        return sndcontrolmsg(priv,
-	     BRLVGER_SET_DISPLAY_VOLTAGE, BRLVGER_WRITE_REQ, voltage,
-	     0, NULL, 0);
-}
-
-#if 0 /* Had problems testing these commands. Not particularly useful anyway.*/
-
-static int
-brlvger_get_display_voltage(struct brlvger_priv *priv)
-{
-	__u8 voltage = 0;
-	int ret = rcvcontrolmsg(priv,
-	    BRLVGER_GET_DISPLAY_VOLTAGE, BRLVGER_READ_REQ, 0,
-	    0, &voltage, 1);
-	if(ret<0)
-		return ret;
-	return voltage;
-}
-
-static int
-brlvger_get_current(struct brlvger_priv *priv)
-{
-	unsigned char data;
-	int ret = rcvcontrolmsg(priv,
-	    BRLVGER_GET_CURRENT,	BRLVGER_READ_REQ,	0,
-	    0, &data, 1);
-	if(ret<0)
-		return ret;
-	return data;
-}
-#endif
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/misc/usbtest.c	Wed Mar 17 19:29:10 2004
@@ -149,8 +149,6 @@
 				if (!out)
 					out = e;
 			}
-			if (in && out)
-				goto found;
 			continue;
 try_iso:
 			if (e->desc.bEndpointAddress & USB_DIR_IN) {
@@ -160,9 +158,9 @@
 				if (!iso_out)
 					iso_out = e;
 			}
-			if (iso_in && iso_out)
-				goto found;
 		}
+		if ((in && out)  ||  (iso_in && iso_out))
+			goto found;
 	}
 	return -EINVAL;
 
@@ -181,7 +179,8 @@
 			in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
 		dev->out_pipe = usb_sndbulkpipe (udev,
 			out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-	} else if (iso_in) {
+	}
+	if (iso_in) {
 		dev->iso_in = &iso_in->desc;
 		dev->in_iso_pipe = usb_rcvisocpipe (udev,
 				iso_in->desc.bEndpointAddress
@@ -211,7 +210,7 @@
 static struct urb *simple_alloc_urb (
 	struct usb_device	*udev,
 	int			pipe,
-	long			bytes
+	unsigned long		bytes
 )
 {
 	struct urb		*urb;
@@ -490,7 +489,7 @@
 	struct usb_interface		*iface = dev->intf;
 	struct usb_device		*udev;
 
-	if (alternate < 0 || alternate >= iface->num_altsetting)
+	if (alternate < 0 || alternate >= 256)
 		return -EINVAL;
 
 	udev = interface_to_usbdev (iface);
@@ -556,23 +555,19 @@
 {
 	struct usb_interface	*iface = dev->intf;
 	struct usb_device	*udev = interface_to_usbdev (iface);
-	int			i, retval;
+	int			i, alt, retval;
 
 	/* [9.2.3] if there's more than one altsetting, we need to be able to
 	 * set and get each one.  mostly trusts the descriptors from usbcore.
 	 */
 	for (i = 0; i < iface->num_altsetting; i++) {
 
-		/* 9.2.3 constrains the range here, and Linux ensures
-		 * they're ordered meaningfully in this array
-		 */
-		if (iface->altsetting [i].desc.bAlternateSetting != i) {
+		/* 9.2.3 constrains the range here */
+		alt = iface->altsetting [i].desc.bAlternateSetting;
+		if (alt < 0 || alt >= iface->num_altsetting) {
 			dev_dbg (&iface->dev,
 					"invalid alt [%d].bAltSetting = %d\n",
-					i, 
-					iface->altsetting [i].desc
-						.bAlternateSetting);
-			return -EDOM;
+					i, alt);
 		}
 
 		/* [real world] get/set unimplemented if there's only one */
@@ -580,18 +575,18 @@
 			continue;
 
 		/* [9.4.10] set_interface */
-		retval = set_altsetting (dev, i);
+		retval = set_altsetting (dev, alt);
 		if (retval) {
 			dev_dbg (&iface->dev, "can't set_interface = %d, %d\n",
-					i, retval);
+					alt, retval);
 			return retval;
 		}
 
 		/* [9.4.4] get_interface always works */
 		retval = get_altsetting (dev);
-		if (retval != i) {
+		if (retval != alt) {
 			dev_dbg (&iface->dev, "get alt should be %d, was %d\n",
-					i, retval);
+					alt, retval);
 			return (retval < 0) ? retval : -EDOM;
 		}
 
@@ -916,7 +911,7 @@
 			req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8);
 			// interface == 0
 			len = sizeof (struct usb_interface_descriptor);
-			expected = -EPIPE;
+			expected = EPIPE;
 			break;
 		// NOTE: two consecutive stalls in the queue here.
 		// that tests fault recovery a bit more aggressively.
@@ -945,7 +940,7 @@
 			req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8);
 			// endpoint == 0
 			len = sizeof (struct usb_interface_descriptor);
-			expected = -EPIPE;
+			expected = EPIPE;
 			break;
 		// NOTE: sometimes even a third fault in the queue!
 		case 12:	// get string 0 descriptor (MAY STALL)
@@ -1072,7 +1067,7 @@
 	 * due to errors, or is just NAKing requests.
 	 */
 	if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) {
-		dbg ("submit/unlink fail %d", retval);
+		dev_dbg (&dev->intf->dev, "submit fail %d\n", retval);
 		return retval;
 	}
 
@@ -1087,18 +1082,22 @@
 		 * "normal" drivers would prevent resubmission, but
 		 * since we're testing unlink paths, we can't.
 		 */
-		dbg ("unlink retry");
+		dev_dbg (&dev->intf->dev, "unlink retry\n");
 		goto retry;
 	}
 	if (!(retval == 0 || retval == -EINPROGRESS)) {
-		dbg ("submit/unlink fail %d", retval);
+		dev_dbg (&dev->intf->dev, "unlink fail %d\n", retval);
 		return retval;
 	}
 
 	wait_for_completion (&completion);
 	retval = urb->status;
 	simple_free_urb (urb);
-	return retval;
+
+	if (async)
+		return (retval != -ECONNRESET) ? -ECONNRESET : 0;
+	else
+		return (retval != -ENOENT) ? -ENOENT : 0;
 }
 
 static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
@@ -1723,7 +1722,8 @@
 			retval = unlink_simple (dev, dev->in_pipe,
 						param->length);
 		if (retval)
-			dbg ("unlink reads failed, iterations left %d", i);
+			dev_dbg (&intf->dev, "unlink reads failed %d, "
+				"iterations left %d\n", retval, i);
 		break;
 	case 12:
 		if (dev->out_pipe == 0 || !param->length)
@@ -1735,7 +1735,8 @@
 			retval = unlink_simple (dev, dev->out_pipe,
 						param->length);
 		if (retval)
-			dbg ("unlink writes failed, iterations left %d", i);
+			dev_dbg (&intf->dev, "unlink writes failed %d, "
+				"iterations left %d\n", retval, i);
 		break;
 
 	/* ep halt tests */
@@ -1965,7 +1966,10 @@
 	.name		= "usb test device",
 	.ep_in		= 2,
 	.ep_out		= 2,
-	.alt		= 0,
+	.alt		= 1,
+	.autoconf	= 1,		// iso and ctrl_out need autoconf
+	.ctrl_out	= 1,
+	.iso		= 1,		// iso_ep's are #8 in/out
 };
 
 /* peripheral running Linux and 'zero.c' test firmware, or
diff -Nru a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
--- a/drivers/usb/net/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/net/Kconfig	Wed Mar 17 19:29:10 2004
@@ -131,6 +131,14 @@
 comment "USB Host-to-Host Cables"
 	depends on USB_USBNET
 
+config USB_ALI_M5632
+	boolean "ALi M5632 based 'USB 2.0 Data Link' cables"
+	depends on USB_USBNET
+	default y
+	help
+	  Choose this option if you're using a host-to-host cable
+	  based on this design, which supports USB 2.0 high speed.
+
 config USB_AN2720
 	boolean "AnchorChips 2720 based cables (Xircom PGUNET, ...)"
 	depends on USB_USBNET
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/net/pegasus.h	Wed Mar 17 19:29:10 2004
@@ -128,6 +128,7 @@
 #define	VENDOR_DLINK		0x2001
 #define	VENDOR_ELCON		0x0db7
 #define	VENDOR_ELSA		0x05cc
+#define	VENDOR_GIGABYTE		0x1044
 #define	VENDOR_HAWKING		0x0e66
 #define	VENDOR_HP		0x03f0
 #define	VENDOR_IODATA		0x04bb
@@ -178,6 +179,9 @@
 PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet",
 		VENDOR_ADMTEK, 0x8513,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "ADMtek ADM8515 \"Pegasus II\" USB-2.0 Ethernet",
+		VENDOR_ADMTEK, 0x8515,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)",
 		VENDOR_ADMTEK, 0x0986,
 		DEFAULT_GPIO_RESET | HAS_HOME_PNA )
@@ -223,6 +227,8 @@
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
 		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002,
+		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c,
@@ -262,6 +268,8 @@
 PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "OCT Inc.", VENDOR_OCT, 0x0109,
+		DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "OCT USB TO Ethernet", VENDOR_OCT, 0x0901,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
 		DEFAULT_GPIO_RESET | PEGASUS_II )
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/net/usbnet.c	Wed Mar 17 19:29:09 2004
@@ -384,6 +384,23 @@
 }
 
 
+#ifdef	CONFIG_USB_ALI_M5632
+#define	HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * ALi M5632 driver ... does high speed
+ *
+ *-------------------------------------------------------------------------*/
+
+static const struct driver_info	ali_m5632_info = {
+	.description =	"ALi M5632",
+};
+
+
+#endif
+
+
 #ifdef	CONFIG_USB_AN2720
 #define	HAVE_HARDWARE
 
@@ -3009,7 +3026,7 @@
 		return -ENODEV;
 	}
 	xdev = interface_to_usbdev (udev);
-	interface = &udev->altsetting [udev->act_altsetting];
+	interface = udev->cur_altsetting;
 
 	usb_get_dev (xdev);
 
@@ -3133,6 +3150,13 @@
 
 static const struct usb_device_id	products [] = {
 
+#ifdef	CONFIG_USB_ALI_M5632
+{
+	USB_DEVICE (0x0402, 0x5632),	// ALi defaults
+	.driver_info =	(unsigned long) &ali_m5632_info,
+},
+#endif
+
 #ifdef	CONFIG_USB_AN2720
 {
 	USB_DEVICE (0x0547, 0x2720),	// AnchorChips defaults
@@ -3310,6 +3334,15 @@
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
 	.idProduct              = 0x9032,	/* SL-6000 */
+	.bInterfaceClass        = 0x02,
+	.bInterfaceSubClass     = 0x0a,
+	.bInterfaceProtocol     = 0x00,
+	.driver_info =  (unsigned long) &zaurus_pxa_info,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
+	.idProduct              = 0x9050,	/* C-860 */
 	.bInterfaceClass        = 0x02,
 	.bInterfaceSubClass     = 0x0a,
 	.bInterfaceProtocol     = 0x00,
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/serial/ftdi_sio.c	Wed Mar 17 19:29:10 2004
@@ -286,6 +286,7 @@
 
 
 static struct usb_device_id id_table_8U232AM [] = {
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
@@ -358,6 +359,7 @@
 
 
 static struct usb_device_id id_table_FT232BM [] = {
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
@@ -451,6 +453,7 @@
 
 
 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) },
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/serial/ftdi_sio.h	Wed Mar 17 19:29:10 2004
@@ -30,6 +30,8 @@
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
 
+/* www.irtrans.de device */
+#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
 
 /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
 /* they use the ftdi chipset for the USB interface and the vendor id is the same */
diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
--- a/drivers/usb/serial/kl5kusb105.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/serial/kl5kusb105.c	Wed Mar 17 19:29:09 2004
@@ -273,6 +273,7 @@
 
 	/* allocate the private data structure */
 	for (i=0; i<serial->num_ports; i++) {
+		int j;
 		priv = kmalloc(sizeof(struct klsi_105_private),
 						   GFP_KERNEL);
 		if (!priv) {
@@ -293,10 +294,10 @@
 		usb_set_serial_port_data(serial->port[i], priv);
 
 		spin_lock_init (&priv->lock);
-		for (i=0; i<NUM_URBS; i++) {
+		for (j=0; j<NUM_URBS; j++) {
 			struct urb* urb = usb_alloc_urb(0, GFP_KERNEL);
 
-			priv->write_urb_pool[i] = urb;
+			priv->write_urb_pool[j] = urb;
 			if (urb == NULL) {
 				err("No more urbs???");
 				continue;
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/serial/pl2303.c	Wed Mar 17 19:29:09 2004
@@ -403,7 +403,7 @@
 {
 	struct termios tmp_termios;
 	struct usb_serial *serial = port->serial;
-	unsigned char buf[10];
+	unsigned char *buf;
 	int result;
 
 	if (port_paranoia_check (port, __FUNCTION__))
@@ -414,6 +414,10 @@
 	usb_clear_halt(serial->dev, port->write_urb->pipe);
 	usb_clear_halt(serial->dev, port->read_urb->pipe);
 
+	buf = kmalloc(10, GFP_KERNEL);
+	if (buf==NULL)
+		return -ENOMEM;
+
 #define FISH(a,b,c,d)								\
 	result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
 			       b, a, c, d, buf, 1, 100);			\
@@ -432,6 +436,8 @@
 	SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
 	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
 	FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
+
+	kfree(buf);
 
 	/* Setup termios */
 	if (port->tty) {
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/serial/usb-serial.c	Wed Mar 17 19:29:09 2004
@@ -391,7 +391,7 @@
 	struct usb_serial *serial = serial_table[index];
 
 	if (serial)
-		kobject_get (&serial->kobj);
+		kref_get(&serial->kref);
 	return serial;
 }
 
@@ -486,7 +486,7 @@
 		if (retval) {
 			port->open_count = 0;
 			module_put(serial->type->owner);
-			kobject_put(&serial->kobj);
+			kref_put(&serial->kref);
 		}
 	}
 bailout:
@@ -518,7 +518,7 @@
 	}
 
 	module_put(port->serial->type->owner);
-	kobject_put(&port->serial->kobj);
+	kref_put(&port->serial->kref);
 }
 
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
@@ -748,7 +748,7 @@
 			begin += length;
 			length = 0;
 		}
-		kobject_put(&serial->kobj);
+		kref_put(&serial->kref);
 	}
 	*eof = 1;
 done:
@@ -830,15 +830,15 @@
 	wake_up_interruptible(&tty->write_wait);
 }
 
-static void destroy_serial (struct kobject *kobj)
+static void destroy_serial(struct kref *kref)
 {
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
 	int i;
 
-	dbg ("%s - %s", __FUNCTION__, kobj->name);
+	serial = to_usb_serial(kref);
 
-	serial = to_usb_serial(kobj);
+	dbg ("%s - %s", __FUNCTION__, serial->type->name);
 	serial_shutdown (serial);
 
 	/* return the minor range that this device had */
@@ -886,10 +886,6 @@
 	kfree (serial);
 }
 
-static struct kobj_type usb_serial_kobj_type = {
-	.release = destroy_serial,
-};
-
 static void port_release(struct device *dev)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
@@ -930,10 +926,7 @@
 	serial->interface = interface;
 	serial->vendor = dev->descriptor.idVendor;
 	serial->product = dev->descriptor.idProduct;
-
-	/* initialize the kobject portion of the usb_device */
-	kobject_init(&serial->kobj);
-	serial->kobj.ktype = &usb_serial_kobj_type;
+	kref_init(&serial->kref, destroy_serial);
 
 	return serial;
 }
@@ -1006,7 +999,7 @@
 
 	/* descriptor matches, let's find the endpoints needed */
 	/* check out the 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;
 		
@@ -1284,7 +1277,7 @@
 	if (serial) {
 		/* let the last holder of this object 
 		 * cause it to be cleaned up */
-		kobject_put (&serial->kobj);
+		kref_put(&serial->kref);
 	}
 	dev_info(dev, "device disconnected\n");
 }
diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/serial/usb-serial.h	Wed Mar 17 19:29:10 2004
@@ -55,6 +55,7 @@
 #define __LINUX_USB_SERIAL_H
 
 #include <linux/config.h>
+#include <linux/kref.h>
 
 #define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
 #define SERIAL_TTY_MINORS	255	/* loads of devices :) */
@@ -163,10 +164,10 @@
 	__u16				vendor;
 	__u16				product;
 	struct usb_serial_port *	port[MAX_NUM_PORTS];
-	struct kobject			kobj;
+	struct kref			kref;
 	void *				private;
 };
-#define to_usb_serial(d) container_of(d, struct usb_serial, kobj)
+#define to_usb_serial(d) container_of(d, struct usb_serial, kref)
 
 #define NUM_DONT_CARE	(-1)
 
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/serial/visor.c	Wed Mar 17 19:29:09 2004
@@ -239,6 +239,8 @@
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), 
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
+	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), 
+		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), 
 		.driver_info = (kernel_ulong_t)&palm_os_4_probe },
 	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
@@ -275,6 +277,7 @@
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
+	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
 	{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
 	{ },					/* optional parameter entry */
diff -Nru a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
--- a/drivers/usb/serial/visor.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/serial/visor.h	Wed Mar 17 19:29:10 2004
@@ -46,6 +46,7 @@
 
 #define SAMSUNG_VENDOR_ID		0x04E8
 #define SAMSUNG_SCH_I330_ID		0x8001
+#define SAMSUNG_SPH_I500_ID		0x6601
 
 #define GARMIN_VENDOR_ID		0x091E
 #define GARMIN_IQUE_3600_ID		0x0004
diff -Nru a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
--- a/drivers/usb/storage/Kconfig	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/storage/Kconfig	Wed Mar 17 19:29:10 2004
@@ -1,8 +1,6 @@
 #
 # USB Storage driver configuration
 #
-comment "SCSI support is needed for USB Storage"
-	depends on USB && SCSI=n
 
 config USB_STORAGE
 	tristate "USB Mass Storage support"
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/storage/scsiglue.c	Wed Mar 17 19:29:09 2004
@@ -64,8 +64,10 @@
 	return "SCSI emulation for USB Mass Storage devices";
 }
 
-static int slave_configure (struct scsi_device *sdev)
+static int slave_configure(struct scsi_device *sdev)
 {
+	struct us_data *us = (struct us_data *) sdev->host->hostdata[0];
+
 	/* Scatter-gather buffers (all but the last) must have a length
 	 * divisible by the bulk maxpacket size.  Otherwise a data packet
 	 * would end up being short, causing a premature end to the data
@@ -75,6 +77,16 @@
 	 * have the desired effect because, except at the beginning and
 	 * 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
+	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS &&
+			us->pusb_dev->speed == USB_SPEED_HIGH)
+		blk_queue_max_sectors(sdev->request_queue, 128);
 
 	/* this is to satisify the compiler, tho I don't think the 
 	 * return code is ever checked anywhere. */
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/storage/transport.c	Wed Mar 17 19:29:09 2004
@@ -563,9 +563,9 @@
 
 	/*
 	 * If we're running the CB transport, which is incapable
-	 * of determining status on its own, we need to auto-sense
+	 * of determining status on its own, we will auto-sense
 	 * unless the operation involved a data-in transfer.  Devices
-	 * can signal data-in errors by stalling the bulk-in pipe.
+	 * 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) {
@@ -698,7 +698,11 @@
 		 * out the sense buffer so the higher layers won't realize
 		 * we did an unsolicited auto-sense. */
 		if (result == USB_STOR_TRANSPORT_GOOD &&
-				(srb->sense_buffer[2] & 0xf) == 0x0) {
+			/* Filemark 0, ignore EOM, ILI 0, no sense */
+				(srb->sense_buffer[2] & 0xaf) == 0 &&
+			/* No ASC or ASCQ */
+				srb->sense_buffer[12] == 0 &&
+				srb->sense_buffer[13] == 0) {
 			srb->result = SAM_STAT_GOOD;
 			srb->sense_buffer[0] = 0x0;
 		}
@@ -809,15 +813,19 @@
 	}
 
 	/* If not UFI, we interpret the data as a result code 
-	 * The first byte should always be a 0x0
-	 * The second byte & 0x0F should be 0x0 for good, otherwise error 
+	 * The first byte should always be a 0x0.
+	 *
+	 * Some bogus devices don't follow that rule.  They stuff the ASC
+	 * into the first byte -- so if it's non-zero, call it a failure.
 	 */
 	if (us->iobuf[0]) {
-		US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
+		US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n",
 				us->iobuf[0]);
-		return USB_STOR_TRANSPORT_ERROR;
+		goto Failed;
+
 	}
 
+	/* The second byte & 0x0F should be 0x0 for good, otherwise error */
 	switch (us->iobuf[1] & 0x0F) {
 		case 0x00: 
 			return USB_STOR_TRANSPORT_GOOD;
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	Wed Mar 17 19:29:10 2004
+++ b/drivers/usb/storage/unusual_devs.h	Wed Mar 17 19:29:10 2004
@@ -261,6 +261,14 @@
 		US_SC_SCSI, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
 
+/* This entry is needed because the device reports Sub=ff */
+UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0500, 
+               "Sony",
+               "DSC-T1", 
+               US_SC_8070, US_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
+
+
 /* Reported by wim@geeks.nl */
 UNUSUAL_DEV(  0x054c, 0x0025, 0x0100, 0x0100, 
 		"Sony",
@@ -368,7 +376,7 @@
 UNUSUAL_DEV(  0x05dc, 0x0001, 0x0000, 0x0001,
 		"Lexar",
 		"Jumpshot USB CF Reader",
-		US_SC_SCSI, US_PR_JUMPSHOT, NULL,
+		US_SC_DEVICE, US_PR_JUMPSHOT, NULL,
 		US_FL_MODE_XLATE ),
 #endif
 
@@ -409,6 +417,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Reported by Henning Schild <henning@wh9.tu-dresden.de> */
+UNUSUAL_DEV(  0x05e3, 0x0702, 0x0113, 0x0113,
+		"EagleTec",
+		"External Hard Disk",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY ),
+
 /* Reported by Hanno Boeck <hanno@gmx.de>
  * Taken from the Lycoris Kernel */
 UNUSUAL_DEV(  0x0636, 0x0003, 0x0000, 0x9999,
@@ -440,12 +455,6 @@
 		US_SC_SCSI, US_PR_DEVICE, NULL,
 		0 ),
 
-UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001,
-		"Minolta",
-		"DiMAGE 7i",
-		US_SC_SCSI, US_PR_DEVICE, NULL,
-		0 ),
-
 UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001,
 		"Minolta",
 		"DiMAGE 7Hi",
@@ -619,6 +628,9 @@
  *   are using transport protocol CB.
  * - They don't like the INQUIRY command. So we must handle this command
  *   of the SCSI layer ourselves.
+ * - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have
+ *   bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB).
+ *   So don't remove the US_PR_CB override!
  */
 UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
 		"Casio",
@@ -649,6 +661,17 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_MODE_XLATE ),
 
+/* Entry needed for flags. Moreover, all devices with this ID use
+ * bulk-only transport, but _some_ falsely report Control/Bulk instead.
+ * One example is "Trumpion Digital Research MYMP3".
+ * Submitted by Bjoern Brill <brill(at)fs.math.uni-frankfurt.de>
+ */
+UNUSUAL_DEV(  0x090a, 0x1001, 0x0100, 0x0100,
+		"Trumpion",
+		"t33520 USB Flash Card Controller",
+		US_SC_DEVICE, US_PR_BULK, NULL,
+		US_FL_MODE_XLATE),
+
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
 		"Trumpion",
@@ -688,15 +711,9 @@
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_FIX_INQUIRY ),
 
-/* This entry from <matthias@ma-c.de> in the Debian mailing list */
-UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff,
-		"Pentax",
-		"Optio 330GS",
-		US_SC_8070, US_PR_CB, NULL,
-		US_FL_MODE_XLATE | US_FL_FIX_INQUIRY ),
 
 /* Submitted by Per Winkvist <per.winkvist@uk.com> */
-UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
+UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
                 "Pentax",
                 "Optio S/S4",
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/storage/usb.c	Wed Mar 17 19:29:09 2004
@@ -423,7 +423,7 @@
 	/* Fill in the device-related fields */
 	us->pusb_dev = interface_to_usbdev(intf);
 	us->pusb_intf = intf;
-	us->ifnum = intf->altsetting->desc.bInterfaceNumber;
+	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
 
 	/* Store our private data in the interface and increment the
 	 * device's reference count */
@@ -452,7 +452,7 @@
 {
 	struct usb_device *dev = us->pusb_dev;
 	struct usb_interface_descriptor *idesc =
-		&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting].desc;
+		&us->pusb_intf->cur_altsetting->desc;
 	struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
 	struct usb_device_id *id = &storage_usb_ids[id_index];
 
@@ -686,7 +686,7 @@
 static int get_pipes(struct us_data *us)
 {
 	struct usb_host_interface *altsetting =
-		&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting];
+		us->pusb_intf->cur_altsetting;
 	int i;
 	struct usb_endpoint_descriptor *ep;
 	struct usb_endpoint_descriptor *ep_in = NULL;
@@ -877,8 +877,9 @@
 	int result;
 
 	US_DEBUGP("USB Mass Storage device detected\n");
-	US_DEBUGP("act_altsetting is %d, id_index is %d\n",
-			intf->act_altsetting, id_index);
+	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);
@@ -953,8 +954,6 @@
 
 	scsi_scan_host(us->host);
 
-	printk(KERN_DEBUG 
-	       "WARNING: USB Mass Storage data integrity not assured\n");
 	printk(KERN_DEBUG 
 	       "USB Mass Storage device found at %d\n", us->pusb_dev->devnum);
 	return 0;
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	Wed Mar 17 19:29:09 2004
+++ b/drivers/usb/storage/usb.h	Wed Mar 17 19:29:09 2004
@@ -176,6 +176,5 @@
  * single queue element srb for write access */
 #define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
 #define scsi_lock(host)		spin_lock_irq(host->host_lock)
-#define sg_address(psg)		(page_address((psg).page) + (psg).offset)
 
 #endif
diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
--- a/drivers/video/console/fbcon.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/video/console/fbcon.c	Wed Mar 17 19:29:09 2004
@@ -309,94 +309,6 @@
 }
 
 /*
- * drawing helpers
- */
-static void putcs_unaligned(struct vc_data *vc, struct fb_info *info,
-			    struct fb_image *image, int count,
-			    const unsigned short *s)
-{
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	unsigned int width = (vc->vc_font.width + 7) >> 3;
-	unsigned int cellsize = vc->vc_font.height * width;
-	unsigned int maxcnt = info->pixmap.size/cellsize;
-	unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
-	unsigned int shift_high = 8, size, pitch, cnt, k;
-	unsigned int buf_align = info->pixmap.buf_align - 1;
-	unsigned int scan_align = info->pixmap.scan_align - 1;
-	unsigned int idx = vc->vc_font.width >> 3;
-	u8 *src, *dst, *dst0;
-
-	while (count) {
-		if (count > maxcnt)
-			cnt = k = maxcnt;
-		else
-			cnt = k = count;
-
-		image->width = vc->vc_font.width * cnt;
-		pitch = ((image->width + 7) >> 3) + scan_align;
-		pitch &= ~scan_align;
-		size = pitch * vc->vc_font.height + buf_align;
-		size &= ~buf_align;
-		dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
-		image->data = dst0;
-		while (k--) {
-			src = vc->vc_font.data + (scr_readw(s++) & charmask)*
-			cellsize;
-			dst = dst0;
-			fb_move_buf_unaligned(info, &info->pixmap, dst, pitch, src,
-						idx, image->height, shift_high,
-						shift_low, mod);
-			shift_low += mod;
-			dst0 += (shift_low >= 8) ? width : width - 1;
-			shift_low &= 7;
-			shift_high = 8 - shift_low;
-		}
-		info->fbops->fb_imageblit(info, image);
-		image->dx += cnt * vc->vc_font.width;
-		count -= cnt;
-	}
-}
-
-static void putcs_aligned(struct vc_data *vc, struct fb_info *info,
-			  struct fb_image *image, int count,
-			  const unsigned short *s)
-{
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	unsigned int width = vc->vc_font.width >> 3;
-	unsigned int cellsize = vc->vc_font.height * width;
-	unsigned int maxcnt = info->pixmap.size/cellsize;
-	unsigned int scan_align = info->pixmap.scan_align - 1;
-	unsigned int buf_align = info->pixmap.buf_align - 1;
-	unsigned int pitch, cnt, size, k;
-	u8 *src, *dst, *dst0;
-
-	while (count) {
-		if (count > maxcnt)
-			cnt = k = maxcnt;
-		else
-			cnt = k = count;
-		
-		pitch = width * cnt + scan_align;
-		pitch &= ~scan_align;
-		size = pitch * vc->vc_font.height + buf_align;
-		size &= ~buf_align;
-		image->width = vc->vc_font.width * cnt;
-		dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
-		image->data = dst0;
-		while (k--) {
-			src = vc->vc_font.data + (scr_readw(s++)&charmask)*cellsize;
-			dst = dst0;
-			fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src,
-						width, image->height);
-			dst0 += width;
-		}
-		info->fbops->fb_imageblit(info, image);
-		image->dx += cnt * vc->vc_font.width;
-		count -= cnt;
-	}
-}
-
-/*
  * Accelerated handlers.
  */
 void accel_bmove(struct vc_data *vc, struct fb_info *info, int sy, 
@@ -430,48 +342,23 @@
 	info->fbops->fb_fillrect(info, &region);
 }	
 
-static void accel_putc(struct vc_data *vc, struct fb_info *info,
-                      int c, int ypos, int xpos)
+void accel_putcs(struct vc_data *vc, struct fb_info *info,
+			const unsigned short *s, int count, int yy, int xx)
 {
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	unsigned int width = (vc->vc_font.width + 7) >> 3;
+	unsigned int cellsize = vc->vc_font.height * width;
+	unsigned int maxcnt = info->pixmap.size/cellsize;
 	unsigned int scan_align = info->pixmap.scan_align - 1;
 	unsigned int buf_align = info->pixmap.buf_align - 1;
+	unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
+	unsigned int shift_high = 8, pitch, cnt, size, k;
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
-	unsigned int size, pitch;
-	struct fb_image image;
-	u8 *src, *dst;
-
-	image.dx = xpos * vc->vc_font.width;
-	image.dy = 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;
-
-	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;
-	src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width;
-
-	fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);
-
-	info->fbops->fb_imageblit(info, &image);
-}
-
-void accel_putcs(struct vc_data *vc, struct fb_info *info,
-			const unsigned short *s, int count, int yy, int xx)
-{
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
+	unsigned int idx = vc->vc_font.width >> 3;
 	struct fb_image image;
 	u16 c = scr_readw(s);
+	u8 *src, *dst, *dst0;
 
 	image.fg_color = attr_fgcol(fgshift, c);
 	image.bg_color = attr_bgcol(bgshift, c);
@@ -480,10 +367,41 @@
 	image.height = vc->vc_font.height;
 	image.depth = 1;
 
-	if (!(vc->vc_font.width & 7))
-               putcs_aligned(vc, info, &image, count, s);
-        else
-               putcs_unaligned(vc, info, &image, count, s);
+	while (count) {
+		if (count > maxcnt)
+			cnt = k = maxcnt;
+		else
+			cnt = k = count;
+
+		image.width = vc->vc_font.width * cnt;
+		pitch = ((image.width + 7) >> 3) + scan_align;
+		pitch &= ~scan_align;
+		size = pitch * image.height + buf_align;
+		size &= ~buf_align;
+		dst0 = fb_get_buffer_offset(info, &info->pixmap, size);
+		image.data = dst0;
+		while (k--) {
+			src = vc->vc_font.data + (scr_readw(s++) & charmask)*cellsize;
+			dst = dst0;
+
+			if (mod) {
+				fb_move_buf_unaligned(info, &info->pixmap, dst, pitch,
+						   src, idx, image.height, shift_high,
+						   shift_low, mod);
+				shift_low += mod;
+				dst0 += (shift_low >= 8) ? width : width - 1;
+				shift_low &= 7;
+				shift_high = 8 - shift_low;
+			} else {
+				fb_move_buf_aligned(info, &info->pixmap, dst, pitch,
+						 src, idx, image.height);
+				dst0 += width;
+			}
+		}
+		info->fbops->fb_imageblit(info, &image);
+		image.dx += cnt * vc->vc_font.width;
+		count -= cnt;
+	}
 }
 
 void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
@@ -724,15 +642,13 @@
 static void fbcon_set_display(struct vc_data *vc, int init, int logo)
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	int nr_rows, nr_cols, old_rows, old_cols, i, charcnt = 256;
 	struct display *p = &fb_display[vc->vc_num];
-	int nr_rows, nr_cols;
-	int old_rows, old_cols;
 	unsigned short *save = NULL, *r, *q;
-	int i, charcnt = 256;
 	struct font_desc *font;
 
 	if (vc->vc_num != fg_console || (info->flags & FBINFO_FLAG_MODULE) ||
-	    info->fix.type == FB_TYPE_TEXT)
+	    (info->fix.type == FB_TYPE_TEXT))
 		logo = 0;
 
 	info->var.xoffset = info->var.yoffset = p->yscroll = 0;	/* reset wrap/pan */
@@ -958,11 +874,19 @@
 		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;
@@ -972,7 +896,28 @@
 	if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT)
 		return;
 
-	accel_putc(vc, info, c, real_y(p, ypos), xpos);
+	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;
+
+	fb_move_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,
diff -Nru a/drivers/video/modedb.c b/drivers/video/modedb.c
--- a/drivers/video/modedb.c	Wed Mar 17 19:29:09 2004
+++ b/drivers/video/modedb.c	Wed Mar 17 19:29:09 2004
@@ -554,5 +554,5 @@
     return 0;
 }
 
-EXPORT_SYMBOL(__fb_try_mode);
 EXPORT_SYMBOL(vesa_modes);
+EXPORT_SYMBOL(fb_find_mode);
diff -Nru a/fs/Kconfig b/fs/Kconfig
--- a/fs/Kconfig	Wed Mar 17 19:29:09 2004
+++ b/fs/Kconfig	Wed Mar 17 19:29:09 2004
@@ -1587,7 +1587,7 @@
 #
 config INTERMEZZO_FS
 	tristate "InterMezzo file system support (replicating fs) (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL && BROKEN
+	depends on INET && EXPERIMENTAL 
 	help
 	  InterMezzo is a networked file system with disconnected operation
 	  and kernel level write back caching.  It is most often used for
diff -Nru a/fs/compat_ioctl.c b/fs/compat_ioctl.c
--- a/fs/compat_ioctl.c	Wed Mar 17 19:29:10 2004
+++ b/fs/compat_ioctl.c	Wed Mar 17 19:29:10 2004
@@ -1952,6 +1952,7 @@
 		set_fs (KERNEL_DS);
 		err = sys_ioctl(fd, cmd, (unsigned long)&a);
 		set_fs (old_fs);
+		break;
 	default:
 		return -EINVAL;
 	}                                        
diff -Nru a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
--- a/fs/exportfs/expfs.c	Wed Mar 17 19:29:10 2004
+++ b/fs/exportfs/expfs.c	Wed Mar 17 19:29:10 2004
@@ -135,7 +135,6 @@
 	 * the noprogress counter.  If we go through the loop 10 times (2 is
 	 * probably enough) without getting anywhere, we just give up
 	 */
-	lock_kernel();
 	noprogress= 0;
 	while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
 		struct dentry *pd = target_dir;
@@ -232,7 +231,6 @@
 		/* something went wrong - oh-well */
 		if (!err)
 			err = -ESTALE;
-		unlock_kernel();
 		goto err_target;
 	}
 	/* if we weren't after a directory, have one more step to go */
@@ -254,7 +252,6 @@
 		}
 	}
 	dput(target_dir);
-	unlock_kernel();
 	/* now result is properly connected, it is our best bet */
 	if (acceptable(context, result))
 		return result;
diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
--- a/fs/hugetlbfs/inode.c	Wed Mar 17 19:29:10 2004
+++ b/fs/hugetlbfs/inode.c	Wed Mar 17 19:29:10 2004
@@ -683,11 +683,24 @@
 
 static struct vfsmount *hugetlbfs_vfsmount;
 
-static atomic_t hugetlbfs_counter = ATOMIC_INIT(0);
+/*
+ * Return the next identifier for a shm file
+ */
+static unsigned long hugetlbfs_counter(void)
+{
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+	static unsigned long counter;
+	unsigned long ret;
+
+	spin_lock(&lock);
+	ret = ++counter;
+	spin_unlock(&lock);
+	return ret;
+}
 
 struct file *hugetlb_zero_setup(size_t size)
 {
-	int error, n;
+	int error;
 	struct file *file;
 	struct inode *inode;
 	struct dentry *dentry, *root;
@@ -699,11 +712,9 @@
 
 	if (!is_hugepage_mem_enough(size))
 		return ERR_PTR(-ENOMEM);
-	n = atomic_read(&hugetlbfs_counter);
-	atomic_inc(&hugetlbfs_counter);
 
 	root = hugetlbfs_vfsmount->mnt_root;
-	snprintf(buf, 16, "%d", n);
+	snprintf(buf, 16, "%lu", hugetlbfs_counter());
 	quick_string.name = buf;
 	quick_string.len = strlen(quick_string.name);
 	quick_string.hash = 0;
diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c
--- a/fs/intermezzo/dir.c	Wed Mar 17 19:29:09 2004
+++ b/fs/intermezzo/dir.c	Wed Mar 17 19:29:09 2004
@@ -1300,13 +1300,9 @@
                 return rc;
         }
 
-        case TCGETS:
-                EXIT;
-                return -EINVAL;
-
         default:
                 EXIT;
-                return -EINVAL;
+                return -ENOTTY;
                 
         }
         EXIT;
diff -Nru a/fs/intermezzo/file.c b/fs/intermezzo/file.c
--- a/fs/intermezzo/file.c	Wed Mar 17 19:29:09 2004
+++ b/fs/intermezzo/file.c	Wed Mar 17 19:29:09 2004
@@ -217,9 +217,9 @@
                 fdata->fd_mode = file->f_dentry->d_inode->i_mode;
                 fdata->fd_uid = file->f_dentry->d_inode->i_uid;
                 fdata->fd_gid = file->f_dentry->d_inode->i_gid;
-                fdata->fd_ngroups = current->ngroups;
-                for (i=0 ; i < current->ngroups ; i++)
-                        fdata->fd_groups[i] = current->groups[i];
+                fdata->fd_ngroups = current->group_info->ngroups;
+                for (i=0 ; i < current->group_info->ngroups ; i++)
+                        fdata->fd_groups[i] = GROUP_AT(current->group_info,i);
                 if (!ISLENTO(minor)) 
                         fdata->fd_info.flags = LENTO_FL_KML; 
                 else { 
diff -Nru a/fs/intermezzo/fileset.c b/fs/intermezzo/fileset.c
--- a/fs/intermezzo/fileset.c	Wed Mar 17 19:29:09 2004
+++ b/fs/intermezzo/fileset.c	Wed Mar 17 19:29:09 2004
@@ -418,7 +418,7 @@
         new.fsgid = 0;
         new.fs = get_fs(); 
         /* XXX where can we get the groups from? */
-        new.ngroups = 0;
+        new.group_info = groups_alloc(0);
 
         push_ctxt(save, &new); 
 }
diff -Nru a/fs/intermezzo/intermezzo_fs.h b/fs/intermezzo/intermezzo_fs.h
--- a/fs/intermezzo/intermezzo_fs.h	Wed Mar 17 19:29:09 2004
+++ b/fs/intermezzo/intermezzo_fs.h	Wed Mar 17 19:29:09 2004
@@ -152,14 +152,14 @@
         uid_t            fsuid;
         gid_t            fsgid;
         mm_segment_t     fs;
-	int              ngroups;
-	gid_t	         groups[NGROUPS];
+        struct group_info * group_info;
+/*	int              ngroups;
+	gid_t	         groups[NGROUPS];*/
 
 };
 
 static inline void push_ctxt(struct run_ctxt *save, struct run_ctxt *new)
 {
-        int i;
         save->fs = get_fs();
         save->pwd = dget(current->fs->pwd);
         save->pwdmnt = mntget(current->fs->pwdmnt);
@@ -167,9 +167,10 @@
         save->fsuid = current->fsuid;
         save->root = current->fs->root;
         save->rootmnt = current->fs->rootmnt;
-        save->ngroups = current->ngroups;
+        save->group_info = current->group_info;
+/*      save->ngroups = current->ngroups;
         for (i = 0; i< current->ngroups; i++) 
-                save->groups[i] = current->groups[i];
+                save->groups[i] = current->groups[i];*/
 
         set_fs(new->fs);
         lock_kernel();
@@ -179,18 +180,17 @@
         unlock_kernel();
         current->fsuid = new->fsuid;
         current->fsgid = new->fsgid;
-        if (new->ngroups > 0) {
+        /*if (new->ngroups > 0) {
                 current->ngroups = new->ngroups;
                 for (i = 0; i< new->ngroups; i++) 
                         current->groups[i] = new->groups[i];
-        }
+        }*/
+        current->group_info = new->group_info;
         
 }
 
 static inline void pop_ctxt(struct run_ctxt *saved)
 {
-        int i;
-
         set_fs(saved->fs);
         lock_kernel();
         set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
@@ -199,10 +199,12 @@
         unlock_kernel();
         current->fsuid = saved->fsuid;
         current->fsgid = saved->fsgid;
+        current->group_info = saved->group_info;
+/*
         current->ngroups = saved->ngroups;
         for (i = 0; i< saved->ngroups; i++) 
                 current->groups[i] = saved->groups[i];
-
+*/
         mntput(saved->pwdmnt);
         dput(saved->pwd);
 }
@@ -392,7 +394,7 @@
         uid_t fd_fsuid;
         gid_t fd_fsgid;
         int fd_ngroups;
-        gid_t fd_groups[NGROUPS_MAX];
+        gid_t fd_groups[NGROUPS_SMALL];
         /* information how to complete the close operation */
         struct lento_vfs_context fd_info;
         struct presto_version fd_version;
diff -Nru a/fs/intermezzo/intermezzo_kml.h b/fs/intermezzo/intermezzo_kml.h
--- a/fs/intermezzo/intermezzo_kml.h	Wed Mar 17 19:29:10 2004
+++ b/fs/intermezzo/intermezzo_kml.h	Wed Mar 17 19:29:10 2004
@@ -41,7 +41,7 @@
         u32 fsgid;
         u32 opcode;
         u32 ngroups;
-        u32 groups[NGROUPS_MAX];
+        u32 groups[NGROUPS_SMALL];
 };
 
 enum kml_opcode {
diff -Nru a/fs/intermezzo/journal.c b/fs/intermezzo/journal.c
--- a/fs/intermezzo/journal.c	Wed Mar 17 19:29:09 2004
+++ b/fs/intermezzo/journal.c	Wed Mar 17 19:29:09 2004
@@ -309,7 +309,7 @@
                                        __u32 fsuid, __u32 fsgid)
 {
         struct kml_prefix_hdr p;
-        u32 loggroups[NGROUPS_MAX];
+        u32 loggroups[NGROUPS_SMALL];
 
         int i; 
 
@@ -332,15 +332,15 @@
 static inline char *
 journal_log_prefix(char *buf, int opcode, struct rec_info *rec)
 {
-        __u32 groups[NGROUPS_MAX]; 
+        __u32 groups[NGROUPS_SMALL]; 
         int i; 
 
         /* convert 16 bit gid's to 32 bit gid's */
-        for (i=0; i<current->ngroups; i++) 
-                groups[i] = (__u32) current->groups[i];
+        for (i=0; i<current->group_info->ngroups; i++) 
+                groups[i] = GROUP_AT(current->group_info,i);
         
         return journal_log_prefix_with_groups_and_ids(buf, opcode, rec,
-                                                      (__u32)current->ngroups,
+                                                      (__u32)current->group_info->ngroups,
                                                       groups,
                                                       (__u32)current->fsuid,
                                                       (__u32)current->fsgid);
@@ -1319,7 +1319,7 @@
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
         ino = cpu_to_le64(dentry->d_inode->i_ino);
         generation = cpu_to_le32(dentry->d_inode->i_generation);
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + sizeof(*new_file_ver) +
                 sizeof(ino) + sizeof(generation) + sizeof(pathlen) +
                 sizeof(remote_ino) + sizeof(remote_generation) + 
@@ -1529,7 +1529,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dentry, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + sizeof(*old_ver) +
                 sizeof(valid) + sizeof(mode) + sizeof(uid) + sizeof(gid) +
                 sizeof(fsize) + sizeof(mtime) + sizeof(ctime) + sizeof(flags) +
@@ -1600,7 +1600,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dentry, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + sizeof(pathlen) +
                 size_round(le32_to_cpu(pathlen)) +
                 sizeof(struct kml_suffix);
@@ -1659,7 +1659,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dentry, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
                 sizeof(struct kml_suffix);
@@ -1715,7 +1715,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dentry, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
                 sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
                 sizeof(targetlen) + sizeof(struct kml_suffix);
@@ -1773,7 +1773,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dentry, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size = sizeof(__u32) * current->ngroups + 
+        size = sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(pathlen) +
                 sizeof(struct kml_suffix);
@@ -1828,7 +1828,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dir, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
                 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
                 sizeof(struct kml_suffix);
@@ -1891,7 +1891,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dentry, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size = sizeof(__u32) * current->ngroups + 
+        size = sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
                 sizeof(lmode) + sizeof(uid) + sizeof(gid) + sizeof(lmajor) +
                 sizeof(lminor) + sizeof(pathlen) +
@@ -1951,7 +1951,7 @@
         BUFF_ALLOC(buffer, srcbuffer);
         path = presto_path(tgt, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
                 sizeof(srcpathlen) + sizeof(pathlen) +
                 sizeof(struct kml_suffix);
@@ -2009,7 +2009,7 @@
         BUFF_ALLOC(buffer, srcbuffer);
         path = presto_path(tgt, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 4 * sizeof(*src_dir_ver) +
                 sizeof(srcpathlen) + sizeof(pathlen) +
                 sizeof(struct kml_suffix);
@@ -2069,7 +2069,7 @@
         BUFF_ALLOC(buffer, NULL);
         path = presto_path(dir, root, buffer, PAGE_SIZE);
         pathlen = cpu_to_le32(MYPATHLEN(buffer, path));
-        size = sizeof(__u32) * current->ngroups + 
+        size = sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 3 * sizeof(*tgt_dir_ver) +
                 sizeof(pathlen) + sizeof(llen) + sizeof(*rb) +
                 sizeof(old_targetlen) + sizeof(struct kml_suffix);
@@ -2116,7 +2116,7 @@
         __u32 open_fsuid;
         __u32 open_fsgid;
         __u32 open_ngroups;
-        __u32 open_groups[NGROUPS_MAX];
+        __u32 open_groups[NGROUPS_SMALL];
         __u32 open_mode;
         __u32 open_uid;
         __u32 open_gid;
@@ -2146,9 +2146,9 @@
                 open_fsuid = fd->fd_fsuid;
                 open_fsgid = fd->fd_fsgid;
         } else {
-                open_ngroups = current->ngroups;
-                for (i=0; i<current->ngroups; i++)
-                        open_groups[i] =  (__u32) current->groups[i]; 
+                open_ngroups = current->group_info->ngroups;
+                for (i=0; i<current->group_info->ngroups; i++)
+                        open_groups[i] =  (__u32) GROUP_AT(current->group_info,i); 
                 open_mode = dentry->d_inode->i_mode;
                 open_uid = dentry->d_inode->i_uid;
                 open_gid = dentry->d_inode->i_gid;
@@ -2246,7 +2246,7 @@
 /* write closes for the local close records in the LML */ 
 int presto_complete_lml(struct presto_file_set *fset)
 {
-        __u32 groups[NGROUPS_MAX];
+        __u32 groups[NGROUPS_SMALL];
         loff_t lml_offset;
         loff_t read_offset; 
         char *buffer;
@@ -2408,7 +2408,7 @@
          */
         mode=cpu_to_le32(dentry->d_inode->i_mode);
 
-        size =  sizeof(__u32) * current->ngroups + 
+        size =  sizeof(__u32) * current->group_info->ngroups + 
                 sizeof(struct kml_prefix_hdr) + 
                 2 * sizeof(struct presto_version) +
                 sizeof(flags) + sizeof(mode) + sizeof(namelen) + 
diff -Nru a/fs/intermezzo/kml_reint.c b/fs/intermezzo/kml_reint.c
--- a/fs/intermezzo/kml_reint.c	Wed Mar 17 19:29:10 2004
+++ b/fs/intermezzo/kml_reint.c	Wed Mar 17 19:29:10 2004
@@ -53,11 +53,11 @@
         ctxt.root = ctxt.pwd;
         ctxt.rootmnt = ctxt.pwdmnt;
         if (rec->prefix.hdr->ngroups > 0) {
-                ctxt.ngroups = rec->prefix.hdr->ngroups;
-                for (i = 0; i< ctxt.ngroups; i++) 
-                        ctxt.groups[i] = rec->prefix.groups[i];
+                ctxt.group_info = groups_alloc(rec->prefix.hdr->ngroups);
+                for (i = 0; i< ctxt.group_info->ngroups; i++) 
+                        GROUP_AT(ctxt.group_info,i)= rec->prefix.groups[i];
         } else
-                ctxt.ngroups = 0;
+                ctxt.group_info = groups_alloc(0);
 
         push_ctxt(saved, &ctxt);
 }
diff -Nru a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
--- a/fs/intermezzo/vfs.c	Wed Mar 17 19:29:09 2004
+++ b/fs/intermezzo/vfs.c	Wed Mar 17 19:29:09 2004
@@ -965,8 +965,6 @@
                 do_rcvd = presto_do_rcvd(info, dir);
                 error = iops->unlink(dir->d_inode, dentry);
                 unlock_kernel();
-                if (!error)
-                        d_delete(dentry);
         }
 
         if (linkno > 1) { 
@@ -988,10 +986,6 @@
         }
 
         //        up(&dir->d_inode->i_zombie);
-        if (error) {
-                EXIT;
-                goto exit;
-        }
 
         presto_debug_fail_blkdev(fset, KML_OPCODE_UNLINK | 0x10);
         if ( do_kml )
@@ -1048,6 +1042,8 @@
                 if (nd.last.name[nd.last.len])
                         goto slashes;
                 error = presto_do_unlink(fset, nd.dentry, dentry, info);
+                if (!error)
+                        d_delete(dentry);
         exit2:
                 EXIT;
                 dput(dentry);
diff -Nru a/fs/jbd/recovery.c b/fs/jbd/recovery.c
--- a/fs/jbd/recovery.c	Wed Mar 17 19:29:10 2004
+++ b/fs/jbd/recovery.c	Wed Mar 17 19:29:10 2004
@@ -137,7 +137,10 @@
 
 	*bhp = NULL;
 
-	J_ASSERT (offset < journal->j_maxlen);
+	if (offset >= journal->j_maxlen) {
+		printk(KERN_ERR "JBD: corrupted journal superblock\n");
+		return -EIO;
+	}
 
 	err = journal_bmap(journal, offset, &blocknr);
 
diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c	Wed Mar 17 19:29:09 2004
+++ b/fs/jfs/jfs_logmgr.c	Wed Mar 17 19:29:09 2004
@@ -1811,7 +1811,7 @@
 		lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL);
 		if (lbuf == 0)
 			goto error;
-		lbuf->l_ldata = (char *) __get_free_page(GFP_KERNEL);
+		lbuf->l_ldata = (char *) get_zeroed_page(GFP_KERNEL);
 		if (lbuf->l_ldata == 0) {
 			kfree(lbuf);
 			goto error;
diff -Nru a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
--- a/fs/jfs/jfs_metapage.c	Wed Mar 17 19:29:09 2004
+++ b/fs/jfs/jfs_metapage.c	Wed Mar 17 19:29:09 2004
@@ -341,6 +341,10 @@
 		}
 		mp->data = kmap(mp->page) + page_offset;
 	}
+
+	if (new)
+		memset(mp->data, 0, PSIZE);
+
 	jfs_info("__get_metapage: returning = 0x%p", mp);
 	return mp;
 
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	Wed Mar 17 19:29:09 2004
+++ b/fs/jfs/super.c	Wed Mar 17 19:29:09 2004
@@ -548,11 +548,11 @@
 
 	if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
+		memset(jfs_ip, 0, sizeof(struct jfs_inode_info));
 		INIT_LIST_HEAD(&jfs_ip->anon_inode_list);
 		init_rwsem(&jfs_ip->rdwrlock);
 		init_MUTEX(&jfs_ip->commit_sem);
 		init_rwsem(&jfs_ip->xattr_sem);
-		jfs_ip->atlhead = 0;
 		jfs_ip->active_ag = -1;
 #ifdef CONFIG_JFS_POSIX_ACL
 		jfs_ip->i_acl = JFS_ACL_NOT_CACHED;
diff -Nru a/fs/proc/root.c b/fs/proc/root.c
--- a/fs/proc/root.c	Wed Mar 17 19:29:10 2004
+++ b/fs/proc/root.c	Wed Mar 17 19:29:10 2004
@@ -74,9 +74,6 @@
 #ifdef CONFIG_PROC_DEVICETREE
 	proc_device_tree_init();
 #endif
-#ifdef CONFIG_PPC_RTAS
-	proc_rtas_init();
-#endif
 	proc_bus = proc_mkdir("bus", 0);
 }
 
diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c
--- a/fs/reiserfs/file.c	Wed Mar 17 19:29:09 2004
+++ b/fs/reiserfs/file.c	Wed Mar 17 19:29:09 2004
@@ -365,7 +365,7 @@
     // it means there are no existing in-tree representation for file area
     // we are going to overwrite, so there is nothing to scan through for holes.
     for ( curr_block = 0, itempos = path.pos_in_item ; curr_block < blocks_to_allocate && res == POSITION_FOUND ; ) {
-
+retry:
 	if ( itempos >= ih_item_len(ih)/UNFM_P_SIZE ) {
 	    /* We run out of data in this indirect item, let's look for another
 	       one. */
@@ -422,8 +422,8 @@
 		    bh=get_last_bh(&path);
 		    ih=get_ih(&path);
 		    item = get_item(&path);
-		    // Itempos is still the same
-		    continue;
+		    itempos = path.pos_in_item;
+		    goto retry;
 		}
 		modifying_this_item = 1;
 	    }
@@ -856,8 +856,12 @@
 			/* Try to find next item */
 			res = search_for_position_by_key(inode->i_sb, &key, &path);
 			/* Abort if no more items */
-			if ( res != POSITION_FOUND )
+			if ( res != POSITION_FOUND ) {
+			    /* make sure later loops don't use this item */
+			    itembuf = NULL;
+			    item = NULL;
 			    break;
+			}
 
 			/* Update information about current indirect item */
 			itembuf = get_last_bh( &path );
@@ -1191,6 +1195,14 @@
     return res;
 }
 
+static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user *buf,
+			       size_t count, loff_t pos)
+{
+    return generic_file_aio_write(iocb, buf, count, pos);
+}
+
+
+
 struct file_operations reiserfs_file_operations = {
     .read	= generic_file_read,
     .write	= reiserfs_file_write,
@@ -1199,6 +1211,8 @@
     .release	= reiserfs_file_release,
     .fsync	= reiserfs_sync_file,
     .sendfile	= generic_file_sendfile,
+    .aio_read   = generic_file_aio_read,
+    .aio_write  = reiserfs_aio_write,
 };
 
 
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	Wed Mar 17 19:29:09 2004
+++ b/fs/reiserfs/inode.c	Wed Mar 17 19:29:09 2004
@@ -209,7 +209,7 @@
   pathrelse(path) ;
   reiserfs_update_sd(th, inode) ;
   journal_end(th, s, len) ;
-  journal_begin(th, s, len) ;
+  journal_begin(th, s, JOURNAL_PER_BALANCE_CNT * 6) ;
   reiserfs_update_inode_transaction(inode) ;
 }
 
@@ -444,7 +444,7 @@
         /* make sure future calls to the direct io funcs for this offset
         ** in the file fail by unmapping the buffer
         */
-        reiserfs_unmap_buffer(bh_result);
+        clear_buffer_mapped(bh_result);
         ret = -EINVAL ;
     }
     /* Possible unpacked tail. Flush the data before pages have
diff -Nru a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
--- a/fs/reiserfs/stree.c	Wed Mar 17 19:29:09 2004
+++ b/fs/reiserfs/stree.c	Wed Mar 17 19:29:09 2004
@@ -652,8 +652,8 @@
                                        stop at leaf level - set to
                                        DISK_LEAF_NODE_LEVEL */
     ) {
-    int  n_block_number = SB_ROOT_BLOCK (p_s_sb),
-      expected_level = SB_TREE_HEIGHT (p_s_sb);
+    int  n_block_number;
+    int  expected_level;
     struct buffer_head  *       p_s_bh;
     struct path_element *       p_s_last_element;
     int				n_node_level, n_retval;
@@ -677,6 +677,8 @@
     /* With each iteration of this loop we search through the items in the
        current node, and calculate the next current node(next path element)
        for the next iteration of this loop.. */
+    n_block_number = SB_ROOT_BLOCK (p_s_sb);
+    expected_level = -1;
     while ( 1 ) {
 
 #ifdef CONFIG_REISERFS_CHECK
@@ -690,7 +692,6 @@
 	/* prep path to have another element added to it. */
 	p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length);
 	fs_gen = get_generation (p_s_sb);
-	expected_level --;
 
 #ifdef SEARCH_BY_KEY_READA
 	/* schedule read of right neighbor */
@@ -705,25 +706,26 @@
 	    pathrelse(p_s_search_path);
 	    return IO_ERROR;
 	}
-
- 	if( fs_changed (fs_gen, p_s_sb) ) {
- 		PROC_INFO_INC( p_s_sb, search_by_key_fs_changed );
- 		PROC_INFO_INC( p_s_sb, sbk_fs_changed[ expected_level - 1 ] );
- 	}
+	if (expected_level == -1)
+		expected_level = SB_TREE_HEIGHT (p_s_sb);
+	expected_level --;
 
 	/* It is possible that schedule occurred. We must check whether the key
 	   to search is still in the tree rooted from the current buffer. If
 	   not then repeat search from the root. */
 	if ( fs_changed (fs_gen, p_s_sb) && 
-	     (!B_IS_IN_TREE (p_s_bh) || !key_in_buffer(p_s_search_path, p_s_key, p_s_sb)) ) {
- 	    PROC_INFO_INC( p_s_sb, search_by_key_restarted );
+	    (!B_IS_IN_TREE (p_s_bh) ||
+	     B_LEVEL(p_s_bh) != expected_level ||
+	     !key_in_buffer(p_s_search_path, p_s_key, p_s_sb))) {
+	    PROC_INFO_INC( p_s_sb, search_by_key_fs_changed );
+	    PROC_INFO_INC( p_s_sb, search_by_key_restarted );
 	    PROC_INFO_INC( p_s_sb, sbk_restarted[ expected_level - 1 ] );
 	    decrement_counters_in_path(p_s_search_path);
 	    
 	    /* Get the root block number so that we can repeat the search
-               starting from the root. */
+	       starting from the root. */
 	    n_block_number = SB_ROOT_BLOCK (p_s_sb);
-	    expected_level = SB_TREE_HEIGHT (p_s_sb);
+	    expected_level = -1;
 	    right_neighbor_of_leaf_node = 0;
 	    
 	    /* repeat search from the root */
@@ -1103,6 +1105,7 @@
 	    for (n_counter = *p_n_removed;
 		 n_counter < n_unfm_number; n_counter++, p_n_unfm_pointer-- ) {
 
+		cond_resched();
 		if (item_moved (&s_ih, p_s_path)) {
 		    need_research = 1 ;
 		    break;
@@ -1754,7 +1757,7 @@
 	  reiserfs_update_sd(th, p_s_inode) ;
 
 	  journal_end(th, p_s_inode->i_sb, orig_len_alloc) ;
-	  journal_begin(th, p_s_inode->i_sb, orig_len_alloc) ;
+	  journal_begin(th, p_s_inode->i_sb, JOURNAL_PER_BALANCE_CNT * 6) ;
 	  reiserfs_update_inode_transaction(p_s_inode) ;
 	}
     } while ( n_file_size > ROUND_UP (n_new_file_size) &&
diff -Nru a/include/asm-arm/arch-ebsa285/irqs.h b/include/asm-arm/arch-ebsa285/irqs.h
--- a/include/asm-arm/arch-ebsa285/irqs.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-arm/arch-ebsa285/irqs.h	Wed Mar 17 19:29:09 2004
@@ -91,8 +91,8 @@
 
 #undef RTC_IRQ
 #define RTC_IRQ		IRQ_ISA_RTC_ALARM
-#undef AUX_IRQ
-#define AUX_IRQ		(machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
+#define I8042_KBD_IRQ	IRQ_ISA_KEYBOARD
+#define I8042_AUX_IRQ	(machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
 #define IRQ_FLOPPYDISK	IRQ_ISA_FLOPPY
 
 #define irq_canonicalize(_i)	(((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA_2 : _i)
diff -Nru a/include/asm-arm/arch-shark/irqs.h b/include/asm-arm/arch-shark/irqs.h
--- a/include/asm-arm/arch-shark/irqs.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-arm/arch-shark/irqs.h	Wed Mar 17 19:29:10 2004
@@ -8,5 +8,6 @@
 
 #define IRQ_ISA_KEYBOARD	 1
 #define RTC_IRQ			 8
-#define AUX_IRQ			12
+#define I8042_KBD_IRQ		 1
+#define I8042_AUX_IRQ		12
 #define IRQ_HARDDISK            14
diff -Nru a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h
--- a/include/asm-arm26/thread_info.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-arm26/thread_info.h	Wed Mar 17 19:29:09 2004
@@ -81,8 +81,6 @@
 
 /* FIXME - PAGE_SIZE < 32K */
 #define THREAD_SIZE		(8192)
-/*FIXME INIT_THREAD_SIZE - how big? */
-//#define INIT_THREAD_SIZE        (65536)
 #define __get_user_regs(x) (((struct pt_regs *)((unsigned long)(x) + THREAD_SIZE - 8)) - 1)
 
 extern struct thread_info *alloc_thread_info(struct task_struct *task);
diff -Nru a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
--- a/include/asm-ia64/acpi.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-ia64/acpi.h	Wed Mar 17 19:29:10 2004
@@ -93,7 +93,8 @@
 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_irq_to_vector (u32 irq);
+int acpi_irq_to_vector (u32 irq); /* deprecated in favor of acpi_gsi_to_irq */
+int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
 #ifdef CONFIG_ACPI_NUMA
 /* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
diff -Nru a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
--- a/include/asm-ia64/gcc_intrin.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ia64/gcc_intrin.h	Wed Mar 17 19:29:09 2004
@@ -23,6 +23,8 @@
 extern void ia64_bad_param_for_setreg (void);
 extern void ia64_bad_param_for_getreg (void);
 
+register unsigned long ia64_r13 asm ("r13");
+
 #define ia64_setreg(regnum, val)						\
 ({										\
 	switch (regnum) {							\
@@ -67,10 +69,7 @@
 		asm volatile ("mov %0=psr" : "=r"(ia64_intri_res));		\
 		break;								\
 	case _IA64_REG_TP:	/* for current() */				\
-		{								\
-			register __u64 ia64_r13 asm ("r13");			\
-			ia64_intri_res = ia64_r13;				\
-		}								\
+		ia64_intri_res = ia64_r13;					\
 		break;								\
 	case _IA64_REG_AR_KR0 ... _IA64_REG_AR_EC:				\
 		asm volatile ("mov %0=ar%1" : "=r" (ia64_intri_res)		\
diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
--- a/include/asm-ia64/machvec.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ia64/machvec.h	Wed Mar 17 19:29:09 2004
@@ -154,10 +154,10 @@
 	ia64_mv_dma_unmap_single *dma_unmap_single;
 	ia64_mv_dma_map_sg *dma_map_sg;
 	ia64_mv_dma_unmap_sg *dma_unmap_sg;
-	ia64_mv_dma_sync_single *dma_sync_single_for_cpu;
-	ia64_mv_dma_sync_sg *dma_sync_sg_for_cpu;
-	ia64_mv_dma_sync_single *dma_sync_single_for_device;
-	ia64_mv_dma_sync_sg *dma_sync_sg_for_device;
+	ia64_mv_dma_sync_single_for_cpu *dma_sync_single_for_cpu;
+	ia64_mv_dma_sync_sg_for_cpu *dma_sync_sg_for_cpu;
+	ia64_mv_dma_sync_single_for_device *dma_sync_single_for_device;
+	ia64_mv_dma_sync_sg_for_device *dma_sync_sg_for_device;
 	ia64_mv_dma_supported *dma_supported;
 	ia64_mv_irq_desc *irq_desc;
 	ia64_mv_irq_to_vector *irq_to_vector;
diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
--- a/include/asm-ia64/spinlock.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ia64/spinlock.h	Wed Mar 17 19:29:09 2004
@@ -61,7 +61,7 @@
 		      "}\n\t"
 		      "cmpxchg4.acq r30 = [%1], r30, ar.ccv;;\n\t"
 		      "cmp4.ne p14, p0 = r30, r0\n"
-		      "(p14) brl.cond.spnt.many ia64_spinlock_contention_pre3_4"
+		      "(p14) brl.cond.spnt.many ia64_spinlock_contention_pre3_4;;"
 		      : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
 # endif /* CONFIG_MCKINLEY */
 #else
@@ -81,7 +81,7 @@
 		      "mov ar.ccv = r0;;\n\t"
 		      "cmpxchg4.acq r30 = [%0], r30, ar.ccv;;\n\t"
 		      "cmp4.ne p14, p0 = r30, r0\n\t"
-		      "(p14) brl.call.spnt.many b6=ia64_spinlock_contention"
+		      "(p14) brl.call.spnt.many b6=ia64_spinlock_contention;;"
 		      : "=r"(ptr) : "r"(ptr) : IA64_SPINLOCK_CLOBBERS);
 # endif /* CONFIG_MCKINLEY */
 #endif
diff -Nru a/include/asm-mips/shmparam.h b/include/asm-mips/shmparam.h
--- a/include/asm-mips/shmparam.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-mips/shmparam.h	Wed Mar 17 19:29:10 2004
@@ -6,6 +6,8 @@
 #ifndef _ASM_SHMPARAM_H
 #define _ASM_SHMPARAM_H
 
+#define __ARCH_FORCE_SHMLBA	1
+
 #define	SHMLBA 0x40000			/* attach addr a multiple of this */
 
 #endif /* _ASM_SHMPARAM_H */
diff -Nru a/include/asm-parisc/shmparam.h b/include/asm-parisc/shmparam.h
--- a/include/asm-parisc/shmparam.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-parisc/shmparam.h	Wed Mar 17 19:29:09 2004
@@ -1,6 +1,8 @@
 #ifndef _ASMPARISC_SHMPARAM_H
 #define _ASMPARISC_SHMPARAM_H
 
+#define __ARCH_FORCE_SHMLBA 	1
+
 #define SHMLBA 0x00400000   /* attach addr needs to be 4 Mb aligned */
 
 #endif /* _ASMPARISC_SHMPARAM_H */
diff -Nru a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h
--- a/include/asm-ppc/dma-mapping.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-ppc/dma-mapping.h	Wed Mar 17 19:29:10 2004
@@ -100,17 +100,42 @@
 /* We don't do anything here. */
 #define dma_unmap_sg(dev, sg, nents, dir)	do { } while (0)
 
-static inline void dma_sync_single(struct device *dev, dma_addr_t dma_handle,
-				   size_t size,
-				   enum dma_data_direction direction)
+static inline void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			size_t size,
+			enum dma_data_direction direction)
 {
 	BUG_ON(direction == DMA_NONE);
 
 	consistent_sync(bus_to_virt(dma_handle), size, direction);
 }
 
-static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
-			       int nelems, enum dma_data_direction direction)
+static inline void
+dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+			   size_t size,
+			   enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+
+	consistent_sync(bus_to_virt(dma_handle), size, direction);
+}
+
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+		    int nelems, enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	for (i = 0; i < nelems; i++, sg++)
+		consistent_sync_page(sg->page, sg->offset,
+				     sg->length, direction);
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+		       int nelems, enum dma_data_direction direction)
 {
 	int i;
 
@@ -137,12 +162,21 @@
 }
 
 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)
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			      unsigned long offset, size_t size,
+			      enum dma_data_direction direction)
+{
+	/* just sync everything, that's all the pci API can do */
+	dma_sync_single_for_cpu(dev, dma_handle, offset + size, direction);
+}
+
+static inline void
+dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction direction)
 {
 	/* just sync everything, that's all the pci API can do */
-	dma_sync_single(dev, dma_handle, offset + size, direction);
+	dma_sync_single_for_device(dev, dma_handle, offset + size, direction);
 }
 
 static inline void dma_cache_sync(void *vaddr, size_t size,
diff -Nru a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
--- a/include/asm-ppc/pci.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-ppc/pci.h	Wed Mar 17 19:29:10 2004
@@ -200,7 +200,7 @@
 {
 	BUG_ON(direction == PCI_DMA_NONE);
 
-	consistent_sync_for_cpu(bus_to_virt(dma_handle), size, direction);
+	consistent_sync(bus_to_virt(dma_handle), size, direction);
 }
 
 static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
@@ -209,7 +209,7 @@
 {
 	BUG_ON(direction == PCI_DMA_NONE);
 
-	consistent_sync_for_device(bus_to_virt(dma_handle), size, direction);
+	consistent_sync(bus_to_virt(dma_handle), size, direction);
 }
 
 /* Make physical memory consistent for a set of streaming
@@ -227,8 +227,8 @@
 	BUG_ON(direction == PCI_DMA_NONE);
 
 	for (i = 0; i < nelems; i++, sg++)
-		consistent_sync_page_for_cpu(sg->page, sg->offset,
-					     sg->length, direction);
+		consistent_sync_page(sg->page, sg->offset,
+				     sg->length, direction);
 }
 
 static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
@@ -240,8 +240,8 @@
 	BUG_ON(direction == PCI_DMA_NONE);
 
 	for (i = 0; i < nelems; i++, sg++)
-		consistent_sync_page_for_device(sg->page, sg->offset,
-						sg->length, direction);
+		consistent_sync_page(sg->page, sg->offset,
+				     sg->length, direction);
 }
 
 /* Return whether the given PCI device DMA address mask can
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ppc/unistd.h	Wed Mar 17 19:29:09 2004
@@ -415,10 +415,10 @@
 int sys_pipe(int __user *fildes);
 int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
-asmlinkage long sys_rt_sigaction(int sig,
-				const struct sigaction __user *act,
-				struct sigaction __user *oact,
-				size_t sigsetsize);
+long sys_rt_sigaction(int sig,
+		      const struct sigaction __user *act,
+		      struct sigaction __user *oact,
+		      size_t sigsetsize);
 
 #endif /* __KERNEL_SYSCALLS__ */
 
diff -Nru a/include/asm-ppc64/dma-mapping.h b/include/asm-ppc64/dma-mapping.h
--- a/include/asm-ppc64/dma-mapping.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-ppc64/dma-mapping.h	Wed Mar 17 19:29:10 2004
@@ -1 +1,75 @@
-#include <asm-generic/dma-mapping.h>
+/* Copyright (C) 2004 IBM
+ *
+ * Implements the generic device dma API for ppc64. Handles
+ * the pci and vio busses
+ */
+
+#ifndef _ASM_DMA_MAPPING_H
+#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>
+#include <asm/scatterlist.h>
+#include <asm/bug.h>
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
+extern void *dma_alloc_coherent(struct device *dev, size_t size,
+		dma_addr_t *dma_handle, int flag);
+extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+		dma_addr_t dma_handle);
+extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
+		size_t size, enum dma_data_direction direction);
+extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+		size_t size, enum dma_data_direction direction);
+extern dma_addr_t dma_map_page(struct device *dev, struct page *page,
+		unsigned long offset, size_t size,
+		enum dma_data_direction direction);
+extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+		size_t size, enum dma_data_direction direction);
+extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+		enum dma_data_direction direction);
+extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+		int nhwentries, enum dma_data_direction direction);
+extern void dma_sync_single(struct device *dev, dma_addr_t dma_handle,
+		size_t size, enum dma_data_direction direction);
+extern void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+		enum dma_data_direction direction);
+
+/* Now for the API extensions over the pci_ one */
+
+#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)
+{
+	/* no easy way to get cache size on all processors, so return
+	 * the maximum possible, to be safe */
+	return (1 << L1_CACHE_SHIFT_MAX);
+}
+
+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)
+{
+	/* just sync everything, that's all the pci API can do */
+	dma_sync_single(dev, dma_handle, offset+size, direction);
+}
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	/* could define this in terms of the dma_cache ... operations,
+	 * but if you get this on a platform, you should convert the platform
+	 * to using the generic device DMA API */
+	BUG();
+}
+
+#endif	/* _ASM_DMA_MAPPING_H */
diff -Nru a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
--- a/include/asm-ppc64/eeh.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-ppc64/eeh.h	Wed Mar 17 19:29:10 2004
@@ -17,15 +17,11 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-/* Start Change Log
- * 2001/10/27 : engebret : Created.
- * End Change Log 
- */
-
-#ifndef _EEH_H
-#define _EEH_H
+#ifndef _PPC64_EEH_H
+#define _PPC64_EEH_H
 
 #include <linux/string.h>
+#include <linux/init.h>
 
 struct pci_dev;
 
@@ -33,22 +29,43 @@
  * 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))
+#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)
 
-/* This is for profiling only */
-extern unsigned long eeh_total_mmio_ffs;
-
-void eeh_init(void);
-int eeh_get_state(unsigned long ea);
+extern void __init eeh_init(void);
 unsigned long eeh_check_failure(void *token, unsigned long val);
 void *eeh_ioremap(unsigned long addr, void *vaddr);
+void __init pci_addr_cache_build(void);
+
+/**
+ * eeh_add_device - perform EEH initialization for the indicated pci device
+ * @dev: pci device for which to set up EEH
+ *
+ * This routine can be used to perform EEH initialization for PCI
+ * devices that were added after system boot (e.g. hotplug, dlpar).
+ * Whether this actually enables EEH or not for this device depends
+ * on the type of the device, on earlier boot command-line
+ * arguments & etc.
+ */
+void eeh_add_device(struct pci_dev *);
+
+/**
+ * eeh_remove_device - undo EEH setup for the indicated pci device
+ * @dev: pci device to be removed
+ *
+ * This routine should be when a device is removed from a running
+ * system (e.g. by hotplug or dlpar).
+ */
+void eeh_remove_device(struct pci_dev *);
 
 #define EEH_DISABLE		0
 #define EEH_ENABLE		1
@@ -56,18 +73,8 @@
 #define EEH_RELEASE_DMA		3
 int eeh_set_option(struct pci_dev *dev, int options);
 
-/* Given a PCI device check if eeh should be configured or not.
- * This may look at firmware properties and/or kernel cmdline options.
- */
-int is_eeh_configured(struct pci_dev *dev);
-
-/* Translate a (possible) eeh token to a physical addr.
- * If "token" is not an eeh token it is simply returned under
- * the assumption that it is already a physical addr.
- */
-unsigned long eeh_token_to_phys(unsigned long token);
-
-/* EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
+/*
+ * 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
@@ -78,30 +85,22 @@
  * 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) (~(val) == 0) */
-/* #define EEH_POSSIBLE_ERROR(addr, vaddr, val) ((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val) */
-/* This version is rearranged to collect some profiling data */
-#define EEH_POSSIBLE_IO_ERROR(val) (~(val) == 0 && ++eeh_total_mmio_ffs)
-#define EEH_POSSIBLE_ERROR(addr, vaddr, val) (EEH_POSSIBLE_IO_ERROR(val) && (vaddr) != (addr))
+#define EEH_POSSIBLE_IO_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...
+ */
+#define EEH_POSSIBLE_ERROR(addr, vaddr, val, type) \
+		((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val, type))
 
 /* 
  * MMIO read/write operations with EEH support.
- *
- * addr: 64b token of the form 0xA0PPBBDDyyyyyyyy
- *       0xA0     : Unmapped MMIO region
- *       PP       : PHB index (starting at zero)
- *	 BB	  : PCI Bus number under given PHB
- *	 DD	  : PCI devfn under given bus
- *       yyyyyyyy : Virtual address offset
- * 
- * An actual virtual address is produced from this token
- * by masking into the form:
- *   0xE0000000yyyyyyyy
  */
 static inline u8 eeh_readb(void *addr) {
 	volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
 	u8 val = in_8(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u8))
 		return eeh_check_failure(addr, val);
 	return val;
 }
@@ -109,10 +108,11 @@
 	volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
 	out_8(vaddr, val);
 }
+
 static inline u16 eeh_readw(void *addr) {
 	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
 	u16 val = in_le16(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u16))
 		return eeh_check_failure(addr, val);
 	return val;
 }
@@ -120,10 +120,22 @@
 	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
 	out_le16(vaddr, val);
 }
+static inline u16 eeh_raw_readw(void *addr) {
+	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+	u16 val = in_be16(vaddr);
+	if (EEH_POSSIBLE_ERROR(addr, vaddr, 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);
+	out_be16(vaddr, val);
+}
+
 static inline u32 eeh_readl(void *addr) {
 	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
 	u32 val = in_le32(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u32))
 		return eeh_check_failure(addr, val);
 	return val;
 }
@@ -131,10 +143,22 @@
 	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
 	out_le32(vaddr, val);
 }
+static inline u32 eeh_raw_readl(void *addr) {
+	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+	u32 val = in_be32(vaddr);
+	if (EEH_POSSIBLE_ERROR(addr, vaddr, 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);
+	out_be32(vaddr, val);
+}
+
 static inline u64 eeh_readq(void *addr) {
 	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
 	u64 val = in_le64(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val))
+	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u64))
 		return eeh_check_failure(addr, val);
 	return val;
 }
@@ -142,6 +166,17 @@
 	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
 	out_le64(vaddr, val);
 }
+static inline u64 eeh_raw_readq(void *addr) {
+	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+	u64 val = in_be64(vaddr);
+	if (EEH_POSSIBLE_ERROR(addr, vaddr, 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);
+	out_be64(vaddr, val);
+}
 
 static inline void eeh_memset_io(void *addr, int c, unsigned long n) {
 	void *vaddr = (void *)IO_TOKEN_TO_ADDR(addr);
@@ -150,8 +185,15 @@
 static inline void eeh_memcpy_fromio(void *dest, void *src, unsigned long n) {
 	void *vsrc = (void *)IO_TOKEN_TO_ADDR(src);
 	memcpy(dest, vsrc, n);
-	/* look for ffff's here at dest[n] */
+	/* Look for ffff's here at dest[n].  Assume that at least 4 bytes
+	 * were copied. Check all four bytes.
+	 */
+	if ((n >= 4) &&
+		(EEH_POSSIBLE_ERROR(src, vsrc, (*((u32 *) dest+n-4)), u32))) {
+		eeh_check_failure(src, (*((u32 *) dest+n-4)));
+	}
 }
+
 static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) {
 	void *vdest = (void *)IO_TOKEN_TO_ADDR(dest);
 	memcpy(vdest, src, n);
@@ -169,8 +211,8 @@
 	if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
 		return ~0;
 	val = in_8((u8 *)(port+pci_io_base));
-	if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
-		return eeh_check_failure((void*)(port+pci_io_base), val);
+	if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val, u8))
+		return eeh_check_failure((void*)(port), val);
 	return val;
 }
 
@@ -184,8 +226,8 @@
 	if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
 		return ~0;
 	val = in_le16((u16 *)(port+pci_io_base));
-	if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
-		return eeh_check_failure((void*)(port+pci_io_base), val);
+	if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val, u16))
+		return eeh_check_failure((void*)(port), val);
 	return val;
 }
 
@@ -199,8 +241,8 @@
 	if (_IO_IS_ISA(port) && !_IO_HAS_ISA_BUS)
 		return ~0;
 	val = in_le32((u32 *)(port+pci_io_base));
-	if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val))
-		return eeh_check_failure((void*)(port+pci_io_base), val);
+	if (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR(val, u32))
+		return eeh_check_failure((void*)(port), val);
 	return val;
 }
 
@@ -209,4 +251,23 @@
 		return out_le32((u32 *)(port+pci_io_base), val);
 }
 
-#endif /* _EEH_H */
+/* 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 (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR((*(((u8*)buf)+ns-1)), u8))
+		eeh_check_failure((void*)(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 (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR((*(((u16*)buf)+ns-1)), u16))
+		eeh_check_failure((void*)(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 (!_IO_IS_ISA(port) && EEH_POSSIBLE_IO_ERROR((*(((u32*)buf)+nl-1)), u32))
+		eeh_check_failure((void*)(port), *(u32*)buf);
+}
+
+#endif /* _PPC64_EEH_H */
diff -Nru a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h
--- a/include/asm-ppc64/hvcall.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ppc64/hvcall.h	Wed Mar 17 19:29:09 2004
@@ -4,6 +4,14 @@
 #define H_Success	0
 #define H_Busy		1	/* Hardware busy -- retry later */
 #define H_Constrained	4	/* Resource request constrained to max allowed */
+#define H_LongBusyStartRange   9900  /* Start of long busy range */
+#define H_LongBusyOrder1msec   9900  /* Long busy, hint that 1msec is a good time to retry */
+#define H_LongBusyOrder10msec  9901  /* Long busy, hint that 10msec is a good time to retry */
+#define H_LongBusyOrder100msec 9902  /* Long busy, hint that 100msec is a good time to retry */
+#define H_LongBusyOrder1sec    9903  /* Long busy, hint that 1sec is a good time to retry */
+#define H_LongBusyOrder10sec   9904  /* Long busy, hint that 10sec is a good time to retry */
+#define H_LongBusyOrder100sec  9905  /* Long busy, hint that 100sec is a good time to retry */
+#define H_LongBusyEndRange     9905  /* End of long busy range */
 #define H_Hardware	-1	/* Hardware error */
 #define H_Function	-2	/* Function not supported */
 #define H_Privilege	-3	/* Caller not privileged */
@@ -21,6 +29,16 @@
 #define H_RemoteParm           -15
 #define H_Resource             -16
 
+/* Long Busy is a condition that can be returned by the firmware
+ * when a call cannot be completed now, but the identical call
+ * should be retried later.  This prevents calls blocking in the
+ * firmware for long periods of time. Annoyingly the firmware can return
+ * a range of return codes, hinting at how long we should wait before
+ * retrying.  If you don't care for the hint, the macro below is a good
+ * way to check for the long_busy return codes
+ */
+#define H_isLongBusy(x)  ((x >= H_LongBusyStartRange) && (x <= H_LongBusyEndRange))
+
 /* Flags */
 #define H_LARGE_PAGE		(1UL<<(63-16))
 #define H_EXACT		    (1UL<<(63-24))	/* Use exact PTE or return H_PTEG_FULL */
@@ -76,7 +94,7 @@
 #define H_PROD		        0xE8
 #define H_GET_PPP		0xEC
 #define H_SET_PPP		0xF0
-#define H_SET_PURR		0xF4
+#define H_PURR			0xF4
 #define H_PIC		        0xF8
 #define H_REG_CRQ		0xFC
 #define H_FREE_CRQ		0x100
@@ -84,6 +102,9 @@
 #define H_SEND_CRQ		0x108
 #define H_COPY_RDMA             0x110
 #define H_POLL_PENDING	        0x1D8
+#define H_VTERM_PARTNER_INFO	0x150
+#define H_REGISTER_VTERM		0x154
+#define H_FREE_VTERM			0x158
 
 /* plpar_hcall() -- Generic call interface using above opcodes
  *
diff -Nru a/include/asm-ppc64/iSeries/iSeries_proc.h b/include/asm-ppc64/iSeries/iSeries_proc.h
--- a/include/asm-ppc64/iSeries/iSeries_proc.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ppc64/iSeries/iSeries_proc.h	Wed Mar 17 19:29:09 2004
@@ -19,12 +19,6 @@
 #ifndef _ISERIES_PROC_H
 #define _ISERIES_PROC_H
 
-#include <linux/proc_fs.h>
-
 extern void iSeries_proc_early_init(void);
-
-typedef void (*iSeriesProcFunction)(struct proc_dir_entry *iSeries_proc);
-
-extern void iSeries_proc_callback(iSeriesProcFunction initFunction);
 
 #endif /* _iSeries_PROC_H */
diff -Nru a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h
--- a/include/asm-ppc64/iSeries/mf.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ppc64/iSeries/mf.h	Wed Mar 17 19:29:09 2004
@@ -67,6 +67,4 @@
 extern int mf_getRtc( struct rtc_time * tm );
 extern int mf_setRtc( struct rtc_time * tm );
 
-extern void mf_proc_init(struct proc_dir_entry *iSeries_proc);
-
 #endif /* MF_H_INCLUDED */
diff -Nru a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
--- a/include/asm-ppc64/io.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-ppc64/io.h	Wed Mar 17 19:29:10 2004
@@ -58,6 +58,13 @@
 #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)))
+/*
+ * The *_ns versions below don't do byte-swapping.
+ * Neither do the standard versions now, these are just here
+ * for older code.
+ */
+#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))
@@ -90,12 +97,16 @@
  * They are only used in practice for transferring buffers which
  * are arrays of bytes, and byte-swapping is not appropriate in
  * that case.  - paulus */
-#define insb(port, buf, ns)	_insb((u8 *)((port)+pci_io_base), (buf), (ns))
-#define outsb(port, buf, ns)	_outsb((u8 *)((port)+pci_io_base), (buf), (ns))
-#define insw(port, buf, ns)	_insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define outsw(port, buf, ns)	_outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define insl(port, buf, nl)	_insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
-#define outsl(port, buf, nl)	_outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
+#define insb(port, buf, ns)	eeh_insb((port), (buf), (ns))
+#define insw(port, buf, ns)	eeh_insw_ns((port), (buf), (ns))
+#define insl(port, buf, nl)	eeh_insl_ns((port), (buf), (nl))
+#define insw_ns(port, buf, ns)	eeh_insw_ns((port), (buf), (ns))
+#define insl_ns(port, buf, nl)	eeh_insl_ns((port), (buf), (nl))
+
+#define outsb(port, buf, ns)  _outsb((u8 *)((port)+pci_io_base), (buf), (ns))
+#define outsw(port, buf, ns)  _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
+#define outsl(port, buf, nl)  _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
+
 #endif
 
 #define readb_relaxed(addr) readb(addr)
@@ -130,9 +141,7 @@
  * Neither do the standard versions now, these are just here
  * for older code.
  */
-#define insw_ns(port, buf, ns)	_insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
 #define outsw_ns(port, buf, ns)	_outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
-#define insl_ns(port, buf, nl)	_insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
 #define outsl_ns(port, buf, nl)	_outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
 
 
@@ -204,6 +213,9 @@
 
 /*
  * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ * These routines do not perform EEH-related I/O address translation,
+ * and should not be used directly by device drivers.  Use inb/readb
+ * instead.
  */
 static inline int in_8(volatile unsigned char *addr)
 {
diff -Nru a/include/asm-ppc64/pmc.h b/include/asm-ppc64/pmc.h
--- a/include/asm-ppc64/pmc.h	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,113 +0,0 @@
-/* 
- * pmc.h
- * Copyright (C) 2001  Dave Engebretsen & Mike Corrigan IBM Corporation.
- *
- * The PPC64 PMC subsystem encompases both the hardware PMC registers and 
- * a set of software event counters.  An interface is provided via the
- * proc filesystem which can be used to access this subsystem.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-/* Start Change Log
- * 2001/06/05 : engebret : Created.
- * End Change Log 
- */
-
-#ifndef _PPC64_TYPES_H
-#include        <asm/types.h>
-#endif
-
-#ifndef _PMC_H
-#define _PMC_H
-
-#define STAB_ENTRY_MAX 64
-
-struct _pmc_hw
-{
-	u64 mmcr0; 
-	u64 mmcr1; 
-	u64 mmcra; 
-
-	u64 pmc1; 
-	u64 pmc2; 
-	u64 pmc3; 
-	u64 pmc4; 
-	u64 pmc5; 
-	u64 pmc6; 
-	u64 pmc7; 
-	u64 pmc8; 
-};
-
-struct _pmc_sw
-{
-	u64 stab_faults;           /* Count of faults on the stab      */
-	u64 stab_capacity_castouts;/* Count of castouts from the stab  */
-	u64 stab_invalidations;	   /* Count of invalidations from the  */
-                                   /*   stab, not including castouts   */
-	u64 stab_entry_use[STAB_ENTRY_MAX]; 
-
-	u64 htab_primary_overflows;
-	u64 htab_capacity_castouts;
-	u64 htab_read_to_write_fault;
-};
-
-#define PMC_HW_TEXT_ENTRY_COUNT (sizeof(struct _pmc_hw) / sizeof(u64))
-#define PMC_SW_TEXT_ENTRY_COUNT (sizeof(struct _pmc_sw) / sizeof(u64))
-#define PMC_TEXT_ENTRY_SIZE  64
-
-struct _pmc_sw_text {
-	char buffer[PMC_SW_TEXT_ENTRY_COUNT * PMC_TEXT_ENTRY_SIZE];
-};
-
-struct _pmc_hw_text {
-	char buffer[PMC_HW_TEXT_ENTRY_COUNT * PMC_TEXT_ENTRY_SIZE];
-};
-
-extern struct _pmc_sw pmc_sw_system;
-extern struct _pmc_sw pmc_sw_cpu[];
-
-extern struct _pmc_sw_text pmc_sw_text;
-extern struct _pmc_hw_text pmc_hw_text;
-extern char *ppc64_pmc_stab(int file);
-extern char *ppc64_pmc_htab(int file);
-extern char *ppc64_pmc_hw(int file);
-
-#if 1
-#define PMC_SW_PROCESSOR(F)      pmc_sw_cpu[smp_processor_id()].F++
-#define PMC_SW_PROCESSOR_A(F, E) (pmc_sw_cpu[smp_processor_id()].F[(E)])++
-#define PMC_SW_SYSTEM(F)         pmc_sw_system.F++
-#else
-#define PMC_SW_PROCESSOR(F)   do {;} while (0)
-#define PMC_SW_PROCESSOR_A(F) do {;} while (0)
-#define PMC_SW_SYSTEM(F)      do {;} while (0)
-#endif
-
-#define MMCR0 795
-#define MMCR1 798
-#define MMCRA 786
-#define PMC1  787
-#define PMC2  788
-#define PMC3  789
-#define PMC4  790
-#define PMC5  791
-#define PMC6  792
-#define PMC7  793
-#define PMC8  794
-
-#define PMC_CONTROL_CPI 1
-#define PMC_CONTROL_TLB 2
-
-#endif /* _PMC_H */
diff -Nru a/include/asm-ppc64/proc_fs.h b/include/asm-ppc64/proc_fs.h
--- a/include/asm-ppc64/proc_fs.h	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,39 +0,0 @@
-#ifndef _PPC64_PROC_FS_H
-#define _PPC64_PROC_FS_H
-/*
- * proc_fs.h
- * Copyright (C) 2001  Mike Corrigan  IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * 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
- */
-
-/* Change Activity: */
-/* tgall -- merge of iSeries/iSeries_proc.h and proc_pmc.h */
-/* End Change Activity */
-
-#include <linux/proc_fs.h>
-
-struct proc_ppc64_t {
-	struct proc_dir_entry *root;
-	struct proc_dir_entry *naca;
-	struct proc_dir_entry *paca;
-	struct proc_dir_entry *systemcfg;
-	struct proc_dir_entry *rtas;
-};
-
-extern struct proc_ppc64_t proc_ppc64;
-extern int proc_ppc64_init(void);
-
-#endif /* _PPC64_PROC_FS_H */
diff -Nru a/include/asm-ppc64/proc_pmc.h b/include/asm-ppc64/proc_pmc.h
--- a/include/asm-ppc64/proc_pmc.h	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/*
- * pmc_proc.h
- * Copyright (C) 2001  Mike Corrigan  IBM Corporation
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * 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
- */
-
-
-/* Change Activity: */
-/* End Change Activity */
-
-#ifndef _PMC_PROC_H
-#define _PMC_PROC_H
-
-#include <linux/proc_fs.h>
-
-void pmc_proc_init(struct proc_dir_entry *iSeries_proc);
-void proc_ppc64_init(void);
-
-#endif /* _PMC_PROC_H */
-
diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
--- a/include/asm-ppc64/rtas.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-ppc64/rtas.h	Wed Mar 17 19:29:10 2004
@@ -177,6 +177,7 @@
 extern void rtas_halt(void);
 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);
 
 /* Given an RTAS status code of 9900..9905 compute the hinted delay */
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ppc64/unistd.h	Wed Mar 17 19:29:09 2004
@@ -274,10 +274,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/types.h>
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-
 /* On powerpc a system call basically clobbers the same registers like a
  * function call, with the exception of LR (which is needed for the
  * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
@@ -401,22 +397,17 @@
  */
 static inline _syscall3(int, execve, __const__ char *, file, char **, argv,
 			char **,envp)
-static inline _syscall3(int, open, __const__ char *, file, int, flag, int, mode)
-static inline _syscall1(int, close, int, fd)
-static inline _syscall1(int, dup, int, fd)
-static inline _syscall3(int, read, int, fd, char *, buf , off_t, count)
-static inline _syscall3(int, write, int, fd, __const__ char *, buf, off_t,
-			count)
-static inline _syscall0(pid_t, setsid)
-static inline _syscall3(off_t, lseek, int, fd, off_t, offset, int, count)
-static inline _syscall3(pid_t, waitpid, pid_t, pid, int *, wait_stat, int,
-			options)
 
 #endif /* __KERNEL_SYSCALLS__ */
 
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
-				unsigned long prot, unsigned long flags,
-				unsigned long fd, off_t offset);
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+
+unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot,
+		       unsigned long flags, unsigned long fd, off_t offset);
 struct pt_regs;
 int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
 		unsigned long a3, unsigned long a4, unsigned long a5,
@@ -430,13 +421,11 @@
 int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
 		unsigned long p4, unsigned long p5, unsigned long p6,
 		struct pt_regs *regs);
-asmlinkage int sys_pipe(int *fildes);
+int sys_pipe(int *fildes);
 int sys_ptrace(long request, long pid, long addr, long data);
 struct sigaction;
-asmlinkage long sys_rt_sigaction(int sig,
-				const struct sigaction __user *act,
-				struct sigaction __user *oact,
-				size_t sigsetsize);
+long sys_rt_sigaction(int sig, const struct sigaction __user *act,
+		      struct sigaction __user *oact, size_t sigsetsize);
 
 /*
  * "Conditional" syscalls
@@ -445,6 +434,8 @@
  * but it doesn't work on all toolchains, so we just do it by hand
  */
 #define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall");
+
+#endif		/* __KERNEL__ */
 
 #endif		/* __ASSEMBLY__ */
 
diff -Nru a/include/asm-ppc64/vio.h b/include/asm-ppc64/vio.h
--- a/include/asm-ppc64/vio.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-ppc64/vio.h	Wed Mar 17 19:29:09 2004
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/device.h>
+#include <linux/pci.h>
 #include <asm/hvcall.h>
 #include <asm/prom.h>
 #include <asm/scatterlist.h>
@@ -44,8 +45,11 @@
 void vio_unregister_driver(struct vio_driver *drv);
 const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, 
 						const struct vio_dev *dev);
+
 struct vio_dev * __devinit vio_register_device(struct device_node *node_vdev);
 void __devinit vio_unregister_device(struct vio_dev *dev);
+struct vio_dev *vio_find_node(struct device_node *vnode);
+
 const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length);
 int vio_get_irq(struct vio_dev *dev);
 struct iommu_table * vio_build_iommu_table(struct vio_dev *dev);
@@ -64,6 +68,33 @@
 			   dma_addr_t *dma_handle);
 void vio_free_consistent(struct vio_dev *dev, size_t size, void *vaddr, 
 			 dma_addr_t dma_handle);
+
+static inline int vio_dma_supported(struct vio_dev *hwdev, u64 mask)
+{
+	return 1;
+}
+
+#define vio_map_page(dev, page, off, size, dir) \
+		vio_map_single(dev, (page_address(page) + (off)), size, dir)
+#define vio_unmap_page(dev,addr,sz,dir) vio_unmap_single(dev,addr,sz,dir)
+
+
+static inline void vio_dma_sync_single(struct vio_dev *hwdev,
+				       dma_addr_t dma_handle,
+				       size_t size, int direction)
+{
+	BUG_ON(direction == PCI_DMA_NONE);
+	/* nothing to do */
+}
+
+static inline void vio_dma_sync_sg(struct vio_dev *hwdev,
+				   struct scatterlist *sg,
+				   int nelems, int direction)
+{
+	BUG_ON(direction == PCI_DMA_NONE);
+	/* nothing to do */
+}
+static inline int vio_set_dma_mask(struct vio_dev *dev, u64 mask) { return -EIO; }
 
 extern struct bus_type vio_bus_type;
 
diff -Nru a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
--- a/include/asm-s390/bitops.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-s390/bitops.h	Wed Mar 17 19:29:09 2004
@@ -532,7 +532,7 @@
  * Find-bit routines..
  */
 static inline int
-find_first_zero_bit(unsigned long * addr, unsigned int size)
+find_first_zero_bit(const unsigned long * addr, unsigned int size)
 {
 	unsigned long cmp, count;
         unsigned int res;
@@ -571,7 +571,7 @@
 }
 
 static inline int
-find_first_bit(unsigned long * addr, unsigned int size)
+find_first_bit(const unsigned long * addr, unsigned int size)
 {
 	unsigned long cmp, count;
         unsigned int res;
@@ -610,7 +610,7 @@
 }
 
 static inline int
-find_next_zero_bit (unsigned long * addr, int size, int offset)
+find_next_zero_bit (const unsigned long * addr, int size, int offset)
 {
         unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
         unsigned long bitvec, reg;
@@ -649,7 +649,7 @@
 }
 
 static inline int
-find_next_bit (unsigned long * addr, int size, int offset)
+find_next_bit (const unsigned long * addr, int size, int offset)
 {
         unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
         unsigned long bitvec, reg;
@@ -693,7 +693,7 @@
  * Find-bit routines..
  */
 static inline unsigned long
-find_first_zero_bit(unsigned long * addr, unsigned long size)
+find_first_zero_bit(const unsigned long * addr, unsigned long size)
 {
         unsigned long res, cmp, count;
 
@@ -735,7 +735,7 @@
 }
 
 static inline unsigned long
-find_first_bit(unsigned long * addr, unsigned long size)
+find_first_bit(const unsigned long * addr, unsigned long size)
 {
         unsigned long res, cmp, count;
 
@@ -777,7 +777,7 @@
 }
 
 static inline unsigned long
-find_next_zero_bit (unsigned long * addr, unsigned long size, unsigned long offset)
+find_next_zero_bit (const unsigned long * addr, unsigned long size, unsigned long offset)
 {
         unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
         unsigned long bitvec, reg;
@@ -821,7 +821,7 @@
 }
 
 static inline unsigned long
-find_next_bit (unsigned long * addr, unsigned long size, unsigned long offset)
+find_next_bit (const unsigned long * addr, unsigned long size, unsigned long offset)
 {
         unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
         unsigned long bitvec, reg;
diff -Nru a/include/asm-s390/cio.h b/include/asm-s390/cio.h
--- a/include/asm-s390/cio.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-s390/cio.h	Wed Mar 17 19:29:10 2004
@@ -132,6 +132,7 @@
 #define CCW_CMD_SENSE_PGID	0x34
 #define CCW_CMD_SUSPEND_RECONN	0x5B
 #define CCW_CMD_RDC		0x64
+#define CCW_CMD_RELEASE		0x94
 #define CCW_CMD_SET_PGID	0xAF
 #define CCW_CMD_SENSE_ID	0xE4
 #define CCW_CMD_DCTL		0xF3
diff -Nru a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
--- a/include/asm-s390/lowcore.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-s390/lowcore.h	Wed Mar 17 19:29:09 2004
@@ -44,6 +44,10 @@
 #define __LC_PGM_ILC                    0x08C
 #define __LC_PGM_INT_CODE               0x08E
 
+#define __LC_PER_ATMID			0x096
+#define __LC_PER_ADDRESS		0x098
+#define __LC_PER_ACCESS_ID		0x0A1
+
 #define __LC_SUBCHANNEL_ID              0x0B8
 #define __LC_SUBCHANNEL_NR              0x0BA
 #define __LC_IO_INT_PARM                0x0BC
diff -Nru a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
--- a/include/asm-s390/ptrace.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-s390/ptrace.h	Wed Mar 17 19:29:09 2004
@@ -277,6 +277,14 @@
 			 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
 			 PSW_MASK_PSTATE)
 
+/* This macro merges a NEW PSW mask specified by the user into
+   the currently active PSW mask CURRENT, modifying only those
+   bits in CURRENT that the user may be allowed to change: this
+   is the condition code and the program mask bits.  */
+#define PSW_MASK_MERGE(CURRENT,NEW) \
+	(((CURRENT) & ~(PSW_MASK_CC|PSW_MASK_PM)) | \
+	 ((NEW) & (PSW_MASK_CC|PSW_MASK_PM)))
+
 /*
  * The first entries in pt_regs and user_regs_struct
  * are common for the two structures. The s390_regs structure
diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
--- a/include/asm-s390/unistd.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-s390/unistd.h	Wed Mar 17 19:29:10 2004
@@ -256,12 +256,15 @@
 #define __NR_clock_gettime	(__NR_timer_create+6)
 #define __NR_clock_getres	(__NR_timer_create+7)
 #define __NR_clock_nanosleep	(__NR_timer_create+8)
+
 /*
  * Number 263 is reserved for vserver
  */
 #define __NR_fadvise64_64	264
+#define __NR_statfs64		265
+#define __NR_fstatfs64		266
 
-#define NR_syscalls 265
+#define NR_syscalls 267
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff -Nru a/include/asm-sparc/shmparam.h b/include/asm-sparc/shmparam.h
--- a/include/asm-sparc/shmparam.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-sparc/shmparam.h	Wed Mar 17 19:29:10 2004
@@ -2,6 +2,8 @@
 #ifndef _ASMSPARC_SHMPARAM_H
 #define _ASMSPARC_SHMPARAM_H
 
+#define __ARCH_FORCE_SHMLBA 	1
+
 extern int vac_cache_size;
 #define SHMLBA (vac_cache_size ? vac_cache_size : \
 		(sparc_cpu_model == sun4c ? (64 * 1024) : \
diff -Nru a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h
--- a/include/asm-sparc/thread_info.h	Wed Mar 17 19:29:10 2004
+++ b/include/asm-sparc/thread_info.h	Wed Mar 17 19:29:10 2004
@@ -100,9 +100,6 @@
  * Size of kernel stack for each process.
  * Observe the order of get_free_pages() in alloc_thread_info().
  * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste.
- *
- * XXX Watch how INIT_THREAD_SIZE evolves in linux/sched.h and elsewhere.
- *     On 2.5.24 it happens to match 8192 magically.
  */
 #define THREAD_SIZE		8192
 
diff -Nru a/include/asm-sparc64/shmparam.h b/include/asm-sparc64/shmparam.h
--- a/include/asm-sparc64/shmparam.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-sparc64/shmparam.h	Wed Mar 17 19:29:09 2004
@@ -4,6 +4,7 @@
 
 #include <asm/spitfire.h>
 
+#define __ARCH_FORCE_SHMLBA	1
 /* attach addr a multiple of this */
 #define	SHMLBA	((PAGE_SIZE > L1DCACHE_SIZE) ? PAGE_SIZE : L1DCACHE_SIZE)
 
diff -Nru a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
--- a/include/asm-um/processor-generic.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-um/processor-generic.h	Wed Mar 17 19:29:09 2004
@@ -94,8 +94,6 @@
 	.request		= { 0 } \
 }
 
-#define INIT_THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
-
 typedef struct {
 	unsigned long seg;
 } mm_segment_t;
diff -Nru a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
--- a/include/asm-x86_64/bitops.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-x86_64/bitops.h	Wed Mar 17 19:29:09 2004
@@ -503,6 +503,8 @@
 /* find last set bit */
 #define fls(x) generic_fls(x)
 
+#define ARCH_HAS_ATOMIC_UNSIGNED 1
+
 #endif /* __KERNEL__ */
 
 #endif /* _X86_64_BITOPS_H */
diff -Nru a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
--- a/include/asm-x86_64/smp.h	Wed Mar 17 19:29:09 2004
+++ b/include/asm-x86_64/smp.h	Wed Mar 17 19:29:09 2004
@@ -48,6 +48,7 @@
 extern void zap_low_mappings(void);
 void smp_stop_cpu(void);
 extern char cpu_sibling_map[];
+extern char phys_proc_id[NR_CPUS];
 
 #define SMP_TRAMPOLINE_BASE 0x6000
 
diff -Nru a/include/linux/brlvger.h b/include/linux/brlvger.h
--- a/include/linux/brlvger.h	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,54 +0,0 @@
-/*
- *      Tieman Voyager braille display USB driver.
- *
- *      Copyright 2001-2002 Stephane Dalton <sdalton@videotron.ca>
- *                      and Stéphane Doyon  <s.doyon@videotron.ca>
- *            Maintained by Stéphane Doyon  <s.doyon@videotron.ca>.
- */
-/*
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _LINUX_BRLVGER_H
-#define _LINUX_BRLVGER_H
-
-/* Ioctl request codes */
-#define BRLVGER_GET_INFO	0
-#define BRLVGER_DISPLAY_ON	2
-#define BRLVGER_DISPLAY_OFF	3
-#define BRLVGER_BUZZ		4
-
-/* Base minor for the char devices */
-#define BRLVGER_MINOR		128
-
-/* Size of some fields */
-#define BRLVGER_HWVER_SIZE	2
-#define BRLVGER_FWVER_SIZE	200 /* arbitrary, a long string */
-#define BRLVGER_SERIAL_BIN_SIZE	8
-#define BRLVGER_SERIAL_SIZE	((2*BRLVGER_SERIAL_BIN_SIZE)+1)
-
-struct brlvger_info {
-	__u8 driver_version[12];
-	__u8 driver_banner[200];
-
-	__u32 display_length;
-	/* All other char[] fields are strings except this one.
-	   Hardware version: first byte is major, second byte is minor. */
-	__u8 hwver[BRLVGER_HWVER_SIZE];
-	__u8 fwver[BRLVGER_FWVER_SIZE];
-	__u8 serialnum[BRLVGER_SERIAL_SIZE];
-};
-
-#endif
diff -Nru a/include/linux/cdrom.h b/include/linux/cdrom.h
--- a/include/linux/cdrom.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/cdrom.h	Wed Mar 17 19:29:09 2004
@@ -722,7 +722,9 @@
 /*
  * feature profile
  */
-#define CDF_MRW		0x28
+#define CDF_RWRT	0x0020	/* "Random Writable" */
+#define CDF_HWDM	0x0024	/* "Hardware Defect Management" */
+#define CDF_MRW 	0x0028
 
 /*
  * media status bits
@@ -771,6 +773,34 @@
 	__u8 reserved5;
 };
 
+/* cf. mmc4r02g.pdf 5.3.10 Random Writable Feature (0020h) pg 197 of 635 */
+struct rwrt_feature_desc {
+	__u16 feature_code;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved1		: 2;
+	__u8 feature_version	: 4;
+	__u8 persistent		: 1;
+	__u8 curr		: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 curr		: 1;
+	__u8 persistent		: 1;
+	__u8 feature_version	: 4;
+	__u8 reserved1		: 2;
+#endif
+	__u8 add_len;
+	__u32 last_lba;
+	__u32 block_size;
+	__u16 blocking;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2		: 7;
+	__u8 page_present	: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 page_present	: 1;
+	__u8 reserved2		: 7;
+#endif
+	__u8 reserved3;
+};
+
 typedef struct {
 	__u16 disc_information_length;
 #if defined(__BIG_ENDIAN_BITFIELD)
@@ -1140,6 +1170,7 @@
 
 extern int cdrom_get_media_event(struct cdrom_device_info *cdi, struct media_event_desc *med);
 extern int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write);
+extern int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write);
 
 #endif  /* End of kernel only stuff */ 
 
diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h
--- a/include/linux/hiddev.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/hiddev.h	Wed Mar 17 19:29:09 2004
@@ -39,33 +39,33 @@
 };
 
 struct hiddev_devinfo {
-	unsigned int bustype;
-	unsigned int busnum;
-	unsigned int devnum;
-	unsigned int ifnum;
-	short vendor;
-	short product;
-	short version;
-	unsigned num_applications;
+	__u32 bustype;
+	__u32 busnum;
+	__u32 devnum;
+	__u32 ifnum;
+	__s16 vendor;
+	__s16 product;
+	__s16 version;
+	__u32 num_applications;
 };
 
 struct hiddev_collection_info {
-	unsigned index;
-	unsigned type;
-	unsigned usage;
-	unsigned level;
+	__u32 index;
+	__u32 type;
+	__u32 usage;
+	__u32 level;
 };
 
 #define HID_STRING_SIZE 256
 struct hiddev_string_descriptor {
-	int index;
+	__s32 index;
 	char value[HID_STRING_SIZE];
 };
 
 struct hiddev_report_info {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned num_fields;
+	__u32 report_type;
+	__u32 report_id;
+	__u32 num_fields;
 };
 
 /* To do a GUSAGE/SUSAGE, fill in at least usage_code,  report_type and 
@@ -88,20 +88,20 @@
 #define HID_REPORT_TYPE_MAX     3
 
 struct hiddev_field_info {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned field_index;
-	unsigned maxusage;
-	unsigned flags;
-	unsigned physical;		/* physical usage for this field */
-	unsigned logical;		/* logical usage for this field */
-	unsigned application;		/* application usage for this field */
+	__u32 report_type;
+	__u32 report_id;
+	__u32 field_index;
+	__u32 maxusage;
+	__u32 flags;
+	__u32 physical;		/* physical usage for this field */
+	__u32 logical;		/* logical usage for this field */
+	__u32 application;		/* application usage for this field */
 	__s32 logical_minimum;
 	__s32 logical_maximum;
 	__s32 physical_minimum;
 	__s32 physical_maximum;
-	unsigned unit_exponent;
-	unsigned unit;
+	__u32 unit_exponent;
+	__u32 unit;
 };
 
 /* Fill in report_type, report_id and field_index to get the information on a
@@ -118,14 +118,22 @@
 #define HID_FIELD_BUFFERED_BYTE		0x100
 
 struct hiddev_usage_ref {
-	unsigned report_type;
-	unsigned report_id;
-	unsigned field_index;
-	unsigned usage_index;
-	unsigned usage_code;
+	__u32 report_type;
+	__u32 report_id;
+	__u32 field_index;
+	__u32 usage_index;
+	__u32 usage_code;
 	__s32 value;
 };
 
+/* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
+ * It really manifests itself as setting the value of consecutive usages */
+struct hiddev_usage_ref_multi {
+	struct hiddev_usage_ref uref;
+	__u32 num_values;
+	__s32 values[HID_MAX_USAGES];
+};
+
 /* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
  * is set to (HIDDEV_FLAG_UREF | HIDDEV_FLAG_REPORT) and a new report has
  * been sent by the device 
@@ -160,6 +168,10 @@
 #define HIDIOCGCOLLECTIONINDEX	_IOW('H', 0x10, struct hiddev_usage_ref)
 #define HIDIOCGCOLLECTIONINFO	_IOWR('H', 0x11, struct hiddev_collection_info)
 #define HIDIOCGPHYS(len)	_IOC(_IOC_READ, 'H', 0x12, len)
+
+/* For writing/reading to multiple/consecutive usages */
+#define HIDIOCGUSAGES		_IOWR('H', 0x13, struct hiddev_usage_ref_multi)
+#define HIDIOCSUSAGES		_IOW('H', 0x14, struct hiddev_usage_ref_multi)
 
 /* 
  * Flags to be used in HIDIOCSFLAG
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/ide.h	Wed Mar 17 19:29:09 2004
@@ -742,8 +742,6 @@
 
 	u64		capacity64;	/* total number of sectors */
 
-	int		last_lun;	/* last logical unit */
-	int		forced_lun;	/* if hdxlun was given at boot */
 	int		lun;		/* logical unit */
 	int		crc_count;	/* crc counter to reduce drive speed */
 	struct list_head list;
@@ -937,7 +935,6 @@
 	int		mmio;		/* hosts iomio (0), mmio (1) or custom (2) select */
 	int		rqsize;		/* max sectors per request */
 	int		irq;		/* our irq number */
-	int		initializing;	/* set while initializing self */
 
 	unsigned long	dma_master;	/* reference base addr dmabase */
 	unsigned long	dma_base;	/* base addr for dma ports */
@@ -1612,6 +1609,7 @@
 extern char *ide_xfer_verbose(u8 xfer_rate);
 extern void ide_toggle_bounce(ide_drive_t *drive, int on);
 extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
+extern byte ide_dump_atapi_status(ide_drive_t *drive, const char *msg, byte stat);
 
 typedef struct ide_pio_timings_s {
 	int	setup_time;	/* Address setup (ns) minimum */
diff -Nru a/include/linux/init.h b/include/linux/init.h
--- a/include/linux/init.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/init.h	Wed Mar 17 19:29:09 2004
@@ -110,12 +110,21 @@
 };
 
 /* OBSOLETE: see moduleparam.h for the right way. */
-#define __setup(str, fn)					\
-	static char __setup_str_##fn[] __initdata = str;	\
-	static struct obs_kernel_param __setup_##fn		\
+#define __setup_param(str, unique_id, fn)			\
+	static char __setup_str_##unique_id[] __initdata = str;	\
+	static struct obs_kernel_param __setup_##unique_id	\
 		 __attribute_used__				\
 		 __attribute__((__section__(".init.setup")))	\
-		= { __setup_str_##fn, fn }
+		= { __setup_str_##unique_id, fn }
+
+#define __setup_null_param(str, unique_id)			\
+	__setup_param(str, unique_id, NULL)
+
+#define __setup(str, fn)					\
+	__setup_param(str, fn, fn)
+
+#define __obsolete_setup(str)					\
+	__setup_null_param(str, __LINE__)
 
 #endif /* __ASSEMBLY__ */
 
@@ -172,7 +181,10 @@
 	{ return exitfn; }					\
 	void cleanup_module(void) __attribute__((alias(#exitfn)));
 
-#define __setup(str,func) /* nothing */
+#define __setup_param(str, unique_id, fn)	/* nothing */
+#define __setup_null_param(str, unique_id) 	/* nothing */
+#define __setup(str, func) 			/* nothing */
+#define __obsolete_setup(str) 			/* nothing */
 #endif
 
 /* Data marked not to be saved by software_suspend() */
diff -Nru a/include/linux/miscdevice.h b/include/linux/miscdevice.h
--- a/include/linux/miscdevice.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/miscdevice.h	Wed Mar 17 19:29:09 2004
@@ -3,7 +3,6 @@
 #include <linux/module.h>
 #include <linux/major.h>
 
-#define BUSMOUSE_MINOR 0
 #define PSMOUSE_MINOR  1
 #define MS_BUSMOUSE_MINOR 2
 #define ATIXL_BUSMOUSE_MINOR 3
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/mm.h	Wed Mar 17 19:29:09 2004
@@ -152,6 +152,12 @@
 struct mmu_gather;
 struct inode;
 
+#ifdef ARCH_HAS_ATOMIC_UNSIGNED
+typedef unsigned page_flags_t;
+#else
+typedef unsigned long page_flags_t;
+#endif
+
 /*
  * Each physical page in the system has a struct page associated with
  * it to keep track of whatever it is we are using the page for at the
@@ -168,7 +174,7 @@
  * TODO: make this structure smaller, it could be as small as 32 bytes.
  */
 struct page {
-	unsigned long flags;		/* atomic flags, some possibly
+	page_flags_t flags;		/* atomic flags, some possibly
 					   updated asynchronously */
 	atomic_t count;			/* Usage count, see below. */
 	struct list_head list;		/* ->mapping has some page lists. */
@@ -333,7 +339,7 @@
  * We'll have up to (MAX_NUMNODES * MAX_NR_ZONES) zones total,
  * so we use (MAX_NODES_SHIFT + MAX_ZONES_SHIFT) here to get enough bits.
  */
-#define NODEZONE_SHIFT (BITS_PER_LONG - MAX_NODES_SHIFT - MAX_ZONES_SHIFT)
+#define NODEZONE_SHIFT (sizeof(page_flags_t)*8 - MAX_NODES_SHIFT - MAX_ZONES_SHIFT)
 #define NODEZONE(node, zone)	((node << ZONES_SHIFT) | zone)
 
 static inline unsigned long page_zonenum(struct page *page)
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/mmzone.h	Wed Mar 17 19:29:09 2004
@@ -316,7 +316,7 @@
 
 #include <asm/mmzone.h>
 
-#if BITS_PER_LONG == 32
+#if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED)
 /*
  * with 32 bit page->flags field, we reserve 8 bits for node/zone info.
  * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes.
diff -Nru a/include/linux/moduleparam.h b/include/linux/moduleparam.h
--- a/include/linux/moduleparam.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/moduleparam.h	Wed Mar 17 19:29:09 2004
@@ -126,12 +126,15 @@
 #define param_check_invbool(name, p) __param_check(name, p, int)
 
 /* Comma-separated array: num is set to number they actually specified. */
-#define module_param_array(name, type, num, perm)			\
+#define module_param_array_named(name, array, type, num, perm)		\
 	static struct kparam_array __param_arr_##name			\
-	= { ARRAY_SIZE(name), &num, param_set_##type, param_get_##type,	\
-	    sizeof(name[0]), name };					\
+	= { ARRAY_SIZE(array), &num, param_set_##type, param_get_##type,\
+	    sizeof(array[0]), array };					\
 	module_param_call(name, param_array_set, param_array_get, 	\
 			  &__param_arr_##name, perm)
+
+#define module_param_array(name, type, num, perm)		\
+	module_param_array_named(name, name, type, num, perm)
 
 extern int param_array_set(const char *val, struct kernel_param *kp);
 extern int param_array_get(char *buffer, struct kernel_param *kp);
diff -Nru a/include/linux/netpoll.h b/include/linux/netpoll.h
--- a/include/linux/netpoll.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/netpoll.h	Wed Mar 17 19:29:09 2004
@@ -9,7 +9,6 @@
 
 #include <linux/netdevice.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/list.h>
 
 struct netpoll;
diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h
--- a/include/linux/page-flags.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/page-flags.h	Wed Mar 17 19:29:09 2004
@@ -80,9 +80,6 @@
 /*
  * Global page accounting.  One instance per CPU.  Only unsigned longs are
  * allowed.
- *
- * NOTE: if this structure is changed then mm/page_alloc.c and
- * arch/s390/appldata/appldata_mem.c must be updated accordingly
  */
 struct page_state {
 	unsigned long nr_dirty;		/* Dirty writeable pages */
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/pci_ids.h	Wed Mar 17 19:29:09 2004
@@ -342,6 +342,8 @@
 #define PCI_DEVICE_ID_ATI_RS300_133	0x5831
 #define PCI_DEVICE_ID_ATI_RS300_166	0x5832
 #define PCI_DEVICE_ID_ATI_RS300_200	0x5833
+/* ATI IXP Chipset */
+#define PCI_DEVICE_ID_ATI_IXP_IDE	0x4349
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C592	0x0005
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h	Wed Mar 17 19:29:10 2004
+++ b/include/linux/proc_fs.h	Wed Mar 17 19:29:10 2004
@@ -141,10 +141,6 @@
 	return;
 }
 #endif /* CONFIG_PROC_DEVICETREE */
-/*
- * proc_rtas.c
- */
-extern void proc_rtas_init(void);
 
 extern struct proc_dir_entry *proc_symlink(const char *,
 		struct proc_dir_entry *, const char *);
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h	Wed Mar 17 19:29:10 2004
+++ b/include/linux/reiserfs_fs.h	Wed Mar 17 19:29:10 2004
@@ -1335,7 +1335,8 @@
 #define fs_generation(s) (REISERFS_SB(s)->s_generation_counter)
 #define get_generation(s) atomic_read (&fs_generation(s))
 #define FILESYSTEM_CHANGED_TB(tb)  (get_generation((tb)->tb_sb) != (tb)->fs_gen)
-#define fs_changed(gen,s) (gen != get_generation (s))
+#define __fs_changed(gen,s) (gen != get_generation (s))
+#define fs_changed(gen,s) ({cond_resched(); __fs_changed(gen, s);})
 
 
 /***************************************************************************/
diff -Nru a/include/linux/rmap-locking.h b/include/linux/rmap-locking.h
--- a/include/linux/rmap-locking.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/rmap-locking.h	Wed Mar 17 19:29:09 2004
@@ -10,8 +10,8 @@
 struct pte_chain;
 extern kmem_cache_t *pte_chain_cache;
 
-#define pte_chain_lock(page)	bit_spin_lock(PG_chainlock, &page->flags)
-#define pte_chain_unlock(page)	bit_spin_unlock(PG_chainlock, &page->flags)
+#define pte_chain_lock(page)	bit_spin_lock(PG_chainlock, (unsigned long *)&page->flags)
+#define pte_chain_unlock(page)	bit_spin_unlock(PG_chainlock, (unsigned long *)&page->flags)
 
 struct pte_chain *pte_chain_alloc(int gfp_flags);
 void __pte_chain_free(struct pte_chain *pte_chain);
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/sched.h	Wed Mar 17 19:29:09 2004
@@ -560,13 +560,9 @@
  */
 extern struct exec_domain	default_exec_domain;
 
-#ifndef INIT_THREAD_SIZE
-# define INIT_THREAD_SIZE	2048*sizeof(long)
-#endif
-
 union thread_union {
 	struct thread_info thread_info;
-	unsigned long stack[INIT_THREAD_SIZE/sizeof(long)];
+	unsigned long stack[THREAD_SIZE/sizeof(long)];
 };
 
 #ifndef __HAVE_ARCH_KSTACK_END
diff -Nru a/include/linux/serio.h b/include/linux/serio.h
--- a/include/linux/serio.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/serio.h	Wed Mar 17 19:29:09 2004
@@ -117,6 +117,7 @@
 #define SERIO_MZ	0x05
 #define SERIO_MZP	0x06
 #define SERIO_MZPP	0x07
+#define SERIO_VSXXXAA	0x08
 #define SERIO_SUNKBD	0x10
 #define SERIO_WARRIOR	0x18
 #define SERIO_SPACEORB	0x19
@@ -134,6 +135,7 @@
 #define SERIO_HIL	0x25
 #define SERIO_SNES232	0x26
 #define SERIO_SEMTECH	0x27
+#define SERIO_LKKBD	0x28
 
 #define SERIO_ID	0xff00UL
 #define SERIO_EXTRA	0xff0000UL
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/usb.h	Wed Mar 17 19:29:09 2004
@@ -72,14 +72,11 @@
 
 /**
  * struct usb_interface - what usb device drivers talk to
- * @altsetting: array of interface descriptors, one for each alternate
+ * @altsetting: array of interface structures, one for each alternate
  * 	setting that may be selected.  Each one includes a set of
- * 	endpoint configurations and will be in numberic order,
- * 	0..num_altsetting.
+ * 	endpoint configurations.  They will be in no particular order.
  * @num_altsetting: number of altsettings defined.
- * @act_altsetting: index of current altsetting.  this number is always
- *	less than num_altsetting.  after the device is configured, each
- *	interface uses its default setting of zero.
+ * @cur_altsetting: the current altsetting.
  * @driver: the USB driver that is bound to this interface.
  * @minor: the minor number assigned to this interface, if this
  *	interface is bound to a driver that uses the USB major number.
@@ -89,6 +86,8 @@
  *	number from the USB core by calling usb_register_dev().
  * @dev: driver model's view of this device
  * @class_dev: driver model's class view of this device.
+ * @released: wait for the interface to be released when changing
+ *	configurations.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -102,26 +101,33 @@
  * calls such as dev_get_drvdata() on the dev member of this structure.
  *
  * Each interface may have alternate settings.  The initial configuration
- * of a device sets the first of these, but the device driver can change
+ * of a device sets altsetting 0, but the device driver can change
  * that setting using usb_set_interface().  Alternate settings are often
  * used to control the the use of periodic endpoints, such as by having
  * different endpoints use different amounts of reserved USB bandwidth.
  * All standards-conformant USB devices that use isochronous endpoints
  * will use them in non-default settings.
+ *
+ * The USB specification says that alternate setting numbers must run from
+ * 0 to one less than the total number of alternate settings.  But some
+ * devices manage to mess this up, and the structures aren't necessarily
+ * stored in numerical order anyhow.  Use usb_altnum_to_altsetting() to
+ * look up an alternate setting in the altsetting array based on its number.
  */
 struct usb_interface {
-	/* array of alternate settings for this interface.
-	 * these will be in numeric order, 0..num_altsettting
-	 */
+	/* array of alternate settings for this interface,
+	 * stored in no particular order */
 	struct usb_host_interface *altsetting;
 
-	unsigned act_altsetting;	/* active alternate setting */
+	struct usb_host_interface *cur_altsetting;	/* the currently
+					 * active alternate setting */
 	unsigned num_altsetting;	/* number of alternate settings */
 
 	struct usb_driver *driver;	/* driver */
 	int minor;			/* minor number this interface is bound to */
 	struct device dev;		/* interface specific device info */
 	struct class_device *class_dev;
+	struct completion *released;	/* wait for release */
 };
 #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define	interface_to_usbdev(intf) \
@@ -140,19 +146,43 @@
 /* this maximum is arbitrary */
 #define USB_MAXINTERFACES	32
 
-/* USB_DT_CONFIG: Configuration descriptor information.
- *
- * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
- * descriptor type is different.  Highspeed-capable devices can look
- * different depending on what speed they're currently running.  Only
- * devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG.
+/**
+ * struct usb_host_config - representation of a device's configuration
+ * @desc: the device's configuration descriptor.
+ * @interface: array of usb_interface structures, one for each interface
+ *	in the configuration.  The number of interfaces is stored in
+ *	desc.bNumInterfaces.
+ * @extra: pointer to buffer containing all extra descriptors associated
+ *	with this configuration (those preceding the first interface
+ *	descriptor).
+ * @extralen: length of the extra descriptors buffer.
+ *
+ * USB devices may have multiple configurations, but only one can be active
+ * at any time.  Each encapsulates a different operational environment;
+ * for example, a dual-speed device would have separate configurations for
+ * full-speed and high-speed operation.  The number of configurations
+ * available is stored in the device descriptor as bNumConfigurations.
+ *
+ * A configuration can contain multiple interfaces.  Each corresponds to
+ * a different function of the USB device, and all are available whenever
+ * the configuration is active.  The USB standard says that interfaces
+ * are supposed to be numbered from 0 to desc.bNumInterfaces-1, but a lot
+ * of devices get this wrong.  In addition, the interface array is not
+ * guaranteed to be sorted in numerical order.  Use usb_ifnum_to_if() to
+ * look up an interface entry based on its number.
+ *
+ * Device drivers should not attempt to activate configurations.  The choice
+ * of which configuration to install is a policy decision based on such
+ * considerations as available power, functionality provided, and the user's
+ * desires (expressed through hotplug scripts).  However, drivers can call
+ * usb_reset_configuration() to reinitialize the current configuration and
+ * all its interfaces.
  */
 struct usb_host_config {
 	struct usb_config_descriptor	desc;
 
-	/* the interfaces associated with this configuration
-	 * these will be in numeric order, 0..desc.bNumInterfaces
-	 */
+	/* the interfaces associated with this configuration,
+	 * stored in no particular order */
 	struct usb_interface *interface[USB_MAXINTERFACES];
 
 	unsigned char *extra;   /* Extra descriptors */
@@ -294,8 +324,12 @@
 const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 					 const struct usb_device_id *id);
 
-extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor);
-extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
+extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
+		int minor);
+extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev,
+		unsigned ifnum);
+extern struct usb_host_interface *usb_altnum_to_altsetting(
+		struct usb_interface *intf, unsigned int altnum);
 
 
 /**
@@ -461,8 +495,8 @@
  * @minor_base: the start of the minor range for this driver.
  *
  * This structure is used for the usb_register_dev() and
- * usb_unregister_dev() functions, to consolodate a number of the
- * paramaters used for them.
+ * usb_unregister_dev() functions, to consolidate a number of the
+ * parameters used for them.
  */
 struct usb_class_driver {
 	char *name;
@@ -520,7 +554,7 @@
  * @urb_list: For use by current owner of the URB.
  * @pipe: Holds endpoint number, direction, type, and more.
  *	Create these values with the eight macros available;
- *	usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl"
+ *	usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
  *	(control), "bulk", "int" (interrupt), or "iso" (isochronous).
  *	For example usb_sndbulkpipe() or usb_rcvintpipe().  Endpoint
  *	numbers range from zero to fifteen.  Note that "in" endpoint two
@@ -539,8 +573,8 @@
  * 	the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP
  *	is set).  This buffer must be suitable for DMA; allocate it with
  *	kmalloc() or equivalent.  For transfers to "in" endpoints, contents
- *	of this buffer will be modified.  This buffer is used for data
- *	phases of control transfers.
+ *	of this buffer will be modified.  This buffer is used for the data
+ *	stage of control transfers.
  * @transfer_dma: When transfer_flags includes URB_NO_TRANSFER_DMA_MAP,
  *	the device driver is saying that it provided this DMA address,
  *	which the host controller driver should use in preference to the
@@ -563,8 +597,7 @@
  *	device driver has provided this DMA address for the setup packet.
  *	The host controller driver should use this in preference to
  *	setup_packet.
- * @start_frame: Returns the initial frame for interrupt or isochronous
- *	transfers.
+ * @start_frame: Returns the initial frame for isochronous transfers.
  * @number_of_packets: Lists the number of ISO transfer buffers.
  * @interval: Specifies the polling interval for interrupt or isochronous
  *	transfers.  The units are frames (milliseconds) for for full and low
@@ -632,13 +665,14 @@
  * Interrupt UBS must provide an interval, saying how often (in milliseconds
  * or, for highspeed devices, 125 microsecond units)
  * to poll for transfers.  After the URB has been submitted, the interval
- * and start_frame fields reflect how the transfer was actually scheduled.
+ * field reflects how the transfer was actually scheduled.
  * The polling interval may be more frequent than requested.
  * For example, some controllers have a maximum interval of 32 microseconds,
  * while others support intervals of up to 1024 microseconds.
  * Isochronous URBs also have transfer intervals.  (Note that for isochronous
  * endpoints, as well as high speed interrupt endpoints, the encoding of
- * the transfer interval in the endpoint descriptor is logarithmic.)
+ * the transfer interval in the endpoint descriptor is logarithmic.
+ * Device drivers must convert that value to linear units themselves.)
  *
  * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling
  * the host controller to schedule the transfer as soon as bandwidth
@@ -671,8 +705,9 @@
  * The context field is normally used to link URBs back to the relevant
  * driver or request state.
  *
- * When completion callback is invoked for non-isochronous URBs, the
- * actual_length field tells how many bytes were transferred.
+ * When the completion callback is invoked for non-isochronous URBs, the
+ * actual_length field tells how many bytes were transferred.  This field
+ * is updated even when the URB terminated with an error or was unlinked.
  *
  * ISO transfer status is reported in the status and actual_length fields
  * of the iso_frame_desc array, and the number of errors is reported in
@@ -699,9 +734,9 @@
 	int actual_length;		/* (return) actual transfer length */
 	unsigned char *setup_packet;	/* (in) setup packet (control only) */
 	dma_addr_t setup_dma;		/* (in) dma addr for setup_packet */
-	int start_frame;		/* (modify) start frame (INT/ISO) */
+	int start_frame;		/* (modify) start frame (ISO) */
 	int number_of_packets;		/* (in) number of ISO packets */
-	int interval;			/* (in) transfer interval (INT/ISO) */
+	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 */
diff -Nru a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
--- a/include/linux/usb_gadget.h	Wed Mar 17 19:29:09 2004
+++ b/include/linux/usb_gadget.h	Wed Mar 17 19:29:09 2004
@@ -465,6 +465,8 @@
  * 	driver setup() requests
  * @ep_list: List of other endpoints supported by the device.
  * @speed: Speed of current connection to USB host.
+ * @is_dualspeed: True if the controller supports both high and full speed
+ *	operation.  If it does, the gadget driver must also support both.
  * @name: Identifies the controller hardware type.  Used in diagnostics
  * 	and sometimes configuration.
  * @dev: Driver model state for this abstract device.
@@ -488,6 +490,7 @@
 	struct usb_ep			*ep0;
 	struct list_head		ep_list;	/* of usb_ep */
 	enum usb_device_speed		speed;
+	unsigned			is_dualspeed:1;
 	const char			*name;
 	struct device			dev;
 };
@@ -690,7 +693,7 @@
 /**
  * struct usb_string - wraps a C string and its USB id
  * @id:the (nonzero) ID for this string
- * @s:the string, in ISO-8859/1 characters
+ * @s:the string, in UTF-8 encoding
  *
  * If you're using usb_gadget_get_string(), use this to wrap a string
  * together with its ID.
@@ -716,6 +719,17 @@
 /* put descriptor for string with that id into buf (buflen >= 256) */
 int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf);
 
+/*-------------------------------------------------------------------------*/
+
+/* utility to simplify managing config descriptors */
+
+/* write vector of descriptors into buffer */
+int usb_descriptor_fillbuf(void *, unsigned,
+		const struct usb_descriptor_header **);
+
+/* build config descriptor from single descriptor vector */
+int usb_gadget_config_buf(const struct usb_config_descriptor *config,
+	void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
 
 #endif  /* __KERNEL__ */
 
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Wed Mar 17 19:29:09 2004
+++ b/init/main.c	Wed Mar 17 19:29:09 2004
@@ -156,8 +156,11 @@
 	p = &__setup_start;
 	do {
 		int n = strlen(p->str);
-		if (!strncmp(line,p->str,n)) {
-			if (p->setup_func(line+n))
+		if (!strncmp(line, p->str, n)) {
+			if (!p->setup_func) {
+				printk(KERN_WARNING "Parameter %s is obsolete, ignored\n", p->str);
+				return 1;
+			} else if (p->setup_func(line + n))
 				return 1;
 		}
 		p++;
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	Wed Mar 17 19:29:09 2004
+++ b/ipc/shm.c	Wed Mar 17 19:29:09 2004
@@ -656,7 +656,10 @@
 			if (shmflg & SHM_RND)
 				addr &= ~(SHMLBA-1);	   /* round down */
 			else
-				return -EINVAL;
+#ifndef __ARCH_FORCE_SHMLBA
+				if (addr & ~PAGE_MASK)
+#endif
+					return -EINVAL;
 		}
 		flags = MAP_SHARED | MAP_FIXED;
 	} else {
@@ -759,6 +762,21 @@
 
 	down_write(&mm->mmap_sem);
 
+	/*
+	 * This function tries to be smart and unmap shm segments that
+	 * were modified by partial mlock or munmap calls:
+	 * - It first determines the size of the shm segment that should be
+	 *   unmapped: It searches for a vma that is backed by shm and that
+	 *   started at address shmaddr. It records it's size and then unmaps
+	 *   it.
+	 * - Then it unmaps all shm vmas that started at shmaddr and that
+	 *   are within the initially determined size.
+	 * Errors from do_munmap are ignored: the function only fails if
+	 * it's called with invalid parameters or if it's called to unmap
+	 * a part of a vma. Both calls in this function are for full vmas,
+	 * the parameters are directly copied from the vma itself and always
+	 * valid - therefore do_munmap cannot fail. (famous last words?)
+	 */
 	/*
 	 * If it had been mremap()'d, the starting address would not
 	 * match the usual checks anyway. So assume all vma's are
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	Wed Mar 17 19:29:10 2004
+++ b/kernel/exit.c	Wed Mar 17 19:29:10 2004
@@ -1146,7 +1146,8 @@
 	return retval;
 }
 
-#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
+#if !defined(__alpha__) && !defined(__ia64__) && \
+    !defined(__arm__) && !defined(__s390__)
 
 /*
  * sys_waitpid() remains for compatibility. waitpid() should be
diff -Nru a/kernel/kthread.c b/kernel/kthread.c
--- a/kernel/kthread.c	Wed Mar 17 19:29:10 2004
+++ b/kernel/kthread.c	Wed Mar 17 19:29:10 2004
@@ -10,6 +10,7 @@
 #include <linux/completion.h>
 #include <linux/err.h>
 #include <linux/unistd.h>
+#include <linux/file.h>
 #include <asm/semaphore.h>
 
 struct kthread_create_info
@@ -41,6 +42,21 @@
 	return (kthread_stop_info.k == current);
 }
 
+
+static void kthread_exit_files(void)
+{
+	struct fs_struct *fs;
+	struct task_struct *tsk = current;
+
+	exit_fs(tsk);		/* current->fs->count--; */
+	fs = init_task.fs;
+	tsk->fs = fs;
+	atomic_inc(&fs->count);
+ 	exit_files(tsk);
+	current->files = init_task.files;
+	atomic_inc(&tsk->files->count);
+}
+
 static int kthread(void *_create)
 {
 	struct kthread_create_info *create = _create;
@@ -49,6 +65,8 @@
 	sigset_t blocked;
 	int ret = -EINTR;
 	cpumask_t mask = CPU_MASK_ALL;
+
+	kthread_exit_files();
 
 	/* Copy data: it's on keventd's stack */
 	threadfn = create->threadfn;
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Wed Mar 17 19:29:10 2004
+++ b/kernel/module.c	Wed Mar 17 19:29:10 2004
@@ -1243,7 +1243,15 @@
 		mod->symtab[i].st_info
 			= elf_type(&mod->symtab[i], sechdrs, secstrings, mod);
 }
-#endif
+#else
+static inline void add_kallsyms(struct module *mod,
+				Elf_Shdr *sechdrs,
+				unsigned int symindex,
+				unsigned int strindex,
+				const char *secstrings)
+{
+}
+#endif /* CONFIG_KALLSYMS */
 
 /* Allocate and load the module: note that size of section 0 is always
    zero, and we rely on this for optional sections. */
@@ -1516,13 +1524,11 @@
 	percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
 		       sechdrs[pcpuindex].sh_size);
 
+	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
+
 	err = module_finalize(hdr, sechdrs, mod);
 	if (err < 0)
 		goto cleanup;
-
-#ifdef CONFIG_KALLSYMS
-	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
-#endif
 
 	mod->args = args;
 	if (obsparmindex) {
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Wed Mar 17 19:29:10 2004
+++ b/kernel/sched.c	Wed Mar 17 19:29:10 2004
@@ -594,28 +594,21 @@
 {
 	unsigned long flags;
 	runqueue_t *rq;
+	int preempted;
 
 repeat:
-	preempt_disable();
-	rq = task_rq(p);
-	if (unlikely(task_running(rq, p))) {
-		cpu_relax();
-		/*
-		 * enable/disable preemption just to make this
-		 * a preemption point - we are busy-waiting
-		 * anyway.
-		 */
-		preempt_enable();
-		goto repeat;
-	}
 	rq = task_rq_lock(p, &flags);
-	if (unlikely(task_running(rq, p))) {
+	/* Must be off runqueue entirely, not preempted. */
+	if (unlikely(p->array)) {
+		/* If it's preempted, we yield.  It could be a while. */
+		preempted = !task_running(rq, p);
 		task_rq_unlock(rq, &flags);
-		preempt_enable();
+		cpu_relax();
+		if (preempted)
+			yield();
 		goto repeat;
 	}
 	task_rq_unlock(rq, &flags);
-	preempt_enable();
 }
 
 /***
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	Wed Mar 17 19:29:09 2004
+++ b/kernel/signal.c	Wed Mar 17 19:29:09 2004
@@ -2482,7 +2482,8 @@
 #endif /* __sparc__ */
 #endif
 
-#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
+#if !defined(__alpha__) && !defined(__ia64__) && \
+    !defined(__arm__) && !defined(__s390__)
 /*
  * For backwards compatibility.  Functionality superseded by sigprocmask.
  */
diff -Nru a/kernel/workqueue.c b/kernel/workqueue.c
--- a/kernel/workqueue.c	Wed Mar 17 19:29:10 2004
+++ b/kernel/workqueue.c	Wed Mar 17 19:29:10 2004
@@ -47,6 +47,7 @@
 	struct workqueue_struct *wq;
 	task_t *thread;
 
+	int run_depth;		/* Detect run_workqueue() recursion depth */
 } ____cacheline_aligned;
 
 /*
@@ -129,6 +130,13 @@
 	 * done.
 	 */
 	spin_lock_irqsave(&cwq->lock, flags);
+	cwq->run_depth++;
+	if (cwq->run_depth > 3) {
+		/* morton gets to eat his hat */
+		printk("%s: recursion depth exceeded: %d\n",
+			__FUNCTION__, cwq->run_depth);
+		dump_stack();
+	}
 	while (!list_empty(&cwq->worklist)) {
 		struct work_struct *work = list_entry(cwq->worklist.next,
 						struct work_struct, entry);
@@ -146,6 +154,7 @@
 		cwq->remove_sequence++;
 		wake_up(&cwq->work_done);
 	}
+	cwq->run_depth--;
 	spin_unlock_irqrestore(&cwq->lock, flags);
 }
 
@@ -218,6 +227,14 @@
 			continue;
 		cwq = wq->cpu_wq + cpu;
 
+		if (cwq->thread == current) {
+			/*
+			 * Probably keventd trying to flush its own queue.
+			 * So simply run it by hand rather than deadlocking.
+			 */
+			run_workqueue(cwq);
+			continue;
+		}
 		spin_lock_irq(&cwq->lock);
 		sequence_needed = cwq->insert_sequence;
 
@@ -267,6 +284,7 @@
 	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
 	if (!wq)
 		return NULL;
+	memset(wq, 0, sizeof(*wq));
 
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 		if (!cpu_online(cpu))
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Wed Mar 17 19:29:09 2004
+++ b/mm/filemap.c	Wed Mar 17 19:29:09 2004
@@ -574,7 +574,7 @@
 
 /*
  * This is a generic file read routine, and uses the
- * inode->i_op->readpage() function for the actual low-level
+ * mapping->a_ops->readpage() function for the actual low-level
  * stuff.
  *
  * This is really ugly. But the goto's actually try to clarify some
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	Wed Mar 17 19:29:09 2004
+++ b/mm/page_alloc.c	Wed Mar 17 19:29:09 2004
@@ -73,7 +73,7 @@
 {
 	printk("Bad page state at %s (in process '%s', page %p)\n", function, current->comm, page);
 	printk("flags:0x%08lx mapping:%p mapped:%d count:%d\n",
-		page->flags, page->mapping,
+		(unsigned long)page->flags, page->mapping,
 		page_mapped(page), page_count(page));
 	printk("Backtrace:\n");
 	dump_stack();
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	Wed Mar 17 19:29:10 2004
+++ b/mm/rmap.c	Wed Mar 17 19:29:10 2004
@@ -118,7 +118,7 @@
 	int referenced = 0;
 
 	if (page_test_and_clear_young(page))
-		mark_page_accessed(page);
+		referenced++;
 
 	if (TestClearPageReferenced(page))
 		referenced++;
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Wed Mar 17 19:29:10 2004
+++ b/mm/slab.c	Wed Mar 17 19:29:10 2004
@@ -914,7 +914,7 @@
 		printk("\n");
 	}
 	realobj = (char*)objp+obj_dbghead(cachep);
-	size = cachep->objsize;
+	size = obj_reallen(cachep);
 	for (i=0; i<size && lines;i+=16, lines--) {
 		int limit;
 		limit = 16;
@@ -2885,7 +2885,8 @@
 #endif
 
 	page = virt_to_page((void*)addr);
-	printk("struct page at %p, flags %lxh.\n", page, page->flags);
+	printk("struct page at %p, flags %08lx\n",
+			page, (unsigned long)page->flags);
 	if (PageSlab(page)) {
 		kmem_cache_t *c;
 		struct slab *s;
diff -Nru a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
--- a/net/ipv4/ipvs/ip_vs_ctl.c	Wed Mar 17 19:29:10 2004
+++ b/net/ipv4/ipvs/ip_vs_ctl.c	Wed Mar 17 19:29:10 2004
@@ -1384,95 +1384,223 @@
 /*
  *	IPVS sysctl table (under the /proc/sys/net/ipv4/vs/)
  */
-struct ip_vs_sysctl_table {
-	struct ctl_table_header *sysctl_header;
-	ctl_table vs_vars[NET_IPV4_VS_LAST];
-	ctl_table vs_dir[2];
-	ctl_table ipv4_dir[2];
-	ctl_table root_dir[2];
-};
 
-static struct ip_vs_sysctl_table ipv4_vs_table = {
-	NULL,
-	{{NET_IPV4_VS_AMEMTHRESH, "amemthresh",
-	  &sysctl_ip_vs_amemthresh, sizeof(int), 0644, NULL,
-	  &proc_dointvec},
+static struct ctl_table vs_vars[] = {
+	{
+		.ctl_name	= NET_IPV4_VS_AMEMTHRESH,
+		.procname	= "amemthresh",
+		.data		= &sysctl_ip_vs_amemthresh,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 #ifdef CONFIG_IP_VS_DEBUG
-	 {NET_IPV4_VS_DEBUG_LEVEL, "debug_level",
-	  &sysctl_ip_vs_debug_level, sizeof(int), 0644, NULL,
-	  &proc_dointvec},
+	{
+		.ctl_name	= NET_IPV4_VS_DEBUG_LEVEL,
+		.procname	= "debug_level",
+		.data		= &sysctl_ip_vs_debug_level,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 #endif
-	 {NET_IPV4_VS_AMDROPRATE, "am_droprate",
-	  &sysctl_ip_vs_am_droprate, sizeof(int), 0644, NULL,
-	  &proc_dointvec},
-	 {NET_IPV4_VS_DROP_ENTRY, "drop_entry",
-	  &sysctl_ip_vs_drop_entry, sizeof(int), 0644, NULL,
-	  &proc_do_defense_mode},
-	 {NET_IPV4_VS_DROP_PACKET, "drop_packet",
-	  &sysctl_ip_vs_drop_packet, sizeof(int), 0644, NULL,
-	  &proc_do_defense_mode},
-	 {NET_IPV4_VS_SECURE_TCP, "secure_tcp",
-	  &sysctl_ip_vs_secure_tcp, sizeof(int), 0644, NULL,
-	  &proc_do_defense_mode},
+	{
+		.ctl_name	= NET_IPV4_VS_AMDROPRATE,
+		.procname	= "am_droprate",
+		.data		= &sysctl_ip_vs_am_droprate,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_DROP_ENTRY,
+		.procname	= "drop_entry",
+		.data		= &sysctl_ip_vs_drop_entry,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_do_defense_mode,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_DROP_PACKET,
+		.procname	= "drop_packet",
+		.data		= &sysctl_ip_vs_drop_packet,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_do_defense_mode,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_SECURE_TCP,
+		.procname	= "secure_tcp",
+		.data		= &sysctl_ip_vs_secure_tcp,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_do_defense_mode,
+	},
 #if 0
-	 {NET_IPV4_VS_TO_ES, "timeout_established",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_SS, "timeout_synsent",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_SYN_SENT],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_SR, "timeout_synrecv",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_SYN_RECV],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_FW, "timeout_finwait",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_FIN_WAIT],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_TW, "timeout_timewait",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_TIME_WAIT],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_CL, "timeout_close",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_CW, "timeout_closewait",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE_WAIT],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_LA, "timeout_lastack",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_LAST_ACK],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_LI, "timeout_listen",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_LISTEN],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_SA, "timeout_synack",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_SYNACK],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_UDP, "timeout_udp",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_UDP],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {NET_IPV4_VS_TO_ICMP, "timeout_icmp",
-	  &vs_timeout_table_dos.timeout[IP_VS_S_ICMP],
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_ES,
+		.procname	= "timeout_established",
+	  	.data	= &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_SS,
+		.procname	= "timeout_synsent",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_SYN_SENT],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_SR,
+		.procname	= "timeout_synrecv",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_SYN_RECV],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_FW,
+		.procname	= "timeout_finwait",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_FIN_WAIT],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_TW,
+		.procname	= "timeout_timewait",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_TIME_WAIT],
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_CL,
+		.procname	= "timeout_close",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_CW,
+		.procname	= "timeout_closewait",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE_WAIT],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_LA,
+		.procname	= "timeout_lastack",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_LAST_ACK],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_LI,
+		.procname	= "timeout_listen",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_LISTEN],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_SA,
+		.procname	= "timeout_synack",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_SYNACK],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_UDP,
+		.procname	= "timeout_udp",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_UDP],
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_TO_ICMP,
+		.procname	= "timeout_icmp",
+		.data	= &vs_timeout_table_dos.timeout[IP_VS_S_ICMP],
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
 #endif
-	 {NET_IPV4_VS_CACHE_BYPASS, "cache_bypass",
-	  &sysctl_ip_vs_cache_bypass, sizeof(int), 0644, NULL,
-	  &proc_dointvec},
-	 {NET_IPV4_VS_EXPIRE_NODEST_CONN, "expire_nodest_conn",
-	  &sysctl_ip_vs_expire_nodest_conn, sizeof(int), 0644, NULL,
-	  &proc_dointvec},
-	 {NET_IPV4_VS_SYNC_THRESHOLD, "sync_threshold",
-	  &sysctl_ip_vs_sync_threshold, sizeof(sysctl_ip_vs_sync_threshold),
-	  0644, NULL, &proc_do_sync_threshold},
-	 {NET_IPV4_VS_NAT_ICMP_SEND, "nat_icmp_send",
-	  &sysctl_ip_vs_nat_icmp_send, sizeof(int), 0644, NULL,
-	  &proc_dointvec},
-	 {0}},
-	{{NET_IPV4_VS, "vs", NULL, 0, 0555, ipv4_vs_table.vs_vars},
-	 {0}},
-	{{NET_IPV4, "ipv4", NULL, 0, 0555, ipv4_vs_table.vs_dir},
-	 {0}},
-	{{CTL_NET, "net", NULL, 0, 0555, ipv4_vs_table.ipv4_dir},
-	 {0}}
+	{
+		.ctl_name	= NET_IPV4_VS_CACHE_BYPASS,
+		.procname	= "cache_bypass",
+		.data		= &sysctl_ip_vs_cache_bypass,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_EXPIRE_NODEST_CONN,
+		.procname	= "expire_nodest_conn",
+		.data		= &sysctl_ip_vs_expire_nodest_conn,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_SYNC_THRESHOLD,
+		.procname	= "sync_threshold",
+		.data		= &sysctl_ip_vs_sync_threshold,
+		.maxlen		= sizeof(sysctl_ip_vs_sync_threshold),
+		.mode		= 0644,
+		.proc_handler	= &proc_do_sync_threshold,
+	},
+	{
+		.ctl_name	= NET_IPV4_VS_NAT_ICMP_SEND,
+		.procname	= "nat_icmp_send",
+		.data		= &sysctl_ip_vs_nat_icmp_send,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table vs_table[] = {
+	{
+		.ctl_name	= NET_IPV4_VS,
+		.procname	= "vs",
+		.mode		= 0555,
+		.child		= vs_vars
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table ipv4_table[] = {
+	{
+		.ctl_name	= NET_IPV4,
+		.procname	= "ipv4",
+		.mode		= 0555,
+		.child		= vs_table,
+	},
+	{ .ctl_name = 0 }
 };
 
+static ctl_table vs_root_table[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.mode		= 0555,
+		.child		= ipv4_table,
+	},
+	{ .ctl_name = 0 }
+};
+
+static struct ctl_table_header * sysctl_header;
+
 #ifdef CONFIG_PROC_FS
 
 struct ip_vs_iter {
@@ -2184,9 +2312,13 @@
 
 
 static struct nf_sockopt_ops ip_vs_sockopts = {
-	{ NULL, NULL }, PF_INET,
-	IP_VS_BASE_CTL, IP_VS_SO_SET_MAX+1, do_ip_vs_set_ctl,
-	IP_VS_BASE_CTL, IP_VS_SO_GET_MAX+1, do_ip_vs_get_ctl
+	.pf		= PF_INET,
+	.set_optmin	= IP_VS_BASE_CTL,
+	.set_optmax	= IP_VS_SO_SET_MAX+1,
+	.set		= do_ip_vs_set_ctl,
+	.get_optmin	= IP_VS_BASE_CTL,
+	.get_optmax	= IP_VS_SO_GET_MAX+1,
+	.get		= do_ip_vs_get_ctl,
 };
 
 
@@ -2206,8 +2338,7 @@
 	proc_net_fops_create("ip_vs", 0, &ip_vs_info_fops);
 	proc_net_fops_create("ip_vs_stats",0, &ip_vs_stats_fops);
 
-	ipv4_vs_table.sysctl_header =
-		register_sysctl_table(ipv4_vs_table.root_dir, 0);
+	sysctl_header = register_sysctl_table(vs_root_table, 0);
 
 	/* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++)  {
@@ -2239,7 +2370,7 @@
 	ip_vs_trash_cleanup();
 	del_timer_sync(&defense_timer);
 	ip_vs_kill_estimator(&ip_vs_stats);
-	unregister_sysctl_table(ipv4_vs_table.sysctl_header);
+	unregister_sysctl_table(sysctl_header);
 	proc_net_remove("ip_vs_stats");
 	proc_net_remove("ip_vs");
 	nf_unregister_sockopt(&ip_vs_sockopts);
diff -Nru a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c
--- a/net/ipv4/ipvs/ip_vs_lblc.c	Wed Mar 17 19:29:10 2004
+++ b/net/ipv4/ipvs/ip_vs_lblc.c	Wed Mar 17 19:29:10 2004
@@ -108,29 +108,50 @@
 /*
  *      IPVS LBLC sysctl table
  */
-struct ip_vs_lblc_sysctl_table {
-	struct ctl_table_header *sysctl_header;
-	ctl_table vs_vars[2];
-	ctl_table vs_dir[2];
-	ctl_table ipv4_dir[2];
-	ctl_table root_dir[2];
+
+static ctl_table vs_vars_table[] = {
+	{
+		.ctl_name	= NET_IPV4_VS_LBLC_EXPIRE,
+		.procname	= "lblc_expiration",
+		.data		= &sysctl_ip_vs_lblc_expiration,
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table vs_table[] = {
+	{
+		.ctl_name	= NET_IPV4_VS,
+		.procname	= "vs",
+		.mode		= 0555, 
+		.child		= vs_vars_table
+	},
+	{ .ctl_name = 0 }
 };
 
+static ctl_table ipv4_table[] = {
+	{
+		.ctl_name	= NET_IPV4,
+		.procname	= "ipv4", 
+		.mode		= 0555,
+		.child		= vs_table
+	},
+	{ .ctl_name = 0 }
+};
 
-static struct ip_vs_lblc_sysctl_table lblc_sysctl_table = {
-	NULL,
-	{{NET_IPV4_VS_LBLC_EXPIRE, "lblc_expiration",
-	  &sysctl_ip_vs_lblc_expiration,
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {0}},
-	{{NET_IPV4_VS, "vs", NULL, 0, 0555, lblc_sysctl_table.vs_vars},
-	 {0}},
-	{{NET_IPV4, "ipv4", NULL, 0, 0555, lblc_sysctl_table.vs_dir},
-	 {0}},
-	{{CTL_NET, "net", NULL, 0, 0555, lblc_sysctl_table.ipv4_dir},
-	 {0}}
+static ctl_table lblc_root_table[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net", 
+		.mode		= 0555, 
+		.child		= ipv4_table
+	},
+	{ .ctl_name = 0 }
 };
 
+static struct ctl_table_header * sysctl_header;
 
 /*
  *      new/free a ip_vs_lblc_entry, which is a mapping of a destionation
@@ -586,15 +607,14 @@
 static int __init ip_vs_lblc_init(void)
 {
 	INIT_LIST_HEAD(&ip_vs_lblc_scheduler.n_list);
-	lblc_sysctl_table.sysctl_header =
-		register_sysctl_table(lblc_sysctl_table.root_dir, 0);
+	sysctl_header = register_sysctl_table(lblc_root_table, 0);
 	return register_ip_vs_scheduler(&ip_vs_lblc_scheduler);
 }
 
 
 static void __exit ip_vs_lblc_cleanup(void)
 {
-	unregister_sysctl_table(lblc_sysctl_table.sysctl_header);
+	unregister_sysctl_table(sysctl_header);
 	unregister_ip_vs_scheduler(&ip_vs_lblc_scheduler);
 }
 
diff -Nru a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c
--- a/net/ipv4/ipvs/ip_vs_lblcr.c	Wed Mar 17 19:29:10 2004
+++ b/net/ipv4/ipvs/ip_vs_lblcr.c	Wed Mar 17 19:29:10 2004
@@ -297,29 +297,50 @@
 /*
  *      IPVS LBLCR sysctl table
  */
-struct ip_vs_lblcr_sysctl_table {
-	struct ctl_table_header *sysctl_header;
-	ctl_table vs_vars[2];
-	ctl_table vs_dir[2];
-	ctl_table ipv4_dir[2];
-	ctl_table root_dir[2];
+
+static ctl_table vs_vars_table[] = {
+	{
+		.ctl_name	= NET_IPV4_VS_LBLCR_EXPIRE,
+		.procname	= "lblcr_expiration",
+		.data		= &sysctl_ip_vs_lblcr_expiration,
+		.maxlen		= sizeof(int),
+		.mode		= 0644, 
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table vs_table[] = {
+	{
+		.ctl_name	= NET_IPV4_VS,
+		.procname	= "vs",
+		.mode		= 0555,
+		.child		= vs_vars_table
+	},
+	{ .ctl_name = 0 }
 };
 
+static ctl_table ipv4_table[] = {
+	{
+		.ctl_name	= NET_IPV4,
+		.procname	= "ipv4", 
+		.mode		= 0555,
+		.child		= vs_table
+	},
+	{ .ctl_name = 0 }
+};
 
-static struct ip_vs_lblcr_sysctl_table lblcr_sysctl_table = {
-	NULL,
-	{{NET_IPV4_VS_LBLCR_EXPIRE, "lblcr_expiration",
-	  &sysctl_ip_vs_lblcr_expiration,
-	  sizeof(int), 0644, NULL, &proc_dointvec_jiffies},
-	 {0}},
-	{{NET_IPV4_VS, "vs", NULL, 0, 0555, lblcr_sysctl_table.vs_vars},
-	 {0}},
-	{{NET_IPV4, "ipv4", NULL, 0, 0555, lblcr_sysctl_table.vs_dir},
-	 {0}},
-	{{CTL_NET, "net", NULL, 0, 0555, lblcr_sysctl_table.ipv4_dir},
-	 {0}}
+static ctl_table lblcr_root_table[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net", 
+		.mode		= 0555, 
+		.child		= ipv4_table
+	},
+	{ .ctl_name = 0 }
 };
 
+static struct ctl_table_header * sysctl_header;
 
 /*
  *      new/free a ip_vs_lblcr_entry, which is a mapping of a destination
@@ -844,8 +865,7 @@
 static int __init ip_vs_lblcr_init(void)
 {
 	INIT_LIST_HEAD(&ip_vs_lblcr_scheduler.n_list);
-	lblcr_sysctl_table.sysctl_header =
-		register_sysctl_table(lblcr_sysctl_table.root_dir, 0);
+	sysctl_header = register_sysctl_table(lblcr_root_table, 0);
 #ifdef CONFIG_IP_VS_LBLCR_DEBUG
 	proc_net_create("ip_vs_lblcr", 0, ip_vs_lblcr_getinfo);
 #endif
@@ -858,7 +878,7 @@
 #ifdef CONFIG_IP_VS_LBLCR_DEBUG
 	proc_net_remove("ip_vs_lblcr");
 #endif
-	unregister_sysctl_table(lblcr_sysctl_table.sysctl_header);
+	unregister_sysctl_table(sysctl_header);
 	unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
 }
 
diff -Nru a/scripts/Makefile b/scripts/Makefile
--- a/scripts/Makefile	Wed Mar 17 19:29:09 2004
+++ b/scripts/Makefile	Wed Mar 17 19:29:09 2004
@@ -2,14 +2,10 @@
 # scripts contains sources for various helper programs used throughout
 # the kernel for the build process.
 # ---------------------------------------------------------------------------
-# fix-dep: 	 Used to generate dependency information during build process
-# split-include: Divide all config symbols up in a number of files in
-#                include/config/...
 # docproc: 	 Preprocess .tmpl file in order to generate .sgml docs
 # conmakehash:	 Create arrays for initializing the kernel console tables
 
-host-progs	:= fixdep split-include conmakehash docproc kallsyms modpost \
-		   mk_elfconfig pnmtologo bin2c
+host-progs	:= conmakehash kallsyms modpost mk_elfconfig pnmtologo bin2c
 always		:= $(host-progs) empty.o
 
 modpost-objs	:= modpost.o file2alias.o sumversion.o
@@ -17,10 +13,7 @@
 subdir-$(CONFIG_MODVERSIONS)	+= genksyms
 
 # Let clean descend into subdirs
-subdir-	+= lxdialog kconfig
-
-# fixdep is needed to compile other host programs
-$(addprefix $(obj)/,$(filter-out fixdep,$(always)) $(subdir-y)): $(obj)/fixdep
+subdir-	+= basic lxdialog kconfig
 
 # dependencies on generated files need to be listed explicitly
 
diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build
--- a/scripts/Makefile.build	Wed Mar 17 19:29:10 2004
+++ b/scripts/Makefile.build	Wed Mar 17 19:29:10 2004
@@ -162,7 +162,7 @@
 	$(if $($(quiet)cmd_cc_o_c),echo '  $($(quiet)cmd_cc_o_c)';)	  \
 	$(cmd_cc_o_c);							  \
 	$(cmd_modversions)						  \
-	scripts/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp;  \
+	scripts/basic/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp;  \
 	rm -f $(depfile);						  \
 	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
 endef
diff -Nru a/scripts/Makefile.lib b/scripts/Makefile.lib
--- a/scripts/Makefile.lib	Wed Mar 17 19:29:09 2004
+++ b/scripts/Makefile.lib	Wed Mar 17 19:29:09 2004
@@ -249,7 +249,7 @@
 	@set -e; \
 	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
 	$(cmd_$(1)); \
-	scripts/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
+	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
 	rm -f $(depfile); \
 	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
 
diff -Nru a/scripts/basic/Makefile b/scripts/basic/Makefile
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/basic/Makefile	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,18 @@
+###
+# Makefile.basic list the most basic programs used during the build process.
+# The programs listed herein is what is needed to do the basic stuff,
+# such as splitting .config and fix dependency file.
+# This initial step is needed to avoid files to be recompiled
+# when kernel configuration changes (which is what happens when
+# .config is included by main Makefile.
+# ---------------------------------------------------------------------------
+# fixdep: 	 Used to generate dependency information during build process
+# split-include: Divide all config symbols up in a number of files in
+#                include/config/...
+# docproc:	 Used in Documentation/docbook
+
+host-progs	:= fixdep split-include docproc
+always		:= $(host-progs)
+
+# fixdep is needed to compile other host programs
+$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff -Nru a/scripts/basic/docproc.c b/scripts/basic/docproc.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/basic/docproc.c	Wed Mar 17 19:29:09 2004
@@ -0,0 +1,387 @@
+/*
+ *	docproc is a simple preprocessor for the template files
+ *      used as placeholders for the kernel internal documentation.
+ *	docproc is used for documentation-frontend and
+ *      dependency-generator.
+ *	The two usages have in common that they require
+ *	some knowledge of the .tmpl syntax, therefore they
+ *	are kept together.
+ *
+ *	documentation-frontend
+ *		Scans the template file and call kernel-doc for
+ *		all occurrences of ![EIF]file
+ *		Beforehand each referenced file are scanned for
+ *		any exported sympols "EXPORT_SYMBOL()" statements.
+ *		This is used to create proper -function and
+ *		-nofunction arguments in calls to kernel-doc.
+ *		Usage: docproc doc file.tmpl
+ *
+ *	dependency-generator:
+ *		Scans the template file and list all files
+ *		referenced in a format recognized by make.
+ *		Usage:	docproc depend file.tmpl
+ *		Writes dependency information to stdout
+ *		in the following format:
+ *		file.tmpl src.c	src2.c
+ *		The filenames are obtained from the following constructs:
+ *		!Efilename
+ *		!Ifilename
+ *		!Dfilename
+ *		!Ffilename
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+/* exitstatus is used to keep track of any failing calls to kernel-doc,
+ * but execution continues. */
+int exitstatus = 0;
+
+typedef void DFL(char *);
+DFL *defaultline;
+
+typedef void FILEONLY(char * file);
+FILEONLY *internalfunctions;
+FILEONLY *externalfunctions;
+FILEONLY *symbolsonly;
+
+typedef void FILELINE(char * file, char * line);
+FILELINE * singlefunctions;
+FILELINE * entity_system;
+
+#define MAXLINESZ     2048
+#define MAXFILES      250
+#define KERNELDOCPATH "scripts/"
+#define KERNELDOC     "kernel-doc"
+#define DOCBOOK       "-docbook"
+#define FUNCTION      "-function"
+#define NOFUNCTION    "-nofunction"
+
+void usage (void)
+{
+	fprintf(stderr, "Usage: docproc {doc|depend} file\n");
+	fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
+	fprintf(stderr, "doc: frontend when generating kernel documentation\n");
+	fprintf(stderr, "depend: generate list of files referenced within file\n");
+}
+
+/*
+ * Execute kernel-doc with parameters givin in svec
+ */
+void exec_kernel_doc(char **svec)
+{
+	pid_t pid;
+	int ret;
+	/* Make sure output generated so far are flushed */
+	fflush(stdout);
+	switch(pid=fork()) {
+		case -1:
+			perror("fork");
+			exit(1);
+		case  0:
+			execvp(KERNELDOCPATH KERNELDOC, svec);
+			perror("exec " KERNELDOCPATH KERNELDOC);
+			exit(1);
+		default:
+			waitpid(pid, &ret ,0);
+	}
+	if (WIFEXITED(ret))
+		exitstatus |= WEXITSTATUS(ret);
+	else
+		exitstatus = 0xff;
+}
+
+/* Types used to create list of all exported symbols in a number of files */
+struct symbols
+{
+	char *name;
+};
+
+struct symfile
+{
+	char *filename;
+	struct symbols *symbollist;
+	int symbolcnt;
+};
+
+struct symfile symfilelist[MAXFILES];
+int symfilecnt = 0;
+
+void add_new_symbol(struct symfile *sym, char * symname)
+{
+	sym->symbollist =
+          realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
+	sym->symbollist[sym->symbolcnt++].name = strdup(symname);
+}
+
+/* Add a filename to the list */
+struct symfile * add_new_file(char * filename)
+{
+	symfilelist[symfilecnt++].filename = strdup(filename);
+	return &symfilelist[symfilecnt - 1];
+}
+/* Check if file already are present in the list */
+struct symfile * filename_exist(char * filename)
+{
+	int i;
+	for (i=0; i < symfilecnt; i++)
+		if (strcmp(symfilelist[i].filename, filename) == 0)
+			return &symfilelist[i];
+	return NULL;
+}
+
+/*
+ * List all files referenced within the template file.
+ * Files are separated by tabs.
+ */
+void adddep(char * file)		   { printf("\t%s", file); }
+void adddep2(char * file, char * line)     { line = line; adddep(file); }
+void noaction(char * line)		   { line = line; }
+void noaction2(char * file, char * line)   { file = file; line = line; }
+
+/* Echo the line without further action */
+void printline(char * line)               { printf("%s", line); }
+
+/*
+ * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL
+ * in filename.
+ * All symbols located are stored in symfilelist.
+ */
+void find_export_symbols(char * filename)
+{
+	FILE * fp;
+	struct symfile *sym;
+	char line[MAXLINESZ];
+	if (filename_exist(filename) == NULL) {
+		sym = add_new_file(filename);
+		fp = fopen(filename, "r");
+		if (fp == NULL)
+		{
+			fprintf(stderr, "docproc: ");
+			perror(filename);
+		}
+		while(fgets(line, MAXLINESZ, fp)) {
+			char *p;
+			char *e;
+			if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
+                            ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
+				/* Skip EXPORT_SYMBOL{_GPL} */
+				while (isalnum(*p) || *p == '_')
+					p++;
+				/* Remove paranteses and additional ws */
+				while (isspace(*p))
+					p++;
+				if (*p != '(')
+					continue; /* Syntax error? */
+				else
+					p++;
+				while (isspace(*p))
+					p++;
+				e = p;
+				while (isalnum(*e) || *e == '_')
+					e++;
+				*e = '\0';
+				add_new_symbol(sym, p);
+			}
+		}
+		fclose(fp);
+	}
+}
+
+/*
+ * Document all external or internal functions in a file.
+ * Call kernel-doc with following parameters:
+ * kernel-doc -docbook -nofunction function_name1 filename
+ * function names are obtained from all the the src files
+ * by find_export_symbols.
+ * intfunc uses -nofunction
+ * extfunc uses -function
+ */
+void docfunctions(char * filename, char * type)
+{
+	int i,j;
+	int symcnt = 0;
+	int idx = 0;
+	char **vec;
+
+	for (i=0; i <= symfilecnt; i++)
+		symcnt += symfilelist[i].symbolcnt;
+	vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*));
+	if (vec == NULL) {
+		perror("docproc: ");
+		exit(1);
+	}
+	vec[idx++] = KERNELDOC;
+	vec[idx++] = DOCBOOK;
+	for (i=0; i < symfilecnt; i++) {
+		struct symfile * sym = &symfilelist[i];
+		for (j=0; j < sym->symbolcnt; j++) {
+			vec[idx++]     = type;
+			vec[idx++] = sym->symbollist[j].name;
+		}
+	}
+	vec[idx++]     = filename;
+	vec[idx] = NULL;
+	printf("<!-- %s -->\n", filename);
+	exec_kernel_doc(vec);
+	fflush(stdout);
+	free(vec);
+}
+void intfunc(char * filename) {	docfunctions(filename, NOFUNCTION); }
+void extfunc(char * filename) { docfunctions(filename, FUNCTION);   }
+
+/*
+ * Document spåecific function(s) in a file.
+ * Call kernel-doc with the following parameters:
+ * kernel-doc -docbook -function function1 [-function function2]
+ */
+void singfunc(char * filename, char * line)
+{
+	char *vec[200]; /* Enough for specific functions */
+        int i, idx = 0;
+        int startofsym = 1;
+	vec[idx++] = KERNELDOC;
+	vec[idx++] = DOCBOOK;
+
+        /* Split line up in individual parameters preceeded by FUNCTION */
+        for (i=0; line[i]; i++) {
+                if (isspace(line[i])) {
+                        line[i] = '\0';
+                        startofsym = 1;
+                        continue;
+                }
+                if (startofsym) {
+                        startofsym = 0;
+                        vec[idx++] = FUNCTION;
+                        vec[idx++] = &line[i];
+                }
+        }
+	vec[idx++] = filename;
+	vec[idx] = NULL;
+	exec_kernel_doc(vec);
+}
+
+/*
+ * Parse file, calling action specific functions for:
+ * 1) Lines containing !E
+ * 2) Lines containing !I
+ * 3) Lines containing !D
+ * 4) Lines containing !F
+ * 5) Default lines - lines not matching the above
+ */
+void parse_file(FILE *infile)
+{
+	char line[MAXLINESZ];
+	char * s;
+	while(fgets(line, MAXLINESZ, infile)) {
+		if (line[0] == '!') {
+			s = line + 2;
+			switch (line[1]) {
+				case 'E':
+					while (*s && !isspace(*s)) s++;
+					*s = '\0';
+					externalfunctions(line+2);
+					break;
+				case 'I':
+					while (*s && !isspace(*s)) s++;
+					*s = '\0';
+					internalfunctions(line+2);
+					break;
+				case 'D':
+					while (*s && !isspace(*s)) s++;
+                                        *s = '\0';
+                                        symbolsonly(line+2);
+                                        break;
+				case 'F':
+					/* filename */
+					while (*s && !isspace(*s)) s++;
+					*s++ = '\0';
+                                        /* function names */
+					while (isspace(*s))
+						s++;
+					singlefunctions(line +2, s);
+					break;
+				default:
+					defaultline(line);
+			}
+		}
+		else {
+			defaultline(line);
+		}
+	}
+	fflush(stdout);
+}
+
+
+int main(int argc, char *argv[])
+{
+	FILE * infile;
+	if (argc != 3) {
+		usage();
+		exit(1);
+	}
+	/* Open file, exit on error */
+	infile = fopen(argv[2], "r");
+        if (infile == NULL) {
+                fprintf(stderr, "docproc: ");
+                perror(argv[2]);
+                exit(2);
+        }
+
+	if (strcmp("doc", argv[1]) == 0)
+	{
+		/* Need to do this in two passes.
+		 * First pass is used to collect all symbols exported
+		 * in the various files.
+		 * Second pass generate the documentation.
+		 * This is required because function are declared
+		 * and exported in different files :-((
+		 */
+		/* Collect symbols */
+		defaultline       = noaction;
+		internalfunctions = find_export_symbols;
+		externalfunctions = find_export_symbols;
+		symbolsonly       = find_export_symbols;
+		singlefunctions   = noaction2;
+		parse_file(infile);
+
+		/* Rewind to start from beginning of file again */
+		fseek(infile, 0, SEEK_SET);
+		defaultline       = printline;
+		internalfunctions = intfunc;
+		externalfunctions = extfunc;
+		symbolsonly       = printline;
+		singlefunctions   = singfunc;
+
+		parse_file(infile);
+	}
+	else if (strcmp("depend", argv[1]) == 0)
+	{
+		/* Create first part of dependency chain
+		 * file.tmpl */
+		printf("%s\t", argv[2]);
+		defaultline       = noaction;
+		internalfunctions = adddep;
+		externalfunctions = adddep;
+		symbolsonly       = adddep;
+		singlefunctions   = adddep2;
+		parse_file(infile);
+		printf("\n");
+	}
+	else
+	{
+		fprintf(stderr, "Unknown option: %s\n", argv[1]);
+		exit(1);
+	}
+	fclose(infile);
+	fflush(stdout);
+	return exitstatus;
+}
+
diff -Nru a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/basic/fixdep.c	Wed Mar 17 19:29:09 2004
@@ -0,0 +1,381 @@
+/*
+ * "Optimize" a list of dependencies as spit out by gcc -MD
+ * for the kernel build
+ * ===========================================================================
+ *
+ * Author       Kai Germaschewski
+ * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ *
+ * Introduction:
+ *
+ * gcc produces a very nice and correct list of dependencies which
+ * tells make when to remake a file.
+ *
+ * To use this list as-is however has the drawback that virtually
+ * every file in the kernel includes <linux/config.h> which then again
+ * includes <linux/autoconf.h>
+ *
+ * If the user re-runs make *config, linux/autoconf.h will be
+ * regenerated.  make notices that and will rebuild every file which
+ * includes autoconf.h, i.e. basically all files. This is extremely
+ * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
+ *
+ * So we play the same trick that "mkdep" played before. We replace
+ * the dependency on linux/autoconf.h by a dependency on every config
+ * option which is mentioned in any of the listed prequisites.
+ *
+ * To be exact, split-include populates a tree in include/config/,
+ * e.g. include/config/his/driver.h, which contains the #define/#undef
+ * for the CONFIG_HIS_DRIVER option.
+ *
+ * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
+ * which depend on "include/linux/config/his/driver.h" will be rebuilt,
+ * so most likely only his driver ;-)
+ *
+ * The idea above dates, by the way, back to Michael E Chastain, AFAIK.
+ *
+ * So to get dependencies right, there two issues:
+ * o if any of the files the compiler read changed, we need to rebuild
+ * o if the command line given to the compile the file changed, we
+ *   better rebuild as well.
+ *
+ * The former is handled by using the -MD output, the later by saving
+ * the command line used to compile the old object and comparing it
+ * to the one we would now use.
+ *
+ * Again, also this idea is pretty old and has been discussed on
+ * kbuild-devel a long time ago. I don't have a sensibly working
+ * internet connection right now, so I rather don't mention names
+ * without double checking.
+ *
+ * This code here has been based partially based on mkdep.c, which
+ * says the following about its history:
+ *
+ *   Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
+ *   This is a C version of syncdep.pl by Werner Almesberger.
+ *
+ *
+ * It is invoked as
+ *
+ *   fixdep <depfile> <target> <cmdline>
+ *
+ * and will read the dependency file <depfile>
+ *
+ * The transformed dependency snipped is written to stdout.
+ *
+ * It first generates a line
+ *
+ *   cmd_<target> = <cmdline>
+ *
+ * and then basically copies the .<target>.d file to stdout, in the
+ * process filtering out the dependency on linux/autoconf.h and adding
+ * dependencies on include/config/my/option.h for every
+ * CONFIG_MY_OPTION encountered in any of the prequisites.
+ *
+ * It will also filter out all the dependencies on *.ver. We need
+ * to make sure that the generated version checksum are globally up
+ * to date before even starting the recursive build, so it's too late
+ * at this point anyway.
+ *
+ * The algorithm to grep for "CONFIG_..." is bit unusual, but should
+ * be fast ;-) We don't even try to really parse the header files, but
+ * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
+ * be picked up as well. It's not a problem with respect to
+ * correctness, since that can only give too many dependencies, thus
+ * we cannot miss a rebuild. Since people tend to not mention totally
+ * unrelated CONFIG_ options all over the place, it's not an
+ * efficiency problem either.
+ *
+ * (Note: it'd be easy to port over the complete mkdep state machine,
+ *  but I don't think the added complexity is worth it)
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <ctype.h>
+#include <netinet/in.h>
+
+#define INT_CONF ntohl(0x434f4e46)
+#define INT_ONFI ntohl(0x4f4e4649)
+#define INT_NFIG ntohl(0x4e464947)
+#define INT_FIG_ ntohl(0x4649475f)
+
+char *target;
+char *depfile;
+char *cmdline;
+
+void usage(void)
+
+{
+	fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
+	exit(1);
+}
+
+void print_cmdline(void)
+{
+	printf("cmd_%s := %s\n\n", target, cmdline);
+}
+
+char * str_config  = NULL;
+int    size_config = 0;
+int    len_config  = 0;
+
+/*
+ * Grow the configuration string to a desired length.
+ * Usually the first growth is plenty.
+ */
+void grow_config(int len)
+{
+	while (len_config + len > size_config) {
+		if (size_config == 0)
+			size_config = 2048;
+		str_config = realloc(str_config, size_config *= 2);
+		if (str_config == NULL)
+			{ perror("fixdep:malloc"); exit(1); }
+	}
+}
+
+
+
+/*
+ * Lookup a value in the configuration string.
+ */
+int is_defined_config(const char * name, int len)
+{
+	const char * pconfig;
+	const char * plast = str_config + len_config - len;
+	for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
+		if (pconfig[ -1] == '\n'
+		&&  pconfig[len] == '\n'
+		&&  !memcmp(pconfig, name, len))
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Add a new value to the configuration string.
+ */
+void define_config(const char * name, int len)
+{
+	grow_config(len + 1);
+
+	memcpy(str_config+len_config, name, len);
+	len_config += len;
+	str_config[len_config++] = '\n';
+}
+
+/*
+ * Clear the set of configuration strings.
+ */
+void clear_config(void)
+{
+	len_config = 0;
+	define_config("", 0);
+}
+
+/*
+ * Record the use of a CONFIG_* word.
+ */
+void use_config(char *m, int slen)
+{
+	char s[PATH_MAX];
+	char *p;
+
+	if (is_defined_config(m, slen))
+	    return;
+
+	define_config(m, slen);
+
+	memcpy(s, m, slen); s[slen] = 0;
+
+	for (p = s; p < s + slen; p++) {
+		if (*p == '_')
+			*p = '/';
+		else
+			*p = tolower((unsigned char)*p);
+	}
+	printf("    $(wildcard include/config/%s.h) \\\n", s);
+}
+
+void parse_config_file(char *map, size_t len)
+{
+	int *end = (int *) (map + len);
+	/* start at +1, so that p can never be < map */
+	int *m   = (int *) map + 1;
+	char *p, *q;
+
+	for (; m < end; m++) {
+		if (*m == INT_CONF) { p = (char *) m  ; goto conf; }
+		if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
+		if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
+		if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
+		continue;
+	conf:
+		if (p > map + len - 7)
+			continue;
+		if (memcmp(p, "CONFIG_", 7))
+			continue;
+		for (q = p + 7; q < map + len; q++) {
+			if (!(isalnum(*q) || *q == '_'))
+				goto found;
+		}
+		continue;
+
+	found:
+		use_config(p+7, q-p-7);
+	}
+}
+
+/* test is s ends in sub */
+int strrcmp(char *s, char *sub)
+{
+	int slen = strlen(s);
+	int sublen = strlen(sub);
+
+	if (sublen > slen)
+		return 1;
+
+	return memcmp(s + slen - sublen, sub, sublen);
+}
+
+void do_config_file(char *filename)
+{
+	struct stat st;
+	int fd;
+	void *map;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "fixdep: ");
+		perror(filename);
+		exit(2);
+	}
+	fstat(fd, &st);
+	if (st.st_size == 0) {
+		close(fd);
+		return;
+	}
+	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	if ((long) map == -1) {
+		perror("fixdep: mmap");
+		close(fd);
+		return;
+	}
+
+	parse_config_file(map, st.st_size);
+
+	munmap(map, st.st_size);
+
+	close(fd);
+}
+
+void parse_dep_file(void *map, size_t len)
+{
+	char *m = map;
+	char *end = m + len;
+	char *p;
+	char s[PATH_MAX];
+
+	p = strchr(m, ':');
+	if (!p) {
+		fprintf(stderr, "fixdep: parse error\n");
+		exit(1);
+	}
+	memcpy(s, m, p-m); s[p-m] = 0;
+	printf("deps_%s := \\\n", target);
+	m = p+1;
+
+	clear_config();
+
+	while (m < end) {
+		while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
+			m++;
+		p = m;
+		while (p < end && *p != ' ') p++;
+		if (p == end) {
+			do p--; while (!isalnum(*p));
+			p++;
+		}
+		memcpy(s, m, p-m); s[p-m] = 0;
+		if (strrcmp(s, "include/linux/autoconf.h") &&
+		    strrcmp(s, ".ver")) {
+			printf("  %s \\\n", s);
+			do_config_file(s);
+		}
+		m = p + 1;
+	}
+	printf("\n%s: $(deps_%s)\n\n", target, target);
+	printf("$(deps_%s):\n", target);
+}
+
+void print_deps(void)
+{
+	struct stat st;
+	int fd;
+	void *map;
+
+	fd = open(depfile, O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "fixdep: ");
+		perror(depfile);
+		exit(2);
+	}
+	fstat(fd, &st);
+	if (st.st_size == 0) {
+		fprintf(stderr,"fixdep: %s is empty\n",depfile);
+		close(fd);
+		return;
+	}
+	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	if ((long) map == -1) {
+		perror("fixdep: mmap");
+		close(fd);
+		return;
+	}
+
+	parse_dep_file(map, st.st_size);
+
+	munmap(map, st.st_size);
+
+	close(fd);
+}
+
+void traps(void)
+{
+	static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
+
+	if (*(int *)test != INT_CONF) {
+		fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
+			*(int *)test);
+		exit(2);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	traps();
+
+	if (argc != 4)
+		usage();
+
+	depfile = argv[1];
+	target = argv[2];
+	cmdline = argv[3];
+
+	print_cmdline();
+	print_deps();
+
+	return 0;
+}
diff -Nru a/scripts/basic/split-include.c b/scripts/basic/split-include.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/scripts/basic/split-include.c	Wed Mar 17 19:29:09 2004
@@ -0,0 +1,226 @@
+/*
+ * split-include.c
+ *
+ * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
+ * This is a C version of syncdep.pl by Werner Almesberger.
+ *
+ * This program takes autoconf.h as input and outputs a directory full
+ * of one-line include files, merging onto the old values.
+ *
+ * Think of the configuration options as key-value pairs.  Then there
+ * are five cases:
+ *
+ *    key      old value   new value   action
+ *
+ *    KEY-1    VALUE-1     VALUE-1     leave file alone
+ *    KEY-2    VALUE-2A    VALUE-2B    write VALUE-2B into file
+ *    KEY-3    -           VALUE-3     write VALUE-3  into file
+ *    KEY-4    VALUE-4     -           write an empty file
+ *    KEY-5    (empty)     -           leave old empty file alone
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ERROR_EXIT(strExit)						\
+    {									\
+	const int errnoSave = errno;					\
+	fprintf(stderr, "%s: ", str_my_name);				\
+	errno = errnoSave;						\
+	perror((strExit));						\
+	exit(1);							\
+    }
+
+
+
+int main(int argc, const char * argv [])
+{
+    const char * str_my_name;
+    const char * str_file_autoconf;
+    const char * str_dir_config;
+
+    FILE * fp_config;
+    FILE * fp_target;
+    FILE * fp_find;
+
+    int buffer_size;
+
+    char * line;
+    char * old_line;
+    char * list_target;
+    char * ptarget;
+
+    struct stat stat_buf;
+
+    /* Check arg count. */
+    if (argc != 3)
+    {
+	fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
+	exit(1);
+    }
+
+    str_my_name       = argv[0];
+    str_file_autoconf = argv[1];
+    str_dir_config    = argv[2];
+
+    /* Find a buffer size. */
+    if (stat(str_file_autoconf, &stat_buf) != 0)
+	ERROR_EXIT(str_file_autoconf);
+    buffer_size = 2 * stat_buf.st_size + 4096;
+
+    /* Allocate buffers. */
+    if ( (line        = malloc(buffer_size)) == NULL
+    ||   (old_line    = malloc(buffer_size)) == NULL
+    ||   (list_target = malloc(buffer_size)) == NULL )
+	ERROR_EXIT(str_file_autoconf);
+
+    /* Open autoconfig file. */
+    if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
+	ERROR_EXIT(str_file_autoconf);
+
+    /* Make output directory if needed. */
+    if (stat(str_dir_config, &stat_buf) != 0)
+    {
+	if (mkdir(str_dir_config, 0755) != 0)
+	    ERROR_EXIT(str_dir_config);
+    }
+
+    /* Change to output directory. */
+    if (chdir(str_dir_config) != 0)
+	ERROR_EXIT(str_dir_config);
+
+    /* Put initial separator into target list. */
+    ptarget = list_target;
+    *ptarget++ = '\n';
+
+    /* Read config lines. */
+    while (fgets(line, buffer_size, fp_config))
+    {
+	const char * str_config;
+	int is_same;
+	int itarget;
+
+	if (line[0] != '#')
+	    continue;
+	if ((str_config = strstr(line, "CONFIG_")) == NULL)
+	    continue;
+
+	/* Make the output file name. */
+	str_config += sizeof("CONFIG_") - 1;
+	for (itarget = 0; !isspace(str_config[itarget]); itarget++)
+	{
+	    int c = (unsigned char) str_config[itarget];
+	    if (isupper(c)) c = tolower(c);
+	    if (c == '_')   c = '/';
+	    ptarget[itarget] = c;
+	}
+	ptarget[itarget++] = '.';
+	ptarget[itarget++] = 'h';
+	ptarget[itarget++] = '\0';
+
+	/* Check for existing file. */
+	is_same = 0;
+	if ((fp_target = fopen(ptarget, "r")) != NULL)
+	{
+	    fgets(old_line, buffer_size, fp_target);
+	    if (fclose(fp_target) != 0)
+		ERROR_EXIT(ptarget);
+	    if (!strcmp(line, old_line))
+		is_same = 1;
+	}
+
+	if (!is_same)
+	{
+	    /* Auto-create directories. */
+	    int islash;
+	    for (islash = 0; islash < itarget; islash++)
+	    {
+		if (ptarget[islash] == '/')
+		{
+		    ptarget[islash] = '\0';
+		    if (stat(ptarget, &stat_buf) != 0
+		    &&  mkdir(ptarget, 0755)     != 0)
+			ERROR_EXIT( ptarget );
+		    ptarget[islash] = '/';
+		}
+	    }
+
+	    /* Write the file. */
+	    if ((fp_target = fopen(ptarget, "w" )) == NULL)
+		ERROR_EXIT(ptarget);
+	    fputs(line, fp_target);
+	    if (ferror(fp_target) || fclose(fp_target) != 0)
+		ERROR_EXIT(ptarget);
+	}
+
+	/* Update target list */
+	ptarget += itarget;
+	*(ptarget-1) = '\n';
+    }
+
+    /*
+     * Close autoconfig file.
+     * Terminate the target list.
+     */
+    if (fclose(fp_config) != 0)
+	ERROR_EXIT(str_file_autoconf);
+    *ptarget = '\0';
+
+    /*
+     * Fix up existing files which have no new value.
+     * This is Case 4 and Case 5.
+     *
+     * I re-read the tree and filter it against list_target.
+     * This is crude.  But it avoids data copies.  Also, list_target
+     * is compact and contiguous, so it easily fits into cache.
+     *
+     * Notice that list_target contains strings separated by \n,
+     * with a \n before the first string and after the last.
+     * fgets gives the incoming names a terminating \n.
+     * So by having an initial \n, strstr will find exact matches.
+     */
+
+    fp_find = popen("find * -type f -name \"*.h\" -print", "r");
+    if (fp_find == 0)
+	ERROR_EXIT( "find" );
+
+    line[0] = '\n';
+    while (fgets(line+1, buffer_size, fp_find))
+    {
+	if (strstr(list_target, line) == NULL)
+	{
+	    /*
+	     * This is an old file with no CONFIG_* flag in autoconf.h.
+	     */
+
+	    /* First strip the \n. */
+	    line[strlen(line)-1] = '\0';
+
+	    /* Grab size. */
+	    if (stat(line+1, &stat_buf) != 0)
+		ERROR_EXIT(line);
+
+	    /* If file is not empty, make it empty and give it a fresh date. */
+	    if (stat_buf.st_size != 0)
+	    {
+		if ((fp_target = fopen(line+1, "w")) == NULL)
+		    ERROR_EXIT(line);
+		if (fclose(fp_target) != 0)
+		    ERROR_EXIT(line);
+	    }
+	}
+    }
+
+    if (pclose(fp_find) != 0)
+	ERROR_EXIT("find");
+
+    return 0;
+}
diff -Nru a/scripts/docproc.c b/scripts/docproc.c
--- a/scripts/docproc.c	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,387 +0,0 @@
-/*
- *	docproc is a simple preprocessor for the template files
- *      used as placeholders for the kernel internal documentation.
- *	docproc is used for documentation-frontend and
- *      dependency-generator.
- *	The two usages have in common that they require
- *	some knowledge of the .tmpl syntax, therefore they
- *	are kept together.
- *
- *	documentation-frontend
- *		Scans the template file and call kernel-doc for
- *		all occurrences of ![EIF]file
- *		Beforehand each referenced file are scanned for
- *		any exported sympols "EXPORT_SYMBOL()" statements.
- *		This is used to create proper -function and
- *		-nofunction arguments in calls to kernel-doc.
- *		Usage: docproc doc file.tmpl
- *
- *	dependency-generator:
- *		Scans the template file and list all files
- *		referenced in a format recognized by make.
- *		Usage:	docproc depend file.tmpl
- *		Writes dependency information to stdout
- *		in the following format:
- *		file.tmpl src.c	src2.c
- *		The filenames are obtained from the following constructs:
- *		!Efilename
- *		!Ifilename
- *		!Dfilename
- *		!Ffilename
- *		
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-/* exitstatus is used to keep track of any failing calls to kernel-doc,
- * but execution continues. */
-int exitstatus = 0;
-
-typedef void DFL(char *);
-DFL *defaultline;
-
-typedef void FILEONLY(char * file);
-FILEONLY *internalfunctions;
-FILEONLY *externalfunctions;
-FILEONLY *symbolsonly;
-
-typedef void FILELINE(char * file, char * line);
-FILELINE * singlefunctions;
-FILELINE * entity_system;
-
-#define MAXLINESZ     2048
-#define MAXFILES      250
-#define KERNELDOCPATH "scripts/"
-#define KERNELDOC     "kernel-doc"
-#define DOCBOOK       "-docbook"
-#define FUNCTION      "-function"
-#define NOFUNCTION    "-nofunction"
-
-void usage (void)
-{
-	fprintf(stderr, "Usage: docproc {doc|depend} file\n");
-	fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
-	fprintf(stderr, "doc: frontend when generating kernel documentation\n");
-	fprintf(stderr, "depend: generate list of files referenced within file\n");
-}
-
-/*
- * Execute kernel-doc with parameters givin in svec
- */
-void exec_kernel_doc(char **svec)
-{
-	pid_t pid;
-	int ret;
-	/* Make sure output generated so far are flushed */
-	fflush(stdout);
-	switch(pid=fork()) {
-		case -1:
-			perror("fork");
-			exit(1);
-		case  0:
-			execvp(KERNELDOCPATH KERNELDOC, svec);
-			perror("exec " KERNELDOCPATH KERNELDOC);
-			exit(1);
-		default:
-			waitpid(pid, &ret ,0);
-	}
-	if (WIFEXITED(ret))
-		exitstatus |= WEXITSTATUS(ret);
-	else
-		exitstatus = 0xff;
-}
-
-/* Types used to create list of all exported symbols in a number of files */
-struct symbols
-{
-	char *name;
-};
-
-struct symfile
-{
-	char *filename;
-	struct symbols *symbollist;
-	int symbolcnt;
-};
-
-struct symfile symfilelist[MAXFILES];
-int symfilecnt = 0;
-
-void add_new_symbol(struct symfile *sym, char * symname)
-{
-	sym->symbollist =
-          realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *));
-	sym->symbollist[sym->symbolcnt++].name = strdup(symname);
-}
-
-/* Add a filename to the list */
-struct symfile * add_new_file(char * filename)
-{
-	symfilelist[symfilecnt++].filename = strdup(filename);
-	return &symfilelist[symfilecnt - 1];					
-}
-/* Check if file already are present in the list */
-struct symfile * filename_exist(char * filename)
-{
-	int i;
-	for (i=0; i < symfilecnt; i++)
-		if (strcmp(symfilelist[i].filename, filename) == 0)
-			return &symfilelist[i];
-	return NULL;
-}
-
-/*
- * List all files referenced within the template file.
- * Files are separated by tabs.
- */
-void adddep(char * file)		   { printf("\t%s", file); }
-void adddep2(char * file, char * line)     { line = line; adddep(file); }
-void noaction(char * line)		   { line = line; }
-void noaction2(char * file, char * line)   { file = file; line = line; }
-
-/* Echo the line without further action */
-void printline(char * line)               { printf("%s", line); }
-
-/* 
- * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL 
- * in filename.
- * All symbols located are stored in symfilelist.
- */
-void find_export_symbols(char * filename)
-{
-	FILE * fp;
-	struct symfile *sym;
-	char line[MAXLINESZ];
-	if (filename_exist(filename) == NULL) {
-		sym = add_new_file(filename);
-		fp = fopen(filename, "r");
-		if (fp == NULL)
-		{
-			fprintf(stderr, "docproc: ");
-			perror(filename);
-		}
-		while(fgets(line, MAXLINESZ, fp)) {
-			char *p;
-			char *e;
-			if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
-                            ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
-				/* Skip EXPORT_SYMBOL{_GPL} */
-				while (isalnum(*p) || *p == '_')
-					p++;
-				/* Remove paranteses and additional ws */
-				while (isspace(*p))
-					p++;
-				if (*p != '(')
-					continue; /* Syntax error? */
-				else
-					p++;
-				while (isspace(*p))
-					p++;
-				e = p;
-				while (isalnum(*e) || *e == '_')
-					e++;
-				*e = '\0';
-				add_new_symbol(sym, p);
-			}
-		}
-		fclose(fp);
-	}
-}
-
-/*
- * Document all external or internal functions in a file.
- * Call kernel-doc with following parameters:
- * kernel-doc -docbook -nofunction function_name1 filename
- * function names are obtained from all the the src files
- * by find_export_symbols.
- * intfunc uses -nofunction
- * extfunc uses -function
- */
-void docfunctions(char * filename, char * type)
-{
-	int i,j;
-	int symcnt = 0;
-	int idx = 0;
-	char **vec;
-	
-	for (i=0; i <= symfilecnt; i++)
-		symcnt += symfilelist[i].symbolcnt;
-	vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*));
-	if (vec == NULL) {
-		perror("docproc: ");
-		exit(1);
-	}
-	vec[idx++] = KERNELDOC;
-	vec[idx++] = DOCBOOK;
-	for (i=0; i < symfilecnt; i++) {
-		struct symfile * sym = &symfilelist[i];
-		for (j=0; j < sym->symbolcnt; j++) {
-			vec[idx++]     = type;
-			vec[idx++] = sym->symbollist[j].name;
-		}
-	}
-	vec[idx++]     = filename;
-	vec[idx] = NULL;
-	printf("<!-- %s -->\n", filename);
-	exec_kernel_doc(vec);
-	fflush(stdout);
-	free(vec);
-}
-void intfunc(char * filename) {	docfunctions(filename, NOFUNCTION); }
-void extfunc(char * filename) { docfunctions(filename, FUNCTION);   }
-
-/*
- * Document spåecific function(s) in a file.
- * Call kernel-doc with the following parameters:
- * kernel-doc -docbook -function function1 [-function function2]
- */
-void singfunc(char * filename, char * line)
-{
-	char *vec[200]; /* Enough for specific functions */
-        int i, idx = 0;
-        int startofsym = 1;
-	vec[idx++] = KERNELDOC;
-	vec[idx++] = DOCBOOK;
-
-        /* Split line up in individual parameters preceeded by FUNCTION */        
-        for (i=0; line[i]; i++) {
-                if (isspace(line[i])) {
-                        line[i] = '\0';
-                        startofsym = 1;
-                        continue;
-                }
-                if (startofsym) {
-                        startofsym = 0;
-                        vec[idx++] = FUNCTION;
-                        vec[idx++] = &line[i];
-                }
-        }
-	vec[idx++] = filename;
-	vec[idx] = NULL;
-	exec_kernel_doc(vec);
-}
-
-/*
- * Parse file, calling action specific functions for:
- * 1) Lines containing !E
- * 2) Lines containing !I
- * 3) Lines containing !D
- * 4) Lines containing !F
- * 5) Default lines - lines not matching the above
- */
-void parse_file(FILE *infile)
-{
-	char line[MAXLINESZ];
-	char * s;
-	while(fgets(line, MAXLINESZ, infile)) {
-		if (line[0] == '!') {
-			s = line + 2;
-			switch (line[1]) {
-				case 'E':
-					while (*s && !isspace(*s)) s++;
-					*s = '\0';
-					externalfunctions(line+2);
-					break;
-				case 'I':
-					while (*s && !isspace(*s)) s++;
-					*s = '\0';
-					internalfunctions(line+2);
-					break;
-				case 'D':
-					while (*s && !isspace(*s)) s++;
-                                        *s = '\0';
-                                        symbolsonly(line+2);
-                                        break;
-				case 'F':
-					/* filename */
-					while (*s && !isspace(*s)) s++;
-					*s++ = '\0';
-                                        /* function names */
-					while (isspace(*s))
-						s++;
-					singlefunctions(line +2, s);
-					break;
-				default:
-					defaultline(line);
-			}
-		}
-		else {
-			defaultline(line);
-		}
-	}
-	fflush(stdout);
-}
-		
-
-int main(int argc, char *argv[])
-{
-	FILE * infile;
-	if (argc != 3) {
-		usage();
-		exit(1);
-	}
-	/* Open file, exit on error */
-	infile = fopen(argv[2], "r");
-        if (infile == NULL) {
-                fprintf(stderr, "docproc: ");
-                perror(argv[2]);
-                exit(2);
-        }
-
-	if (strcmp("doc", argv[1]) == 0)
-	{
-		/* Need to do this in two passes.
-		 * First pass is used to collect all symbols exported
-		 * in the various files.
-		 * Second pass generate the documentation.
-		 * This is required because function are declared
-		 * and exported in different files :-((
-		 */
-		/* Collect symbols */
-		defaultline       = noaction;
-		internalfunctions = find_export_symbols;
-		externalfunctions = find_export_symbols;
-		symbolsonly       = find_export_symbols;
-		singlefunctions   = noaction2;
-		parse_file(infile);
-
-		/* Rewind to start from beginning of file again */
-		fseek(infile, 0, SEEK_SET);
-		defaultline       = printline;
-		internalfunctions = intfunc;
-		externalfunctions = extfunc;
-		symbolsonly       = printline;
-		singlefunctions   = singfunc;
-		
-		parse_file(infile);
-	}
-	else if (strcmp("depend", argv[1]) == 0)
-	{
-		/* Create first part of dependency chain
-		 * file.tmpl */
-		printf("%s\t", argv[2]);
-		defaultline       = noaction;
-		internalfunctions = adddep;
-		externalfunctions = adddep;
-		symbolsonly       = adddep;
-		singlefunctions   = adddep2;
-		parse_file(infile);
-		printf("\n");
-	}
-	else
-	{
-		fprintf(stderr, "Unknown option: %s\n", argv[1]);
-		exit(1);
-	}
-	fclose(infile);
-	fflush(stdout);
-	return exitstatus;
-}
-
diff -Nru a/scripts/fixdep.c b/scripts/fixdep.c
--- a/scripts/fixdep.c	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,381 +0,0 @@
-/*
- * "Optimize" a list of dependencies as spit out by gcc -MD 
- * for the kernel build
- * ===========================================================================
- *
- * Author       Kai Germaschewski
- * Copyright    2002 by Kai Germaschewski  <kai.germaschewski@gmx.de>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- *
- * Introduction:
- * 
- * gcc produces a very nice and correct list of dependencies which
- * tells make when to remake a file.
- *
- * To use this list as-is however has the drawback that virtually
- * every file in the kernel includes <linux/config.h> which then again
- * includes <linux/autoconf.h>
- *
- * If the user re-runs make *config, linux/autoconf.h will be
- * regenerated.  make notices that and will rebuild every file which
- * includes autoconf.h, i.e. basically all files. This is extremely
- * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
- * 
- * So we play the same trick that "mkdep" played before. We replace
- * the dependency on linux/autoconf.h by a dependency on every config
- * option which is mentioned in any of the listed prequisites.
- *  
- * To be exact, split-include populates a tree in include/config/,
- * e.g. include/config/his/driver.h, which contains the #define/#undef
- * for the CONFIG_HIS_DRIVER option.
- *
- * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
- * which depend on "include/linux/config/his/driver.h" will be rebuilt,
- * so most likely only his driver ;-) 
- *
- * The idea above dates, by the way, back to Michael E Chastain, AFAIK.
- * 
- * So to get dependencies right, there two issues:
- * o if any of the files the compiler read changed, we need to rebuild
- * o if the command line given to the compile the file changed, we
- *   better rebuild as well.
- *
- * The former is handled by using the -MD output, the later by saving
- * the command line used to compile the old object and comparing it
- * to the one we would now use.
- *
- * Again, also this idea is pretty old and has been discussed on
- * kbuild-devel a long time ago. I don't have a sensibly working
- * internet connection right now, so I rather don't mention names
- * without double checking.
- *
- * This code here has been based partially based on mkdep.c, which
- * says the following about its history:
- *
- *   Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
- *   This is a C version of syncdep.pl by Werner Almesberger.
- *
- *
- * It is invoked as
- *
- *   fixdep <depfile> <target> <cmdline>
- *
- * and will read the dependency file <depfile>
- *
- * The transformed dependency snipped is written to stdout.
- *
- * It first generates a line
- *
- *   cmd_<target> = <cmdline>
- *
- * and then basically copies the .<target>.d file to stdout, in the
- * process filtering out the dependency on linux/autoconf.h and adding
- * dependencies on include/config/my/option.h for every
- * CONFIG_MY_OPTION encountered in any of the prequisites.
- *
- * It will also filter out all the dependencies on *.ver. We need
- * to make sure that the generated version checksum are globally up
- * to date before even starting the recursive build, so it's too late
- * at this point anyway.
- *
- * The algorithm to grep for "CONFIG_..." is bit unusual, but should
- * be fast ;-) We don't even try to really parse the header files, but
- * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will
- * be picked up as well. It's not a problem with respect to
- * correctness, since that can only give too many dependencies, thus
- * we cannot miss a rebuild. Since people tend to not mention totally
- * unrelated CONFIG_ options all over the place, it's not an
- * efficiency problem either.
- * 
- * (Note: it'd be easy to port over the complete mkdep state machine,
- *  but I don't think the added complexity is worth it)
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-#include <ctype.h>
-#include <netinet/in.h>
-
-#define INT_CONF ntohl(0x434f4e46)
-#define INT_ONFI ntohl(0x4f4e4649)
-#define INT_NFIG ntohl(0x4e464947)
-#define INT_FIG_ ntohl(0x4649475f)
-
-char *target;
-char *depfile;
-char *cmdline;
-
-void usage(void)
-
-{
-	fprintf(stderr, "Usage: fixdep <depfile> <target> <cmdline>\n");
-	exit(1);
-}
-
-void print_cmdline(void)
-{
-	printf("cmd_%s := %s\n\n", target, cmdline);
-}
-
-char * str_config  = NULL;
-int    size_config = 0;
-int    len_config  = 0;
-
-/*
- * Grow the configuration string to a desired length.
- * Usually the first growth is plenty.
- */
-void grow_config(int len)
-{
-	while (len_config + len > size_config) {
-		if (size_config == 0)
-			size_config = 2048;
-		str_config = realloc(str_config, size_config *= 2);
-		if (str_config == NULL)
-			{ perror("fixdep:malloc"); exit(1); }
-	}
-}
-
-
-
-/*
- * Lookup a value in the configuration string.
- */
-int is_defined_config(const char * name, int len)
-{
-	const char * pconfig;
-	const char * plast = str_config + len_config - len;
-	for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) {
-		if (pconfig[ -1] == '\n'
-		&&  pconfig[len] == '\n'
-		&&  !memcmp(pconfig, name, len))
-			return 1;
-	}
-	return 0;
-}
-
-/*
- * Add a new value to the configuration string.
- */
-void define_config(const char * name, int len)
-{
-	grow_config(len + 1);
-
-	memcpy(str_config+len_config, name, len);
-	len_config += len;
-	str_config[len_config++] = '\n';
-}
-
-/*
- * Clear the set of configuration strings.
- */
-void clear_config(void)
-{
-	len_config = 0;
-	define_config("", 0);
-}
-
-/*
- * Record the use of a CONFIG_* word.
- */
-void use_config(char *m, int slen)
-{
-	char s[PATH_MAX];
-	char *p;
-
-	if (is_defined_config(m, slen))
-	    return;
-
-	define_config(m, slen);
-
-	memcpy(s, m, slen); s[slen] = 0;
-
-	for (p = s; p < s + slen; p++) {
-		if (*p == '_')
-			*p = '/';
-		else
-			*p = tolower((unsigned char)*p);
-	}
-	printf("    $(wildcard include/config/%s.h) \\\n", s);
-}
-
-void parse_config_file(char *map, size_t len)
-{
-	int *end = (int *) (map + len);
-	/* start at +1, so that p can never be < map */
-	int *m   = (int *) map + 1;
-	char *p, *q;
-
-	for (; m < end; m++) {
-		if (*m == INT_CONF) { p = (char *) m  ; goto conf; }
-		if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
-		if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
-		if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
-		continue;
-	conf:
-		if (p > map + len - 7)
-			continue;
-		if (memcmp(p, "CONFIG_", 7))
-			continue;
-		for (q = p + 7; q < map + len; q++) {
-			if (!(isalnum(*q) || *q == '_'))
-				goto found;
-		}
-		continue;
-
-	found: 
-		use_config(p+7, q-p-7);
-	}
-}
-
-/* test is s ends in sub */
-int strrcmp(char *s, char *sub)
-{
-	int slen = strlen(s);
-	int sublen = strlen(sub);
-  
-	if (sublen > slen)
-		return 1;
-	
-	return memcmp(s + slen - sublen, sub, sublen);
-}
-
-void do_config_file(char *filename)
-{
-	struct stat st;
-	int fd;
-	void *map;
-
-	fd = open(filename, O_RDONLY);
-	if (fd < 0) {
-		fprintf(stderr, "fixdep: ");
-		perror(filename);
-		exit(2);
-	}
-	fstat(fd, &st);
-	if (st.st_size == 0) {
-		close(fd);
-		return;
-	}
-	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-	if ((long) map == -1) {
-		perror("fixdep: mmap");
-		close(fd);
-		return;
-	}
-	
-	parse_config_file(map, st.st_size);
-
-	munmap(map, st.st_size);
-
-	close(fd);
-}
-
-void parse_dep_file(void *map, size_t len)
-{
-	char *m = map;
-	char *end = m + len;
-	char *p;
-	char s[PATH_MAX];
-
-	p = strchr(m, ':');
-	if (!p) {
-		fprintf(stderr, "fixdep: parse error\n");
-		exit(1);
-	}
-	memcpy(s, m, p-m); s[p-m] = 0;
-	printf("deps_%s := \\\n", target);
-	m = p+1;
-
-	clear_config();
-
-	while (m < end) {
-		while (m < end && (*m == ' ' || *m == '\\' || *m == '\n'))
-			m++;
-		p = m;
-		while (p < end && *p != ' ') p++;
-		if (p == end) {
-			do p--; while (!isalnum(*p));
-			p++;
-		}
-		memcpy(s, m, p-m); s[p-m] = 0;
-		if (strrcmp(s, "include/linux/autoconf.h") &&
-		    strrcmp(s, ".ver")) {
-			printf("  %s \\\n", s);
-			do_config_file(s);
-		}
-		m = p + 1;
-	}
-	printf("\n%s: $(deps_%s)\n\n", target, target);
-	printf("$(deps_%s):\n", target);
-}
-
-void print_deps(void)
-{
-	struct stat st;
-	int fd;
-	void *map;
-
-	fd = open(depfile, O_RDONLY);
-	if (fd < 0) {
-		fprintf(stderr, "fixdep: ");
-		perror(depfile);
-		exit(2);
-	}
-	fstat(fd, &st);
-	if (st.st_size == 0) {
-		fprintf(stderr,"fixdep: %s is empty\n",depfile);
-		close(fd);
-		return;
-	}
-	map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-	if ((long) map == -1) {
-		perror("fixdep: mmap");
-		close(fd);
-		return;
-	}
-	
-	parse_dep_file(map, st.st_size);
-
-	munmap(map, st.st_size);
-
-	close(fd);
-}
-
-void traps(void)
-{
-	static char test[] __attribute__((aligned(sizeof(int)))) = "CONF";
-
-	if (*(int *)test != INT_CONF) {
-		fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n",
-			*(int *)test);
-		exit(2);
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	traps();
-
-	if (argc != 4)
-		usage();
-		
-	depfile = argv[1];
-	target = argv[2];
-	cmdline = argv[3];
-
-	print_cmdline();
-	print_deps();
-
-	return 0;
-}
diff -Nru a/scripts/modpost.c b/scripts/modpost.c
--- a/scripts/modpost.c	Wed Mar 17 19:29:09 2004
+++ b/scripts/modpost.c	Wed Mar 17 19:29:09 2004
@@ -11,6 +11,7 @@
  * Usage: modpost vmlinux module1.o module2.o ...
  */
 
+#include <ctype.h>
 #include "modpost.h"
 
 /* Are we using CONFIG_MODVERSIONS? */
@@ -44,8 +45,6 @@
 	va_end(arglist);
 }
 
-#define NOFAIL(ptr)	do_nofail((ptr), __FILE__, __LINE__, #ptr)
-
 void *do_nofail(void *ptr, const char *file, int line, const char *expr)
 {
 	if (!ptr) {
@@ -63,21 +62,19 @@
 new_module(char *modname)
 {
 	struct module *mod;
-	char *p;
-	size_t len;
+	char *p, *s;
 	
 	mod = NOFAIL(malloc(sizeof(*mod)));
 	memset(mod, 0, sizeof(*mod));
 	p = NOFAIL(strdup(modname));
 
-	len = strlen(p);
-
 	/* strip trailing .o */
-	if (len > 2 && p[len-2] == '.' && p[len-1] == 'o')
-		p[len -2] = '\0';
+	if ((s = strrchr(p, '.')) != NULL)
+		if (strcmp(s, ".o") == 0)
+			*s = '\0';
 
 	/* add to list */
-	mod->name = NOFAIL(strdup(p));
+	mod->name = p;
 	mod->next = modules;
 	modules = mod;
 
@@ -207,6 +204,42 @@
 	if (map == MAP_FAILED)
 		return NULL;
 	return map;
+}
+
+/*
+   Return a copy of the next line in a mmap'ed file.
+   spaces in the beginning of the line is trimmed away.
+   Return a pointer to a static buffer.
+*/
+char*
+get_next_line(unsigned long *pos, void *file, unsigned long size)
+{
+	static char line[4096];
+	int skip = 1;
+	size_t len = 0;
+	char *p = (char *)file + *pos;
+	char *s = line;
+
+	for (; *pos < size ; (*pos)++)
+	{
+		if (skip && isspace(*p)) {
+			p++;
+			continue;
+		}
+		skip = 0;
+		if (*p != '\n' && (*pos < size)) {
+			len++;
+			*s++ = *p++;
+			if (len > 4095)
+				break; /* Too long, stop */
+		} else {
+			/* End of string */
+			*s = '\0';
+			return line;
+		}
+	}
+	/* End of buffer */
+	return NULL;
 }
 
 void
diff -Nru a/scripts/modpost.h b/scripts/modpost.h
--- a/scripts/modpost.h	Wed Mar 17 19:29:09 2004
+++ b/scripts/modpost.h	Wed Mar 17 19:29:09 2004
@@ -53,6 +53,9 @@
 
 #endif
 
+#define NOFAIL(ptr)   do_nofail((ptr), __FILE__, __LINE__, #ptr)
+void *do_nofail(void *ptr, const char *file, int line, const char *expr);
+
 struct buffer {
 	char *p;
 	int pos;
@@ -95,4 +98,5 @@
 			unsigned long modinfo_offset);
 
 void *grab_file(const char *filename, unsigned long *size);
+char* get_next_line(unsigned long *pos, void *file, unsigned long size);
 void release_file(void *file, unsigned long size);
diff -Nru a/scripts/split-include.c b/scripts/split-include.c
--- a/scripts/split-include.c	Wed Mar 17 19:29:09 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,226 +0,0 @@
-/*
- * split-include.c
- *
- * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
- * This is a C version of syncdep.pl by Werner Almesberger.
- *
- * This program takes autoconf.h as input and outputs a directory full
- * of one-line include files, merging onto the old values.
- *
- * Think of the configuration options as key-value pairs.  Then there
- * are five cases:
- *
- *    key      old value   new value   action
- *
- *    KEY-1    VALUE-1     VALUE-1     leave file alone
- *    KEY-2    VALUE-2A    VALUE-2B    write VALUE-2B into file
- *    KEY-3    -           VALUE-3     write VALUE-3  into file
- *    KEY-4    VALUE-4     -           write an empty file
- *    KEY-5    (empty)     -           leave old empty file alone
- */
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define ERROR_EXIT(strExit)						\
-    {									\
-	const int errnoSave = errno;					\
-	fprintf(stderr, "%s: ", str_my_name);				\
-	errno = errnoSave;						\
-	perror((strExit));						\
-	exit(1);							\
-    }
-
-
-
-int main(int argc, const char * argv [])
-{
-    const char * str_my_name;
-    const char * str_file_autoconf;
-    const char * str_dir_config;
-
-    FILE * fp_config;
-    FILE * fp_target;
-    FILE * fp_find;
-
-    int buffer_size;
-
-    char * line;
-    char * old_line;
-    char * list_target;
-    char * ptarget;
-
-    struct stat stat_buf;
-
-    /* Check arg count. */
-    if (argc != 3)
-    {
-	fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
-	exit(1);
-    }
-
-    str_my_name       = argv[0];
-    str_file_autoconf = argv[1];
-    str_dir_config    = argv[2];
-
-    /* Find a buffer size. */
-    if (stat(str_file_autoconf, &stat_buf) != 0)
-	ERROR_EXIT(str_file_autoconf);
-    buffer_size = 2 * stat_buf.st_size + 4096;
-
-    /* Allocate buffers. */
-    if ( (line        = malloc(buffer_size)) == NULL
-    ||   (old_line    = malloc(buffer_size)) == NULL
-    ||   (list_target = malloc(buffer_size)) == NULL )
-	ERROR_EXIT(str_file_autoconf);
-
-    /* Open autoconfig file. */
-    if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
-	ERROR_EXIT(str_file_autoconf);
-
-    /* Make output directory if needed. */
-    if (stat(str_dir_config, &stat_buf) != 0)
-    {
-	if (mkdir(str_dir_config, 0755) != 0)
-	    ERROR_EXIT(str_dir_config);
-    }
-
-    /* Change to output directory. */
-    if (chdir(str_dir_config) != 0)
-	ERROR_EXIT(str_dir_config);
-	
-    /* Put initial separator into target list. */
-    ptarget = list_target;
-    *ptarget++ = '\n';
-
-    /* Read config lines. */
-    while (fgets(line, buffer_size, fp_config))
-    {
-	const char * str_config;
-	int is_same;
-	int itarget;
-
-	if (line[0] != '#')
-	    continue;
-	if ((str_config = strstr(line, "CONFIG_")) == NULL)
-	    continue;
-
-	/* Make the output file name. */
-	str_config += sizeof("CONFIG_") - 1;
-	for (itarget = 0; !isspace(str_config[itarget]); itarget++)
-	{
-	    int c = (unsigned char) str_config[itarget];
-	    if (isupper(c)) c = tolower(c);
-	    if (c == '_')   c = '/';
-	    ptarget[itarget] = c;
-	}
-	ptarget[itarget++] = '.';
-	ptarget[itarget++] = 'h';
-	ptarget[itarget++] = '\0';
-
-	/* Check for existing file. */
-	is_same = 0;
-	if ((fp_target = fopen(ptarget, "r")) != NULL)
-	{
-	    fgets(old_line, buffer_size, fp_target);
-	    if (fclose(fp_target) != 0)
-		ERROR_EXIT(ptarget);
-	    if (!strcmp(line, old_line))
-		is_same = 1;
-	}
-
-	if (!is_same)
-	{
-	    /* Auto-create directories. */
-	    int islash;
-	    for (islash = 0; islash < itarget; islash++)
-	    {
-		if (ptarget[islash] == '/')
-		{
-		    ptarget[islash] = '\0';
-		    if (stat(ptarget, &stat_buf) != 0
-		    &&  mkdir(ptarget, 0755)     != 0)
-			ERROR_EXIT( ptarget );
-		    ptarget[islash] = '/';
-		}
-	    }
-
-	    /* Write the file. */
-	    if ((fp_target = fopen(ptarget, "w" )) == NULL)
-		ERROR_EXIT(ptarget);
-	    fputs(line, fp_target);
-	    if (ferror(fp_target) || fclose(fp_target) != 0)
-		ERROR_EXIT(ptarget);
-	}
-
-	/* Update target list */
-	ptarget += itarget;
-	*(ptarget-1) = '\n';
-    }
-
-    /*
-     * Close autoconfig file.
-     * Terminate the target list.
-     */
-    if (fclose(fp_config) != 0)
-	ERROR_EXIT(str_file_autoconf);
-    *ptarget = '\0';
-
-    /*
-     * Fix up existing files which have no new value.
-     * This is Case 4 and Case 5.
-     *
-     * I re-read the tree and filter it against list_target.
-     * This is crude.  But it avoids data copies.  Also, list_target
-     * is compact and contiguous, so it easily fits into cache.
-     *
-     * Notice that list_target contains strings separated by \n,
-     * with a \n before the first string and after the last.
-     * fgets gives the incoming names a terminating \n.
-     * So by having an initial \n, strstr will find exact matches.
-     */
-
-    fp_find = popen("find * -type f -name \"*.h\" -print", "r");
-    if (fp_find == 0)
-	ERROR_EXIT( "find" );
-
-    line[0] = '\n';
-    while (fgets(line+1, buffer_size, fp_find))
-    {
-	if (strstr(list_target, line) == NULL)
-	{
-	    /*
-	     * This is an old file with no CONFIG_* flag in autoconf.h.
-	     */
-
-	    /* First strip the \n. */
-	    line[strlen(line)-1] = '\0';
-
-	    /* Grab size. */
-	    if (stat(line+1, &stat_buf) != 0)
-		ERROR_EXIT(line);
-
-	    /* If file is not empty, make it empty and give it a fresh date. */
-	    if (stat_buf.st_size != 0)
-	    {
-		if ((fp_target = fopen(line+1, "w")) == NULL)
-		    ERROR_EXIT(line);
-		if (fclose(fp_target) != 0)
-		    ERROR_EXIT(line);
-	    }
-	}
-    }
-
-    if (pclose(fp_find) != 0)
-	ERROR_EXIT("find");
-
-    return 0;
-}
diff -Nru a/scripts/sumversion.c b/scripts/sumversion.c
--- a/scripts/sumversion.c	Wed Mar 17 19:29:09 2004
+++ b/scripts/sumversion.c	Wed Mar 17 19:29:09 2004
@@ -323,12 +323,12 @@
  * figure out source file. */
 static int parse_source_files(const char *objfile, struct md4_ctx *md)
 {
-	char *cmd, *file, *p, *end;
+	char *cmd, *file, *line, *dir;
 	const char *base;
-	unsigned long flen;
-	int dirlen, ret = 0;
+	unsigned long flen, pos = 0;
+	int dirlen, ret = 0, check_files = 0;
 
-	cmd = malloc(strlen(objfile) + sizeof("..cmd"));
+	cmd = NOFAIL(malloc(strlen(objfile) + sizeof("..cmd")));
 
 	base = strrchr(objfile, '/');
 	if (base) {
@@ -339,6 +339,9 @@
 		dirlen = 0;
 		sprintf(cmd, ".%s.cmd", objfile);
 	}
+	dir = NOFAIL(malloc(dirlen + 1));
+	strncpy(dir, objfile, dirlen);
+	dir[dirlen] = '\0';
 
 	file = grab_file(cmd, &flen);
 	if (!file) {
@@ -357,48 +360,38 @@
 
 	   Sum all files in the same dir or subdirs.
 	*/
-	/* Strictly illegal: file is not nul terminated. */
-	p = strstr(file, "\ndeps_");
-	if (!p) {
-		fprintf(stderr, "Warning: could not find deps_ line in %s\n",
-			cmd);
-		goto out_file;
-	}
-	p = strstr(p, ":=");
-	if (!p) {
-		fprintf(stderr, "Warning: could not find := line in %s\n",
-			cmd);
-		goto out_file;
-	}
-	p += strlen(":=");
-	p += strspn(p, " \\\n");
-
-	end = strstr(p, "\n\n");
-	if (!end) {
-		fprintf(stderr, "Warning: could not find end line in %s\n",
-			cmd);
-		goto out_file;
-	}
+	while ((line = get_next_line(&pos, file, flen)) != NULL) {
+		char* p = line;
+		if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
+			check_files = 1;
+			continue;
+		}
+		if (!check_files)
+			continue;
 
-	while (p < end) {
-		unsigned int len;
+		/* Continue until line does not end with '\' */
+		if ( *(p + strlen(p)-1) != '\\')
+			break;
+		/* Terminate line at first space, to get rid of final ' \' */
+		while (*p) {
+			if isspace(*p) {
+				*p = '\0';
+				break;
+			}
+			p++;
+		}
 
-		len = strcspn(p, " \\\n");
-		if (memcmp(objfile, p, dirlen) == 0) {
-			char source[len + 1];
-
-			memcpy(source, p, len);
-			source[len] = '\0';
-			printf("parsing %s\n", source);
-			if (!parse_file(source, md)) {
+		/* Check if this file is in same dir as objfile */
+		if ((strstr(line, dir)+strlen(dir)-1) == strrchr(line, '/')) {
+			if (!parse_file(line, md)) {
 				fprintf(stderr,
 					"Warning: could not open %s: %s\n",
-					source, strerror(errno));
+					line, strerror(errno));
 				goto out_file;
 			}
+
 		}
-		p += len;
-		p += strspn(p, " \\\n");
+
 	}
 
 	/* Everyone parsed OK */
@@ -406,6 +399,7 @@
 out_file:
 	release_file(file, flen);
 out:
+	free(dir);
 	free(cmd);
 	return ret;
 }
diff -Nru a/scripts/ver_linux b/scripts/ver_linux
--- a/scripts/ver_linux	Wed Mar 17 19:29:09 2004
+++ b/scripts/ver_linux	Wed Mar 17 19:29:09 2004
@@ -21,8 +21,9 @@
 make --version 2>&1 | awk -F, '{print $1}' | awk \
       '/GNU Make/{print "Gnu make              ",$NF}'
 
-ld -v 2>&1 | awk -F\) '{print $1}' | awk \
-      '/BFD/{print "binutils              ",$NF}'
+ld -v | awk -F\) '{print $1}' | awk \
+'/BFD/{print "binutils              ",$NF} \
+/^GNU/{print "binutils              ",$4}'
 
 fdformat --version | awk -F\- '{print "util-linux            ", $NF}'
 
diff -Nru a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
--- a/security/selinux/include/av_perm_to_string.h	Wed Mar 17 19:29:10 2004
+++ b/security/selinux/include/av_perm_to_string.h	Wed Mar 17 19:29:10 2004
@@ -84,6 +84,7 @@
    { SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel" },
    { SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user" },
    { SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce" },
+   { SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool" },
    { SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info" },
    { SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read" },
    { SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod" },
diff -Nru a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
--- a/security/selinux/include/av_permissions.h	Wed Mar 17 19:29:09 2004
+++ b/security/selinux/include/av_permissions.h	Wed Mar 17 19:29:09 2004
@@ -512,6 +512,7 @@
 #define SECURITY__COMPUTE_RELABEL                 0x00000020UL
 #define SECURITY__COMPUTE_USER                    0x00000040UL
 #define SECURITY__SETENFORCE                      0x00000080UL
+#define SECURITY__SETBOOL                         0x00000100UL
 
 #define SYSTEM__IPC_INFO                          0x00000001UL
 #define SYSTEM__SYSLOG_READ                       0x00000002UL
diff -Nru a/security/selinux/include/conditional.h b/security/selinux/include/conditional.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/security/selinux/include/conditional.h	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,22 @@
+/*
+ * Interface to booleans in the security server. This is exported
+ * for the selinuxfs.
+ *
+ * Author: Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ *	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.
+ */
+
+#ifndef _SELINUX_CONDITIONAL_H_
+#define _SELINUX_CONDITIONAL_H_
+
+int security_get_bools(int *len, char ***names, int **values);
+
+int security_set_bools(int len, int *values);
+
+int security_get_bool_value(int bool);
+
+#endif
diff -Nru a/security/selinux/include/security.h b/security/selinux/include/security.h
--- a/security/selinux/include/security.h	Wed Mar 17 19:29:09 2004
+++ b/security/selinux/include/security.h	Wed Mar 17 19:29:09 2004
@@ -2,7 +2,9 @@
  * Security server interface.
  *
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ *
  */
+
 #ifndef _SELINUX_SECURITY_H_
 #define _SELINUX_SECURITY_H_
 
@@ -13,12 +15,19 @@
 #define SECCLASS_NULL			0x0000 /* no class */
 
 #define SELINUX_MAGIC 0xf97cff8c
-#define POLICYDB_VERSION 15
+#define POLICYDB_VERSION 16
+#define POLICYDB_VERSION_COMPAT 15
 
 #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
 extern int selinux_enabled;
 #else
 #define selinux_enabled 1
+#endif
+
+#ifdef CONFIG_SECURITY_SELINUX_MLS
+#define selinux_mls_enabled 1
+#else
+#define selinux_mls_enabled 0
 #endif
 
 int security_load_policy(void * data, size_t len);
diff -Nru a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
--- a/security/selinux/selinuxfs.c	Wed Mar 17 19:29:10 2004
+++ b/security/selinux/selinuxfs.c	Wed Mar 17 19:29:10 2004
@@ -1,5 +1,16 @@
+/* Updated: Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * 	Added conditional policy language extensions
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ *	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.
+ */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
@@ -7,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/security.h>
 #include <asm/uaccess.h>
+#include <asm/semaphore.h>
 
 /* selinuxfs pseudo filesystem for exporting the security policy API.
    Based on the proc code and the fs/nfsd/nfsctl.c code. */
@@ -16,6 +28,14 @@
 #include "avc_ss.h"
 #include "security.h"
 #include "objsec.h"
+#include "conditional.h"
+
+static DECLARE_MUTEX(sel_sem);
+
+/* global data for booleans */
+static struct dentry *bool_dir = NULL;
+static int bool_num = 0;
+static int *bool_pending_values = NULL;
 
 extern void selnl_notify_setenforce(int val);
 
@@ -40,7 +60,9 @@
 	SEL_CREATE,	/* compute create labeling decision */
 	SEL_RELABEL,	/* compute relabeling decision */
 	SEL_USER,	/* compute reachable user contexts */
-	SEL_POLICYVERS	/* return policy version for this kernel */
+	SEL_POLICYVERS,	/* return policy version for this kernel */
+	SEL_COMMIT_BOOLS,
+	SEL_MLS		/* return if MLS policy is enabled */
 };
 
 static ssize_t sel_read_enforce(struct file *filp, char *buf,
@@ -169,24 +191,74 @@
 	.read		= sel_read_policyvers,
 };
 
+/* declaration for sel_write_load */
+static int sel_make_bools(void);
+
+static ssize_t sel_read_mls(struct file *filp, char *buf,
+				size_t count, loff_t *ppos)
+{
+	char *page;
+	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;
+}
+
+static struct file_operations sel_mls_ops = {
+	.read		= sel_read_mls,
+};
+
 static ssize_t sel_write_load(struct file * file, const char * buf,
 			      size_t count, loff_t *ppos)
 
 {
+	int ret;
 	ssize_t length;
-	void *data;
+	void *data = NULL;
+
+	down(&sel_sem);
 
 	length = task_has_security(current, SECURITY__LOAD_POLICY);
 	if (length)
-		return length;
+		goto out;
 
 	if (*ppos != 0) {
 		/* No partial writes. */
-		return -EINVAL;
+		length = -EINVAL;
+		goto out;
 	}
 
-	if ((count < 0) || (count > 64 * 1024 * 1024) || (data = vmalloc(count)) == NULL)
-		return -ENOMEM;
+	if ((count < 0) || (count > 64 * 1024 * 1024)
+	    || (data = vmalloc(count)) == NULL) {
+		length = -ENOMEM;
+		goto out;
+	}
 
 	length = -EFAULT;
 	if (copy_from_user(data, buf, count) != 0)
@@ -196,8 +268,13 @@
 	if (length)
 		goto out;
 
-	length = count;
+	ret = sel_make_bools();
+	if (ret)
+		length = ret;
+	else
+		length = count;
 out:
+	up(&sel_sem);
 	vfree(data);
 	return length;
 }
@@ -601,9 +678,322 @@
 	return length;
 }
 
+static struct inode *sel_make_inode(struct super_block *sb, int mode)
+{
+	struct inode *ret = new_inode(sb);
+
+	if (ret) {
+		ret->i_mode = mode;
+		ret->i_uid = ret->i_gid = 0;
+		ret->i_blksize = PAGE_CACHE_SIZE;
+		ret->i_blocks = 0;
+		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
+	}
+	return ret;
+}
+
+#define BOOL_INO_OFFSET 30
+
+static ssize_t sel_read_bool(struct file *filep, char *buf,
+			     size_t count, loff_t *ppos)
+{
+	char *page = NULL;
+	ssize_t length;
+	ssize_t end;
+	ssize_t ret;
+	int cur_enforcing;
+	struct inode *inode;
+
+	down(&sel_sem);
+
+	ret = -EFAULT;
+
+	/* check to see if this file has been deleted */
+	if (!filep->f_op)
+		goto out;
+
+	if (count < 0 || count > PAGE_SIZE) {
+		ret = -EINVAL;
+		goto out;
+	}
+	if (!(page = (char*)__get_free_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);
+	if (cur_enforcing < 0) {
+		ret = cur_enforcing;
+		goto out;
+	}
+
+	length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
+			  bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
+	if (length < 0) {
+		ret = length;
+		goto out;
+	}
+
+	if (*ppos >= length) {
+		ret = 0;
+		goto out;
+	}
+	if (count + *ppos > length)
+		count = length - *ppos;
+	end = count + *ppos;
+	if (copy_to_user(buf, (char *) page + *ppos, count)) {
+		ret = -EFAULT;
+		goto out;
+	}
+	*ppos = end;
+	ret = count;
+out:
+	up(&sel_sem);
+	if (page)
+		free_page((unsigned long)page);
+	return ret;
+}
+
+static ssize_t sel_write_bool(struct file *filep, const char *buf,
+			      size_t count, loff_t *ppos)
+{
+	char *page = NULL;
+	ssize_t length = -EFAULT;
+	int new_value;
+	struct inode *inode;
+
+	down(&sel_sem);
+
+	length = task_has_security(current, SECURITY__SETBOOL);
+	if (length)
+		goto out;
+
+	/* check to see if this file has been deleted */
+	if (!filep->f_op)
+		goto out;
+
+	if (count < 0 || count >= PAGE_SIZE) {
+		length = -ENOMEM;
+		goto out;
+	}
+	if (*ppos != 0) {
+		/* No partial writes. */
+		goto out;
+	}
+	page = (char*)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	memset(page, 0, PAGE_SIZE);
+
+	if (copy_from_user(page, buf, count))
+		goto out;
+
+	length = -EINVAL;
+	if (sscanf(page, "%d", &new_value) != 1)
+		goto out;
+
+	if (new_value)
+		new_value = 1;
+
+	inode = filep->f_dentry->d_inode;
+	bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
+	length = count;
+
+out:
+	up(&sel_sem);
+	if (page)
+		free_page((unsigned long) page);
+	return length;
+}
+
+static struct file_operations sel_bool_ops = {
+	.read           = sel_read_bool,
+	.write          = sel_write_bool,
+};
+
+static ssize_t sel_commit_bools_write(struct file *filep, const char *buf,
+				      size_t count, loff_t *ppos)
+{
+	char *page = NULL;
+	ssize_t length = -EFAULT;
+	int new_value;
+
+	down(&sel_sem);
+
+	length = task_has_security(current, SECURITY__SETBOOL);
+	if (length)
+		goto out;
+
+	/* check to see if this file has been deleted */
+	if (!filep->f_op)
+		goto out;
+
+	if (count < 0 || count >= PAGE_SIZE) {
+		length = -ENOMEM;
+		goto out;
+	}
+	if (*ppos != 0) {
+		/* No partial writes. */
+		goto out;
+	}
+	page = (char*)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	memset(page, 0, PAGE_SIZE);
+
+	if (copy_from_user(page, buf, count))
+		goto out;
+
+	length = -EINVAL;
+	if (sscanf(page, "%d", &new_value) != 1)
+		goto out;
+
+	if (new_value) {
+		security_set_bools(bool_num, bool_pending_values);
+	}
+
+	length = count;
+
+out:
+	up(&sel_sem);
+	if (page)
+		free_page((unsigned long) page);
+	return length;
+}
+
+static struct file_operations sel_commit_bools_ops = {
+	.write          = sel_commit_bools_write,
+};
+
+/* delete booleans - partial revoke() from
+ * fs/proc/generic.c proc_kill_inodes */
+static void sel_remove_bools(struct dentry *de)
+{
+	struct list_head *p, *node;
+	struct super_block *sb = de->d_sb;
+
+	spin_lock(&dcache_lock);
+	node = de->d_subdirs.next;
+	while (node != &de->d_subdirs) {
+		struct dentry *d = list_entry(node, struct dentry, d_child);
+		list_del_init(node);
+
+		if (d->d_inode) {
+			d = dget_locked(d);
+			spin_unlock(&dcache_lock);
+			d_delete(d);
+			simple_unlink(de->d_inode, d);
+			dput(d);
+			spin_lock(&dcache_lock);
+		}
+		node = de->d_subdirs.next;
+	}
+
+	spin_unlock(&dcache_lock);
+
+	file_list_lock();
+	list_for_each(p, &sb->s_files) {
+		struct file * filp = list_entry(p, struct file, f_list);
+		struct dentry * dentry = filp->f_dentry;
+
+		if (dentry->d_parent != de) {
+			continue;
+		}
+		filp->f_op = NULL;
+	}
+	file_list_unlock();
+}
+
+#define BOOL_DIR_NAME "booleans"
+
+static int sel_make_bools(void)
+{
+	int i, ret = 0;
+	ssize_t len;
+	struct dentry *dentry = NULL;
+	struct dentry *dir = bool_dir;
+	struct inode *inode = NULL;
+	struct inode_security_struct *isec;
+	struct qstr qname;
+	char **names = NULL, *page;
+	int num;
+	int *values = NULL;
+	u32 sid;
+
+	/* remove any existing files */
+	if (bool_pending_values)
+		kfree(bool_pending_values);
+
+	sel_remove_bools(dir);
+
+	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	memset(page, 0, PAGE_SIZE);
+
+	ret = security_get_bools(&num, &names, &values);
+	if (ret != 0)
+		goto out;
+
+	for (i = 0; i < num; i++) {
+		qname.name = names[i];
+		qname.len = strlen(qname.name);
+		qname.hash = full_name_hash(qname.name, qname.len);
+		dentry = d_alloc(dir, &qname);
+		if (!dentry) {
+			ret = -ENOMEM;
+			goto err;
+		}
+		inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);
+		if (!inode) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]);
+		if (len < 0) {
+			ret = -EINVAL;
+			goto err;
+		} else if (len >= PAGE_SIZE) {
+			ret = -ENAMETOOLONG;
+			goto err;
+		}
+		isec = (struct inode_security_struct*)inode->i_security;
+		if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
+			goto err;
+		isec->sid = sid;
+		isec->initialized = 1;
+		inode->i_fop = &sel_bool_ops;
+		inode->i_ino = i + BOOL_INO_OFFSET;
+		d_add(dentry, inode);
+	}
+	bool_num = num;
+	bool_pending_values = values;
+out:
+	free_page((unsigned long)page);
+	if (names) {
+		for (i = 0; i < num; i++) {
+			if (names[i])
+				kfree(names[i]);
+		}
+		kfree(names);
+	}
+	return ret;
+err:
+	d_genocide(dir);
+	ret = -ENOMEM;
+	goto out;
+}
 
 static int sel_fill_super(struct super_block * sb, void * data, int silent)
 {
+	int ret;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct qstr qname;
+
 	static struct tree_descr selinux_files[] = {
 		[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
 		[SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
@@ -613,9 +1003,37 @@
 		[SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},
 		[SEL_USER] = {"user", &transaction_ops, S_IRUGO|S_IWUGO},
 		[SEL_POLICYVERS] = {"policyvers", &sel_policyvers_ops, S_IRUGO},
+		[SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR},
+		[SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
 		/* last one */ {""}
 	};
-	return simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
+	ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
+	if (ret)
+		return ret;
+
+	qname.name = BOOL_DIR_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_IFDIR | S_IRUGO | S_IXUGO);
+	if (!inode)
+		goto out;
+	inode->i_op = &simple_dir_inode_operations;
+	inode->i_fop = &simple_dir_operations;
+	d_add(dentry, inode);
+	bool_dir = dentry;
+	ret = sel_make_bools();
+	if (ret)
+		goto out;
+
+	return 0;
+out:
+	dput(dentry);
+	printk(KERN_ERR "security:	error creating conditional out_dput\n");
+	return -ENOMEM;
 }
 
 static struct super_block *sel_get_sb(struct file_system_type *fs_type,
diff -Nru a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile
--- a/security/selinux/ss/Makefile	Wed Mar 17 19:29:09 2004
+++ b/security/selinux/ss/Makefile	Wed Mar 17 19:29:09 2004
@@ -5,7 +5,7 @@
 EXTRA_CFLAGS += -Isecurity/selinux/include
 obj-y := ss.o
 
-ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o
+ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o
 
 ss-$(CONFIG_SECURITY_SELINUX_MLS) += mls.o
 
diff -Nru a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
--- a/security/selinux/ss/avtab.c	Wed Mar 17 19:29:10 2004
+++ b/security/selinux/ss/avtab.c	Wed Mar 17 19:29:10 2004
@@ -3,10 +3,22 @@
  *
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
+
+/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * 	Added conditional policy language extensions
+ *
+ * Copyright (C) 2003 Tresys Technology, LLC
+ *	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.
+ */
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/errno.h>
+
 #include "avtab.h"
 #include "policydb.h"
 
@@ -16,6 +28,29 @@
  (keyp->source_type << 9)) & \
  AVTAB_HASH_MASK)
 
+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);
+	if (newnode == NULL)
+		return NULL;
+	memset(newnode, 0, sizeof(struct avtab_node));
+	newnode->key = *key;
+	newnode->datum = *datum;
+	if (prev) {
+		newnode->next = prev->next;
+		prev->next = newnode;
+	} else {
+		newnode->next = h->htable[hvalue];
+		h->htable[hvalue] = newnode;
+	}
+
+	h->nel++;
+	return newnode;
+}
+
 int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
 {
 	int hvalue;
@@ -44,24 +79,48 @@
 			break;
 	}
 
-	newnode = kmalloc(sizeof(*newnode), GFP_KERNEL);
-	if (newnode == NULL)
+	newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
+	if(!newnode)
 		return -ENOMEM;
-	memset(newnode, 0, sizeof(*newnode));
-	newnode->key = *key;
-	newnode->datum = *datum;
-	if (prev) {
-		newnode->next = prev->next;
-		prev->next = newnode;
-	} else {
-		newnode->next = h->htable[hvalue];
-		h->htable[hvalue] = newnode;
-	}
 
-	h->nel++;
 	return 0;
 }
 
+/* Unlike avtab_insert(), this function allow multiple insertions of the same
+ * key/specified mask into the table, as needed by the conditional avtab.
+ * It also returns a pointer to the node inserted.
+ */
+struct avtab_node *
+avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_datum * datum)
+{
+	int hvalue;
+	struct avtab_node *prev, *cur, *newnode;
+
+	if (!h)
+		return NULL;
+	hvalue = AVTAB_HASH(key);
+	for (prev = NULL, cur = h->htable[hvalue];
+	     cur;
+	     prev = cur, cur = cur->next) {
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class == cur->key.target_class &&
+		    (datum->specified & cur->datum.specified))
+			break;
+		if (key->source_type < cur->key.source_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type < cur->key.target_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class < cur->key.target_class)
+			break;
+	}
+	newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum);
+
+	return newnode;
+}
 
 struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified)
 {
@@ -93,6 +152,67 @@
 	return NULL;
 }
 
+/* This search function returns a node pointer, and can be used in
+ * conjunction with avtab_search_next_node()
+ */
+struct avtab_node*
+avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
+{
+	int hvalue;
+	struct avtab_node *cur;
+
+	if (!h)
+		return NULL;
+
+	hvalue = AVTAB_HASH(key);
+	for (cur = h->htable[hvalue]; cur; cur = cur->next) {
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class == cur->key.target_class &&
+		    (specified & cur->datum.specified))
+			return cur;
+
+		if (key->source_type < cur->key.source_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type < cur->key.target_type)
+			break;
+		if (key->source_type == cur->key.source_type &&
+		    key->target_type == cur->key.target_type &&
+		    key->target_class < cur->key.target_class)
+			break;
+	}
+	return NULL;
+}
+
+struct avtab_node*
+avtab_search_node_next(struct avtab_node *node, int specified)
+{
+	struct avtab_node *cur;
+
+	if (!node)
+		return NULL;
+
+	for (cur = node->next; cur; cur = cur->next) {
+		if (node->key.source_type == cur->key.source_type &&
+		    node->key.target_type == cur->key.target_type &&
+		    node->key.target_class == cur->key.target_class &&
+		    (specified & cur->datum.specified))
+			return cur;
+
+		if (node->key.source_type < cur->key.source_type)
+			break;
+		if (node->key.source_type == cur->key.source_type &&
+		    node->key.target_type < cur->key.target_type)
+			break;
+		if (node->key.source_type == cur->key.source_type &&
+		    node->key.target_type == cur->key.target_type &&
+		    node->key.target_class < cur->key.target_class)
+			break;
+	}
+	return NULL;
+}
+
 void avtab_destroy(struct avtab *h)
 {
 	int i;
@@ -179,13 +299,72 @@
 	       max_chain_len);
 }
 
+int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey)
+{
+	__u32 *buf;
+	__u32 items, items2;
+
+	memset(avkey, 0, sizeof(struct avtab_key));
+	memset(avdatum, 0, sizeof(struct avtab_datum));
+
+	buf = next_entry(fp, sizeof(__u32));
+	if (!buf) {
+		printk(KERN_ERR "security: avtab: truncated entry\n");
+		goto bad;
+	}
+	items2 = le32_to_cpu(buf[0]);
+	buf = next_entry(fp, sizeof(__u32)*items2);
+	if (!buf) {
+		printk(KERN_ERR "security: avtab: truncated entry\n");
+		goto bad;
+	}
+	items = 0;
+	avkey->source_type = le32_to_cpu(buf[items++]);
+	avkey->target_type = le32_to_cpu(buf[items++]);
+	avkey->target_class = le32_to_cpu(buf[items++]);
+	avdatum->specified = le32_to_cpu(buf[items++]);
+	if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) {
+		printk(KERN_ERR "security: avtab: null entry\n");
+		goto bad;
+	}
+	if ((avdatum->specified & AVTAB_AV) &&
+	    (avdatum->specified & AVTAB_TYPE)) {
+		printk(KERN_ERR "security: avtab: entry has both access vectors and types\n");
+		goto bad;
+	}
+	if (avdatum->specified & AVTAB_AV) {
+		if (avdatum->specified & AVTAB_ALLOWED)
+			avtab_allowed(avdatum) = le32_to_cpu(buf[items++]);
+		if (avdatum->specified & AVTAB_AUDITDENY)
+			avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]);
+		if (avdatum->specified & AVTAB_AUDITALLOW)
+			avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]);
+	} else {
+		if (avdatum->specified & AVTAB_TRANSITION)
+			avtab_transition(avdatum) = le32_to_cpu(buf[items++]);
+		if (avdatum->specified & AVTAB_CHANGE)
+			avtab_change(avdatum) = le32_to_cpu(buf[items++]);
+		if (avdatum->specified & AVTAB_MEMBER)
+			avtab_member(avdatum) = le32_to_cpu(buf[items++]);
+	}
+	if (items != items2) {
+		printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n",
+		       items2, items);
+		goto bad;
+	}
+
+	return 0;
+bad:
+	return -1;
+}
+
 int avtab_read(struct avtab *a, void *fp, u32 config)
 {
 	int i, rc = -EINVAL;
 	struct avtab_key avkey;
 	struct avtab_datum avdatum;
 	u32 *buf;
-	u32 nel, items, items2;
+	u32 nel;
 
 
 	buf = next_entry(fp, sizeof(u32));
@@ -199,55 +378,8 @@
 		goto bad;
 	}
 	for (i = 0; i < nel; i++) {
-		memset(&avkey, 0, sizeof(avkey));
-		memset(&avdatum, 0, sizeof(avdatum));
-
-		buf = next_entry(fp, sizeof(u32));
-		if (!buf) {
-			printk(KERN_ERR "security: avtab: truncated entry\n");
-			goto bad;
-		}
-		items2 = le32_to_cpu(buf[0]);
-		buf = next_entry(fp, sizeof(u32)*items2);
-		if (!buf) {
-			printk(KERN_ERR "security: avtab: truncated entry\n");
+		if (avtab_read_item(fp, &avdatum, &avkey))
 			goto bad;
-		}
-		items = 0;
-		avkey.source_type = le32_to_cpu(buf[items++]);
-		avkey.target_type = le32_to_cpu(buf[items++]);
-		avkey.target_class = le32_to_cpu(buf[items++]);
-		avdatum.specified = le32_to_cpu(buf[items++]);
-		if (!(avdatum.specified & (AVTAB_AV | AVTAB_TYPE))) {
-			printk(KERN_ERR "security: avtab: null entry\n");
-			goto bad;
-		}
-		if ((avdatum.specified & AVTAB_AV) &&
-		    (avdatum.specified & AVTAB_TYPE)) {
-			printk(KERN_ERR "security: avtab: entry has both "
-			       "access vectors and types\n");
-			goto bad;
-		}
-		if (avdatum.specified & AVTAB_AV) {
-			if (avdatum.specified & AVTAB_ALLOWED)
-				avtab_allowed(&avdatum) = le32_to_cpu(buf[items++]);
-			if (avdatum.specified & AVTAB_AUDITDENY)
-				avtab_auditdeny(&avdatum) = le32_to_cpu(buf[items++]);
-			if (avdatum.specified & AVTAB_AUDITALLOW)
-				avtab_auditallow(&avdatum) = le32_to_cpu(buf[items++]);
-		} else {
-			if (avdatum.specified & AVTAB_TRANSITION)
-				avtab_transition(&avdatum) = le32_to_cpu(buf[items++]);
-			if (avdatum.specified & AVTAB_CHANGE)
-				avtab_change(&avdatum) = le32_to_cpu(buf[items++]);
-			if (avdatum.specified & AVTAB_MEMBER)
-				avtab_member(&avdatum) = le32_to_cpu(buf[items++]);
-		}
-		if (items != items2) {
-			printk(KERN_ERR "security: avtab: entry only had %d "
-			       "items, expected %d\n", items2, items);
-			goto bad;
-		}
 		rc = avtab_insert(a, &avkey, &avdatum);
 		if (rc) {
 			if (rc == -ENOMEM)
diff -Nru a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
--- a/security/selinux/ss/avtab.h	Wed Mar 17 19:29:09 2004
+++ b/security/selinux/ss/avtab.h	Wed Mar 17 19:29:09 2004
@@ -7,6 +7,16 @@
  *
  *  Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
+
+/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * 	Added conditional policy language extensions
+ *
+ * Copyright (C) 2003 Tresys Technology, LLC
+ *	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.
+ */
 #ifndef _SS_AVTAB_H_
 #define _SS_AVTAB_H_
 
@@ -25,6 +35,7 @@
 #define AVTAB_MEMBER     32
 #define AVTAB_CHANGE     64
 #define AVTAB_TYPE       (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
+#define AVTAB_ENABLED    0x80000000 /* reserved for used in cond_avtab */
 	u32 specified;	/* what fields are specified */
 	u32 data[3];	/* access vectors or types */
 #define avtab_allowed(x) (x)->data[0]
@@ -56,7 +67,16 @@
 			    void *args),
 	      void *args);
 void avtab_hash_eval(struct avtab *h, char *tag);
+
+int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey);
 int avtab_read(struct avtab *a, void *fp, u32 config);
+
+struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
+					  struct avtab_datum *datum);
+
+struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified);
+
+struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
 
 #define AVTAB_HASH_BITS 15
 #define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
diff -Nru a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/security/selinux/ss/conditional.c	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,487 @@
+/* Authors: Karl MacMillan <kmacmillan@tresys.com>
+ *          Frank Mayer <mayerf@tresys.com>
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ *	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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <asm/semaphore.h>
+#include <linux/slab.h>
+
+#include "security.h"
+#include "conditional.h"
+
+/*
+ * cond_evaluate_expr evaluates a conditional expr
+ * in reverse polish notation. It returns true (1), false (0),
+ * or undefined (-1). Undefined occurs when the expression
+ * exceeds the stack depth of COND_EXPR_MAXDEPTH.
+ */
+static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
+{
+
+	struct cond_expr *cur;
+	int s[COND_EXPR_MAXDEPTH];
+	int sp = -1;
+
+	for (cur = expr; cur != NULL; cur = cur->next) {
+		switch (cur->expr_type) {
+		case COND_BOOL:
+			if (sp == (COND_EXPR_MAXDEPTH - 1))
+				return -1;
+			sp++;
+			s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
+			break;
+		case COND_NOT:
+			if (sp < 0)
+				return -1;
+			s[sp] = !s[sp];
+			break;
+		case COND_OR:
+			if (sp < 1)
+				return -1;
+			sp--;
+			s[sp] |= s[sp + 1];
+			break;
+		case COND_AND:
+			if (sp < 1)
+				return -1;
+			sp--;
+			s[sp] &= s[sp + 1];
+			break;
+		case COND_XOR:
+			if (sp < 1)
+				return -1;
+			sp--;
+			s[sp] ^= s[sp + 1];
+			break;
+		case COND_EQ:
+			if (sp < 1)
+				return -1;
+			sp--;
+			s[sp] = (s[sp] == s[sp + 1]);
+			break;
+		case COND_NEQ:
+			if (sp < 1)
+				return -1;
+			sp--;
+			s[sp] = (s[sp] != s[sp + 1]);
+			break;
+		default:
+			return -1;
+		}
+	}
+	return s[0];
+}
+
+/*
+ * evaluate_cond_node evaluates the conditional stored in
+ * a struct cond_node and if the result is different than the
+ * current state of the node it sets the rules in the true/false
+ * list appropriately. If the result of the expression is undefined
+ * all of the rules are disabled for safety.
+ */
+int evaluate_cond_node(struct policydb *p, struct cond_node *node)
+{
+	int new_state;
+	struct cond_av_list* cur;
+
+	new_state = cond_evaluate_expr(p, node->expr);
+	if (new_state != node->cur_state) {
+		node->cur_state = new_state;
+		if (new_state == -1)
+			printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n");
+		/* turn the rules on or off */
+		for (cur = node->true_list; cur != NULL; cur = cur->next) {
+			if (new_state <= 0) {
+				cur->node->datum.specified &= ~AVTAB_ENABLED;
+			} else {
+				cur->node->datum.specified |= AVTAB_ENABLED;
+			}
+		}
+
+		for (cur = node->false_list; cur != NULL; cur = cur->next) {
+			/* -1 or 1 */
+			if (new_state) {
+				cur->node->datum.specified &= ~AVTAB_ENABLED;
+			} else {
+				cur->node->datum.specified |= AVTAB_ENABLED;
+			}
+		}
+	}
+	return 0;
+}
+
+int cond_policydb_init(struct policydb *p)
+{
+	p->bool_val_to_struct = NULL;
+	p->cond_list = NULL;
+	if (avtab_init(&p->te_cond_avtab))
+		return -1;
+
+	return 0;
+}
+
+static void cond_av_list_destroy(struct cond_av_list *list)
+{
+	struct cond_av_list *cur, *next;
+	for (cur = list; cur != NULL; cur = next) {
+		next = cur->next;
+		/* the avtab_ptr_t node is destroy by the avtab */
+		kfree(cur);
+	}
+}
+
+static void cond_node_destroy(struct cond_node *node)
+{
+	struct cond_expr *cur_expr, *next_expr;
+
+	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) {
+		next_expr = cur_expr->next;
+		kfree(cur_expr);
+	}
+	cond_av_list_destroy(node->true_list);
+	cond_av_list_destroy(node->false_list);
+	kfree(node);
+}
+
+static void cond_list_destroy(struct cond_node *list)
+{
+	struct cond_node *next, *cur;
+
+	if (list == NULL)
+		return;
+
+	for (cur = list; cur != NULL; cur = next) {
+		next = cur->next;
+		cond_node_destroy(cur);
+	}
+}
+
+void cond_policydb_destroy(struct policydb *p)
+{
+	if (p->bool_val_to_struct != NULL)
+		kfree(p->bool_val_to_struct);
+	avtab_destroy(&p->te_cond_avtab);
+	cond_list_destroy(p->cond_list);
+}
+
+int cond_init_bool_indexes(struct policydb *p)
+{
+	if (p->bool_val_to_struct)
+		kfree(p->bool_val_to_struct);
+	p->bool_val_to_struct = (struct cond_bool_datum**)
+		kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
+	if (!p->bool_val_to_struct)
+		return -1;
+	return 0;
+}
+
+int cond_destroy_bool(void *key, void *datum, void *p)
+{
+	if (key)
+		kfree(key);
+	kfree(datum);
+	return 0;
+}
+
+int cond_index_bool(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct cond_bool_datum *booldatum;
+
+	booldatum = datum;
+	p = datap;
+
+	if (!booldatum->value || booldatum->value > p->p_bools.nprim)
+		return -EINVAL;
+
+	p->p_bool_val_to_name[booldatum->value - 1] = key;
+	p->bool_val_to_struct[booldatum->value -1] = booldatum;
+
+	return 0;
+}
+
+int bool_isvalid(struct cond_bool_datum *b)
+{
+	if (!(b->state == 0 || b->state == 1))
+		return 0;
+	return 1;
+}
+
+int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = 0;
+	struct cond_bool_datum *booldatum;
+	__u32 *buf, len;
+
+	booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
+	if (!booldatum)
+		return -1;
+	memset(booldatum, 0, sizeof(struct cond_bool_datum));
+
+	buf = next_entry(fp, sizeof(__u32) * 3);
+	if (!buf)
+		goto err;
+
+	booldatum->value = le32_to_cpu(buf[0]);
+	booldatum->state = le32_to_cpu(buf[1]);
+
+	if (!bool_isvalid(booldatum))
+		goto err;
+
+	len = le32_to_cpu(buf[2]);
+
+	buf = next_entry(fp, len);
+	if (!buf)
+		goto err;
+	key = kmalloc(len + 1, GFP_KERNEL);
+	if (!key)
+		goto err;
+	memcpy(key, buf, len);
+	key[len] = 0;
+	if (hashtab_insert(h, key, booldatum))
+		goto err;
+
+	return 0;
+err:
+	cond_destroy_bool(key, booldatum, 0);
+	return -1;
+}
+
+static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list,
+			     struct cond_av_list *other)
+{
+	struct cond_av_list *list, *last = NULL, *cur;
+	struct avtab_key key;
+	struct avtab_datum datum;
+	struct avtab_node *node_ptr;
+	int len, i;
+	__u32 *buf;
+	__u8 found;
+
+	*ret_list = NULL;
+
+	len = 0;
+	buf = next_entry(fp, sizeof(__u32));
+	if (!buf)
+		return -1;
+
+	len = le32_to_cpu(buf[0]);
+	if (len == 0) {
+		return 0;
+	}
+
+	for (i = 0; i < len; i++) {
+		if (avtab_read_item(fp, &datum, &key))
+			goto err;
+
+		/*
+		 * For type rules we have to make certain there aren't any
+		 * conflicting rules by searching the te_avtab and the
+		 * cond_te_avtab.
+		 */
+		if (datum.specified & AVTAB_TYPE) {
+			if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) {
+				printk("security: type rule already exists outside of a conditional.");
+				goto err;
+			}
+			/*
+			 * If we are reading the false list other will be a pointer to
+			 * the true list. We can have duplicate entries if there is only
+			 * 1 other entry and it is in our true list.
+			 *
+			 * If we are reading the true list (other == NULL) there shouldn't
+			 * be any other entries.
+			 */
+			if (other) {
+				node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE);
+				if (node_ptr) {
+					if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) {
+						printk("security: too many conflicting type rules.");
+						goto err;
+					}
+					found = 0;
+					for (cur = other; cur != NULL; cur = cur->next) {
+						if (cur->node == node_ptr) {
+							found = 1;
+							break;
+						}
+					}
+					if (!found) {
+						printk("security: conflicting type rules.");
+						goto err;
+					}
+				}
+			} else {
+				if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) {
+					printk("security: conflicting type rules when adding type rule for true.");
+					goto err;
+				}
+			}
+		}
+		node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum);
+		if (!node_ptr) {
+			printk("security: could not insert rule.");
+			goto err;
+		}
+
+		list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
+		if (!list)
+			goto err;
+		memset(list, 0, sizeof(struct cond_av_list));
+
+		list->node = node_ptr;
+		if (i == 0)
+			*ret_list = list;
+		else
+			last->next = list;
+		last = list;
+
+	}
+
+	return 0;
+err:
+	cond_av_list_destroy(*ret_list);
+	*ret_list = NULL;
+	return -1;
+}
+
+static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
+{
+	if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
+		printk("security: conditional expressions uses unknown operator.\n");
+		return 0;
+	}
+
+	if (expr->bool > p->p_bools.nprim) {
+		printk("security: conditional expressions uses unknown bool.\n");
+		return 0;
+	}
+	return 1;
+}
+
+static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
+{
+	__u32 *buf;
+	int len, i;
+	struct cond_expr *expr = NULL, *last = NULL;
+
+	buf = next_entry(fp, sizeof(__u32));
+	if (!buf)
+		return -1;
+
+	node->cur_state = le32_to_cpu(buf[0]);
+
+	len = 0;
+	buf = next_entry(fp, sizeof(__u32));
+	if (!buf)
+		return -1;
+
+	/* expr */
+	len = le32_to_cpu(buf[0]);
+
+	for (i = 0; i < len; i++ ) {
+		buf = next_entry(fp, sizeof(__u32) * 2);
+		if (!buf)
+			goto err;
+
+		expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
+		if (!expr) {
+			goto err;
+		}
+		memset(expr, 0, sizeof(struct cond_expr));
+
+		expr->expr_type = le32_to_cpu(buf[0]);
+		expr->bool = le32_to_cpu(buf[1]);
+
+		if (!expr_isvalid(p, expr))
+			goto err;
+
+		if (i == 0) {
+			node->expr = expr;
+		} else {
+			last->next = expr;
+		}
+		last = expr;
+	}
+
+	if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
+		goto err;
+	if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0)
+		goto err;
+	return 0;
+err:
+	cond_node_destroy(node);
+	return -1;
+}
+
+int cond_read_list(struct policydb *p, void *fp)
+{
+	struct cond_node *node, *last = NULL;
+	__u32 *buf;
+	int i, len;
+
+	buf = next_entry(fp, sizeof(__u32));
+	if (!buf)
+		return -1;
+
+	len = le32_to_cpu(buf[0]);
+
+	for (i = 0; i < len; i++) {
+		node = kmalloc(sizeof(struct cond_node), GFP_KERNEL);
+		if (!node)
+			goto err;
+		memset(node, 0, sizeof(struct cond_node));
+
+		if (cond_read_node(p, node, fp) != 0)
+			goto err;
+
+		if (i == 0) {
+			p->cond_list = node;
+		} else {
+			last->next = node;
+		}
+		last = node;
+	}
+	return 0;
+err:
+	cond_list_destroy(p->cond_list);
+	return -1;
+}
+
+/* Determine whether additional permissions are granted by the conditional
+ * av table, and if so, add them to the result
+ */
+void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd)
+{
+	struct avtab_node *node;
+
+	if(!ctab || !key || !avd)
+		return;
+
+	for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL;
+				node = avtab_search_node_next(node, AVTAB_AV)) {
+		if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
+		     (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
+			avd->allowed |= avtab_allowed(&node->datum);
+		if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
+		     (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
+			/* Since a '0' in an auditdeny mask represents a
+			 * permission we do NOT want to audit (dontaudit), we use
+			 * the '&' operand to ensure that all '0's in the mask
+			 * are retained (much unlike the allow and auditallow cases).
+			 */
+			avd->auditdeny &= avtab_auditdeny(&node->datum);
+		if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
+		     (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
+			avd->auditallow |= avtab_auditallow(&node->datum);
+	}
+	return;
+}
diff -Nru a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/security/selinux/ss/conditional.h	Wed Mar 17 19:29:10 2004
@@ -0,0 +1,77 @@
+/* Authors: Karl MacMillan <kmacmillan@tresys.com>
+ *          Frank Mayer <mayerf@tresys.com>
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ *	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.
+ */
+
+#ifndef _CONDITIONAL_H_
+#define _CONDITIONAL_H_
+
+#include "avtab.h"
+#include "symtab.h"
+#include "policydb.h"
+
+#define COND_EXPR_MAXDEPTH 10
+
+/*
+ * A conditional expression is a list of operators and operands
+ * in reverse polish notation.
+ */
+struct cond_expr {
+#define COND_BOOL	1 /* plain bool */
+#define COND_NOT	2 /* !bool */
+#define COND_OR		3 /* bool || bool */
+#define COND_AND	4 /* bool && bool */
+#define COND_XOR	5 /* bool ^ bool */
+#define COND_EQ		6 /* bool == bool */
+#define COND_NEQ	7 /* bool != bool */
+#define COND_LAST	8
+	__u32 expr_type;
+	__u32 bool;
+	struct cond_expr *next;
+};
+
+/*
+ * Each cond_node contains a list of rules to be enabled/disabled
+ * depending on the current value of the conditional expression. This
+ * struct is for that list.
+ */
+struct cond_av_list {
+	struct avtab_node *node;
+	struct cond_av_list *next;
+};
+
+/*
+ * A cond node represents a conditional block in a policy. It
+ * contains a conditional expression, the current state of the expression,
+ * two lists of rules to enable/disable depending on the value of the
+ * expression (the true list corresponds to if and the false list corresponds
+ * to else)..
+ */
+struct cond_node {
+	int cur_state;
+	struct cond_expr *expr;
+	struct cond_av_list *true_list;
+	struct cond_av_list *false_list;
+	struct cond_node *next;
+};
+
+int cond_policydb_init(struct policydb* p);
+void cond_policydb_destroy(struct policydb* p);
+
+int cond_init_bool_indexes(struct policydb* p);
+int cond_destroy_bool(void *key, void *datum, void *p);
+
+int cond_index_bool(void *key, void *datum, void *datap);
+
+int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
+int cond_read_list(struct policydb *p, void *fp);
+
+void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decision *avd);
+
+int evaluate_cond_node(struct policydb *p, struct cond_node *node);
+
+#endif /* _CONDITIONAL_H_ */
diff -Nru a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
--- a/security/selinux/ss/mls.h	Wed Mar 17 19:29:09 2004
+++ b/security/selinux/ss/mls.h	Wed Mar 17 19:29:09 2004
@@ -48,12 +48,12 @@
 
 #define mls_end_user_ranges } }
 
-#define mls_symtab_names , "levels", "categories"
-#define mls_symtab_sizes , 16, 16
-#define mls_index_f ,sens_index, cat_index
-#define mls_destroy_f ,sens_destroy, cat_destroy
-#define mls_read_f ,sens_read, cat_read
-#define mls_write_f ,sens_write, cat_write
+#define mls_symtab_names  "levels", "categories",
+#define mls_symtab_sizes  16, 16,
+#define mls_index_f sens_index, cat_index,
+#define mls_destroy_f sens_destroy, cat_destroy,
+#define mls_read_f sens_read, cat_read,
+#define mls_write_f sens_write, cat_write,
 #define mls_policydb_index_others(p) printk(", %d levels", p->nlevels);
 
 #define mls_set_config(config) config |= POLICYDB_CONFIG_MLS
diff -Nru a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
--- a/security/selinux/ss/policydb.c	Wed Mar 17 19:29:09 2004
+++ b/security/selinux/ss/policydb.c	Wed Mar 17 19:29:09 2004
@@ -3,12 +3,25 @@
  *
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
+
+/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * 	Added conditional policy language extensions
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ *	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.
+ */
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include "security.h"
+
 #include "policydb.h"
+#include "conditional.h"
 #include "mls.h"
 
 #define _DEBUG_HASHES
@@ -19,8 +32,9 @@
 	"classes",
 	"roles",
 	"types",
-	"users"
+	"users",
 	mls_symtab_names
+	"bools"
 };
 #endif
 
@@ -29,8 +43,9 @@
 	32,
 	16,
 	512,
-	128
+	128,
 	mls_symtab_sizes
+	16
 };
 
 /*
@@ -95,6 +110,10 @@
 	if (rc)
 		goto out_free_avtab;
 
+	rc = cond_policydb_init(p);
+	if (rc)
+		goto out_free_avtab;
+
 out:
 	return rc;
 
@@ -195,8 +214,9 @@
 	class_index,
 	role_index,
 	type_index,
-	user_index
+	user_index,
 	mls_index_f
+	cond_index_bool
 };
 
 /*
@@ -267,8 +287,8 @@
 {
 	int i, rc = 0;
 
-	printk(KERN_INFO "security:  %d users, %d roles, %d types",
-	       p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim);
+	printk(KERN_INFO "security:  %d users, %d roles, %d types, %d bools",
+	       p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
 	mls_policydb_index_others(p);
 	printk("\n");
 
@@ -296,6 +316,11 @@
 		goto out;
 	}
 
+	if (cond_init_bool_indexes(p)) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
 	for (i = SYM_ROLES; i < SYM_NUM; i++) {
 		p->sym_val_to_name[i] =
 			kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL);
@@ -402,8 +427,9 @@
 	class_destroy,
 	role_destroy,
 	type_destroy,
-	user_destroy
+	user_destroy,
 	mls_destroy_f
+	cond_destroy_bool
 };
 
 void ocontext_destroy(struct ocontext *c, int i)
@@ -467,6 +493,8 @@
 		kfree(gtmp);
 	}
 
+	cond_policydb_destroy(p);
+
 	return;
 }
 
@@ -1040,8 +1068,9 @@
 	class_read,
 	role_read,
 	type_read,
-	user_read
+	user_read,
 	mls_read_f
+	cond_read_bool
 };
 
 #define mls_config(x) \
@@ -1057,7 +1086,7 @@
 	struct role_trans *tr, *ltr;
 	struct ocontext *l, *c, *newc;
 	struct genfs *genfs_p, *genfs, *newgenfs;
-	int i, j, rc;
+	int i, j, rc, policy_ver, num_syms;
 	u32 *buf, len, len2, config, nprim, nel, nel2;
 	char *policydb_str;
 
@@ -1122,7 +1151,8 @@
 	for (i = 0; i < 4; i++)
 		buf[i] = le32_to_cpu(buf[i]);
 
-	if (buf[0] != POLICYDB_VERSION) {
+	policy_ver = buf[0];
+	if (policy_ver != POLICYDB_VERSION && policy_ver != POLICYDB_VERSION_COMPAT) {
 		printk(KERN_ERR "security:  policydb version %d does not match "
 		       "my version %d\n", buf[0], POLICYDB_VERSION);
 		goto bad;
@@ -1134,18 +1164,30 @@
 		       mls_config(config));
 		goto bad;
 	}
-	if (buf[2] != SYM_NUM || buf[3] != OCON_NUM) {
-		printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
-		       "not match mine (%d,%d)\n",
-		       buf[2], buf[3], SYM_NUM, OCON_NUM);
-		goto bad;
+
+	if (policy_ver == POLICYDB_VERSION_COMPAT) {
+		if (buf[2] != (SYM_NUM - 1) || buf[3] != OCON_NUM) {
+			printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
+			       "not match mine (%d,%d)\n",
+			       buf[2], buf[3], SYM_NUM, OCON_NUM);
+			goto bad;
+		}
+		num_syms = SYM_NUM - 1;
+	} else {
+		if (buf[2] != SYM_NUM || buf[3] != OCON_NUM) {
+			printk(KERN_ERR "security:  policydb table sizes (%d,%d) do "
+			       "not match mine (%d,%d)\n",
+			       buf[2], buf[3], SYM_NUM, OCON_NUM);
+			goto bad;
+		}
+		num_syms = SYM_NUM;
 	}
 
 	rc = mls_read_nlevels(p, fp);
 	if (rc)
 		goto bad;
 
-	for (i = 0; i < SYM_NUM; i++) {
+	for (i = 0; i < num_syms; i++) {
 		buf = next_entry(fp, sizeof(u32)*2);
 		if (!buf) {
 			rc = -EINVAL;
@@ -1165,6 +1207,12 @@
 	rc = avtab_read(&p->te_avtab, fp, config);
 	if (rc)
 		goto bad;
+
+	if (policy_ver == POLICYDB_VERSION) {
+		rc = cond_read_list(p, fp);
+		if (rc)
+			goto bad;
+	}
 
 	buf = next_entry(fp, sizeof(u32));
 	if (!buf) {
diff -Nru a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
--- a/security/selinux/ss/policydb.h	Wed Mar 17 19:29:10 2004
+++ b/security/selinux/ss/policydb.h	Wed Mar 17 19:29:10 2004
@@ -4,6 +4,17 @@
  *
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
+
+/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * 	Added conditional policy language extensions
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ *	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.
+ */
+
 #ifndef _SS_POLICYDB_H_
 #define _SS_POLICYDB_H_
 
@@ -100,6 +111,13 @@
 };
 #endif
 
+/* Boolean data type */
+struct cond_bool_datum {
+	__u32 value;		/* internal type value */
+	int state;
+};
+
+struct cond_node;
 
 /*
  * The configuration data includes security contexts for
@@ -145,9 +163,11 @@
 #ifdef CONFIG_SECURITY_SELINUX_MLS
 #define SYM_LEVELS  5
 #define SYM_CATS    6
-#define SYM_NUM     7
+#define SYM_BOOLS   7
+#define SYM_NUM     8
 #else
-#define SYM_NUM     5
+#define SYM_BOOLS   5
+#define SYM_NUM     6
 #endif
 
 /* object context array indices */
@@ -170,6 +190,7 @@
 #define p_users symtab[SYM_USERS]
 #define p_levels symtab[SYM_LEVELS]
 #define p_cats symtab[SYM_CATS]
+#define p_bools symtab[SYM_BOOLS]
 
 	/* symbol names indexed by (value - 1) */
 	char **sym_val_to_name[SYM_NUM];
@@ -180,6 +201,7 @@
 #define p_user_val_to_name sym_val_to_name[SYM_USERS]
 #define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
 #define p_cat_val_to_name sym_val_to_name[SYM_CATS]
+#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
 
 	/* class, role, and user attributes indexed by (value - 1) */
 	struct class_datum **class_val_to_struct;
@@ -191,6 +213,13 @@
 
 	/* role transitions */
 	struct role_trans *role_tr;
+
+	/* bools indexed by (value - 1) */
+	struct cond_bool_datum **bool_val_to_struct;
+	/* type enforcement conditional access vectors and transitions */
+	struct avtab te_cond_avtab;
+	/* linked list indexing te_cond_avtab by conditional */
+	struct cond_node* cond_list;
 
 	/* role allows */
 	struct role_allow *role_allow;
diff -Nru a/security/selinux/ss/services.c b/security/selinux/ss/services.c
--- a/security/selinux/ss/services.c	Wed Mar 17 19:29:10 2004
+++ b/security/selinux/ss/services.c	Wed Mar 17 19:29:10 2004
@@ -9,6 +9,15 @@
  *	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.
+ *
+ * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * 	Added conditional policy language extensions
+ *
+ * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ *	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.
  */
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -26,6 +35,7 @@
 #include "policydb.h"
 #include "sidtab.h"
 #include "services.h"
+#include "conditional.h"
 #include "mls.h"
 
 extern void selnl_notify_policyload(u32 seqno);
@@ -225,6 +235,9 @@
 			avd->auditallow = avtab_auditallow(avdatum);
 	}
 
+	/* Check conditional av table for additional permissions */
+	cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
+
 	/*
 	 * Remove any permissions prohibited by the MLS policy.
 	 */
@@ -249,7 +262,7 @@
 	 * pair.
 	 */
 	if (tclass == SECCLASS_PROCESS &&
-	    avd->allowed && PROCESS__TRANSITION &&
+	    (avd->allowed & PROCESS__TRANSITION) &&
 	    scontext->role != tcontext->role) {
 		for (ra = policydb.role_allow; ra; ra = ra->next) {
 			if (scontext->role == ra->role &&
@@ -573,6 +586,7 @@
 	struct role_trans *roletr = 0;
 	struct avtab_key avkey;
 	struct avtab_datum *avdatum;
+	struct avtab_node *node;
 	unsigned int type_change = 0;
 	int rc = 0;
 
@@ -639,6 +653,18 @@
 	avkey.target_type = tcontext->type;
 	avkey.target_class = tclass;
 	avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE);
+
+	/* If no permanent rule, also check for enabled conditional rules */
+	if(!avdatum) {
+		node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified);
+		for (; node != NULL; node = avtab_search_node_next(node, specified)) {
+			if (node->datum.specified & AVTAB_ENABLED) {
+				avdatum = &node->datum;
+				break;
+			}
+		}
+	}
+
 	type_change = (avdatum && (avdatum->specified & specified));
 	if (type_change) {
 		/* Use the type from the type transition/member/change rule. */
@@ -1000,6 +1026,7 @@
 			return -EINVAL;
 		}
 		ss_initialized = 1;
+
 		LOAD_UNLOCK;
 		selinux_complete_init();
 		return 0;
@@ -1046,6 +1073,7 @@
 	memcpy(&policydb, &newpolicydb, sizeof policydb);
 	sidtab_set(&sidtab, &newsidtab);
 	seqno = ++latest_granting;
+
 	POLICY_WRUNLOCK;
 	LOAD_UNLOCK;
 
@@ -1424,6 +1452,119 @@
 		}
 	}
 
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
+int security_get_bools(int *len, char ***names, int **values)
+{
+	int i, rc = -ENOMEM;
+
+	POLICY_RDLOCK;
+	*names = NULL;
+	*values = NULL;
+
+	*len = policydb.p_bools.nprim;
+	if (!*len) {
+		rc = 0;
+		goto out;
+	}
+
+	*names = (char**)kmalloc(sizeof(char*) * *len, GFP_ATOMIC);
+	if (!*names)
+		goto err;
+	memset(*names, 0, sizeof(char*) * *len);
+
+	*values = (int*)kmalloc(sizeof(int) * *len, GFP_ATOMIC);
+	if (!*values)
+		goto err;
+
+	for (i = 0; i < *len; i++) {
+		size_t name_len;
+		(*values)[i] = policydb.bool_val_to_struct[i]->state;
+		name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
+		(*names)[i] = (char*)kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
+		if (!(*names)[i])
+			goto err;
+		strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
+		(*names)[i][name_len - 1] = 0;
+	}
+	rc = 0;
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+err:
+	if (*names) {
+		for (i = 0; i < *len; i++)
+			if ((*names)[i])
+				kfree((*names)[i]);
+	}
+	if (*values)
+		kfree(*values);
+	goto out;
+}
+
+
+int security_set_bools(int len, int *values)
+{
+	int i, rc = 0;
+	int lenp, seqno = 0;
+	struct cond_node *cur;
+
+	POLICY_WRLOCK;
+
+	lenp = policydb.p_bools.nprim;
+	if (len != lenp) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	printk(KERN_INFO "security: committed booleans { ");
+	for (i = 0; i < len; i++) {
+		if (values[i]) {
+			policydb.bool_val_to_struct[i]->state = 1;
+		} else {
+			policydb.bool_val_to_struct[i]->state = 0;
+		}
+		if (i != 0)
+			printk(", ");
+		printk("%s:%d", policydb.p_bool_val_to_name[i],
+		       policydb.bool_val_to_struct[i]->state);
+	}
+	printk(" }\n");
+
+	for (cur = policydb.cond_list; cur != NULL; cur = cur->next) {
+		rc = evaluate_cond_node(&policydb, cur);
+		if (rc)
+			goto out;
+	}
+
+	seqno = ++latest_granting;
+
+out:
+	POLICY_WRUNLOCK;
+	if (!rc) {
+		avc_ss_reset(seqno);
+		selnl_notify_policyload(seqno);
+	}
+	return rc;
+}
+
+int security_get_bool_value(int bool)
+{
+	int rc = 0;
+	int len;
+
+	POLICY_RDLOCK;
+
+	len = policydb.p_bools.nprim;
+	if (bool >= len) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	rc = policydb.bool_val_to_struct[bool]->state;
 out:
 	POLICY_RDUNLOCK;
 	return rc;
