http://linux.bkbits.net/linux-2.5
ak@muc.de[torvalds]|ChangeSet|20041028232035|44146 ak
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/10/28 16:20:35-07:00 ak@muc.de 
#   [PATCH] Fix x86-64 genapic build
#   
#   The x86-64 genapic patch that was recently merged missed some definitions
#   and doesn't compile at all.
#   
#   This fixes it by adding the missing defines for genapic
#   
#   Signed-off-by: Andi Kleen <ak@muc.de>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-x86_64/apicdef.h
#   2004/10/16 01:30:51-07:00 ak@muc.de +3 -0
#   Fix x86-64 genapic build
# 
# ChangeSet
#   2004/10/28 16:20:25-07:00 trini@kernel.crashing.org 
#   [PATCH] Fix ppc32 compile
#   
#   D'oh.  Something got cut-off there on Randy's end.  Obviously correct
#   fix follows.
#   
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/platforms/prep_setup.c
#   2004/10/28 13:55:20-07:00 trini@kernel.crashing.org +2 -1
#   Fix ppc32 compile
# 
# ChangeSet
#   2004/10/28 12:58:55-07:00 olh@suse.de 
#   [PATCH] rmmod ohci1394 hangs
#   
#   this sequence of commands will hang the final rmmod.
#   
#   	init=/bin/bash --login
#   	mount proc
#   	modprove -v ohci1394
#   	rmmod ohci1394
#   	modprobe -v ohci1394
#   	rmmod ohci1394  ->  hangs
#   
#   knodemgrd_0 exits on the first rmmod, but leaves nodemgr_serialize in down
#   state.
#   
#   This fixes it for me.
#   
#   Signed-off-by: Olaf Hering <olh@suse.de>
#   Acked-by: Ben Collins <bcollins@debian.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/ieee1394/nodemgr.c
#   2004/10/28 12:46:54-07:00 olh@suse.de +6 -2
#   rmmod ohci1394 hangs
# 
# ChangeSet
#   2004/10/28 12:11:00-07:00 torvalds@ppc970.osdl.org 
#   Merge http://lia64.bkbits.net/linux-ia64-release-2.6.10
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# include/asm-ia64/io.h
#   2004/10/28 12:10:56-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/28 10:07:59-07:00 sfr@canb.auug.org.au 
#   [PATCH] ppc64 iSeries pci cleanups
#   
#   This merges two files (iSeries_IoMmTable.[ch]) into iSeries_pci.c.  This
#   allowed quite a few more things to become declared static.
#   
#   It then does some fairly mechanical cleanups in iSeries_pci.c (replacing
#   studly caps, removing the last of the PCIFR() macros and removing a
#   couple of empty or unused routines).  There are no semantic changes. 
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/iSeries_pci.c
#   2004/10/27 01:43:41-07:00 sfr@canb.auug.org.au +138 -49
#   ppc64 iSeries pci cleanups
# 
# arch/ppc64/kernel/Makefile
#   2004/10/27 21:50:05-07:00 sfr@canb.auug.org.au +1 -2
#   ppc64 iSeries pci cleanups
# 
# BitKeeper/deleted/.del-iSeries_IoMmTable.h~e27021ebd5cdd3ee
#   2004/10/28 10:07:52-07:00 sfr@canb.auug.org.au +0 -0
#   Delete: arch/ppc64/kernel/iSeries_IoMmTable.h
# 
# BitKeeper/deleted/.del-iSeries_IoMmTable.c~60ca6231a8780121
#   2004/10/28 10:07:52-07:00 sfr@canb.auug.org.au +0 -0
#   Delete: arch/ppc64/kernel/iSeries_IoMmTable.c
# 
# ChangeSet
#   2004/10/28 09:31:02-07:00 martin.wilck@fujitsu-siemens.com 
#   [PATCH] skip sync_arb_IDs on P4/Xeon
#   
#   The "Synchronize Arbitration IDs with APIC IDs" IPI does not make sense
#   on Pentium 4 and Xeon because they don't have an APIC bus where
#   arbitration IDs would be needed. 
#   
#   The Intel Developers manual (Vol.  3, Ch.  8.6.1) says this IPI is
#   unsupported on P4/Xeon.  Using it may, according to Intel, lead to
#   unpredictable results.
#   
#   Signed-off-by: Martin Wilck <martin.wilck@fujitsu-siemens.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/apic.c
#   2004/10/26 05:18:47-07:00 martin.wilck@fujitsu-siemens.com +4 -0
#   skip sync_arb_IDs on P4/Xeon
# 
# ChangeSet
#   2004/10/28 09:14:32-07:00 stelian@popies.net 
#   [PATCH] sonypi: bump up the version number
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/sonypi.h
#   2004/10/28 02:20:55-07:00 stelian@popies.net +1 -1
#   sonypi: bump up the version number
# 
# ChangeSet
#   2004/10/28 09:14:19-07:00 stelian@popies.net 
#   [PATCH] sonypi: whitespace and coding style fixes
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/sonypi.h
#   2004/10/28 02:18:59-07:00 stelian@popies.net +8 -8
#   sonypi: whitespace and coding style fixes
# 
# drivers/char/sonypi.h
#   2004/10/28 02:18:59-07:00 stelian@popies.net +9 -9
#   sonypi: whitespace and coding style fixes
# 
# drivers/char/sonypi.c
#   2004/10/28 02:18:59-07:00 stelian@popies.net +155 -130
#   sonypi: whitespace and coding style fixes
# 
# ChangeSet
#   2004/10/28 09:14:07-07:00 stelian@popies.net 
#   [PATCH] sonypi: don't suppose the bluetooth subsystem is initialy off
#   
#   Leave the choice to the user.
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/sonypi.c
#   2004/10/28 02:13:37-07:00 stelian@popies.net +1 -1
#   sonypi: don't suppose the bluetooth subsystem is initialy off
# 
# ChangeSet
#   2004/10/28 09:13:54-07:00 stelian@popies.net 
#   [PATCH] sonypi: make CONFIG_SONYPI depend on CONFIG_INPUT
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/Kconfig
#   2004/10/28 02:09:18-07:00 stelian@popies.net +1 -1
#   sonypi: make CONFIG_SONYPI depend on CONFIG_INPUT
# 
# ChangeSet
#   2004/10/28 09:13:42-07:00 stelian@popies.net 
#   [PATCH] sonypi: rework input support
#   
#    * feed most of special keys through the input subsystem
#    * initialize two separate input devices: a mouse like one for
#      the jogdial and a keyboard like one for the special keys
#    * add support for SONYPI_EVENT_FNKEY_RELEASED
#   
#   Many people participated in a way or another to this patch, 
#   including Daniel K. <daniel@cluded.net>, Bastien Nocera <hadess@hadess.net>,
#   Dmitry Torokhov <dtor@mail.ru> and Vojtech Pavlik <vojtech@suse.cz>.
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/sonypi.h
#   2004/10/28 02:06:42-07:00 stelian@popies.net +1 -0
#   sonypi: rework input support
# 
# include/linux/input.h
#   2004/10/28 02:06:42-07:00 stelian@popies.net +22 -0
#   sonypi: rework input support
# 
# drivers/char/sonypi.h
#   2004/10/28 02:06:42-07:00 stelian@popies.net +48 -14
#   sonypi: rework input support
# 
# drivers/char/sonypi.c
#   2004/10/28 02:06:42-07:00 stelian@popies.net +134 -35
#   sonypi: rework input support
# 
# ChangeSet
#   2004/10/28 09:13:29-07:00 stelian@popies.net 
#   [PATCH] sonypi: power management related fixes
#   
#    * switch from a sysdev to a platform device
#    * drop old style PM code
#    * use pci_get_device()/pci_dev_put() instead of pci_find_device()
#   
#   Patch originaly from Dmitry Torokhov <dtor@mail.ru>.
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/sonypi.h
#   2004/10/28 02:03:43-07:00 stelian@popies.net +1 -4
#   sonypi: power management related fixes
# 
# drivers/char/sonypi.c
#   2004/10/28 02:03:43-07:00 stelian@popies.net +94 -122
#   sonypi: power management related fixes
# 
# ChangeSet
#   2004/10/28 09:13:17-07:00 stelian@popies.net 
#   [PATCH] sonypi: replace homebrew queue with kfifo
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/sonypi.h
#   2004/10/28 02:01:57-07:00 stelian@popies.net +6 -11
#   sonypi: replace homebrew queue with kfifo
# 
# drivers/char/sonypi.c
#   2004/10/28 02:01:57-07:00 stelian@popies.net +42 -90
#   sonypi: replace homebrew queue with kfifo
# 
# ChangeSet
#   2004/10/28 09:13:05-07:00 stelian@popies.net 
#   [PATCH] sonypi: module related fixes
#   
#    * use module_param() instead of MODULE_PARM() and __setup()
#    * use MODULE_VERSION()
#   
#   Signed-off-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/sonypi.h
#   2004/10/28 02:01:10-07:00 stelian@popies.net +1 -31
#   sonypi: module related fixes
# 
# drivers/char/sonypi.c
#   2004/10/28 02:01:10-07:00 stelian@popies.net +77 -70
#   sonypi: module related fixes
# 
# Documentation/sonypi.txt
#   2004/10/28 02:01:09-07:00 stelian@popies.net +4 -7
#   sonypi: module related fixes
# 
# Documentation/kernel-parameters.txt
#   2004/10/28 02:01:10-07:00 stelian@popies.net +2 -2
#   sonypi: module related fixes
# 
# ChangeSet
#   2004/10/28 08:35:45-07:00 chrisw@osdl.org 
#   [PATCH] error out on execve with no binfmts
#   
#   Early calls to userspace can invoke an execve() before any binfmt handlers
#   are registered.  Properly return an error in this case rather than 0.
#   On at least one arch (x86_64) without this patch, the system will double
#   fault on early attempts to call_usermodehelper.
#   
#   Signed-off-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/exec.c
#   2004/10/28 00:40:03-07:00 chrisw@osdl.org +2 -1
#   error out on execve with no binfmts
# 
# ChangeSet
#   2004/10/28 08:35:33-07:00 cw@f00f.org 
#   [PATCH] Remove build warning from drivers/char/random.c on 32-bit platforms
#   
#   Remove build warning from drivers/char/random.c on 32-bit platforms.
#   
#   Signed-off-by: Chris Wedgwood <cw@f00f.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2004/10/28 00:40:02-07:00 cw@f00f.org +3 -5
#   Remove build warning from drivers/char/random.c on 32-bit platforms
# 
# ChangeSet
#   2004/10/28 08:35:20-07:00 olh@suse.de 
#   [PATCH] remove double newline from sysrq action_msg
#   
#   __handle_sysrq already prints a newline, so the action_msg string doesnt
#   need yet another newline.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/poweroff.c
#   2004/10/28 00:40:02-07:00 olh@suse.de +1 -1
#   remove double newline from sysrq action_msg
# 
# arch/ppc64/xmon/start.c
#   2004/10/28 00:40:02-07:00 olh@suse.de +1 -1
#   remove double newline from sysrq action_msg
# 
# arch/ppc/xmon/start.c
#   2004/10/28 00:40:02-07:00 olh@suse.de +1 -1
#   remove double newline from sysrq action_msg
# 
# arch/i386/mach-voyager/voyager_basic.c
#   2004/10/28 00:40:02-07:00 olh@suse.de +1 -1
#   remove double newline from sysrq action_msg
# 
# ChangeSet
#   2004/10/28 08:35:08-07:00 kraxel@bytesex.org 
#   [PATCH] bttv subdev fix
#   
#   - Make bttv check the device_register return value.
#   
#   - Yet another unchecked return value fixed.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/bttv-gpio.c
#   2004/10/28 00:40:02-07:00 kraxel@bytesex.org +7 -3
#   bttv subdev fix
# 
# ChangeSet
#   2004/10/28 08:34:55-07:00 axboe@suse.de 
#   [PATCH] issues with online scheduler switching
#   
#   There are two issues with online io scheduler switching that this patch
#   addresses.  The first is pretty simple - it concerns racing with scheduler
#   removal on switch.  elevator_find() does not grab a reference to the io
#   scheduler, so before elevator_attach() is run it could go away.  Add
#   elevator_get() to solve that.
#   
#   Second issue is the flushing out of requests that is needed before
#   switching can be problematic with requests that aren't allocated in the
#   block layer (such as requests on the stack of a process).  The problem is
#   that we don't know when they will have finished, and most io schedulers
#   need to access the elevator structures on io completion.  This can be fixed
#   by adding an intermedia step that switches to noop, since it doesn't need
#   to touch anything but the request_queue.  The queue drain can then safely
#   be split into two operations - one that waits for file system requests, and
#   one that waits for the queue to completely empty.  Requests arriving after
#   the first drain will get stuck in a seperate queue list.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/blkdev.h
#   2004/10/28 00:40:02-07:00 axboe@suse.de +3 -1
#   issues with online scheduler switching
# 
# drivers/block/ll_rw_blk.c
#   2004/10/28 00:40:02-07:00 axboe@suse.de +27 -3
#   issues with online scheduler switching
# 
# drivers/block/elevator.c
#   2004/10/28 00:40:02-07:00 axboe@suse.de +80 -25
#   issues with online scheduler switching
# 
# ChangeSet
#   2004/10/28 08:34:43-07:00 manfred@colorfullife.com 
#   [PATCH] handle posix message queues with /proc/sys disabled
#   
#   register_sysctl_table() fails if sysctl support is not compiled into the
#   kernel.  The POSIX message queue subsystem aborted it's initialization if
#   register_sysctl_table() fails, and that causes an oops in sys_mq_open().
#   The patch fixes that by ignoring failures from register_sysctl_table().
#   
#   Signed-off-by; Manfred Spraul <manfred@colorfullife.com>
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ipc/mqueue.c
#   2004/10/28 00:40:01-07:00 manfred@colorfullife.com +3 -6
#   handle posix message queues with /proc/sys disabled
# 
# ChangeSet
#   2004/10/28 08:34:31-07:00 axboe@suse.de 
#   [PATCH] cfq v2 switch bug
#   
#   Fix online switching issue with cfq v2.  It does deferred clearing of
#   e->elevator_data, which screws up the current io scheduler.  It does not
#   have to, so just remove it.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/cfq-iosched.c
#   2004/10/28 00:40:02-07:00 axboe@suse.de +0 -2
#   cfq v2 switch bug
# 
# ChangeSet
#   2004/10/28 08:34:18-07:00 wli@holomorphy.com 
#   [PATCH] remove itimer_ticks and itimer_next
#   
#   These two variables are long, long dead. This patch removes them.
#   
#   Signed-off-by: William Irwin <wli@holomorphy.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/sched.h
#   2004/10/28 00:40:02-07:00 wli@holomorphy.com +0 -2
#   remove itimer_ticks and itimer_next
# 
# ChangeSet
#   2004/10/28 08:34:06-07:00 colin@colino.net 
#   [PATCH] fix via-pmu.c compilation without CONFIG_PMAC_PBOOK
#   
#   This patch fixes via-pmu.c compilation when CONFIG_PMAC_PBOOK is not set.
#   Looks like the #endif was one line too late.
#   
#   Signed-off-by: Colin Leroy <colin@colino.net>
#   Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/macintosh/via-pmu.c
#   2004/10/28 00:40:01-07:00 colin@colino.net +1 -1
#   fix via-pmu.c compilation without CONFIG_PMAC_PBOOK
# 
# ChangeSet
#   2004/10/28 08:33:53-07:00 hch@lst.de 
#   [PATCH] remove mousedrivers.sgml
#   
#   It's been totally obsoleted by the input layer
#   
#   Acked-by: Alan Cox <alan@redhat.com>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/DocBook/Makefile
#   2004/10/28 00:40:01-07:00 hch@lst.de +3 -3
#   remove mousedrivers.sgml
# 
# BitKeeper/deleted/.del-mousedrivers.tmpl~35c97c24ff898e5d
#   2004/10/28 08:33:46-07:00 hch@lst.de +0 -0
#   Delete: Documentation/DocBook/mousedrivers.tmpl
# 
# ChangeSet
#   2004/10/28 08:33:43-07:00 hch@lst.de 
#   [PATCH] remove invoke_softirq
#   
#   This was used by the early irqstacks implementation on s390 and has been
#   replaced by __ARCH_HAS_DO_SOFTIRQ now.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/softirq.c
#   2004/10/28 00:40:00-07:00 hch@lst.de +1 -1
#   remove invoke_softirq
# 
# include/linux/interrupt.h
#   2004/10/28 00:40:01-07:00 hch@lst.de +0 -4
#   remove invoke_softirq
# 
# ChangeSet
#   2004/10/28 08:33:30-07:00 hch@lst.de 
#   [PATCH] fix show_refcnt return value type
#   
#   module_attribute.show is defined to return ssize_t
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/module.c
#   2004/10/28 00:40:00-07:00 hch@lst.de +1 -1
#   fix show_refcnt return value type
# 
# ChangeSet
#   2004/10/28 08:33:18-07:00 tglx@linutronix.de 
#   [PATCH] Lock initializer unifying (Network drivers)
#   
#   To make spinlock/rwlock initialization consistent all over the kernel,
#   this patch converts explicit lock-initializers into spin_lock_init() and
#   rwlock_init() calls.
#   
#   Currently, spinlocks and rwlocks are initialized in two different ways:
#   
#     lock = SPIN_LOCK_UNLOCKED
#     spin_lock_init(&lock)
#   
#     rwlock = RW_LOCK_UNLOCKED
#     rwlock_init(&rwlock)
#   
#   this patch converts all explicit lock initializations to
#   spin_lock_init() or rwlock_init(). (Besides consistency this also helps
#   automatic lock validators and debugging code.)
#   
#   The conversion was done with a script, it was verified manually and it
#   was reviewed, compiled and tested as far as possible on x86, ARM, PPC.
#   
#   There is no runtime overhead or actual code change resulting out of this
#   patch, because spin_lock_init() and rwlock_init() are macros and are
#   thus equivalent to the explicit initialization method.
#   
#   Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/znet.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/wireless/airo.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/wan/cycx_x25.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/wan/cycx_main.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/tulip/xircom_tulip_cb.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/tulip/xircom_cb.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/tulip/de4x5.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +2 -2
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/tokenring/ibmtr.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/sundance.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/ppp_generic.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/pci-skeleton.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/lasi_82596.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/hamradio/mkiss.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/depca.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/atarilance.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/82596.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# drivers/net/7990.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Network drivers)
# 
# ChangeSet
#   2004/10/28 08:33:04-07:00 tglx@linutronix.de 
#   [PATCH] Lock initializer unifying (Core)
#   
#   To make spinlock/rwlock initialization consistent all over the kernel,
#   this patch converts explicit lock-initializers into spin_lock_init() and
#   rwlock_init() calls.
#   
#   Currently, spinlocks and rwlocks are initialized in two different ways:
#   
#     lock = SPIN_LOCK_UNLOCKED
#     spin_lock_init(&lock)
#   
#     rwlock = RW_LOCK_UNLOCKED
#     rwlock_init(&rwlock)
#   
#   this patch converts all explicit lock initializations to
#   spin_lock_init() or rwlock_init(). (Besides consistency this also helps
#   automatic lock validators and debugging code.)
#   
#   The conversion was done with a script, it was verified manually and it
#   was reviewed, compiled and tested as far as possible on x86, ARM, PPC.
#   
#   There is no runtime overhead or actual code change resulting out of this
#   patch, because spin_lock_init() and rwlock_init() are macros and are
#   thus equivalent to the explicit initialization method.
#   
#   Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/swapfile.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Core)
# 
# kernel/futex.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Core)
# 
# kernel/fork.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +4 -4
#   Lock initializer unifying (Core)
# 
# ipc/util.c
#   2004/10/28 00:40:00-07:00 tglx@linutronix.de +1 -1
#   Lock initializer unifying (Core)
# 
# ChangeSet
#   2004/10/28 08:32:52-07:00 pluto@ds14.agh.edu.pl 
#   [PATCH] signal.c: gcc-3.4 fix
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2004/10/28 00:40:00-07:00 pluto@ds14.agh.edu.pl +1 -1
#   signal.c: gcc-3.4 fix
# 
# ChangeSet
#   2004/10/28 08:32:40-07:00 james4765@gmail.com 
#   [PATCH] ftape documentation fixes
#   
#   Description: Cleanup and update to Documentation/ftape.txt
#   
#   Signed-off by: James Nelson <james4765@gmail.com>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/ftape.txt
#   2004/10/28 00:39:59-07:00 james4765@gmail.com +38 -56
#   ftape documentation fixes
# 
# ChangeSet
#   2004/10/28 08:32:27-07:00 james4765@gmail.com 
#   [PATCH] ftape has no maintainer
#   
#   After tracking down the original author of the ftape sources, I found out
#   that he no longer had interest in maintaining it.
#   
#   Signed-off-by: James Nelson <james4765@gmail.com>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# MAINTAINERS
#   2004/10/28 00:39:59-07:00 james4765@gmail.com +2 -4
#   ftape has no maintainer
# 
# ChangeSet
#   2004/10/28 08:32:15-07:00 werner@almesberger.net 
#   [PATCH] make buffer head argument of buffer_##name "const"
#   
#   Allow the buffer_foo() predicates to take a (const struct buffer_head *).
#   
#   I've checked that the argument of test_bit is indeed "const" on all
#   architectures.
#   
#   Signed-off-by: Werner Almesberger <werner@almesberger.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/buffer_head.h
#   2004/10/28 00:39:59-07:00 werner@almesberger.net +1 -1
#   make buffer head argument of buffer_##name "const"
# 
# ChangeSet
#   2004/10/28 08:32:02-07:00 juhl-lkml@dif.dk 
#   [PATCH] add a bunch of missing files to Documentation/00-INDEX
#   
#   Add a bunch of entries to Documentation/00-INDEX that are currently missing
#   (and removes the entry for one file that no longer exist).
#   
#   Patch has already been OK'ed by Paul G.
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/00-INDEX
#   2004/10/28 00:39:59-07:00 juhl-lkml@dif.dk +46 -4
#   add a bunch of missing files to Documentation/00-INDEX
# 
# ChangeSet
#   2004/10/28 08:31:50-07:00 petero2@telia.com 
#   [PATCH] Fix incorrect Mt Rainier detection
#   
#   cdrom_is_mrw() can incorrectly think that a drive is Mt Rainier capable,
#   because if forgets to check if the "GET CONFIGURATION" command returns the
#   MRW feature number.  According to the MMC spec, the drive shall return all
#   feature numbers >= the starting feature number, so even if the drive
#   doesn't support Mt Rainier, it can return some data that makes
#   cdrom_is_mrw() incorrectly think the drive is MRW capable.
#   
#   This problem stops me from mounting DVD+RW discs in R/W mode on my laptop,
#   because it makes cdrom_open_write() call cdrom_mrw_open_write() which fails
#   because the drive isn't really MRW capable.
#   
#   The fix is to make sure the returned feature number is the correct one for
#   Mt Rainier.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Acked-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/cdrom/cdrom.c
#   2004/10/28 00:39:59-07:00 petero2@telia.com +2 -0
#   Fix incorrect Mt Rainier detection
# 
# ChangeSet
#   2004/10/28 08:31:38-07:00 arjan@infradead.org 
#   [PATCH] unexport add_timer_on()
#   
#   add_timer_on() isn't used by modules (in fact it's only used ONCE, in
#   workqueue.c) and it's not even a good api for drivers, in fact, the comment
#   for it says
#   
#    * This is not very scalable on SMP. Double adds are not possible.
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/timer.c
#   2004/10/28 00:39:59-07:00 arjan@infradead.org +0 -1
#   unexport add_timer_on()
# 
# ChangeSet
#   2004/10/28 08:31:26-07:00 axboe@suse.de 
#   [PATCH] kill excessive cdrom prints
#   
#   Don't know where this came from, but dumping this on every open gets boring
#   really quickly.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/cdrom/cdrom.c
#   2004/10/28 00:56:33-07:00 axboe@suse.de +3 -5
#   kill excessive cdrom prints
# 
# ChangeSet
#   2004/10/28 08:31:13-07:00 dhowells@redhat.com 
#   [PATCH] Unexport some RxRPC symbols
#   
#   Remove some of the exports on RxRPC symbols that aren't currently used (and
#   most probably won't be) by external modules.
#   
#   Signed-off-by: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/rxrpc/rxrpc_syms.c
#   2004/10/28 00:39:58-07:00 dhowells@redhat.com +0 -15
#   Unexport some RxRPC symbols
# 
# ChangeSet
#   2004/10/28 08:31:00-07:00 james4765@gmail.com 
#   [PATCH] ramdisk.txt update
#   
#   General cleanup and updating of ramdisk.txt.
#   
#   Signed-off by: Jim Nelson <james4765@gmail.com>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/ramdisk.txt
#   2004/10/28 00:39:58-07:00 james4765@gmail.com +55 -94
#   ramdisk.txt update
# 
# ChangeSet
#   2004/10/28 08:30:48-07:00 hch@lst.de 
#   [PATCH] unexport firmware_class
#   
#   it's marked static already, and there's no point in exporting it
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/base/firmware_class.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -1
#   unexport firmware_class
# 
# ChangeSet
#   2004/10/28 08:30:36-07:00 hch@lst.de 
#   [PATCH] unexport set_selection and paste_selection
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/selection.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -3
#   unexport set_selection and paste_selection
# 
# ChangeSet
#   2004/10/28 08:30:25-07:00 hch@lst.de 
#   [PATCH] mark pi_unclaim static
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/paride/paride.h
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -2
#   mark pi_unclaim static
# 
# drivers/block/paride/paride.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +1 -3
#   mark pi_unclaim static
# 
# ChangeSet
#   2004/10/28 08:30:15-07:00 hch@lst.de 
#   [PATCH] unexport vc_cons_allocated
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/vt.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -1
#   unexport vc_cons_allocated
# 
# ChangeSet
#   2004/10/28 08:30:02-07:00 hch@lst.de 
#   [PATCH] parport: kill dead code and exports
#   
#   There's lots of exports in parport that aren't used by any drivers.  Behind
#   many of them there's actually dead code.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/parport.h
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -13
#   parport: kill dead code and exports
# 
# drivers/parport/share.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -1
#   parport: kill dead code and exports
# 
# drivers/parport/procfs.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -3
#   parport: kill dead code and exports
# 
# drivers/parport/probe.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -1
#   parport: kill dead code and exports
# 
# drivers/parport/ieee1284.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +1 -3
#   parport: kill dead code and exports
# 
# drivers/parport/daisy.c
#   2004/10/28 00:39:58-07:00 hch@lst.de +1 -154
#   parport: kill dead code and exports
# 
# ChangeSet
#   2004/10/28 08:29:50-07:00 hch@lst.de 
#   [PATCH] remove ext2 xatts exports
#   
#   I think Andreas exported them to allow modular xattr handlers, but with
#   James rework these aren't possible anymore, and we never had them anyway.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext2/xattr.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -5
#   remove ext2 xatts exports
# 
# ChangeSet
#   2004/10/28 08:29:39-07:00 hch@lst.de 
#   [PATCH] unexport sys_lseek
#   
#   Fortunately dvb stopped using it in their firmware loader
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/read_write.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -1
#   unexport sys_lseek
# 
# ChangeSet
#   2004/10/28 08:29:27-07:00 hch@lst.de 
#   [PATCH] remove page_follow_link
#   
#   All filesystems have been switched to page_follow_link_light
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fs.h
#   2004/10/28 00:39:58-07:00 hch@lst.de +0 -1
#   remove page_follow_link
# 
# fs/namei.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -13
#   remove page_follow_link
# 
# ChangeSet
#   2004/10/28 08:29:14-07:00 hch@lst.de 
#   [PATCH] unexport kick_process
#   
#   This isn't exactly the kind of interface modules should use.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -2
#   unexport kick_process
# 
# ChangeSet
#   2004/10/28 08:29:01-07:00 hch@lst.de 
#   [PATCH] unexport getnstimeofday
#   
#   This recently added function is only used by the posix timers code, no need
#   to be exported.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/time.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -2
#   unexport getnstimeofday
# 
# ChangeSet
#   2004/10/28 08:28:49-07:00 hch@lst.de 
#   [PATCH] remove dead exports in sounds/oss
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/sound_syms.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -3
#   remove dead exports in sounds/oss
# 
# sound/oss/sound_calls.h
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -1
#   remove dead exports in sounds/oss
# 
# sound/oss/msnd.h
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -4
#   remove dead exports in sounds/oss
# 
# sound/oss/msnd.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +2 -25
#   remove dead exports in sounds/oss
# 
# sound/oss/dev_table.h
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -1
#   remove dead exports in sounds/oss
# 
# sound/oss/dev_table.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +3 -1
#   remove dead exports in sounds/oss
# 
# sound/oss/audio_syms.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -3
#   remove dead exports in sounds/oss
# 
# sound/oss/audio.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +2 -2
#   remove dead exports in sounds/oss
# 
# sound/oss/aci.h
#   2004/10/28 00:39:57-07:00 hch@lst.de +0 -1
#   remove dead exports in sounds/oss
# 
# sound/oss/aci.c
#   2004/10/28 00:39:57-07:00 hch@lst.de +1 -2
#   remove dead exports in sounds/oss
# 
# ChangeSet
#   2004/10/28 08:28:37-07:00 paulmck@us.ibm.com 
#   [PATCH] RCU: eliminating explicit memory barriers from SysV IPC
#   
#   This patch uses the rcu_assign_pointer() API to eliminate a number of explicit
#   memory barriers from the SysV IPC code that uses RCU.  It also restructures
#   the ipc_ids structure so that the array size is stored in the same memory
#   block as the array itself (see the new struct ipc_id_ary).  This prevents the
#   race that the earlier code was subject to, where a reader could see a mismatch
#   between the size and the actual array.  With the size stored with the array,
#   the possibility of mismatch is eliminated -- with out the need for careful
#   ordering and explicit memory barriers.  This has been tested successfully on
#   i386 and ppc64.
#   
#   Signed-off-by: <paulmck@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ipc/util.h
#   2004/10/28 00:39:57-07:00 paulmck@us.ibm.com +7 -6
#   RCU: eliminating explicit memory barriers from SysV IPC
# 
# ipc/util.c
#   2004/10/28 00:56:32-07:00 paulmck@us.ibm.com +36 -44
#   RCU: eliminating explicit memory barriers from SysV IPC
# 
# ipc/sem.c
#   2004/10/28 00:39:57-07:00 paulmck@us.ibm.com +1 -1
#   RCU: eliminating explicit memory barriers from SysV IPC
# 
# ipc/msg.c
#   2004/10/28 00:39:57-07:00 paulmck@us.ibm.com +1 -1
#   RCU: eliminating explicit memory barriers from SysV IPC
# 
# ChangeSet
#   2004/10/28 08:28:24-07:00 paulmck@us.ibm.com 
#   [PATCH] RCU: use rcu_assign_pointer()
#   
#   This patch uses the rcu_assign_pointer() API to eliminate a number of explicit
#   memory barriers from code using RCU.  This has been tested successfully on
#   i386 and ppc64.
#   
#   Signed-off-by: <paulmck@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/sched/sch_api.c
#   2004/10/28 00:39:56-07:00 paulmck@us.ibm.com +1 -2
#   RCU: use rcu_assign_pointer()
# 
# net/ipv4/route.c
#   2004/10/28 00:39:56-07:00 paulmck@us.ibm.com +3 -4
#   RCU: use rcu_assign_pointer()
# 
# net/ipv4/devinet.c
#   2004/10/28 00:39:56-07:00 paulmck@us.ibm.com +1 -2
#   RCU: use rcu_assign_pointer()
# 
# net/decnet/dn_route.c
#   2004/10/28 00:39:57-07:00 paulmck@us.ibm.com +5 -8
#   RCU: use rcu_assign_pointer()
# 
# net/core/netfilter.c
#   2004/10/28 00:39:56-07:00 paulmck@us.ibm.com +1 -2
#   RCU: use rcu_assign_pointer()
# 
# include/linux/list.h
#   2004/10/28 00:39:57-07:00 paulmck@us.ibm.com +0 -2
#   RCU: use rcu_assign_pointer()
# 
# arch/x86_64/kernel/mce.c
#   2004/10/28 00:39:56-07:00 paulmck@us.ibm.com +1 -2
#   RCU: use rcu_assign_pointer()
# 
# ChangeSet
#   2004/10/28 08:28:13-07:00 paulmck@us.ibm.com 
#   [PATCH] RCU: rcu_assign_pointer() removal of memory barriers
#   
#   This patch adds the rcu_assign_pointer() API that helps reduce the need for
#   explicit memory barriers in code that uses RCU.  This API buries the required
#   memory barriers in a macro that also does the assignment.  This has been
#   tested successfully on i386 and ppc64.
#   
#   Signed-off-by: <paulmck@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/rcupdate.h
#   2004/10/28 00:39:57-07:00 paulmck@us.ibm.com +18 -0
#   RCU: rcu_assign_pointer() removal of memory barriers
# 
# ChangeSet
#   2004/10/28 08:28:00-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: config cleanups
#   
#   Cleanup the video4linux driver configuration by using "select" instead of
#   "default if ...".
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/Kconfig
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +15 -2
#   v4l: config cleanups
# 
# drivers/media/Kconfig
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +0 -12
#   v4l: config cleanups
# 
# ChangeSet
#   2004/10/28 08:27:48-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: videodev whitespace cleanup
#   
#   The patch just removes all trailing whitespaces, there are no actual code
#   changes.  I've a script to remove them from my sources now, that should kill
#   those no-op whitespace changes in my patches after merging this initial
#   cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/videodev2.h
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +8 -8
#   v4l: videodev whitespace cleanup
# 
# include/linux/videodev.h
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +7 -7
#   v4l: videodev whitespace cleanup
# 
# drivers/media/video/v4l2-common.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +6 -6
#   v4l: videodev whitespace cleanup
# 
# drivers/media/video/v4l1-compat.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +18 -18
#   v4l: videodev whitespace cleanup
# 
# ChangeSet
#   2004/10/28 08:27:36-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: videobuf whitespace cleanup
#   
#   The patch just removes all trailing whitespaces, there are no actual code
#   changes.  I've a script to remove them from my sources now, that should kill
#   those no-op whitespace changes in my patches after merging this initial
#   cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/video-buf.h
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +3 -3
#   v4l: videobuf whitespace cleanup
# 
# drivers/media/video/video-buf.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +16 -16
#   v4l: videobuf whitespace cleanup
# 
# ChangeSet
#   2004/10/28 08:27:23-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: tuner update
#   
#   This is an update for the v4l tuner modules (tuner.o + tda9887.o).
#   Changes:
#   
#     * fix two tuner config entries.
#     * switch insmod options to new 2.6-ish style.
#     * add suspend/resume functions.
#   
#   The patch also removes all trailing whitespaces.  I've a script to remove them
#   from my sources now, that should kill those no-op whitespace changes in my
#   patches after merging this initial cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/tuner.h
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +1 -1
#   v4l: tuner update
# 
# drivers/media/video/tuner.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +102 -67
#   v4l: tuner update
# 
# drivers/media/video/tda9887.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +28 -3
#   v4l: tuner update
# 
# ChangeSet
#   2004/10/28 08:27:11-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: msp3400 update
#   
#   This is a update for the msp3400 module.  Changes:
#   
#    * switch over to 2.6-ish insmod options.
#    * use kthread for thread management.
#    * add support for v4l2 audio ioctls.
#    * merge a number of changes from the ivtv project.
#    * add suspend/resume functions.
#   
#   The patch also removes all trailing whitespaces.  I've a script to remove them
#   from my sources now, that should kill those no-op whitespace changes in my
#   patches after merging this initial cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/msp3400.h
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +22 -0
#   v4l: msp3400 update
# 
# drivers/media/video/msp3400.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +668 -372
#   v4l: msp3400 update
# 
# ChangeSet
#   2004/10/28 08:26:59-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: IR whitespace cleanup
#   
#   The patch just removes all trailing whitespaces, there are no actual code
#   changes.  I've a script to remove them from my sources now, that should kill
#   those no-op whitespace changes in my patches after merging this initial
#   cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/ir-common.h
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +2 -0
#   v4l: IR whitespace cleanup
# 
# drivers/media/common/ir-common.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +5 -3
#   v4l: IR whitespace cleanup
# 
# ChangeSet
#   2004/10/28 08:26:46-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: i2c whitespace cleanup
#   
#   The patch just removes all trailing whitespaces, there are no actual code
#   changes.  I've a script to remove them from my sources now, that should kill
#   those no-op whitespace changes in my patches after merging this initial
#   cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/media/audiochip.h
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +1 -1
#   v4l: i2c whitespace cleanup
# 
# drivers/media/video/tvmixer.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +5 -5
#   v4l: i2c whitespace cleanup
# 
# drivers/media/video/tvaudio.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +36 -36
#   v4l: i2c whitespace cleanup
# 
# drivers/media/video/tda9875.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +18 -18
#   v4l: i2c whitespace cleanup
# 
# drivers/media/video/tda7432.c
#   2004/10/28 00:39:56-07:00 kraxel@bytesex.org +42 -42
#   v4l: i2c whitespace cleanup
# 
# ChangeSet
#   2004/10/28 08:26:34-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: bttv whitespace cleanup
#   
#   The patch just removes all trailing whitespaces, there are no actual code
#   changes.  I've a script to remove them from my sources now, that should kill
#   those no-op whitespace changes in my patches after merging this initial
#   cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/bttvp.h
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +4 -4
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv.h
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +9 -9
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv-vbi.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +8 -8
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv-risc.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +7 -7
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv-if.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +7 -7
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv-i2c.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +7 -7
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv-gpio.c
#   2004/10/28 00:56:30-07:00 kraxel@bytesex.org +2 -2
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv-driver.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +71 -72
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bttv-cards.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +91 -91
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/btcx-risc.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +3 -3
#   v4l: bttv whitespace cleanup
# 
# drivers/media/video/bt848.h
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +5 -5
#   v4l: bttv whitespace cleanup
# 
# ChangeSet
#   2004/10/28 08:26:21-07:00 kraxel@bytesex.org 
#   [PATCH] v4l: bttv IR input update
#   
#   This is a update for the IR input modules for the bttv driver.  It adds IR
#   support to more TV cards and has some some minor cleanups.
#   
#   It also removes all trailing whitespaces.  I've a script to remove them from
#   my sources now, that should kill those no-op whitespace changes in my patches
#   after merging this initial cleanup.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/ir-kbd-i2c.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +24 -23
#   v4l: bttv IR input update
# 
# drivers/media/video/ir-kbd-gpio.c
#   2004/10/28 00:39:55-07:00 kraxel@bytesex.org +101 -6
#   v4l: bttv IR input update
# 
# ChangeSet
#   2004/10/28 08:26:09-07:00 arjanv@infradead.org 
#   [PATCH] make filemap_fdatawrite_range() static
#   
#   The patch below marks filemap_fdatawrite_range static, it's not used
#   outside mm/filemap.c.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/filemap.c
#   2004/10/28 00:39:54-07:00 arjanv@infradead.org +1 -2
#   make filemap_fdatawrite_range() static
# 
# ChangeSet
#   2004/10/28 08:25:56-07:00 arjanv@infradead.org 
#   [PATCH] remove unused code: dump_extended_fpu
#   
#   dump_extended_fpu() is used nowhere in the kernel; save a few bytes...
#   
#   Signed-off-by: <arjanv@infradead.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/i387.h
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +0 -2
#   remove unused code: dump_extended_fpu
# 
# arch/i386/kernel/i387.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +0 -15
#   remove unused code: dump_extended_fpu
# 
# arch/i386/kernel/i386_ksyms.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +0 -1
#   remove unused code: dump_extended_fpu
# 
# ChangeSet
#   2004/10/28 08:25:43-07:00 arjanv@infradead.org 
#   [PATCH] vmalloc_to_page helper
#   
#   After William did the remap_pfn_range change, a very common pattern became:
#   	page = page_to_pfn(vmalloc_to_page((void *)pos));
#   	if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
#   
#   the patch below adds a very simple helper, vmalloc_to_pfn() to simplify this
#   a bit.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/nommu.c
#   2004/10/28 00:39:54-07:00 arjanv@infradead.org +6 -0
#   vmalloc_to_page helper
# 
# mm/memory.c
#   2004/10/28 00:39:54-07:00 arjanv@infradead.org +10 -0
#   vmalloc_to_page helper
# 
# include/linux/mm.h
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -0
#   vmalloc_to_page helper
# 
# drivers/usb/media/w9968cf.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/usb/media/vicam.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/usb/media/usbvideo.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/usb/media/stv680.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/usb/media/sn9c102_core.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/usb/media/se401.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/usb/media/ov511.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/media/video/meye.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# drivers/media/video/cpia.c
#   2004/10/28 00:39:55-07:00 arjanv@infradead.org +1 -1
#   vmalloc_to_page helper
# 
# ChangeSet
#   2004/10/28 08:25:30-07:00 arjanv@infradead.org 
#   [PATCH] unexport raise_softirq
#   
#   The patch below unexports raise_softirq().  raise_softirq() is not the
#   right api for drivers to use, instead raise_softirq_irqoff() is, and
#   thankfully all in-kernel code is using that variant already.  To avoid
#   future "accidents", unexport.
#   
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/softirq.c
#   2004/10/28 00:56:31-07:00 arjanv@infradead.org +0 -2
#   unexport raise_softirq
# 
# ChangeSet
#   2004/10/28 08:25:18-07:00 penberg@cs.helsinki.fi 
#   [PATCH] fbcon: Replace logo_shown magic numbers with constants
#   
#   This patch replaces logo_shown magic numbers with constants in
#   drivers/video/console/fbcon.c.
#   
#   Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/console/fbcon.c
#   2004/10/28 00:39:54-07:00 penberg@cs.helsinki.fi +18 -10
#   fbcon: Replace logo_shown magic numbers with constants
# 
# ChangeSet
#   2004/10/28 08:25:05-07:00 penberg@cs.helsinki.fi 
#   [PATCH] fbcon: Remove spurious casts
#   
#   This patch removes unnecessary casts from drivers/video/console/fbcon.c.
#   Assignment from a void pointer does not require a cast and char type is
#   promoted to int automatically.
#   
#   Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/console/fbcon.c
#   2004/10/28 00:56:40-07:00 penberg@cs.helsinki.fi +41 -41
#   fbcon: Remove spurious casts
# 
# ChangeSet
#   2004/10/28 08:24:53-07:00 adaplas@hotpop.com 
#   [PATCH] fbcon: Fix endian bug in fbcon_putc (console mouse problem)
#   
#   The typecast (const unsigned short *) &c in fbcon_putc is not correct for
#   big-endian machines.  This problem manifests as a black cursor that can be
#   used to erase the console screen contents.  The correct fix is to use
#   scr_writew instead.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/console/fbcon.c
#   2004/10/28 00:56:40-07:00 adaplas@hotpop.com +4 -1
#   fbcon: Fix endian bug in fbcon_putc (console mouse problem)
# 
# ChangeSet
#   2004/10/28 08:24:40-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Add __iomem annotations to intelfb
#   
#   - Add __iomem annotations to intelfb
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/intelfb/intelfbhw.h
#   2004/10/28 00:39:54-07:00 adaplas@hotpop.com +7 -5
#   fbdev: Add __iomem annotations to intelfb
# 
# drivers/video/intelfb/intelfbhw.c
#   2004/10/28 00:39:54-07:00 adaplas@hotpop.com +16 -12
#   fbdev: Add __iomem annotations to intelfb
# 
# drivers/video/intelfb/intelfbdrv.c
#   2004/10/28 00:39:54-07:00 adaplas@hotpop.com +13 -10
#   fbdev: Add __iomem annotations to intelfb
# 
# drivers/video/intelfb/intelfb.h
#   2004/10/28 00:39:54-07:00 adaplas@hotpop.com +3 -3
#   fbdev: Add __iomem annotations to intelfb
# 
# ChangeSet
#   2004/10/28 08:24:28-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Add __iomem annotations for savagefb
#   
#   Add __iomem annotations for savagefb
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/savage/savagefb.h
#   2004/10/28 00:39:54-07:00 adaplas@hotpop.com +4 -4
#   fbdev: Add __iomem annotations for savagefb
# 
# drivers/video/savage/savagefb.c
#   2004/10/28 00:39:54-07:00 adaplas@hotpop.com +2 -6
#   fbdev: Add __iomem annotations for savagefb
# 
# ChangeSet
#   2004/10/28 08:24:15-07:00 agx@sigxcpu.org 
#   [PATCH] fbdev: Fix rivafb crashes on PPC
#   
#    - fixes crashes when changing video modes/switching away from X on ppc
#    - fixes random crashes when scrolling in e.g. vi
#    - improves on the NV30 support
#    - reintroduces noaccel (not perfect but helps a lot for debugging)
#    - converts MODULE_PARM to module_param
#    - cleans up some printks, FB_ACCELF_TEXT cruft
#   Most of this is taken from either XFree86 4.3 or BenH's 2.4 ppc tree.
#   
#   From: Antonino Daplas <adaplas@pol.net>
#    - adjust pixmap->scan_align to 1 and use cfb_* drawing functions
#      if FBINFO_HWACCEL_DISABLED is set
#   
#   Signed-off-by: Guido Guenter <agx@sigxcpu.org>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/riva/riva_hw.h
#   2004/10/28 00:39:54-07:00 agx@sigxcpu.org +3 -1
#   fbdev: Fix rivafb crashes on PPC
# 
# drivers/video/riva/riva_hw.c
#   2004/10/28 00:39:54-07:00 agx@sigxcpu.org +18 -7
#   fbdev: Fix rivafb crashes on PPC
# 
# drivers/video/riva/nv_driver.c
#   2004/10/28 00:39:54-07:00 agx@sigxcpu.org +61 -13
#   fbdev: Fix rivafb crashes on PPC
# 
# drivers/video/riva/fbdev.c
#   2004/10/28 00:39:54-07:00 agx@sigxcpu.org +43 -26
#   fbdev: Fix rivafb crashes on PPC
# 
# drivers/video/Makefile
#   2004/10/28 00:39:53-07:00 agx@sigxcpu.org +2 -1
#   fbdev: Fix rivafb crashes on PPC
# 
# ChangeSet
#   2004/10/28 08:24:03-07:00 bjorn.helgaas@hp.com 
#   [PATCH] radeonfb: If no video memory, exit with error
#   
#   Nothing good will happen if we try to ioremap and use a zero-sized frame
#   buffer.  I observed this problem on an ia64 sx1000 box, where the BIOS
#   doesn't run the option ROM.  If we try to continue, radeonfb just gets
#   hopelessly confused because the card isn't initialized correctly.
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/radeon_base.c
#   2004/10/28 00:39:53-07:00 bjorn.helgaas@hp.com +3 -1
#   radeonfb: If no video memory, exit with error
# 
# ChangeSet
#   2004/10/28 08:23:51-07:00 penberg@cs.helsinki.fi 
#   [PATCH] radeonfb: screeninfo initialization cleanup
#   
#   This patch changes the initialization of radeonfb_default_var to use named
#   initializers and avoids explicitly setting fields that are automatically
#   zeroed.
#   
#   Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
#   Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/radeon_monitor.c
#   2004/10/28 00:39:53-07:00 penberg@cs.helsinki.fi +19 -4
#   radeonfb: screeninfo initialization cleanup
# 
# ChangeSet
#   2004/10/28 08:23:38-07:00 adaplas@hotpop.com 
#   [PATCH] savagefb export fixes
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/savage/savagefb_accel.c
#   2004/10/28 00:39:53-07:00 adaplas@hotpop.com +5 -0
#   savagefb export fixes
# 
# drivers/video/savage/savagefb-i2c.c
#   2004/10/28 00:39:53-07:00 adaplas@hotpop.com +5 -0
#   savagefb export fixes
# 
# drivers/video/Kconfig
#   2004/10/28 00:39:53-07:00 adaplas@hotpop.com +2 -2
#   savagefb export fixes
# 
# ChangeSet
#   2004/10/28 08:23:26-07:00 nickpiggin@yahoo.com.au 
#   [PATCH] vmscan: pages_scanned fix
#   
#   kswapd is still sometimes going into loops.  The problem seemed to be
#   happening on systems with zero inactive pages in ZONE_DMA, so pages_scanned
#   could never be increased, all_unreclaimable would never be set, and kswapd
#   would never break.
#   
#   So change pages_scanned to be a count of the number of _active_ list pages
#   scanned rather than inactive.  This has been reported to solve the problems.
#   
#   This is not subject to the reverse problem where one might have zero active
#   list pages, because inactive pages are either be reclaimed, or put onto the
#   active list.
#   
#   I think it is reasonable to have all_unreclaimed trigger based on the amount
#   of active list scanning rather than inactive.
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmscan.c
#   2004/10/28 00:39:52-07:00 nickpiggin@yahoo.com.au +1 -1
#   vmscan: pages_scanned fix
# 
# ChangeSet
#   2004/10/28 08:23:13-07:00 paulmck@us.ibm.com 
#   [PATCH] scheduler: remove redundant #ifdef
#   
#   Removes a redundant #ifdef CONFIG_SMP that is nested within an enclosing
#   #ifdef CONFIG_SMP.
#   
#   Signed-off-by: <paulmck@us.ibm.com>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/10/28 00:56:35-07:00 paulmck@us.ibm.com +0 -2
#   scheduler: remove redundant #ifdef
# 
# ChangeSet
#   2004/10/28 08:23:01-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: tty_write fix
#   
#   Make the s/390 console drivers compile without warnings again after the
#   recent tty layer change that moved the copy_from_user out of the drivers.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/char/tty3270.c
#   2004/10/28 00:39:52-07:00 schwidefsky@de.ibm.com +0 -1
#   s390: tty_write fix
# 
# drivers/s390/char/sclp_tty.c
#   2004/10/28 00:39:52-07:00 schwidefsky@de.ibm.com +1 -3
#   s390: tty_write fix
# 
# drivers/s390/char/con3215.c
#   2004/10/28 00:39:52-07:00 schwidefsky@de.ibm.com +0 -1
#   s390: tty_write fix
# 
# ChangeSet
#   2004/10/28 08:22:48-07:00 cw@f00f.org 
#   [PATCH] uml: resolve symbols in back-traces
#   
#   Resolve symbols in back-traces.
#   
#   Signed-off-by: Chris Wedgwood <cw@f00f.org>
#   Acked-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/sysrq.c
#   2004/10/28 00:39:52-07:00 cw@f00f.org +4 -14
#   uml: resolve symbols in back-traces
# 
# ChangeSet
#   2004/10/28 08:22:36-07:00 cw@f00f.org 
#   [PATCH] uml: mconsole_proc rewrite
#   
#   This is an update/resync of kraxel's mconsole_proc rewrite from about
#   two months ago and IMO it should be merged as-is (yes, it means /proc
#   has to be mounted but the current code crashes so this is better IMO).
#   
#   Signed-off-by: Chris Wedgwood <cw@f00f.org>
#   Acked-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/mconsole_kern.c
#   2004/10/28 00:39:52-07:00 cw@f00f.org +29 -55
#   uml: mconsole_proc rewrite
# 
# ChangeSet
#   2004/10/28 08:22:24-07:00 cw@f00f.org 
#   [PATCH] uml: minor warning removal
#   
#   Include some files to remove missing prototype warnings.
#   
#   Signed-off-by: Chris Wedgwood <cw@f00f.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/main.c
#   2004/10/28 00:39:52-07:00 cw@f00f.org +2 -0
#   uml: minor warning removal
# 
# ChangeSet
#   2004/10/28 08:22:11-07:00 cw@f00f.org 
#   [PATCH] uml: Kconfig.debug update
#   
#   Update Kconfig.debug so we get SYSRQ back and also the spinlock
#   debugging options.
#   
#   Signed-off-by: Chris Wedgwood <cw@f00f.org>
#   Acked-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/Kconfig.debug
#   2004/10/28 00:39:51-07:00 cw@f00f.org +3 -3
#   uml: Kconfig.debug update
# 
# ChangeSet
#   2004/10/28 08:21:59-07:00 cw@f00f.org 
#   [PATCH] uml: Build fix for TT w/o SKAS
#   
#   This is required to get UML to build with only TT mode.
#   
#   Signed-of-by: Chris Wedgwood <cw@f00f.org>
#   Acked-by: Jeff Dike <jdike@addtoit.com>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/process.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +13 -0
#   uml: Build fix for TT w/o SKAS
# 
# ChangeSet
#   2004/10/28 08:21:46-07:00 cw@f00f.org 
#   [PATCH] uml: use generic IRQ code
#   
#   Convert UML to use the generic IRQ code.
#   
#   Signed-off-by: Chris Wedgwood <cw@f00f.org>
#   Acked-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-um/hardirq.h
#   2004/10/28 00:39:51-07:00 cw@f00f.org +24 -4
#   uml: use generic IRQ code
# 
# arch/um/kernel/process_kern.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +0 -1
#   uml: use generic IRQ code
# 
# arch/um/kernel/irq_user.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +1 -1
#   uml: use generic IRQ code
# 
# arch/um/kernel/irq.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +18 -630
#   uml: use generic IRQ code
# 
# arch/um/include/irq_user.h
#   2004/10/28 00:39:51-07:00 cw@f00f.org +1 -1
#   uml: use generic IRQ code
# 
# arch/um/drivers/xterm_kern.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +1 -0
#   uml: use generic IRQ code
# 
# arch/um/drivers/port_kern.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +1 -0
#   uml: use generic IRQ code
# 
# arch/um/drivers/net_kern.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +1 -0
#   uml: use generic IRQ code
# 
# arch/um/drivers/line.c
#   2004/10/28 00:39:51-07:00 cw@f00f.org +6 -4
#   uml: use generic IRQ code
# 
# arch/um/Kconfig
#   2004/10/28 00:39:51-07:00 cw@f00f.org +5 -0
#   uml: use generic IRQ code
# 
# ChangeSet
#   2004/10/28 08:21:34-07:00 yi.zhu@intel.com 
#   [PATCH] swsusp: print error message when swapping is disabled
#   
#   This patch gives some clues to the user when swapping is not enabled during
#   swsusp.  Please apply.
#   
#   Signed-off-by: Zhu Yi <yi.zhu@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/swsusp.c
#   2004/10/28 00:39:51-07:00 yi.zhu@intel.com +4 -1
#   swsusp: print error message when swapping is disabled
# 
# ChangeSet
#   2004/10/28 08:21:21-07:00 pavel@ucw.cz 
#   [PATCH] Kill useless pm_access from vt.c
#   
#   pm_access does nothing these days, and looks ugly.  This removes it from
#   vt.c.  That actually looks like last user in the tree; it should be
#   possible to kill pm_access completely after 2.6.10.  Ouch and add warning
#   to obsolete pm.txt file.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/vt.c
#   2004/10/28 00:56:35-07:00 pavel@ucw.cz +0 -6
#   Kill useless pm_access from vt.c
# 
# Documentation/pm.txt
#   2004/10/28 00:39:51-07:00 pavel@ucw.cz +4 -4
#   Kill useless pm_access from vt.c
# 
# ChangeSet
#   2004/10/28 08:21:08-07:00 bjorn.helgaas@hp.com 
#   [PATCH] ia64 iomap implementation
#   
#   This preserves the ioreadX() == inX() semantics (same as i386), since it's
#   not clear that the speedup of omitting the mf.a for port operations is
#   worth the risk of breaking drivers.
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/iomap.c
#   2004/10/28 00:39:50-07:00 bjorn.helgaas@hp.com +5 -1
#   ia64 iomap implementation
# 
# include/asm-ia64/io.h
#   2004/10/28 00:39:50-07:00 bjorn.helgaas@hp.com +16 -1
#   ia64 iomap implementation
# 
# ChangeSet
#   2004/10/28 08:20:56-07:00 jamesclv@us.ibm.com 
#   [PATCH] x86-64 clustered APIC support
#   
#   Forthcoming IBM boxes will be using Nocona and/or Opteron chips in
#   clustered mode to get beyond 8 CPUs.  In fact, there are plans to try for
#   128 CPUs when the Tulsa chip comes out.  Thus, there are a fair number of
#   signed vs.  unsigned changes in the patch.
#   
#   Thanks to the HPET timer and some HW changes, I've been able to remove the
#   MPS/ACPI string comparisons from the detection code.  Instead, it scans
#   bios_cpu_apicid and uses simple heuristics to select the correct IRQ
#   delivery mode.  No need for a config option.  Hurrah!
#   
#   Likewise, I've been able to avoid the preprocessor tricks that the i386
#   sub-arch needed to build with one or more sub-arches.
#   
#   Reluctantly-Acked-by: Andi Kleen <ak@muc.de>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-x86_64/mach_apic.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +28 -0
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/ipi.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +113 -0
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/genapic.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +34 -0
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/genapic_flat.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +119 -0
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/genapic_cluster.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +127 -0
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/smp.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +19 -25
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/msi.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +1 -0
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/mpspec.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +2 -2
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/mach_apic.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-x86_64/mach_apic.h
# 
# include/asm-x86_64/irq.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +1 -1
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/ipi.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-x86_64/ipi.h
# 
# include/asm-x86_64/genapic.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-x86_64/genapic.h
# 
# include/asm-x86_64/apicdef.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +23 -10
#   x86-64 clustered APIC support
# 
# include/asm-x86_64/apic.h
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +1 -1
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/smpboot.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +4 -5
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/smp.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +1 -99
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/mpparse.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +1 -0
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/io_apic.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +11 -50
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/genapic_flat.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/x86_64/kernel/genapic_flat.c
# 
# arch/x86_64/kernel/genapic_cluster.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/x86_64/kernel/genapic_cluster.c
# 
# arch/x86_64/kernel/genapic.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +82 -0
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/apic.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +3 -19
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/Makefile
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +2 -1
#   x86-64 clustered APIC support
# 
# arch/i386/kernel/acpi/boot.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +1 -1
#   x86-64 clustered APIC support
# 
# arch/x86_64/kernel/genapic.c
#   2004/10/28 00:39:50-07:00 jamesclv@us.ibm.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/x86_64/kernel/genapic.c
# 
# ChangeSet
#   2004/10/28 08:20:42-07:00 venkatesh.pallipadi@intel.com 
#   [PATCH] HPET reenabling after suspend-resume
#   
#   hpet hardware seems to need a little prodding during resume for it to start
#   sending the timer interupts again.  Attached patch does it for both i386
#   and x86_64.
#   
#   Makefile change below: Right now suspend-resume ordering of system devices
#   depends on their order of linking.  It is ugly.  But, thats the way it
#   works currently.  And we want timer device to resume before PIC.
#   
#   Signed-off-by: "Venkatesh Pallipadi" <venkatesh.pallipadi@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/hpet.h
#   2004/10/28 00:39:50-07:00 venkatesh.pallipadi@intel.com +1 -0
#   HPET reenabling after suspend-resume
# 
# arch/x86_64/kernel/time.c
#   2004/10/28 00:39:50-07:00 venkatesh.pallipadi@intel.com +52 -35
#   HPET reenabling after suspend-resume
# 
# arch/x86_64/kernel/Makefile
#   2004/10/28 00:56:45-07:00 venkatesh.pallipadi@intel.com +1 -1
#   HPET reenabling after suspend-resume
# 
# arch/i386/kernel/time_hpet.c
#   2004/10/28 00:39:50-07:00 venkatesh.pallipadi@intel.com +41 -26
#   HPET reenabling after suspend-resume
# 
# arch/i386/kernel/time.c
#   2004/10/28 00:39:50-07:00 venkatesh.pallipadi@intel.com +18 -12
#   HPET reenabling after suspend-resume
# 
# arch/i386/kernel/Makefile
#   2004/10/28 00:39:50-07:00 venkatesh.pallipadi@intel.com +1 -1
#   HPET reenabling after suspend-resume
# 
# ChangeSet
#   2004/10/28 08:20:30-07:00 paul.mundt@nokia.com 
#   [PATCH] sh: syscall updates
#   
#   This adds the new syscalls (waitid/add_key/request_key/keyctl).
#   
#   Signed-off-by: Paul Mundt <paul.mundt@nokia.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh/unistd.h
#   2004/10/28 00:39:50-07:00 paul.mundt@nokia.com +6 -1
#   sh: syscall updates
# 
# arch/sh/kernel/entry.S
#   2004/10/28 00:39:50-07:00 paul.mundt@nokia.com +5 -0
#   sh: syscall updates
# 
# ChangeSet
#   2004/10/28 08:20:17-07:00 paul.mundt@nokia.com 
#   [PATCH] sh: compile fixes
#   
#   A few random build failures/warnings popped up in 2.6.9, this fixes them.
#   
#   Signed-off-by: Paul Mundt <paul.mundt@nokia.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh/system.h
#   2004/10/28 00:39:50-07:00 paul.mundt@nokia.com +0 -1
#   sh: compile fixes
# 
# include/asm-sh/pgtable.h
#   2004/10/28 00:39:50-07:00 paul.mundt@nokia.com +1 -1
#   sh: compile fixes
# 
# include/asm-sh/bitops.h
#   2004/10/28 00:39:50-07:00 paul.mundt@nokia.com +1 -1
#   sh: compile fixes
# 
# ChangeSet
#   2004/10/28 08:20:04-07:00 paul.mundt@nokia.com 
#   [PATCH] sh: do_signal() update for generic changes
#   
#   A while back get_signal_to_deliver() changed to take a struct k_sigaction *.
#   This updates do_signal() and handle_signal() to follow the generic API change.
#   
#   Signed-off-by: Paul Mundt <paul.mundt@nokia.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh/kernel/signal.c
#   2004/10/28 00:39:49-07:00 paul.mundt@nokia.com +6 -7
#   sh: do_signal() update for generic changes
# 
# ChangeSet
#   2004/10/28 08:19:52-07:00 david@gibson.dropbear.id.au 
#   [PATCH] ppc64: rework hugepage code
#   
#   Rework the ppc64 hugepage code.  Instead of using specially marked pmd
#   entries in the normal pagetables to represent hugepages, use normal pte_t
#   entries, in a special set of pagetables used for hugepages only.
#   
#   Using pte_t instead of a special hugepte_t makes the code more similar to
#   that for other architecturess, allowing more possibilities for
#   consolidating the hugepage code.
#   
#   Using independent pagetables for the hugepages is also a prerequisite for
#   moving the hugepages into their own region well outside the normal user
#   address space.  The restrictions imposed by the powerpc mmu's segment
#   design mean we probably want to do that in the fairly near future.
#   
#   Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/pgtable.h
#   2004/10/28 00:39:49-07:00 david@gibson.dropbear.id.au +14 -8
#   ppc64: rework hugepage code
# 
# include/asm-ppc64/page.h
#   2004/10/28 00:39:49-07:00 david@gibson.dropbear.id.au +0 -1
#   ppc64: rework hugepage code
# 
# include/asm-ppc64/mmu.h
#   2004/10/28 00:39:49-07:00 david@gibson.dropbear.id.au +1 -0
#   ppc64: rework hugepage code
# 
# arch/ppc64/mm/init.c
#   2004/10/28 00:39:49-07:00 david@gibson.dropbear.id.au +8 -0
#   ppc64: rework hugepage code
# 
# arch/ppc64/mm/hugetlbpage.c
#   2004/10/28 00:39:49-07:00 david@gibson.dropbear.id.au +227 -194
#   ppc64: rework hugepage code
# 
# arch/ppc64/mm/hash_utils.c
#   2004/10/28 00:39:49-07:00 david@gibson.dropbear.id.au +4 -6
#   ppc64: rework hugepage code
# 
# ChangeSet
#   2004/10/28 08:19:39-07:00 paulus@samba.org 
#   [PATCH] PPC/PPC64: Fix FP state corruption on UP
#   
#   Unfortunately the patch Ben sent last week to fix a bug in the saving and
#   restoring of floating-point and altivec context across signal handlers
#   introduced another bug, which tends to corrupt the FP and altivec contexts
#   of other tasks.  This patch fixes the problem for both ppc32 and ppc64. 
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/signal32.c
#   2004/10/28 00:39:49-07:00 paulus@samba.org +6 -2
#   PPC/PPC64: Fix FP state corruption on UP
# 
# arch/ppc64/kernel/signal.c
#   2004/10/28 00:39:49-07:00 paulus@samba.org +6 -2
#   PPC/PPC64: Fix FP state corruption on UP
# 
# arch/ppc/kernel/signal.c
#   2004/10/28 00:39:49-07:00 paulus@samba.org +9 -4
#   PPC/PPC64: Fix FP state corruption on UP
# 
# ChangeSet
#   2004/10/28 08:19:27-07:00 mporter@kernel.crashing.org 
#   [PATCH] ppc32: disable broken L2 cache on all 440GX revs
#   
#   Always disable L2 cache on PPC440GX.  All revs/speeds of silicon have
#   parity error problems despite errata claims to the contrary.
#   
#   Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/platforms/4xx/ocotea.c
#   2004/10/28 00:39:49-07:00 mporter@kernel.crashing.org +6 -2
#   ppc32: disable broken L2 cache on all 440GX revs
# 
# ChangeSet
#   2004/10/28 08:19:14-07:00 paulus@samba.org 
#   [PATCH] ppc64: cpu hotplug notifier for numa
#   
#   This patch is from Nathan Lynch <nathanl@austin.ibm.com>.
#   
#   The NUMA properties of all "possible" cpus are not necessarily available at
#   boot time on ppc64 LPAR.  Only the properties for present cpus are known.
#   
#   This patch modifies the ppc64 numa code to map a cpu to its node right before
#   it is brought up -- this means that secondary cpus are now mapped to their
#   nodes during smp_init().  Cpus are removed from their nodes after they have
#   gone offline.
#   
#   Also some minor cleanups:
#   
#   - Stash the "minimum common depth" in a global at boot time, so we don't
#     have to rediscover it every time something changes.
#   
#   - Remove unnecessary variable from of_get_associativity() which is accessed
#     while possibly uninitialized.
#   
#   - Remove the cpu portion from dump_numa_topology() since it will show only
#     the boot cpu now.  We could display this information from smp_cpus_done() if
#     necessary.
#   
#   Signed-off-by: Nathan Lynch <nathanl@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/mm/numa.c
#   2004/10/28 00:39:49-07:00 paulus@samba.org +110 -84
#   ppc64: cpu hotplug notifier for numa
# 
# ChangeSet
#   2004/10/28 08:19:02-07:00 sfr@canb.auug.org.au 
#   [PATCH] ppc64: iSeries console: cleanup after tty_write user copies  removal
#   
#   This patch just removes more of the infrastructure in the PPC64 iSeries
#   console driver that is no longer needed since we no longer need to do
#   copies from user mode in the tty drivers.
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/viocons.c
#   2004/10/28 00:39:49-07:00 sfr@canb.auug.org.au +22 -123
#   ppc64: iSeries console: cleanup after tty_write user copies  removal
# 
# ChangeSet
#   2004/10/28 08:18:50-07:00 jmorris@redhat.com 
#   [PATCH] SELinux: fix sidtab locking bug
#   
#   This patch by Kaigai Kohei fixes a bug in the SELinux sidtab code, where we
#   do a spin_unlock_irq() while nested under another irq lock, which enables
#   interrupts and allows a deadlock to happen:
#   
#     sidtab_set() is called between POLICY_WRLOCK and POLICY_WRUNLOCK in
#     services.c:1092.  sidtab_set() uses SIDTAB_LOCK()/SIDTAB_UNLOCK(), but
#     SIDTAB_UNLOCK() enables any interruptions because it's defined as
#     spin_unlock_irq().  If an interruption occurs between SIDTAB_UNLOCK() and
#     POLICY_WRUNLOCK, and interruption context try to hold the POLICY_RDLOCK,
#     then a deadlock happen in the result.
#   
#   The solution is to save & restore flags on the inner lock, per the patch
#   below.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by: Kaigai Kohei <kaigai@ak.jp.nec.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/ss/sidtab.c
#   2004/10/28 00:39:48-07:00 jmorris@redhat.com +13 -8
#   SELinux: fix sidtab locking bug
# 
# ChangeSet
#   2004/10/28 08:18:38-07:00 jmorris@redhat.com 
#   [PATCH] SELinux: fix netif bugs and simplify.
#   
#   This patch fixes and simplifies locking in the SELiunux netif cache.
#   
#   An old problem (which I forgot about) is fixed where a netif lookup can be
#   followed by a preemption, causing a race against sel_netif_put().  Kaigai
#   Kohei discovered a problem where netif lookups were also not protected
#   against races with sel_netif_flush().
#   
#   The code has now been reworked to fix these problems, eliminate the
#   refcounting and remove atomic operations entirely from the read path
#   (generally making better use of RCU).  The avc entry ref has been removed
#   as part of this simplification in anticipation of an RCU scalability patch
#   which removes them in general.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/netif.c
#   2004/10/28 00:39:48-07:00 jmorris@redhat.com +75 -45
#   SELinux: fix netif bugs and simplify.
# 
# security/selinux/include/objsec.h
#   2004/10/28 00:39:48-07:00 jmorris@redhat.com +0 -1
#   SELinux: fix netif bugs and simplify.
# 
# security/selinux/include/netif.h
#   2004/10/28 00:39:48-07:00 jmorris@redhat.com +1 -10
#   SELinux: fix netif bugs and simplify.
# 
# security/selinux/hooks.c
#   2004/10/28 00:39:48-07:00 jmorris@redhat.com +13 -30
#   SELinux: fix netif bugs and simplify.
# 
# ChangeSet
#   2004/10/28 08:18:25-07:00 jgarzik@pobox.com 
#   [PATCH] add nth_page()
#   
#   Provide a function to get the pageframe number of the nth page at
#   scatterlist.page.  We cannot just index off scatterlist.page because the
#   physically-contiguous pages may not be contiguous in mem_map[].
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mm.h
#   2004/10/28 00:56:39-07:00 jgarzik@pobox.com +2 -0
#   add nth_page()
# 
# ChangeSet
#   2004/10/28 08:18:13-07:00 hugh@veritas.com 
#   [PATCH] anon cris align address_space
#   
#   CRIS does not demand alignment, so PageAnon's PAGE_MAPPING_ANON bit got
#   mixed up with the low bit of the struct address_space *mapping pointer.
#   
#   Patch based on that from Mikael Starvik, but moved the alignment to the
#   declaration of struct address_space itself, and align to sizeof(long) so
#   it's well-aligned on all architectures.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fs.h
#   2004/10/28 00:56:35-07:00 hugh@veritas.com +6 -1
#   anon cris align address_space
# 
# ChangeSet
#   2004/10/28 08:18:00-07:00 hugh@veritas.com 
#   [PATCH] tmpfs truncate latency
#   
#   High latency observed when deleting a large video file from tmpfs.
#   
#   shmem_truncate held info->lock (easily dropped) and nested atomic kmaps
#   (more awkward to handle, since it's structured to keep them) while scanning
#   the many pages of its swap vector.  Now be prepared to cond_resched every
#   64 ops (but scan an empty page in one go).
#   
#   shmem_free_pages to free a linked list of empty swap vector pages at the
#   end (cond_resched every 64): could still free them one by one in the main
#   loop, but this foreshadows scalability changes - which will want to use RCU
#   on them, only freeing the pages after a grace period.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/shmem.c
#   2004/10/28 00:39:47-07:00 hugh@veritas.com +118 -62
#   tmpfs truncate latency
# 
# ChangeSet
#   2004/10/28 08:17:47-07:00 hugh@veritas.com 
#   [PATCH] omit CommitAvail
#   
#   CommitLimit was a good addition to /proc/meminfo, but we don't usually show
#   both what's used and what's free: don't waste lines of screenspace, omit
#   CommitAvail, let the user do the arithmetic as with all the others.  And in
#   updating that Documentation, removed the long-gone ReverseMaps.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/proc/proc_misc.c
#   2004/10/28 00:39:48-07:00 hugh@veritas.com +0 -2
#   omit CommitAvail
# 
# Documentation/vm/overcommit-accounting
#   2004/10/28 00:39:48-07:00 hugh@veritas.com +2 -3
#   omit CommitAvail
# 
# Documentation/filesystems/proc.txt
#   2004/10/28 00:39:48-07:00 hugh@veritas.com +0 -14
#   omit CommitAvail
# 
# ChangeSet
#   2004/10/28 08:17:35-07:00 hugh@veritas.com 
#   [PATCH] statm: fix negative data
#   
#   The sixth "data" field of /proc/$pid/statm was sometimes negative: text is
#   a subset of shared_vm, and so was subtracted twice from total_vm.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Acked-by: William Irwin <wli@holomorphy.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/proc/task_mmu.c
#   2004/10/28 00:39:47-07:00 hugh@veritas.com +1 -1
#   statm: fix negative data
# 
# ChangeSet
#   2004/10/28 08:17:23-07:00 hugh@veritas.com 
#   [PATCH] statm: shared = rss - anon_rss
#   
#   The third "shared" field of /proc/$pid/statm in 2.4 was a count of pages in
#   the mm whose page_count is more than 1 (oddly, including pages shared just
#   with swapcache).  That's too costly to calculate each time, so 2.6 changed
#   it to the total file-backed extent.  But Andrea knows apps and users
#   surprised when (rss - shared) goes negative: we need to provide an rss-like
#   statistic, close to the 2.4 interpretation.
#   
#   Something that's quick and easy to maintain accurately is mm->anon_rss, the
#   count of anonymous pages in the mm.  Then shared = rss - anon_rss gives a
#   pretty good and meaningful approximation to 2.4's intention: wli confirms
#   that this will be useful to Oracle too.
#   
#   Where to show it?  I think it's best to treat this as a bugfix and show it
#   in the third field of /proc/$pid/statm, after resident, as before - there's
#   no evidence that the total file-backed extent was found useful.
#   
#   Albert would like other fields to revert to page counts, but that's a lot
#   harder: if mprotect can change the category of a page, then it can't be
#   accounted as simply as this.  Only go that route if real need shown.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Acked-by: William Irwin <wli@holomorphy.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/rmap.c
#   2004/10/28 00:39:47-07:00 hugh@veritas.com +3 -0
#   statm: shared = rss - anon_rss
# 
# mm/memory.c
#   2004/10/28 00:56:39-07:00 hugh@veritas.com +7 -1
#   statm: shared = rss - anon_rss
# 
# kernel/fork.c
#   2004/10/28 00:56:32-07:00 hugh@veritas.com +1 -0
#   statm: shared = rss - anon_rss
# 
# include/linux/sched.h
#   2004/10/28 00:56:31-07:00 hugh@veritas.com +2 -2
#   statm: shared = rss - anon_rss
# 
# fs/proc/task_mmu.c
#   2004/10/28 00:56:48-07:00 hugh@veritas.com +1 -1
#   statm: shared = rss - anon_rss
# 
# ChangeSet
#   2004/10/28 08:17:10-07:00 hugh@veritas.com 
#   [PATCH] statm: __vm_stat_accounting
#   
#   The procfs shared_vm accounting in do_mmap_pgoff didn't balance with munmap
#   in the case of shared anonymous: because file comes in NULL, whereas
#   vm_file gets set at the end by shmem_zero_setup.
#   
#   Update file; and update vm_flags (a driver is likely to add VM_IO or
#   VM_RESERVED, modifying reserved_vm); and update pgoff (doesn't affect
#   procfs accounting, but could affect vma_merge - though at present all
#   drivers which modify vm_pgoff set a VM_SPECIAL which prevents merging). 
#   And do that __vm_stat_account before advancing to make_pages_present.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Acked-by: William Irwin <wli@holomorphy.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/mmap.c
#   2004/10/28 00:39:47-07:00 hugh@veritas.com +4 -1
#   statm: __vm_stat_accounting
# 
# ChangeSet
#   2004/10/28 08:16:58-07:00 hugh@veritas.com 
#   [PATCH] shmem NUMA policy spinlock
#   
#   The NUMA policy for shared memory or tmpfs page allocation was protected by
#   a semaphore.  It helps to improve scalability if we change that to a
#   spinlock (and there's only one place that needs to drop and reacquire). 
#   Oh, and don't even bother to get the spinlock while the tree is empty.
#   
#   Acked-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/mempolicy.c
#   2004/10/28 00:39:47-07:00 hugh@veritas.com +25 -13
#   shmem NUMA policy spinlock
# 
# include/linux/mempolicy.h
#   2004/10/28 00:39:47-07:00 hugh@veritas.com +3 -3
#   shmem NUMA policy spinlock
# 
# ChangeSet
#   2004/10/28 08:16:45-07:00 dhowells@redhat.com 
#   [PATCH] move key_init to security_initcall
#   
#   During system boot many probes, etc.  will generate upcalls to userspace
#   via call_usermodehelper().  This has the effect of calling execve() before
#   the key subsystem has been initialized, and thus Oopsing on a NULL key_jar
#   during key_alloc().  Move key_init to security_initcall so that it's called
#   along with other security initialization routines which have similar
#   requirements.
#   
#   Signed-off-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/keys/key.c
#   2004/10/28 00:39:47-07:00 dhowells@redhat.com +1 -1
#   move key_init to security_initcall
# 
# ChangeSet
#   2004/10/27 21:34:02-07:00 herbert@gondor.apana.org.au 
#   [ETHTOOL]: Enforce SG requires TX csum rule.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/ethtool.c
#   2004/10/27 21:33:42-07:00 herbert@gondor.apana.org.au +30 -1
#   [ETHTOOL]: Enforce SG requires TX csum rule.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/27 21:32:34-07:00 herbert@gondor.apana.org.au 
#   [XFRM]: Don't panic in xfrm_user_init
#   
#   Since xfrm_user can be built as a module it's best not to panic
#   when something goes wrong in xfrm_user_init.  Call me a wimp for
#   not fixing netlink_kernel_init's return value :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_user.c
#   2004/10/27 21:32:14-07:00 herbert@gondor.apana.org.au +1 -2
#   [XFRM]: Don't panic in xfrm_user_init
#   
#   Since xfrm_user can be built as a module it's best not to panic
#   when something goes wrong in xfrm_user_init.  Call me a wimp for
#   not fixing netlink_kernel_init's return value :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/27 21:31:44-07:00 herbert@gondor.apana.org.au 
#   [NETLINK]: Check netlink_insert in kernel_create
#   
#   This patch checks the return value of netlink_insert() in
#   netlink_kernel_create().  It could fail if someone loads
#   the same module twice for instance.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/netlink/af_netlink.c
#   2004/10/27 21:31:13-07:00 herbert@gondor.apana.org.au +4 -1
#   [NETLINK]: Check netlink_insert in kernel_create
#   
#   This patch checks the return value of netlink_insert() in
#   netlink_kernel_create().  It could fail if someone loads
#   the same module twice for instance.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/27 21:14:44-07:00 gerg@snapgear.com 
#   [PATCH] update total_vm on non-MMU configurations
#   
#   This patch fixes 3 problems with the nommu.c support code:
#   
#   1. export mem_map and vmtruncate (to make them the same as MMU version)
#   
#   2. update the total_vm usage in mmap routines
#      Without this the OOM killer has no "badness" points to rate
#      processes on...
#   
#      This patch was originally submitted by Giovanni Casoli
#      <giovanni.casoli@atengineering.it> for a 2.4.26 kernel.
#      I applied it to the 2.6.9 code.
#   
#   3. provide stub for arch_get_unmapped_area
#   
#   Signed-off-by:  Greg Ungerer <gerg@uclinux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/nommu.c
#   2004/10/27 18:15:15-07:00 gerg@snapgear.com +18 -1
#   update total_vm on non-MMU configurations
# 
# ChangeSet
#   2004/10/27 21:14:32-07:00 gerg@snapgear.com 
#   [PATCH] support all relocation types for m68knommu modules
#   
#   Add code to support the apply_relocate_add() function, needed to
#   support all relocation types of the m68k and Coldfire families.
#   This code is straight out of the m68k support for this.
#   
#   Patch was originally from Christian Magnusson
#   <christian.magnusson@runaware.com>
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68knommu/kernel/module.c
#   2004/10/27 18:11:41-07:00 gerg@snapgear.com +32 -3
#   support all relocation types for m68knommu modules
# 
# ChangeSet
#   2004/10/27 21:14:20-07:00 gerg@snapgear.com 
#   [PATCH] remove other unused shglcores.h include
#   
#   Remove remaining unused shglcores.h include.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# BitKeeper/deleted/.del-shglports.h~c8ba727a2ef6d4b0
#   2004/10/27 21:14:13-07:00 gerg@snapgear.com +0 -0
#   Delete: include/asm-m68knommu/shglports.h
# 
# ChangeSet
#   2004/10/27 21:14:07-07:00 gerg@snapgear.com 
#   [PATCH] remove unused shglcore.h include
#   
#   Remove unused shglcore.h include.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# BitKeeper/deleted/.del-shglcore.h~c60e86894f746001
#   2004/10/27 21:14:00-07:00 gerg@snapgear.com +0 -0
#   Delete: include/asm-m68knommu/shglcore.h
# 
# ChangeSet
#   2004/10/27 21:13:57-07:00 gerg@snapgear.com 
#   [PATCH] clean up HZ definition
#   
#   Clean up the definition of HZ on m68knommu systems.
#   There is really only a couple of cases to handle, most
#   boards use the traditional 100Hz still. Only special
#   case out those that don't. The current code is just
#   spaghetti.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-m68knommu/param.h
#   2004/10/27 18:14:34-07:00 gerg@snapgear.com +3 -30
#   clean up HZ definition
# 
# ChangeSet
#   2004/10/27 21:13:44-07:00 gerg@snapgear.com 
#   [PATCH] remove unused shglcore support
#   
#   Remove unused SHGLCORE support.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-m68knommu/page_offset.h
#   2004/10/27 18:14:34-07:00 gerg@snapgear.com +0 -4
#   remove unused shglcore support
# 
# ChangeSet
#   2004/10/27 21:13:32-07:00 gerg@snapgear.com 
#   [PATCH] remove uneeded includes (5307/config.c)
#   
#   Remove uneeded includes. asm/delay.h is not needed here.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68knommu/platform/5307/config.c
#   2004/10/27 18:11:45-07:00 gerg@snapgear.com +0 -1
#   remove uneeded includes (5307/config.c)
# 
# ChangeSet
#   2004/10/27 21:13:20-07:00 gerg@snapgear.com 
#   [PATCH] remove uneeded includes (5249/config.c)
#   
#   Remove uneeded includes. asm/delay.h is not needed here.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68knommu/platform/5249/config.c
#   2004/10/27 18:11:42-07:00 gerg@snapgear.com +0 -1
#   remove uneeded includes (5249/config.c)
# 
# ChangeSet
#   2004/10/27 21:13:07-07:00 gerg@snapgear.com 
#   [PATCH] remove uneeded includes (5206e/config.c)
#   
#   Remove uneeded includes. asm/delay.h is not needed here.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68knommu/platform/5206e/config.c
#   2004/10/27 18:11:42-07:00 gerg@snapgear.com +0 -1
#   remove uneeded includes (5206e/config.c)
# 
# ChangeSet
#   2004/10/27 21:12:55-07:00 gerg@snapgear.com 
#   [PATCH] remove unused include in m68knommu mm/memory.c
#   
#   Remove unused shglcore.h include from m68knommu/mm/memory.c
#   That file will be removed in an upcoming patch.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68knommu/mm/memory.c
#   2004/10/27 18:11:42-07:00 gerg@snapgear.com +0 -1
#   remove unused include in m68knommu mm/memory.c
# 
# ChangeSet
#   2004/10/27 21:12:43-07:00 gerg@snapgear.com 
#   [PATCH] remove unused include in m68knommu mm/init.c
#   
#   Remove unused shglcore.h include from m68knommu/mm/init.c
#   That file will be removed in an upcoming patch.
#   
#   Signed-off-by: Greg Ungerer <gerg@snapgear.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/m68knommu/mm/init.c
#   2004/10/27 18:11:42-07:00 gerg@snapgear.com +0 -1
#   remove unused include in m68knommu mm/init.c
# 
# ChangeSet
#   2004/10/27 18:50:42-07:00 torvalds@ppc970.osdl.org 
#   Fix kbuild problem with O=
#   
#   Kbuild can't fix up "-I $(src)/.." to the right directory
#   due to the particular magic transformations it does on -I
#   arguments. Remove the space, use "-I$(src)/.." and it works.
#   
#   Hopefully Sam will fix this build issue. 
#   
#   I think somebody should dress up as scripts/Makefile.lib
#   for Halloween. Now _that_ would be scary.
# 
# drivers/media/video/cx88/Makefile
#   2004/10/27 18:50:35-07:00 torvalds@ppc970.osdl.org +1 -1
#   Fix kbuild problem with O=
#   
#   Kbuild can't fix up "-I $(src)/.." to the right directory
#   due to the particular magic transformations it does on -I
#   arguments. Remove the space, use "-I$(src)/.." and it works.
#   
#   Hopefully Sam will fix this build issue. 
#   
#   I think somebody should dress up as scripts/Makefile.lib
#   for Halloween. Now _that_ would be scary.
# 
# ChangeSet
#   2004/10/27 18:25:29-07:00 torvalds@ppc970.osdl.org 
#   Fix atyfb modular build on ppc.
#   
#   Noted by Al Viro, superhacker and endlessly patient person.
#   
#   Sign up today!
#   
#   You too can become a superhacker by setting up a cross-compile
#   environment for all architectures and building "allmodconfig"
#   trees all day long to find places where others have screwed up.
# 
# drivers/video/aty/atyfb_base.c
#   2004/10/27 18:25:22-07:00 torvalds@ppc970.osdl.org +5 -6
#   Fix atyfb modular build on ppc.
#   
#   Noted by Al Viro, superhacker and endlessly patient person.
#   
#   Sign up today!
#   
#   You too can become a superhacker by setting up a cross-compile
#   environment for all architectures and building "allmodconfig"
#   trees all day long to find places where others have screwed up.
# 
# ChangeSet
#   2004/10/27 18:16:37-07:00 randolph@tausq.org 
#   [PATCH] Fix cc-option call for xcompiles
#   
#   If an arch Makefile overrides CROSS_COMPILE (e.g. parisc, mips, ...)
#   then the cc-option call in the main Makefile uses the wrong compiler 
#   to check for options.
#   
#   Signed-off-by: Randolph Chung <tausq@debian.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Makefile
#   2004/10/27 16:16:30-07:00 randolph@tausq.org +2 -2
#   Fix cc-option call for xcompiles
# 
# ChangeSet
#   2004/10/27 18:16:25-07:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] FB_INTEL Kconfig breakage
#   
#   	FB_INTEL selects AGP_INTEL (i.e. intel-agp.c), which is i386-only.
#   AGP_INTEL itself depends on X86 && !X86_64 and for a good reason - it doesn't
#   build elsewhere.
#   
#   	Added dependency to FB_INTEL itself; as it is allmodconfig had been
#   broken on everything outside i386.
#   
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/Kconfig
#   2004/10/27 01:21:16-07:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1
#   FB_INTEL Kconfig breakage
# 
# ChangeSet
#   2004/10/27 16:33:17-07:00 greearb@candelatech.com 
#   [VLAN]: Sync code and feature set with 2.4.x
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/8021q/vlan_dev.c
#   2004/10/27 16:32:46-07:00 greearb@candelatech.com +57 -6
#   [VLAN]: Sync code and feature set with 2.4.x
# 
# net/8021q/vlan.h
#   2004/10/27 16:32:46-07:00 greearb@candelatech.com +2 -0
#   [VLAN]: Sync code and feature set with 2.4.x
# 
# net/8021q/vlan.c
#   2004/10/27 16:32:46-07:00 greearb@candelatech.com +50 -17
#   [VLAN]: Sync code and feature set with 2.4.x
# 
# include/linux/if_vlan.h
#   2004/10/27 16:32:46-07:00 greearb@candelatech.com +3 -1
#   [VLAN]: Sync code and feature set with 2.4.x
# 
# ChangeSet
#   2004/10/27 15:56:14-07:00 trini@kernel.crashing.org 
#   ppc32: Remove sandpoint_early_serial_map()
#   
#   This was causing problems and isn't needed.
#   
#   Signed-off-by: Randy Vinson <rvinson@mvista.com>
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
# 
# arch/ppc/platforms/sandpoint.c
#   2004/10/27 15:55:36-07:00 trini@kernel.crashing.org +0 -36
#   Remove sandpoint_early_serial_map().
# 
# ChangeSet
#   2004/10/27 23:23:24+01:00 nico@org.rmk.(none) 
#   [ARM PATCH] 2080/1: clean up io-{read|write}sl
#   
#   Patch from Nicolas Pitre
#   
#   - eliminate difference between ARMv3 and ARMv4 versions of io-readsl
#   - unified little/big endian support
#   - misc optimisations
#   
#   Signed-off-by: Nicolas Pitre 
# 
# arch/arm/lib/io-writesl.S
#   2004/09/07 21:09:12+01:00 nico@org.rmk.(none) +32 -26
#   [PATCH] 2080/1: clean up io-{read|write}sl
# 
# arch/arm/lib/Makefile
#   2004/09/07 21:14:33+01:00 nico@org.rmk.(none) +3 -3
#   [PATCH] 2080/1: clean up io-{read|write}sl
# 
# arch/arm/lib/io-readsl.S
#   2004/10/27 23:19:56+01:00 nico@org.rmk.(none) +79 -0
# 
# arch/arm/lib/io-readsl.S
#   2004/10/27 23:19:56+01:00 nico@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/lib/io-readsl.S
# 
# BitKeeper/deleted/.del-io-readsl-armv4.S~d2b5ac49a016718a
#   2004/10/27 23:19:55+01:00 nico@org.rmk.(none) +0 -0
#   Delete: arch/arm/lib/io-readsl-armv4.S
# 
# BitKeeper/deleted/.del-io-readsl-armv3.S~1f9b970464df2172
#   2004/10/27 23:19:54+01:00 nico@org.rmk.(none) +0 -0
#   Delete: arch/arm/lib/io-readsl-armv3.S
# 
# ChangeSet
#   2004/10/27 15:07:39-07:00 trini@kernel.crashing.org 
#   ppc32: Fix warning in gen550 code.
#   
#   In gen550_dbg.c, cast addr in our direct_inb/oub routines to
#   __iomem.
#   
#   Signed-off-by: Randy Vinson <rvinson@mvista.com>
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
# 
# arch/ppc/syslib/gen550_dbg.c
#   2004/10/27 15:07:21-07:00 trini@kernel.crashing.org +2 -2
#   In our direct_inb/outb routines, cast addr to __iomem.
# 
# ChangeSet
#   2004/10/27 15:05:27-07:00 trini@kernel.crashing.org 
#   ppc32: Move request_irq() calls to arch_initcall() functions
#   
#   request_irq() needs to be called a bit later than we were
#   doing before, causing crashes.
#   
#   Signed-off-by: Randy Vinson <rvinson@mvista.com>
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
# 
# arch/ppc/syslib/i8259.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +11 -3
#   Move the call to request_irq to its own arch_initcall function.
# 
# arch/ppc/syslib/Makefile
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +2 -1
#   Only include i8259.o on MVME5100_IPMC761_PRESENT.
# 
# arch/ppc/platforms/sandpoint.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +9 -2
#   Move the call to openpic_hookup_cascade to its own arch_initcall 
#   function.
# 
# arch/ppc/platforms/prep_setup.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +10 -3
#   Move the call to openpic_hookup_cascade to its own arch_initcall 
#   function.
# 
# arch/ppc/platforms/pplus.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +10 -2
#   Move the call to openpic_hookup_cascade to its own arch_initcall 
#   function.
# 
# arch/ppc/platforms/mvme5100.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +12 -3
#   Move the call to openpic_hookup_cascade to its own arch_initcall 
#   function.
# 
# arch/ppc/platforms/mcpn765.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +9 -2
#   Move the call to openpic_hookup_cascade to its own arch_initcall 
#   function.
# 
# arch/ppc/platforms/lopec.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +11 -4
#   Move the call to openpic_hookup_cascade to its own arch_initcall 
#   function.
# 
# arch/ppc/platforms/chrp_setup.c
#   2004/10/27 15:05:16-07:00 trini@kernel.crashing.org +10 -3
#   Move the call to openpic_hookup_cascade to its own arch_initcall 
#   function.
# 
# ChangeSet
#   2004/10/27 23:58:00+02:00 marcel@holtmann.org 
#   [Bluetooth] Allow vendor specific packet types
#   
#   The vendor packet type 0xff is not handled at the moment. This patch
#   corrects this behaviour and also adapts the security filter for this
#   packet type.
#   
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# ChangeSet
#   2004/10/27 22:56:28+01:00 rmk@flint.arm.linux.org.uk 
#   [MMC] Deprecate "req" member of mmc_data structure.
#   
#   Host drivers should now use the scatterlist rather than accessing
#   the request directly.  This marks the request pointer as being
#   deprecated so that host driver authors get a chance to fix their
#   drivers up before we remove this member.
# 
# net/bluetooth/hci_sock.c
#   2004/10/27 23:54:40+02:00 marcel@holtmann.org +2 -1
#   Allow vendor specific packet types
# 
# include/net/bluetooth/hci.h
#   2004/10/27 23:54:30+02:00 marcel@holtmann.org +1 -1
#   Allow vendor specific packet types
# 
# include/linux/mmc/mmc.h
#   2004/10/27 22:53:03+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   Deprecate "req" element of mmc_data structure.
# 
# ChangeSet
#   2004/10/27 23:48:28+02:00 marcel@holtmann.org 
#   [Bluetooth] Fix another disconnect race
#   
#   When the selecting of the alternate setting for the SCO audio support
#   fails, the hci_usb_disconnect() will dereference a NULL pointer. To
#   avoid this, the isoc_iface variable must be set before releasing the
#   interface and unset afterwards.
#   
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# ChangeSet
#   2004/10/27 22:44:54+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2173/1: OMAP update 7/8, take 3: Add PM support
#   
#   Patch from Tony Lindgren
#   
#   This patch by Dirk Behme, Todd Poynor et al adds power management
#   support for OMAP. Suspend works on at least 1510 and 16xx.
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# drivers/bluetooth/hci_usb.c
#   2004/10/27 23:42:21+02:00 marcel@holtmann.org +8 -0
#   Fix another disconnect race
# 
# include/asm-arm/arch-omap/pm.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +151 -108
#   [PATCH] 2173/1: OMAP update 7/8, take 3: Add PM support
# 
# arch/arm/mach-omap/sleep.S
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +314 -0
#   [PATCH] 2173/1: OMAP update 7/8, take 3: Add PM support
# 
# arch/arm/mach-omap/sleep.S
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-omap/sleep.S
# 
# arch/arm/mach-omap/pm.c
#   2004/10/27 20:16:28+01:00 tony@com.rmk.(none) +621 -0
#   [PATCH] 2173/1: OMAP update 7/8, take 3: Add PM support
# 
# arch/arm/mach-omap/pm.c
#   2004/10/27 20:16:28+01:00 tony@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-omap/pm.c
# 
# ChangeSet
#   2004/10/27 22:39:45+01:00 rmk@flint.arm.linux.org.uk 
#   [MMC] Switch PXAMCI to use supplied scatterlist.
#   
#   This converts the PXA MCI driver to use the supplied scatter list
#   rather than accessing the struct request directly, thereby making
#   this host driver independent of the block layer.
#   
#   We also clean up the driver to use a consistent driver name for
#   resources.
# 
# drivers/mmc/pxamci.c
#   2004/10/27 22:37:04+01:00 rmk@flint.arm.linux.org.uk +34 -33
#   Convert PXAMCI to use supplied scatterlist.
#   Use consistent driver name throughout for resources.
# 
# ChangeSet
#   2004/10/27 23:35:49+02:00 marcel@holtmann.org 
#   [Bluetooth] Ignore the BPA 100/105 devices
#   
#   The BPA 100/105 devices from Digianswer identify themself with the USB
#   class code for H:2 devices, but they are using quite a different host
#   transport protocol and so ignore them.
#   
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# ChangeSet
#   2004/10/27 14:35:28-07:00 chas@relax.cmf.nrl.navy.mil 
#   [ATM]: don't leak skb on as_indicate failure; don't wakeup twice on as_close
#   
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/27 14:35:24-07:00 torvalds@ppc970.osdl.org 
#   Fix up "compat_sys_keyctl()" system call.
#   
#   Fix name, and make sure that it's listed as a conditional
#   system call so that we stub it out to ENOSYS if the kernel
#   isn't compiled with key management support.
# 
# security/keys/compat.c
#   2004/10/27 14:35:17-07:00 torvalds@ppc970.osdl.org +2 -2
#   Fix up "compat_sys_keyctl()" system call.
#   
#   Fix name, and make sure that it's listed as a conditional
#   system call so that we stub it out to ENOSYS if the kernel
#   isn't compiled with key management support.
# 
# kernel/sys.c
#   2004/10/27 14:35:17-07:00 torvalds@ppc970.osdl.org +1 -0
#   Fix up "compat_sys_keyctl()" system call.
#   
#   Fix name, and make sure that it's listed as a conditional
#   system call so that we stub it out to ENOSYS if the kernel
#   isn't compiled with key management support.
# 
# include/linux/compat.h
#   2004/10/27 14:35:17-07:00 torvalds@ppc970.osdl.org +1 -1
#   Fix up "compat_sys_keyctl()" system call.
#   
#   Fix name, and make sure that it's listed as a conditional
#   system call so that we stub it out to ENOSYS if the kernel
#   isn't compiled with key management support.
# 
# arch/ppc64/kernel/misc.S
#   2004/10/27 14:35:17-07:00 torvalds@ppc970.osdl.org +1 -1
#   Fix up "compat_sys_keyctl()" system call.
#   
#   Fix name, and make sure that it's listed as a conditional
#   system call so that we stub it out to ENOSYS if the kernel
#   isn't compiled with key management support.
# 
# net/atm/signaling.c
#   2004/10/27 14:35:08-07:00 chas@relax.cmf.nrl.navy.mil +3 -1
#   [ATM]: don't leak skb on as_indicate failure; don't wakeup twice on as_close
#   
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/27 14:30:35-07:00 davem@nuts.davemloft.net 
#   Merge bk://kernel.bkbits.net/acme/sk_buff-2.6
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# drivers/net/wan/wanxl.c
#   2004/10/27 14:30:24-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/net/wan/hd6457x.c
#   2004/10/27 14:30:24-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/net/wan/farsync.c
#   2004/10/27 14:30:24-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/net/wan/dscc4.c
#   2004/10/27 14:30:24-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/char/pcmcia/synclink_cs.c
#   2004/10/27 14:30:24-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/char/synclinkmp.c
#   2004/10/27 14:30:23-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/char/synclink.c
#   2004/10/27 14:30:23-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/bluetooth/hci_usb.c
#   2004/10/27 23:29:02+02:00 marcel@holtmann.org +4 -3
#   Ignore the BPA 100/105 devices
# 
# ChangeSet
#   2004/10/27 14:27:50-07:00 laforge@netfilter.org 
#   [NET]: Fix NLM_F_MULTI in tcp_diag and xfrm_user
#   
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_user.c
#   2004/10/27 14:27:31-07:00 laforge@netfilter.org +7 -2
#   [NET]: Fix NLM_F_MULTI in tcp_diag and xfrm_user
#   
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_diag.c
#   2004/10/27 14:27:31-07:00 laforge@netfilter.org +5 -3
#   [NET]: Fix NLM_F_MULTI in tcp_diag and xfrm_user
#   
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/bluetooth/hci_usb.h
#   2004/10/27 23:27:06+02:00 marcel@holtmann.org +0 -3
#   Ignore the BPA 100/105 devices
# 
# ChangeSet
#   2004/10/27 14:24:02-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Remove bogus lock and make cls_set_class return unsigned long.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_cls.h
#   2004/10/27 14:23:43-07:00 tgraf@suug.ch +1 -3
#   [PKT_SCHED]: Remove bogus lock and make cls_set_class return unsigned long.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/27 21:47:06+01:00 rmk@flint.arm.linux.org.uk 
#   [MMC] Remove block knowledge from MMCI driver.
#   
#   Convert MMCI driver to use the scatter list provided by the upper
#   MMC layers.  This removes all knowledge of struct request from the
#   MMCI driver.
# 
# drivers/mmc/mmci.h
#   2004/10/27 21:44:15+01:00 rmk@flint.arm.linux.org.uk +2 -6
#   Remove our own scatterlist.
#   Use the scatterlist provided by the upper MMC layers instead.
# 
# drivers/mmc/mmci.c
#   2004/10/27 21:44:14+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   max_phys_segs should be set to NR_SG
# 
# ChangeSet
#   2004/10/27 21:38:11+01:00 rmk@flint.arm.linux.org.uk 
#   [MMC] Add support for passing scatterlists to MMC host drivers.
#   
#   This is intended to remove block layer knowledge from MMC host
#   drivers.  Host drivers are expected to use the scatter list for
#   data transfers rather than accessing the struct request.
# 
# ChangeSet
#   2004/10/27 13:36:23-07:00 hollisb@us.ibm.com 
#   [PATCH] HVSI reset support
#   
#   This patch adds support for when the service processor (the
#   other end of the console) resets due to a critical error; we can resume
#   the connection when it comes back.
#   
#   Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/hvsi.c
#   2004/10/20 10:10:34-07:00 hollisb@us.ibm.com +81 -37
#   HVSI reset support
# 
# ChangeSet
#   2004/10/27 13:36:10-07:00 hollisb@us.ibm.com 
#   [PATCH] HVSI early boot console
#   
#   This patch adds support for the udbg early console interfaces
#   when using an HVSI console.
#   
#   Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pSeries_lpar.c
#   2004/10/07 03:52:23-07:00 hollisb@us.ibm.com +77 -5
#   HVSI early boot console
# 
# ChangeSet
#   2004/10/27 13:35:58-07:00 hollisb@us.ibm.com 
#   [PATCH] HVSI hangup oops
#   
#   Testing revealed that the HVSI driver could oops if carrier
#   detect dropped mid-data transfer.
#   
#   This fixes it by properly locking the hangup.
#   
#   Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/hvsi.c
#   2004/10/11 11:24:13-07:00 hollisb@us.ibm.com +6 -0
#   HVSI hangup oops
# 
# ChangeSet
#   2004/10/27 13:34:52-07:00 dhowells@redhat.com 
#   [PATCH] ppc/ppc64: hook up key management syscalls
#   
#   The attached patch permits my key management stuff to be used on PPC, PPC64
#   and PPC on PPC64. Syscall numbers were allocated by Paul Mackerras.
#   
#   I've updated my keyctl utility to work on PPC/PPC64 too:
#   
#   	http://people.redhat.com/~dhowells/keys/keyctl.c
#   
#   Signed-Off-By: David Howells <dhowells@redhat.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mmc/mmc.h
#   2004/10/27 21:34:50+01:00 rmk@flint.arm.linux.org.uk +3 -0
#   Add request scatterlist pointers and scatterlist length.
# 
# drivers/mmc/mmc_queue.h
#   2004/10/27 21:34:50+01:00 rmk@flint.arm.linux.org.uk +1 -0
#   Add per-queue scatter list.
# 
# drivers/mmc/mmc_queue.c
#   2004/10/27 21:34:50+01:00 rmk@flint.arm.linux.org.uk +19 -3
#   Allocate (and free) per-queue scatter list.
# 
# drivers/mmc/mmc_block.c
#   2004/10/27 21:34:49+01:00 rmk@flint.arm.linux.org.uk +3 -0
#   Convert block requests to a scatter list.
# 
# security/keys/keyctl.c
#   2004/10/21 03:54:48-07:00 dhowells@redhat.com +25 -29
#   ppc/ppc64: hook up key management syscalls
# 
# security/keys/internal.h
#   2004/10/21 03:39:25-07:00 dhowells@redhat.com +20 -0
#   ppc/ppc64: hook up key management syscalls
# 
# security/keys/compat.c
#   2004/10/22 06:02:07-07:00 dhowells@redhat.com +78 -0
#   ppc/ppc64: hook up key management syscalls
# 
# security/keys/Makefile
#   2004/10/22 02:49:39-07:00 dhowells@redhat.com +1 -0
#   ppc/ppc64: hook up key management syscalls
# 
# include/linux/compat.h
#   2004/10/22 03:02:14-07:00 dhowells@redhat.com +2 -0
#   ppc/ppc64: hook up key management syscalls
# 
# include/asm-ppc64/unistd.h
#   2004/10/22 02:27:40-07:00 dhowells@redhat.com +4 -1
#   ppc/ppc64: hook up key management syscalls
# 
# include/asm-ppc/unistd.h
#   2004/10/22 02:27:40-07:00 dhowells@redhat.com +4 -1
#   ppc/ppc64: hook up key management syscalls
# 
# arch/ppc64/kernel/sys_ppc32.c
#   2004/10/22 05:55:56-07:00 dhowells@redhat.com +18 -0
#   ppc/ppc64: hook up key management syscalls
# 
# arch/ppc64/kernel/misc.S
#   2004/10/22 03:08:44-07:00 dhowells@redhat.com +6 -0
#   ppc/ppc64: hook up key management syscalls
# 
# arch/ppc64/Kconfig
#   2004/10/22 06:01:30-07:00 dhowells@redhat.com +5 -0
#   ppc/ppc64: hook up key management syscalls
# 
# arch/ppc/kernel/misc.S
#   2004/10/22 02:27:40-07:00 dhowells@redhat.com +3 -0
#   ppc/ppc64: hook up key management syscalls
# 
# security/keys/compat.c
#   2004/10/22 06:02:07-07:00 dhowells@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/security/keys/compat.c
# 
# ChangeSet
#   2004/10/27 13:16:54-07:00 torvalds@ppc970.osdl.org 
#   Don't ask the user for esoteric compiler tweaks by default.
#   
#   You can get all the kernel tweaking if you say yes to EMBEDDED,
#   which exposes questions that make sense only for experts.
# 
# init/Kconfig
#   2004/10/27 13:16:47-07:00 torvalds@ppc970.osdl.org +4 -4
#   Don't ask the user for esoteric compiler tweaks by default.
#   
#   You can get all the kernel tweaking if you say yes to EMBEDDED,
#   which exposes questions that make sense only for experts.
# 
# ChangeSet
#   2004/10/27 21:09:49+01:00 rmk@flint.arm.linux.org.uk 
#   [MMC] Fix incorrectly balanced spin_lock_irq()
# 
# drivers/mmc/mmc_queue.c
#   2004/10/27 21:07:26+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   Fix incorrectly balanced spin_lock_irq
# 
# ChangeSet
#   2004/10/27 21:02:08+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2172/1: S3C2410 - clock updates
#   
#   Patch from Ben Dooks
#   
#   This patch does the following:
#   
#   - move the clock initialisation to just after the cpu init
#   - add the two clocks for the s3c2440
#   - add dclk0/1 and clkout0/1 definitions
#   - add list of clocks to the board specific struct
#   - fix initialisation of the clock control
#   - update handling of parent clocks for >1 parent
#   
#   this fixes the following problems:
#   
#   - serial console with no clock sources
#   - clocks specific to various boards
#   - hang if LCD controller enabled at start time
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/s3c2440.c
#   2004/10/27 14:17:19+01:00 ben-linux@org.rmk.(none) +31 -0
#   [PATCH] 2172/1: S3C2410 - clock updates
# 
# arch/arm/mach-s3c2410/s3c2410.c
#   2004/10/27 13:08:09+01:00 ben-linux@org.rmk.(none) +6 -0
#   [PATCH] 2172/1: S3C2410 - clock updates
# 
# arch/arm/mach-s3c2410/cpu.h
#   2004/10/27 13:21:01+01:00 ben-linux@org.rmk.(none) +3 -0
#   [PATCH] 2172/1: S3C2410 - clock updates
# 
# arch/arm/mach-s3c2410/cpu.c
#   2004/10/27 13:32:28+01:00 ben-linux@org.rmk.(none) +10 -0
#   [PATCH] 2172/1: S3C2410 - clock updates
# 
# arch/arm/mach-s3c2410/clock.h
#   2004/10/27 13:18:37+01:00 ben-linux@org.rmk.(none) +20 -1
#   [PATCH] 2172/1: S3C2410 - clock updates
# 
# arch/arm/mach-s3c2410/clock.c
#   2004/10/27 14:56:14+01:00 ben-linux@org.rmk.(none) +87 -11
#   [PATCH] 2172/1: S3C2410 - clock updates
# 
# ChangeSet
#   2004/10/27 20:57:05+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2139/1: BAST - Power management initialisation
#   
#   Patch from Ben Dooks
#   
#   Allow power managemnet support for the Simtec EB2410ITX (BAST)
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/mach-bast.c
#   2004/10/07 13:36:28+01:00 ben-linux@org.rmk.(none) +37 -0
#   [PATCH] 2139/1: BAST - Power management initialisation
# 
# ChangeSet
#   2004/10/27 20:46:58+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2161/1: S3C2410 - uncompressor low level uart configuration
#   
#   Patch from Ben Dooks
#   
#   Allow the uncompressing messages to be sent to the UART
#   specified in the kernel configuration, instead of just
#   UART 0. This includes the Kconfig update to make this
#   option available all the time, and to rename it's
#   description text.
#   
#   This patch also fixes s3c2440 support for the
#   uncompressor
#   
#   Signed-off-by: Ben Dooks 
# 
# include/asm-arm/arch-s3c2410/uncompress.h
#   2004/10/26 23:50:20+01:00 ben-linux@org.rmk.(none) +22 -4
#   [PATCH] 2161/1: S3C2410 - uncompressor low level uart configuration
# 
# arch/arm/Kconfig.debug
#   2004/10/26 23:54:56+01:00 ben-linux@org.rmk.(none) +5 -2
#   [PATCH] 2161/1: S3C2410 - uncompressor low level uart configuration
# 
# ChangeSet
#   2004/10/27 20:42:02+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2159/1: BAST - include/asm-arm/arch-s3c2410/bast-pmu.h
#   
#   Patch from Ben Dooks
#   
#   Header file for BAST Power Management unit register
#   definitions
#   
#   Signed-off-by: Ben Dooks 
# 
# include/asm-arm/arch-s3c2410/bast-pmu.h
#   2004/10/08 16:07:59+01:00 ben-linux@org.rmk.(none) +43 -0
#   [PATCH] 2159/1: BAST - include/asm-arm/arch-s3c2410/bast-pmu.h
# 
# include/asm-arm/arch-s3c2410/bast-pmu.h
#   2004/10/08 16:07:59+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/arch-s3c2410/bast-pmu.h
# 
# ChangeSet
#   2004/10/27 20:37:05+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2158/1: S3C2410 - clean warnings from arch/arm/mach-s3c2410/pm.c
#   
#   Patch from Ben Dooks
#   
#   Clean warnings about unsigned long / unsigned int printk args
#   and update comment on debugging
#   
#   Depends on patch 2134/3
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/pm.c
#   2004/10/25 10:40:07+01:00 ben-linux@org.rmk.(none) +9 -7
#   [PATCH] 2158/1: S3C2410 - clean warnings from arch/arm/mach-s3c2410/pm.c
# 
# ChangeSet
#   2004/10/27 20:32:05+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2157/2: S3C2410 - default configuration update
#   
#   Patch from Ben Dooks
#   
#   Updated default configurations for s3c2410 and bast
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/configs/s3c2410_defconfig
#   2004/10/27 11:30:53+01:00 ben-linux@org.rmk.(none) +61 -20
#   [PATCH] 2157/2: S3C2410 - default configuration update
# 
# arch/arm/configs/bast_defconfig
#   2004/10/27 11:31:20+01:00 ben-linux@org.rmk.(none) +94 -40
#   [PATCH] 2157/2: S3C2410 - default configuration update
# 
# ChangeSet
#   2004/10/27 20:27:05+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2156/1: S3C2410 - Documentation updates
#   
#   Patch from Ben Dooks
#   
#   Update the following in Documentation/arm/Samsing-S3C24XX/
#   
#   - mtd merge update
#   - list of contributors
#   - change history
#   
#   Signed-off-by: Ben Dooks 
# 
# Documentation/arm/Samsung-S3C24XX/Overview.txt
#   2004/10/25 10:10:23+01:00 ben-linux@org.rmk.(none) +14 -5
#   [PATCH] 2156/1: S3C2410 - Documentation updates
# 
# Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt
#   2004/10/25 10:12:12+01:00 ben-linux@org.rmk.(none) +19 -5
#   [PATCH] 2156/1: S3C2410 - Documentation updates
# 
# ChangeSet
#   2004/10/27 20:22:06+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2155/1: S3C2410 - fix definition of S3C2410_UDC_MAXP_REG
#   
#   Patch from Ben Dooks
#   
#   Attached is the fix for the S3C2410_UDC_MAXP_REG
#   definition.
#   
#   Signed-off-by: Ben Dooks 
#   Signed-off-by: Arnaud Patard 
# 
# include/asm-arm/arch-s3c2410/regs-udc.h
#   2004/10/24 11:50:26+01:00 ben-linux@org.rmk.(none) +4 -3
#   [PATCH] 2155/1: S3C2410 - fix definition of S3C2410_UDC_MAXP_REG
# 
# ChangeSet
#   2004/10/27 20:16:54+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2152/1: S3C2410 - lcd controller register fixes
#   
#   Patch from Ben Dooks
#   
#   Fix the mis-definition of the following registers / bits
#   in the s3c2410 LCD controller register header:
#   
#   - S3C2410_LCDCON1_MMODE
#   - S3C2410_LCDCON1_ENVID
#   - S3C2410_LCDCON3_HBPD
#   - S3C2410_LCDCON3_WDLY
#   
#   and adds the following missing register definitoons
#   
#   - S3C2410_LCDBANK
#   - S3C2410_LCDBASEU
#   - S3C2410_OFFSIZE
#   - S3C2410_PAGEWIDTH
#   
#   thanks to Arnaud Patard for finding these problems
#   
#   Signed-off-by: Ben Dooks 
#   Signed-off-by: Arnaud Patard 
# 
# include/asm-arm/arch-s3c2410/regs-lcd.h
#   2004/09/06 01:44:05+01:00 ben-linux@org.rmk.(none) +10 -4
#   [PATCH] 2152/1: S3C2410 - lcd controller register fixes
# 
# ChangeSet
#   2004/10/27 20:11:45+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2151/1: S3C2410 - fix guard on include/asm-arm/arch-s3c2410/regs-iic.h
#   
#   Patch from Ben Dooks
#   
#   fix guard define so it does not clash with another header
#   file.
#   
#   Signed-off-by: Ben Dooks 
# 
# include/asm-arm/arch-s3c2410/regs-iic.h
#   2004/10/20 14:19:10+01:00 ben-linux@org.rmk.(none) +3 -3
#   [PATCH] 2151/1: S3C2410 - fix guard on include/asm-arm/arch-s3c2410/regs-iic.h
# 
# ChangeSet
#   2004/10/27 20:06:52+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2149/1: S3C2410 - usb-simtec.c fixes and cleanup
#   
#   Patch from Ben Dooks
#   
#   This patch does the following
#   
#    - removes the setup code to change device/host
#      behaviour, which does not belong here
#   
#    - tidies up the debug output
#   
#    - fixes the call to free_irq() to pass the
#      right info
#   
#    - ensures the usb code is notified when the
#      over-current condition is removed
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/usb-simtec.c
#   2004/10/19 15:40:40+01:00 ben-linux@org.rmk.(none) +5 -15
#   [PATCH] 2149/1: S3C2410 - usb-simtec.c fixes and cleanup
# 
# ChangeSet
#   2004/10/27 20:01:54+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2148/1: S3C2410 - I2C platfrom data
#   
#   Patch from Ben Dooks
#   
#   Attached is the include file for the i2c platform data
#   for the s3c2410/s3c2440 I2C controller
#   
#   Signed-off-by: Ben Dooks 
# 
# include/asm-arm/arch-s3c2410/iic.h
#   2004/10/19 12:15:42+01:00 ben-linux@org.rmk.(none) +36 -0
#   [PATCH] 2148/1: S3C2410 - I2C platfrom data
# 
# include/asm-arm/arch-s3c2410/iic.h
#   2004/10/19 12:15:42+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/arch-s3c2410/iic.h
# 
# ChangeSet
#   2004/10/27 19:56:42+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2147/1: S3C2410 - reorganise board support
#   
#   Patch from Ben Dooks
#   
#   this patch makes the following changes:
#   
#    - renames struct s3c2410_board to s3c24xx_board
#    - moves board registration into cpu.c
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/s3c2440.c
#   2004/10/18 23:52:08+01:00 ben-linux@org.rmk.(none) +0 -5
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/s3c2410.h
#   2004/10/18 23:49:20+01:00 ben-linux@org.rmk.(none) +1 -14
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/s3c2410.c
#   2004/10/18 23:52:16+01:00 ben-linux@org.rmk.(none) +0 -24
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/mach-vr1000.c
#   2004/10/18 23:50:51+01:00 ben-linux@org.rmk.(none) +3 -2
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/mach-smdk2410.c
#   2004/10/18 23:51:15+01:00 ben-linux@org.rmk.(none) +2 -2
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/mach-h1940.c
#   2004/10/18 23:55:02+01:00 ben-linux@org.rmk.(none) +3 -2
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/mach-bast.c
#   2004/10/18 23:49:37+01:00 ben-linux@org.rmk.(none) +2 -2
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/cpu.h
#   2004/10/18 23:51:54+01:00 ben-linux@org.rmk.(none) +16 -0
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# arch/arm/mach-s3c2410/cpu.c
#   2004/10/18 23:53:59+01:00 ben-linux@org.rmk.(none) +29 -1
#   [PATCH] 2147/1: S3C2410 - reorganise board support
# 
# ChangeSet
#   2004/10/27 19:51:45+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2146/1: S3C2410 - serial fixes and s3c2440 updates
#   
#   Patch from Ben Dooks
#   
#   fixes the following:
#   
#    - no debug output in the head code for either s3c2410 or s3c2440
#    - fifo size calculation in the low-level debugging code
#    - serial constants for s3c2440 serial fifo sizes
#    - added s3c2440 support for uncompress.h
#   
#   Signed-off-by: Ben Dooks 
# 
# include/asm-arm/arch-s3c2410/regs-serial.h
#   2004/10/17 22:15:31+01:00 ben-linux@org.rmk.(none) +9 -0
#   [PATCH] 2146/1: S3C2410 - serial fixes and s3c2440 updates
# 
# arch/arm/kernel/debug.S
#   2004/10/18 23:16:41+01:00 ben-linux@org.rmk.(none) +25 -1
#   [PATCH] 2146/1: S3C2410 - serial fixes and s3c2440 updates
# 
# arch/arm/boot/compressed/head.S
#   2004/10/17 23:39:10+01:00 ben-linux@org.rmk.(none) +9 -0
#   [PATCH] 2146/1: S3C2410 - serial fixes and s3c2440 updates
# 
# ChangeSet
#   2004/10/27 19:46:36+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2138/1: S3C2410 - Power Management documentation (4/4)
#   
#   Patch from Ben Dooks
#   
#   Documentation for the suspend and resume code in
#   Documentation/arm/Samsung-S3C24XX/Suspend.txt
#   
#   Signed-off-by: Ben Dooks 
# 
# Documentation/arm/Samsung-S3C24XX/Suspend.txt
#   2004/10/07 13:50:02+01:00 ben-linux@org.rmk.(none) +88 -0
#   [PATCH] 2138/1: S3C2410 - Power Management documentation (4/4)
# 
# Documentation/arm/Samsung-S3C24XX/Suspend.txt
#   2004/10/07 13:50:02+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/Documentation/arm/Samsung-S3C24XX/Suspend.txt
# 
# ChangeSet
#   2004/10/27 19:41:32+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2136/1: S3C2410 - Power Management IRQ wakeup (3/4)
#   
#   Patch from Ben Dooks
#   
#   Allow all wake-up capable IRQs to be configured
#   as such
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/irq.c
#   2004/10/05 23:39:43+01:00 ben-linux@org.rmk.(none) +74 -7
#   [PATCH] 2136/1: S3C2410 - Power Management IRQ wakeup (3/4)
# 
# ChangeSet
#   2004/10/27 11:36:56-07:00 tony.luck@intel.com 
#   [IA64] fix(?) unwind data for ia64_monarch_init_handler
#   
#   Roland> I can see the ERROR: comes from unwcheck.pl but I have no
#   Roland> idea what it is checking (something to do with unwind info?)
#   Roland> let alone how to fix the problem.
#   
#   Roland> Is this benign or is there something to be fixed?
#   
#   David> Both: it needs to be fixed, but it's (mostly) benign since the only
#   David> time we're executing that code is when the unwinder can't run anyhow,
#   David> since we're in the middle of delivering an MCA.  That may (and
#   David> probably will) change in the future, so it's something that should be
#   David> fixed.
#   
#   David> I was hoping someone who knows and could test the MCA code better
#   David> would fix it but that hasn't happened yet, so it's time for plan B.
#   
#   David> Tony, below is a patch that fixes the unwind info enough that the
#   David> warning/error goes away.  The unwind-info may not be 100% correct
#   David> though.  Someone who can test/exercise this code may want to check on
#   David> that.
#   
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# ChangeSet
#   2004/10/27 19:36:30+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2135/3: S3C2410 - Power Management timer resume (2/4)
#   
#   Patch from Ben Dooks
#   
#   Support for restarting the system timer after a suspend-resume
#   cycle.
#   
#   Also fixes the following
#   
#    - missed partial setup for BAST and VR1000
#    - added IPAQ RX3715 timer setup
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/time.c
#   2004/10/21 12:22:11+01:00 ben-linux@org.rmk.(none) +16 -12
#   [PATCH] 2135/3: S3C2410 - Power Management timer resume (2/4)
# 
# arch/ia64/kernel/mca_asm.S
#   2004/10/27 11:33:12-07:00 tony.luck@intel.com +2 -1
#   fix(?) unwind data for ia64_monarch_init_handler
# 
# ChangeSet
#   2004/10/27 19:31:31+01:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2134/3: S3C2410 - Power Management core (1/4)
#   
#   Patch from Ben Dooks
#   
#   Core support for S3C2410 suspend to SDRAM
#   
#   Signed-off-by: Ben Dooks 
# 
# arch/arm/mach-s3c2410/sleep.S
#   2004/10/05 23:51:39+01:00 ben-linux@org.rmk.(none) +168 -0
#   [PATCH] 2134/3: S3C2410 - Power Management core (1/4)
# 
# arch/arm/mach-s3c2410/pm.h
#   2004/10/07 13:35:00+01:00 ben-linux@org.rmk.(none) +36 -0
#   [PATCH] 2134/3: S3C2410 - Power Management core (1/4)
# 
# arch/arm/mach-s3c2410/sleep.S
#   2004/10/05 23:51:39+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-s3c2410/sleep.S
# 
# arch/arm/mach-s3c2410/pm.h
#   2004/10/07 13:35:00+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-s3c2410/pm.h
# 
# arch/arm/mach-s3c2410/Makefile
#   2004/10/05 22:19:23+01:00 ben-linux@org.rmk.(none) +4 -0
#   [PATCH] 2134/3: S3C2410 - Power Management core (1/4)
# 
# arch/arm/mach-s3c2410/Kconfig
#   2004/10/07 12:32:10+01:00 ben-linux@org.rmk.(none) +27 -0
#   [PATCH] 2134/3: S3C2410 - Power Management core (1/4)
# 
# arch/arm/mach-s3c2410/pm.c
#   2004/10/07 13:38:36+01:00 ben-linux@org.rmk.(none) +583 -0
#   [PATCH] 2134/3: S3C2410 - Power Management core (1/4)
# 
# arch/arm/mach-s3c2410/pm.c
#   2004/10/07 13:38:36+01:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-s3c2410/pm.c
# 
# ChangeSet
#   2004/10/27 19:15:23+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
#   
#   Patch from Tony Lindgren
#   
#   This patch syncs the mainline kernel with the linux-omap tree.
#   The highlights of the patch are:
#   - Collapse OMAP 1610, 6912 and 1710 into one processor group 16xx
#   - USB updates by David Brownell
#   - Pin multiplexing updates by David Brownell
#   - Board specific low level serial port init
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# arch/arm/mach-omap/usb.c
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +79 -37
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/time.c
#   2004/10/27 16:48:54+01:00 tony@com.rmk.(none) +0 -1
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/ocpi.c
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +3 -11
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/mux.c
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +49 -11
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/irq.c
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +4 -6
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/gpio.c
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +11 -11
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/board-perseus2.c
#   2004/10/27 00:49:50+01:00 tony@com.rmk.(none) +4 -0
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/board-osk.c
#   2004/10/27 16:52:19+01:00 tony@com.rmk.(none) +18 -2
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/board-innovator.c
#   2004/10/27 00:49:50+01:00 tony@com.rmk.(none) +17 -21
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/board-h3.c
#   2004/10/27 16:54:44+01:00 tony@com.rmk.(none) +5 -6
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/board-h2.c
#   2004/10/27 16:52:53+01:00 tony@com.rmk.(none) +11 -7
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/board-generic.c
#   2004/10/27 00:49:50+01:00 tony@com.rmk.(none) +6 -27
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/Makefile
#   2004/10/27 16:50:35+01:00 tony@com.rmk.(none) +2 -4
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# arch/arm/mach-omap/Kconfig
#   2004/10/27 17:04:14+01:00 tony@com.rmk.(none) +37 -33
#   [PATCH] 2170/1: OMAP update 2/8, take 2: Arch files
# 
# ChangeSet
#   2004/10/27 10:38:53-07:00 hunold@linuxtv.org 
#   [PATCH] DVB: misc. updates to frontend drivers
#   
#   - [DVB] add legacy DishNetwork support to dvb core and stv0299, thanks to Jeremy Hall
#   - [DVB] mt352: major cleanup, support DVICO FusionHDTV DVB-T, thanks to Christopher Pascoe
#   
#   Signed-off-by: Michael Hunold <hunold@linuxtv.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/dvb/frontend.h
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +2 -0
#   DVB: misc. updates to frontend drivers
# 
# drivers/media/dvb/frontends/stv0299.c
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +45 -4
#   DVB: misc. updates to frontend drivers
# 
# drivers/media/dvb/frontends/mt352.h
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +20 -23
#   DVB: misc. updates to frontend drivers
# 
# drivers/media/dvb/frontends/mt352.c
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +285 -150
#   DVB: misc. updates to frontend drivers
# 
# ChangeSet
#   2004/10/27 10:38:38-07:00 hunold@linuxtv.org 
#   [PATCH] DVB: revamp dibusb driver
#   
#   - [DVB] dibusb: update documentation for the dibusb DVB driver
#   - [DVB] dibusb: major overhaul of the driver, including adding new vendor and product ids from clones
#   
#   Signed-off-by: Michael Hunold <hunold@linuxtv.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/dvb/frontends/dib3000mb.h
#   2004/09/28 12:39:06-07:00 hunold@linuxtv.org +9 -9
#   DVB: revamp dibusb driver
# 
# drivers/media/dvb/frontends/dib3000mb.c
#   2004/10/13 12:36:12-07:00 hunold@linuxtv.org +209 -73
#   DVB: revamp dibusb driver
# 
# drivers/media/dvb/dibusb/dvb-dibusb.h
#   2004/09/30 14:29:28-07:00 hunold@linuxtv.org +104 -55
#   DVB: revamp dibusb driver
# 
# drivers/media/dvb/dibusb/dvb-dibusb.c
#   2004/10/04 02:12:20-07:00 hunold@linuxtv.org +105 -72
#   DVB: revamp dibusb driver
# 
# drivers/media/dvb/dibusb/Kconfig
#   2004/09/30 14:29:28-07:00 hunold@linuxtv.org +5 -3
#   DVB: revamp dibusb driver
# 
# Documentation/dvb/README.dibusb
#   2004/09/28 12:36:44-07:00 hunold@linuxtv.org +26 -8
#   DVB: revamp dibusb driver
# 
# ChangeSet
#   2004/10/27 10:38:21-07:00 hunold@linuxtv.org 
#   [PATCH] DVB: add new driver
#   
#   - [DVB] add new driver for the Terratec CinergyT2/qanu USB2 DVB-T receiver, thanks to Daniel Mack and Holger Waechtler
#   
#   Signed-off-by: Michael Hunold <hunold@linuxtv.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/dvb/cinergyT2/cinergyT2.c
#   2004/10/26 06:17:54-07:00 hunold@linuxtv.org +811 -0
#   DVB: add new driver
# 
# drivers/media/dvb/cinergyT2/Makefile
#   2004/10/15 08:15:48-07:00 hunold@linuxtv.org +3 -0
#   DVB: add new driver
# 
# drivers/media/dvb/cinergyT2/cinergyT2.c
#   2004/10/26 06:17:54-07:00 hunold@linuxtv.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/dvb/cinergyT2/cinergyT2.c
# 
# drivers/media/dvb/cinergyT2/Makefile
#   2004/10/15 08:15:48-07:00 hunold@linuxtv.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/dvb/cinergyT2/Makefile
# 
# drivers/media/dvb/cinergyT2/Kconfig
#   2004/10/15 08:22:20-07:00 hunold@linuxtv.org +59 -0
#   DVB: add new driver
# 
# drivers/media/dvb/Makefile
#   2004/10/25 05:14:41-07:00 hunold@linuxtv.org +1 -1
#   DVB: add new driver
# 
# drivers/media/dvb/Kconfig
#   2004/10/25 05:14:41-07:00 hunold@linuxtv.org +1 -0
#   DVB: add new driver
# 
# drivers/media/dvb/cinergyT2/Kconfig
#   2004/10/15 08:22:20-07:00 hunold@linuxtv.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/dvb/cinergyT2/Kconfig
# 
# ChangeSet
#   2004/10/27 10:38:00-07:00 hunold@linuxtv.org 
#   [PATCH] DVB: misc. updates to the dvb-core
#   
#   - [DVB] ttusb_dec: add new 2000T type model number
#   - [DVB] dvb_ca_en50221: properly zero out private pointer
#   - [DVB] dvb-bt8xx: properly use a mutex when starting/stopping the dma engine, remove card list, it's not need anymore
#   - [DVB] bt878: fix hex <=> dec typo (missing 0x prefix), mark remove bt878_remove() function __devexit_p
#   - [DVB] dvb-core: add dvb_net_debug module parameter, remove some dead code
#   
#   Signed-off-by: Michael Hunold <hunold@linuxtv.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/dvb/ttusb-dec/ttusb_dec.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +1 -0
#   DVB: misc. updates to the dvb-core
# 
# drivers/media/dvb/frontends/grundig_29504-401.c
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +1 -1
#   DVB: misc. updates to the dvb-core
# 
# drivers/media/dvb/dvb-core/dvb_net.c
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +8 -7
#   DVB: misc. updates to the dvb-core
# 
# drivers/media/dvb/dvb-core/dvb_ca_en50221.c
#   2004/10/25 05:14:42-07:00 hunold@linuxtv.org +1 -0
#   DVB: misc. updates to the dvb-core
# 
# drivers/media/dvb/bt8xx/dvb-bt8xx.h
#   2004/10/25 05:14:41-07:00 hunold@linuxtv.org +2 -2
#   DVB: misc. updates to the dvb-core
# 
# drivers/media/dvb/bt8xx/dvb-bt8xx.c
#   2004/10/25 05:14:41-07:00 hunold@linuxtv.org +22 -18
#   DVB: misc. updates to the dvb-core
# 
# drivers/media/dvb/bt8xx/bt878.c
#   2004/10/25 05:14:41-07:00 hunold@linuxtv.org +2 -2
#   DVB: misc. updates to the dvb-core
# 
# Documentation/dvb/readme.txt
#   2004/10/25 05:14:41-07:00 hunold@linuxtv.org +3 -3
#   DVB: misc. updates to the dvb-core
# 
# ChangeSet
#   2004/10/27 10:37:48-07:00 hunold@linuxtv.org 
#   [PATCH] DVB: rework debugging in av7110
#   
#   - [DVB] av7110: switch from stupid DEB_xx() debug macros to saner dprintk() style debugging
#   - [DVB] av7110: fix dvb-ttpci ca write() polling
#   - [DVB] budget: switch from stupid DEB_xx() debug macros to saner dprintk() style debugging
#   
#   Signed-off-by: Michael Hunold <hunold@linuxtv.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/dvb/ttpci/budget.h
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +7 -0
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/budget.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +8 -9
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/budget-patch.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +7 -9
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/budget-core.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +9 -9
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/budget-ci.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +2 -4
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/budget-av.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +9 -21
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/av7110_v4l.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +33 -33
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/av7110_ir.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +3 -8
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/av7110_hw.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +50 -50
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/av7110_ca.c
#   2004/10/25 05:14:44-07:00 hunold@linuxtv.org +12 -9
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/av7110_av.c
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +26 -36
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/av7110.h
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +5 -0
#   DVB: rework debugging in av7110
# 
# drivers/media/dvb/ttpci/av7110.c
#   2004/10/25 05:14:43-07:00 hunold@linuxtv.org +51 -58
#   DVB: rework debugging in av7110
# 
# ChangeSet
#   2004/10/27 17:07:16+00:00 steiner@sgi.com 
#   [IA64-SGI] Update asm-ia64/sn/sn_cpuid.h macros
#   
#   (I missed a file in the cleanup code that I sent yesterday.)
#   
#   SGI SN code currently makes assumptions about the bits in the LID
#   register. These assumptions do not conform to the bit specifications
#   from Intel. For example, SN currently assumes that bits [28:16] of
#   the LID contain the physical node ID of a node.
#   
#   This patch eliminates these assumptions. A SAL call is now used to translate
#   LID values to the NASID/subnode/slice values that are needed for SN
#   platforms. The results of the SAL call are saved in the SN nodepda.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/sn/kernel/iomv.c
#   2004/10/27 17:05:02+00:00 steiner@sgi.com +1 -0
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# ChangeSet
#   2004/10/27 16:21:44+00:00 jbarnes@sgi.com 
#   [IA64] fix machine vectors for mmiowb
#   
#   I left out some of the necessary machine vector magic in the mmiowb patch
#   which caused the generic build to break.  This patch fixes it up by properly
#   #defining it and #undefing it and adding a routine to lib/io.c.
#    
#   Signed-off-by: Jesse Barnes <jbarnes@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/io.h
#   2004/10/27 16:20:39+00:00 jbarnes@sgi.com +3 -2
#   fix machine vectors for mmiowb
# 
# arch/ia64/lib/io.c
#   2004/10/27 16:20:39+00:00 jbarnes@sgi.com +7 -0
#   fix machine vectors for mmiowb
# 
# ChangeSet
#   2004/10/27 14:29:04+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Group linux/* includes together in mcbsp.c
# 
# arch/arm/mach-omap/mcbsp.c
#   2004/10/27 14:24:11+01:00 rmk@flint.arm.linux.org.uk +1 -1
#   Group linux/* includes together.
# 
# ChangeSet
#   2004/10/27 14:19:43+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2169/1: OMAP update 8/8: McBSP update
#   
#   Patch from Tony Lindgren
#   
#   Patch by Samuel Ortiz to update OMAP McBSP support
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# include/asm-arm/arch-omap/mcbsp.h
#   2004/10/21 00:42:48+01:00 tony@com.rmk.(none) +1 -1
#   [PATCH] 2169/1: OMAP update 8/8: McBSP update
# 
# arch/arm/mach-omap/mcbsp.c
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +24 -8
#   [PATCH] 2169/1: OMAP update 8/8: McBSP update
# 
# ChangeSet
#   2004/10/27 14:11:54+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2167/1: OMAP update 6/8: Add graphics acceleration support to DMA
#   
#   Patch from Tony Lindgren
#   
#   This patch by Imre Deak adds support for graphics acceleration
#   features on the OMAP DMA controller.
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# include/asm-arm/arch-omap/dma.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +22 -6
#   [PATCH] 2167/1: OMAP update 6/8: Add graphics acceleration support to DMA
# 
# arch/arm/mach-omap/dma.c
#   2004/10/26 01:06:40+01:00 tony@com.rmk.(none) +302 -88
#   [PATCH] 2167/1: OMAP update 6/8: Add graphics acceleration support to DMA
# 
# ChangeSet
#   2004/10/27 13:59:24+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2166/1: OMAP update 5/8: Change OMAP to use generic clock framework
#   
#   Patch from Tony Lindgren
#   
#   This patch by Tuukka Tikkanen changes OMAP to use ARM generic
#   clock framework instead of older OMAP specific clock framework.
#   Patch replaces old clocks.c with new clock.[ch].
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# arch/arm/mach-omap/clock.h
#   2004/10/27 13:55:01+01:00 tony@com.rmk.(none) +106 -0
# 
# arch/arm/mach-omap/clock.h
#   2004/10/27 13:55:01+01:00 tony@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-omap/clock.h
# 
# arch/arm/mach-omap/clock.c
#   2004/10/27 13:54:45+01:00 tony@com.rmk.(none) +947 -0
# 
# arch/arm/mach-omap/clock.c
#   2004/10/27 13:54:45+01:00 tony@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-omap/clock.c
# 
# BitKeeper/deleted/.del-clocks.c~6c857d00f6457e
#   2004/10/27 13:54:45+01:00 tony@com.rmk.(none) +0 -0
#   Delete: arch/arm/mach-omap/clocks.c
# 
# ChangeSet
#   2004/10/27 13:50:45+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2165/1: OMAP update 4/X: Replace 1610 and 5912 header files with 16xx
#   
#   Patch from Tony Lindgren
#   
#   This patch replaces old OMAP headers for 1610 and 5912. These
#   headers are replaced with a common omap16xx.h header file.
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# include/asm-arm/arch-omap/omap16xx.h
#   2004/10/21 00:42:48+01:00 tony@com.rmk.(none) +72 -22
#   [PATCH] 2165/1: OMAP update 4/X: Replace 1610 and 5912 header files with 16xx
# 
# BitKeeper/deleted/.del-omap5912.h~ef7fb854d2ac315
#   2004/10/27 13:47:36+01:00 tony@com.rmk.(none) +0 -0
#   Delete: include/asm-arm/arch-omap/omap5912.h
# 
# ChangeSet
#   2004/10/27 13:41:41+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2164/1: OMAP update 3/8: Include files
#   
#   Patch from Tony Lindgren
#   
#   This patch syncs the mainline kernel with the linux-omap tree.
#   The highlights of the patch are:
#   - Collapse OMAP 1610, 6912 and 1710 into one processor group 16xx
#   - USB updates by David Brownell
#   - Pin multiplexing updates by David Brownell
#   - Board specific low level serial port init
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# include/asm-arm/arch-omap/uncompress.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +9 -16
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/timex.h
#   2004/10/21 01:14:47+01:00 tony@com.rmk.(none) +1 -3
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/serial.h
#   2004/10/26 23:43:05+01:00 tony@com.rmk.(none) +5 -1
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/mux.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +32 -7
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/memory.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +3 -1
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/irqs.h
#   2004/10/20 23:42:48+01:00 tony@com.rmk.(none) +1 -21
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/hardware.h
#   2004/10/20 17:35:45+01:00 tony@com.rmk.(none) +32 -64
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/board.h
#   2004/10/26 18:16:38+01:00 tony@com.rmk.(none) +46 -5
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/board-innovator.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +3 -9
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/board-h3.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +8 -64
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/board-h2.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +8 -4
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/tc.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +64 -0
#   [PATCH] 2164/1: OMAP update 3/8: Include files
# 
# include/asm-arm/arch-omap/tc.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/arch-omap/tc.h
# 
# ChangeSet
#   2004/10/27 13:07:27+01:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2162/1: OMAP update 1/8: Improved cpu detection and serial init
#   
#   Patch from Tony Lindgren
#   
#   This patch improves the OMAP cpu detection during the boot,
#   and adds board-specific init for the serial ports.
#   
#   Signed-off-by: Tony Lindgren
#   
# 
# arch/arm/mach-omap/common.h
#   2004/10/26 03:17:42+01:00 tony@com.rmk.(none) +1 -0
#   [PATCH] 2162/1: OMAP update 1/8: Improved cpu detection and serial init
# 
# arch/arm/mach-omap/common.c
#   2004/10/27 00:01:58+01:00 tony@com.rmk.(none) +319 -60
#   [PATCH] 2162/1: OMAP update 1/8: Improved cpu detection and serial init
# 
# include/asm-arm/arch-omap/cpu.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +183 -0
#   [PATCH] 2162/1: OMAP update 1/8: Improved cpu detection and serial init
# 
# include/asm-arm/arch-omap/cpu.h
#   2004/10/18 17:20:19+01:00 tony@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/arch-omap/cpu.h
# 
# ChangeSet
#   2004/10/26 21:50:42-07:00 herbert@gondor.apana.org.au 
#   [NETLINK]: Remove netlink_sock_nr
#   
#   This patch removes netlink_sock_nr which is only used by a printk
#   statement in af_netlink.c.  Even that's only there if
#   NETLINK_REFCNT_DEBUG is defined.
#   
#   If we were really looking for netlink refcnt bugs there are probably
#   better places to do that anyway.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/netlink/af_netlink.c
#   2004/10/26 21:50:12-07:00 herbert@gondor.apana.org.au +0 -8
#   [NETLINK]: Remove netlink_sock_nr
#   
#   This patch removes netlink_sock_nr which is only used by a printk
#   statement in af_netlink.c.  Even that's only there if
#   NETLINK_REFCNT_DEBUG is defined.
#   
#   If we were really looking for netlink refcnt bugs there are probably
#   better places to do that anyway.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 23:50:29+00:00 tony.luck@intel.com 
#   [IA64] Need <asm/meminit.h> for GRANULEROUNDDOWN
#   
#   Alex's change for mem=/max_addr= now needs to include meminit.h
#   
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/kernel/efi.c
#   2004/10/26 23:43:15+00:00 tony.luck@intel.com +1 -0
#   Need <asm/meminit.h> for GRANULEROUNDDOWN
# 
# ChangeSet
#   2004/10/26 23:50:13+00:00 pfg@sgi.com 
#   [IA64-SGI] only allocate irq if the device can interrupt
#   
#   Signed-off-by: Patrick Gefre <pfg@sgi.com>
#   Acked-by: Mike Habeck <habeck@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/sn/kernel/io_init.c
#   2004/10/26 23:43:02+00:00 pfg@sgi.com +3 -1
#   only allocate irq if the device can interrupt
# 
# ChangeSet
#   2004/10/26 23:49:56+00:00 steiner@sgi.com 
#   [IA64-SGI] Delete simulator support from SN idle loop
#   
#   Delete hack for supporting simulator for SN platforms. This capability
#   has been moved into the simulator environment & is no longer required
#   in the kernel.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/sn/kernel/idle.c
#   2004/10/26 23:42:49+00:00 steiner@sgi.com +3 -9
#   Delete simulator support from SN idle loop
# 
# ChangeSet
#   2004/10/26 23:49:38+00:00 steiner@sgi.com 
#   [IA64-SGI] Update asm-ia64/sn/sn_cpuid.h macros
#   
#   SGI SN code currently makes assumptions about the bits in the LID
#   register. These assumptions do not conform to the bit specifications
#   from Intel. For example, SN currently assumes that bits [28:16] of
#   the LID contain the physical node ID of a node.
#    
#   This patch eliminates these assumptions. A SAL call is now used to translate
#   LID values to the NASID/subnode/slice values that are needed for SN
#   platforms. The results of the SAL call are saved in the SN nodepda.
#   
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/sn/sn_sal.h
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +32 -0
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# include/asm-ia64/sn/sn_cpuid.h
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +28 -67
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# include/asm-ia64/sn/nodepda.h
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +10 -0
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# include/asm-ia64/sn/intr.h
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +1 -1
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# arch/ia64/sn/kernel/sn2/sn_proc_fs.c
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +2 -1
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# arch/ia64/sn/kernel/sn2/sn2_smp.c
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +12 -7
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# arch/ia64/sn/kernel/setup.c
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +45 -6
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# arch/ia64/sn/kernel/irq.c
#   2004/10/26 23:42:36+00:00 steiner@sgi.com +4 -4
#   Update asm-ia64/sn/sn_cpuid.h macros
# 
# ChangeSet
#   2004/10/26 16:41:27-07:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Make net/tc_act/tc_pedit.h include net/act_api.h
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/tc_act/tc_pedit.h
#   2004/10/26 16:40:56-07:00 davem@nuts.davemloft.net +1 -1
#   [PKT_SCHED]: Make net/tc_act/tc_pedit.h include net/act_api.h
# 
# ChangeSet
#   2004/10/26 19:39:53-04:00 jgarzik@pobox.com 
#   [libata] use kunmap_atomic() correctly
# 
# drivers/scsi/libata-scsi.c
#   2004/10/26 19:39:47-04:00 jgarzik@pobox.com +4 -4
#   [libata] use kunmap_atomic() correctly
# 
# ChangeSet
#   2004/10/26 16:31:24-07:00 hadi@cyberus.ca 
#   [PKT_SCHED]: Add generic packet editor.
#   
#   Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/Makefile
#   2004/10/26 16:30:45-07:00 hadi@cyberus.ca +1 -0
#   [PKT_SCHED]: Add generic packet editor.
# 
# net/sched/Kconfig
#   2004/10/26 16:30:45-07:00 hadi@cyberus.ca +7 -0
#   [PKT_SCHED]: Add generic packet editor.
# 
# include/net/tc_act/tc_pedit.h
#   2004/10/26 16:30:34-07:00 hadi@cyberus.ca +14 -0
#   [PKT_SCHED]: Add generic packet editor.
# 
# include/linux/tc_act/tc_pedit.h
#   2004/10/26 16:30:34-07:00 hadi@cyberus.ca +36 -0
#   [PKT_SCHED]: Add generic packet editor.
# 
# include/net/tc_act/tc_pedit.h
#   2004/10/26 16:30:34-07:00 hadi@cyberus.ca +0 -0
#   BitKeeper file /disk1/BK/net-2.6/include/net/tc_act/tc_pedit.h
# 
# include/linux/tc_act/tc_pedit.h
#   2004/10/26 16:30:34-07:00 hadi@cyberus.ca +0 -0
#   BitKeeper file /disk1/BK/net-2.6/include/linux/tc_act/tc_pedit.h
# 
# net/sched/pedit.c
#   2004/10/26 16:30:32-07:00 hadi@cyberus.ca +302 -0
#   [PKT_SCHED]: Add generic packet editor.
# 
# net/sched/pedit.c
#   2004/10/26 16:30:32-07:00 hadi@cyberus.ca +0 -0
#   BitKeeper file /disk1/BK/net-2.6/net/sched/pedit.c
# 
# ChangeSet
#   2004/10/26 16:18:39-07:00 zach@vmware.com 
#   [PATCH] faster signal handling on x86
#   
#   Optimize away the unconditional write to debug registers on signal delivery
#   path.  This is already done on x86_64.
#   
#   We only need to write to dr7 if there is a breakpoint to re-enable, and 
#   MOVDR is a serializing instruction, which is expensive.  Getting rid of 
#   it gets a 33% faster signal delivery path (at least on Xeon - I didn't
#   test other CPUs, so your gain may vary).
#   
#   [ Editors note: it's likely only that slow on Netburst.  Serializing is
#     not that expensive, but it is likely that writing to %db7 invalidates
#     the trace cache, which explains why it's so slow on Xeon - it's not
#     just the op itself, it has to re-populate the cache all the time.
#   					--- Linus ]
#   
#   
#   Measured delta TSC for three paths on a 2.4GHz Xeon.
#   
#   1) With unconditional write to dr7 :  800-1000 cycles
#   2) With conditional write to dr7   :  84-112 cycles
#   3) With unlikely write to dr7      :  84 cycles
#   
#   Performance test using divzero microbenchmark (3 million divide by zeros):
#   
#   With unconditional write:
#      7.445 real / 6.136 system
#      7.529 real / 6.482 system
#      7.541 real / 5.974 system
#      7.546 real / 6.217 system
#      7.445 real / 6.167 system
#   
#   With unlikely write:
#      5.779 real / 4.518 system
#      5.783 real / 4.591 system
#      5.552 real / 4.569 system
#      5.790 real / 4.528 system
#      5.554 real / 4.382 system
#   
#   That's about a 33% speedup - more than I expected; apparently getting rid
#   of the serializing instruction makes the do_signal path much faster.
#   
#   Zachary Amsden (zach@vmware.com)
# 
# arch/i386/kernel/signal.c
#   2004/10/26 14:30:54-07:00 zach@vmware.com +3 -1
#   faster signal handling on x86
# 
# ChangeSet
#   2004/10/26 16:07:39-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/police.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +1 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_u32.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +2 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_tcindex.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +2 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_rsvp6.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +2 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_rsvp.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +2 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_route.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +2 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_fw.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +2 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_api.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +1 -0
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/act_api.c
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +2 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/tc_act/tc_mirred.h
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +1 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/tc_act/tc_gact.h
#   2004/10/26 16:07:19-07:00 tgraf@suug.ch +1 -1
#   [PKT_SCHED]: Use new header architecture
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 16:06:57-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Inline psched_tod_diff
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/sch_api.c
#   2004/10/26 16:06:38-07:00 tgraf@suug.ch +0 -15
#   [PKT_SCHED]: Inline psched_tod_diff
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_sched.h
#   2004/10/26 16:06:38-07:00 tgraf@suug.ch +12 -1
#   [PKT_SCHED]: Inline psched_tod_diff
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 16:06:11-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Cleanup cls_set_class
#   
#   Clean up a really messy cross reference where a macro cls_set_class
#   in pkt_sched.h would point to a function tcf_set_class in cls_api.c
#   that uses a inlined function __cls_set_class in pkt_sched.h again.
#   
#   Make tcf_set_class be cls_set_class since it was never used and
#   inline it as well.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_api.c
#   2004/10/26 16:05:51-07:00 tgraf@suug.ch +0 -14
#   [PKT_SCHED]: Cleanup cls_set_class
#   
#   Clean up a really messy cross reference where a macro cls_set_class
#   in pkt_sched.h would point to a function tcf_set_class in cls_api.c
#   that uses a inlined function __cls_set_class in pkt_sched.h again.
#   
#   Make tcf_set_class be cls_set_class since it was never used and
#   inline it as well.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_sched.h
#   2004/10/26 16:05:51-07:00 tgraf@suug.ch +0 -12
#   [PKT_SCHED]: Cleanup cls_set_class
#   
#   Clean up a really messy cross reference where a macro cls_set_class
#   in pkt_sched.h would point to a function tcf_set_class in cls_api.c
#   that uses a inlined function __cls_set_class in pkt_sched.h again.
#   
#   Make tcf_set_class be cls_set_class since it was never used and
#   inline it as well.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_cls.h
#   2004/10/26 16:05:51-07:00 tgraf@suug.ch +25 -0
#   [PKT_SCHED]: Cleanup cls_set_class
#   
#   Clean up a really messy cross reference where a macro cls_set_class
#   in pkt_sched.h would point to a function tcf_set_class in cls_api.c
#   that uses a inlined function __cls_set_class in pkt_sched.h again.
#   
#   Make tcf_set_class be cls_set_class since it was never used and
#   inline it as well.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 16:05:14-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: psched_*_per_* can be static
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/sch_api.c
#   2004/10/26 16:04:54-07:00 tgraf@suug.ch +2 -2
#   [PKT_SCHED]: psched_*_per_* can be static
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 16:04:32-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Move tc_classify from pkt_cls.h to sch_api.c
#   
#   tc_classiy has grown too big to be inlined, move it to sch_api.c
#   and export it.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/sch_api.c
#   2004/10/26 16:04:12-07:00 tgraf@suug.ch +47 -0
#   [PKT_SCHED]: Move tc_classify from pkt_cls.h to sch_api.c
#   
#   tc_classiy has grown too big to be inlined, move it to sch_api.c
#   and export it.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_sched.h
#   2004/10/26 16:04:12-07:00 tgraf@suug.ch +3 -0
#   [PKT_SCHED]: Move tc_classify from pkt_cls.h to sch_api.c
#   
#   tc_classiy has grown too big to be inlined, move it to sch_api.c
#   and export it.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_cls.h
#   2004/10/26 16:04:12-07:00 tgraf@suug.ch +0 -45
#   [PKT_SCHED]: Move tc_classify from pkt_cls.h to sch_api.c
#   
#   tc_classiy has grown too big to be inlined, move it to sch_api.c
#   and export it.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 16:03:13-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Transform pkt_sched.h prototypes to be extern
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_sched.h
#   2004/10/26 16:02:53-07:00 tgraf@suug.ch +18 -15
#   [PKT_SCHED]: Transform pkt_sched.h prototypes to be extern
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 16:02:21-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Remove obsolete definitions in pkt_sched.h
#   
#   Removes all obsolete definitions in pkt_sched.h now in sch_generic.h
#   or act_api.h.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_sched.h
#   2004/10/26 16:02:02-07:00 tgraf@suug.ch +1 -218
#   [PKT_SCHED]: Remove obsolete definitions in pkt_sched.h
#   
#   Removes all obsolete definitions in pkt_sched.h now in sch_generic.h
#   or act_api.h.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 16:00:53-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Add net/act_api.h with public action/policer bits
#   
#   Adds net/act_api.h containing all public action/policer bits used
#   by schedulers and classifiers
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/act_api.h
#   2004/10/26 16:00:20-07:00 tgraf@suug.ch +122 -0
#   [PKT_SCHED]: Add net/act_api.h with public action/policer bits
# 
# include/net/act_api.h
#   2004/10/26 16:00:20-07:00 tgraf@suug.ch +0 -0
#   BitKeeper file /disk1/BK/net-2.6/include/net/act_api.h
# 
# ChangeSet
#   2004/10/26 15:58:53-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Remove obsolete definitions in pkt_cls.h
#   
#   Removes all obsolete definitions in pkt_cls.h now in sch_generic.h
#   and includes them via sch_generic.h.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_cls.h
#   2004/10/26 15:58:33-07:00 tgraf@suug.ch +1 -59
#   [PKT_SCHED]: Remove obsolete definitions in pkt_cls.h
#   
#   Removes all obsolete definitions in pkt_cls.h now in sch_generic.h
#   and includes them via sch_generic.h.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 15:57:39-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Add net/sch_generic.h with generic sched definitions.
#   
#   Adds net/sch_generic.h containing all bits directly referenced by
#   schedulers and classifiers. Map of users:
#   
#   Group 1)
#    struct qdisc_rate_table         sch_*, tcf_police -> cls_*
#   
#      Could theoretically be moved to pkt_sched.h with Patch 4
#      but the long term goal it so make net/act_api.h to being
#      dependent on net/pkt_sched.h
#   
#   Group 2)
#    struct Qdisc                    sch_*, tcf_proto -> cls_*
#    struct Qdisc_ops                sch_*, tcf_proto -> cls_*
#    struct Qdisc_class_ops          sch_*, tcf_proto -> cls_*
#    struct tcf_proto_ops            sch_*, cls_*
#    struct tcf_proto                sch_*, cls_*
#   
#      Obviously used by schedulers but also by classifiers to
#      bind classes (tcf_proto -> Qdisc -> Qdisc_ops ->
#      Qdisc_class_ops). tcf_proto OTOH is used by schedulers,
#      (neat cross usage).
#   
#   Group 3)
#    struct tcf_result               sch_*, cls_*
#   
#      Used to communicate between scheduler and classifer
#      to report classify result.
#    
#   Group 4)
#    sch_tree_(un)lock               sch_*, cls_*
#    tcf_tree_(un)lock               sch_*, cls_*
#    qdisc(un)lock_tree              sch_*, cls_*
#      
#      Randomly used in schedulers and classifiers.
#    
#   Group 5)
#    tcf_destroy                     sch_*, cls_api.c
#   
#      Coud theoretically be moved to pkt_sched.h if we include
#      pkt_sched.h in cls_api.c but this is really generic and
#      it seemd cleaner to have it here. This would be the only
#      classifier related action in pkt_sched.h
#   
#   The following types are referenced in sch_generic.h but defined in
#   either pkt_cls.h or pkt_sched.h because they will never be used
#   by the other side:
#   
#     - qdisc_walker (pkt_sched.h)
#     - tcf_walker (pkt_cls.h)
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/sch_generic.h
#   2004/10/26 15:56:55-07:00 tgraf@suug.ch +175 -0
#   [PKT_SCHED]: Add net/sch_generic.h with generic sched definitions.
# 
# include/net/sch_generic.h
#   2004/10/26 15:56:55-07:00 tgraf@suug.ch +0 -0
#   BitKeeper file /disk1/BK/net-2.6/include/net/sch_generic.h
# 
# ChangeSet
#   2004/10/26 15:55:51-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: pkt_cls.h needs pkt_sched.h
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/pkt_cls.h
#   2004/10/26 15:55:20-07:00 tgraf@suug.ch +2 -0
#   [PKT_SCHED]: pkt_cls.h needs pkt_sched.h
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/27 00:36:12+02:00 rmk+lkml@arm.linux.org.uk 
#   arm: Fix ARM kernel build with permitted binutils versions
#   
#   All ARM binutils versions post 2.11.90 contains an extra "feature" which
#   interferes with the kernel in various ways - extra "mapping symbols"
#   in the ELF symbol table '$a', '$t' and '$d'.  This causes two problems:
#   
#   1. Since '$a' symbols have the same value as function names, this
#      causes anything which uses the kallsyms infrastructure to report
#      wrong values.
#   2. programs which parse System.map do not expect symbols to start with
#      '$'.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
#   
#   ===== kernel/module.c 1.120 vs edited =====
# 
# scripts/mksysmap
#   2004/10/08 17:39:39+02:00 rmk+lkml@arm.linux.org.uk +1 -1
#   arm: Fix ARM kernel build with permitted binutils versions
# 
# scripts/kallsyms.c
#   2004/10/08 17:34:20+02:00 rmk+lkml@arm.linux.org.uk +13 -1
#   arm: Fix ARM kernel build with permitted binutils versions
# 
# kernel/module.c
#   2004/10/08 17:34:19+02:00 rmk+lkml@arm.linux.org.uk +14 -2
#   arm: Fix ARM kernel build with permitted binutils versions
# 
# ChangeSet
#   2004/10/27 00:29:10+02:00 juhl-lkml@dif.dk 
#   kconfig: Small spelling fix for MODULE_SRCVERSION_ALL Kconfig
#   
#   Here's a trivial patch fixing a small spelling error in init/Kconfig in
#   the description of MODULE_SRCVERSION_ALL
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# init/Kconfig
#   2004/10/24 17:41:12+02:00 juhl-lkml@dif.dk +1 -1
#   kconfig: Small spelling fix for MODULE_SRCVERSION_ALL Kconfig
# 
# ChangeSet
#   2004/10/27 00:27:31+02:00 trini@kernel.crashing.org 
#   kbuild: warning fixes on Solaris 9
#   
#   The following set of patches is based loosely on the patches that
#   Jean-Christophe Dubois came up with for 2.6.7.  Where as the original
#   patches added a number of casts to unsigned char, I went the route of
#   making the chars be explicitly signed.  I honestly don't know which
#   route is better to go down.  Doing this is the bulk of the patch.  Out
#   of the rest of the odds 'n ends is that on Solaris, Elf32_Word is a
#   ulong, which means all of the printf's are unhappy (uint format, ulong
#   arg) for most of the typedefs.
#   
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# scripts/mod/sumversion.c
#   2004/10/27 00:22:41+02:00 trini@kernel.crashing.org +4 -4
#   kbuild: warning fixes on Solaris 9
# 
# scripts/mod/modpost.c
#   2004/10/27 00:22:13+02:00 trini@kernel.crashing.org +1 -1
#   kbuild: warning fixes on Solaris 9
# 
# scripts/mod/file2alias.c
#   2004/10/27 00:22:12+02:00 trini@kernel.crashing.org +12 -7
#   kbuild: warning fixes on Solaris 9
# 
# scripts/kconfig/symbol.c
#   2004/10/27 00:22:08+02:00 trini@kernel.crashing.org +1 -1
#   kbuild: warning fixes on Solaris 9
# 
# scripts/kconfig/mconf.c
#   2004/10/27 00:22:09+02:00 trini@kernel.crashing.org +2 -2
#   kbuild: warning fixes on Solaris 9
# 
# scripts/kconfig/confdata.c
#   2004/10/27 00:22:10+02:00 trini@kernel.crashing.org +3 -3
#   kbuild: warning fixes on Solaris 9
# 
# scripts/kconfig/conf.c
#   2004/10/27 00:22:04+02:00 trini@kernel.crashing.org +3 -3
#   kbuild: warning fixes on Solaris 9
# 
# scripts/conmakehash.c
#   2004/10/27 00:22:06+02:00 trini@kernel.crashing.org +1 -1
#   kbuild: warning fixes on Solaris 9
# 
# scripts/basic/split-include.c
#   2004/10/27 00:22:06+02:00 trini@kernel.crashing.org +1 -1
#   kbuild: warning fixes on Solaris 9
# 
# scripts/basic/fixdep.c
#   2004/10/27 00:22:09+02:00 trini@kernel.crashing.org +5 -5
#   kbuild: warning fixes on Solaris 9
# 
# scripts/basic/docproc.c
#   2004/10/27 00:22:07+02:00 trini@kernel.crashing.org +7 -7
#   kbuild: warning fixes on Solaris 9
# 
# arch/ppc/boot/utils/mkbugboot.c
#   2004/10/27 00:22:03+02:00 trini@kernel.crashing.org +1 -1
#   kbuild: warning fixes on Solaris 9
# 
# ChangeSet
#   2004/10/27 00:07:03+02:00 sam@mars.ravnborg.org 
#   kbuild/usr: initramfs list fixed and simplified
#   
#   Moving logic to scripts/gen_initramfs_list.sh make a nice cleanup in
#   usr/Makefile.
#   A new initramfs image will be generated if the initramfs_list file changes.
#   This patch also fixes the bug with make O=..
#   
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# usr/Makefile
#   2004/10/27 00:06:46+02:00 sam@mars.ravnborg.org +9 -20
#   Simplify - logic moved to gen_initramfs_list.sh script
# 
# scripts/gen_initramfs_list.sh
#   2004/10/27 00:06:46+02:00 sam@mars.ravnborg.org +35 -16
#   Moved logic to this file.
#   It now handles both dirs, files and no input given.
#   For invalid input print error and boild out.
# 
# scripts/Makefile.lib
#   2004/10/27 00:06:46+02:00 sam@mars.ravnborg.org +27 -0
#   Added filechk - copy from top level Makefile
# 
# BitKeeper/etc/ignore
#   2004/10/27 00:06:24+02:00 sam@mars.ravnborg.org +1 -0
#   added usr/initramfs_list
# 
# BitKeeper/deleted/.del-initramfs_list~e02c62efaa478389
#   2004/10/27 00:02:17+02:00 sam@mars.ravnborg.org +0 -0
#   Delete: usr/initramfs_list
# 
# ChangeSet
#   2004/10/26 22:53:13+02:00 bzolnier@trik.(none) 
#   [ide] remove needless exports from ide-taskfile.c
#   
#   Also remove unused MAX_DMA define.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# include/linux/ide.h
#   2004/10/26 22:51:19+02:00 bzolnier@trik.(none) +0 -5
#   [ide] remove needless exports from ide-taskfile.c
# 
# drivers/ide/ide-taskfile.c
#   2004/10/26 22:52:46+02:00 bzolnier@trik.(none) +4 -29
#   [ide] remove needless exports from ide-taskfile.c
# 
# ChangeSet
#   2004/10/26 20:37:32+00:00 steiner@sgi.com 
#   [IA64] Delete obsolete code from SGI console driver
#   
#   Delete obsolete code that supports the SGI simulator. This
#   support code has been moved into the fakeprom and is no
#   longer required in the kernel.
#    
#   Signed-off-by: Jack Steiner <steiner@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# drivers/serial/sn_console.c
#   2004/10/26 20:36:11+00:00 steiner@sgi.com +4 -75
#   Delete obsolete code from SGI console driver
# 
# ChangeSet
#   2004/10/26 20:33:21+00:00 jasonuhl@sgi.com 
#   [IA64] fix pgtable.h comments
#   
#   Remove some statements from comments in <asm-ia64/pgtable.h> whose
#   correctness is page size dependent ... and based on using an 8k
#   page size, which almost nobody actually uses.
#    
#   Signed-off-by: Jason Uhlenkott <jasonuhl@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/pgtable.h
#   2004/10/26 20:31:23+00:00 jasonuhl@sgi.com +4 -4
#   fix pgtable.h comments
# 
# ChangeSet
#   2004/10/26 22:19:18+02:00 bzolnier@trik.(none) 
#   [ide] add ide_use_dma()
#   
#   Should prevent bugs like the recent piix one in the future.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# include/linux/ide.h
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +2 -0
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/triflex.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +8 -17
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/slc90e66.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +6 -27
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/sis5513.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -27
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/siimage.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +6 -27
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/serverworks.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -29
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/piix.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +1 -15
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/pdc202xx_old.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -28
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/pdc202xx_new.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -28
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/it8172.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -27
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/hpt366.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -26
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/hpt34x.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +9 -29
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/cmd64x.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -27
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/atiixp.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -27
#   [ide] add ide_use_dma()
# 
# drivers/ide/pci/aec62xx.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +7 -27
#   [ide] add ide_use_dma()
# 
# drivers/ide/ide-dma.c
#   2004/10/26 22:18:53+02:00 bzolnier@trik.(none) +32 -0
#   [ide] add ide_use_dma()
# 
# ChangeSet
#   2004/10/26 21:55:02+02:00 bzolnier@trik.(none) 
#   [ide] add pci_get_legacy_ide_irq()
#   
#   This patch adds pci_get_legacy_ide_irq() to the PCI layer for dealing
#   with PCI IDE chipsets that use the "legacy mode" IRQ routing, thus
#   violating the normal PCI routing.  The generic implementation provides
#   IRQ numbers 14 and 15, and it adds a ppc64 specific one with platform
#   callbacks so that a plaform can provide different IRQ numbers for "legacy"
#   IDE.  I only fixed the amd7xxx.c driver for now, I expect people using
#   this interface will slowly fix their drivers (I will fix via soon as I'll
#   need it too, and maybe a few others).
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# include/asm-ppc64/pci.h
#   2004/10/26 04:18:38+02:00 bzolnier@trik.(none) +10 -1
#   [ide] add pci_get_legacy_ide_irq()
# 
# include/asm-ppc64/machdep.h
#   2004/10/26 04:18:38+02:00 bzolnier@trik.(none) +3 -0
#   [ide] add pci_get_legacy_ide_irq()
# 
# include/asm-generic/pci.h
#   2004/10/26 04:18:38+02:00 bzolnier@trik.(none) +7 -0
#   [ide] add pci_get_legacy_ide_irq()
# 
# drivers/ide/pci/amd74xx.c
#   2004/10/26 04:18:38+02:00 bzolnier@trik.(none) +2 -2
#   [ide] add pci_get_legacy_ide_irq()
# 
# ChangeSet
#   2004/10/26 21:53:59+02:00 bzolnier@trik.(none) 
#   [ide] remove unused internal exports from ide core
#   
#   From: Arjan van de Ven <arjan@fenrus.demon.nl>
#   
#   ide-iops.c exports a few functions that either have no users or have no
#   users AND shouldn't be used by drivers; the patch below unexports them.
#   
#   -EXPORT_SYMBOL(SELECT_INTERRUPT);
#   -EXPORT_SYMBOL(SELECT_MASK);
#   -EXPORT_SYMBOL(QUIRK_LIST);
#   -EXPORT_SYMBOL(ata_vlb_sync);
#   
#   only used in the core ide code
#   
#   -EXPORT_SYMBOL(ata_input_data);
#   -EXPORT_SYMBOL(ata_output_data);
#   
#   drivers should (and do) use the hwif-> function pointer variant of these,
#   these functions are internal and used for setting the default hwif->
#   function pointers only. No need to export, in fact exporting is only asking
#   for accidents
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/ide-iops.c
#   2004/10/26 21:53:34+02:00 bzolnier@trik.(none) +0 -12
#   [ide] remove unused internal exports from ide core
# 
# ChangeSet
#   2004/10/26 21:50:54+02:00 sam@mars.ravnborg.org 
#   Merge bk://linux-sam.bkbits.net/kbuild
#   into mars.ravnborg.org:/home/sam/bk/to-linus
# 
# lib/Kconfig.debug
#   2004/10/26 21:50:45+02:00 sam@mars.ravnborg.org +0 -0
#   Auto merged
# 
# init/Kconfig
#   2004/10/26 21:50:44+02:00 sam@mars.ravnborg.org +0 -0
#   Auto merged
# 
# arch/i386/Makefile
#   2004/10/26 21:50:44+02:00 sam@mars.ravnborg.org +0 -0
#   Auto merged
# 
# Makefile
#   2004/10/26 21:50:44+02:00 sam@mars.ravnborg.org +0 -0
#   Auto merged
# 
# Documentation/DocBook/Makefile
#   2004/10/26 21:50:44+02:00 sam@mars.ravnborg.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/26 12:32:47-07:00 juhl-lkml@dif.dk 
#   [NET]: Fix spelling error for IPComp help in Kconfig.
#   
#   Signed-off-by: Jasper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/Kconfig
#   2004/10/26 12:32:29-07:00 juhl-lkml@dif.dk +2 -2
#   [NET]: Fix spelling error for IPComp help in Kconfig.
#   
#   Signed-off-by: Jasper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/Kconfig
#   2004/10/26 12:32:28-07:00 juhl-lkml@dif.dk +2 -2
#   [NET]: Fix spelling error for IPComp help in Kconfig.
#   
#   Signed-off-by: Jasper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 12:28:02-07:00 herbert@gondor.apana.org.au 
#   [TCP]: Move tcp_get_info() into tcp.c
#   
#   In my recent foray into tcp_diag I discovered some ugly looking ifdef's
#   on CONFIG_IPV6 that'll break when IPv6 is built as a module.  In order
#   to fix it, we need to allow tcp_diag to be built as a module.
#   
#   So here is a start.  This patch move tcp_get_info from tcp_diag.c into
#   the site of the other caller, tcp.c.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_diag.c
#   2004/10/26 12:27:43-07:00 herbert@gondor.apana.org.au +0 -57
#   [TCP]: Move tcp_get_info() into tcp.c
#   
#   In my recent foray into tcp_diag I discovered some ugly looking ifdef's
#   on CONFIG_IPV6 that'll break when IPv6 is built as a module.  In order
#   to fix it, we need to allow tcp_diag to be built as a module.
#   
#   So here is a start.  This patch move tcp_get_info from tcp_diag.c into
#   the site of the other caller, tcp.c.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp.c
#   2004/10/26 12:27:43-07:00 herbert@gondor.apana.org.au +57 -0
#   [TCP]: Move tcp_get_info() into tcp.c
#   
#   In my recent foray into tcp_diag I discovered some ugly looking ifdef's
#   on CONFIG_IPV6 that'll break when IPv6 is built as a module.  In order
#   to fix it, we need to allow tcp_diag to be built as a module.
#   
#   So here is a start.  This patch move tcp_get_info from tcp_diag.c into
#   the site of the other caller, tcp.c.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 21:27:14+02:00 bzolnier@trik.(none) 
#   [ide] pdc202xx_old: PDC20267 needs the same LBA48 fixup as PDC20265
#   
#   From: Krzysztof Chmielewski <k.chmielewski@neostrada.pl>
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/pdc202xx_old.c
#   2004/10/26 21:26:53+02:00 bzolnier@trik.(none) +2 -1
#   [ide] pdc202xx_old: PDC20267 needs the same LBA48 fixup as PDC20265
# 
# ChangeSet
#   2004/10/26 19:24:59+00:00 kaos@sgi.com 
#   [IA64] Correct references from text/data to init.text/data.
#   
#   These errors were found by 'make buildcheck'.
#    
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# drivers/ide/pci/sgiioc4.c
#   2004/10/26 19:23:57+00:00 kaos@sgi.com +6 -6
#   Correct references from text/data to init.text/data.
# 
# arch/ia64/mm/discontig.c
#   2004/10/26 19:23:47+00:00 kaos@sgi.com +2 -2
#   Correct references from text/data to init.text/data.
# 
# ChangeSet
#   2004/10/26 21:19:43+02:00 bzolnier@trik.(none) 
#   [ide] ide-probe: undecoded slave fixup
#   
#   Undecoded slave fixup is a oneliner patch to ide-probe to
#   recognize both of my Maxtor drives that appear to have the same
#   serial number, D3000000.
#   
#   Signed-off-by: tabris@tabris.net
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/ide-probe.c
#   2004/10/26 21:19:22+02:00 bzolnier@trik.(none) +2 -0
#   [ide] ide-probe: undecoded slave fixup
# 
# ChangeSet
#   2004/10/26 19:14:39+00:00 markgw@sgi.com 
#   [IA64] sn_hwperf correctly handle bricks with multiple slabs
#   
#   The procfs handler for /proc/sgi_sn/sn_topology did
#   not correctly handle multiple slabs in the same brick,
#   e.g. a brick containing a compute node and an ionode.
#    
#   Signed-off-by: Mark Goodwin <markgw@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# include/asm-ia64/sn/sn2/sn_hwperf.h
#   2004/10/26 19:13:13+00:00 markgw@sgi.com +9 -1
#   sn_hwperf correctly handle bricks with multiple slabs
# 
# arch/ia64/sn/kernel/sn2/sn_hwperf.c
#   2004/10/26 19:12:58+00:00 markgw@sgi.com +22 -29
#   sn_hwperf correctly handle bricks with multiple slabs
# 
# ChangeSet
#   2004/10/26 21:07:19+02:00 bzolnier@trik.(none) 
#   [ide] ide-disk: fix /proc/ide/hd?/smart_thresholds
#   
#   Add missing ->data_phase assignment.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/ide-disk.c
#   2004/10/26 21:06:57+02:00 bzolnier@trik.(none) +1 -0
#   [ide] ide-disk: fix /proc/ide/hd?/smart_thresholds
# 
# ChangeSet
#   2004/10/26 19:03:51+00:00 kaos@sgi.com 
#   [IA64] Correct bit test for salinfo oem decode
#   
#   The valid.oem_data bit is in different positions in each section.  Make
#   the test for valid oem data a section specific test.
#    
#   Signed-off-by: Keith Owens <kaos@sgi.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/sn/kernel/mca.c
#   2004/10/26 19:02:40+00:00 kaos@sgi.com +15 -13
#   Correct bit test for salinfo oem decode
# 
# ChangeSet
#   2004/10/26 18:41:39+00:00 eranian@hpl.hp.com 
#   [IA64] misc small patches for perfmon
#   
#   change-log:
#   - update comment for pfm_do_fasync()
#   - fix return value for pfm_smpl_buffer_alloc(). Now
#     return ENOMEM instead of EAGAIN when buffer too big
#     for RLIMIT_MEMLOCK.
#   - added missing vm_pgoff initialization in pfm_smpl_buffer_alloc()
#   - added flags tro debug print in pfm_write_pmcs
#   - added seed and mask to debug print in pfm_write_pmds
#   - shorten some of the debug prints
#   - remove bogus sanity check from pfm_save_regs() in SMP.
#     this could cause invalid PMU state restore
#   
#   signed-off-by: eranian@hpl.hp.com
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/kernel/perfmon.c
#   2004/10/26 18:39:25+00:00 eranian@hpl.hp.com +12 -20
#   misc small patches for perfmon
# 
# ChangeSet
#   2004/10/26 18:36:52+00:00 alex.williamson@hp.com 
#   [IA64] efi.c: fix mem= & max_addr=
#   
#   With this change, there's some extra fuzz introduced that a max_addr
#   specification will get rounded down to a granule boundary and memory
#   quantity, when using mem=, will be within a granule size of the
#   requested amount.  Let me know if anyone finds more problems with it.
#   
#   Signed-off-by: Alex Williamson <alex.williamson@hp.com>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/kernel/efi.c
#   2004/10/26 18:34:33+00:00 alex.williamson@hp.com +23 -11
#   fix mem= & max_addr=
# 
# ChangeSet
#   2004/10/26 18:23:18+00:00 akpm@osdl.org 
#   [IA64] Need <asm/uaccess.h> for KERNEL_DS & set_fs() definitions.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Tony Luck <tony.luck@intel.com>
# 
# arch/ia64/ia32/elfcore32.h
#   2004/10/26 18:20:48+00:00 akpm@osdl.org +1 -0
#   Need <asm/uaccess.h> for KERNEL_DS & set_fs() definitions.
# 
# ChangeSet
#   2004/10/26 09:09:37-07:00 torvalds@ppc970.osdl.org 
#   Merge bk://gkernel.bkbits.net/net-drivers-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# net/core/dev.c
#   2004/10/26 09:09:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# include/linux/netdevice.h
#   2004/10/26 09:09:33-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/26 08:22:01-07:00 akpm@osdl.org 
#   [PATCH] revert- sys_setaltroot
#   
#   We decided to do this a different way.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/syscalls.h
#   2004/10/24 02:47:46-07:00 akpm@osdl.org +0 -1
#   revert- sys_setaltroot
# 
# include/asm-sparc64/unistd.h
#   2004/10/24 02:47:46-07:00 akpm@osdl.org +1 -1
#   revert- sys_setaltroot
# 
# include/asm-ia64/unistd.h
#   2004/10/24 02:47:46-07:00 akpm@osdl.org +0 -1
#   revert- sys_setaltroot
# 
# include/asm-i386/unistd.h
#   2004/10/24 03:32:46-07:00 akpm@osdl.org +1 -1
#   revert- sys_setaltroot
# 
# fs/namei.c
#   2004/10/24 03:32:35-07:00 akpm@osdl.org +5 -57
#   revert- sys_setaltroot
# 
# arch/sparc64/kernel/systbls.S
#   2004/10/24 02:47:46-07:00 akpm@osdl.org +2 -2
#   revert- sys_setaltroot
# 
# arch/ia64/kernel/entry.S
#   2004/10/24 02:47:46-07:00 akpm@osdl.org +1 -1
#   revert- sys_setaltroot
# 
# arch/i386/kernel/entry.S
#   2004/10/24 03:32:48-07:00 akpm@osdl.org +1 -1
#   revert- sys_setaltroot
# 
# ChangeSet
#   2004/10/26 08:02:35-07:00 roland@redhat.com 
#   [PATCH] Wake up signalled tasks when exiting ptrace
#   
#   In general it is not safe to do any non-ptrace wakeup of a thread in
#   TASK_TRACED, because the waking thread could race with a ptrace call
#   that could be doing things like mucking directly with its kernel stack. 
#   
#   AFAIK noone has established that whatever clobberation ptrace can do to
#   a running thread is safe even if it will never return to user mode, so
#   we can't allow this even for SIGKILL.
#   
#   What we _can_ safely do is make a thread switching out of TASK_TRACED
#   resume rather than sitting in TASK_STOPPED if it has a pending SIGKILL
#   or SIGCONT.  The following patch does this.
#   
#   This should be sufficient for the shutdown case.  When killing all
#   processes, if the tracer gets killed first, the tracee goes into
#   TASK_STOPPED and will be woken and killed by the SIGKILL (same as
#   before).  If the tracee gets killed first, it gets a pending SIGKILL and
#   doesn't wake up immediately--but, now, when the tracer gets killed, the
#   tracee will then wake up to die. 
#   
#   This will also fix the (same) situations that can arise now where you
#   have used gdb (or whatever ptrace caller), killed -9 the gdb and the
#   process being debugged, but still have to kill -CONT the process before
#   it goes away (now it should just go away either the first time or when
#   you kill gdb). 
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/ptrace.c
#   2004/10/25 21:13:16-07:00 roland@redhat.com +14 -0
#   Wake up signalled tasks when exiting ptrace
# 
# ChangeSet
#   2004/10/26 08:02:20-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Some sparse fixes
#   
#   This is a batch of sparse fixes for things in arch/ppc64/* and
#   include/asm-ppc64/*
#   
#   More to come of course...
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/udbg.h
#   2004/10/25 23:52:29-07:00 benh@kernel.crashing.org +3 -1
#   ppc64: Some sparse fixes
# 
# include/asm-ppc64/io.h
#   2004/10/25 23:16:16-07:00 benh@kernel.crashing.org +1 -1
#   ppc64: Some sparse fixes
# 
# arch/ppc64/mm/init.c
#   2004/10/25 23:16:16-07:00 benh@kernel.crashing.org +3 -3
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/xics.c
#   2004/10/25 23:16:16-07:00 benh@kernel.crashing.org +21 -18
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/vecemu.c
#   2004/10/25 23:42:56-07:00 benh@kernel.crashing.org +1 -1
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/udbg.c
#   2004/10/25 23:51:33-07:00 benh@kernel.crashing.org +46 -46
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/rtasd.c
#   2004/10/25 23:16:16-07:00 benh@kernel.crashing.org +1 -1
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/proc_ppc64.c
#   2004/10/25 23:36:24-07:00 benh@kernel.crashing.org +22 -11
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/pci.c
#   2004/10/25 23:16:16-07:00 benh@kernel.crashing.org +2 -2
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/pSeries_pci.c
#   2004/10/25 23:16:16-07:00 benh@kernel.crashing.org +8 -8
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/nvram.c
#   2004/10/25 23:16:16-07:00 benh@kernel.crashing.org +1 -1
#   ppc64: Some sparse fixes
# 
# arch/ppc64/kernel/lparcfg.c
#   2004/10/25 23:42:05-07:00 benh@kernel.crashing.org +5 -5
#   ppc64: Some sparse fixes
# 
# ChangeSet
#   2004/10/26 08:02:03-07:00 benh@kernel.crashing.org 
#   [PATCH] 8250: Fix empty port registration
#   
#   My latest 8250 patch prevented registration of "empty" ports (ports that
#   have a 0 iobase in the static table). Unfortunately, some archs seem to rely
#   on this, and so broke. This patch reverts that part of the patch.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/serial/8250.c
#   2004/10/25 05:05:26-07:00 benh@kernel.crashing.org +0 -7
#   8250: Fix empty port registration
# 
# ChangeSet
#   2004/10/26 07:53:34-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Add new "Maple" platform support
#   
#   This adds support for the Maple 970FX Eval Board.  It adds the basic
#   arch support.  For the Maple to be fully functional, it needs a couple
#   more patches to be applied for IDE and Ethernet that are currently
#   pending with the respective maintainers of those subsystems.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/maple_time.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +226 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/maple_setup.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +243 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/maple_pci.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +528 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/configs/maple_defconfig
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +921 -0
#   ppc64: Add new "Maple" platform support
# 
# include/asm-ppc64/processor.h
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +1 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/udbg.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +29 -3
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/setup.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +8 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/prom_init.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +2 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/misc.S
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +2 -2
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/maple_time.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/maple_time.c
# 
# arch/ppc64/kernel/maple_setup.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/maple_setup.c
# 
# arch/ppc64/kernel/maple_pci.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/maple_pci.c
# 
# arch/ppc64/kernel/idle.c
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +5 -3
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/kernel/Makefile
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +3 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/configs/maple_defconfig
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/configs/maple_defconfig
# 
# arch/ppc64/Makefile
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +2 -0
#   ppc64: Add new "Maple" platform support
# 
# arch/ppc64/Kconfig
#   2004/10/25 19:24:06-07:00 benh@kernel.crashing.org +15 -0
#   ppc64: Add new "Maple" platform support
# 
# ChangeSet
#   2004/10/26 07:31:50-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Fix g5-only build
#   
#   The iommu_free_table() patch broke g5 only build by adding back some
#   incestuous relationship between generic code and pSeries code. 
#   
#   This wraps this in #ifdef as a quick fix until the original author of
#   the patch comes up with a better solution.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/iommu.h
#   2004/10/26 00:19:17-07:00 benh@kernel.crashing.org +8 -0
#   ppc64: Fix g5-only build
# 
# arch/ppc64/kernel/prom.c
#   2004/10/26 00:22:28-07:00 benh@kernel.crashing.org +5 -0
#   ppc64: Fix g5-only build
# 
# ChangeSet
#   2004/10/26 07:31:36-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Fix new mpic driver on some POWER3
#   
#   On machines using the "ISU" mecanism for the MPIC, the new driver didn't properly
#   calculate the new interrupt count when an ISU was added. That would cause later on
#   failure to request interrupts in the offending range.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/mpic.c
#   2004/10/25 21:36:00-07:00 benh@kernel.crashing.org +4 -2
#   ppc64: Fix new mpic driver on some POWER3
# 
# ChangeSet
#   2004/10/26 07:31:24-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: PCI ignores empty phb regions
#   
#   The ppc64 PCI code, when parsing the OF tree, may end up getting empty
#   regions in addition to the "normal" ones for the PHB (some pSeries OF
#   device-tree contains weird "ranges" properties). These are harmless but
#   do trigger some annoying warnings during boot, so let's ignore them.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pci.c
#   2004/10/25 21:18:54-07:00 benh@kernel.crashing.org +2 -0
#   ppc64: PCI ignores empty phb regions
# 
# ChangeSet
#   2004/10/26 03:42:24-04:00 jgarzik@pobox.com 
#   [libata] return ENOTTY rather than EOPNOTSUPP for unknown-ioctl
# 
# drivers/scsi/libata-scsi.c
#   2004/10/26 03:42:18-04:00 jgarzik@pobox.com +1 -1
#   [libata] return ENOTTY rather than EOPNOTSUPP for unknown-ioctl
# 
# ChangeSet
#   2004/10/26 01:20:52-04:00 arjan@infradead.org 
#   [PATCH] remove NET_HW_FLOWCONTROL
#   
#   CONFIG_NET_HW_FLOWCONTROL is entirely unused now, and superceded by NAPI in
#   practice, so remove the dead code
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# net/core/dev.c
#   2004/10/25 16:14:10-04:00 arjan@infradead.org +2 -91
#   remove NET_HW_FLOWCONTROL
# 
# net/Kconfig
#   2004/10/25 16:14:23-04:00 arjan@infradead.org +0 -18
#   remove NET_HW_FLOWCONTROL
# 
# include/linux/netdevice.h
#   2004/10/25 16:08:54-04:00 arjan@infradead.org +0 -2
#   remove NET_HW_FLOWCONTROL
# 
# ChangeSet
#   2004/10/25 21:28:00-07:00 davem@nuts.davemloft.net 
#   Merge bk://bk.skbuff.net:20610/linux-2.6-inet6-20041026/
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# net/ipv6/route.c
#   2004/10/25 21:27:49-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/net/ip6_route.h
#   2004/10/25 21:27:49-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/26 13:11:47+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] kill a warning when building without CONFIG_SYSCTL.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/addrconf.c
#   2004/10/26 13:11:35+09:00 yoshfuji@linux-ipv6.org +2 -1
#   [IPV6] kill a warning when building without CONFIG_SYSCTL.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2004/10/25 21:11:03-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: don't include <stddef.h>
#   
#   This patch fixes a couple of places where the ppc64 iSeries code would
#   #include <stddef.h>. The only "system" include I consider acceptable is
#   <stdarg.h> provided by gcc.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pacaData.c
#   2004/10/25 15:43:35-07:00 benh@kernel.crashing.org +2 -3
#   ppc64: don't include <stddef.h>
# 
# arch/ppc64/kernel/LparData.c
#   2004/10/25 15:44:56-07:00 benh@kernel.crashing.org +2 -3
#   ppc64: don't include <stddef.h>
# 
# ChangeSet
#   2004/10/25 21:10:51-07:00 benh@kernel.crashing.org 
#   [PATCH] Remove bogus definition of local chrp_int_ack_special in pSeries_setup.c.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pSeries_setup.c
#   2004/10/25 20:09:10-07:00 benh@kernel.crashing.org +1 -3
#   Remove bogus definition of local chrp_int_ack_special in pSeries_setup.c.
# 
# ChangeSet
#   2004/10/25 20:57:45-07:00 herbert@gondor.apana.org.au 
#   [TCP]: Handle real partial-ACKs of TSO frames correctly.
#   
#   Actually, I think we've caught your crash now.  If that code path
#   is triggering at all, then it'll trigger with TSO packets too.  If
#   we get a truly partial ack on a TSO packet, then tcp_tso_acked will
#   not trim it off.  So we will fall through to this last-ditch trim
#   call, which doesn't update packets_out.
#   
#   There are two solutions to this problem.  I've taken the simpler
#   approach for now.  We simply trim off the partial bits in tcp_tso_acked
#   and live with the fact that the packet counters may differ from
#   what's on the netwrok by one.
#   
#   Later on we can 'fix' this by remembering where the original TSO
#   packet started from, perhaps in skb->h or somewhere.  Dave, is this
#   worth it?
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_output.c
#   2004/10/25 20:57:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [TCP]: Handle real partial-ACKs of TSO frames correctly.
#   
#   Actually, I think we've caught your crash now.  If that code path
#   is triggering at all, then it'll trigger with TSO packets too.  If
#   we get a truly partial ack on a TSO packet, then tcp_tso_acked will
#   not trim it off.  So we will fall through to this last-ditch trim
#   call, which doesn't update packets_out.
#   
#   There are two solutions to this problem.  I've taken the simpler
#   approach for now.  We simply trim off the partial bits in tcp_tso_acked
#   and live with the fact that the packet counters may differ from
#   what's on the netwrok by one.
#   
#   Later on we can 'fix' this by remembering where the original TSO
#   packet started from, perhaps in skb->h or somewhere.  Dave, is this
#   worth it?
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_input.c
#   2004/10/25 20:57:25-07:00 herbert@gondor.apana.org.au +6 -12
#   [TCP]: Handle real partial-ACKs of TSO frames correctly.
#   
#   Actually, I think we've caught your crash now.  If that code path
#   is triggering at all, then it'll trigger with TSO packets too.  If
#   we get a truly partial ack on a TSO packet, then tcp_tso_acked will
#   not trim it off.  So we will fall through to this last-ditch trim
#   call, which doesn't update packets_out.
#   
#   There are two solutions to this problem.  I've taken the simpler
#   approach for now.  We simply trim off the partial bits in tcp_tso_acked
#   and live with the fact that the packet counters may differ from
#   what's on the netwrok by one.
#   
#   Later on we can 'fix' this by remembering where the original TSO
#   packet started from, perhaps in skb->h or somewhere.  Dave, is this
#   worth it?
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/26 12:55:56+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: update neighbor cache entry by RS.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2004/10/26 12:55:42+09:00 yoshfuji@linux-ipv6.org +62 -0
#   [IPV6] NDISC: update neighbor cache entry by RS.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/ndisc.h
#   2004/10/26 12:55:42+09:00 yoshfuji@linux-ipv6.org +5 -0
#   [IPV6] NDISC: update neighbor cache entry by RS.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2004/10/26 12:54:58+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] simplify functions related to RTF_ALLONLINK.
#   
#   Simplify ipv6_get_saddr(), ipv6_dev_get_saddr() and
#   rt6_purge_dflt_routers().
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/route.c
#   2004/10/26 12:54:27+09:00 yoshfuji@linux-ipv6.org +2 -5
#   [IPV6] simplify functions related to RTF_ALLONLINK.
#   
#   Simplify ipv6_get_saddr(), ipv6_dev_get_saddr() and
#   rt6_purge_dflt_routers().
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2004/10/26 12:54:27+09:00 yoshfuji@linux-ipv6.org +2 -2
#   [IPV6] simplify functions related to RTF_ALLONLINK.
#   
#   Simplify ipv6_get_saddr(), ipv6_dev_get_saddr() and
#   rt6_purge_dflt_routers().
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/addrconf.c
#   2004/10/26 12:54:27+09:00 yoshfuji@linux-ipv6.org +5 -18
#   [IPV6] simplify functions related to RTF_ALLONLINK.
#   
#   Simplify ipv6_get_saddr(), ipv6_dev_get_saddr() and
#   rt6_purge_dflt_routers().
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/ip6_route.h
#   2004/10/26 12:54:27+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [IPV6] simplify functions related to RTF_ALLONLINK.
#   
#   Simplify ipv6_get_saddr(), ipv6_dev_get_saddr() and
#   rt6_purge_dflt_routers().
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/addrconf.h
#   2004/10/26 12:54:27+09:00 yoshfuji@linux-ipv6.org +1 -2
#   [IPV6] simplify functions related to RTF_ALLONLINK.
#   
#   Simplify ipv6_get_saddr(), ipv6_dev_get_saddr() and
#   rt6_purge_dflt_routers().
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2004/10/26 12:54:41+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] Remove codes related to RTF_ALLONLINK.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/route.c
#   2004/10/26 12:54:23+09:00 yoshfuji@linux-ipv6.org +2 -5
#   [IPV6] Remove codes related to RTF_ALLONLINK.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2004/10/26 12:54:23+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [IPV6] Remove codes related to RTF_ALLONLINK.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ip6_fib.c
#   2004/10/26 12:54:23+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [IPV6] Remove codes related to RTF_ALLONLINK.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/addrconf.c
#   2004/10/26 12:54:23+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [IPV6] Remove codes related to RTF_ALLONLINK.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/linux/ipv6_route.h
#   2004/10/26 12:54:23+09:00 yoshfuji@linux-ipv6.org +2 -1
#   [IPV6] Remove codes related to RTF_ALLONLINK.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2004/10/26 12:51:07+09:00 Brian.Haley@hp.com 
#   [IPV6] Lookup appropriate destination when sending TCPv6 with routing header.
#   
#   Signed-off-by: Brian Haley <Brian.Haley@hp.com>
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/tcp_ipv6.c
#   2004/10/26 12:50:56+09:00 Brian.Haley@hp.com +6 -0
#   [IPV6] Lookup appropriate destination when sending TCPv6 with routing header.
#   
#   Signed-off-by: Brian Haley <Brian.Haley@hp.com>
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2004/10/25 20:49:06-07:00 akpm@osdl.org 
#   [CRYPTO]: aes-586-asm: small optimizations
#   
#   From: Denis Vlasenko <vda@port.imtp.ilyichevsk.odessa.ua>
#   
#   - recode back-to-back fwd_rnd() pairs to avoid two register moves.
#   
#   - ditto for inv_rnd().
#   
#   - optimize out lea 0(%ebp),%ebp
#   
#   - remove two stray insns
#   
#   # size aes-i586-asm.o.org aes-i586-asm.o
#      text    data     bss     dec     hex filename
#      5971       0       0    5971    1753 aes-i586-asm.o.org
#      5905       0       0    5905    1711 aes-i586-asm.o
#   
#   Overall, patch does not add and does not modify any insns, only removes a
#   handful of them.  However, speed difference is way below noise level.
#   
#   Run-tested with tcrypt module.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/i386/crypto/aes-i586-asm.S
#   2004/10/25 20:48:46-07:00 akpm@osdl.org +103 -65
#   [CRYPTO]: aes-586-asm: small optimizations
#   
#   From: Denis Vlasenko <vda@port.imtp.ilyichevsk.odessa.ua>
#   
#   - recode back-to-back fwd_rnd() pairs to avoid two register moves.
#   
#   - ditto for inv_rnd().
#   
#   - optimize out lea 0(%ebp),%ebp
#   
#   - remove two stray insns
#   
#   # size aes-i586-asm.o.org aes-i586-asm.o
#      text    data     bss     dec     hex filename
#      5971       0       0    5971    1753 aes-i586-asm.o.org
#      5905       0       0    5905    1711 aes-i586-asm.o
#   
#   Overall, patch does not add and does not modify any insns, only removes a
#   handful of them.  However, speed difference is way below noise level.
#   
#   Run-tested with tcrypt module.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:48:25-07:00 akpm@osdl.org 
#   [CRYPTO]: aes-586-asm: formatting changes
#   
#   From: Denis Vlasenko <vda@port.imtp.ilyichevsk.odessa.ua>
#   
#   - Macro parameters renamed for clarity.
#   
#   - Inaccurate comments fixed.
#   
#   - ebp register usage de-obfuscated (this is needed for next patch).
#   
#   No real code changes.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/i386/crypto/aes-i586-asm.S
#   2004/10/25 20:48:06-07:00 akpm@osdl.org +115 -118
#   [CRYPTO]: aes-586-asm: formatting changes
#   
#   From: Denis Vlasenko <vda@port.imtp.ilyichevsk.odessa.ua>
#   
#   - Macro parameters renamed for clarity.
#   
#   - Inaccurate comments fixed.
#   
#   - ebp register usage de-obfuscated (this is needed for next patch).
#   
#   No real code changes.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:47:38-07:00 akpm@osdl.org 
#   [CRYPTO]: reduce sha512_transform() stack usage, speedup
#   
#   Patch moves large temporary u64 W[80] from stack to ctx struct:
#   
#   * reduces stack usage by 640 bytes
#   * saves one 640-byte memset() per sha512_transform()
#     (we still do it after *all* iterations are done)
#   * quite unexpectedly saves 1.6k of code on i386
#     because stack offsets now fit into 8bits
#     and many stack addressing insns got 3 bytes smaller:
#   
#   # size sha512.o.org sha512.o
#   text       data     bss     dec     hex filename
#   8281        372       0    8653    21cd sha512.o.org
#   6649        372       0    7021    1b6d sha512.o
#   
#   # objdump -d sha512.o.org | cut -b9- >sha512.d.org
#   # objdump -d sha512.o | cut -b9- >sha512.d
#   # diff -u sha512.d.org sha512.d
#   [snip]
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# crypto/sha512.c
#   2004/10/25 20:47:19-07:00 akpm@osdl.org +7 -5
#   [CRYPTO]: reduce sha512_transform() stack usage, speedup
#   
#   Patch moves large temporary u64 W[80] from stack to ctx struct:
#   
#   * reduces stack usage by 640 bytes
#   * saves one 640-byte memset() per sha512_transform()
#     (we still do it after *all* iterations are done)
#   * quite unexpectedly saves 1.6k of code on i386
#     because stack offsets now fit into 8bits
#     and many stack addressing insns got 3 bytes smaller:
#   
#   # size sha512.o.org sha512.o
#   text       data     bss     dec     hex filename
#   8281        372       0    8653    21cd sha512.o.org
#   6649        372       0    7021    1b6d sha512.o
#   
#   # objdump -d sha512.o.org | cut -b9- >sha512.d.org
#   # objdump -d sha512.o | cut -b9- >sha512.d
#   # diff -u sha512.d.org sha512.d
#   [snip]
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:46:17-07:00 akpm@osdl.org 
#   [CRYPTO]: small sha512 cleanup
#   
#   Looks like open-coded be_to_cpu.  GCC produces rather poor code for this. 
#   be_to_cpu produces asm()s which are ~4 times shorter.
#   
#   Compile-tested only.
#   
#   I am not sure whether input can be 64bit-unaligned.
#   If it indeed can be, replace:
#   
#   ((u64*)(input))[I]  ->  get_unaligned( ((u64*)(input))+I )
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# crypto/sha512.c
#   2004/10/25 20:45:58-07:00 akpm@osdl.org +2 -17
#   [CRYPTO]: small sha512 cleanup
#   
#   Looks like open-coded be_to_cpu.  GCC produces rather poor code for this. 
#   be_to_cpu produces asm()s which are ~4 times shorter.
#   
#   Compile-tested only.
#   
#   I am not sure whether input can be 64bit-unaligned.
#   If it indeed can be, replace:
#   
#   ((u64*)(input))[I]  ->  get_unaligned( ((u64*)(input))+I )
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:45:35-07:00 akpm@osdl.org 
#   [CRYPTO]: small sha256 cleanup
#   
#   Looks like open-coded be_to_cpu.  GCC produces rather poor code for this. 
#   be_to_cpu produces asm()s which are ~4 times shorter.
#   
#   Compile-tested only.
#   
#   I am not sure whether input can be 32bit-unaligned.
#   If it indeed can be, replace:
#   
#   ((u32*)(input))[I]  ->  get_unaligned( ((u32*)(input))+I )
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# crypto/sha256.c
#   2004/10/25 20:45:16-07:00 akpm@osdl.org +1 -9
#   [CRYPTO]: small sha256 cleanup
#   
#   Looks like open-coded be_to_cpu.  GCC produces rather poor code for this. 
#   be_to_cpu produces asm()s which are ~4 times shorter.
#   
#   Compile-tested only.
#   
#   I am not sure whether input can be 32bit-unaligned.
#   If it indeed can be, replace:
#   
#   ((u32*)(input))[I]  ->  get_unaligned( ((u32*)(input))+I )
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 23:42:58-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/janitor
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/tulip/tulip_core.c
#   2004/10/25 23:42:55-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/slip.c
#   2004/10/25 23:42:55-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/sis900.c
#   2004/10/25 23:42:55-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ns83820.c
#   2004/10/25 23:42:55-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/3c59x.c
#   2004/10/25 23:42:55-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 23:41:18-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/misc
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/e1000/e1000_main.c
#   2004/10/25 23:41:15-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 20:31:50-07:00 davem@nuts.davemloft.net 
#   Merge bk://212.42.230.204/nf-2.6
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# net/ipv6/netfilter/ip6_tables.c
#   2004/10/25 20:31:40-07:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 20:29:14-07:00 hch@lst.de 
#   [NET]: Remove dead socket layer exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/socket.c
#   2004/10/25 20:28:54-07:00 hch@lst.de +1 -3
#   [NET]: Remove dead socket layer exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/sock.c
#   2004/10/25 20:28:54-07:00 hch@lst.de +9 -17
#   [NET]: Remove dead socket layer exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/sock.h
#   2004/10/25 20:28:54-07:00 hch@lst.de +0 -2
#   [NET]: Remove dead socket layer exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/net.h
#   2004/10/25 20:28:54-07:00 hch@lst.de +0 -1
#   [NET]: Remove dead socket layer exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:26:28-07:00 hch@lst.de 
#   [TCP]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_output.c
#   2004/10/25 20:26:08-07:00 hch@lst.de +0 -5
#   [TCP]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_ipv4.c
#   2004/10/25 20:26:08-07:00 hch@lst.de +2 -3
#   [TCP]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_input.c
#   2004/10/25 20:26:08-07:00 hch@lst.de +0 -1
#   [TCP]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp.c
#   2004/10/25 20:26:08-07:00 hch@lst.de +0 -1
#   [TCP]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/af_inet.c
#   2004/10/25 20:26:08-07:00 hch@lst.de +0 -2
#   [TCP]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/tcp.h
#   2004/10/25 20:26:08-07:00 hch@lst.de +0 -1
#   [TCP]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:25:51-07:00 hch@lst.de 
#   [IPV6]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/ipv6_syms.c
#   2004/10/25 20:25:32-07:00 hch@lst.de +0 -4
#   [IPV6]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:24:58-07:00 torvalds@ppc970.osdl.org 
#   Fix UP non-preempt build for kernel lock changes.
#   
#   Duh. I had tested every "interesting" combination of SMP and PREEMPT,
#   but the _trivial_ one was broken ;)
# 
# include/linux/smp_lock.h
#   2004/10/25 20:24:52-07:00 torvalds@ppc970.osdl.org +1 -1
#   Fix UP non-preempt build for kernel lock changes.
#   
#   Duh. I had tested every "interesting" combination of SMP and PREEMPT,
#   but the _trivial_ one was broken ;)
# 
# ChangeSet
#   2004/10/25 20:24:06-07:00 hch@lst.de 
#   [XFRM]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_state.c
#   2004/10/25 20:23:46-07:00 hch@lst.de +6 -16
#   [XFRM]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2004/10/25 20:23:46-07:00 hch@lst.de +6 -3
#   [XFRM]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_export.c
#   2004/10/25 20:23:46-07:00 hch@lst.de +0 -8
#   [XFRM]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/xfrm.h
#   2004/10/25 20:23:46-07:00 hch@lst.de +0 -7
#   [XFRM]: Remove dead exports.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:22:11-07:00 hch@lst.de 
#   [ATM]: Mark vcc_remove_socket static
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/common.c
#   2004/10/25 20:21:51-07:00 hch@lst.de +1 -2
#   [ATM]: Mark vcc_remove_socket static
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/atmdev.h
#   2004/10/25 20:21:51-07:00 hch@lst.de +0 -1
#   [ATM]: Mark vcc_remove_socket static
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:20:56-07:00 pcaulfie@redhat.com 
#   [DECNET]: Connect hang bugfix
#   
#   This patch fixes a bug in the DECnet connect that seems to have been in 2.6 for
#   a while now.
#   
#   If a connection is rejected by a remote host (eg invalid access control, no
#   such object etc) the Linux end hangs in connect() because it is only waiting for
#   the socket to go into RUN state.
#   
#   This patch sets the ECONNREFUSED error state on the socket when the connection
#   is rejected to that the connect() exits it's wait loop and returns the error to
#   the user.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/decnet/dn_nsp_in.c
#   2004/10/25 20:20:37-07:00 pcaulfie@redhat.com +1 -0
#   [DECNET]: Connect hang bugfix
#   
#   This patch fixes a bug in the DECnet connect that seems to have been in 2.6 for
#   a while now.
#   
#   If a connection is rejected by a remote host (eg invalid access control, no
#   such object etc) the Linux end hangs in connect() because it is only waiting for
#   the socket to go into RUN state.
#   
#   This patch sets the ECONNREFUSED error state on the socket when the connection
#   is rejected to that the connect() exits it's wait loop and returns the error to
#   the user.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:10:46-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: Rename TCQ_F_INGRES to TCQ_F_INGRESS.
#   
#   This typo annoyned me several times by not showing up in greps.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/sch_api.c
#   2004/10/25 20:10:27-07:00 tgraf@suug.ch +3 -3
#   [PKT_SCHED]: Rename TCQ_F_INGRES to TCQ_F_INGRESS.
#   
#   This typo annoyned me several times by not showing up in greps.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/pkt_sched.h
#   2004/10/25 20:10:27-07:00 tgraf@suug.ch +1 -1
#   [PKT_SCHED]: Rename TCQ_F_INGRES to TCQ_F_INGRESS.
#   
#   This typo annoyned me several times by not showing up in greps.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:09:20-07:00 ehrhardt@mathematik.uni-ulm.de 
#   [IPV4]: Do not try to unhash null-netdev nexthops.
#   
#   Signed-off-by: Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/fib_semantics.c
#   2004/10/25 20:09:01-07:00 ehrhardt@mathematik.uni-ulm.de +2 -0
#   [IPV4]: Do not try to unhash null-netdev nexthops.
#   
#   Signed-off-by: Christian Ehrhardt <ehrhardt@mathematik.uni-ulm.de>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:07:30-07:00 chas@cmf.nrl.navy.mil 
#   [ATM]: [horizon] eliminate pci_find_device()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/horizon.h
#   2004/10/25 20:07:11-07:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: [horizon] eliminate pci_find_device()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/horizon.c
#   2004/10/25 20:07:11-07:00 chas@cmf.nrl.navy.mil +156 -176
#   [ATM]: [horizon] eliminate pci_find_device()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:06:33-07:00 linville@tuxdriver.com 
#   [VLAN]: Add MODULE_VERSION
#   
#   Signed-off-by: John W. Linville <linville@tuxdriver.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/8021q/vlan.c
#   2004/10/25 20:06:13-07:00 linville@tuxdriver.com +6 -4
#   [VLAN]: Add MODULE_VERSION
#   
#   Signed-off-by: John W. Linville <linville@tuxdriver.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:05:55-07:00 linville@tuxdriver.com 
#   [BONDING]: Add MODULE_VERSION
#   
#   Signed-off-by: John W. Linville <linville@tuxdriver.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/bonding/bond_main.c
#   2004/10/25 20:05:36-07:00 linville@tuxdriver.com +1 -0
#   [BONDING]: Add MODULE_VERSION
#   
#   Signed-off-by: John W. Linville <linville@tuxdriver.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 20:04:33-07:00 arnouten@bzzt.net 
#   [TCP]: Add /proc/net/tcp{,6} layout documentation.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# Documentation/networking/proc_net_tcp.txt
#   2004/10/25 20:04:00-07:00 arnouten@bzzt.net +47 -0
#   [TCP]: Add /proc/net/tcp{,6} layout documentation.
# 
# Documentation/networking/proc_net_tcp.txt
#   2004/10/25 20:04:00-07:00 arnouten@bzzt.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6/Documentation/networking/proc_net_tcp.txt
# 
# ChangeSet
#   2004/10/25 19:47:47-07:00 suresh.krishnan@ericsson.ca 
#   [NET]: Address family not supported for sendmsg()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/udp.c
#   2004/10/25 19:47:26-07:00 suresh.krishnan@ericsson.ca +1 -1
#   [NET]: Address family not supported for sendmsg()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/raw.c
#   2004/10/25 19:47:26-07:00 suresh.krishnan@ericsson.ca +1 -1
#   [NET]: Address family not supported for sendmsg()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/udp.c
#   2004/10/25 19:47:26-07:00 suresh.krishnan@ericsson.ca +1 -1
#   [NET]: Address family not supported for sendmsg()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/raw.c
#   2004/10/25 19:47:26-07:00 suresh.krishnan@ericsson.ca +1 -1
#   [NET]: Address family not supported for sendmsg()
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 18:42:30-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Cleanup console detection
#   
#   This removes some leftover code that was in #if 0 in the console
#   autodetect code.
#   
#   It also adds passing of the default serial speed as console options when
#   it is available from Open Firmware. 
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/setup.c
#   2004/10/25 18:18:06-07:00 benh@kernel.crashing.org +17 -20
#   ppc64: Cleanup console detection
# 
# ChangeSet
#   2004/10/25 18:42:17-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Improve PCI config accessors
#   
#   This improves the config space access routines on G5, by adding a
#   generic helper function to locate the pci_controller structure (to be
#   used by an upcoming new platform too) and cleaning up the pmac routines.
#   
#   It includes the fix to skip devices that aren't present in the OF tree
#   that is necessary for newer G5 desktop models.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/pci-bridge.h
#   2004/10/25 17:38:39-07:00 benh@kernel.crashing.org +17 -0
#   ppc64: Improve PCI config accessors
# 
# arch/ppc64/kernel/pmac_pci.c
#   2004/10/25 17:38:39-07:00 benh@kernel.crashing.org +53 -65
#   ppc64: Improve PCI config accessors
# 
# arch/ppc64/kernel/pmac.h
#   2004/10/25 17:38:39-07:00 benh@kernel.crashing.org +0 -1
#   ppc64: Improve PCI config accessors
# 
# ChangeSet
#   2004/10/25 18:40:55-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: annotate remaining IO accessors
#   
#   This patch adds proper __iomem annotations to the remaning IO macros on
#   ppc64, and removes now useless casts from eeh.h. This fixes the sparse
#   warnings in mpic.c among others.
#   
#   I need to do an equivalent things for ppc32 (though I think viro did
#   some of it already) and fix users.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/pci-bridge.h
#   2004/10/25 16:04:25-07:00 benh@kernel.crashing.org +3 -3
#   ppc64: annotate remaining IO accessors
# 
# include/asm-ppc64/io.h
#   2004/10/25 16:12:57-07:00 benh@kernel.crashing.org +14 -14
#   ppc64: annotate remaining IO accessors
# 
# include/asm-ppc64/eeh.h
#   2004/10/25 16:17:38-07:00 benh@kernel.crashing.org +85 -72
#   ppc64: annotate remaining IO accessors
# 
# ChangeSet
#   2004/10/25 18:28:03-07:00 akpm@osdl.org 
#   [PATCH] ide_pio_sector() kmap fix
#   
#   kunmap_atomic() takes a kernel-virtual address, not a pageframe address.
#   For the hundredth time.
#   
#   We really should get typechecking happening there..
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/ide/ide-taskfile.c
#   2004/10/25 08:54:48-07:00 akpm@osdl.org +1 -1
#   ide_pio_sector() kmap fix
# 
# ChangeSet
#   2004/10/25 18:25:55-07:00 bfg-kernel@blenning.no 
#   [PATCH] firmware spelling errors
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/scsi/megaraid.c
#   2004/10/25 13:06:50-07:00 bfg-kernel@blenning.no +1 -1
#   firmware spelling errors
# 
# drivers/net/wan/cosa.c
#   2004/10/25 13:06:50-07:00 bfg-kernel@blenning.no +1 -1
#   firmware spelling errors
# 
# drivers/base/Kconfig
#   2004/10/25 13:06:50-07:00 bfg-kernel@blenning.no +1 -1
#   firmware spelling errors
# 
# drivers/atm/fore200e.h
#   2004/10/25 13:06:50-07:00 bfg-kernel@blenning.no +1 -1
#   firmware spelling errors
# 
# ChangeSet
#   2004/10/25 18:25:43-07:00 petero2@telia.com 
#   [PATCH] Fix incorrect kunmap_atomic in pktcdvd
#   
#   The pktcdvd driver uses kunmap_atomic() incorrectly.  The function is
#   supposed to take an address as the first parameter, but the pktcdvd driver
#   passed a page pointer.  Thanks to Douglas Gilbert and Jens Axboe for
#   discovering this.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/pktcdvd.c
#   2004/10/25 13:06:50-07:00 petero2@telia.com +2 -2
#   Fix incorrect kunmap_atomic in pktcdvd
# 
# ChangeSet
#   2004/10/25 18:25:31-07:00 jack@suse.cz 
#   [PATCH] Quota warnings somewhat broken
#   
#   Fix end of lines in quota messages.
#   
#   Signed-off-by: Jan Kara <jack@suse.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/dquot.c
#   2004/10/25 13:06:50-07:00 jack@suse.cz +6 -6
#   Quota warnings somewhat broken
# 
# ChangeSet
#   2004/10/25 18:25:18-07:00 edwardsg@sgi.com 
#   [PATCH] increase max LOG_BUF_SHIFT value
#   
#   We've run into problems at 512p with the kernel log buffer wrapping and
#   overwriting some of the early boot output.  This is with a
#   CONFIG_LOG_BUF_SHIFT value of 20 (1MB).  The patch below just bumps the max
#   possible setting to 21 (2MB).
#   
#   Signed-off-by: Greg Edwards <edwardsg@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# init/Kconfig
#   2004/10/25 13:06:50-07:00 edwardsg@sgi.com +1 -1
#   increase max LOG_BUF_SHIFT value
# 
# ChangeSet
#   2004/10/25 18:25:06-07:00 colin@colino.net 
#   [PATCH] clean up therm_adt746x
#   
#   This patch cleans therm_adt746x a bit: lines at maximum 80 chars width,
#   dispatches the big function in three little ones.
#   
#   Functionality not changed.
#   
#   Signed-off-by: Colin Leroy <colin@colino.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/macintosh/therm_adt746x.c
#   2004/10/25 13:06:50-07:00 colin@colino.net +143 -103
#   clean up therm_adt746x
# 
# ChangeSet
#   2004/10/25 18:24:54-07:00 bjorn.helgaas@hp.com 
#   [PATCH] PCDP: call acpi_register_gsi() with arguments in correct order
#   
#   PCDP: call acpi_register_gsi() with arguments in correct order
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/firmware/pcdp.c
#   2004/10/25 13:06:50-07:00 bjorn.helgaas@hp.com +2 -2
#   PCDP: call acpi_register_gsi() with arguments in correct order
# 
# ChangeSet
#   2004/10/25 18:24:41-07:00 bunk@stusta.de 
#   [PATCH] ISDN hisax_fcpcipnp.c: kill unused variable
#   
#   drivers/isdn/hisax/hisax_fcpcipnp.c: In function `hisax_fcpcipnp_init':
#   drivers/isdn/hisax/hisax_fcpcipnp.c:999: warning: unused variable `pci_nr_found'
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/isdn/hisax/hisax_fcpcipnp.c
#   2004/10/25 13:06:49-07:00 bunk@stusta.de +1 -1
#   ISDN hisax_fcpcipnp.c: kill unused variable
# 
# ChangeSet
#   2004/10/25 18:24:29-07:00 bunk@stusta.de 
#   [PATCH] CREDITS update
#   
#   Adrian sent me a check for $100.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# CREDITS
#   2004/10/25 13:06:49-07:00 bunk@stusta.de +8 -0
#   CREDITS update
# 
# ChangeSet
#   2004/10/25 18:24:17-07:00 margitsw@t-online.de 
#   [PATCH] Add prism54 to MAINTAINERS
#   
#   Add prism54 to MAINTAINERS
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# MAINTAINERS
#   2004/10/25 13:06:49-07:00 margitsw@t-online.de +7 -0
#   Add prism54 to MAINTAINERS
# 
# ChangeSet
#   2004/10/25 18:24:02-07:00 yanmin.zhang@intel.com 
#   [PATCH] hugetlb_get_unmapped_area fix
#   
#   hugetlb_get_unmapped_area() fails to find an unmapped area while unmapped
#   area is huge.  That's because hugetlb_get_unmapped_area just searches
#   forward from mm->free_area_cache.  If reaching TASK_SIZE, it does not go
#   back to TASK_UNMAPPED_BASE, just returns -ENOMEM.
#   
#   1) Add a specific hugetlb_get_unmapped_area on i386.
#   2) Generic hugetlb_get_unmapped_area is also fixed.
#   
#   Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/page.h
#   2004/10/25 13:06:49-07:00 yanmin.zhang@intel.com +1 -0
#   hugetlb_get_unmapped_area fix
# 
# fs/hugetlbfs/inode.c
#   2004/10/25 13:06:49-07:00 yanmin.zhang@intel.com +16 -2
#   hugetlb_get_unmapped_area fix
# 
# arch/i386/mm/hugetlbpage.c
#   2004/10/25 13:06:49-07:00 yanmin.zhang@intel.com +140 -0
#   hugetlb_get_unmapped_area fix
# 
# ChangeSet
#   2004/10/25 18:23:50-07:00 jbarnes@engr.sgi.com 
#   [PATCH] I/O space write barrier
#   
#   On some platforms (e.g.  SGI Challenge, Origin, and Altix machines), writes
#   to I/O space aren't ordered coming from different CPUs.  For the most part,
#   this isn't a problem since drivers generally spinlock around code that does
#   writeX calls, but if the last operation a driver does before it releases a
#   lock is a write and some other CPU takes the lock and immediately does a
#   write, it's possible the second CPU's write could arrive before the
#   first's.
#   
#   This patch adds a mmiowb() call to deal with this sort of situation, and
#   adds some documentation describing I/O ordering issues to
#   deviceiobook.tmpl.  The idea is to mirror the regular, cacheable memory
#   barrier operation, wmb.  Example of the problem this new macro solves:
#   
#   CPU A:  spin_lock_irqsave(&dev_lock, flags)
#   CPU A:  ...
#   CPU A:  writel(newval, ring_ptr);
#   CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
#           ...
#   CPU B:  spin_lock_irqsave(&dev_lock, flags)
#   CPU B:  writel(newval2, ring_ptr);
#   CPU B:  ...
#   CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
#   
#   In this case, newval2 could be written to ring_ptr before newval.  Fixing
#   it is easy though:
#   
#   CPU A:  spin_lock_irqsave(&dev_lock, flags)
#   CPU A:  ...
#   CPU A:  writel(newval, ring_ptr);
#   CPU A:  mmiowb(); /* ensure no other writes beat us to the device */
#   CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
#           ...
#   CPU B:  spin_lock_irqsave(&dev_lock, flags)
#   CPU B:  writel(newval2, ring_ptr);
#   CPU B:  ...
#   CPU B:  mmiowb();
#   CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
#   
#   Note that this doesn't address a related case where the driver may want to
#   actually make a given write get to the device before proceeding.  This
#   should be dealt with by immediately reading a register from the card that
#   has no side effects.  According to the PCI spec, that will guarantee that
#   all writes have arrived before being sent to the target bus.  If no such
#   register is available (in the case of card resets perhaps), reading from
#   config space is sufficient (though it may return all ones if the card isn't
#   responding to read cycles).  I've tried to describe how mmiowb() differs
#   from PCI posted write flushing in the patch to deviceiobook.tmpl.
#   
#   Signed-off-by: Jesse Barnes <jbarnes@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-x86_64/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-v850/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-sparc64/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-sparc/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-sh64/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +5 -0
#   I/O space write barrier
# 
# include/asm-sh/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-s390/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-ppc64/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-ppc/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-parisc/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-mips/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +4 -0
#   I/O space write barrier
# 
# include/asm-m68knommu/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-m68k/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +1 -0
#   I/O space write barrier
# 
# include/asm-m32r/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +5 -0
#   I/O space write barrier
# 
# include/asm-ia64/sn/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +4 -4
#   I/O space write barrier
# 
# include/asm-ia64/machvec_sn2.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-ia64/machvec_init.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +1 -0
#   I/O space write barrier
# 
# include/asm-ia64/machvec.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +7 -0
#   I/O space write barrier
# 
# include/asm-ia64/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +16 -0
#   I/O space write barrier
# 
# include/asm-i386/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-h8300/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-cris/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-arm26/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-arm/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# include/asm-alpha/io.h
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +2 -0
#   I/O space write barrier
# 
# arch/ia64/sn/kernel/iomv.c
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +5 -8
#   I/O space write barrier
# 
# Documentation/DocBook/deviceiobook.tmpl
#   2004/10/25 13:06:49-07:00 jbarnes@engr.sgi.com +67 -4
#   I/O space write barrier
# 
# ChangeSet
#   2004/10/25 18:23:36-07:00 paulkf@microgate.com 
#   [PATCH] serial send_break duration fix
#   
#   Fix tty_io.c send_break() to assert break for proper duration.  If driver
#   break_ctl() changes task state, then break may end prematurely.  USB serial
#   driver break_ctl() sends a URB, changing task state to TASK_RUNNING.
#   
#   Signed-off-by: Paul Fulghum <paulkf@microgate.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/tty_io.c
#   2004/10/25 13:06:49-07:00 paulkf@microgate.com +3 -3
#   serial send_break duration fix
# 
# ChangeSet
#   2004/10/25 18:23:23-07:00 jim.houston@ccur.com 
#   [PATCH] idr_remove safety checking
#   
#   idr_remove() should fail gracefully and warn if the id being removed is not
#   valid.
#   
#   The attached patch should do the job without additional overhead.
#   
#   With the existing code, removing an id which was not allocated could remove
#   a valid id which shares the same lowest layer of the radix tree.
#   
#   I ran a kernel with this patch but have not done any tests to force
#   a failure.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/idr.c
#   2004/10/25 13:06:49-07:00 jim.houston@ccur.com +12 -3
#   idr_remove safety checking
# 
# ChangeSet
#   2004/10/25 18:23:11-07:00 hch@lst.de 
#   [PATCH] use generic_file_open in udf
#   
#   Let's try to reduce the number of hand-crafted LFS checks
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/udf/file.c
#   2004/10/25 13:06:49-07:00 hch@lst.de +1 -21
#   use generic_file_open in udf
# 
# ChangeSet
#   2004/10/25 18:22:59-07:00 nickpiggin@yahoo.com.au 
#   [PATCH] vm: unreclaimable pages debugginf
#   
#   Add zone->all_unreclaiable to the sysrq-M and omm-killing diagnostic output.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/page_alloc.c
#   2004/10/25 13:06:48-07:00 nickpiggin@yahoo.com.au +5 -1
#   vm: unreclaimable pages debugginf
# 
# ChangeSet
#   2004/10/25 18:22:46-07:00 clameter@sgi.com 
#   [PATCH] Posix layer <-> clock driver API fix
#   
#   This is needed for an mmtimer driver update that we are currently working
#   on.  The mmtimer driver provides CLOCK_SGI_CYCLE via clock_gettime and
#   clock_settime.
#   
#   With this api fix one will be able to use timer_create, timer_settime and
#   friends from userspace to schedule and receive signals via timer interrupts
#   of mmtimer.
#   
#   Changelog
#   	* Clean up timer api for drivers that use register_posix_clock. Drivers
#   	  will then be able to use posix timers to schedule interrupts.
#   	* Change API for posix_clocks[].timer_create to only pass one pointer
#   	  to a k_itimer structure that is now allocated and managed by the
#   	  posix layer in the same way as for the other posix timer
#   	  functions.
#   	* Isolate a posix_timer_event(timr) function in posix-timers.c that may
#   	  be called by the interrupt routine of a timer to signal that the
#   	  scheduled event has taken place.
#   
#   Signed-off-by: Christoph Lameter <clameter@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/posix-timers.c
#   2004/10/25 13:06:48-07:00 clameter@sgi.com +34 -55
#   Posix layer <-> clock driver API fix
# 
# include/linux/posix-timers.h
#   2004/10/25 13:06:48-07:00 clameter@sgi.com +5 -6
#   Posix layer <-> clock driver API fix
# 
# ChangeSet
#   2004/10/25 18:22:34-07:00 zippel@linux-m68k.org 
#   [PATCH] hfs: export type/creator via xattr
#   
#   This exports the hfs type/creator info via xattr.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hfs/attr.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +121 -0
#   hfs: export type/creator via xattr
# 
# fs/hfsplus/ioctl.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +106 -0
#   hfs: export type/creator via xattr
# 
# fs/hfsplus/inode.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +3 -0
#   hfs: export type/creator via xattr
# 
# fs/hfsplus/hfsplus_fs.h
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +5 -0
#   hfs: export type/creator via xattr
# 
# fs/hfs/inode.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +3 -0
#   hfs: export type/creator via xattr
# 
# fs/hfs/hfs_fs.h
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +7 -0
#   hfs: export type/creator via xattr
# 
# fs/hfs/attr.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/fs/hfs/attr.c
# 
# fs/hfs/Makefile
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +1 -1
#   hfs: export type/creator via xattr
# 
# ChangeSet
#   2004/10/25 18:22:21-07:00 zippel@linux-m68k.org 
#   [PATCH] hfs: write back resource info directly
#   
#   Write back the information for a dirty resource inode directly and not via the
#   main inode, as at the time the latter is written the former might already be
#   gone.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hfsplus/inode.c
#   2004/10/25 13:18:30-07:00 zippel@linux-m68k.org +14 -10
#   hfs: write back resource info directly
# 
# fs/hfs/inode.c
#   2004/10/25 13:18:30-07:00 zippel@linux-m68k.org +14 -11
#   hfs: write back resource info directly
# 
# ChangeSet
#   2004/10/25 18:22:09-07:00 zippel@linux-m68k.org 
#   [PATCH] hfs: read correct dir time
#   
#   Fix a small typo and read the correct time for a dir.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hfs/inode.c
#   2004/10/25 13:18:30-07:00 zippel@linux-m68k.org +1 -1
#   hfs: read correct dir time
# 
# ChangeSet
#   2004/10/25 18:21:55-07:00 zippel@linux-m68k.org 
#   [PATCH] hfs: manage correct block count
#   
#   Manage the fs block count with a separate variable and keep a correct i_blocks
#   for e.g.  correct du output.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hfsplus/inode.c
#   2004/10/25 13:18:30-07:00 zippel@linux-m68k.org +6 -3
#   hfs: manage correct block count
# 
# fs/hfsplus/hfsplus_fs.h
#   2004/10/25 13:18:30-07:00 zippel@linux-m68k.org +1 -0
#   hfs: manage correct block count
# 
# fs/hfsplus/extents.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +6 -4
#   hfs: manage correct block count
# 
# fs/hfsplus/btree.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +5 -3
#   hfs: manage correct block count
# 
# fs/hfs/inode.c
#   2004/10/25 13:18:30-07:00 zippel@linux-m68k.org +6 -3
#   hfs: manage correct block count
# 
# fs/hfs/hfs_fs.h
#   2004/10/25 13:18:30-07:00 zippel@linux-m68k.org +1 -0
#   hfs: manage correct block count
# 
# fs/hfs/extent.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +6 -4
#   hfs: manage correct block count
# 
# fs/hfs/btree.c
#   2004/10/25 13:06:48-07:00 zippel@linux-m68k.org +5 -3
#   hfs: manage correct block count
# 
# ChangeSet
#   2004/10/25 18:21:43-07:00 zippel@linux-m68k.org 
#   [PATCH] hfs: relax dirty check
#   
#   hfs has two dirty bits, but currently OS X uses only one of them, so match its
#   behaviour, so that a uncleanly unmounted disk can be mounted r/w again, after
#   it has been checked.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hfsplus/super.c
#   2004/10/25 13:06:47-07:00 zippel@linux-m68k.org +2 -4
#   hfs: relax dirty check
# 
# fs/hfs/super.c
#   2004/10/25 13:06:47-07:00 zippel@linux-m68k.org +1 -2
#   hfs: relax dirty check
# 
# fs/hfs/mdb.c
#   2004/10/25 13:06:47-07:00 zippel@linux-m68k.org +4 -4
#   hfs: relax dirty check
# 
# ChangeSet
#   2004/10/25 18:21:31-07:00 zippel@linux-m68k.org 
#   [PATCH] hfs: update key after rename
#   
#   After a file has been renamed, the cached search key must be updated.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hfs/dir.c
#   2004/10/25 13:06:47-07:00 zippel@linux-m68k.org +3 -0
#   hfs: update key after rename
# 
# ChangeSet
#   2004/10/25 18:21:18-07:00 jbarnes@engr.sgi.com 
#   [PATCH] mmtimer sparse fixes
#   
#   Small patch to add __iomem annotations to mmtimer.c.
#   
#   Signed-off-by: Jesse Barnes <jbarnes@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/mmtimer.c
#   2004/10/25 13:06:47-07:00 jbarnes@engr.sgi.com +5 -5
#   mmtimer sparse fixes
# 
# ChangeSet
#   2004/10/25 18:21:06-07:00 suresh.b.siddha@intel.com 
#   [PATCH] intel irqbalance quirk cleanup
#   
#   - Remove the call to quirk_intel_irqbalance() from quirk_pciehp_msi().
#   
#   - Move the x86(/x86_64)-specific quirk_intel_irqbalance() into x86 quirks.c
#     due to its dependency on <linux/irq.h>
#   
#   - Mark it __init rather than __devinit, since it calls __init functions.
#   
#   Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/quirks.c
#   2004/10/25 13:06:47-07:00 suresh.b.siddha@intel.com +49 -0
#   intel irqbalance quirk cleanup
# 
# drivers/pci/quirks.c
#   2004/10/25 13:06:47-07:00 suresh.b.siddha@intel.com +0 -47
#   intel irqbalance quirk cleanup
# 
# arch/x86_64/kernel/Makefile
#   2004/10/25 13:06:47-07:00 suresh.b.siddha@intel.com +2 -1
#   intel irqbalance quirk cleanup
# 
# arch/i386/kernel/quirks.c
#   2004/10/25 13:06:47-07:00 suresh.b.siddha@intel.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/i386/kernel/quirks.c
# 
# arch/i386/kernel/Makefile
#   2004/10/25 13:06:47-07:00 suresh.b.siddha@intel.com +1 -1
#   intel irqbalance quirk cleanup
# 
# ChangeSet
#   2004/10/25 18:20:53-07:00 sds@epoch.ncsc.mil 
#   [PATCH] Add DAC check for setxattr(security.selinux)
#   
#   This patch against 2.6.9 adds a DAC ownership check to the existing MAC
#   permission checks when setting the security.selinux attribute via setxattr.
#   In the past, the MAC permission checks were viewed as sufficient for
#   controlling relabeling operations, but experience in the Fedora SELinux
#   integration has shown that a DAC check is also appropriate here,
#   particularly under targeted policy.
#   
#   Signed-off-by: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/hooks.c
#   2004/10/25 13:06:47-07:00 sds@epoch.ncsc.mil +3 -0
#   Add DAC check for setxattr(security.selinux)
# 
# ChangeSet
#   2004/10/25 21:20:44-04:00 akpm@osdl.org 
#   [PATCH] e1000 module_param build fix
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2004/10/25 18:20:41-07:00 rddunlap@osdl.org 
#   [PATCH] __init dependencies: ignore __param
#   
#   Ignore __param section references; they aren't discarded.
#   
#   Error: ./drivers/mtd/devices/phram.o __param refers to 0000000000000010 R_X86_64_64       .init.text+0x0000000000000013
#   Error: ./drivers/scsi/dc395x.o __param refers to 0000000000000020 R_X86_64_64       .init.data+0x0000000000000064
#   Error: ./drivers/usb/gadget/ether.o __param refers to 0000000000000048 R_X86_64_64       .init.data+0x0000000000000020
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/e1000/e1000_param.c
#   2004/10/24 05:47:51-04:00 akpm@osdl.org +1 -1
#   e1000-module_param-fix
# 
# scripts/reference_init.pl
#   2004/10/25 13:06:47-07:00 rddunlap@osdl.org +1 -0
#   __init dependencies: ignore __param
# 
# ChangeSet
#   2004/10/25 18:20:28-07:00 axboe@suse.de 
#   [PATCH] fix bad segment coalescing in blk_recalc_rq_segments()
#   
#   blk_recalc_rq_segments forgots to take ->max_segment_size into account and
#   gladly merges segments bigger than we can support, thus underestimating the
#   number of segments needed to fill it.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/ll_rw_blk.c
#   2004/10/25 13:06:47-07:00 axboe@suse.de +19 -5
#   fix bad segment coalescing in blk_recalc_rq_segments()
# 
# ChangeSet
#   2004/10/25 18:20:16-07:00 rusty@rustcorp.com.au 
#   [PATCH] Eliminate init_module and cleanup_module from Documentation
#   
#   In 2.2, you used to just be able to call functions "init_module" and
#   "cleanup_module" and they'd be magically called.
#   
#   These days you should use module_init(myinit)/module_exit(myexit) and avoid
#   #ifdef MODULE.
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/sound/oss/README.modules
#   2004/10/25 13:06:47-07:00 rusty@rustcorp.com.au +3 -2
#   Eliminate init_module and cleanup_module from Documentation
# 
# Documentation/s390/s390dbf.txt
#   2004/10/25 13:06:47-07:00 rusty@rustcorp.com.au +12 -6
#   Eliminate init_module and cleanup_module from Documentation
# 
# Documentation/i2c/writing-clients
#   2004/10/25 13:06:47-07:00 rusty@rustcorp.com.au +7 -21
#   Eliminate init_module and cleanup_module from Documentation
# 
# Documentation/DocBook/videobook.tmpl
#   2004/10/25 13:06:47-07:00 rusty@rustcorp.com.au +8 -6
#   Eliminate init_module and cleanup_module from Documentation
# 
# Documentation/DocBook/mousedrivers.tmpl
#   2004/10/25 13:06:47-07:00 rusty@rustcorp.com.au +8 -13
#   Eliminate init_module and cleanup_module from Documentation
# 
# ChangeSet
#   2004/10/25 18:20:03-07:00 rusty@rustcorp.com.au 
#   [PATCH] boot parameters: quoting of environment variables revisited
#   
#   As noticed by Joey Hess (and thanks for Christoph for forwarding it).  Also
#   requirements from Werner Almesberger.
#   
#   If someone passes 'foo="some value"' the param engine removes the quotes
#   and hands 'foo' and 'some value'.  The __setup() parameters expect a single
#   string, and so we try to regenerate it from the two parts.  Finally, we try
#   to place it as an environment variable.
#   
#   Werner wants quotes stripped out of the environment variable.  It makes
#   sense to do that for __setup, too (so it sees 'foo=some value'), since
#   __setup functions don't usually handle quotes.
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# init/main.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +9 -2
#   boot parameters: quoting of environment variables revisited
# 
# ChangeSet
#   2004/10/25 18:19:51-07:00 rusty@rustcorp.com.au 
#   [PATCH] Builtin Module Parameters in sysfs too
#   
#   Currently, only module parameters in loaded modules are exported in
#   /sys/modules/, while those of "modules" built into the kernel can be set by
#   the kernel command line, but not read or set via sysfs.
#   
#   - move module parameters from /sys/modules/$(module_name)/$(parameter_name) to
#     /sys/modules/$(module_name)/parameters/$(parameter_name)
#   
#   - remove dummy kernel_param for exporting refcnt, add "struct module *"-based
#     attribute instead
#   
#   - also export module paramters for "modules" which are built into the kernel,
#     so parameters are always accessible at
#     /sys/modules/$(KBUILD_MODNAME)/$(parameter_name)
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (modified)
#   Signed-off-by: Dominik Brodowski <linux@brodo.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/params.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +391 -0
#   Builtin Module Parameters in sysfs too
# 
# kernel/module.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +29 -105
#   Builtin Module Parameters in sysfs too
# 
# include/linux/moduleparam.h
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +11 -0
#   Builtin Module Parameters in sysfs too
# 
# include/linux/module.h
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +18 -20
#   Builtin Module Parameters in sysfs too
# 
# ChangeSet
#   2004/10/25 18:19:39-07:00 rusty@rustcorp.com.au 
#   [PATCH] Fix for MODULE_PARM obsolete
#   
#   There is no __attribute_unused__: use __attribute__((__unused__)).
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/module.h
#   2004/10/25 13:18:33-07:00 rusty@rustcorp.com.au +2 -2
#   Fix for MODULE_PARM obsolete
# 
# ChangeSet
#   2004/10/25 18:19:27-07:00 rusty@rustcorp.com.au 
#   [PATCH] Remove MODULE_PARM from arch/i386
#   
#   This patch removes MODULE_PARM for everything under arch/i386.  Currently
#   only APM.
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/apm.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +9 -9
#   Remove MODULE_PARM from arch/i386
# 
# ChangeSet
#   2004/10/25 18:19:14-07:00 rusty@rustcorp.com.au 
#   [PATCH] Remove MODULE_PARM from i386 defconfig.
#   
#   This cleans up defconfig for i386.  Not much work.  This patch removes
#   MODULE_PARM for everything made by "defconfig" on x86.  There are only a
#   few left.
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/s2io.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +8 -8
#   Remove MODULE_PARM from i386 defconfig.
# 
# drivers/net/8139too.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +4 -4
#   Remove MODULE_PARM from i386 defconfig.
# 
# drivers/ide/ide-cd.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +1 -1
#   Remove MODULE_PARM from i386 defconfig.
# 
# drivers/char/lp.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +2 -2
#   Remove MODULE_PARM from i386 defconfig.
# 
# drivers/cdrom/cdrom.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +6 -6
#   Remove MODULE_PARM from i386 defconfig.
# 
# drivers/acpi/thermal.c
#   2004/10/25 13:06:46-07:00 rusty@rustcorp.com.au +1 -1
#   Remove MODULE_PARM from i386 defconfig.
# 
# ChangeSet
#   2004/10/25 18:19:02-07:00 rusty@rustcorp.com.au 
#   [PATCH] MODULE_PARM must die: make it warn first.
#   
#   This patch adds a warning whenever MODULE_PARM is used.  Successive
#   patches change them over to module_param.  Help appreciated!
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/module.h
#   2004/10/25 13:18:33-07:00 rusty@rustcorp.com.au +4 -2
#   MODULE_PARM must die: make it warn first.
# 
# ChangeSet
#   2004/10/25 18:18:49-07:00 roland@redhat.com 
#   [PATCH] session leader tty disassociation fix
#   
#   The session leader should disassociate from its controlling terminal and
#   send SIGHUP signals only when the whole session leader process dies. 
#   Currently, this gets done when any thread in that process dies, which is
#   wrong.  This patch fixes it.  
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/exit.c
#   2004/10/25 13:06:46-07:00 roland@redhat.com +4 -2
#   session leader tty disassociation fix
# 
# ChangeSet
#   2004/10/25 18:18:37-07:00 roland@redhat.com 
#   [PATCH] acct: report single record for multithreaded process
#   
#   This patch changes process accounting to write just one record for a
#   process with many NPTL threads, rather than one record for each thread.  No
#   record is written until the last thread exits.  The process's record shows
#   the cumulative time of all the threads that ever lived in that process
#   (thread group).  This seems like the clearly right thing and I assume it is
#   what anyone using process accounting really would like to see.
#   
#   There is a race condition between multiple threads exiting at the same time
#   to decide which one should write the accounting record.  I couldn't think
#   of anything clever using existing bookkeeping that would get this right, so
#   I added another counter for this.  (There may be some potential to clean up
#   existing places that figure out how many non-zombie threads are in the
#   group, now that this count is available.)
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/fork.c
#   2004/10/25 13:06:45-07:00 roland@redhat.com +2 -0
#   acct: report single record for multithreaded process
# 
# kernel/exit.c
#   2004/10/25 13:18:33-07:00 roland@redhat.com +2 -1
#   acct: report single record for multithreaded process
# 
# kernel/acct.c
#   2004/10/25 13:06:45-07:00 roland@redhat.com +12 -6
#   acct: report single record for multithreaded process
# 
# include/linux/sched.h
#   2004/10/25 13:06:45-07:00 roland@redhat.com +1 -0
#   acct: report single record for multithreaded process
# 
# ChangeSet
#   2004/10/25 18:18:25-07:00 jim.hague@acm.org 
#   [PATCH] pm2fb: Colour palette fixes
#   
#   - Hardware CLUT only needs setting on pseudocolor.
#   - Pseudo palette values need to be 32bit wide for cfb_*().
#   
#   Signed-off-by: Jim Hague <jim.hague@acm.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/pm2fb.c
#   2004/10/25 13:06:45-07:00 jim.hague@acm.org +3 -6
#   pm2fb: Colour palette fixes
# 
# ChangeSet
#   2004/10/25 18:18:13-07:00 jim.hague@acm.org 
#   [PATCH] pm2fb: Blanking fixes
#   
#   - Current blanking code forces +ve (h|v)sync. Correct, match 2.4
#     behaviour, and introduce VESA constants for clarity.
#   
#   Signed-off-by: Jim Hague <jim.hague@acm.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/pm2fb.c
#   2004/10/25 13:18:34-07:00 jim.hague@acm.org +14 -12
#   pm2fb: Blanking fixes
# 
# ChangeSet
#   2004/10/25 18:18:00-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: S3 Savage Framebuffer Driver
#   
#   S3 Savage Frambuffer Driver for the following chipsets:
#   
#   Savage 3D
#   Savage MX
#   Savage 4
#   Savage 2000
#   ProSavage
#   SuperSavage
#   
#   This is based from the driver written by:
#    Denis Oliver Kropp <dok@directfb.org>
#    Sven Neumann <neo@directfb.org>
#   
#   Initial Porting to 2.6 done by:
#    Mika Pruikkonen <mpruikko@cc.hut.fi>
#   
#   Added the following:
#   - Console acceleration support (imageblit, fillrect, copyarea) -
#     Configurable
#   - DDC2/I2C support for (ProSavage DDR-K, Savage 4 and Prosavage PM only -
#     Configurable
#   - 8, 16, 32 bits per pixel
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/savage/savagefb_accel.c
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +135 -0
#   fbdev: S3 Savage Framebuffer Driver
# 
# drivers/video/savage/savagefb.h
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +354 -0
#   fbdev: S3 Savage Framebuffer Driver
# 
# drivers/video/savage/savagefb.c
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +2281 -0
#   fbdev: S3 Savage Framebuffer Driver
# 
# drivers/video/savage/savagefb-i2c.c
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +257 -0
#   fbdev: S3 Savage Framebuffer Driver
# 
# drivers/video/savage/Makefile
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +8 -0
#   fbdev: S3 Savage Framebuffer Driver
# 
# include/linux/fb.h
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +15 -0
#   fbdev: S3 Savage Framebuffer Driver
# 
# drivers/video/savage/savagefb_accel.c
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/savage/savagefb_accel.c
# 
# drivers/video/savage/savagefb.h
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/savage/savagefb.h
# 
# drivers/video/savage/savagefb.c
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/savage/savagefb.c
# 
# drivers/video/savage/savagefb-i2c.c
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/savage/savagefb-i2c.c
# 
# drivers/video/savage/Makefile
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/savage/Makefile
# 
# drivers/video/Makefile
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +2 -1
#   fbdev: S3 Savage Framebuffer Driver
# 
# drivers/video/Kconfig
#   2004/10/25 13:06:41-07:00 adaplas@hotpop.com +36 -0
#   fbdev: S3 Savage Framebuffer Driver
# 
# ChangeSet
#   2004/10/25 18:17:47-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
#   
#     Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G integrated
#     graphics chips.
#     Port from kernel 2.4 + some modifications and cleanup :
#          - Fix HW accel on 845G
#          - Use of agpgart for fb memory reservation
#          - Add mtrr support
#   
#   Signed-off-by: Sylvain Meyer <sylvain.meyer@worldonline.fr>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/intelfb/intelfbhw.h
#   2004/10/25 12:56:30-07:00 adaplas@hotpop.com +565 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/intelfb/intelfbhw.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +1749 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/intelfb/intelfbdrv.h
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +77 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/intelfb/intelfbdrv.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +1625 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/intelfb/intelfb.h
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +294 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/intelfb/builtinmodes.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +222 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/intelfb/Makefile
#   2004/10/25 12:56:30-07:00 adaplas@hotpop.com +8 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# include/linux/fb.h
#   2004/10/25 13:18:34-07:00 adaplas@hotpop.com +1 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/intelfb/intelfbhw.h
#   2004/10/25 12:56:30-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/intelfb/intelfbhw.h
# 
# drivers/video/intelfb/intelfbhw.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/intelfb/intelfbhw.c
# 
# drivers/video/intelfb/intelfbdrv.h
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/intelfb/intelfbdrv.h
# 
# drivers/video/intelfb/intelfbdrv.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/intelfb/intelfbdrv.c
# 
# drivers/video/intelfb/intelfb.h
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/intelfb/intelfb.h
# 
# drivers/video/intelfb/builtinmodes.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/intelfb/builtinmodes.c
# 
# drivers/video/intelfb/Makefile
#   2004/10/25 12:56:30-07:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/intelfb/Makefile
# 
# drivers/video/Makefile
#   2004/10/25 13:18:34-07:00 adaplas@hotpop.com +3 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/video/Kconfig
#   2004/10/25 13:18:34-07:00 adaplas@hotpop.com +21 -0
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# drivers/Makefile
#   2004/10/25 12:56:30-07:00 adaplas@hotpop.com +2 -1
#   fbdev: Intel 830M/845G/852GM/855GM/865G framebuffer driver port
# 
# ChangeSet
#   2004/10/25 18:17:34-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Cleanup rivafb cursor implementation
#   
#   remove/modify all references to info->cursor
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/riva/rivafb.h
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +1 -0
#   fbdev: Cleanup rivafb cursor implementation
# 
# drivers/video/riva/fbdev.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +26 -29
#   fbdev: Cleanup rivafb cursor implementation
# 
# ChangeSet
#   2004/10/25 18:17:22-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Clean up i810fb cursor implementation
#   
#   remove/modify all references to info->cursor
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/i810/i810_main.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +14 -26
#   fbdev: Clean up i810fb cursor implementation
# 
# ChangeSet
#   2004/10/25 18:17:10-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Clean up softcursor implementation
#   
#   - use struct fb_pixmap pixmap instead of struct fb_pixmap sprite.  The
#     softcursor uses fb_imageblit which also uses pixmap.
#   
#   - remove/change all references to info->cursor
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/softcursor.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +23 -49
#   fbdev: Clean up softcursor implementation
# 
# ChangeSet
#   2004/10/25 18:16:57-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Clean up of fbcon/fbdev cursor interface
#   
#   The current cursor interface is confusing.  Some fields are taken from the
#   cursor structure in struct fb_info (enable, mask, rop fields) and the rest are
#   taken from the passed cursor structure.  These lead to a lot of confusion,
#   making it hard for developers to write their own implementation.
#   
#   Also, the cursor code has several 'short-circuits', occassionally leading to
#   undefined cursor behavior.
#   
#   These are the changes brought about by the patch:
#   
#   - Removed struct fb_cursor and related fields from struct fb_info, and
#     instead, placed them in a struct not visible to fbdev.
#   
#   - The struct fb_cursor passed to fb_cursor() will _always_ contain valid
#     data with various bitflags indicating which fields have changed
#   
#   - The struct fb_pixmap sprite in struct fb_info is used only by drivers with
#     hardware cursor implementation.  Initializing and allocating memory for this
#     structure is not needed.  Remove initialization and memory allocation.
#   
#   - The FBIO_CURSOR ioctl is broken (because fb_cursor() is broken).  For now,
#     remove fb_cursor code and make the FBIO_CURSOR ioctl always return -ENODEV.
#   
#   - The flag FB_CUR_SETCUR is changed to FB_CUR_SETIMAGE, indicating that the
#     cursor sprite has changed.  The image change is now checked by fbcon so
#     drivers will not unnecessarily load the sprite image everytime.  This causes
#     hardware cursors to flicker, especially in rivafb.
#   
#   - Remove fb_load_cursor_image().  This is unused, and should not be
#     implemented generically.
#   
#   - Documented the usage of the cursor interface in skeletonfb.c
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fb.h
#   2004/10/25 13:18:34-07:00 adaplas@hotpop.com +1 -6
#   fbdev: Clean up of fbcon/fbdev cursor interface
# 
# drivers/video/skeletonfb.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +33 -11
#   fbdev: Clean up of fbcon/fbdev cursor interface
# 
# drivers/video/fbmem.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +1 -129
#   fbdev: Clean up of fbcon/fbdev cursor interface
# 
# drivers/video/console/fbcon.h
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +4 -0
#   fbdev: Clean up of fbcon/fbdev cursor interface
# 
# drivers/video/console/fbcon.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +14 -6
#   fbdev: Clean up of fbcon/fbdev cursor interface
# 
# drivers/video/console/bitblit.c
#   2004/10/25 12:56:29-07:00 adaplas@hotpop.com +101 -85
#   fbdev: Clean up of fbcon/fbdev cursor interface
# 
# ChangeSet
#   2004/10/25 18:16:44-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Various mach64 changes
#   
#     Alexander Kern <alex.kern@gmx.de>
#     [PATCH] port Daniel Mantione 2.4 driver to 2.6
#     [PATCH] add more pci_id number
#     [PATCH] add accelerated imgblit
#     [PATCH] revert SDRAM_MAGIC_PLL to old behaviour
#     [PATCH] do a "from BIOS" initialisation only by __i386__
#   
#     Arnaud FONTAINE <arnaud.fontaine@free.fr>
#     [PATCH atyfb] correction for 3D Rage Mobility L
#   
#     Geert Uytterhoeven <geert@linux-m68k.org>
#     [PATCH atyfb] Atari Atyfb fixes
#     [PATCH atyfb] Atyfb on Mach64 GX or Atari
#     [PATCH 468] m68k sparse floating point
#   
#     James Simmons <jsimmons@infradead.org>
#     [PATCH add] port to framebuffer_alloc api
#   
#     Nicolas Souchu <nsouch@free.fr>
#     [PATCH] I do not found a copy, but it was incorporated too
#   
#     Ville Syrjälä <syrjala@sci.fi>
#     [PATCH] fix pan with doublescan
#     [PATCH] another double scan fix
#     [PATCH] disable linear aperture register access
#     [PATCH] Memory type correction
#     [PATCH] atyfb (2.6): Fix mmio_start
#     [PATCH] atyfb (2.6): Fix mem_refresh_rate for Mobility
#     [PATCH] atyfb (2.6): Add RGB565 support
#     [PATCH] atyfb: Blank LCD by turning off backlight voltage
#     [PATCH] atyfb: Rage LT LCD register access
#     [PATCH] atyfb: vblank irq support
#     [PATCH] atyfb: MTRR support
#   
#   
#   Antonino Daplas <adaplas@pol.net>
#      remove/modify all references to info->cursor
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/video/mach64.h
#   2004/10/25 12:50:25-07:00 adaplas@hotpop.com +285 -66
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/xlinit.c
#   2004/10/25 12:50:25-07:00 adaplas@hotpop.com +34 -34
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/mach64_gx.c
#   2004/10/25 12:50:25-07:00 adaplas@hotpop.com +10 -10
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/mach64_cursor.c
#   2004/10/25 12:50:25-07:00 adaplas@hotpop.com +139 -158
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/mach64_ct.c
#   2004/10/25 12:50:25-07:00 adaplas@hotpop.com +535 -198
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/mach64_accel.c
#   2004/10/25 12:50:25-07:00 adaplas@hotpop.com +192 -20
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/atyfb_base.c
#   2004/10/25 12:59:19-07:00 adaplas@hotpop.com +2320 -1265
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/atyfb.h
#   2004/10/25 12:50:25-07:00 adaplas@hotpop.com +143 -62
#   fbdev: Various mach64 changes
# 
# drivers/video/aty/ati_ids.h
#   2004/10/25 12:50:24-07:00 adaplas@hotpop.com +1 -0
#   fbdev: Various mach64 changes
# 
# drivers/video/Kconfig
#   2004/10/25 13:18:34-07:00 adaplas@hotpop.com +13 -6
#   fbdev: Various mach64 changes
# 
# ChangeSet
#   2004/10/25 18:16:32-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Remove inter_module_get/put from i810fb
#   
#   The function inter_module_get/put is to be deprecated. Remove.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/i810/i810_main.c
#   2004/10/25 13:18:35-07:00 adaplas@hotpop.com +24 -33
#   fbdev: Remove inter_module_get/put from i810fb
# 
# drivers/video/i810/i810.h
#   2004/10/25 12:47:57-07:00 adaplas@hotpop.com +0 -1
#   fbdev: Remove inter_module_get/put from i810fb
# 
# ChangeSet
#   2004/10/25 18:16:19-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Reduce pixmap memory allocation size
#   
#   - Reduce pixmap size allocated by fbmem, i810fb and rivafb from 16-64K to
#     8K.  This size is sufficient that a single putcs call can be accomodated by
#     a single imageblit
#   
#   - Replace NR_FB_DRIVERS with FB_MAX
#   
#   - Trivial code, Kconfig and Documentation cleanup
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/riva/fbdev.c
#   2004/10/25 13:18:35-07:00 adaplas@hotpop.com +3 -3
#   fbdev: Reduce pixmap memory allocation size
# 
# drivers/video/i810/i810_main.c
#   2004/10/25 13:18:36-07:00 adaplas@hotpop.com +3 -3
#   fbdev: Reduce pixmap memory allocation size
# 
# drivers/video/fbmem.c
#   2004/10/25 13:18:35-07:00 adaplas@hotpop.com +4 -5
#   fbdev: Reduce pixmap memory allocation size
# 
# drivers/video/console/fbcon.c
#   2004/10/25 13:18:35-07:00 adaplas@hotpop.com +6 -6
#   fbdev: Reduce pixmap memory allocation size
# 
# drivers/video/Kconfig
#   2004/10/25 13:18:35-07:00 adaplas@hotpop.com +3 -3
#   fbdev: Reduce pixmap memory allocation size
# 
# ChangeSet
#   2004/10/25 18:16:06-07:00 werner@almesberger.net 
#   [PATCH] update CREDITS entry of Werner Almesberger
#   
#   This patch updates my entry.  (Long overdue ...)
#   
#   Signed-off-by: Werner Almesberger <werner@almesberger.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# CREDITS
#   2004/10/25 13:18:28-07:00 werner@almesberger.net +4 -6
#   update CREDITS entry of Werner Almesberger
# 
# ChangeSet
#   2004/10/25 18:15:53-07:00 agk@redhat.com 
#   [PATCH] device-mapper trivial: duplicate kfree in error path
#   
#   Remove duplicate kfree in dm_register_target error path.
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-target.c
#   2004/10/25 12:47:57-07:00 agk@redhat.com +2 -3
#   device-mapper trivial: duplicate kfree in error path
# 
# ChangeSet
#   2004/10/25 18:15:41-07:00 agk@redhat.com 
#   [PATCH] device-mapper trivial: stray semi-colon
#   
#   Remove stray semicolon.
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   From: Lars Marowsky-Bree <lmb@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm.c
#   2004/10/25 12:47:57-07:00 agk@redhat.com +1 -1
#   device-mapper trivial: stray semi-colon
# 
# ChangeSet
#   2004/10/25 18:15:29-07:00 agk@redhat.com 
#   [PATCH] device-mapper: dm-crypt: new IV mode ESSIV
#   
#   This patch adds a new IV mode ''encrypted sector|salt IV'' described in
#     http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/472
#   
#   To use ESSIV, set the ivmode (using the new syntax) to "essiv:<hash>".
#   "hash" should be a valid cryptoapi hash.
#   
#   This, for example, is a valid dm-target line:
#   
#   0 200 crypt aes-cbc-essiv:sha256 00000000000000000000000000000000 0 /dev/loop/5 0
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-Off-By: Christophe Saout <christophe@saout.de>
#   Signed-Off-By: Fruhwirth Clemens <clemens@endorphin.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-crypt.c
#   2004/10/25 12:47:56-07:00 agk@redhat.com +111 -3
#   device-mapper: dm-crypt: new IV mode ESSIV
# 
# ChangeSet
#   2004/10/25 18:15:17-07:00 agk@redhat.com 
#   [PATCH] device-mapper: dm-crypt generator extension
#   
#   Create crypt_iv_operations structure with generator method and move the
#   plain iv generator into this structure.  Optionally accept an extended
#   <sector format> syntax: <cipher>-<chaining mode>-<iv mode>
#   
#   This also makes it ready to support chaining modes other than CBC 
#   mode, such as CMC (not implemented in cryptoapi yet), 
#   The problems outlined by Adam J. Richter in
#     http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
#   would be fixed by switching to CMC chaining mode.
#   
#   Example of a valid target line:
#     0 200 crypt aes-cbc-plain 00000000000000000000000000000000 0 /dev/loop/5 0
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-Off-By: Christophe Saout <christophe@saout.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-crypt.c
#   2004/10/25 13:18:37-07:00 agk@redhat.com +112 -37
#   device-mapper: dm-crypt generator extension
# 
# ChangeSet
#   2004/10/25 18:15:05-07:00 agk@redhat.com 
#   [PATCH] device-mapper: dm-crypt tidy-ups
#   
#   Small dm-crypt tidy-ups:
#   - Use unsigned consistently
#   - Simplify crypt_iv_plain memset
#   - Use DMEMIT macro
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-Off-By: Christophe Saout <christophe@saout.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-crypt.c
#   2004/10/25 13:18:37-07:00 agk@redhat.com +31 -34
#   device-mapper: dm-crypt tidy-ups
# 
# ChangeSet
#   2004/10/25 18:14:52-07:00 alex.kiernan@gmail.com 
#   [PATCH] UFS: solaris compatibility fix
#   
#   Fix handling of device inodes on Solaris x86 filesystems, add support for
#   large dev_t against Solaris UFS filesystems.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ufs/util.h
#   2004/10/25 12:47:56-07:00 alex.kiernan@gmail.com +2 -0
#   UFS: solaris compatibility fix
# 
# fs/ufs/util.c
#   2004/10/25 12:47:56-07:00 alex.kiernan@gmail.com +53 -0
#   UFS: solaris compatibility fix
# 
# fs/ufs/namei.c
#   2004/10/25 12:47:56-07:00 alex.kiernan@gmail.com +2 -2
#   UFS: solaris compatibility fix
# 
# fs/ufs/inode.c
#   2004/10/25 12:47:56-07:00 alex.kiernan@gmail.com +2 -2
#   UFS: solaris compatibility fix
# 
# ChangeSet
#   2004/10/25 18:14:40-07:00 marcelo.tosatti@cyclades.com 
#   [PATCH] Change pagevec counters back to unsigned long and cacheline align
#   
#   Change pagevec "nr" and "cold" back to "unsigned long", because <4 byte
#   accesses can be slow on architectures < Pentium III (additional "data16"
#   operand on instruction).
#   
#   This still honours the cacheline alignment, making the size of "pagevec"
#   structure a power of two (either 64 or 128 bytes).
#   
#   Haven't been able to see any significant change on performance on my
#   limited testing.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/pagevec.h
#   2004/10/25 12:47:56-07:00 marcelo.tosatti@cyclades.com +4 -3
#   Change pagevec counters back to unsigned long and cacheline align
# 
# ChangeSet
#   2004/10/25 18:14:27-07:00 Peter_Pregler@email.com 
#   [PATCH] cpia.c rmmod deadlock fix
#   
#   Newer versions of module-init-tools do some locking now which leads to a
#   dead-lock if cpia.c does a request_module("cpia_usb/pp").  The attached
#   patch against 2.6.8 removes the request_module.  The problem is actually
#   the same as is documented in debian bug #259056 which was caused by alsa
#   autoloading some oss-modules.  So I guess there might be more places in the
#   kernel where this new locking in the module-init-tools might lead to
#   dead-locks.
#   
#   Signed-off-by: Peter Pregler <Peter_Pregler@email.com>
#   Acked-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/cpia.c
#   2004/10/25 12:47:55-07:00 Peter_Pregler@email.com +1 -10
#   cpia.c rmmod deadlock fix
# 
# ChangeSet
#   2004/10/25 18:14:15-07:00 vandrove@vc.cvut.cz 
#   [PATCH] Weak symbols in modules and versioned symbols
#   
#   Weak symbol may be unavailable in kernel, but if it is available, its
#   signature should be same as was at the build time.  If we do not attach
#   signatures to weak symbols, kernel is tainted when such module is loaded.
#   
#   vmmon: no version for "sys_ioctl" found: kernel tainted.
#   
#   I also believe that it is safer to add & check signatures here - module
#   wants either sys_ioctl with right signature, or no sys_ioctl at all, not
#   sys_ioctl with different signature (which signals that there is some
#   misbuild occuring).
#   
#   Signed-off-by: Petr Vandrovec <vandrove@vc.cvut.cz>
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (forwarded)
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/mod/modpost.c
#   2004/10/25 12:47:56-07:00 vandrove@vc.cvut.cz +9 -5
#   Weak symbols in modules and versioned symbols
# 
# ChangeSet
#   2004/10/25 18:14:02-07:00 jmorris@redhat.com 
#   [PATCH] Add d_alloc_name() to libfs
#   
#   This patch consolidates several occurrences of duplicated code into a new
#   libfs function d_alloc_name().
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2004/10/25 21:14:01-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/e1000-2
# 
# drivers/net/e1000/e1000_main.c
#   2004/10/25 21:13:57-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/e1000/e1000.h
#   2004/10/25 21:13:57-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# security/selinux/selinuxfs.c
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +3 -14
#   Add d_alloc_name() to libfs
# 
# net/sunrpc/rpc_pipe.c
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +1 -5
#   Add d_alloc_name() to libfs
# 
# include/linux/fs.h
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +1 -0
#   Add d_alloc_name() to libfs
# 
# fs/libfs.c
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +2 -5
#   Add d_alloc_name() to libfs
# 
# fs/dcache.c
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +10 -0
#   Add d_alloc_name() to libfs
# 
# drivers/usb/gadget/inode.c
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +1 -5
#   Add d_alloc_name() to libfs
# 
# drivers/oprofile/oprofilefs.c
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +4 -10
#   Add d_alloc_name() to libfs
# 
# drivers/misc/ibmasm/ibmasmfs.c
#   2004/10/25 12:47:55-07:00 jmorris@redhat.com +2 -11
#   Add d_alloc_name() to libfs
# 
# ChangeSet
#   2004/10/25 18:13:49-07:00 cmm@us.ibm.com 
#   [PATCH] ext2: discard preallocation in last iput
#   
#   Currently the ext2 preallocation is discarded on every iput() (via
#   ext2_put_inode()).  We should only discard the preallocation on the last
#   iput() (via ext2_clear_inode()).
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext2/super.c
#   2004/10/25 12:47:55-07:00 cmm@us.ibm.com +4 -6
#   ext2: discard preallocation in last iput
# 
# fs/ext2/inode.c
#   2004/10/25 12:47:55-07:00 cmm@us.ibm.com +0 -13
#   ext2: discard preallocation in last iput
# 
# fs/ext2/ext2.h
#   2004/10/25 12:47:55-07:00 cmm@us.ibm.com +0 -1
#   ext2: discard preallocation in last iput
# 
# ChangeSet
#   2004/10/25 18:13:38-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: fixes to make version-1 superblocks work in md driver
#   
#   Add some missing data_offset additions and some le_to_cpu convertions and fix
#   a few other little mistakes.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/raid/md_p.h
#   2004/10/25 12:47:55-07:00 neilb@cse.unsw.edu.au +2 -2
#   md: fixes to make version-1 superblocks work in md driver
# 
# include/linux/raid/md.h
#   2004/10/25 12:47:55-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: fixes to make version-1 superblocks work in md driver
# 
# drivers/md/raid10.c
#   2004/10/25 12:47:55-07:00 neilb@cse.unsw.edu.au +1 -0
#   md: fixes to make version-1 superblocks work in md driver
# 
# drivers/md/multipath.c
#   2004/10/25 12:47:55-07:00 neilb@cse.unsw.edu.au +2 -0
#   md: fixes to make version-1 superblocks work in md driver
# 
# drivers/md/md.c
#   2004/10/25 12:47:55-07:00 neilb@cse.unsw.edu.au +11 -20
#   md: fixes to make version-1 superblocks work in md driver
# 
# ChangeSet
#   2004/10/25 18:13:26-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: fix typos in md and raid10
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid10.c
#   2004/10/25 13:18:38-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: fix typos in md and raid10
# 
# drivers/md/md.c
#   2004/10/25 13:18:38-07:00 neilb@cse.unsw.edu.au +2 -2
#   md: fix typos in md and raid10
# 
# ChangeSet
#   2004/10/25 18:13:13-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: don't hold lock on md devices while waiting for them to finish resync.
#   
#   If one md array is waiting for another to finish resyncing, then it holds a
#   reference to the array, so the array cannot be stopped.  With this patch, we
#   drop the reference before waiting.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/md.c
#   2004/10/25 13:18:38-07:00 neilb@cse.unsw.edu.au +36 -17
#   md: don't hold lock on md devices while waiting for them to finish resync.
# 
# ChangeSet
#   2004/10/25 18:13:01-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: discard calc_sb_csum_common in favour of csum_fold
#   
#   csum_fold should always have been used on the result of csum_partial.
#   calc_sb_csum_common therefore isn't needed.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/md.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +1 -26
#   md: discard calc_sb_csum_common in favour of csum_fold
# 
# ChangeSet
#   2004/10/25 18:12:49-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: make read retry use a new bio in raid1 and raid10
#   
#   When retrying a read request, we need to "Reset" the bio.  It is easiest to
#   get this right if we discard the bio we have and re-clone it.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid10.c
#   2004/10/25 13:18:38-07:00 neilb@cse.unsw.edu.au +6 -7
#   md: make read retry use a new bio in raid1 and raid10
# 
# drivers/md/raid1.c
#   2004/10/25 12:47:55-07:00 neilb@cse.unsw.edu.au +5 -1
#   md: make read retry use a new bio in raid1 and raid10
# 
# ChangeSet
#   2004/10/25 18:12:36-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: modify locking when accessing subdevices in md
#   
#   Each md personality keeps a list of devices that are currently active in the
#   array (mdk_rdev_t).  As these can potentially be removed at any time, some
#   locking is needed when accessing entries in the list.  Currently this involves
#   a spinlock, but all the spinlocking this imposed in unplug_slaves bothered me.
#   
#   So, I have changed it to use rcu locking.  This is more appropriate as objects
#   are removed only very rarely, and there is no cost in waiting a little while
#   for a remove to succeed.
#   
#   Also, all changes to the list of devices are performed by the per-array thread
#   (calling md_check_recovery) and so are completely single threaded, so no
#   locking between writers is needed at all.
#   
#   Finally, devices are never added or removed while resync is happening, so
#   resync doesn't need to worry about locking at all.
#   
#   So with this patch, the spinlocking is replaced with rcu read locking and
#   synchronize_kernel.  The rcu_read_lock is held while dereferencing a possible
#   device, and the nr_pending count is atomically incremented if the device is to
#   be held outside of the rcu_read_lock.
#   
#   When removing a device, if the nr_pending count appears to be zero, we set the
#   list entry to NULL and call synchronize_kernel().  If the count is still zero
#   after this, we have a safe removal.  If it is non-zero, then someone has just
#   started using it so we put the pointer back and fail the removal.  When the
#   new user finally drops it's reference, that will cause the per-array thread to
#   wake up again and retry the removal.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid6main.c
#   2004/10/25 12:47:54-07:00 neilb@cse.unsw.edu.au +29 -23
#   md: modify locking when accessing subdevices in md
# 
# drivers/md/raid5.c
#   2004/10/25 12:47:54-07:00 neilb@cse.unsw.edu.au +28 -23
#   md: modify locking when accessing subdevices in md
# 
# drivers/md/raid10.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +33 -29
#   md: modify locking when accessing subdevices in md
# 
# drivers/md/raid1.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +32 -29
#   md: modify locking when accessing subdevices in md
# 
# drivers/md/multipath.c
#   2004/10/25 13:18:38-07:00 neilb@cse.unsw.edu.au +30 -21
#   md: modify locking when accessing subdevices in md
# 
# ChangeSet
#   2004/10/25 18:12:24-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: fix two little bugs in raid10
#   
#   These can cause resync to spin when there is a faulty drive.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid10.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +2 -1
#   md: fix two little bugs in raid10
# 
# ChangeSet
#   2004/10/25 18:12:11-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: make sure md always uses rdev_dec_pending properly
#   
#   The ->nr_pending counted should always be decremented with rdev_dec_pending,
#   as this need to do things when the count hits zero.  There were a few places
#   where it was being decremented directly.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid6main.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: make sure md always uses rdev_dec_pending properly
# 
# drivers/md/raid5.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: make sure md always uses rdev_dec_pending properly
# 
# drivers/md/raid10.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +2 -2
#   md: make sure md always uses rdev_dec_pending properly
# 
# drivers/md/raid1.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +2 -2
#   md: make sure md always uses rdev_dec_pending properly
# 
# drivers/md/multipath.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: make sure md always uses rdev_dec_pending properly
# 
# ChangeSet
#   2004/10/25 18:11:59-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: rationalise unplug functions in md
#   
#   There are currently subtle differences in the different personalities
#   concerning when subdevices are unplugged (faulty?  nr_pending?).  This patch
#   makes them sll uniform.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid6main.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +2 -2
#   md: rationalise unplug functions in md
# 
# drivers/md/raid5.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +2 -2
#   md: rationalise unplug functions in md
# 
# drivers/md/raid10.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: rationalise unplug functions in md
# 
# drivers/md/raid1.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: rationalise unplug functions in md
# 
# drivers/md/multipath.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +1 -1
#   md: rationalise unplug functions in md
# 
# ChangeSet
#   2004/10/25 18:11:47-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: rationalise issue_flush function in md personalities
#   
#   The functions are all subtly different.  This patch makes them all much the
#   same.  In particular, EOPNOTSUPP gets returned by all is appropriate.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid6main.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +6 -16
#   md: rationalise issue_flush function in md personalities
# 
# drivers/md/raid5.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +6 -16
#   md: rationalise issue_flush function in md personalities
# 
# drivers/md/raid10.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +6 -6
#   md: rationalise issue_flush function in md personalities
# 
# drivers/md/raid1.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +6 -6
#   md: rationalise issue_flush function in md personalities
# 
# drivers/md/raid0.c
#   2004/10/25 12:47:54-07:00 neilb@cse.unsw.edu.au +4 -8
#   md: rationalise issue_flush function in md personalities
# 
# drivers/md/multipath.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +5 -8
#   md: rationalise issue_flush function in md personalities
# 
# drivers/md/linear.c
#   2004/10/25 12:47:54-07:00 neilb@cse.unsw.edu.au +4 -7
#   md: rationalise issue_flush function in md personalities
# 
# ChangeSet
#   2004/10/25 18:11:34-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: make retry_list non-global in raid1 and multipath
#   
#   Both raid1 and multipath have a "retry_list" which is global, so all raid1
#   arrays (for example) us the same list.  This is rather ugly, and it is simple
#   enough to make it per-array, so this patch does that.
#   
#   It also changes to multipath code to use list.h lists instead of
#   roll-your-own.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/raid/raid1.h
#   2004/10/25 12:47:54-07:00 neilb@cse.unsw.edu.au +1 -0
#   md: make retry_list non-global in raid1 and multipath
# 
# include/linux/raid/multipath.h
#   2004/10/25 12:47:54-07:00 neilb@cse.unsw.edu.au +2 -1
#   md: make retry_list non-global in raid1 and multipath
# 
# drivers/md/raid1.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +9 -9
#   md: make retry_list non-global in raid1 and multipath
# 
# drivers/md/multipath.c
#   2004/10/25 13:18:40-07:00 neilb@cse.unsw.edu.au +12 -16
#   md: make retry_list non-global in raid1 and multipath
# 
# ChangeSet
#   2004/10/25 18:11:22-07:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: remove md_flush_all
#   
#   Following are 7 patches for md
#   
#   They all grew out of a desire to redo the locking in unplug_slave.  Getting
#   and dropping a spinlock so often for very little gain (it would be nearly
#   impossible to lose the relevant race) really bothered me.
#   
#   I finally figured that I could reply it with rcu locking which is very light
#   wait, and quite up to the task.
#   
#   One the way I found an number of inconsistencies that needed cleaning up and
#   even a few bugs to fix.  The first 6 patches deal with these inconsistencies
#   and bugs.  The last redoes the locking for adding/removing/accessing devices
#   within md personalities.
#   
#   
#   This patch:
#   
#   md_flush_all() isn't needed as each personality defines its own
#   issue_flush_fn.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/md.c
#   2004/10/25 13:18:39-07:00 neilb@cse.unsw.edu.au +0 -33
#   md: remove md_flush_all
# 
# ChangeSet
#   2004/10/25 18:11:09-07:00 dvhltc@us.ibm.com 
#   [PATCH] sched: active_load_balance fixes
#   
#   The following patch against the latest mm fixes several problems with
#   active_load_balance().
#   
#   Rather than starting with the highest allowable domain (SD_LOAD_BALANCE is
#   still set) and depending on the order of the cpu groups, we start at the
#   lowest domain and work up until we find a suitable CPU or run out of
#   options (SD_LOAD_BALANCE is no longer set).  This is a more robust approach
#   as it is more explicit and not subject to the construction order of the cpu
#   groups.
#   
#   We move the test for busiest_rq->nr_running <=1 into the domain loop so we
#   don't continue to try and move tasks when there are none left to move.
#   This new logic (testing for nr_running in the domain loop) should make the
#   busiest_rq==target_rq condition really impossible, so we have replaced the
#   graceful continue on fail with a BUG_ON.  (Bjorn Helgaas, please confirm)
#   
#   We eliminate the exclusion of the busiest_cpu's group from the pool of
#   available groups to push to as it is the ideal group to push to, even if
#   not very likely to be available.  Note that by removing the test for
#   group==busy_group and allowing it to also be tested for suitability, the
#   running time is nearly the same.
#   
#   We no longer force the destination CPU to be in a group of completely idle
#   CPUs, nor to be the last in that group.
#   
#   Signed-off-by: Darren Hart <dvhltc@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/10/25 12:47:53-07:00 dvhltc@us.ibm.com +72 -57
#   sched: active_load_balance fixes
# 
# ChangeSet
#   2004/10/25 18:10:57-07:00 amgta@yacht.ocn.ne.jp 
#   [PATCH] schedstat: fix schedule() statistics
#   
#   The number of times schedule() left the processor idle in the
#   /proc/schedstat (runqueue.sched_goidle) seems to be wrong.
#   
#   The schedule() statistics should satisfy the equation:
#   	sched_cnt == sched_noswitch + sched_switch + sched_goidle
#   
#   (http://eaglet.rain.com/rick/linux/schedstat/v10/format-10.html)
#   
#   The below patch fix this, and I have confirmed to be fixed with:
#   	# grep ^cpu /proc/schedstat | awk '{print $6+$7+$9, $8}'
#   
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/10/25 13:18:41-07:00 amgta@yacht.ocn.ne.jp +2 -1
#   schedstat: fix schedule() statistics
# 
# ChangeSet
#   2004/10/25 18:10:44-07:00 hawkes@oss.sgi.com 
#   [PATCH] sched: improved load_balance() tolerance for pinned tasks
#   
#   A large number of processes that are pinned to a single CPU results in
#   every other CPU's load_balance() seeing this overloaded CPU as "busiest",
#   yet move_tasks() never finds a task to pull-migrate.  This condition occurs
#   during module unload, but can also occur as a denial-of-service using
#   sys_sched_setaffinity().  Several hundred CPUs performing this fruitless
#   load_balance() will livelock on the busiest CPU's runqueue lock.  A smaller
#   number of CPUs will livelock if the pinned task count gets high.  This
#   simple patch remedies the more common first problem: after a move_tasks()
#   failure to migrate anything, the balance_interval increments.  Using a
#   simple increment, vs.  the more dramatic doubling of the balance_interval,
#   is conservative and yet also effective.
#   
#   Signed-off-by: John Hawkes <hawkes@sgi.com>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/10/25 13:18:41-07:00 hawkes@oss.sgi.com +12 -4
#   sched: improved load_balance() tolerance for pinned tasks
# 
# ChangeSet
#   2004/10/25 18:10:32-07:00 jbarnes@engr.sgi.com 
#   [PATCH] sched: small load balance fix
#   
#   Small bug fix for domains that don't load balance (like those that only
#   balance on exec for example).
#   
#   Signed-off-by: John Hawkes <hawkes@sgi.com>
#   Signed-off-by: Jesse Barnes <jbarnes@sgi.com>
#   Acked-by: Nick Piggin <nickpiggin@yahoo.com.au>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/10/25 13:18:41-07:00 jbarnes@engr.sgi.com +1 -2
#   sched: small load balance fix
# 
# ChangeSet
#   2004/10/25 18:10:20-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: network driver
#   
#   From: Frank Pavlic <pavlic@de.ibm.com>
#   From: Thomas Spatzier <tspat@de.ibm.com>
#   
#   s390 network driver changes:
#    - ctc/iucv: Use DECLARE_PER_CPU instead of extern DEFINE_PER_CPU.
#    - lcs: Always set channel state to CH_STATE_INIT when stopping channels.
#    - qeth: vlan fixes.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/net/qeth_main.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +117 -124
#   s390: network driver
# 
# drivers/s390/net/qeth.h
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +1 -3
#   s390: network driver
# 
# drivers/s390/net/lcs.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +4 -4
#   s390: network driver
# 
# drivers/s390/net/iucv.h
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +1 -1
#   s390: network driver
# 
# drivers/s390/net/ctcdbug.h
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +3 -3
#   s390: network driver
# 
# ChangeSet
#   2004/10/25 18:10:07-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: qdio changes
#   
#   From: Utz Bacher <utz.bacher@de.ibm.com>
#   
#   qdio changes:
#    - Rename iqdio_is_inbound_q_done to tiqdio_is_inbound_q_done to
#      keep function naming consistent.
#    - Allocate qdio structures below 2GB.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/cio/qdio.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +8 -8
#   s390: qdio changes
# 
# ChangeSet
#   2004/10/25 18:09:55-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: debug feature system control
#   
#   From: Christian Borntraeger <cborntra@de.ibm.com>
#   
#   Debug feature changes:
#    - Add system control to stop the debug feature.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-s390/debug.h
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +2 -0
#   s390: debug feature system control
# 
# arch/s390/kernel/traps.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +5 -2
#   s390: debug feature system control
# 
# arch/s390/kernel/debug.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +76 -1
#   s390: debug feature system control
# 
# Documentation/s390/s390dbf.txt
#   2004/10/25 13:18:32-07:00 schwidefsky@de.ibm.com +37 -0
#   s390: debug feature system control
# 
# ChangeSet
#   2004/10/25 18:09:42-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: dcss segments cleanup
#   
#   From: Carsten Otte <cotte@de.ibm.com>
#   From: Gerald Schaefer <geraldsc@de.ibm.com>
#   
#   Cleanup segment load/unload infrastructure.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2004/10/25 21:09:39-04:00 akpm@osdl.org 
#   [PATCH] ne2k-pci pci build fix
#   
#   Fix for updated pci_{save,restore}_state()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# include/asm-s390/extmem.h
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +16 -5
#   s390: dcss segments cleanup
# 
# drivers/s390/char/monreader.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +60 -2
#   s390: dcss segments cleanup
# 
# drivers/s390/block/dcssblk.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +71 -48
#   s390: dcss segments cleanup
# 
# arch/s390/mm/extmem.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +367 -408
#   s390: dcss segments cleanup
# 
# drivers/net/ne2k-pci.c
#   2004/10/24 06:28:57-04:00 akpm@osdl.org +2 -2
#   ne2k-pci pci build fix
# 
# ChangeSet
#   2004/10/25 18:09:30-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: core changes
#   
#   s390 core changes:
#    - Load pid to cr4 on context switch.
#    - Correct and check buffer length of cpcmd. Fix cpcmd inline assembly.
#    - Add missing cc clobber to do_softirq insline assembly.
#    - Regenerate default configuration.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/s390/kernel/irq.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +1 -1
#   s390: core changes
# 
# arch/s390/kernel/entry64.S
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +1 -0
#   s390: core changes
# 
# arch/s390/kernel/entry.S
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +1 -0
#   s390: core changes
# 
# arch/s390/kernel/cpcmd.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +12 -11
#   s390: core changes
# 
# arch/s390/kernel/asm-offsets.c
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +2 -0
#   s390: core changes
# 
# arch/s390/defconfig
#   2004/10/25 12:47:52-07:00 schwidefsky@de.ibm.com +11 -2
#   s390: core changes
# 
# ChangeSet
#   2004/10/25 18:09:17-07:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: sacf local root exploit (CAN-2004-0887)
#   
#   s390 core changes:
#    - Force user process back to home space mode in space switch event
#      exception handler.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/s390/kernel/traps.c
#   2004/10/25 13:18:42-07:00 schwidefsky@de.ibm.com +16 -1
#   s390: sacf local root exploit (CAN-2004-0887)
# 
# ChangeSet
#   2004/10/25 18:09:05-07:00 blaisorblade_spam@yahoo.it 
#   [PATCH] uml: add conf INITRAMFS_SOURCE
#   
#   Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/Kconfig_block
#   2004/10/25 12:47:51-07:00 blaisorblade_spam@yahoo.it +27 -0
#   uml: add conf INITRAMFS_SOURCE
# 
# ChangeSet
#   2004/10/25 18:08:53-07:00 blaisorblade_spam@yahoo.it 
#   [PATCH] uml: unused label
#   
#   Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/tt/process_kern.c
#   2004/10/25 12:47:51-07:00 blaisorblade_spam@yahoo.it +0 -1
#   uml: unused label
# 
# ChangeSet
#   2004/10/25 18:08:41-07:00 blaisorblade_spam@yahoo.it 
#   [PATCH] uml: resync LDS script for SMP changes
#   
#   Add a couple entries to the linker script which are needed for SMP to link.
#   (From Yan Burman)
#   
#   Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/uml.lds.S
#   2004/10/25 12:47:51-07:00 blaisorblade_spam@yahoo.it +2 -0
#   uml: resync LDS script for SMP changes
# 
# arch/um/kernel/dyn.lds.S
#   2004/10/25 12:47:51-07:00 blaisorblade_spam@yahoo.it +2 -0
#   uml: resync LDS script for SMP changes
# 
# ChangeSet
#   2004/10/25 18:08:28-07:00 blaisorblade_spam@yahoo.it 
#   [PATCH] uml: Kconfig and defconfig updates.
#   
#   - Make CONFIG_SMP depend on TT mode. Since SMP does not work in SKAS mode
#     (it's still a TODO), add the dependency in the Kconfig. Also mark CONFIG_SMP
#     as experimental.
#   - Workaround kconfig warning: just for now (we wait for a "CONFIG_VIRTUAL_OS"
#     to exclude physical hardware) create the CONFIG_INPUT option (fixed to N),
#     to avoid complaints from make *config ARCH=um about it being undefined.
#   - Mark HPPFS as broken and needing updates.
#   - Update defconfig, both for new kernel options and for changes in the actual
#     config. For instance, enable module support by default.
#   - Update help text for some items and add a help to some other ones.
#   
#   Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/defconfig
#   2004/10/25 12:47:51-07:00 blaisorblade_spam@yahoo.it +38 -117
#   uml: Kconfig and defconfig updates.
# 
# arch/um/Kconfig
#   2004/10/25 12:47:51-07:00 blaisorblade_spam@yahoo.it +40 -10
#   uml: Kconfig and defconfig updates.
# 
# ChangeSet
#   2004/10/25 18:08:16-07:00 bunk@stusta.de 
#   [PATCH] small SOFTWARE_SUSPEND help text fixes
#   
#   Some small fixes for the SOFTWARE_SUSPEND help text.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/Kconfig
#   2004/10/25 12:47:51-07:00 bunk@stusta.de +2 -1
#   small SOFTWARE_SUSPEND help text fixes
# 
# ChangeSet
#   2004/10/25 18:08:03-07:00 pavel@ucw.cz 
#   [PATCH] power/disk.c: small fixups
#   
#   power_down may never ever fail, so it does not really need to return
#   anything.  Kill obsolete code and fixup old comments.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/disk.c
#   2004/10/25 12:47:51-07:00 pavel@ucw.cz +5 -14
#   power/disk.c: small fixups
# 
# ChangeSet
#   2004/10/25 18:07:51-07:00 paulus@samba.org 
#   [PATCH] ppc64: __ioremap_explicit() criterion change
#   
#   This patch is from John Rose <johnrose@austin.ibm.com>.
#   
#   The function __ioremap_explicit() misses a possible (obscure) case when
#   reserving the imalloc area for the new region.  This can result in the
#   unexpected DLPAR-add failure for an I/O slot.  The failure will be
#   characterized by a kernel message resembling "could not obtain imalloc area
#   for ea 0x..." Here's an explanation:
#   
#   At boot time, imalloc regions are created for the ranges of all PHBs.  Upon
#   removal of a child slot for one of these PHBs, the imalloc region is split
#   so that the region for the child slot can be removed.
#   
#   A GFW testcase revealed the following scenario.  A PHB is remapped at boot
#   for virtual address range A through C.  At boot, the partition owns a slot
#   that spans from A to B.  This slot is DLPAR-removed, leaving an imalloc
#   region from B to C.  At this point, the user DLPAR adds an EADS slot that
#   was not present at boot, but is a child of the PHB.  The new slot happens
#   to have a range that directly matches the leftover PHB range, from B to C. 
#   The existing code does not expect this, so the operation fails.
#   
#   Signed-off-by: John Rose <johnrose@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/mm/init.c
#   2004/10/25 12:47:50-07:00 paulus@samba.org +2 -1
#   ppc64: __ioremap_explicit() criterion change
# 
# ChangeSet
#   2004/10/25 18:07:39-07:00 paulus@samba.org 
#   [PATCH] ppc64: create iommu_free_table()
#   
#   This patch is from John Rose <johnrose@austin.ibm.com>.
#   
#   The patch below creates iommu_free_table().  Iommu tables are not currently
#   freed in PPC64.  This could cause a memory leak for DLPAR of an EADS slot. 
#   The function verifies that there are no outstanding TCE entries for the
#   range of the table before freeing it.  I added a call to iommu_free_table()
#   to the code that dynamically removes a device node.  This should be fairly
#   symmetrical with the table allocation, which happens during dynamic
#   addition of a device node.
#   
#   Signed-off-by: John Rose <johnrose@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/iommu.h
#   2004/10/25 12:47:51-07:00 paulus@samba.org +3 -0
#   ppc64: create iommu_free_table()
# 
# arch/ppc64/kernel/prom.c
#   2004/10/25 12:47:50-07:00 paulus@samba.org +3 -0
#   ppc64: create iommu_free_table()
# 
# arch/ppc64/kernel/pSeries_iommu.c
#   2004/10/25 12:47:50-07:00 paulus@samba.org +32 -0
#   ppc64: create iommu_free_table()
# 
# ChangeSet
#   2004/10/25 18:07:26-07:00 paulus@samba.org 
#   [PATCH] ppc64: crash during firmware flash update
#   
#   This patch is from Linas Vepstas <linas@austin.ibm.com>.
#   
#   Race conditions during system shutdown after a firmware flash can sometimes
#   lead to an invalid pointer deref (deref to freed memory).  This patch fixes
#   this.  In addition, it makes sure that the proc entries created by the
#   firmware flash module are removed when the module is unloaded. 
#   
#   Signed-off-by: Linas Vepstas <linas@linas.org>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/rtas_flash.c
#   2004/10/25 12:47:50-07:00 paulus@samba.org +3 -1
#   ppc64: crash during firmware flash update
# 
# ChangeSet
#   2004/10/25 18:07:14-07:00 paulus@samba.org 
#   [PATCH] ppc64: provide notifier list for EEH slot isolations
#   
#   When the EEH (enhanced i/o error handling) hardware on pSeries detects
#   various kinds of PCI errors, it immediately freezes and isolates the slot
#   of the offending PCI card.  We get to know about that by noticing that
#   reads from the device return all-1s, and then we have to do a firmware call
#   to find out whether the all-1s value was due to a slot isolation.
#   
#   This patch adds a notifier so that other parts of the system (e.g.  the RPA
#   PCI hotplug driver) can know that a slot isolation event has occurred and
#   take whatever recovery action is appropriate.  The notifier is called in a
#   workqueue function, although the read from the device that noticed the
#   all-1s value may have been at interrupt level.  As a precaution, if we keep
#   trying to read from the device at interrupt level, and do 1000 reads
#   without the workqueue getting a chance to run, we panic, on the grounds
#   that we presumably have a badly-written driver which will spin forever in
#   its interrupt routine, e.g.  waiting for a bit in a device register to go
#   to 0.
#   
#   This patch is based on an earlier patch by Linas Vepstas <linas@linas.org>.
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/eeh.h
#   2004/10/25 12:47:50-07:00 paulus@samba.org +26 -2
#   ppc64: provide notifier list for EEH slot isolations
# 
# arch/ppc64/kernel/eeh.c
#   2004/10/25 12:47:50-07:00 paulus@samba.org +224 -52
#   ppc64: provide notifier list for EEH slot isolations
# 
# ChangeSet
#   2004/10/25 18:07:02-07:00 david@gibson.dropbear.id.au 
#   [PATCH] ppc64: xmon sparse cleanups
#   
#   This patch removes many sparse warnings from the xmon code.  Mostly K&R
#   function declarations and 0-instead-of-NULLs.  There are still a whole
#   bunch of warnings in xmon/ppc-opc.c, which is a copy of a file from
#   binutils.
#   
#   Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
#   Acked-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/xmon/xmon.c
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +13 -15
#   ppc64: xmon sparse cleanups
# 
# arch/ppc64/xmon/start.c
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +1 -1
#   ppc64: xmon sparse cleanups
# 
# ChangeSet
#   2004/10/25 18:06:50-07:00 david@gibson.dropbear.id.au 
#   [PATCH] ppc64: trivial sparse cleanups
#   
#   This patch squashes a handful of assorted sparse warnings in the ppc64
#   code.  Should be pretty much trivial and self explanatory.
#   
#   Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
#   Acked-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/mm/hugetlbpage.c
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +1 -1
#   ppc64: trivial sparse cleanups
# 
# arch/ppc64/mm/hash_utils.c
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +1 -1
#   ppc64: trivial sparse cleanups
# 
# arch/ppc64/kernel/setup.c
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +1 -1
#   ppc64: trivial sparse cleanups
# 
# arch/ppc64/kernel/nvram.c
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +2 -2
#   ppc64: trivial sparse cleanups
# 
# ChangeSet
#   2004/10/25 18:06:37-07:00 david@gibson.dropbear.id.au 
#   [PATCH] ppc64: don't build virtual IO drivers for PowerMac
#   
#   Only compile vio.c on iSeries and pSeries, since other PPC64 platforms
#   (PowerMac) don't use virtual IO.  The resulting #ifdefs in dma.c are kind
#   of ugly, but at least contained, and I can't see a nicer way of doing it
#   for the time being.
#   
#   Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/dma.c
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +20 -0
#   ppc64: don't build virtual IO drivers for PowerMac
# 
# arch/ppc64/kernel/Makefile
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +2 -1
#   ppc64: don't build virtual IO drivers for PowerMac
# 
# arch/ppc64/Kconfig
#   2004/10/25 12:47:50-07:00 david@gibson.dropbear.id.au +5 -0
#   ppc64: don't build virtual IO drivers for PowerMac
# 
# ChangeSet
#   2004/10/25 18:06:25-07:00 trini@kernel.crashing.org 
#   [PATCH] ppc32: Fix building for Motorola Sandpoint with O=
#   
#   Since we directly -include $(clear_L2_L3) when needed, we need to point to
#   the full path of it.
#   
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/boot/simple/Makefile
#   2004/10/25 12:47:49-07:00 trini@kernel.crashing.org +1 -1
#   ppc32: Fix building for Motorola Sandpoint with O=
# 
# ChangeSet
#   2004/10/25 18:06:13-07:00 chrisw@osdl.org 
#   [PATCH] lsm: remove net related includes from security.h
#   
#   With this we're back to the times when changing skbuff.h only triggers
#   rebuild of _net_ related stuff 8)
#   
#   This uncovered a bug in rmap.h, that was not including mm.h to get the
#   definition of struct vm_area_struct, working by luck.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/commoncap.c
#   2004/10/25 12:47:50-07:00 chrisw@osdl.org +17 -0
#   lsm: remove net related includes from security.h
# 
# include/linux/security.h
#   2004/10/25 12:47:50-07:00 chrisw@osdl.org +7 -18
#   lsm: remove net related includes from security.h
# 
# include/linux/rmap.h
#   2004/10/25 12:47:50-07:00 chrisw@osdl.org +1 -0
#   lsm: remove net related includes from security.h
# 
# ChangeSet
#   2004/10/25 18:06:00-07:00 chrisw@osdl.org 
#   [PATCH] lsm: fix send_sigurg mediation
#   
#   Stephen Smalley notes that send_sigurg isn't mediated by LSM in the same
#   manner as send_sigio.  Patch below is a slight modification of Stephen's
#   original patch.  It moves the security_file_send_sigiotask() hook into the
#   sigio_perm().  The hook's fd and reason arguments are replaced with the
#   signum.  sigio_perm() and it's callers are updated to pass the signum
#   through to the hook.  In send_sigio case, the signum is simply fown->signum
#   or SIGIO when signum is 0, however in send_sigurg the kernel doesn't use
#   fown->signum, it always sends SIGURG.
#   
#   From: Stephen Smalley <sds@epoch.ncsc.mil>
#   Signed-off-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/hooks.c
#   2004/10/25 13:18:32-07:00 chrisw@osdl.org +3 -4
#   lsm: fix send_sigurg mediation
# 
# security/dummy.c
#   2004/10/25 12:47:50-07:00 chrisw@osdl.org +1 -2
#   lsm: fix send_sigurg mediation
# 
# include/linux/security.h
#   2004/10/25 13:18:46-07:00 chrisw@osdl.org +10 -12
#   lsm: fix send_sigurg mediation
# 
# fs/fcntl.c
#   2004/10/25 12:47:50-07:00 chrisw@osdl.org +7 -9
#   lsm: fix send_sigurg mediation
# 
# ChangeSet
#   2004/10/25 18:05:47-07:00 rddunlap@osdl.org 
#   [PATCH] checkstack: add x86_64 arch. support
#   
#   Add support for x86_64 arch. to 'make checkstack' (checkstack.pl).
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Acked-by: Jrn Engel <joern@wohnheim.fh-wedel.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/checkstack.pl
#   2004/10/25 12:47:49-07:00 rddunlap@osdl.org +3 -0
#   checkstack: add x86_64 arch. support
# 
# ChangeSet
#   2004/10/25 18:05:35-07:00 nickpiggin@yahoo.com.au 
#   [PATCH] mm: help zone padding
#   
#   Uses the zero length array which seems to be quite abundant throughout the
#   tree to reduce the size of the zone padding to zero.
#   
#   1536 before, 1152 afterwards for me.
#   
#   Also try to be a bit smarter about getting commonly accessed fields
#   together, which surely can't be worse than before.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mmzone.h
#   2004/10/25 12:47:49-07:00 nickpiggin@yahoo.com.au +19 -18
#   mm: help zone padding
# 
# ChangeSet
#   2004/10/25 18:05:23-07:00 akpm@osdl.org 
#   [PATCH] msnd.c build fix
#   
#   sound/oss/msnd.c: In function `msnd_enable_irq':
#   sound/oss/msnd.c:278: warning: implicit declaration of function `enable_irq'
#   sound/oss/msnd.c: In function `msnd_disable_irq':
#   sound/oss/msnd.c:307: warning: implicit declaration of function `disable_irq'
#   
#   sound/oss/msnd.c:323: `msnd_get_num_devs' undeclared here (not in a function)
#   sound/oss/msnd.c:323: initializer element is not constant
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/msnd.c
#   2004/10/25 12:47:49-07:00 akpm@osdl.org +2 -0
#   msnd.c build fix
# 
# ChangeSet
#   2004/10/25 18:05:11-07:00 dhowells@redhat.com 
#   [PATCH] Shift key-related error codes up and insert ECANCELED
#   
#   This patch shifts the key-related error codes up by one and inserts an
#   ECANCELED error code where not already defined.  It seems that has been
#   defined in glibc without passing it back to the kernel:-/
#   
#   Signed-Off-By: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sparc64/errno.h
#   2004/10/25 12:47:49-07:00 dhowells@redhat.com +5 -4
#   Shift key-related error codes up and insert ECANCELED
# 
# include/asm-sparc/errno.h
#   2004/10/25 12:47:49-07:00 dhowells@redhat.com +5 -4
#   Shift key-related error codes up and insert ECANCELED
# 
# include/asm-generic/errno.h
#   2004/10/25 12:47:49-07:00 dhowells@redhat.com +5 -4
#   Shift key-related error codes up and insert ECANCELED
# 
# include/asm-alpha/errno.h
#   2004/10/25 12:47:49-07:00 dhowells@redhat.com +5 -4
#   Shift key-related error codes up and insert ECANCELED
# 
# ChangeSet
#   2004/10/25 18:04:58-07:00 juhl-lkml@dif.dk 
#   [PATCH] ds_ioctl.c usercopy check
#   
#   Patch adds a check of the return value and returns -EFAULT if
#   __copy_to_user fails.
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Acked-by: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/pcmcia/ds.c
#   2004/10/25 12:47:48-07:00 juhl-lkml@dif.dk +5 -1
#   ds_ioctl.c usercopy check
# 
# ChangeSet
#   2004/10/25 18:04:46-07:00 akpm@osdl.org 
#   [PATCH] revert "ppc: fix build with o=output_dir"
#   
#   This was the wrong fix - back it out and try again later.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/boot/lib/Makefile
#   2004/10/25 12:47:48-07:00 akpm@osdl.org +1 -7
#   revert "ppc: fix build with o=output_dir"
# 
# ChangeSet
#   2004/10/25 21:04:34-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/misc
# 
# net/irda/irlan/irlan_client.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/tulip/xircom_cb.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/tulip/de4x5.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/tulip/de2104x.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/tokenring/olympic.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/smc91x.h
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/pcnet32.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ns83820.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/mac8390.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/hamradio/hdlcdrv.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/e1000/e1000_main.c
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2004/10/25 21:04:30-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 16:21:14-07:00 andrea@novell.com 
#   [NET]: Accept should return ENFILE not EMFILE.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/socket.c
#   2004/10/25 16:20:43-07:00 andrea@novell.com +1 -1
#   [NET]: Accept should return ENFILE not EMFILE.
# 
# ChangeSet
#   2004/10/25 16:10:45-07:00 herbert@gondor.apana.org.au 
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_output.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -4
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/route.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +5 -6
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/ip6_output.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +9 -12
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_output.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -4
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/route.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -3
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ipt_ECN.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ip_nat_standalone.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ip_fw_compat.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ip_output.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -5
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/decnet/dn_route.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -8
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/dst.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -2
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/dev.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +12 -12
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_netfilter.c
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/xfrm.h
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -2
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/ipv6.h
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/ip6_route.h
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/ip.h
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -2
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/dst.h
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +2 -2
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/netdevice.h
#   2004/10/25 16:10:25-07:00 herbert@gondor.apana.org.au +1 -1
#   [NET]: Give skb_checksum_help() an skb_buff * again
#   
#   Since skb_checksum_help has been using pskb_expand_head for a while
#   now without any ill effects, I thought it would be a good idea to
#   remove the double pointers from it and its callers.
#   
#   This is what the following patch does.  The only 'rider' bit is the
#   removal of an unnecessary BUG_ON in ip6_pkt_discard_out.  The preceding
#   assignment was only added because the following function oopsed so
#   there is no point in doing BUG_ON.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 16:05:16-07:00 laforge@netfilter.org 
#   [NETFILTER]: fix ipt_ULOG bogus error messages
#   
#   Please apply the fix below, it addresses some bogus error messages
#   ('error during NLMSG_PUT') that were printed because of a wrong
#   calculation of the 'len' parameter to NLMSG_PUT().
#   
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ipt_ULOG.c
#   2004/10/25 16:04:57-07:00 laforge@netfilter.org +4 -2
#   [NETFILTER]: fix ipt_ULOG bogus error messages
#   
#   Please apply the fix below, it addresses some bogus error messages
#   ('error during NLMSG_PUT') that were printed because of a wrong
#   calculation of the 'len' parameter to NLMSG_PUT().
#   
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 15:48:28-07:00 davem@nuts.davemloft.net 
#   [NETFILTER]: ip_ct_attach decl got removed by accident.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/netfilter.h
#   2004/10/25 15:47:56-07:00 davem@nuts.davemloft.net +2 -0
#   [NETFILTER]: ip_ct_attach decl got removed by accident.
# 
# ChangeSet
#   2004/10/25 15:43:30-07:00 hch@lst.de 
#   [NETFILTER]: Make *_find_target_lock routines static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/netfilter/ip6_tables.c
#   2004/10/25 15:43:11-07:00 hch@lst.de +1 -2
#   [NETFILTER]: Make *_find_target_lock routines static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ip_tables.c
#   2004/10/25 15:43:11-07:00 hch@lst.de +1 -2
#   [NETFILTER]: Make *_find_target_lock routines static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/arp_tables.c
#   2004/10/25 15:43:11-07:00 hch@lst.de +1 -2
#   [NETFILTER]: Make *_find_target_lock routines static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/netfilter_ipv4/ip_tables.h
#   2004/10/25 15:43:11-07:00 hch@lst.de +0 -5
#   [NETFILTER]: Make *_find_target_lock routines static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/netfilter.h
#   2004/10/25 15:43:11-07:00 hch@lst.de +0 -8
#   [NETFILTER]: Make *_find_target_lock routines static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 15:38:06-07:00 bdschuym@pandora.be 
#   [EBTABLES]: Add wildcard support for interface matching.
#   
#   Due to an old braindead decision, ebtables doesn't yet support the
#   wildcard '+' for matching interface names. The following patch removes
#   this nuissance and is backwards compatible.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/netfilter/ebtables.c
#   2004/10/25 15:37:34-07:00 bdschuym@pandora.be +7 -1
#   [EBTABLES]: Add wildcard support for interface matching.
#   
#   Due to an old braindead decision, ebtables doesn't yet support the
#   wildcard '+' for matching interface names. The following patch removes
#   this nuissance and is backwards compatible.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/25 15:21:01-07:00 torvalds@ppc970.osdl.org 
#   Allow BKL re-acquire to fail, causing us to re-schedule.
#   
#   This allows for low-latency BKL contention even with
#   preemption. Previously, since preemption is disabled
#   over context switches, re-acquiring the kernel lock when
#   resuming a process would be non-preemtible.
# 
# lib/kernel_lock.c
#   2004/10/25 15:20:55-07:00 torvalds@ppc970.osdl.org +34 -10
#   Allow BKL re-acquire to fail, causing us to re-schedule.
#   
#   This allows for low-latency BKL contention even with
#   preemption. Previously, since preemption is disabled
#   over context switches, re-acquiring the kernel lock when
#   resuming a process would be non-preemtible.
# 
# kernel/sched.c
#   2004/10/25 15:20:55-07:00 torvalds@ppc970.osdl.org +5 -2
#   Allow BKL re-acquire to fail, causing us to re-schedule.
#   
#   This allows for low-latency BKL contention even with
#   preemption. Previously, since preemption is disabled
#   over context switches, re-acquiring the kernel lock when
#   resuming a process would be non-preemtible.
# 
# include/linux/smp_lock.h
#   2004/10/25 15:20:55-07:00 torvalds@ppc970.osdl.org +19 -5
#   Allow BKL re-acquire to fail, causing us to re-schedule.
#   
#   This allows for low-latency BKL contention even with
#   preemption. Previously, since preemption is disabled
#   over context switches, re-acquiring the kernel lock when
#   resuming a process would be non-preemtible.
# 
# ChangeSet
#   2004/10/25 10:24:04-07:00 hannal@us.ibm.com 
#   [PATCH] add 'for_each_pci_dev()' helper macro
#   
#   Jeff already mistakenly sent in a user of this macro, so we should
#   probably add the macro itself too.
#   
#   Signed-off-by: Hanna Linder <hannal@us.ibm.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/pci.h
#   2004/10/05 15:56:26-07:00 hannal@us.ibm.com +1 -0
#   add 'for_each_pci_dev()' helper macro
# 
# ChangeSet
#   2004/10/25 09:20:09-07:00 torvalds@ppc970.osdl.org 
#   ppc64: make G5 setup compile again
#   
#   The stop_self thing is accessed unconditionally from pSeries_setup.c
# 
# arch/ppc64/kernel/rtas.c
#   2004/10/25 09:20:03-07:00 torvalds@ppc970.osdl.org +0 -2
#   ppc64: make G5 setup compile again
#   
#   The stop_self thing is accessed unconditionally from pSeries_setup.c
# 
# ChangeSet
#   2004/10/25 08:24:40-07:00 mingo@redhat.com 
#   [PATCH] Avoid small irq preemption recursion window
#   
#   This will get rid of the stack recursion possibility that can occur if
#   an IRQ happens to hit the IRQ return path right after we've reset
#   preempt_count() to 0 and are about to disable interrupts again.
#   Trivially fixed by just moving the preempt count update to inside the
#   interrupt disable.
#   
#   This makes the current PREEMPT_ACTIVE method fully work for IRQ
#   recursions.
# 
# arch/i386/kernel/entry.S
#   2004/10/24 17:00:00-07:00 mingo@redhat.com +1 -1
#   Avoid small irq preemption recursion window
# 
# ChangeSet
#   2004/10/25 08:10:39-07:00 linux@dominikbrodowski.de 
#   [PATCH] Fix PCMCIA duplicate pc_debug names
#   
#   Avoid naming confusion concerning "pc_debug" which is widely used by drivers
#   be renaming the PCMCIA "driver services" variant to ds_pc_debug. The module
#   parameter stays the same, thanks to module_param_named().
#   
#   Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.de>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/pcmcia/ds.c
#   2004/10/22 13:32:11-07:00 linux@dominikbrodowski.de +3 -3
#   Fix PCMCIA duplicate pc_debug names
# 
# drivers/pcmcia/bulkmem.c
#   2004/10/22 13:33:05-07:00 linux@dominikbrodowski.de +2 -2
#   Fix PCMCIA duplicate pc_debug names
# 
# ChangeSet
#   2004/10/25 08:03:24-07:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/davem/net-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# drivers/video/aty/atyfb_base.c
#   2004/10/25 08:03:20-07:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 03:49:28-04:00 jgarzik@pobox.com 
#   Merge
# 
# drivers/net/tg3.c
#   2004/10/25 03:49:24-04:00 jgarzik@pobox.com +0 -0
#   SCCS merged
# 
# ChangeSet
#   2004/10/25 03:37:14-04:00 jgarzik@pobox.com 
#   Cset exclude: elf@buici.com|ChangeSet|20040920183610|08290
#   
#   Revert smc91x driver changeset, since this is already covered by other
#   smc91x updates already upstream.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc91x.h
#   2004/10/25 03:37:12-04:00 jgarzik@pobox.com +0 -0
#   Exclude
# 
# ChangeSet
#   2004/10/25 03:34:39-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/set-config
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/wireless/netwave_cs.c
#   2004/10/25 03:34:36-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/wan/lmc/lmc_main.c
#   2004/10/25 03:34:36-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/sk_mca.c
#   2004/10/25 03:34:36-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ibmlana.c
#   2004/10/25 03:34:36-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/media/dvb/dvb-core/dvb_net.c
#   2004/10/25 03:34:36-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 03:33:45-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/defxx
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/defxx.c
#   2004/10/25 03:33:42-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 03:30:48-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/acenic
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/acenic.c
#   2004/10/25 03:30:45-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/25 03:27:44-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/e100
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/e100.c
#   2004/10/25 03:27:41-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/24 21:44:39-07:00 geert@linux-m68k.org 
#   [PATCH] Atyfb: kill assignment warnings on Atari due to __iomem
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/atyfb_base.c
#   2004/10/24 03:59:07-07:00 geert@linux-m68k.org +3 -3
#   Atyfb: kill assignment warnings on Atari due to __iomem
# 
# ChangeSet
#   2004/10/24 21:44:26-07:00 geert@linux-m68k.org 
#   [PATCH] SCx200_ACB depends on PCI
#   
#   SCx200_ACB is a PCI driver and thus should depend on PCI
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/i2c/busses/Kconfig
#   2004/10/24 03:50:17-07:00 geert@linux-m68k.org +1 -1
#   SCx200_ACB depends on PCI
# 
# ChangeSet
#   2004/10/24 21:44:14-07:00 geert@linux-m68k.org 
#   [PATCH] Cyclades assignment warning
#   
#   Remove unneeded cast that causes a warning (cy_isa_addresses is an array
#   of unsigned ints).
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/cyclades.c
#   2004/10/24 03:47:52-07:00 geert@linux-m68k.org +1 -1
#   Cyclades assignment warning
# 
# ChangeSet
#   2004/10/24 21:44:02-07:00 geert@linux-m68k.org 
#   [PATCH] NTFS: missing #include <linux/vmalloc.h>
#   
#   fs/ntfs/compress.c calls v{malloc,free}() without including <linux/vmalloc.h>
#   
#   Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ntfs/compress.c
#   2004/10/24 02:58:41-07:00 geert@linux-m68k.org +1 -0
#   NTFS: missing #include <linux/vmalloc.h>
# 
# ChangeSet
#   2004/10/24 21:43:49-07:00 bgerst@quark.didntduck.org 
#   [PATCH] mem leak in tty_io.c
#   
#   The recent patch to clean up user accesses introduced a memory leak.  If
#   write_buf is reallocated, the old buffer isn't freed.  Also, since kfree
#   can take nulls, I removed the if from the other kfree.
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/tty_io.c
#   2004/10/22 07:36:11-07:00 bgerst@quark.didntduck.org +2 -2
#   mem leak in tty_io.c
# 
# ChangeSet
#   2004/10/24 21:09:41-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: remove unused cruft from prom.h
#   
#   This patch removes some bogus struct definitions from prom.h that aren't
#   used anymore after the other pending ppc64 patches have been applied.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/prom.h
#   2004/10/24 18:55:43-07:00 benh@kernel.crashing.org +0 -27
#   ppc64: remove unused cruft from prom.h
# 
# ChangeSet
#   2004/10/24 21:09:28-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Some cleanups of prom_init.c
#   
#   This patch does a few cleanups of arch/ppc64/kernel/prom_init.c, making
#   the RTAS instanciation code more readable & more robust, fixing a bug
#   in the code bringing in additional CPUs (would work with IBM firmware,
#   but not with another firmware of an upcoming platform), plus remove some
#   old commented out cruft left-over from the big cleanup.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/prom_init.c
#   2004/10/24 18:51:05-07:00 benh@kernel.crashing.org +41 -38
#   ppc64: Some cleanups of prom_init.c
# 
# ChangeSet
#   2004/10/24 21:09:16-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: cleanup/split SMP code
#   
#   Splits arch/ppc64/kernel/smp.c into 3 different files, smp.c, pSeries_smp.c and
#   iSeries_smp.c, thus removing most of the #define mess in those files and making
#   it easier to add a new platform.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/smp.h
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +9 -3
#   ppc64: cleanup/split SMP code
# 
# arch/ppc64/kernel/pSeries_smp.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +393 -0
#   ppc64: cleanup/split SMP code
# 
# arch/ppc64/kernel/iSeries_smp.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +151 -0
#   ppc64: cleanup/split SMP code
# 
# include/asm-ppc64/machdep.h
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +2 -0
#   ppc64: cleanup/split SMP code
# 
# arch/ppc64/kernel/smp.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +16 -452
#   ppc64: cleanup/split SMP code
# 
# arch/ppc64/kernel/setup.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +7 -0
#   ppc64: cleanup/split SMP code
# 
# arch/ppc64/kernel/pmac_smp.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +19 -13
#   ppc64: cleanup/split SMP code
# 
# arch/ppc64/kernel/pSeries_smp.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/pSeries_smp.c
# 
# arch/ppc64/kernel/pSeries_setup.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +15 -0
#   ppc64: cleanup/split SMP code
# 
# arch/ppc64/kernel/iSeries_smp.c
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/iSeries_smp.c
# 
# arch/ppc64/kernel/Makefile
#   2004/10/24 18:29:39-07:00 benh@kernel.crashing.org +2 -0
#   ppc64: cleanup/split SMP code
# 
# ChangeSet
#   2004/10/24 21:09:03-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Rework PCI <-> OF node matching
#   
#   This patch reworks the code that deals with matching PCI devices
#   with Open Firmware device nodes. This code made several incorrect
#   assumptions and can be simplified significantly. The main functional
#   difference now is that PHBs are no longer special cased, but that
#   shouldn't cause any specific problem.
#   
#   It also fixes a problem where u3_iommu.c wouldn't work for PCI
#   devices that lacked a matching OF device node.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/u3_iommu.c
#   2004/10/24 18:12:22-07:00 benh@kernel.crashing.org +6 -0
#   ppc64: Rework PCI <-> OF node matching
# 
# arch/ppc64/kernel/pci_dn.c
#   2004/10/24 18:15:30-07:00 benh@kernel.crashing.org +34 -53
#   ppc64: Rework PCI <-> OF node matching
# 
# ChangeSet
#   2004/10/24 21:08:51-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Some small pci fixes
#   
#   This patch fixes a few issues in the ppc64 pci code, notably some
#   incorrect parsing of Open Firmware "ranges" when setting up host
#   bridge resources that would cause a problem with some future
#   platforms, a default mapping of the ISA IOs if the OF "isa" node
#   lacks a "ranges" property, and a safeguard in pci_scan_all_fns()
#   in case a pci<->OF node mapping cannot be established.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pci.c
#   2004/10/24 18:04:50-07:00 benh@kernel.crashing.org +9 -5
#   ppc64: Some small pci fixes
# 
# ChangeSet
#   2004/10/24 21:08:39-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: cleanups of ppc64 pci.c
#   
#   This patch applies on top of previously posted "ppc64: Move PCI IO mapping
#   from pSeries_pci.c to pci.c".
#   
#   It does cosmetic cleanups & add some debug macros to pci.c without actually
#   changing any functionality. Further patches against ppc64 pci.c that I'll
#   post will be against a file already patched with this one.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pci.c
#   2004/10/24 17:36:51-07:00 benh@kernel.crashing.org +31 -19
#   ppc64: cleanups of ppc64 pci.c
# 
# ChangeSet
#   2004/10/24 21:08:24-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: clean up existence-check of legacy ISAdevices
#   
#   My previous patch exposed the internals of the ppc_md.  data structure
#   to drivers, which wasn't nice, this new patch cleans that up.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/machdep.h
#   2004/10/23 00:41:21-07:00 benh@kernel.crashing.org +3 -0
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# include/asm-ppc64/io.h
#   2004/10/23 00:37:07-07:00 benh@kernel.crashing.org +5 -1
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# include/asm-ppc64/floppy.h
#   2004/10/22 20:22:20-07:00 benh@kernel.crashing.org +1 -0
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# drivers/input/serio/i8042-io.h
#   2004/10/23 00:00:53-07:00 benh@kernel.crashing.org +9 -2
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# drivers/block/floppy.c
#   2004/10/23 00:04:20-07:00 benh@kernel.crashing.org +7 -0
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# arch/ppc64/kernel/setup.c
#   2004/10/23 00:09:58-07:00 benh@kernel.crashing.org +8 -0
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# arch/ppc64/kernel/pmac_setup.c
#   2004/10/22 20:22:20-07:00 benh@kernel.crashing.org +10 -0
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# arch/ppc64/kernel/pSeries_setup.c
#   2004/10/22 20:22:20-07:00 benh@kernel.crashing.org +26 -0
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# arch/ppc64/kernel/pSeries_pci.c
#   2004/10/22 20:22:20-07:00 benh@kernel.crashing.org +0 -13
#   ppc64: clean up existence-check of legacy ISAdevices
# 
# ChangeSet
#   2004/10/24 21:08:12-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: properly build list of legacy serial ports from OF
#   
#   This patch adds a ppc64 implementation of the routine providing
#   the list of default 8250 serial ports. It provides a empty list
#   by default unless the platform code fills it, and it provides
#   a generic function for user by Open Firmware based machines which
#   fills the list based on serial ports found in the OF device-tree.
#   
#   It depends on the previous patch adding the generic support for
#   this to the 8250 driver.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/udbg.h
#   2004/10/22 18:43:59-07:00 benh@kernel.crashing.org +1 -1
#   ppc64: properly build list of legacy serial ports from OF
# 
# include/asm-ppc64/serial.h
#   2004/10/22 18:43:59-07:00 benh@kernel.crashing.org +6 -106
#   ppc64: properly build list of legacy serial ports from OF
# 
# arch/ppc64/kernel/udbg.c
#   2004/10/22 18:43:59-07:00 benh@kernel.crashing.org +15 -2
#   ppc64: properly build list of legacy serial ports from OF
# 
# arch/ppc64/kernel/setup.c
#   2004/10/22 19:30:58-07:00 benh@kernel.crashing.org +182 -0
#   ppc64: properly build list of legacy serial ports from OF
# 
# arch/ppc64/kernel/pSeries_setup.c
#   2004/10/22 18:43:59-07:00 benh@kernel.crashing.org +5 -71
#   ppc64: properly build list of legacy serial ports from OF
# 
# ChangeSet
#   2004/10/24 21:08:00-07:00 benh@kernel.crashing.org 
#   [PATCH] 8250: Let arch provide the list of leagacy ports
#   
#   This patch adds an optional callback for the 8250 driver to request the
#   list of legacy port via a function call instead of relying on a #define
#   of an array.
#   
#   This finally allows to fix the problem of platforms like ppc and ppc64
#   for which the same kernel can boot machines with and without a 8250, and
#   is necessary to properly deal with a new platform coming to ppc64 which
#   has a 8250 but with different irq numbers.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/8250.h
#   2004/10/22 16:03:31-07:00 benh@kernel.crashing.org +0 -0
#   8250: Let arch provide the list of leagacy ports
# 
# drivers/serial/serial_cs.c
#   2004/10/22 16:06:40-07:00 benh@kernel.crashing.org +1 -2
#   8250: Let arch provide the list of leagacy ports
# 
# drivers/serial/au1x00_uart.c
#   2004/10/22 16:06:15-07:00 benh@kernel.crashing.org +1 -1
#   8250: Let arch provide the list of leagacy ports
# 
# drivers/serial/8250_pnp.c
#   2004/10/22 16:05:53-07:00 benh@kernel.crashing.org +1 -2
#   8250: Let arch provide the list of leagacy ports
# 
# drivers/serial/8250_pci.c
#   2004/10/22 16:33:40-07:00 benh@kernel.crashing.org +2 -2
#   8250: Let arch provide the list of leagacy ports
# 
# drivers/serial/8250.c
#   2004/10/22 16:31:26-07:00 benh@kernel.crashing.org +30 -12
#   8250: Let arch provide the list of leagacy ports
# 
# ChangeSet
#   2004/10/24 21:03:45-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Rewrite the openpic driver
#   
#   This patch replaces the open_pic IRQ controller driver with a new
#   version rewritten from scratch, called "mpic" (this is the name of
#   IBM's open_pic implementation and also the only one actually used
#   on any platform).
#   
#   It is smaller, hopefully more readable, supports the various variants
#   of the cell in a single driver (open_pic_u3.c is gone), and adds
#   optional support for the workaround of U3 mpic beeing used along with
#   IO-APICs on HyperTransport (the eval board will uses that, among
#   others).
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/mpic.h
#   2004/10/24 21:03:38-07:00 benh@kernel.crashing.org +267 -0
# 
# arch/ppc64/kernel/mpic.c
#   2004/10/24 21:03:38-07:00 benh@kernel.crashing.org +859 -0
# 
# include/asm-ppc64/smp.h
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +4 -0
#   ppc64: Rewrite the openpic driver
# 
# include/asm-ppc64/irq.h
#   2004/10/22 18:44:19-07:00 benh@kernel.crashing.org +13 -0
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/xics.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +1 -1
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/smp.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +19 -15
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/prom_init.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +0 -1
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/prom.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +4 -4
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/pmac_smp.c
#   2004/10/22 18:47:24-07:00 benh@kernel.crashing.org +7 -7
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/pmac_setup.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +23 -48
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/pSeries_setup.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +80 -22
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/pSeries_pci.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +4 -3
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/mpic.h
#   2004/10/24 21:03:38-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/mpic.h
# 
# arch/ppc64/kernel/mpic.c
#   2004/10/24 21:03:38-07:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/mpic.c
# 
# arch/ppc64/kernel/i8259.h
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +2 -2
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/i8259.c
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +17 -3
#   ppc64: Rewrite the openpic driver
# 
# arch/ppc64/kernel/Makefile
#   2004/10/22 18:44:03-07:00 benh@kernel.crashing.org +3 -3
#   ppc64: Rewrite the openpic driver
# 
# BitKeeper/deleted/.del-open_pic_u3.c~d4b087c3ee7ad834
#   2004/10/24 21:03:38-07:00 benh@kernel.crashing.org +0 -0
#   Delete: arch/ppc64/kernel/open_pic_u3.c
# 
# BitKeeper/deleted/.del-open_pic.h~3394270b8d4236a7
#   2004/10/24 21:03:38-07:00 benh@kernel.crashing.org +0 -0
#   Delete: arch/ppc64/kernel/open_pic.h
# 
# BitKeeper/deleted/.del-open_pic.c~be95ffa1bf03a15a
#   2004/10/24 21:03:38-07:00 benh@kernel.crashing.org +0 -0
#   Delete: arch/ppc64/kernel/open_pic.c
# 
# BitKeeper/deleted/.del-open_pic_defs.h~e0e1008090653957
#   2004/10/24 21:03:37-07:00 benh@kernel.crashing.org +0 -0
#   Delete: arch/ppc64/kernel/open_pic_defs.h
# 
# ChangeSet
#   2004/10/24 21:03:26-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Fix pSeries secondary CPU setup
#   
#   This patch fixes the setup of the secondary CPU(s) on pSeries,
#   on non-LPAR platforms, especially with 970 CPUs, we need to copy
#   some of the HID registers from CPU0 to the other ones as soon as
#   they reach the early asm code. The PowerMac SMP entry did it
#   already, but not the pSeries one.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/smp.c
#   2004/10/19 00:19:36-07:00 benh@kernel.crashing.org +0 -3
#   ppc64: Fix pSeries secondary CPU setup
# 
# arch/ppc64/kernel/head.S
#   2004/10/19 00:18:43-07:00 benh@kernel.crashing.org +28 -20
#   ppc64: Fix pSeries secondary CPU setup
# 
# arch/ppc64/kernel/cpu_setup_power4.S
#   2004/10/19 00:37:12-07:00 benh@kernel.crashing.org +9 -0
#   ppc64: Fix pSeries secondary CPU setup
# 
# ChangeSet
#   2004/10/24 23:42:57-04:00 ambx1@neo.rr.com 
#   [PNPBIOS] acpi compile fix
#   
#   Allow PNPBIOS to compile if ACPI support is not enabled.
#   
#   Signed-off-by: Adam Belay <ambx1@neo.rr.com>
#   
# 
# drivers/pnp/pnpbios/core.c
#   2004/10/24 23:30:15-04:00 ambx1@neo.rr.com +2 -0
#   [PNPBIOS] acpi compile fix
# 
# ChangeSet
#   2004/10/24 23:27:24-04:00 nacc@us.ibm.com 
#   [PNPBIOS] use msleep_interruptible()
#   
#   Description: Use msleep_interruptible() instead of
#   schedule_timeout() to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Adam Belay <ambx1@neo.rr.com>
#   
# 
# drivers/pnp/pnpbios/core.c
#   2004/09/27 12:52:49-04:00 nacc@us.ibm.com +2 -2
#   [PNPBIOS] use msleep_interruptible()
# 
# ChangeSet
#   2004/10/24 23:07:32-04:00 ambx1@neo.rr.com 
#   [PNPBIOS] disable if ACPI is active
#   
#   As further ACPI pnp functionaility is implemented it is no longer
#   safe to run ACPI and PNPBIOS concurrently.
#   
#   We therefore take the following approach:
#   - attempt to enable ACPI support
#   - if ACPI fails (blacklist etc.) enable pnpbios support
#   - if ACPI support is not compiled in the kernel enable pnpbios support
#   
#   Signed-off-by: Adam Belay <ambx1@neo.rr.com>
#   
# 
# drivers/pnp/pnpbios/core.c
#   2004/10/24 21:58:05-04:00 amb@neo.rr.com +6 -0
#   [PNPBIOS] disable if ACPI is active
# 
# ChangeSet
#   2004/10/24 17:40:16-07:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Move PCI IO mapping from pSeries_pci.c to pci.c
#   
#   This patch moves some of the routines responsible for dealing
#   with the mapping of PCI host bridges IO space from pSeries to
#   the generic ppc64 pci code. PowerMac doesn't use it currently,
#   but a new platform will soon.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/pci-bridge.h
#   2004/10/24 17:30:23-07:00 benh@kernel.crashing.org +2 -0
#   ppc64: Move PCI IO mapping from pSeries_pci.c to pci.c
# 
# arch/ppc64/kernel/pci.c
#   2004/10/24 17:28:50-07:00 benh@kernel.crashing.org +90 -0
#   ppc64: Move PCI IO mapping from pSeries_pci.c to pci.c
# 
# arch/ppc64/kernel/pSeries_pci.c
#   2004/10/24 17:28:40-07:00 benh@kernel.crashing.org +0 -86
#   ppc64: Move PCI IO mapping from pSeries_pci.c to pci.c
# 
# ChangeSet
#   2004/10/24 17:36:12-07:00 benh@kernel.crashing.org 
#   [PATCH] Fix msleep to sleep _at_least_ the requested amount
#   
#   Makes sure msleep() sleeps at least the amount provided, since
#   schedule_timeout() doesn't guarantee a full jiffy.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/timer.c
#   2004/10/22 16:16:10-07:00 benh@kernel.crashing.org +2 -2
#   Fix msleep to sleep _at_least_ the requested amount
# 
# ChangeSet
#   2004/10/24 16:44:07-07:00 torvalds@evo.osdl.org 
#   Fix broken intel8x0.c ALSA "merge"
#   
#   The file didn't compile, and the ALSA CVS tree
#   had dropped the bitfield signedness fixes.
# 
# sound/pci/intel8x0.c
#   2004/10/24 16:43:57-07:00 torvalds@evo.osdl.org +12 -11
#   Fix broken intel8x0.c ALSA "merge"
#   
#   The file didn't compile, and the ALSA CVS tree
#   had dropped the bitfield signedness fixes.
# 
# ChangeSet
#   2004/10/24 16:24:27-07:00 torvalds@ppc970.osdl.org 
#   Un-inline the big kernel lock.
#   
#   Now that spinlocks are uninlined, it is silly to keep the
#   BKL inlined. And this should make it a lot easier for people
#   to play around with variations on the locking (ie Ingo's
#   semaphores etc).
# 
# lib/kernel_lock.c
#   2004/10/24 16:24:20-07:00 torvalds@ppc970.osdl.org +102 -0
# 
# lib/kernel_lock.c
#   2004/10/24 16:24:20-07:00 torvalds@ppc970.osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/lib/kernel_lock.c
# 
# lib/Makefile
#   2004/10/24 16:24:20-07:00 torvalds@ppc970.osdl.org +1 -0
#   Un-inline the big kernel lock.
#   
#   Now that spinlocks are uninlined, it is silly to keep the
#   BKL inlined. And this should make it a lot easier for people
#   to play around with variations on the locking (ie Ingo's
#   semaphores etc).
# 
# kernel/sched.c
#   2004/10/24 16:24:20-07:00 torvalds@ppc970.osdl.org +0 -15
#   Un-inline the big kernel lock.
#   
#   Now that spinlocks are uninlined, it is silly to keep the
#   BKL inlined. And this should make it a lot easier for people
#   to play around with variations on the locking (ie Ingo's
#   semaphores etc).
# 
# init/Kconfig
#   2004/10/24 16:24:20-07:00 torvalds@ppc970.osdl.org +5 -0
#   Un-inline the big kernel lock.
#   
#   Now that spinlocks are uninlined, it is silly to keep the
#   BKL inlined. And this should make it a lot easier for people
#   to play around with variations on the locking (ie Ingo's
#   semaphores etc).
# 
# include/linux/spinlock.h
#   2004/10/24 16:24:20-07:00 torvalds@ppc970.osdl.org +2 -2
#   Un-inline the big kernel lock.
#   
#   Now that spinlocks are uninlined, it is silly to keep the
#   BKL inlined. And this should make it a lot easier for people
#   to play around with variations on the locking (ie Ingo's
#   semaphores etc).
# 
# include/linux/smp_lock.h
#   2004/10/24 16:24:20-07:00 torvalds@ppc970.osdl.org +16 -42
#   Un-inline the big kernel lock.
#   
#   Now that spinlocks are uninlined, it is silly to keep the
#   BKL inlined. And this should make it a lot easier for people
#   to play around with variations on the locking (ie Ingo's
#   semaphores etc).
# 
# ChangeSet
#   2004/10/25 01:11:17+02:00 pablo@eurodev.net 
#   [NETFILTER]: fix stats in __ip_conntrack_confirm
#   
#   net_rx_softirq can preempt the calling process while incrementing the stats.
#   I think that we can fix this moving both CONNTRACK_STAT_INC to the locked
#   section. 
#   
#   Signed-off-by: Pablo Neira Ayuso <pablo@eurodev.net>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/10/25 01:11:10+02:00 pablo@eurodev.net +3 -2
#   [NETFILTER]: fix stats in __ip_conntrack_confirm
#   
#   net_rx_softirq can preempt the calling process while incrementing the stats.
#   I think that we can fix this moving both CONNTRACK_STAT_INC to the locked
#   section. 
#   
#   Signed-off-by: Pablo Neira Ayuso <pablo@eurodev.net>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/25 00:46:55+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Introduce skb_header_pointer() to hbh match
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_hbh.c
#   2004/10/25 00:46:48+02:00 yasuyuki.kozakai@toshiba.co.jp +30 -20
#   [NETFILTER]: Introduce skb_header_pointer() to hbh match
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/25 00:45:22+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Introduce skb_header_pointer() to dst match
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_dst.c
#   2004/10/25 00:45:16+02:00 yasuyuki.kozakai@toshiba.co.jp +30 -20
#   [NETFILTER]: Introduce skb_header_pointer() to dst match
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/25 00:43:08+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Fix multiple bugs in hbh match
#   
#   This patch fixes the following bugs in ip6t_hbh.c.
#     - The cast of the pointer to the next IPv6 extension header is wrong.
#     - hdrlen may underflow.
#     - (u16)*optdesc causes to alignment problem.
#     - The calculation of the offset to next option is wrong. In the case
#       that the type isn't 0, it should be "Opt Data Len" field + 2
#       (see RFC2460).
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_hbh.c
#   2004/10/25 00:43:01+02:00 yasuyuki.kozakai@toshiba.co.jp +38 -36
#   [NETFILTER]: Fix multiple bugs in hbh match
#   
#   This patch fixes the following bugs in ip6t_hbh.c.
#     - The cast of the pointer to the next IPv6 extension header is wrong.
#     - hdrlen may underflow.
#     - (u16)*optdesc causes to alignment problem.
#     - The calculation of the offset to next option is wrong. In the case
#       that the type isn't 0, it should be "Opt Data Len" field + 2
#       (see RFC2460).
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/25 00:39:13+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Fix multiple bugs in dst match
#   
#   This patch fixes the following bugs in ip6t_dst.c.
#   
#     - ".me = THIS_MODULE" is missing 
#     - The cast of the pointer to the next IPv6 extension header is wrong.
#     - hdrlen may underflow.
#     - (u16)*optdesc causes to alignment problem.
#     - The calculation of the offset to next option is wrong. In the case
#       that the type isn't 0, it should be "Opt Data Len" field + 2
#       (see RFC2460).
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_dst.c
#   2004/10/25 00:39:07+02:00 yasuyuki.kozakai@toshiba.co.jp +39 -37
#   [NETFILTER]: Fix multiple bugs in dst match
#   
#   This patch fixes the following bugs in ip6t_dst.c.
#   
#     - ".me = THIS_MODULE" is missing 
#     - The cast of the pointer to the next IPv6 extension header is wrong.
#     - hdrlen may underflow.
#     - (u16)*optdesc causes to alignment problem.
#     - The calculation of the offset to next option is wrong. In the case
#       that the type isn't 0, it should be "Opt Data Len" field + 2
#       (see RFC2460).
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/24 15:20:06-07:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Fix software blanking code
#   
#   The code in fbmem.c:fb_blank() is broken.  For drivers without an fb_blank
#   hook, an FBIO_BLANK ioctl will produce wrong colors or will segfault.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/fbmem.c
#   2004/10/24 14:45:24-07:00 adaplas@hotpop.com +5 -3
#   fbdev: Fix software blanking code
# 
# ChangeSet
#   2004/10/24 13:34:51-07:00 torvalds@ppc970.osdl.org 
#   Annotate the trivial unconditional lock/unlock functions on SMP.
#   
#   This does _not_ handle the conditional ones (lock_kernel and the
#   trylock variants), so there will be a fair number of context
#   error warnings with this. However, the warnings are disabled by
#   default in sparse - you have to use "-Wcontext" to see them.
# 
# include/linux/spinlock.h
#   2004/10/24 13:34:44-07:00 torvalds@ppc970.osdl.org +31 -25
#   Annotate the trivial unconditional lock/unlock functions on SMP.
#   
#   This does _not_ handle the conditional ones (lock_kernel and the
#   trylock variants), so there will be a fair number of context
#   error warnings with this. However, the warnings are disabled by
#   default in sparse - you have to use "-Wcontext" to see them.
# 
# ChangeSet
#   2004/10/24 13:33:07-07:00 torvalds@ppc970.osdl.org 
#   Start supporting lock context annotations.
#   
#   This just sets up the portability defines.
# 
# include/linux/compiler.h
#   2004/10/24 13:33:00-07:00 torvalds@ppc970.osdl.org +8 -0
#   Start supporting lock context annotations.
#   
#   This just sets up the portability defines.
# 
# ChangeSet
#   2004/10/24 12:21:08-07:00 rth@twiddle.net 
#   [PATCH] Add __ioremap
#   
#   I hadn't realized this was supposed to be an official interface.
#   Or maybe it's not, but the fb drivers all use it.   Anyway...
# 
# include/asm-alpha/io.h
#   2004/10/23 11:04:06-07:00 rth@twiddle.net +6 -0
#   Add __ioremap
# 
# ChangeSet
#   2004/10/24 12:20:55-07:00 ink@jurassic.park.msu.ru 
#   [PATCH] alpha: bootp fixes
#   
#   - redefine "printk" as "srm_printk" for bootstrappers;
#   - fix stack corruption problem with bootp/bootpz loaders and older
#     SRM consoles.
# 
# arch/alpha/boot/misc.c
#   2004/10/24 11:31:29-07:00 ink@jurassic.park.msu.ru +0 -12
#   alpha: bootp fixes
# 
# arch/alpha/boot/head.S
#   2004/10/24 11:30:59-07:00 ink@jurassic.park.msu.ru +21 -0
#   alpha: bootp fixes
# 
# arch/alpha/boot/bootpz.c
#   2004/10/24 11:30:59-07:00 ink@jurassic.park.msu.ru +14 -11
#   alpha: bootp fixes
# 
# arch/alpha/boot/bootp.c
#   2004/10/24 11:30:59-07:00 ink@jurassic.park.msu.ru +12 -7
#   alpha: bootp fixes
# 
# arch/alpha/boot/bootloader.lds
#   2004/10/24 11:30:59-07:00 ink@jurassic.park.msu.ru +1 -0
#   alpha: bootp fixes
# 
# ChangeSet
#   2004/10/24 12:20:41-07:00 ink@jurassic.park.msu.ru 
#   [PATCH] alpha: fix CIA IO
#   
#   The high order bits of the input address should be cleared only after
#   IO type and base are determined.
# 
# include/asm-alpha/core_cia.h
#   2004/10/24 09:52:42-07:00 ink@jurassic.park.msu.ru +6 -6
#   alpha: fix CIA IO
# 
# ChangeSet
#   2004/10/24 12:20:28-07:00 ink@jurassic.park.msu.ru 
#   [PATCH] alpha: fix sparse warnings
#   
#   - add missing "__user" annotations in csum_partial_copy.c;
#   - make io_remap_page_range more readable and fix a warning.
# 
# include/asm-alpha/pgtable.h
#   2004/10/24 11:10:55-07:00 ink@jurassic.park.msu.ru +6 -2
#   alpha: fix sparse warnings
# 
# arch/alpha/lib/csum_partial_copy.c
#   2004/10/24 10:25:20-07:00 ink@jurassic.park.msu.ru +4 -2
#   alpha: fix sparse warnings
# 
# ChangeSet
#   2004/10/24 16:16:40+02:00 tgraf@suug.ch 
#   [NETFILTER]: Fix warning in CONNMARK
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ipt_CONNMARK.c
#   2004/10/24 16:16:34+02:00 tgraf@suug.ch +1 -1
#   [NETFILTER]: Fix warning in CONNMARK
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/24 16:11:28+02:00 kaber@coreworks.de 
#   Merge coreworks.de:/home/kaber/src/bk-repos/net-2.6
#   into coreworks.de:/home/kaber/src/nf/nf-2.6
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/10/24 16:11:24+02:00 kaber@coreworks.de +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/24 00:43:42+01:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Fix missing parens for __FD_* operations.
#   
#   fork.c highlighted that we were missing some parens.  Add them.
# 
# include/asm-arm/posix_types.h
#   2004/10/24 00:41:22+01:00 rmk@flint.arm.linux.org.uk +4 -4
#   Add parens around use of fd and fdsetp
# 
# ChangeSet
#   2004/10/23 23:19:19+02:00 bzolnier@trik.(none) 
#   [ide] slc90e66: kill /proc/ide/slc90e66
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/slc90e66.c
#   2004/10/23 23:18:50+02:00 bzolnier@trik.(none) +1 -110
#   [ide] slc90e66: kill /proc/ide/slc90e66
# 
# ChangeSet
#   2004/10/23 23:16:57+02:00 bzolnier@trik.(none) 
#   [ide] serverworks: kill /proc/ide/svwks
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/serverworks.h
#   2004/10/23 23:16:37+02:00 bzolnier@trik.(none) +0 -2
#   [ide] serverworks: kill /proc/ide/svwks
# 
# drivers/ide/pci/serverworks.c
#   2004/10/23 23:16:37+02:00 bzolnier@trik.(none) +0 -168
#   [ide] serverworks: kill /proc/ide/svwks
# 
# ChangeSet
#   2004/10/23 23:13:46+02:00 bzolnier@trik.(none) 
#   [ide] sc1200: kill /proc/ide/sc1200
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/sc1200.c
#   2004/10/23 23:13:25+02:00 bzolnier@trik.(none) +0 -65
#   [ide] sc1200: kill /proc/ide/sc1200
# 
# ChangeSet
#   2004/10/23 23:08:13+02:00 bzolnier@trik.(none) 
#   [ide] piix: kill /proc/ide/piix
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/piix.h
#   2004/10/23 23:07:58+02:00 bzolnier@trik.(none) +0 -4
#   [ide] piix: kill /proc/ide/piix
# 
# drivers/ide/pci/piix.c
#   2004/10/23 23:07:58+02:00 bzolnier@trik.(none) +0 -167
#   [ide] piix: kill /proc/ide/piix
# 
# ChangeSet
#   2004/10/23 23:05:06+02:00 bzolnier@trik.(none) 
#   [ide] pdc202xx_old: kill /proc/ide/pdc202xx
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/pdc202xx_old.h
#   2004/10/23 23:04:45+02:00 bzolnier@trik.(none) +0 -37
#   [ide] pdc202xx_old: kill /proc/ide/pdc202xx
# 
# drivers/ide/pci/pdc202xx_old.c
#   2004/10/23 23:04:45+02:00 bzolnier@trik.(none) +3 -127
#   [ide] pdc202xx_old: kill /proc/ide/pdc202xx
# 
# ChangeSet
#   2004/10/23 22:56:34+02:00 bzolnier@trik.(none) 
#   [ide] pdc202xx_new: kill /proc/ide/pdcnew
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/pdc202xx_new.h
#   2004/10/23 22:56:18+02:00 bzolnier@trik.(none) +0 -2
#   [ide] pdc202xx_new: kill /proc/ide/pdcnew
# 
# drivers/ide/pci/pdc202xx_new.c
#   2004/10/23 22:56:18+02:00 bzolnier@trik.(none) +0 -64
#   [ide] pdc202xx_new: kill /proc/ide/pdcnew
# 
# ChangeSet
#   2004/10/23 22:54:07+02:00 bzolnier@trik.(none) 
#   [ide] hpt366: kill /proc/ide/hpt366
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/hpt366.h
#   2004/10/23 22:53:46+02:00 bzolnier@trik.(none) +0 -2
#   [ide] hpt366: kill /proc/ide/hpt366
# 
# drivers/ide/pci/hpt366.c
#   2004/10/23 22:53:46+02:00 bzolnier@trik.(none) +1 -71
#   [ide] hpt366: kill /proc/ide/hpt366
# 
# ChangeSet
#   2004/10/23 22:51:31+02:00 bzolnier@trik.(none) 
#   [ide] cs5530: kill /proc/ide/cs5530
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/cs5530.c
#   2004/10/23 22:51:16+02:00 bzolnier@trik.(none) +0 -58
#   [ide] cs5530: kill /proc/ide/cs5530
# 
# ChangeSet
#   2004/10/23 22:49:23+02:00 bzolnier@trik.(none) 
#   [ide] cs5520: kill /proc/ide/cs5520
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/cs5520.c
#   2004/10/23 22:48:59+02:00 bzolnier@trik.(none) +5 -69
#   [ide] cs5520: kill /proc/ide/cs5520
# 
# ChangeSet
#   2004/10/23 22:46:33+02:00 bzolnier@trik.(none) 
#   [ide] atiixp: kill /proc/ide/atiixp
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/atiixp.c
#   2004/10/23 22:46:12+02:00 bzolnier@trik.(none) +0 -118
#   [ide] atiixp: kill /proc/ide/atiixp
# 
# ChangeSet
#   2004/10/23 22:43:33+02:00 bzolnier@trik.(none) 
#   [ide] aec62xx: kill /proc/ide/aec62xx
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/pci/aec62xx.h
#   2004/10/23 22:43:19+02:00 bzolnier@trik.(none) +0 -2
#   [ide] aec62xx: kill /proc/ide/aec62xx
# 
# drivers/ide/pci/aec62xx.c
#   2004/10/23 22:43:19+02:00 bzolnier@trik.(none) +2 -108
#   [ide] aec62xx: kill /proc/ide/aec62xx
# 
# ChangeSet
#   2004/10/23 10:07:23-07:00 roland@redhat.com 
#   [PATCH] fix core-dump return code
#   
#   While looking at the signal.c coredumping BUG_ON race, I noticed a bug
#   (not directly related) in do_coredump.  It was setting the "core dumped"
#   flag even when the format dumping hook failed (e.g.  for memory
#   allocation failures).
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/exec.c
#   2004/10/22 21:23:42-07:00 roland@redhat.com +2 -1
#   fix core-dump return code
# 
# ChangeSet
#   2004/10/23 10:07:11-07:00 roland@redhat.com 
#   [PATCH] Fix ptrace problem
#   
#   This is indeed a new bug, and it is not architecture-specific.  In my
#   recent changes to close some race conditions, I overlooked the case of a
#   process using PTRACE_ATTACH on its own children.  The new PT_ATTACHED flag
#   does not really mean "PTRACE_ATTACH was used", it means "PTRACE_ATTACH is
#   changing the ->parent link".
#   
#   This fixes the problem that Stephane Eranian program demonstrates.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/ptrace.c
#   2004/10/22 21:43:20-07:00 roland@redhat.com +2 -1
#   Fix ptrace problem
# 
# ChangeSet
#   2004/10/23 10:06:59-07:00 roland@redhat.com 
#   [PATCH] Invalid BUG_ONs in signal.c
#   
#   Oh, duh.  The race is obvious.  Sorry for the confusion there.
#   
#   The BUG_ON's were useful for debugging, since they trigger on a lot of
#   errors, but they _also_ trigger on some unlikely (but valid) races.
#   
#   So just remove them - just fall through to the regular exit code after
#   core-dumping (which does everything right).
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2004/10/22 21:23:31-07:00 roland@redhat.com +8 -14
#   Invalid BUG_ONs in signal.c
# 
# ChangeSet
#   2004/10/23 19:01:21+02:00 perex@suse.cz 
#   [ALSA]  boot_devs removal - module_param_array() accepts NULL now
#   
#   Intel8x0 driver,RME96 driver,ICE1724 driver,NM256 driver
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/rme96.c
#   2004/10/23 11:12:56+02:00 perex@suse.cz +3 -4
#   [ALSA]  boot_devs removal - module_param_array() accepts NULL now
#   
#   D:2004/10/23 17:12:56
#   C:Intel8x0 driver,RME96 driver,ICE1724 driver,NM256 driver
#   F:pci/intel8x0.c:1.173->1.174 
#   F:pci/rme96.c:1.45->1.46 
#   F:pci/ice1712/ice1724.c:1.46->1.47 
#   F:pci/nm256/nm256.c:1.53->1.54 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/nm256/nm256.c
#   2004/10/23 11:12:56+02:00 perex@suse.cz +1 -2
#   [ALSA]  boot_devs removal - module_param_array() accepts NULL now
#   
#   D:2004/10/23 17:12:56
#   C:Intel8x0 driver,RME96 driver,ICE1724 driver,NM256 driver
#   F:pci/intel8x0.c:1.173->1.174 
#   F:pci/rme96.c:1.45->1.46 
#   F:pci/ice1712/ice1724.c:1.46->1.47 
#   F:pci/nm256/nm256.c:1.53->1.54 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/intel8x0.c
#   2004/10/23 11:12:56+02:00 perex@suse.cz +1 -2
#   [ALSA]  boot_devs removal - module_param_array() accepts NULL now
#   
#   D:2004/10/23 17:12:56
#   C:Intel8x0 driver,RME96 driver,ICE1724 driver,NM256 driver
#   F:pci/intel8x0.c:1.173->1.174 
#   F:pci/rme96.c:1.45->1.46 
#   F:pci/ice1712/ice1724.c:1.46->1.47 
#   F:pci/nm256/nm256.c:1.53->1.54 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/ice1724.c
#   2004/10/23 11:12:56+02:00 perex@suse.cz +4 -5
#   [ALSA]  boot_devs removal - module_param_array() accepts NULL now
#   
#   D:2004/10/23 17:12:56
#   C:Intel8x0 driver,RME96 driver,ICE1724 driver,NM256 driver
#   F:pci/intel8x0.c:1.173->1.174 
#   F:pci/rme96.c:1.45->1.46 
#   F:pci/ice1712/ice1724.c:1.46->1.47 
#   F:pci/nm256/nm256.c:1.53->1.54 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/10/23 09:49:57-07:00 chrisw@osdl.org 
#   [PATCH] delay rq_lock acquisition in setscheduler
#   
#   Doing access control checks with rq_lock held can cause deadlock when
#   audit messages are created (via printk or audit infrastructure) which
#   trigger a wakeup and deadlock, as noted by both SELinux and SubDomain
#   folks.  This patch will let the security checks happen w/out lock held,
#   then re-sample the p->policy in case it was raced. 
#   
#   Originally from John Johansen <johansen@immunix.com>, reworked by me.
#   AFAIK, this version drew no objections from Ingo or Andrea. 
#   
#   From: John Johansen <johansen@immunix.com>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2004/10/21 09:41:23-07:00 chrisw@osdl.org +17 -16
#   delay rq_lock acquisition in setscheduler
# 
# ChangeSet
#   2004/10/23 10:31:03+02:00 perex@suse.cz 
#   Merge
# 
# sound/pci/nm256/nm256.c
#   2004/10/23 10:30:38+02:00 perex@suse.cz +1 -0
#   SCCS merged
# 
# sound/pci/intel8x0.c
#   2004/10/23 10:29:06+02:00 perex@suse.cz +5 -2
#   SCCS merged
# 
# sound/parisc/harmony.c
#   2004/10/23 10:26:42+02:00 perex@suse.cz +0 -9
#   SCCS merged
# 
# sound/parisc/Kconfig
#   2004/10/23 10:26:24+02:00 perex@suse.cz +0 -3
#   SCCS merged
# 
# sound/usb/usx2y/usbusx2y.c
#   2004/10/23 07:45:34+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/usb/usbaudio.c
#   2004/10/23 07:45:34+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/rme9652/rme9652.c
#   2004/10/23 07:45:33+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/rme9652/hdsp.c
#   2004/10/23 07:45:33+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/mixart/mixart.c
#   2004/10/23 07:45:33+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/korg1212/korg1212.c
#   2004/10/23 07:45:32+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/ice1712/ice1724.c
#   2004/10/23 07:45:32+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/ice1712/ice1712.c
#   2004/10/23 07:45:32+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/via82xx.c
#   2004/10/23 07:45:31+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/rme96.c
#   2004/10/23 07:45:31+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/au88x0/au88x0.c
#   2004/10/23 07:45:31+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/rme32.c
#   2004/10/23 07:45:30+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/intel8x0m.c
#   2004/10/23 07:45:30+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/es1968.c
#   2004/10/23 07:45:29+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/ens1370.c
#   2004/10/23 07:45:29+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/cs4281.c
#   2004/10/23 07:45:28+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/bt87x.c
#   2004/10/23 07:45:28+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/atiixp_modem.c
#   2004/10/23 07:45:28+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/atiixp.c
#   2004/10/23 07:45:28+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/isa/es18xx.c
#   2004/10/23 07:45:27+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/drivers/dummy.c
#   2004/10/23 07:45:27+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/core/seq/seq.c
#   2004/10/23 07:45:27+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/core/oss/pcm_oss.c
#   2004/10/23 07:45:27+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/core/memalloc.c
#   2004/10/23 07:45:27+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/22 18:04:49-07:00 david-b@pacbell.net 
#   [PATCH] Missed usb devices on boot
#   
#   This marks sets change_bits to all ones when bringing up a hub, since
#   not all hubs seem to send change events for devices that were plugged in
#   when the hub was reset. 
#   
#   David Miller confirms this fixes his boot-time lost keyboard/mouse
#   problem
# 
# drivers/usb/core/hub.c
#   2004/10/22 01:56:46-07:00 david-b@pacbell.net +1 -0
#   Missed usb devices on boot
# 
# ChangeSet
#   2004/10/22 16:07:33-07:00 davem@nuts.davemloft.net 
#   [ATY]: Fix build on sparc after viro sparse changes.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/22 16:07:19-07: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/serial/console.c
#   2004/10/22 16:07:14-07:00 greg@kroah.com +0 -2
#   Auto merged
# 
# drivers/video/aty/atyfb_base.c
#   2004/10/22 16:07:03-07:00 davem@nuts.davemloft.net +4 -2
#   [ATY]: Fix build on sparc after viro sparse changes.
# 
# ChangeSet
#   2004/10/22 15:54:52-07:00 david-b@pacbell.net 
#   [PATCH] USB ehci: minor debug cleanups
#   
#   This updates debug messages, declaring that labels can be constant strings
#   and changing some old-school dbg() calls to driver model dev_dbg().
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ehci-sched.c
#   2004/10/22 08:03:19-07:00 david-b@pacbell.net +7 -6
#   USB ehci: minor debug cleanups
# 
# drivers/usb/host/ehci-dbg.c
#   2004/10/21 09:19:33-07:00 david-b@pacbell.net +9 -8
#   USB ehci: minor debug cleanups
# 
# ChangeSet
#   2004/10/22 15:54:23-07:00 david-b@pacbell.net 
#   [PATCH] USB ehci: handle earlier endpoint_disable()
#   
#   The recent patch to scrub out ep0 state earlier (to get rid of some of
#   the enumeration problems that started with about 2.6.6) requires EHCI
#   to handle endpoint_disable() calls in a slightly different context.
#   
#   This makes those calls work when an endpoint's QH may still be on the
#   async schedule, rather than already unlinked.  (The QH stays on the async
#   schedule for a few milliseconds after it's empty, since it's routine to
#   issue another request almost immediately.)
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ehci-hcd.c
#   2004/10/22 14:11:55-07:00 david-b@pacbell.net +37 -23
#   USB ehci: handle earlier endpoint_disable()
# 
# ChangeSet
#   2004/10/22 15:53:58-07:00 david-b@pacbell.net 
#   [PATCH] USB ehci: minor pci tweaks
#   
#   This has minor PCI tweaks for the EHCI driver:
#   
#     - If the (nonfunctional) AMD 8111 controller shows up, ignore it.
#       (Patch from Matt Dharm, with minor coding style tweaks).
#   
#     - Delete some code that interprets an EHCI capability code; it
#       should be a PCI capability instead.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ehci-hcd.c
#   2004/10/22 14:11:55-07:00 david-b@pacbell.net +11 -6
#   USB ehci: minor pci tweaks
# 
# ChangeSet
#   2004/10/22 15:43:17-07:00 greg@kroah.com 
#   hotplug: prevent skips in sequence number from happening
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/kobject_uevent.c
#   2004/10/22 15:42:52-07:00 greg@kroah.com +9 -8
#   hotplug: prevent skips in sequence number from happening
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/10/22 15:25:42-07:00 davem@nuts.davemloft.net 
#   [NETFILTER]: Fix ipt_hashlimit build with NETFILTER_DEBUG enabled.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ipt_hashlimit.c
#   2004/10/22 15:25:10-07:00 davem@nuts.davemloft.net +9 -12
#   [NETFILTER]: Fix ipt_hashlimit build with NETFILTER_DEBUG enabled.
# 
# ChangeSet
#   2004/10/22 15:01:24-07:00 tgraf@suug.ch 
#   [PKT_SCHED]: u32: Remove unused hgenerator field in tc_u_hnode.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_u32.c
#   2004/10/22 15:01:02-07:00 tgraf@suug.ch +0 -1
#   [PKT_SCHED]: u32: Remove unused hgenerator field in tc_u_hnode.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/22 14:59:07-07:00 shemminger@osdl.org 
#   [PKT_SCHED]: netem: use timer to handle packets not rescheduling
#   
#   Change the behaviour of netem's delayed packets queue to make it work better
#   with TBF and other rate control disciplines.
#   
#   Now, packets are put in the delayed queue and held there until the next timer interval,
#   then moved to the underlying qdisc. qlen is set to match the available packets in 
#   the underlying discipline (and not count those waiting). Previously, netem would perturb
#   the rate control disciplines because of rescheduling and moving packets in
#   the dequeue handler.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/sch_netem.c
#   2004/10/22 14:58:48-07:00 shemminger@osdl.org +29 -19
#   [PKT_SCHED]: netem: use timer to handle packets not rescheduling
#   
#   Change the behaviour of netem's delayed packets queue to make it work better
#   with TBF and other rate control disciplines.
#   
#   Now, packets are put in the delayed queue and held there until the next timer interval,
#   then moved to the underlying qdisc. qlen is set to match the available packets in 
#   the underlying discipline (and not count those waiting). Previously, netem would perturb
#   the rate control disciplines because of rescheduling and moving packets in
#   the dequeue handler.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/22 14:56:35-07:00 herbert@gondor.apana.org.au 
#   [TCP]: Only re-set TSO size for packet which was TSO to begin with.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_output.c
#   2004/10/22 14:56:16-07:00 herbert@gondor.apana.org.au +2 -1
#   [TCP]: Only re-set TSO size for packet which was TSO to begin with.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2004/10/22 14:30:22-07:00 akpm@osdl.org 
#   [PATCH] kobject_uevent warning fix
#   
#   lib/kobject_uevent.c:39: warning: `action_to_string' defined but not used
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/kobject_uevent.c
#   2004/10/18 21:47:24-07:00 akpm@osdl.org +2 -0
#   kobject_uevent warning fix
# 
# ChangeSet
#   2004/10/22 14:29:57-07:00 akpm@osdl.org 
#   [PATCH] remove cpu_run_sbin_hotplug()
#   
#   From: Keshavamurthy Anil S <anil.s.keshavamurthy@intel.com>
#   
#   Remove cpu_run_sbin_hotplug() - use kobject_hotplug() instead.
#   
#   Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/kobject_uevent.c
#   2004/10/18 21:45:44-07:00 akpm@osdl.org +2 -0
#   remove cpu_run_sbin_hotplug()
# 
# kernel/cpu.c
#   2004/10/18 21:45:44-07:00 akpm@osdl.org +0 -35
#   remove cpu_run_sbin_hotplug()
# 
# include/linux/kobject_uevent.h
#   2004/10/18 21:45:44-07:00 akpm@osdl.org +1 -0
#   remove cpu_run_sbin_hotplug()
# 
# drivers/base/cpu.c
#   2004/10/18 21:45:44-07:00 akpm@osdl.org +2 -0
#   remove cpu_run_sbin_hotplug()
# 
# ChangeSet
#   2004/10/22 14:29:19-07:00 akpm@osdl.org 
#   [PATCH] kobject_hotplug: permit no hotplug_ops
#   
#   Make kobject_hotplug() work even if the kobject's kset doesn't implement any
#   hotplug_ops.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/kobject_uevent.c
#   2004/10/18 21:47:24-07:00 akpm@osdl.org +12 -7
#   kobject_hotplug: permit no hotplug_ops
# 
# ChangeSet
#   2004/10/22 14:01:16-07:00 shemminger@osdl.org 
#   [PATCH] avoid problems with kobject_set_name and name with %
#   
#   kobject_set_name takes a printf style argument list. There are many
#   callers that pass only one string, if this string contained a '%' character
#   than bad things would happen.  The fix is simple.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# kernel/module.c
#   2004/10/08 11:32:52-07:00 shemminger@osdl.org +1 -1
#   avoid problems with kobject_set_name and name with %
# 
# fs/sysfs/dir.c
#   2004/10/08 11:32:52-07:00 shemminger@osdl.org +1 -1
#   avoid problems with kobject_set_name and name with %
# 
# drivers/pci/hotplug/pci_hotplug_core.c
#   2004/10/08 11:32:52-07:00 shemminger@osdl.org +1 -1
#   avoid problems with kobject_set_name and name with %
# 
# drivers/firmware/efivars.c
#   2004/10/08 11:32:52-07:00 shemminger@osdl.org +1 -1
#   avoid problems with kobject_set_name and name with %
# 
# drivers/base/core.c
#   2004/10/08 11:32:52-07:00 shemminger@osdl.org +1 -1
#   avoid problems with kobject_set_name and name with %
# 
# drivers/base/class.c
#   2004/10/08 11:32:52-07:00 shemminger@osdl.org +2 -2
#   avoid problems with kobject_set_name and name with %
# 
# drivers/base/bus.c
#   2004/10/08 11:32:52-07:00 shemminger@osdl.org +2 -2
#   avoid problems with kobject_set_name and name with %
# 
# ChangeSet
#   2004/10/22 13:55:29-07:00 shemminger@osdl.org 
#   [PATCH] cdev: protect against buggy drivers
#   
#   Here is a better fix (thanks Greg) that allows long names for character
#   device objects.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# fs/char_dev.c
#   2004/10/08 11:14:29-07:00 shemminger@osdl.org +2 -2
#   cdev: protect against buggy drivers
# 
# ChangeSet
#   2004/10/22 13:37:30-07:00 greg@kroah.com 
#   Merge kroah.com:/home/greg/linux/BK/bleed-2.6
#   into kroah.com:/home/greg/linux/BK/driver-2.6
# 
# lib/Makefile
#   2004/10/22 13:37:23-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/22 21:12:37+01:00 rmk@flint.arm.linux.org.uk 
#   [PCMCIA] Fix PCMCIA behaviour on resume with different card.
#   
#   PCMCIA checks the card CIS against its cached copy.  If it finds
#   that the card does not match, it destroys the bindings with existing
#   drivers, issues an remove event followed by an insert event.  However,
#   ds.c delays the remove event by 100ms, so cardmgr sees the insert
#   before remove.  It thereby ignores the new card.
#   
#   Also, we ended up leaving the fake CIS intact, so the new card appears
#   to be described by the fake CIS.  Destroy the fake CIS in addition to
#   the CIS cache.
# 
# drivers/pcmcia/cs.c
#   2004/10/22 21:09:33+01:00 rmk@flint.arm.linux.org.uk +8 -4
#   Move fake CIS destruction into cistpl.c
#   Report via debug whether the CIS verification was successful on resume.
#   Wait 200ms before sending a new card insertion event.
# 
# drivers/pcmcia/cistpl.c
#   2004/10/22 21:09:32+01:00 rmk@flint.arm.linux.org.uk +8 -0
#   When we destroy the CIS cache, also destroy the fake CIS as well.
# 
# ChangeSet
#   2004/10/22 11:08:47-07:00 oliver@neukum.org 
#   [PATCH] kaweth: no need for packed
#   
#   there was an uneeded packed attribute for a data structure.
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/kaweth.c
#   2004/10/21 16:18:11-07:00 oliver@neukum.org +1 -1
#   kaweth: no need for packed
# 
# ChangeSet
#   2004/10/22 11:08:25-07:00 oliver@neukum.org 
#   [PATCH] kaweth: full conversion to usb_unlink_urb
#   
#   kaweth used its own synchronisation superseded by usb_unlink_urb().
#   
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/kaweth.c
#   2004/10/21 15:41:12-07:00 oliver@neukum.org +3 -10
#   kaweth: full conversion to usb_unlink_urb
# 
# ChangeSet
#   2004/10/22 11:08:03-07:00 david-b@pacbell.net 
#   [PATCH] USB input Kconfig updates
#   
#   This tweaks the USB input driver support, notably fixing a botched
#   dependency that makes all the USB drivers appear strangely in Kconfig.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/Kconfig
#   2004/10/21 08:19:30-07:00 david-b@pacbell.net +5 -6
#   USB input Kconfig updates
# 
# ChangeSet
#   2004/10/22 11:07:37-07:00 bunk@stusta.de 
#   [PATCH] USB: fix usb/serial/console.c compile error
#   
#   The following compile error seems to come from Linus' tree:
#   
#   
#   <--  snip  -->
#   
#   ...
#     CC      drivers/usb/serial/bus.o
#     CC      drivers/usb/serial/console.o
#   drivers/usb/serial/console.c: In function `usb_console_write':
#   drivers/usb/serial/console.c:221: warning: passing arg 3 of pointer to function makes integer from pointer without a cast
#   drivers/usb/serial/console.c:221: error: too many arguments to function
#   drivers/usb/serial/console.c:223: warning: passing arg 3 of `usb_serial_generic_write' makes integer from pointer without a cast
#   drivers/usb/serial/console.c:223: error: too many arguments to function `usb_serial_generic_write'
#   make[3]: *** [drivers/usb/serial/console.o] Error 1
#   
#   <--  snip  -->
#   
#   
#   This was caused by the changed "write" in usb_serial_device_type.
#   
#   
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/console.c
#   2004/10/22 06:12:59-07:00 bunk@stusta.de +2 -2
#   USB: fix usb/serial/console.c compile error
# 
# ChangeSet
#   2004/10/22 11:07:15-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB device init: implement the Windows scheme
#   
#   This patch implements the Windows scheme for USB device initialization.
#   It also incorporates the change recently posted by David to scrub the
#   endpoint state following a SET-ADDRESS.  Other noteworthy changes:
#   
#   	There are two new module parameters to control whether the
#   	old scheme or the new one is used first and whether the other
#   	scheme is tried if the first one fails.  Default settings are
#   	to use the new scheme only.
#   
#   	hub_set_address() returns 0 immediately if the device is already
#   	in the USB_STATE_ADDRESS state.
#   
#   	On the first attempt to read the device descriptor the code
#   	uses a short 1-second timeout.  This ought to help prevent
#   	full-speed devices with an 8- or 16-byte maxpacket from
#   	slowing the procedure down by NAKing the unexpectedly early
#   	status stage of the transfer.
#   
#   	For debugging, the ep0 maxpacket value is printed.  It might
#   	be a good idea to validate it rather than just believing the
#   	device -- although I haven't heard of any device providing
#   	an incorrect value other than 0.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/urb.c
#   2004/10/21 08:00:16-07:00 stern@rowland.harvard.edu +4 -5
#   USB device init: implement the Windows scheme
# 
# drivers/usb/core/hub.c
#   2004/10/21 14:48:17-07:00 stern@rowland.harvard.edu +135 -38
#   USB device init: implement the Windows scheme
# 
# ChangeSet
#   2004/10/22 11:06:49-07:00 janitor@sternwelten.at 
#   [PATCH] USB: dabusb: replace schedule_timeout() with msleep_interruptible()
#   
#   Description: Use msleep_interruptible() instead of schedule_timeout()
#   so that the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/media/dabusb.c
#   2004/10/20 17:41:59-07:00 janitor@sternwelten.at +1 -2
#   USB: dabusb: replace schedule_timeout() with msleep_interruptible()
# 
# ChangeSet
#   2004/10/22 11:06:26-07:00 janitor@sternwelten.at 
#   [PATCH] USB: tiglusb: replace schedule_timeout() with msleep_interruptible()
#   
#   Description: Use msleep_interruptible() instead of schedule_timeout() to
#   guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/tiglusb.c
#   2004/10/20 17:42:00-07:00 janitor@sternwelten.at +1 -2
#   USB: tiglusb: replace schedule_timeout() with msleep_interruptible()
# 
# ChangeSet
#   2004/10/22 19:18:21+02:00 bzolnier@trik.(none) 
#   [ide] kill /proc/ide/ide?/config
#   
#   * writes to PCI config space are non-functional since 2.4.21
#   * reads of full PCI config space are allowed for normal users
#   * I'm not aware of any applications using this interface
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/ide-proc.c
#   2004/10/22 19:17:03+02:00 bzolnier@trik.(none) +0 -257
#   [ide] kill /proc/ide/ide?/config
# 
# ChangeSet
#   2004/10/22 19:10:29+02:00 bzolnier@trik.(none) 
#   [ide] kill ide_hwif_t->ide_dma_verbose
#   
#   * make __ide_dma_verbose() void and drop "__" prefix
#   * ide_dma_verbose() is always available now
#   * use it instead of ide_hwif_t->ide_dma_verbose
#   * sgiioc4.c version reported wrong mode
#   * icside.c version repeated info given by ->ide_dma_check()
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# include/linux/ide.h
#   2004/10/22 18:12:35+02:00 bzolnier@trik.(none) +2 -2
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/ppc/pmac.c
#   2004/10/22 18:12:34+02:00 bzolnier@trik.(none) +0 -1
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/pci/siimage.c
#   2004/10/22 18:12:34+02:00 bzolnier@trik.(none) +0 -7
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/pci/sgiioc4.c
#   2004/10/22 18:12:35+02:00 bzolnier@trik.(none) +0 -12
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/ide.c
#   2004/10/22 18:12:34+02:00 bzolnier@trik.(none) +0 -1
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/ide-dma.c
#   2004/10/22 18:12:35+02:00 bzolnier@trik.(none) +12 -14
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/ide-disk.c
#   2004/10/22 18:12:35+02:00 bzolnier@trik.(none) +1 -1
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/ide-cd.c
#   2004/10/22 18:12:35+02:00 bzolnier@trik.(none) +2 -3
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# drivers/ide/arm/icside.c
#   2004/10/22 18:12:35+02:00 bzolnier@trik.(none) +0 -9
#   [ide] kill ide_hwif_t->ide_dma_verbose
# 
# ChangeSet
#   2004/10/22 19:06:43+02:00 bzolnier@trik.(none) 
#   [ide] ide-scsi: simplify+speedup DMA support
#   
#   * add hwif->sg_mapped flag
#   * add idescsi_map_sg() converting scsi_cmd->sg into
#     hwif->sg_table (this removes need for rq->bio)
#   * remove code (de)allocating rq->bio
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# include/linux/ide.h
#   2004/10/22 01:46:25+02:00 bzolnier@trik.(none) +1 -0
#   [ide] ide-scsi: simplify+speedup DMA support
# 
# drivers/scsi/ide-scsi.c
#   2004/10/22 01:46:25+02:00 bzolnier@trik.(none) +49 -92
#   [ide] ide-scsi: simplify+speedup DMA support
# 
# drivers/ide/ide-io.c
#   2004/10/22 01:46:25+02:00 bzolnier@trik.(none) +9 -3
#   [ide] ide-scsi: simplify+speedup DMA support
# 
# ChangeSet
#   2004/10/22 19:04:21+02:00 bzolnier@trik.(none) 
#   [ide] kill ide_raw_build_sglist()
#   
#   ide_build_sglist() can be now used for REQ_DRIVE_TASKFILE requests.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# include/linux/ide.h
#   2004/10/22 19:03:55+02:00 bzolnier@trik.(none) +0 -1
#   [ide] kill ide_raw_build_sglist()
# 
# drivers/ide/ppc/pmac.c
#   2004/10/22 19:03:55+02:00 bzolnier@trik.(none) +2 -5
#   [ide] kill ide_raw_build_sglist()
# 
# drivers/ide/pci/sgiioc4.c
#   2004/10/22 19:03:55+02:00 bzolnier@trik.(none) +1 -4
#   [ide] kill ide_raw_build_sglist()
# 
# drivers/ide/ide-dma.c
#   2004/10/22 19:03:55+02:00 bzolnier@trik.(none) +4 -35
#   [ide] kill ide_raw_build_sglist()
# 
# ChangeSet
#   2004/10/22 18:51:08+02:00 bzolnier@trik.(none) 
#   [ide] use ide_map_sg()
#   
#   * make Etrax ide.c, icside.c and ide-dma.c use ide_map_sg()
#   * use one sg for REQ_DRIVE_TASKFILE requests in ide-dma.c
#     (no reason for 128 sectors per sg limit)
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/ide-dma.c
#   2004/10/22 18:50:48+02:00 bzolnier@trik.(none) +7 -23
#   [ide] use ide_map_sg()
# 
# drivers/ide/arm/icside.c
#   2004/10/22 18:50:48+02:00 bzolnier@trik.(none) +7 -22
#   [ide] use ide_map_sg()
# 
# arch/cris/arch-v10/drivers/ide.c
#   2004/10/22 18:50:48+02:00 bzolnier@trik.(none) +2 -8
#   [ide] use ide_map_sg()
# 
# ChangeSet
#   2004/10/22 18:20:30+02:00 bzolnier@trik.(none) 
#   [ide] pmac: kill pmac_ide_[raw_]build_sglist()
#   
#   Just use ide_dma_[raw_]build_sglist() from ide-dma.c.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/ppc/pmac.c
#   2004/10/22 18:20:10+02:00 bzolnier@trik.(none) +2 -52
#   [ide] pmac: kill pmac_ide_[raw_]build_sglist()
# 
# ChangeSet
#   2004/10/21 18:47:50-04:00 hannal@us.ibm.com 
#   [PATCH] hw_random.c: replace pci_find_device
#   
#   As pci_find_device is going away I've replaced it with pci_get_device.
#   for_each_pci_dev is a macro wrapper around pci_get_device.
#   If someone with this hardware could test it I would appreciate it.
#   
#   Thanks.
#   
#   Hanna Linder
#   IBM Linux Technology Center
#   
#   Signed-off-by: Hanna Linder <hannal@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/char/hw_random.c
#   2004/10/20 17:52:42-04:00 hannal@us.ibm.com +1 -1
#   hw_random.c: replace pci_find_device
# 
# ChangeSet
#   2004/10/21 15:38:41-07:00 sri@us.ibm.com 
#   [SCTP] Fix HEARTBEAT_ACKs being sent to wrong dest. ip address in a
#   multi-homing scenario after a failback.
#   
#   Signed-off-by: Jorge Hernandez-Herrero <jhh@lucent.com>
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
# 
# net/sctp/outqueue.c
#   2004/10/21 15:38:30-07:00 sri@us.ibm.com +12 -3
#   [SCTP] Fix HEARTBEAT_ACKs being sent to wrong dest. ip address in a
#   multi-homing scenario after a failback.
# 
# ChangeSet
#   2004/10/21 15:32:54-07:00 sri@us.ibm.com 
#   [SCTP] When an address is deleted, update any transports that are caching it as a source adddress.
#   
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
# 
# net/sctp/sm_make_chunk.c
#   2004/10/21 15:32:42-07:00 sri@us.ibm.com +8 -0
#   [SCTP] When an address is deleted, update any transports that are caching it as a source adddress.
# 
# ChangeSet
#   2004/10/21 15:28:41-07:00 sri@us.ibm.com 
#   [SCTP] Update cwnd/ssthresh as per the sctpimpguide modifications.
#   
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
# 
# net/sctp/transport.c
#   2004/10/21 15:28:29-07:00 sri@us.ibm.com +14 -13
#   [SCTP] Update cwnd/ssthresh as per the sctpimpguide modifications.
# 
# net/sctp/associola.c
#   2004/10/21 15:28:29-07:00 sri@us.ibm.com +4 -3
#   [SCTP] Update cwnd/ssthresh as per the sctpimpguide modifications.
# 
# ChangeSet
#   2004/10/21 15:21:31-07:00 sri@us.ibm.com 
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
#   
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
# 
# net/sctp/ulpevent.c
#   2004/10/21 15:21:19-07:00 sri@us.ibm.com +36 -2
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
# 
# net/sctp/socket.c
#   2004/10/21 15:21:18-07:00 sri@us.ibm.com +47 -0
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
# 
# net/sctp/sm_statefuns.c
#   2004/10/21 15:21:18-07:00 sri@us.ibm.com +59 -0
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
# 
# net/sctp/sm_make_chunk.c
#   2004/10/21 15:21:17-07:00 sri@us.ibm.com +23 -0
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
# 
# include/net/sctp/ulpevent.h
#   2004/10/21 15:21:17-07:00 sri@us.ibm.com +3 -0
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
# 
# include/net/sctp/structs.h
#   2004/10/21 15:21:17-07:00 sri@us.ibm.com +6 -0
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
# 
# include/linux/sctp.h
#   2004/10/21 15:21:16-07:00 sri@us.ibm.com +5 -1
#   [SCTP] Adaption layer indication support.
#   
#   Add support for SCTP_ADAPTION_INDICATION notification, SCTP_ADAPTION_LAYER
#   socket option and SCTP_PARAM_ADAPTION_LAYER_IND parameter.
# 
# ChangeSet
#   2004/10/21 15:18:18-07:00 sri@us.ibm.com 
#   [SCTP] Change sctp_assoc_t to a sized type(s32).
#   
#   Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
# 
# net/sctp/socket.c
#   2004/10/21 15:18:06-07:00 sri@us.ibm.com +1 -1
#   [SCTP] Change sctp_assoc_t to a sized type(s32).
# 
# net/sctp/associola.c
#   2004/10/21 15:18:06-07:00 sri@us.ibm.com +3 -3
#   [SCTP] Change sctp_assoc_t to a sized type(s32).
# 
# include/net/sctp/user.h
#   2004/10/21 15:18:06-07:00 sri@us.ibm.com +1 -1
#   [SCTP] Change sctp_assoc_t to a sized type(s32).
# 
# include/net/sctp/sctp.h
#   2004/10/21 15:18:05-07:00 sri@us.ibm.com +1 -1
#   [SCTP] Change sctp_assoc_t to a sized type(s32).
# 
# ChangeSet
#   2004/10/21 13:31:40-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB file-storage gadget: clean up endian issues
#   
#   This patch adds the __le16 data types to the file-storage gadget and
#   removes some erroneous conversions to little-endian order.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/file_storage.c
#   2004/10/20 07:25:24-07:00 stern@rowland.harvard.edu +15 -15
#   USB file-storage gadget: clean up endian issues
# 
# ChangeSet
#   2004/10/21 13:29:33-07:00 david-b@pacbell.net 
#   [PATCH] USB: net2280 compile fixes
#   
#   Fix some compiler warnings that came up with net2280 on processors with
#   64bit dma_addr-t ... one of them would have been a bug on big-endian CPUs.
#   (Thanks to Randy Dunlap for reporting these.)
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/net2280.h
#   2004/10/15 13:26:59-07:00 david-b@pacbell.net +4 -4
#   USB: net2280 compile fixes
# 
# drivers/usb/gadget/net2280.c
#   2004/10/15 13:34:35-07:00 david-b@pacbell.net +6 -3
#   USB: net2280 compile fixes
# 
# ChangeSet
#   2004/10/21 13:29:21-07:00 david-b@pacbell.net 
#   [PATCH] USB: omap_udc updates
#   
#   This is a collection of updates to the OMAP UDC driver.
#   
#     - OMAP-1510 support, including DMA (the DMA controller isn't quite
#       the same as on newer chips) but not double buffering.
#   
#     - Some PIO work:
#   
#         * fix some races that showed up on OMAP-1510
#   
#         * tracking down annoying PIO-OUT lossage and making double buffering
#           start to behave (needed as fallback if all DMA channels are in use).
#   
#     - DMA-IN works on both 1510 and 16xx
#   
#   Plus minor cleanups.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/omap_udc.h
#   2004/10/21 09:19:33-07:00 david-b@pacbell.net +4 -2
#   USB: omap_udc updates
# 
# drivers/usb/gadget/omap_udc.c
#   2004/10/21 09:19:33-07:00 david-b@pacbell.net +245 -90
#   USB: omap_udc updates
# 
# ChangeSet
#   2004/10/21 13:29:07-07:00 david-b@pacbell.net 
#   [PATCH] USB: ohci module param for broken bios
#   
#   This patch provides a way to work around especially broken BIOS/SMM
#   implementations which claim they support the OS-handoff handshake
#   but actually don't.  It's confirmed that this resolves some OSDL bug
#   (ID isn't handy just now).
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/ohci-hcd.c
#   2004/10/12 06:24:03-07:00 david-b@pacbell.net +6 -1
#   USB: ohci module param for broken bios
# 
# ChangeSet
#   2004/10/21 13:28:54-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb error code docs
#   
#   This has various updates to the USB error code documentation that I've
#   had floating around.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# Documentation/usb/error-codes.txt
#   2004/10/21 11:17:34-07:00 david-b@pacbell.net +28 -15
#   USB: usb error code docs
# 
# ChangeSet
#   2004/10/21 13:28:41-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb/hcd kconfig updates
#   
#   This updates the dependencies of the HCDs and host-side USB so that:
#   
#    - Options for PCI-only HCDs (UHCI and, for now, EHCI) only appear
#      systems that actually have PCI.
#   
#    - Adding non-PCI bus glue support for another OHCI adapter doesn't
#      need involve changing the main USB Kconfig anymore.
#   
#    - Minor tweaks to the OMAP support, so OMAP 17xx and 24xx don't need
#      additional Kconfig changes and so the H3/17xx gets the ISP1301 too.
#   
#   This still tries to hide host-side USB config options on systems that
#   don't offer USB.  While currently convenient, that's a losing proposition
#   in the long term:  host controllers on chips like SL811 and TD243 can be
#   put onto any custom board.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/Kconfig
#   2004/10/21 10:36:59-07:00 david-b@pacbell.net +22 -4
#   USB: usb/hcd kconfig updates
# 
# drivers/usb/Kconfig
#   2004/10/21 10:13:54-07:00 david-b@pacbell.net +1 -1
#   USB: usb/hcd kconfig updates
# 
# ChangeSet
#   2004/10/21 13:28:29-07:00 david-b@pacbell.net 
#   [PATCH] USB: goku_udc sparse updates
#   
#   This is a bunch of "sparse" fixes for goku_udc.  One of these might be
#   an issue on some systems for code that explicitly halts IN endpoints
#   (like file_storage) if normal memory access doesn't work for PCI.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/goku_udc.h
#   2004/10/21 09:19:33-07:00 david-b@pacbell.net +4 -4
#   USB: goku_udc sparse updates
# 
# drivers/usb/gadget/goku_udc.c
#   2004/10/21 09:19:33-07:00 david-b@pacbell.net +76 -73
#   USB: goku_udc sparse updates
# 
# ChangeSet
#   2004/10/21 12:51:05-07:00 greg@kroah.com 
#   Merge gregkh@kernel.bkbits.net:linux/usb-2.6
#   into kroah.com:/home/greg/linux/BK/usb-2.6
# 
# drivers/usb/serial/visor.c
#   2004/10/21 12:51:02-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# drivers/usb/serial/usb-serial.c
#   2004/10/21 12:51:02-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# drivers/usb/serial/pl2303.c
#   2004/10/21 12:51:02-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# drivers/usb/serial/cyberjack.c
#   2004/10/21 12:51:02-07:00 greg@kroah.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/20 16:49:07-07:00 stern@rowland.harvard.edu 
#   [PATCH] USB Gadget: Use proper BCD values
#   
#   This updates an earlier patch that added bcdDevice values for a new
#   USB peripheral controller.  The values weren't valid BCD numbers.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/gadget/zero.c
#   2004/10/20 07:01:08-07:00 stern@rowland.harvard.edu +1 -1
#   USB Gadget: Use proper BCD values
# 
# drivers/usb/gadget/file_storage.c
#   2004/10/20 07:00:56-07:00 stern@rowland.harvard.edu +1 -1
#   USB Gadget: Use proper BCD values
# 
# drivers/usb/gadget/ether.c
#   2004/10/20 07:01:03-07:00 stern@rowland.harvard.edu +1 -1
#   USB Gadget: Use proper BCD values
# 
# ChangeSet
#   2004/10/20 16:37:46-07:00 shemminger@osdl.org 
#   [PATCH] USB kaweth: use alloc_etherdev to allocate device private data - fix
#   
#   Goof found by compile warning.
#   
#   
#   From: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/kaweth.c
#   2004/10/19 15:07:25-07:00 shemminger@osdl.org +1 -1
#   USB kaweth: use alloc_etherdev to allocate device private data - fix
# 
# ChangeSet
#   2004/10/20 16:37:27-07:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet patch (new ax8817x device)
#   
#   This patch enables usage of another USB2 100BASE-T adapter.
#   http://www.corega.co.jp/product/list/lanadp/feusb2tx.htm
#   
#   From:          Naoki Shibata <zupae234@yahoo.co.jp>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/usbnet.c
#   2004/10/20 16:30:29-07:00 david-b@pacbell.net +4 -0
#   USB: usbnet patch (new ax8817x device)
# 
# ChangeSet
#   2004/10/20 16:37:08-07:00 dale@farnsworth.org 
#   [PATCH] USB: USB fixes for non-cache-coherent processors
#   
#   I posted this before, but didn't see any discussion.
#   
#   This patch fixes a couple of places where the usb subsystem
#   DMAs to/from local (stack) variables.  This doesn't work on
#   non-cache-coherent processors.  I'm testing on PPC 4xx systems.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/message.c
#   2004/10/01 12:16:40-07:00 dale@farnsworth.org +13 -3
#   USB: USB fixes for non-cache-coherent processors
# 
# drivers/usb/class/audio.c
#   2004/10/01 12:16:40-07:00 dale@farnsworth.org +11 -2
#   USB: USB fixes for non-cache-coherent processors
# 
# ChangeSet
#   2004/10/20 16:36:50-07:00 stern@rowland.harvard.edu 
#   [PATCH] UHCI: No bandwidth reclamation during enumeration
#   
#   A few devices prefer not to have full-speed bandwidth reclamation turned
#   on while they are being enumerated.  In particular this seems to be true
#   for the USB Bluetooth adapters built in to some laptop models (used for
#   remote keyboards).  This patch alters the UHCI driver so that control URBs
#   for devices still in the USB_STATE_DEFAULT state will be placed on the
#   low-speed queue rather than the full-speed queue.  Since the low-speed
#   queue isn't subject to bandwidth reclamation the devices will work
#   properly.  The negative impact on other devices is minimal; the process of
#   device initialization will be slowed down by a few milliseconds.
#   
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/host/uhci-hcd.c
#   2004/10/14 10:25:46-07:00 stern@rowland.harvard.edu +6 -2
#   UHCI: No bandwidth reclamation during enumeration
# 
# ChangeSet
#   2004/10/20 16:36:31-07:00 shemminger@osdl.org 
#   [PATCH] usbnet: use alloc_etherdev to allocate private data
#   
#   In order for network device lifetime stuff to work properly, it is necessary
#   for devices to allocate private data as part of alloc_etherdev.
#   Also, netdev_priv() is improvement over dereferencing netdev->priv
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/usbnet.c
#   2004/10/19 09:44:03-07:00 shemminger@osdl.org +31 -35
#   usbnet: use alloc_etherdev to allocate private data
# 
# ChangeSet
#   2004/10/20 16:36:12-07:00 shemminger@osdl.org 
#   [PATCH] kaweth: use alloc_etherdev to allocate device private
#   
#   Change other usb network driver to use alloc_etherdev to allocate the
#   private data structure. And use netdev_priv to find it.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Oliver Neukum <oliver@neukum.name>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/net/kaweth.c
#   2004/10/19 10:39:56-07:00 shemminger@osdl.org +47 -72
#   kaweth: use alloc_etherdev to allocate device private
# 
# ChangeSet
#   2004/10/20 16:14:25-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb suspend support for hid-core
#   
#   Basic HID driver support for USB suspend/resume.  At least one keyboard
#   works OK as a remote wakeup source ... unless you write the sysfs
#   power/state attribute using that USB keyboard, in which case the input
#   subsystem reports an endless stream of newlines!  :)
#   
#   Someone still needs to implement some configurable timer to support the
#   "suspend idle mice/keyboards/..." policy for devices that can issue
#   wakeup events.  In conjunction with autosuspend policies in hub and
#   HCD (UHCI) code, that could allegedly save 2W of power by enabling the
#   C3 state on Centrino laptops that use USB mice.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/input/hid-core.c
#   2004/10/01 12:12:41-07:00 david-b@pacbell.net +27 -0
#   USB: usb suspend support for hid-core
# 
# ChangeSet
#   2004/10/20 16:14:05-07:00 david-b@pacbell.net 
#   [PATCH] USB: usb hub descriptor fetch needs retries
#   
#   Some of the recent changes to change how descriptors are read have managed
#   to confuse one USB keyboard.  It recovers OK with a few retries though.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/core/hub.c
#   2004/10/01 10:18:19-07:00 david-b@pacbell.net +11 -3
#   USB: usb hub descriptor fetch needs retries
# 
# ChangeSet
#   2004/10/20 16:13:46-07:00 lkml@lievin.net 
#   [PATCH] USB: tiglusb.c: add direct USB support on some new TI handhelds
#   
#   I have extended my driver to add support of the embedded USB port provided by
#   some new Texas Instruments' handhelds. Things are the same except for the
#   maximum packet size.
#   
#   Description: add support of the USB port embedded on some new TI handhelds (TI84+ and TI89 Titanium).
#   
#   Thanks, Romain.
#   
#   Signed-off-by: Romain Lievin <lkml@lievin.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/ticable.h
#   2004/09/26 06:25:53-07:00 lkml@lievin.net +2 -0
#   USB: tiglusb.c: add direct USB support on some new TI handhelds
# 
# drivers/usb/misc/tiglusb.h
#   2004/09/26 06:27:17-07:00 lkml@lievin.net +2 -6
#   USB: tiglusb.c: add direct USB support on some new TI handhelds
# 
# drivers/usb/misc/tiglusb.c
#   2004/09/26 06:39:34-07:00 lkml@lievin.net +42 -16
#   USB: tiglusb.c: add direct USB support on some new TI handhelds
# 
# Documentation/usb/silverlink.txt
#   2004/09/26 06:16:15-07:00 lkml@lievin.net +4 -2
#   USB: tiglusb.c: add direct USB support on some new TI handhelds
# 
# ChangeSet
#   2004/10/20 16:13:25-07:00 lcapitulino@conectiva.com.br 
#   [PATCH] USB: Module version info for Belkin_sa.
#   
#    Add module version information for usb/serial/belkin_sa.c.
#   
#   
#   Signed-off-by: Luiz Capitulino <lcapitulino@conectiva.com.br>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/belkin_sa.c
#   2004/09/25 13:27:57-07:00 lcapitulino@conectiva.com.br +1 -0
#   USB: Module version info for Belkin_sa.
# 
# ChangeSet
#   2004/10/20 16:13:07-07:00 lcapitulino@conectiva.com.br 
#   [PATCH] USB: Module version info for PL2303.
#   
#    Add module version information for usb/serial/pl2303.c.
#   
#   
#   Signed-off-by: Luiz Capitulino <lcapitulino@conectiva.com.br>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/pl2303.c
#   2004/09/25 13:16:56-07:00 lcapitulino@conectiva.com.br +1 -0
#   USB: Module version info for PL2303.
# 
# ChangeSet
#   2004/10/20 16:12:48-07:00 lcapitulino@conectiva.com.br 
#   [PATCH] USB: Module version info for CyberJack.
#   
#    Add module version information for drivers/usb/serial/cyberjack.c.
#   
#   
#   Signed-off-by: Luiz Capitulino <lcapitulino@conectiva.com.br>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/cyberjack.c
#   2004/09/27 17:51:53-07:00 lcapitulino@conectiva.com.br +1 -0
#   USB: Module version info for CyberJack.
# 
# ChangeSet
#   2004/10/20 16:12:29-07:00 zaitcev@redhat.com 
#   [PATCH] USB: usblp BKL removal
#   
#   the appended patch is not in yet, what gives? I sent it to Marcelo with
#   an understanding that it would be in Linus tree any day now. It was a couple
#   of months ago. It's not just BKL witchhunt either. I remember that it fixed
#   an oops, although I do not remember the precise scenario by now (it had
#   something to do with a race between ->release and ->disconnect).
#   
#   
#   From: Pete Zaitcev <zaitcev@redhat.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/class/usblp.c
#   2004/10/04 17:15:43-07:00 zaitcev@redhat.com +8 -8
#   USB: usblp BKL removal
# 
# ChangeSet
#   2004/10/20 16:12:08-07:00 rco3@2005dauphin.org 
#   [PATCH] USB: PL2303 - PharosGPS patch
#   
#   This patch adds recognition/support for the PharosGPS puck, as included with
#   Microsoft's Streets and Trips package.  The device has an inline
#   USB-to-serial converter which functions as a PL2303 but with different
#   VENDOR_ID and PRODUCT_ID, and so the PL2303 driver is modified to recognize
#   this additional device.
#   
#   Signed-off by: Robert C. Olsen, III [pl2303@2005dauphin.org]
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/pl2303.h
#   2004/10/01 06:53:56-07:00 rco3@2005dauphin.org +3 -0
#   USB: PL2303 - PharosGPS patch
# 
# drivers/usb/serial/pl2303.c
#   2004/10/01 06:50:59-07:00 rco3@2005dauphin.org +1 -0
#   USB: PL2303 - PharosGPS patch
# 
# ChangeSet
#   2004/10/20 16:11:49-07:00 philippe.bertin@pandora.be 
#   [PATCH] USB: Superfluous statement in usb.c
# 
# drivers/usb/core/usb.c
#   2004/10/06 12:46:34-07:00 philippe.bertin@pandora.be +0 -2
#   USB: Superfluous statement in usb.c
# 
# ChangeSet
#   2004/10/20 16:11:28-07:00 luca.risolia@studio.unibo.it 
#   [PATCH] USB: W996[87]CF driver updates
#   
#   Small W996[87]CF documentation updates.
#   
#   Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
# 
# drivers/usb/media/w9968cf.h
#   2004/10/08 06:03:21-07:00 luca.risolia@studio.unibo.it +1 -1
#   USB: W996[87]CF driver updates
# 
# MAINTAINERS
#   2004/10/08 06:04:18-07:00 luca.risolia@studio.unibo.it +2 -2
#   USB: W996[87]CF driver updates
# 
# Documentation/usb/w9968cf.txt
#   2004/10/08 06:19:58-07:00 luca.risolia@studio.unibo.it +27 -24
#   USB: W996[87]CF driver updates
# 
# ChangeSet
#   2004/10/20 16:11:09-07:00 stern@rowland.harvard.edu 
#   [PATCH] usbcore: drop reference to bus on allocation error
#   
#   A recent patch introduced this reference counting leak.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
#   
#   
#   ===== drivers/usb/core/usb.c 1.293 vs edited =====
# 
# drivers/usb/core/usb.c
#   2004/10/08 10:05:23-07:00 stern@rowland.harvard.edu +1 -0
#   usbcore: drop reference to bus on allocation error
# 
# ChangeSet
#   2004/10/20 16:10:49-07:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: Fix queuecommand() for disconnected devices
#   
#   Following the recommendation of James Bottomley (of SCSI fame), this patch
#   changes the queuecommand() routine so that when a command is received for a
#   disconnected device, instead of accepting the command and then ignoring it,
#   we fail the command immediately with DID_NO_CONNECT.
#   
#   This fixes a timeout-abort-oops sequence that would occur when the
#   higher-level drivers (mostly the CD driver) try to queue a SYNCHRONIZE
#   CACHE command during scsi_remove_host().
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
#   
#   
#   ===== drivers/usb/storage/scsiglue.c 1.84 vs edited =====
# 
# drivers/usb/storage/scsiglue.c
#   2004/09/30 13:07:33-07:00 mdharm-usb@one-eyed-alien.net +10 -3
#   USB Storage: Fix queuecommand() for disconnected devices
# 
# ChangeSet
#   2004/10/20 15:38:19-07:00 greg@kroah.com 
#   kobject: add CONFIG_DEBUG_KOBJECT
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/kobject.c
#   2004/10/20 15:38:09-07:00 greg@kroah.com +1 -3
#   kobject: add CONFIG_DEBUG_KOBJECT
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/Makefile
#   2004/10/20 15:38:09-07:00 greg@kroah.com +5 -1
#   kobject: add CONFIG_DEBUG_KOBJECT
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/Kconfig.debug
#   2004/10/20 15:38:09-07:00 greg@kroah.com +7 -0
#   kobject: add CONFIG_DEBUG_KOBJECT
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/10/20 15:33:03-07:00 greg@kroah.com 
#   USB: fix DoS in the visor driver by rate limiting sends.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/visor.c
#   2004/10/20 15:32:53-07:00 greg@kroah.com +69 -12
#   USB: fix DoS in the visor driver by rate limiting sends.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/10/20 15:32:01-07:00 greg@kroah.com 
#   USB: fix build error in the USB core if CONFIG_PROCFS is disabled 
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/proc_fs.h
#   2004/10/20 15:31:50-07:00 greg@kroah.com +1 -0
#   USB: fix build error in the USB core if CONFIG_PROCFS is disabled 
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/10/20 15:31:02-07:00 greg@kroah.com 
#   USB: remove unneeded checks in the usb-serial core.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/serial/usb-serial.c
#   2004/10/20 15:30:52-07:00 greg@kroah.com +12 -24
#   USB: remove unneeded checks in the usb-serial core.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/10/20 15:30:06-07:00 greg@kroah.com 
#   USB: add phidgetkit driver.
#   
#   originally written by Sean Young <sean@mess.org> but with LED additions and
#   cleanups from me.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/phidgetkit.c
#   2004/10/20 15:29:55-07:00 greg@kroah.com +581 -0
# 
# drivers/usb/misc/phidgetkit.c
#   2004/10/20 15:29:55-07:00 greg@kroah.com +0 -0
#   BitKeeper file /home/greg/linux/BK/usb-2.6/drivers/usb/misc/phidgetkit.c
# 
# drivers/usb/misc/Makefile
#   2004/10/20 15:29:55-07:00 greg@kroah.com +2 -1
#   USB: add phidgetkit driver.
#   
#   originally written by Sean Young <sean@mess.org> but with LED additions and
#   cleanups from me.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/usb/misc/Kconfig
#   2004/10/20 15:29:55-07:00 greg@kroah.com +10 -0
#   USB: add phidgetkit driver.
#   
#   originally written by Sean Young <sean@mess.org> but with LED additions and
#   cleanups from me.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/10/20 15:28:22-07:00 greg@kroah.com 
#   USB: update devices.txt with the proper USB minor number information.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# Documentation/devices.txt
#   2004/10/20 15:28:12-07:00 greg@kroah.com +17 -6
#   USB: update devices.txt with the proper USB minor number information.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2004/10/20 21:36:17+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Enable ip6t_frag.c to work without skb_linearize()
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_frag.c
#   2004/10/20 21:35:34+02:00 yasuyuki.kozakai@toshiba.co.jp +31 -29
#   [NETFILTER]: Enable ip6t_frag.c to work without skb_linearize()
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/20 21:33:37+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Enable ip6t_multiport.c to work without skb_linearize()
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_multiport.c
#   2004/10/20 21:33:00+02:00 yasuyuki.kozakai@toshiba.co.jp +18 -13
#   [NETFILTER]: Enable ip6t_multiport.c to work without skb_linearize()
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/20 21:27:38+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Enable ip6t_rt.c to work without skb_linearize()
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
# 
# net/ipv6/netfilter/ip6t_rt.c
#   2004/10/20 21:26:53+02:00 yasuyuki.kozakai@toshiba.co.jp +59 -62
#   [NETFILTER]: Enable ip6t_rt.c to work without skb_linearize()
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
# 
# ChangeSet
#   2004/10/20 20:45:50+02:00 kaber@coreworks.de 
#   Merge coreworks.de:/home/kaber/src/nf/nf-post-2.6.9
#   into coreworks.de:/home/kaber/src/nf/nf-2.6
# 
# net/ipv6/netfilter/ip6t_rt.c
#   2004/10/20 20:45:30+02:00 kaber@coreworks.de +0 -0
#   Auto merged
# 
# net/ipv6/netfilter/ip6t_multiport.c
#   2004/10/20 20:45:30+02:00 kaber@coreworks.de +0 -0
#   Auto merged
# 
# net/ipv6/netfilter/ip6t_frag.c
#   2004/10/20 20:45:30+02:00 kaber@coreworks.de +0 -0
#   Auto merged
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/10/20 20:45:30+02:00 kaber@coreworks.de +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/20 20:33:06+02:00 perex@suse.cz 
#   Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5
#   into suse.cz:/home/perex/bk/linux-sound/linux-sound
# 
# sound/core/init.c
#   2004/10/20 20:32:42+02:00 perex@suse.cz +0 -1
#   Auto merged
# 
# ChangeSet
#   2004/10/20 20:27:59+02:00 kaber@coreworks.de 
#   [NETFILTER]: Select source address for gateway in MASQUERADE
#   
#   Suggested by Herbert Xu <herbert@gondor.apana.org.au>
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ipt_MASQUERADE.c
#   2004/10/20 20:26:59+02:00 kaber@coreworks.de +3 -1
#   [NETFILTER]: Select source address for gateway in MASQUERADE
#   
#   Suggested by Herbert Xu <herbert@gondor.apana.org.au>
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/20 14:14:29+02:00 perex@suse.cz 
#   [ALSA]  Fix non-blocking write in ALSA OSS emulation
#   
#   ALSA<-OSS emulation
#   write() calls in non-blocking mode eat the written data and never
#   return -EAGAIN.  The attached patch fixes the problem.
#   
#   Signed-off-by: Benjamin Otte <otte@gnome.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/oss/pcm_oss.c
#   2004/10/18 10:42:06+02:00 perex@suse.cz +6 -6
#   [ALSA]  Fix non-blocking write in ALSA OSS emulation
#   
#   D:2004/10/18 16:42:06
#   C:ALSA<-OSS emulation
#   F:core/oss/pcm_oss.c:1.78->1.79 
#   L:write() calls in non-blocking mode eat the written data and never
#   L:return -EAGAIN.  The attached patch fixes the problem.
#   Signed-off-by: Benjamin Otte <otte@gnome.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:13:41+02:00 perex@suse.cz 
#   [ALSA]  PCM boundary fix in 32bit compat layer
#   
#   IOCTL32 emulation
#   PCM boundary size is fixed within the 32bit value range when HW_PARAMS
#   ioctl is called in 32bit mode.
#   Also, with this patch, the conversion functions are inlined.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/pcm32.c
#   2004/10/18 09:55:51+02:00 perex@suse.cz +64 -4
#   [ALSA]  PCM boundary fix in 32bit compat layer
#   
#   D:2004/10/18 15:55:51
#   C:IOCTL32 emulation
#   F:core/ioctl32/hwdep32.c:1.8->1.9 
#   F:core/ioctl32/ioctl32.c:1.22->1.23 
#   F:core/ioctl32/ioctl32.h:1.15->1.16 
#   F:core/ioctl32/pcm32.c:1.21->1.22 
#   L:PCM boundary size is fixed within the 32bit value range when HW_PARAMS
#   L:ioctl is called in 32bit mode.
#   L:Also, with this patch, the conversion functions are inlined.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/ioctl32.h
#   2004/10/18 09:55:51+02:00 perex@suse.cz +2 -2
#   [ALSA]  PCM boundary fix in 32bit compat layer
#   
#   D:2004/10/18 15:55:51
#   C:IOCTL32 emulation
#   F:core/ioctl32/hwdep32.c:1.8->1.9 
#   F:core/ioctl32/ioctl32.c:1.22->1.23 
#   F:core/ioctl32/ioctl32.h:1.15->1.16 
#   F:core/ioctl32/pcm32.c:1.21->1.22 
#   L:PCM boundary size is fixed within the 32bit value range when HW_PARAMS
#   L:ioctl is called in 32bit mode.
#   L:Also, with this patch, the conversion functions are inlined.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/ioctl32.c
#   2004/10/18 09:55:51+02:00 perex@suse.cz +3 -3
#   [ALSA]  PCM boundary fix in 32bit compat layer
#   
#   D:2004/10/18 15:55:51
#   C:IOCTL32 emulation
#   F:core/ioctl32/hwdep32.c:1.8->1.9 
#   F:core/ioctl32/ioctl32.c:1.22->1.23 
#   F:core/ioctl32/ioctl32.h:1.15->1.16 
#   F:core/ioctl32/pcm32.c:1.21->1.22 
#   L:PCM boundary size is fixed within the 32bit value range when HW_PARAMS
#   L:ioctl is called in 32bit mode.
#   L:Also, with this patch, the conversion functions are inlined.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/hwdep32.c
#   2004/10/18 09:55:51+02:00 perex@suse.cz +1 -1
#   [ALSA]  PCM boundary fix in 32bit compat layer
#   
#   D:2004/10/18 15:55:51
#   C:IOCTL32 emulation
#   F:core/ioctl32/hwdep32.c:1.8->1.9 
#   F:core/ioctl32/ioctl32.c:1.22->1.23 
#   F:core/ioctl32/ioctl32.h:1.15->1.16 
#   F:core/ioctl32/pcm32.c:1.21->1.22 
#   L:PCM boundary size is fixed within the 32bit value range when HW_PARAMS
#   L:ioctl is called in 32bit mode.
#   L:Also, with this patch, the conversion functions are inlined.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:12:54+02:00 perex@suse.cz 
#   [ALSA]  Add VIA8237 driver type
#   
#   VIA82xx driver
#   VIA8237 and later chips are handled as a different type from VIA8233,
#   since they don't support the AC97 slot mapping any more.
#   The alsa-lib will resolve the 5.1 remapping for them.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2004/10/18 09:54:00+02:00 perex@suse.cz +4 -0
#   [ALSA]  Add VIA8237 driver type
#   
#   D:2004/10/18 15:54:00
#   C:VIA82xx driver
#   F:pci/via82xx.c:1.124->1.125 
#   L:VIA8237 and later chips are handled as a different type from VIA8233,
#   L:since they don't support the AC97 slot mapping any more.
#   L:The alsa-lib will resolve the 5.1 remapping for them.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:12:07+02:00 perex@suse.cz 
#   [ALSA]  Exclude uneeded code when ! CONFIG_PROC_FS
#   
#   PCM Midlevel,AC97 Codec Core
#   From Michal Rokos <michal@rokos.info>
#   
#   I tried to compile without procfs support and I got few 'unused code'
#   warnings.
#   
#   This patch fixes it.
#   
#   Tested by compilation only. (With CONFIG_PROC_FS on and off)
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_local.h
#   2004/10/18 08:01:40+02:00 perex@suse.cz +7 -0
#   [ALSA]  Exclude uneeded code when ! CONFIG_PROC_FS
#   
#   D:2004/10/18 14:01:40
#   C:PCM Midlevel,AC97 Codec Core
#   F:core/pcm.c:1.46->1.47 
#   F:pci/ac97/Makefile:1.14->1.15 
#   F:pci/ac97/ac97_local.h:1.7->1.8 
#   L:From Michal Rokos <michal@rokos.info>
#   L:
#   L:I tried to compile without procfs support and I got few 'unused code'
#   L:warnings.
#   L:
#   L:This patch fixes it.
#   L:
#   L:Tested by compilation only. (With CONFIG_PROC_FS on and off)
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/Makefile
#   2004/10/18 08:01:40+02:00 perex@suse.cz +6 -1
#   [ALSA]  Exclude uneeded code when ! CONFIG_PROC_FS
#   
#   D:2004/10/18 14:01:40
#   C:PCM Midlevel,AC97 Codec Core
#   F:core/pcm.c:1.46->1.47 
#   F:pci/ac97/Makefile:1.14->1.15 
#   F:pci/ac97/ac97_local.h:1.7->1.8 
#   L:From Michal Rokos <michal@rokos.info>
#   L:
#   L:I tried to compile without procfs support and I got few 'unused code'
#   L:warnings.
#   L:
#   L:This patch fixes it.
#   L:
#   L:Tested by compilation only. (With CONFIG_PROC_FS on and off)
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm.c
#   2004/10/18 08:01:40+02:00 perex@suse.cz +2 -1
#   [ALSA]  Exclude uneeded code when ! CONFIG_PROC_FS
#   
#   D:2004/10/18 14:01:40
#   C:PCM Midlevel,AC97 Codec Core
#   F:core/pcm.c:1.46->1.47 
#   F:pci/ac97/Makefile:1.14->1.15 
#   F:pci/ac97/ac97_local.h:1.7->1.8 
#   L:From Michal Rokos <michal@rokos.info>
#   L:
#   L:I tried to compile without procfs support and I got few 'unused code'
#   L:warnings.
#   L:
#   L:This patch fixes it.
#   L:
#   L:Tested by compilation only. (With CONFIG_PROC_FS on and off)
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:11:20+02:00 perex@suse.cz 
#   [ALSA]  Fix AC97_EXTENDED_STATUS initialial value
#   
#   AC97 Codec Core
#   Fixed a bug to write an invalid initial value of AC97_EXTENDED_STATUS.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/10/13 04:26:12+02:00 perex@suse.cz +5 -2
#   [ALSA]  Fix AC97_EXTENDED_STATUS initialial value
#   
#   D:2004/10/13 10:26:12
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_codec.c:1.151->1.152 
#   L:Fixed a bug to write an invalid initial value of AC97_EXTENDED_STATUS.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:10:33+02:00 perex@suse.cz 
#   [ALSA]  Fixed SPDIF on CS4298
#   
#   AC97 Codec Core
#   Fixed SPDIF support on CS4298 AC97 chip.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/10/13 04:22:48+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fixed SPDIF on CS4298
#   
#   D:2004/10/13 10:22:48
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_codec.c:1.150->1.151 
#   L:Fixed SPDIF support on CS4298 AC97 chip.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:09:47+02:00 perex@suse.cz 
#   [ALSA]  fix build in !KMOD case (sequencer)
#   
#   ALSA sequencer
#   seq_device.c needs to pull in the snd_seq_autoload_lock()/unlock()
#   defines from seq_kernel.h in the !KMOD case.
#   
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/seq/seq_device.c
#   2004/10/12 01:17:43+02:00 perex@suse.cz +1 -0
#   [ALSA]  fix build in !KMOD case (sequencer)
#   
#   D:2004/10/12 07:17:43
#   C:ALSA sequencer
#   F:core/seq/seq_device.c:1.17->1.18 
#   L:seq_device.c needs to pull in the snd_seq_autoload_lock()/unlock()
#   L:defines from seq_kernel.h in the !KMOD case.
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/10/20 14:09:00+02:00 perex@suse.cz 
#   [ALSA]  RME9632 precise_ptr fix
#   
#   RME HDSP driver
#   Correct hardware position mask to mask correctly when buffer is not
#   maximum size.
#   
#   Signed-off-by:  Ed Wildgoose <lists@wildgooses.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2004/10/11 05:28:09+02:00 perex@suse.cz +1 -3
#   [ALSA]  RME9632 precise_ptr fix
#   
#   D:2004/10/11 11:28:09
#   C:RME HDSP driver
#   F:pci/rme9652/hdsp.c:1.71->1.72 
#   L:Correct hardware position mask to mask correctly when buffer is not
#   L:maximum size.
#   Signed-off-by:  Ed Wildgoose <lists@wildgooses.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:08:13+02:00 perex@suse.cz 
#   [ALSA]  Misc. volume fixes
#   
#   ICE1712 driver
#    - Added mute function to Master/Front/Rear/Side/LFE/CEnter
#    - Master volume is artificially made in software
#    - Added PCM volume control (basically what was the master volume)
#    - Front/Read/Side/LFE/Center is now logarithmic (and computed as <volume> * <master volume> / <maximum volume>)
#   
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1712.h
#   2004/10/11 05:15:49+02:00 perex@suse.cz +5 -1
#   [ALSA]  Misc. volume fixes
#   
#   D:2004/10/11 11:15:49
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.21->1.22 
#   F:pci/ice1712/ice1712.h:1.25->1.26 
#   L: - Added mute function to Master/Front/Rear/Side/LFE/CEnter
#   L: - Master volume is artificially made in software
#   L: - Added PCM volume control (basically what was the master volume)
#   L: - Front/Read/Side/LFE/Center is now logarithmic (and computed as <volume> * <master volume> / <maximum volume>)
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/aureon.c
#   2004/10/11 05:15:49+02:00 perex@suse.cz +295 -77
#   [ALSA]  Misc. volume fixes
#   
#   D:2004/10/11 11:15:49
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.21->1.22 
#   F:pci/ice1712/ice1712.h:1.25->1.26 
#   L: - Added mute function to Master/Front/Rear/Side/LFE/CEnter
#   L: - Master volume is artificially made in software
#   L: - Added PCM volume control (basically what was the master volume)
#   L: - Front/Read/Side/LFE/Center is now logarithmic (and computed as <volume> * <master volume> / <maximum volume>)
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:07:27+02:00 perex@suse.cz 
#   [ALSA]  Add routing/volume of ADAT I/O on EWS88D
#   
#   ICE1712 driver
#   The routing/volume control of ADAT I/O on EWS88D is added.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ews.c
#   2004/10/11 05:08:07+02:00 perex@suse.cz +4 -1
#   [ALSA]  Add routing/volume of ADAT I/O on EWS88D
#   
#   D:2004/10/11 11:08:07
#   C:ICE1712 driver
#   F:pci/ice1712/ews.c:1.20->1.21 
#   L:The routing/volume control of ADAT I/O on EWS88D is added.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 14:04:46+02:00 perex@suse.cz 
#   [ALSA]  fixing a two-rme32-in-one-machine bug
#       
#   RME32 driver
#       - fixing the dev counter in snd_rme32_probe(). The patch can enable a second
#         rme32 card
#   
#   Signed-off-by: Martin Langer <martin-langer@gmx.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme32.c
#   2004/10/07 07:58:41+02:00 perex@suse.cz +5 -7
#   [ALSA]  fixing a two-rme32-in-one-machine bug
#   
#   RME32 driver
#   - fixing the dev counter in snd_rme32_probe(). The patch can enable a second
#     rme32 card now.
#   
#   Signed-off-by: Martin Langer <martin-langer@gmx.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/20 00:47:18-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] ixgb: Configuration and user guide update
#   
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
# 
# drivers/net/Kconfig
#   2004/10/07 18:52:27-04:00 ganesh.venkatesan@intel.com +2 -8
#   ixgb: Configuration and user guide update
# 
# Documentation/networking/ixgb.txt
#   2004/10/07 18:51:47-04:00 ganesh.venkatesan@intel.com +12 -25
#   ixgb: Configuration and user guide update
# 
# ChangeSet
#   2004/10/20 00:47:07-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100: Configuration and user guide update
#   
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
# 
# drivers/net/Kconfig
#   2004/10/07 18:52:27-04:00 ganesh.venkatesan@intel.com +5 -54
#   e100: Configuration and user guide update
# 
# Documentation/networking/e100.txt
#   2004/10/07 18:51:33-04:00 ganesh.venkatesan@intel.com +127 -11
#   e100: Configuration and user guide update
# 
# ChangeSet
#   2004/10/20 00:46:56-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000: Configuration and user guide update
#   
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
# 
# drivers/net/Kconfig
#   2004/10/07 18:52:27-04:00 ganesh.venkatesan@intel.com +2 -23
#   e1000: Configuration and user guide update
# 
# Documentation/networking/e1000.txt
#   2004/10/07 18:51:15-04:00 ganesh.venkatesan@intel.com +154 -65
#   e1000: Configuration and user guide update
# 
# ChangeSet
#   2004/10/20 00:44:45-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100: Driver version number update
#   
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
# 
# drivers/net/e100.c
#   2004/10/15 15:27:01-04:00 ganesh.venkatesan@intel.com +1 -1
#   e100: Driver version number update
# 
# ChangeSet
#   2004/10/20 00:44:35-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100: Fix set ringparam for ethtool returning error code on bad input
#   
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
# 
# drivers/net/e100.c
#   2004/10/15 15:27:01-04:00 ganesh.venkatesan@intel.com +3 -0
#   e100: Fix set ringparam for ethtool returning error
# 
# ChangeSet
#   2004/10/20 00:44:25-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100: Fix loss of connectivity to BMC when interface
#   is brought down.
#   
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
# 
# drivers/net/e100.c
#   2004/10/15 15:27:01-04:00 ganesh.venkatesan@intel.com +0 -10
#   e100: Fix loss of connectivity to BMC when interface
# 
# ChangeSet
#   2004/10/20 00:41:25-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/e100
# 
# drivers/net/e100.c
#   2004/10/20 00:41:22-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/19 15:49:43+02:00 kaber@coreworks.de 
#   [NETFILTER]: Convert ip6t_physdev match function to new argument order
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_physdev.c
#   2004/10/19 15:49:12+02:00 kaber@coreworks.de +1 -2
#   [NETFILTER]: Convert ip6t_physdev match function to new argument order
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:21:00+02:00 kaber@coreworks.de 
#   [NETFILTER]: ip6t_esp.c whitespace cleanup
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_esp.c
#   2004/10/19 02:20:32+02:00 kaber@coreworks.de +36 -38
#   [NETFILTER]: ip6t_esp.c whitespace cleanup
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:19:33+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Enable ip6t_esp.c to work without skb_linearize()
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_esp.c
#   2004/10/19 02:19:06+02:00 yasuyuki.kozakai@toshiba.co.jp +12 -10
#   [NETFILTER]: Enable ip6t_esp.c to work without skb_linearize()
#   
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:18:14+02:00 kaber@coreworks.de 
#   [NETFILTER]: Introduce tabs to ip6t_ah.c
#   
#   Fix horrible indentation, not a single tab in the file.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_ah.c
#   2004/10/19 02:17:48+02:00 kaber@coreworks.de +130 -134
#   [NETFILTER]: Introduce tabs to ip6t_ah.c
#   
#   Fix horrible indentation, not a single tab in the file.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:16:42+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Enable ip6t_ah.c to work without skb_linearize()
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_ah.c
#   2004/10/19 02:16:15+02:00 yasuyuki.kozakai@toshiba.co.jp +9 -7
#   [NETFILTER]: Enable ip6t_ah.c to work without skb_linearize()
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:15:21+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: Enable ip6t_LOG.c to work without skb_linearize()
#   
#   This patch enables ip6t_LOG.c to work without skb_linearize().
#   
#   I changed a large part of this file. At first, ip6_nexthdr() is deleted
#   to prevent multiple call of skb_header_pointer() at dump_packet() and
#   ip6_nexthdr().
#      
#   And the following bugs are fixed. The first bug is fixed by introducing
#   skb_header_pointer(), then I didn't separate patches.
#   
#       - No check with skb->len. Then invalid memory access may occur.
#   
#       - If packet is fragmented and it's not first fragment, nonexistent
#         extension headers is tried to parse.
#   
#       - All headers which aren't TCP/UDP/ICMPv6 are treated as IPv6
#         extension header.
#     
#       - The encrypted data after ESP is tried to parse.
#      
#       - ntohl() for ID in Fragment header is missing.
#      
#       - If doff*4 of TCP header is less than sizeof(struct tcphdr),
#         TCP options are tried to parse.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_LOG.c
#   2004/10/19 02:14:54+02:00 yasuyuki.kozakai@toshiba.co.jp +178 -99
#   [NETFILTER]: Enable ip6t_LOG.c to work without skb_linearize()
#   
#   This patch enables ip6t_LOG.c to work without skb_linearize().
#   
#   I changed a large part of this file. At first, ip6_nexthdr() is deleted
#   to prevent multiple call of skb_header_pointer() at dump_packet() and
#   ip6_nexthdr().
#      
#   And the following bugs are fixed. The first bug is fixed by introducing
#   skb_header_pointer(), then I didn't separate patches.
#   
#       - No check with skb->len. Then invalid memory access may occur.
#   
#       - If packet is fragmented and it's not first fragment, nonexistent
#         extension headers is tried to parse.
#   
#       - All headers which aren't TCP/UDP/ICMPv6 are treated as IPv6
#         extension header.
#     
#       - The encrypted data after ESP is tried to parse.
#      
#       - ntohl() for ID in Fragment header is missing.
#      
#       - If doff*4 of TCP header is less than sizeof(struct tcphdr),
#         TCP options are tried to parse.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:13:27+02:00 yasuyuki.kozakai@toshiba.co.jp 
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_rt.c
#   2004/10/19 02:13:00+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_owner.c
#   2004/10/19 02:13:00+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_multiport.c
#   2004/10/19 02:13:00+02:00 yasuyuki.kozakai@toshiba.co.jp +3 -4
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_mark.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_mac.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_limit.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_length.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_ipv6header.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_hl.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -1
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_hbh.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_frag.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_eui64.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_esp.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_dst.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_ah.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -2
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_MARK.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -1
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6t_LOG.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +1 -1
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6_tables.c
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +122 -132
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# include/linux/netfilter_ipv6/ip6_tables.h
#   2004/10/19 02:12:59+02:00 yasuyuki.kozakai@toshiba.co.jp +8 -4
#   [NETFILTER]: prearation of removing skb_linearize()
#      
#   This patch uses skb_header_pointer() so that packets can be parsed even though
#   skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
#   yet. We can remove it after changing all match/target modules.
#      
#   Moreover ...
#       - I deleted the optimization not to parse IPv6 extension header
#         many time from previous patch. I'll send the patch to do this
#         separately.
#       - fixed the bug that "offset" argument of match functions are always 0.
#       - deleted "hdr" and "datalen" argument and added "protoff" argument
#         to match functions. "protoff" means the offset to Layer 4 protocol
#         header.
#       - the argument order of target function is changed likely IPv4 modules.
#         This prevents user from meeting kernel panic when they use old
#         match modules.
#       - changed {tcp,udp,icmp6}_match(). These functions became very similar
#         to codes in ip_tables.c again.
#      
#   Signed-off-by: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:08:50+02:00 rusty@rustcorp.com.au 
#   [NETFILTER]: Change MASQUERADE to Use Device Address Directly
#   
#   Instead of doing a dubious route lookup, just use the first IP address
#   of the (dynamic) interface.  Also, reset assured bit so after masq
#   connections can be cleaned up if memory pressure.
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ipt_MASQUERADE.c
#   2004/10/19 02:08:24+02:00 rusty@rustcorp.com.au +18 -29
#   [NETFILTER]: Change MASQUERADE to Use Device Address Directly
#   
#   Instead of doing a dubious route lookup, just use the first IP address
#   of the (dynamic) interface.  Also, reset assured bit so after masq
#   connections can be cleaned up if memory pressure.
#   
#   Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/19 02:06:42+02:00 pablo@eurodev.net 
#   [NETFILTER]: Clean up ip_conntrack stats
#   
#   Signed-off-by: Pablo Neira <pablo@eurodev.net>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_conntrack_core.c
#   2004/10/19 02:06:14+02:00 pablo@eurodev.net +2 -4
#   [NETFILTER]: Clean up ip_conntrack stats
#   
#   Signed-off-by: Pablo Neira <pablo@eurodev.net>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2004/10/17 11:48:59+02:00 vda@port.imtp.ilyichevsk.odessa.ua 
#   kbuild: make gcc -align options .config-settable
#   
#   With all alignment options set to 1 (minimum alignment),
#   I've got 5% smaller vmlinux compared to one built with
#   default code alignment.
#   Original implementation altered to use cc-option-align by sam.
#   
#   From: Denis Vlasenko <vda@port.imtp.ilyichevsk.odessa.ua>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# init/Kconfig
#   2004/10/17 02:03:21+02:00 vda@port.imtp.ilyichevsk.odessa.ua +37 -0
#   kbuild: make gcc -align options .config-settable
# 
# Makefile
#   2004/10/17 11:44:55+02:00 vda@port.imtp.ilyichevsk.odessa.ua +7 -0
#   kbuild: make gcc -align options .config-settable
# 
# ChangeSet
#   2004/10/17 11:41:54+02:00 sam@mars.ravnborg.org 
#   kbuild: Add cc-option-align
#   
#   gcc version >= 3.00 shifted from -malign-* to -falign-*. $(cc-option-align) will
#   based on current gcc version specify the right prefix for the align option.
#   Documented in Documentation/makefiles.txt
#   
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# arch/i386/Makefile
#   2004/10/17 11:41:36+02:00 sam@mars.ravnborg.org +1 -1
#   Use cc-option-align from top-level Makefile
# 
# Makefile
#   2004/10/17 11:41:36+02:00 sam@mars.ravnborg.org +5 -0
#   Introduced cc-option-align
# 
# Documentation/kbuild/makefiles.txt
#   2004/10/17 11:41:36+02:00 sam@mars.ravnborg.org +15 -0
#   Documented cc-option-align
# 
# ChangeSet
#   2004/10/17 02:01:07+02:00 sam@mars.ravnborg.org 
#   kbuild: explicit enable framepointer
#   
#   Newer gcc versions automatically turns on -fomit-frame-pointer when
#   -O2 is specified thus breaking CONFIG_FRAME_POINTER option.
#   Explicitly specifying -fno-omit-frame-pointer fixes it.
#   
#   From: Tejun Heo <tj@home-tj.org>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# Makefile
#   2004/10/17 02:00:48+02:00 sam@mars.ravnborg.org +3 -1
#   Newer gcc versions automatically turns on -fomit-frame-pointer when
#   -O2 is specified thus breaking CONFIG_FRAME_POINTER option.
#   Explicitly specifying -fno-omit-frame-pointer fixes it.
# 
# ChangeSet
#   2004/10/17 01:55:32+02:00 sam@mars.ravnborg.org 
#   kbuild: use two double-quotes for localversion
#   
#   Modifies LOCALVERSION definition such that it uses
#   patsubst instead of subst to remove surrounding double quotes from
#   CONFIG_LOCALVERSION.  This helps syntax-highlighting editors.
#   
#   From: Tejun Heo <tj@home-tj.org>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# Makefile
#   2004/10/17 01:55:11+02:00 sam@mars.ravnborg.org +1 -1
#   Use two double qutes so editors do not get confused
# 
# ChangeSet
#   2004/10/17 01:17:08+02:00 sam@mars.ravnborg.org 
#   kbuild: Create Makefile in output dir for *config targets
#   
#   Upon request from Andi Kleen the Makefile is now created for *config
#   targets also. So the MAkefile in the output directory is present when
#   it is expected (after kernel configuration).
#   Also tell user the Makefile is generated.
#   
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# Makefile
#   2004/10/17 01:16:51+02:00 sam@mars.ravnborg.org +19 -14
#   Create a Makefile in output directory for *config targets and
#   tell user a Makefile is generated.
# 
# ChangeSet
#   2004/10/16 23:51:27+02:00 trini@kernel.crashing.org 
#   kbuild: fix 'htmldocs' and friends with O=
#   
#   The following patch fixes up 'htmldocs' and related to work when
#   trees are being built with O=.  I fixed it all up by passing the srctree
#   as an env-var to docproc (and thus what it calls) and then pull that out
#   when needed.
#   
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# scripts/kernel-doc
#   2004/10/16 02:00:00+02:00 trini@kernel.crashing.org +1 -1
#   kbuild: fix 'htmldocs' and friends with O=
# 
# scripts/basic/docproc.c
#   2004/10/16 02:00:00+02:00 trini@kernel.crashing.org +15 -4
#   kbuild: fix 'htmldocs' and friends with O=
# 
# Documentation/DocBook/Makefile
#   2004/10/16 02:00:00+02:00 trini@kernel.crashing.org +5 -2
#   kbuild: fix 'htmldocs' and friends with O=
# 
# ChangeSet
#   2004/10/16 23:48:22+02:00 agruen@suse.de 
#   kbuild: Allow install of external modules to custom path
#   
#   Currently, a ``make modules_install'' for an external module will
#   install that module into /lib/modules/$(uname -r)/extra. Allow to
#   override this default by specifying INSTALL_MOD_DIR.
#   
#   Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# scripts/Makefile.modinst
#   2004/10/16 02:00:00+02:00 agruen@suse.de +4 -1
#   kbuild: Allow install of external modules to custom path
# 
# ChangeSet
#   2004/10/16 23:26:48+02:00 rddunlap@osdl.org 
#   kconfig: OVERRIDE: save kernel version in .config file
#   
#   Omit .config file timestamp in the file if the environment variable
#   "KCONFIG_NOTIMESTAMP" exists and is non-null.
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# scripts/kconfig/confdata.c
#   2004/09/17 18:31:23+02:00 rddunlap@osdl.org +12 -4
#   kconfig: OVERRIDE: save kernel version in .config file
# 
# ChangeSet
#   2004/10/16 23:03:11+02:00 vda@port.imtp.ilyichevsk.odessa.ua 
#   kconfig.debug: mention that DEBUG_SLAB can slow down machine quite a bit
#   
#   I experienced x3 slowdown due to this option being set.
#   
#   Please add this small warning to DEBUG_SLAB help text.
#   
#   Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
# 
# lib/Kconfig.debug
#   2004/09/16 13:19:28+02:00 vda@port.imtp.ilyichevsk.odessa.ua +1 -1
#   kconfig.debug: mention that DEBUG_SLAB can slow down machine quite a bit
# 
# ChangeSet
#   2004/10/15 19:54:22-04:00 rddunlap@osdl.org 
#   [PATCH] skfp: remove assignment expression in conditional (sparse)(v2)
#   
#   Fix sparse warning:
#   drivers/net/skfp/hwmtm.c:1904:20: warning: assignment expression in
#   conditional
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
# 
# drivers/net/skfp/hwmtm.c
#   2004/10/15 17:47:42-04:00 rddunlap@osdl.org +2 -1
#   skfp: remove assignment expression in conditional (sparse)(v2)
# 
# ChangeSet
#   2004/10/15 19:53:37-04:00 shemminger@osdl.org 
#   [PATCH] slip: use netdev_priv
#   
#   Replace dev->priv with netdev_priv(dev)
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/slip.c
#   2004/10/15 15:35:54-04:00 shemminger@osdl.org +16 -18
#   slip: use netdev_priv
# 
# ChangeSet
#   2004/10/15 19:53:24-04:00 shemminger@osdl.org 
#   [PATCH] slip: use module_param
#   
#   Replace MODULE_PARM with module_param (also make slip_maxdev static).
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/slip.c
#   2004/10/15 15:34:30-04:00 shemminger@osdl.org +3 -2
#   slip: use module_param
# 
# ChangeSet
#   2004/10/15 19:52:15-04:00 shemminger@osdl.org 
#   [PATCH] tg3: make driver only data static
#   
#   Several data structures should have been marked static because
#   the are local to this driver.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tg3.c
#   2004/10/15 15:57:56-04:00 shemminger@osdl.org +6 -6
#   tg3: make driver only data static
# 
# ChangeSet
#   2004/10/15 19:52:02-04:00 shemminger@osdl.org 
#   [PATCH] tg3: use netdev_priv
#   
#   use netdev_priv
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tg3.c
#   2004/10/15 15:19:26-04:00 shemminger@osdl.org +2 -2
#   tg3: use netdev_priv
# 
# ChangeSet
#   2004/10/15 19:51:49-04:00 shemminger@osdl.org 
#   [PATCH] tg3: use module_param
#   
#   get rid of deprecated use of MODULE_PARM
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tg3.c
#   2004/10/15 15:19:54-04:00 shemminger@osdl.org +3 -3
#   tg3: use module_param
# 
# ChangeSet
#   2004/10/15 19:44:57-04:00 shemminger@osdl.org 
#   [PATCH] dummy: use netdev_priv
#   
#   Can use netdev_priv in dummy device.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/dummy.c
#   2004/10/15 17:25:11-04:00 shemminger@osdl.org +2 -2
#   dummy: use netdev_priv
# 
# ChangeSet
#   2004/10/15 19:44:44-04:00 shemminger@osdl.org 
#   [PATCH] eql: use netdev_priv
#   
#   Use netdev_priv where possible.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/eql.c
#   2004/10/15 17:26:15-04:00 shemminger@osdl.org +13 -13
#   eql: use netdev_priv
# 
# ChangeSet
#   2004/10/15 19:43:15-04:00 shemminger@osdl.org 
#   [PATCH] ns83820: use module_param
#   
#   Replace MODULE_PARM with module_param
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/ns83820.c
#   2004/10/15 18:05:25-04:00 shemminger@osdl.org +5 -4
#   ns83820: use module_param
# 
# ChangeSet
#   2004/10/15 19:13:34-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/linux-2.6
#   into pobox.com:/spare/repo/netdev-2.6/janitor
# 
# drivers/net/3c59x.c
#   2004/10/15 19:13:31-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/15 15:31:42-04:00 bunk@stusta.de 
#   [PATCH] net/tokenring/olympic.c: remove unused variable
#   
#   Recent changes in Linus' tree removed all uses of a variable, resulteing
#   in the following warning:
#   
#   <--  snip  -->
#   
#   ...
#     CC      drivers/net/tokenring/olympic.o
#   drivers/net/tokenring/olympic.c: In function `olympic_arb_cmd':
#   drivers/net/tokenring/olympic.c:1404: warning: unused variable `i'
#   ...
#   
#   <--  snip  -->
#   
#   
#   The following patch removes this unused variable:
#   
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
# 
# drivers/net/tokenring/olympic.c
#   2004/10/07 16:53:15-04:00 bunk@stusta.de +0 -1
#   net/tokenring/olympic.c: remove unused variable
# 
# ChangeSet
#   2004/10/15 15:27:16-04:00 linville@tuxdriver.com 
#   [PATCH] 3c59x: style change in vortex_ethtool_ops declaration
#   
#   Style change suggested during patch review.
#   
#   Signed-off-by: John W. Linville <linville@tuxdriver.com>
# 
# drivers/net/3c59x.c
#   2004/10/14 20:00:00-04:00 linville@tuxdriver.com +1 -1
#   3c59x: style change in vortex_ethtool_ops declaration
# 
# ChangeSet
#   2004/10/15 15:25:41-04:00 rddunlap@osdl.org 
#   [PATCH] pcnet32: use unsigned 1-bit fields
# 
# drivers/net/pcnet32.c
#   2004/10/10 18:23:08-04:00 rddunlap@osdl.org +3 -3
#   pcnet32: use unsigned 1-bit fields
# 
# ChangeSet
#   2004/10/15 12:47:59-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000: white space corrections
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/10/07 16:59:53-04:00 ganesh.venkatesan@intel.com +0 -1
#   e1000: white space corrections
# 
# ChangeSet
#   2004/10/15 12:47:46-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000: driver version update
# 
# drivers/net/e1000/e1000_main.c
#   2004/10/07 16:59:54-04:00 ganesh.venkatesan@intel.com +1 -1
#   e1000: driver version update
# 
# ChangeSet
#   2004/10/15 12:47:32-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000: fix set ringparam for ethtool returning error code on bad input
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/10/07 16:59:53-04:00 ganesh.venkatesan@intel.com +3 -0
#   e1000: fix set ringparam for ethtool returning error
# 
# ChangeSet
#   2004/10/15 12:47:19-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000: remove unused function e1000_enable_mng_pass_thru
# 
# drivers/net/e1000/e1000_hw.c
#   2004/10/07 16:59:53-04:00 ganesh.venkatesan@intel.com +0 -25
#   e1000: remove unused function e1000_enable_mng_pass_thru
# 
# ChangeSet
#   2004/10/15 12:47:06-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000:  modified ethtool_set_pauseparam to use e1000_setup_link
#   for flow control settings for fiber serdes link
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/10/07 16:59:53-04:00 ganesh.venkatesan@intel.com +2 -1
#   e1000:  modified ethtool_set_pauseparam to use
# 
# ChangeSet
#   2004/10/14 09:10:57-04:00 pekon@fi.muni.cz 
#   [PATCH] PATCH: netpoll with xircom_cb
#   
#   I have a headless computer with xircom pcmcia card and needed netconsole
#   on it. After looking around in other drivers I concocted this patch.  It
#   survived light testing. I have no documentation for the hw, so it maybe
#   totally bogus.
# 
# drivers/net/tulip/xircom_cb.c
#   2004/10/13 21:54:34-04:00 pekon@fi.muni.cz +14 -0
#   PATCH: netpoll with xircom_cb
# 
# ChangeSet
#   2004/10/07 22:35:15-03:00 acme@conectiva.com.br 
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# include/linux/hdlc.h
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +6 -2
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/wan/wanxl.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +0 -2
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/wan/pc300_drv.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +0 -1
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/wan/hd6457x.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +0 -2
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/wan/farsync.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +20 -22
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/net/wan/dscc4.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +0 -1
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/char/synclinkmp.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +1 -3
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/char/synclink.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +1 -3
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# drivers/char/pcmcia/synclink_cs.c
#   2004/10/07 22:35:06-03:00 acme@conectiva.com.br +1 -3
#   [SKBUFF] move common code to hdlc_type_trans
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/10/07 14:06:21+02:00 perex@suse.cz 
#   Merge suse.cz:/home/perex/bk/linux-sound/linux-sound
#   into suse.cz:/home/perex/bk/linux-sound/work
# 
# sound/pci/intel8x0.c
#   2004/10/07 14:06:00+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# include/sound/seq_kernel.h
#   2004/10/07 14:05:59+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# include/sound/pcm.h
#   2004/10/07 14:05:59+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/07 13:16:37+02:00 perex@suse.cz 
#   Merge
# 
# sound/pci/intel8x0.c
#   2004/10/07 13:16:21+02:00 perex@suse.cz +9 -7
#   SCCS merged
# 
# include/sound/pcm.h
#   2004/10/07 13:06:21+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/07 12:34:36+02:00 perex@suse.cz 
#   [ALSA]  Fix the detection of secondary codec
#   
#   CS46xx driver
#   Fixed the detection of secondary codec.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2004/10/06 05:25:53+02:00 perex@suse.cz +1 -2
#   [ALSA]  Fix the detection of secondary codec
#   
#   D:2004/10/06 11:25:53
#   C:CS46xx driver
#   F:pci/cs46xx/cs46xx_lib.c:1.86->1.87 
#   L:Fixed the detection of secondary codec.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:33:47+02:00 perex@suse.cz 
#   [ALSA]  Fix Aureon CCS init sequence
#   
#   ICE1712 driver
#   - Fix Aureon 5.1 Sky GPIO write mask bits
#   - Fix 192kHz bit
#   
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/aureon.c
#   2004/10/06 05:19:28+02:00 perex@suse.cz +6 -6
#   [ALSA]  Fix Aureon CCS init sequence
#   
#   D:2004/10/06 11:19:28
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.20->1.21 
#   L:- Fix Aureon 5.1 Sky GPIO write mask bits
#   L:- Fix 192kHz bit
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:32:59+02:00 perex@suse.cz 
#   [ALSA]  Fix compilation (sync with parisc tree)
#   
#   PARISC Harmony driver
#   Sync with parisc tree - fix compilations, module description fixes.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/parisc/harmony.c
#   2004/10/06 05:12:12+02:00 perex@suse.cz +9 -6
#   [ALSA]  Fix compilation (sync with parisc tree)
#   
#   D:2004/10/06 11:12:12
#   C:PARISC Harmony driver
#   F:parisc/harmony.c:1.17->1.18 
#   L:Sync with parisc tree - fix compilations, module description fixes.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:32:11+02:00 perex@suse.cz 
#   [ALSA]  Fix ac97 codec reset and clean up
#   
#   CS46xx driver
#   - Fixed AC97 codec RESET for duel codecs (only for CONFIG_SND_CS46XX_NEW_DSP)
#   - Clean up the codec detection routine
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2004/10/06 04:55:22+02:00 perex@suse.cz +49 -74
#   [ALSA]  Fix ac97 codec reset and clean up
#   
#   D:2004/10/06 10:55:22
#   C:CS46xx driver
#   F:pci/cs46xx/cs46xx_lib.c:1.85->1.86 
#   L:- Fixed AC97 codec RESET for duel codecs (only for CONFIG_SND_CS46XX_NEW_DSP)
#   L:- Clean up the codec detection routine
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:31:18+02:00 perex@suse.cz 
#   [ALSA]  Added dxs quirk for QDI Kudoz 7X/600-6AL
#   
#   VIA82xx driver
#   Added the default dxs_support entry for QDI Kudoz 7X/600-6AL.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2004/10/05 12:19:28+02:00 perex@suse.cz +1 -0
#   [ALSA]  Added dxs quirk for QDI Kudoz 7X/600-6AL
#   
#   D:2004/10/05 18:19:28
#   C:VIA82xx driver
#   F:pci/via82xx.c:1.123->1.124 
#   L:Added the default dxs_support entry for QDI Kudoz 7X/600-6AL.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:30:20+02:00 perex@suse.cz 
#   [ALSA]  Fix typo
#   
#   ALSA sequencer
#   Fixed a typo for snd_seq_autoload_lock() in the last change
#   (only for the case without CONFIG_KMOD).
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/seq_kernel.h
#   2004/10/05 05:07:41+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix typo
#   
#   D:2004/10/05 11:07:41
#   C:ALSA sequencer
#   F:include/seq_kernel.h:1.12->1.13 
#   L:Fixed a typo for snd_seq_autoload_lock() in the last change
#   L:(only for the case without CONFIG_KMOD).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:29:22+02:00 perex@suse.cz 
#   [ALSA]  Add KERN_ERR to error messages
#   
#   ALSA Core
#   Added KERN_ERR prefix to error messages in snd_assert() and
#   snd_runtime_check() macros.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/core.h
#   2004/10/04 10:41:01+02:00 perex@suse.cz +2 -2
#   [ALSA]  Add KERN_ERR to error messages
#   
#   D:2004/10/04 16:41:01
#   C:ALSA Core
#   F:include/core.h:1.58->1.59 
#   L:Added KERN_ERR prefix to error messages in snd_assert() and
#   L:snd_runtime_check() macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:28:22+02:00 perex@suse.cz 
#   [ALSA]  Fix pci_restore_state()
#   
#   ALSA Core
#   Fixed pci_save_state() call with the new API.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/init.c
#   2004/10/04 10:40:12+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix pci_restore_state()
#   
#   D:2004/10/04 16:40:12
#   C:ALSA Core
#   F:core/init.c:1.48->1.49 
#   L:Fixed pci_save_state() call with the new API.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:27:21+02:00 perex@suse.cz 
#   [ALSA]  Fix dead blocking during module_init()
#   
#   ALSA sequencer,ALSA<-OSS sequencer
#   Fixed the auto-loading of modules during module_init().
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_midi.c
#   2004/10/04 05:33:23+02:00 perex@suse.cz +2 -0
#   [ALSA]  Fix dead blocking during module_init()
#   
#   D:2004/10/04 11:33:23
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   F:core/seq/seq.c:1.15->1.16 
#   F:core/seq/seq_clientmgr.c:1.37->1.38 
#   F:core/seq/seq_device.c:1.16->1.17 
#   F:core/seq/seq_dummy.c:1.14->1.15 
#   F:core/seq/seq_midi.c:1.23->1.24 
#   F:core/seq/oss/seq_oss.c:1.16->1.17 
#   F:include/seq_kernel.h:1.11->1.12 
#   L:Fixed the auto-loading of modules during module_init().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_dummy.c
#   2004/10/04 05:33:23+02:00 perex@suse.cz +5 -1
#   [ALSA]  Fix dead blocking during module_init()
#   
#   D:2004/10/04 11:33:23
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   F:core/seq/seq.c:1.15->1.16 
#   F:core/seq/seq_clientmgr.c:1.37->1.38 
#   F:core/seq/seq_device.c:1.16->1.17 
#   F:core/seq/seq_dummy.c:1.14->1.15 
#   F:core/seq/seq_midi.c:1.23->1.24 
#   F:core/seq/oss/seq_oss.c:1.16->1.17 
#   F:include/seq_kernel.h:1.11->1.12 
#   L:Fixed the auto-loading of modules during module_init().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_device.c
#   2004/10/04 05:33:23+02:00 perex@suse.cz +30 -1
#   [ALSA]  Fix dead blocking during module_init()
#   
#   D:2004/10/04 11:33:23
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   F:core/seq/seq.c:1.15->1.16 
#   F:core/seq/seq_clientmgr.c:1.37->1.38 
#   F:core/seq/seq_device.c:1.16->1.17 
#   F:core/seq/seq_dummy.c:1.14->1.15 
#   F:core/seq/seq_midi.c:1.23->1.24 
#   F:core/seq/oss/seq_oss.c:1.16->1.17 
#   F:include/seq_kernel.h:1.11->1.12 
#   L:Fixed the auto-loading of modules during module_init().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_clientmgr.c
#   2004/10/04 05:33:23+02:00 perex@suse.cz +1 -6
#   [ALSA]  Fix dead blocking during module_init()
#   
#   D:2004/10/04 11:33:23
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   F:core/seq/seq.c:1.15->1.16 
#   F:core/seq/seq_clientmgr.c:1.37->1.38 
#   F:core/seq/seq_device.c:1.16->1.17 
#   F:core/seq/seq_dummy.c:1.14->1.15 
#   F:core/seq/seq_midi.c:1.23->1.24 
#   F:core/seq/oss/seq_oss.c:1.16->1.17 
#   F:include/seq_kernel.h:1.11->1.12 
#   L:Fixed the auto-loading of modules during module_init().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq.c
#   2004/10/04 05:33:23+02:00 perex@suse.cz +10 -12
#   [ALSA]  Fix dead blocking during module_init()
#   
#   D:2004/10/04 11:33:23
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   F:core/seq/seq.c:1.15->1.16 
#   F:core/seq/seq_clientmgr.c:1.37->1.38 
#   F:core/seq/seq_device.c:1.16->1.17 
#   F:core/seq/seq_dummy.c:1.14->1.15 
#   F:core/seq/seq_midi.c:1.23->1.24 
#   F:core/seq/oss/seq_oss.c:1.16->1.17 
#   F:include/seq_kernel.h:1.11->1.12 
#   L:Fixed the auto-loading of modules during module_init().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/oss/seq_oss.c
#   2004/10/04 05:33:24+02:00 perex@suse.cz +9 -5
#   [ALSA]  Fix dead blocking during module_init()
#   
#   D:2004/10/04 11:33:23
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   F:core/seq/seq.c:1.15->1.16 
#   F:core/seq/seq_clientmgr.c:1.37->1.38 
#   F:core/seq/seq_device.c:1.16->1.17 
#   F:core/seq/seq_dummy.c:1.14->1.15 
#   F:core/seq/seq_midi.c:1.23->1.24 
#   F:core/seq/oss/seq_oss.c:1.16->1.17 
#   F:include/seq_kernel.h:1.11->1.12 
#   L:Fixed the auto-loading of modules during module_init().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/seq_kernel.h
#   2004/10/04 05:33:24+02:00 perex@suse.cz +8 -0
#   [ALSA]  Fix dead blocking during module_init()
#   
#   D:2004/10/04 11:33:23
#   C:ALSA sequencer,ALSA<-OSS sequencer
#   F:core/seq/seq.c:1.15->1.16 
#   F:core/seq/seq_clientmgr.c:1.37->1.38 
#   F:core/seq/seq_device.c:1.16->1.17 
#   F:core/seq/seq_dummy.c:1.14->1.15 
#   F:core/seq/seq_midi.c:1.23->1.24 
#   F:core/seq/oss/seq_oss.c:1.16->1.17 
#   F:include/seq_kernel.h:1.11->1.12 
#   L:Fixed the auto-loading of modules during module_init().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:26:16+02:00 perex@suse.cz 
#   [ALSA]  Clean up bitmap
#   
#   EMU10K1/EMU10K2 driver
#   Clean up the declaration of bitmap with DECLARE_BITMAP().
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/emu10k1.h
#   2004/10/01 10:16:50+02:00 perex@suse.cz +3 -3
#   [ALSA]  Clean up bitmap
#   
#   D:2004/10/01 16:16:50
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.46->1.47 
#   L:Clean up the declaration of bitmap with DECLARE_BITMAP().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:25:41+02:00 perex@suse.cz 
#   [ALSA]  fix snd_opl3_init documentation
#   
#   Documentation
#   
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
#   2004/10/01 08:43:42+02:00 perex@suse.cz +1 -1
#   [ALSA]  fix snd_opl3_init documentation
#   
#   D:2004/10/01 14:43:42
#   C:Documentation
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.41->1.42 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/10/07 12:25:09+02:00 perex@suse.cz 
#   [ALSA]  fix description of SPSA=3 in the proc file
#   
#   AC97 Codec Core
#   
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_proc.c
#   2004/10/01 08:42:22+02:00 perex@suse.cz +1 -1
#   [ALSA]  fix description of SPSA=3 in the proc file
#   
#   D:2004/10/01 14:42:22
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_proc.c:1.11->1.12 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/10/07 12:24:37+02:00 perex@suse.cz 
#   [ALSA]  fix DAC slot assignment
#   
#   AC97 Codec Core
#   write the DAC slot assignment bits to the extended ID register
#   where they belong instead of overwriting the SPSA bits in the
#   extended status register
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_pcm.c
#   2004/10/01 08:41:04+02:00 perex@suse.cz +2 -2
#   [ALSA]  fix DAC slot assignment
#   
#   D:2004/10/01 14:41:04
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_pcm.c:1.17->1.18 
#   L:write the DAC slot assignment bits to the extended ID register
#   L:where they belong instead of overwriting the SPSA bits in the
#   L:extended status register
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/10/07 12:24:06+02:00 perex@suse.cz 
#   [ALSA]  Fix / clean up OPL3 for CS4281
#   
#   Documentation,OPL3,CS4281 driver
#   Moved cs4281-specific code into cs4281 driver from opl3.
#   The ugly type-casting is removed now.
#   
#   The opl3 instance can be created via snd_opl3_new() (followed by
#   snd_opl3_init()) to allow the driver to set its own command and
#   private_data/private_free.
#   
#   snd_opl3_create() is kept for compatibility as it was.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs4281.c
#   2004/09/30 11:48:43+02:00 perex@suse.cz +29 -4
#   [ALSA]  Fix / clean up OPL3 for CS4281
#   
#   D:2004/09/30 17:48:43
#   C:Documentation,OPL3,CS4281 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.40->1.41 
#   F:drivers/opl3/opl3_lib.c:1.22->1.23 
#   F:include/opl3.h:1.11->1.12 
#   F:pci/cs4281.c:1.64->1.65 
#   L:Moved cs4281-specific code into cs4281 driver from opl3.
#   L:The ugly type-casting is removed now.
#   L:
#   L:The opl3 instance can be created via snd_opl3_new() (followed by
#   L:snd_opl3_init()) to allow the driver to set its own command and
#   L:private_data/private_free.
#   L:
#   L:snd_opl3_create() is kept for compatibility as it was.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/opl3/opl3_lib.c
#   2004/09/30 11:48:43+02:00 perex@suse.cz +70 -68
#   [ALSA]  Fix / clean up OPL3 for CS4281
#   
#   D:2004/09/30 17:48:43
#   C:Documentation,OPL3,CS4281 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.40->1.41 
#   F:drivers/opl3/opl3_lib.c:1.22->1.23 
#   F:include/opl3.h:1.11->1.12 
#   F:pci/cs4281.c:1.64->1.65 
#   L:Moved cs4281-specific code into cs4281 driver from opl3.
#   L:The ugly type-casting is removed now.
#   L:
#   L:The opl3 instance can be created via snd_opl3_new() (followed by
#   L:snd_opl3_init()) to allow the driver to set its own command and
#   L:private_data/private_free.
#   L:
#   L:snd_opl3_create() is kept for compatibility as it was.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/opl3.h
#   2004/09/30 11:48:43+02:00 perex@suse.cz +5 -0
#   [ALSA]  Fix / clean up OPL3 for CS4281
#   
#   D:2004/09/30 17:48:43
#   C:Documentation,OPL3,CS4281 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.40->1.41 
#   F:drivers/opl3/opl3_lib.c:1.22->1.23 
#   F:include/opl3.h:1.11->1.12 
#   F:pci/cs4281.c:1.64->1.65 
#   L:Moved cs4281-specific code into cs4281 driver from opl3.
#   L:The ugly type-casting is removed now.
#   L:
#   L:The opl3 instance can be created via snd_opl3_new() (followed by
#   L:snd_opl3_init()) to allow the driver to set its own command and
#   L:private_data/private_free.
#   L:
#   L:snd_opl3_create() is kept for compatibility as it was.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
#   2004/09/30 11:48:43+02:00 perex@suse.cz +33 -1
#   [ALSA]  Fix / clean up OPL3 for CS4281
#   
#   D:2004/09/30 17:48:43
#   C:Documentation,OPL3,CS4281 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.40->1.41 
#   F:drivers/opl3/opl3_lib.c:1.22->1.23 
#   F:include/opl3.h:1.11->1.12 
#   F:pci/cs4281.c:1.64->1.65 
#   L:Moved cs4281-specific code into cs4281 driver from opl3.
#   L:The ugly type-casting is removed now.
#   L:
#   L:The opl3 instance can be created via snd_opl3_new() (followed by
#   L:snd_opl3_init()) to allow the driver to set its own command and
#   L:private_data/private_free.
#   L:
#   L:snd_opl3_create() is kept for compatibility as it was.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:23:34+02:00 perex@suse.cz 
#   ALSA CVS update
#   USB generic driver
#   add Edirol UA-25 support
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2004/09/30 05:11:25+02:00 perex@suse.cz +34 -3
#   ALSA CVS update
#   D:2004/09/30 11:11:25
#   C:USB generic driver
#   F:usb/usbaudio.c:1.109->1.110 
#   F:usb/usbaudio.h:1.34->1.35 
#   F:usb/usbquirks.h:1.37->1.38 
#   L:add Edirol UA-25 support
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.h
#   2004/09/30 05:11:25+02:00 perex@suse.cz +2 -2
#   ALSA CVS update
#   D:2004/09/30 11:11:25
#   C:USB generic driver
#   F:usb/usbaudio.c:1.109->1.110 
#   F:usb/usbaudio.h:1.34->1.35 
#   F:usb/usbquirks.h:1.37->1.38 
#   L:add Edirol UA-25 support
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.c
#   2004/09/30 05:11:25+02:00 perex@suse.cz +26 -10
#   ALSA CVS update
#   D:2004/09/30 11:11:25
#   C:USB generic driver
#   F:usb/usbaudio.c:1.109->1.110 
#   F:usb/usbaudio.h:1.34->1.35 
#   F:usb/usbquirks.h:1.37->1.38 
#   L:add Edirol UA-25 support
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/10/07 12:23:01+02:00 perex@suse.cz 
#   [ALSA]  Fix AC3 playback on SB Live
#   
#   EMU10K1/EMU10K2 driver
#   Fix the AC3 playback on SB Live!
#   (Audigy has been working fine.)
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2004/09/30 05:06:53+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix AC3 playback on SB Live
#   
#   D:2004/09/30 11:06:53
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emupcm.c:1.32->1.33 
#   L:Fix the AC3 playback on SB Live!
#   L:(Audigy has been working fine.)
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:22:30+02:00 perex@suse.cz 
#   [ALSA]  Fix AC97 master mute
#   
#   ICE1712 driver
#   Instead of muting the AC97 chip and thus eliminating the possibility of recording,
#   muting is done by setting front playback to DAC only instead of DAC+AUX.
#   
#   Signed-off-by: Peter Christensen <ungod@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/aureon.c
#   2004/09/29 10:55:44+02:00 perex@suse.cz +39 -3
#   [ALSA]  Fix AC97 master mute
#   
#   D:2004/09/29 16:55:44
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.19->1.20 
#   L:Instead of muting the AC97 chip and thus eliminating the possibility of recording,
#   L:muting is done by setting front playback to DAC only instead of DAC+AUX.
#   Signed-off-by: Peter Christensen <ungod@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:21:33+02:00 perex@suse.cz 
#   [ALSA]  Fix SPDIF support on ICH4/5/6
#   
#   Intel8x0 driver
#   Fixed SPDIF support on ICH4/5/6.  The driver name of these chipsets
#   is set as 'ICH4' to tell from the older ICHs.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/09/29 10:46:41+02:00 perex@suse.cz +11 -0
#   [ALSA]  Fix SPDIF support on ICH4/5/6
#   
#   D:2004/09/29 16:46:41
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.171->1.172 
#   L:Fixed SPDIF support on ICH4/5/6.  The driver name of these chipsets
#   L:is set as 'ICH4' to tell from the older ICHs.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:20:47+02:00 perex@suse.cz 
#   [ALSA]  Add (experimental) CM9761 support
#   
#   AC97 Codec Core
#   CM9761 support patch is added.
#   At least, SPDIF and 4.0 output seems working.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.h
#   2004/09/29 10:45:52+02:00 perex@suse.cz +1 -0
#   [ALSA]  Add (experimental) CM9761 support
#   
#   D:2004/09/29 16:45:52
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_codec.c:1.149->1.150 
#   F:pci/ac97/ac97_id.h:1.9->1.10 
#   F:pci/ac97/ac97_patch.c:1.57->1.58 
#   F:pci/ac97/ac97_patch.h:1.16->1.17 
#   L:CM9761 support patch is added.
#   L:At least, SPDIF and 4.0 output seems working.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2004/09/29 10:45:52+02:00 perex@suse.cz +134 -0
#   [ALSA]  Add (experimental) CM9761 support
#   
#   D:2004/09/29 16:45:52
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_codec.c:1.149->1.150 
#   F:pci/ac97/ac97_id.h:1.9->1.10 
#   F:pci/ac97/ac97_patch.c:1.57->1.58 
#   F:pci/ac97/ac97_patch.h:1.16->1.17 
#   L:CM9761 support patch is added.
#   L:At least, SPDIF and 4.0 output seems working.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_id.h
#   2004/09/29 10:45:52+02:00 perex@suse.cz +3 -0
#   [ALSA]  Add (experimental) CM9761 support
#   
#   D:2004/09/29 16:45:52
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_codec.c:1.149->1.150 
#   F:pci/ac97/ac97_id.h:1.9->1.10 
#   F:pci/ac97/ac97_patch.c:1.57->1.58 
#   F:pci/ac97/ac97_patch.h:1.16->1.17 
#   L:CM9761 support patch is added.
#   L:At least, SPDIF and 4.0 output seems working.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/09/29 10:45:52+02:00 perex@suse.cz +3 -0
#   [ALSA]  Add (experimental) CM9761 support
#   
#   D:2004/09/29 16:45:52
#   C:AC97 Codec Core
#   F:pci/ac97/ac97_codec.c:1.149->1.150 
#   F:pci/ac97/ac97_id.h:1.9->1.10 
#   F:pci/ac97/ac97_patch.c:1.57->1.58 
#   F:pci/ac97/ac97_patch.h:1.16->1.17 
#   L:CM9761 support patch is added.
#   L:At least, SPDIF and 4.0 output seems working.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:19:58+02:00 perex@suse.cz 
#   [ALSA]  add overclocking option for the analog input
#   
#   PCI drivers,BT87x driver
#   adds CONFIG_SND_BT87X_OVERCLOCK to enable sample rates
#   up to 1792000 Hz when recording from the analog input
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/bt87x.c
#   2004/09/29 08:33:18+02:00 perex@suse.cz +14 -6
#   [ALSA]  add overclocking option for the analog input
#   
#   D:2004/09/29 14:33:18
#   C:PCI drivers,BT87x driver
#   F:pci/Kconfig:1.34->1.35 
#   F:pci/bt87x.c:1.13->1.14 
#   L:adds CONFIG_SND_BT87X_OVERCLOCK to enable sample rates
#   L:up to 1792000 Hz when recording from the analog input
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/Kconfig
#   2004/09/29 08:33:18+02:00 perex@suse.cz +10 -0
#   [ALSA]  add overclocking option for the analog input
#   
#   D:2004/09/29 14:33:18
#   C:PCI drivers,BT87x driver
#   F:pci/Kconfig:1.34->1.35 
#   F:pci/bt87x.c:1.13->1.14 
#   L:adds CONFIG_SND_BT87X_OVERCLOCK to enable sample rates
#   L:up to 1792000 Hz when recording from the analog input
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/10/07 12:19:13+02:00 perex@suse.cz 
#   [ALSA]  Add reset_workaround module option
#   
#   Documentation,NM256 driver
#   - The workaround for some laptops like Dell Latitude LS can be
#     specified via reset_workaround module option, too.
#   - The check of reset_workaround is merged into the quirk table.
#   - The spinlock in AC97 reset callback is removed.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/nm256/nm256.c
#   2004/09/28 11:44:03+02:00 perex@suse.cz +20 -20
#   [ALSA]  Add reset_workaround module option
#   
#   D:2004/09/28 17:44:02
#   C:Documentation,NM256 driver
#   F:Documentation/ALSA-Configuration.txt:1.52->1.53 
#   F:pci/nm256/nm256.c:1.51->1.52 
#   L:- The workaround for some laptops like Dell Latitude LS can be
#   L:  specified via reset_workaround module option, too.
#   L:- The check of reset_workaround is merged into the quirk table.
#   L:- The spinlock in AC97 reset callback is removed.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2004/09/28 11:44:02+02:00 perex@suse.cz +6 -0
#   [ALSA]  Add reset_workaround module option
#   
#   D:2004/09/28 17:44:02
#   C:Documentation,NM256 driver
#   F:Documentation/ALSA-Configuration.txt:1.52->1.53 
#   F:pci/nm256/nm256.c:1.51->1.52 
#   L:- The workaround for some laptops like Dell Latitude LS can be
#   L:  specified via reset_workaround module option, too.
#   L:- The check of reset_workaround is merged into the quirk table.
#   L:- The spinlock in AC97 reset callback is removed.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:18:24+02:00 perex@suse.cz 
#   [ALSA]  Adds AC'97 support to Aureon cards.
#   
#   ICE1712 driver
#   This patch adds support of the STAC9744 chip located on Aureon cards,
#   enabling volume control for analogue input channels.
#   It also adds the posibility of listening to both the analogue inputs
#   and the digital audio.
#   
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1712.h
#   2004/09/27 09:45:22+02:00 perex@suse.cz +2 -0
#   [ALSA]  Adds AC'97 support to Aureon cards.
#   
#   D:2004/09/27 15:45:22
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.18->1.19 
#   F:pci/ice1712/aureon.h:1.4->1.5 
#   F:pci/ice1712/ice1712.h:1.24->1.25 
#   L:This patch adds support of the STAC9744 chip located on Aureon cards,
#   L:enabling volume control for analogue input channels.
#   L:It also adds the posibility of listening to both the analogue inputs
#   L:and the digital audio.
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/aureon.h
#   2004/09/27 09:45:22+02:00 perex@suse.cz +5 -0
#   [ALSA]  Adds AC'97 support to Aureon cards.
#   
#   D:2004/09/27 15:45:22
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.18->1.19 
#   F:pci/ice1712/aureon.h:1.4->1.5 
#   F:pci/ice1712/ice1712.h:1.24->1.25 
#   L:This patch adds support of the STAC9744 chip located on Aureon cards,
#   L:enabling volume control for analogue input channels.
#   L:It also adds the posibility of listening to both the analogue inputs
#   L:and the digital audio.
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/aureon.c
#   2004/09/27 09:45:22+02:00 perex@suse.cz +333 -5
#   [ALSA]  Adds AC'97 support to Aureon cards.
#   
#   D:2004/09/27 15:45:22
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.18->1.19 
#   F:pci/ice1712/aureon.h:1.4->1.5 
#   F:pci/ice1712/ice1712.h:1.24->1.25 
#   L:This patch adds support of the STAC9744 chip located on Aureon cards,
#   L:enabling volume control for analogue input channels.
#   L:It also adds the posibility of listening to both the analogue inputs
#   L:and the digital audio.
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:17:32+02:00 perex@suse.cz 
#   [ALSA]  Clean up ice1712 chip struct
#   
#   ICE1712 driver
#   Clean up of ice1712 chip struct.  The board-specific data are moved
#   to spec union.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1712.h
#   2004/09/27 09:44:14+02:00 perex@suse.cz +13 -5
#   [ALSA]  Clean up ice1712 chip struct
#   
#   D:2004/09/27 15:44:14
#   C:ICE1712 driver
#   F:pci/ice1712/ews.c:1.19->1.20 
#   F:pci/ice1712/hoontech.c:1.7->1.8 
#   F:pci/ice1712/ice1712.h:1.23->1.24 
#   L:Clean up of ice1712 chip struct.  The board-specific data are moved
#   L:to spec union.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/hoontech.c
#   2004/09/27 09:44:14+02:00 perex@suse.cz +82 -82
#   [ALSA]  Clean up ice1712 chip struct
#   
#   D:2004/09/27 15:44:14
#   C:ICE1712 driver
#   F:pci/ice1712/ews.c:1.19->1.20 
#   F:pci/ice1712/hoontech.c:1.7->1.8 
#   F:pci/ice1712/ice1712.h:1.23->1.24 
#   L:Clean up of ice1712 chip struct.  The board-specific data are moved
#   L:to spec union.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ews.c
#   2004/09/27 09:44:14+02:00 perex@suse.cz +32 -22
#   [ALSA]  Clean up ice1712 chip struct
#   
#   D:2004/09/27 15:44:14
#   C:ICE1712 driver
#   F:pci/ice1712/ews.c:1.19->1.20 
#   F:pci/ice1712/hoontech.c:1.7->1.8 
#   F:pci/ice1712/ice1712.h:1.23->1.24 
#   L:Clean up of ice1712 chip struct.  The board-specific data are moved
#   L:to spec union.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:16:41+02:00 perex@suse.cz 
#   [ALSA]  Fix peakmeter ioctl on big-endian
#   
#   RME HDSP driver
#   Fixed the data transfer of peakmeter ioctl on big-endian architectures.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2004/09/27 08:00:11+02:00 perex@suse.cz +66 -53
#   [ALSA]  Fix peakmeter ioctl on big-endian
#   
#   D:2004/09/27 14:00:11
#   C:RME HDSP driver
#   F:pci/rme9652/hdsp.c:1.70->1.71 
#   L:Fixed the data transfer of peakmeter ioctl on big-endian architectures.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:15:56+02:00 perex@suse.cz 
#   [ALSA]  Replace with usb_kill_urb()
#   
#   USB generic driver
#   Use usb_kill_urb() instead of deprecated usb_unlink_urb() for sync'ed URBs.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/usb/usbaudio.c
#   2004/09/24 10:50:48+02:00 perex@suse.cz +8 -8
#   [ALSA]  Replace with usb_kill_urb()
#   
#   D:2004/09/24 16:50:48
#   C:USB generic driver
#   F:usb/usbaudio.c:1.108->1.109 
#   L:Use usb_kill_urb() instead of deprecated usb_unlink_urb() for sync'ed URBs.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 12:15:03+02:00 perex@suse.cz 
#   [ALSA]  snd-usb-usx2y 0.7.3
#   
#   USB generic driver,USB USX2Y
#   Use usb_kill_urb() instead of deprecated usb_unlink_urb()
#   
#   Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/usb/usx2y/usbusx2yaudio.c
#   2004/09/24 10:50:04+02:00 perex@suse.cz +17 -19
#   [ALSA]  snd-usb-usx2y 0.7.3
#   
#   D:2004/09/24 16:50:04
#   C:USB generic driver,USB USX2Y
#   F:usb/usbmidi.c:1.33->1.34 
#   F:usb/usx2y/usbusx2y.c:1.2->1.3 
#   F:usb/usx2y/usbusx2yaudio.c:1.3->1.4 
#   L:Use usb_kill_urb() instead of deprecated usb_unlink_urb()
#   Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/usb/usx2y/usbusx2y.c
#   2004/09/24 10:50:04+02:00 perex@suse.cz +7 -3
#   [ALSA]  snd-usb-usx2y 0.7.3
#   
#   D:2004/09/24 16:50:04
#   C:USB generic driver,USB USX2Y
#   F:usb/usbmidi.c:1.33->1.34 
#   F:usb/usx2y/usbusx2y.c:1.2->1.3 
#   F:usb/usx2y/usbusx2yaudio.c:1.3->1.4 
#   L:Use usb_kill_urb() instead of deprecated usb_unlink_urb()
#   Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/usb/usbmidi.c
#   2004/09/24 10:50:04+02:00 perex@suse.cz +3 -3
#   [ALSA]  snd-usb-usx2y 0.7.3
#   
#   D:2004/09/24 16:50:04
#   C:USB generic driver,USB USX2Y
#   F:usb/usbmidi.c:1.33->1.34 
#   F:usb/usx2y/usbusx2y.c:1.2->1.3 
#   F:usb/usx2y/usbusx2yaudio.c:1.3->1.4 
#   L:Use usb_kill_urb() instead of deprecated usb_unlink_urb()
#   Signed-off-by: Karsten Wiese <annabellesgarden@yahoo.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 11:56:30+02:00 perex@suse.cz 
#   [ALSA]  Fix drain/drop of linked PCM streams
#   
#   PCM Midlevel
#   This patch fixes the dead-locking of linked PCM streams when
#   drain/drop is called.  The counter field is added to pcm group
#   struct to handle link/unlink more easily.
#   
#   When the PCM streams are linked, start/drain/drop are operated
#   to all linked streams.  The drain will wait until draining of all
#   linked streams are finished.
#   
#   The XRUN triggers stopping of all linked streams and changes the
#   state of all of them to XRUN even if only one of them is actually
#   in XRUN.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_native.c
#   2004/09/24 09:25:02+02:00 perex@suse.cz +320 -314
#   [ALSA]  Fix drain/drop of linked PCM streams
#   
#   D:2004/09/24 15:25:02
#   C:PCM Midlevel
#   F:core/pcm_lib.c:1.57->1.58 
#   F:core/pcm_native.c:1.106->1.107 
#   F:include/pcm.h:1.48->1.49 
#   L:This patch fixes the dead-locking of linked PCM streams when
#   L:drain/drop is called.  The counter field is added to pcm group
#   L:struct to handle link/unlink more easily.
#   L:
#   L:When the PCM streams are linked, start/drain/drop are operated
#   L:to all linked streams.  The drain will wait until draining of all
#   L:linked streams are finished.
#   L:
#   L:The XRUN triggers stopping of all linked streams and changes the
#   L:state of all of them to XRUN even if only one of them is actually
#   L:in XRUN.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_lib.c
#   2004/09/24 09:25:02+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix drain/drop of linked PCM streams
#   
#   D:2004/09/24 15:25:02
#   C:PCM Midlevel
#   F:core/pcm_lib.c:1.57->1.58 
#   F:core/pcm_native.c:1.106->1.107 
#   F:include/pcm.h:1.48->1.49 
#   L:This patch fixes the dead-locking of linked PCM streams when
#   L:drain/drop is called.  The counter field is added to pcm group
#   L:struct to handle link/unlink more easily.
#   L:
#   L:When the PCM streams are linked, start/drain/drop are operated
#   L:to all linked streams.  The drain will wait until draining of all
#   L:linked streams are finished.
#   L:
#   L:The XRUN triggers stopping of all linked streams and changes the
#   L:state of all of them to XRUN even if only one of them is actually
#   L:in XRUN.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/pcm.h
#   2004/09/24 09:25:03+02:00 perex@suse.cz +2 -0
#   [ALSA]  Fix drain/drop of linked PCM streams
#   
#   D:2004/09/24 15:25:02
#   C:PCM Midlevel
#   F:core/pcm_lib.c:1.57->1.58 
#   F:core/pcm_native.c:1.106->1.107 
#   F:include/pcm.h:1.48->1.49 
#   L:This patch fixes the dead-locking of linked PCM streams when
#   L:drain/drop is called.  The counter field is added to pcm group
#   L:struct to handle link/unlink more easily.
#   L:
#   L:When the PCM streams are linked, start/drain/drop are operated
#   L:to all linked streams.  The drain will wait until draining of all
#   L:linked streams are finished.
#   L:
#   L:The XRUN triggers stopping of all linked streams and changes the
#   L:state of all of them to XRUN even if only one of them is actually
#   L:in XRUN.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 11:55:58+02:00 perex@suse.cz 
#   [ALSA]  Aureon S/PDIF input fixes
#   
#   ICE1712 driver
#   GPIO directions changed
#      * GPIO>22 not configured as they do not exist
#      * GPIO22 set to output (CS8415A CS pin)
#      * GPIO21 set to input. (SPI MISO pin)
#   
#   Init sequence of CS8415A changed:
#     * SWCLK is set to 1 (OMCK output to RMCK pin)
#     * MUX2:0 is set to 001 (S/PDIF input on RXP1)
#     * SODEL is set to 1 (MSB of SDOUT data occurs if the second OSCLK period after the OLRCK edge)
#     * SOLRPOL is set to 1 (SDOUT data is for the right channel with OLRCK is high)
#   
#   Signed-off-by: Peter Christensen <peter@christensen>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/aureon.c
#   2004/09/24 07:42:05+02:00 perex@suse.cz +2 -2
#   [ALSA]  Aureon S/PDIF input fixes
#   
#   D:2004/09/24 13:42:05
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.17->1.18 
#   L:GPIO directions changed
#   L:   * GPIO>22 not configured as they do not exist
#   L:   * GPIO22 set to output (CS8415A CS pin)
#   L:   * GPIO21 set to input. (SPI MISO pin)
#   L:
#   L:Init sequence of CS8415A changed:
#   L:  * SWCLK is set to 1 (OMCK output to RMCK pin)
#   L:  * MUX2:0 is set to 001 (S/PDIF input on RXP1)
#   L:  * SODEL is set to 1 (MSB of SDOUT data occurs if the second OSCLK period after the OLRCK edge)
#   L:  * SOLRPOL is set to 1 (SDOUT data is for the right channel with OLRCK is high)
#   Signed-off-by: Peter Christensen <peter@christensen>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 11:55:16+02:00 perex@suse.cz 
#   [ALSA]  Aureon S/PDIF input fixes
#   
#   ICE1712 driver
#   Fix GPIO pin directions and use RXP1 instead of RXP0 as S/PDIF source on CS8415A
#   
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/aureon.c
#   2004/09/24 07:28:44+02:00 perex@suse.cz +5 -5
#   [ALSA]  Aureon S/PDIF input fixes
#   
#   D:2004/09/24 13:28:44
#   C:ICE1712 driver
#   F:pci/ice1712/aureon.c:1.16->1.17 
#   L:Fix GPIO pin directions and use RXP1 instead of RXP0 as S/PDIF source on CS8415A
#   Signed-off-by: Peter Christensen <peter@developers.dk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 11:54:31+02:00 perex@suse.cz 
#   [ALSA]  Fix DXS entry for GA-7VAX
#   
#   VIA82xx driver
#   From: 1 1 <anoy@mail.ru>
#   
#   I have tested my MB GA-7VAX and want to say you that you should use
#   VIA_DXS_ENABLE instead VIA_DXS_NO_VRA.  On the maximum volume output level
#   with VIA_DXS_NO_VRA there is abnormal loud noise, and with VIA_DXS_ENABLE
#   there are much less noises.  And I have detected unused code section.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2004/09/24 05:08:02+02:00 perex@suse.cz +1 -7
#   [ALSA]  Fix DXS entry for GA-7VAX
#   
#   D:2004/09/24 11:08:02
#   C:VIA82xx driver
#   F:pci/via82xx.c:1.122->1.123 
#   L:From: 1 1 <anoy@mail.ru>
#   L:
#   L:I have tested my MB GA-7VAX and want to say you that you should use
#   L:VIA_DXS_ENABLE instead VIA_DXS_NO_VRA.  On the maximum volume output level
#   L:with VIA_DXS_NO_VRA there is abnormal loud noise, and with VIA_DXS_ENABLE
#   L:there are much less noises.  And I have detected unused code section.
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 11:53:30+02:00 perex@suse.cz 
#   [ALSA]  Fix HDSP meter ioctl
#   
#   RME HDSP driver
#   Fixes and clean up of GET_PEAK_RMS ioctl.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2004/09/23 05:05:29+02:00 perex@suse.cz +122 -98
#   [ALSA]  Fix HDSP meter ioctl
#   
#   D:2004/09/23 11:05:29
#   C:RME HDSP driver
#   F:pci/rme9652/hdsp.c:1.69->1.70 
#   L:Fixes and clean up of GET_PEAK_RMS ioctl.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 11:52:15+02:00 perex@suse.cz 
#   [ALSA]  more au88x0 eq cleanups
#   
#   au88x0 driver
#   cleanup au88x0 equalizer code by factoring out a sign_invert function
#   that ensures all negative integers become positive.
#   
#   Signed-off-by: Jeff Muizelaar <muizelaar@rogers.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/au88x0/au88x0_eq.c
#   2004/09/22 11:11:17+02:00 perex@suse.cz +25 -51
#   [ALSA]  more au88x0 eq cleanups
#   
#   D:2004/09/22 17:11:17
#   C:au88x0 driver
#   F:pci/au88x0/au88x0_eq.c:1.4->1.5 
#   L:cleanup au88x0 equalizer code by factoring out a sign_invert function
#   L:that ensures all negative integers become positive.
#   Signed-off-by: Jeff Muizelaar <muizelaar@rogers.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/07 11:51:16+02:00 perex@suse.cz 
#   [ALSA]  Fix the variable types in struct
#   
#   RME HDSP driver
#   The variable types are declared explicitly like u32 and u64
#   to avoid ambiguity.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/hdsp.h
#   2004/09/22 10:20:44+02:00 perex@suse.cz +6 -6
#   [ALSA]  Fix the variable types in struct
#   
#   D:2004/09/22 16:20:44
#   C:RME HDSP driver
#   F:include/hdsp.h:1.6->1.7 
#   L:The variable types are declared explicitly like u32 and u64
#   L:to avoid ambiguity.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/10/06 23:44:56-04:00 akpm@osdl.org 
#   [PATCH] fix acenic hotplug
#   
#   From: Anton Blanchard <anton@samba.org>
#   
#   Now that the acenic has been converted to the hotplug API a number of uses
#   of __init and __initdata have to be changed to __devinit and __devinitdata.
#   
#   Acked-by: Jes Sorensen <jes@trained-monkey.org>
#   Signed-off-by: Anton Blanchard <anton@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/acenic_firmware.h
#   2004/10/05 02:28:48-04:00 akpm@osdl.org +1 -1
#   fix acenic hotplug
# 
# drivers/net/acenic.c
#   2004/10/05 02:30:43-04:00 akpm@osdl.org +10 -10
#   fix acenic hotplug
# 
# ChangeSet
#   2004/10/04 17:17:08-04:00 nhorman@redhat.com 
#   [PATCH] ns83820: add vlan tag hardware acceleration support
#   
#   	I was poking about in the National Semi 83820 driver, and I happened to notice that the chip supports vlan tag add/strip assist in hardware, but the driver wasn't making use of it.  This patch adds in the driver support to use the vlan tag add/remove hardware, and enables the drivers use of the kernel vlan hwaccel interface.
#   
#   Signed-off-by: Neil Horman <nhorman@redhat.com>
# 
# drivers/net/ns83820.c
#   2004/10/01 09:29:04-04:00 nhorman@redhat.com +106 -6
#   ns83820: add vlan tag hardware acceleration support
# 
# ChangeSet
#   2004/10/04 16:51:14-04:00 sfeldma@pobox.com 
#   [PATCH] janitor: net/tulip: pci_find_device to pci_dev_present
#   
#   Replace pci_find_device with pci_dev_present.  Compile tested.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
# 
# drivers/net/tulip/tulip_core.c
#   2004/10/03 01:01:22-04:00 sfeldma@pobox.com +12 -9
#   janitor: net/tulip: pci_find_device to pci_dev_present
# 
# ChangeSet
#   2004/10/04 16:51:01-04:00 sfeldma@pobox.com 
#   [PATCH] janitor: net/sis900: pci_find_device to pci_get_device
#   
#   Replace pci_find_device with pci_get_device/pci_dev_put to plug
#   race with pci_find_device.  Compile tested.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
# 
# drivers/net/sis900.c
#   2004/10/03 00:29:07-04:00 sfeldma@pobox.com +10 -8
#   janitor: net/sis900: pci_find_device to pci_get_device
# 
# ChangeSet
#   2004/10/02 23:28:36-07:00 ebs@ebshome.net 
#   PPC32: remove bogus eXecute permissions
#   
#   Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
# 
# arch/ppc/platforms/4xx/sycamore.h
#   2004/10/02 23:26:32-07:00 ebs@ebshome.net +0 -0
#   Change mode to -rw-rw-r--
# 
# arch/ppc/platforms/4xx/redwood6.h
#   2004/10/02 23:26:32-07:00 ebs@ebshome.net +0 -0
#   Change mode to -rw-rw-r--
# 
# arch/ppc/platforms/4xx/ebony.h
#   2004/10/02 23:26:32-07:00 ebs@ebshome.net +0 -0
#   Change mode to -rw-rw-r--
# 
# ChangeSet
#   2004/10/01 00:22:45-04:00 jesse.brandeburg@intel.com 
#   [PATCH] e100: whitespace and DPRINTKS
#   
#   This is a short patch to add a couple of new DPRINTKS and fix some
#   whitespace issues.
#   
#   Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
# 
# drivers/net/e100.c
#   2004/09/22 14:55:01-04:00 jesse.brandeburg@intel.com +6 -3
#   e100: whitespace and DPRINTKS
# 
# ChangeSet
#   2004/10/01 00:22:32-04:00 jesse.brandeburg@intel.com 
#   [PATCH] e100: fix NAPI race with watchdog
#   
#   While polling in NAPI mode, we were occassionally getting interrupts
#   re-enabled by the watchdog trying to generate a software interrupt.  Fix
#   is to add a spinlock around that shared hardware register to allow a
#   read-modify-write operation.  This was nasty nasty.  I don't like the
#   spinlock in the hot path but i see no other way.  Comments are welcome.
#   Updates the driver version as well.
#   
#   Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
# 
# drivers/net/e100.c
#   2004/09/22 14:49:05-04:00 jesse.brandeburg@intel.com +16 -3
#   e100: fix NAPI race with watchdog
# 
# ChangeSet
#   2004/10/01 00:20:57-04:00 jesse.brandeburg@intel.com 
#   [PATCH] ixgb: fix endianness issue for tx cleanup
#   
#   This patch fixes tx cleanup so that it works correctly on big endian
#   machines.
#   This time I remembered to update the version string.
#   
#   Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/09/22 15:01:42-04:00 jesse.brandeburg@intel.com +2 -2
#   RESEND ixgb: fix endianness issue for tx cleanup
# 
# ChangeSet
#   2004/10/01 00:18:59-04:00 nacc@us.ibm.com 
#   [PATCH] net/de2104x: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
# 
# drivers/net/tulip/de2104x.c
#   2004/09/15 12:38:42-04:00 nacc@us.ibm.com +1 -2
#   net/de2104x: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2004/10/01 00:14:33-04:00 akpm@osdl.org 
#   [PATCH] e1000 sparc64 dma_mapping build fix
#   
#   drivers/net/e1000/e1000_main.c: In function `e1000_probe':
#   drivers/net/e1000/e1000_main.c:389: error: `DMA_64BIT_MASK' undeclared (first use in this function)
#   drivers/net/e1000/e1000_main.c:389: error: (Each undeclared identifier is reported only once
#   drivers/net/e1000/e1000_main.c:389: error: for each function it appears in.)
#   drivers/net/e1000/e1000_main.c:392: error: `DMA_32BIT_MASK' undeclared (first use in this function)
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/e1000/e1000.h
#   2004/09/21 02:38:09-04:00 akpm@osdl.org +1 -0
#   e1000 sparc64 dma_mapping build fix
# 
# ChangeSet
#   2004/10/01 00:13:59-04:00 akpm@osdl.org 
#   [PATCH] igxb speedup
#   
#   The interrupt routine will call both those functions even if the first doesn't
#   have any work to do.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/ixgb/ixgb_main.c
#   2004/08/30 03:50:40-04:00 akpm@osdl.org +5 -1
#   igxb speedup
# 
# ChangeSet
#   2004/09/30 23:29:15-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 update -- fix MODULE_PARM, module_param, module_param_array
# 
# drivers/net/e1000/e1000_param.c
#   2004/09/21 00:54:34-04:00 ganesh.venkatesan@intel.com +104 -63
#   e1000 update -- fix MODULE_PARM, module_param,
# 
# drivers/net/e1000/e1000.h
#   2004/09/21 00:54:33-04:00 ganesh.venkatesan@intel.com +0 -1
#   e1000 update -- fix MODULE_PARM, module_param,
# 
# drivers/net/Kconfig
#   2004/09/17 11:39:00-04:00 akpm@osdl.org +12 -12
#   via-velocity Kconfig fix
# 
# ChangeSet
#   2004/09/30 19:33:53-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/spare/repo/linux-2.6
#   into pobox.com:/spare/repo/netdev-2.6/misc
# 
# drivers/net/Kconfig
#   2004/09/30 19:33:49-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/22 12:28:46+02:00 perex@suse.cz 
#   [ALSA]  don't stop capture on errors
#   
#   BT87x driver
#   don't stop capture on errors because there's too much broken hardware out there
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 12:28:15+02:00 perex@suse.cz 
#   [ALSA]  remove 'Rawmidi' part from sequencer port names
#   
#   ALSA sequencer
#   
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 11:25:08+02:00 perex@suse.cz 
#   Merge
# 
# ChangeSet
#   2004/09/22 10:06:58+02:00 perex@suse.cz 
#   Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5
#   into suse.cz:/home/perex/bk/linux-sound/linux-sound
# 
# sound/pci/bt87x.c
#   2004/09/22 03:53:26+02:00 perex@suse.cz +2 -3
#   [ALSA]  don't stop capture on errors
#   
#   D:2004/09/22 09:53:26
#   C:BT87x driver
#   F:pci/bt87x.c:1.12->1.13 
#   L:don't stop capture on errors because there's too much broken hardware out there
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/seq/seq_midi.c
#   2004/09/22 02:16:27+02:00 perex@suse.cz +1 -1
#   [ALSA]  remove 'Rawmidi' part from sequencer port names
#   
#   D:2004/09/22 08:16:27
#   C:ALSA sequencer
#   F:core/seq/seq_midi.c:1.22->1.23 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/intel8x0.c
#   2004/09/22 11:24:55+02:00 perex@suse.cz +0 -8
#   SCCS merged
# 
# sound/pci/atiixp_modem.c
#   2004/09/22 11:23:23+02:00 perex@suse.cz +0 -3
#   SCCS merged
# 
# sound/pci/atiixp.c
#   2004/09/22 11:23:14+02:00 perex@suse.cz +0 -3
#   SCCS merged
# 
# sound/pci/intel8x0.c
#   2004/09/22 10:06:47+02:00 perex@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/22 09:55:28+02:00 perex@suse.cz 
#   [ALSA]  use card-specific driver name
#   
#   au88x0 driver
#   use CARD_NAME_SHORT as driver name to allow different configuration file aliases in alsa-lib
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/au88x0/au88x0.c
#   2004/09/22 02:11:15+02:00 perex@suse.cz +1 -1
#   [ALSA]  use card-specific driver name
#   
#   D:2004/09/22 08:11:15
#   C:au88x0 driver
#   F:pci/au88x0/au88x0.c:1.12->1.13 
#   L:use CARD_NAME_SHORT as driver name to allow different configuration file aliases in alsa-lib
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 09:55:06+02:00 perex@suse.cz 
#   [ALSA]  Fix SPDIF rate setting for old ICHs
#   
#   Intel8x0 driver
#   Force to set SPDIF rate when PCMOUT is used on ICH[1-3].
#   ICH4, NFORCE and ALI uses a separate DMA for SPDIF.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/09/21 08:15:27+02:00 perex@suse.cz +12 -12
#   [ALSA]  Fix SPDIF rate setting for old ICHs
#   
#   D:2004/09/21 14:15:27
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.170->1.171 
#   L:Force to set SPDIF rate when PCMOUT is used on ICH[1-3].
#   L:ICH4, NFORCE and ALI uses a separate DMA for SPDIF.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:54:42+02:00 perex@suse.cz 
#   [ALSA]  [hdsp] Fix for 64bit architectures
#   
#   RME HDSP driver
#   Fixed the loading of firmware data and the handling of meter mmap
#   on 64bit architectures.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2004/09/21 05:32:27+02:00 perex@suse.cz +3 -3
#   [ALSA]  [hdsp] Fix for 64bit architectures
#   
#   D:2004/09/21 11:32:27
#   C:RME HDSP driver
#   F:include/hdsp.h:1.5->1.6 
#   F:pci/rme9652/hdsp.c:1.68->1.69 
#   L:Fixed the loading of firmware data and the handling of meter mmap
#   L:on 64bit architectures.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/hdsp.h
#   2004/09/21 05:32:27+02:00 perex@suse.cz +1 -1
#   [ALSA]  [hdsp] Fix for 64bit architectures
#   
#   D:2004/09/21 11:32:27
#   C:RME HDSP driver
#   F:include/hdsp.h:1.5->1.6 
#   F:pci/rme9652/hdsp.c:1.68->1.69 
#   L:Fixed the loading of firmware data and the handling of meter mmap
#   L:on 64bit architectures.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:54:19+02:00 perex@suse.cz 
#   [ALSA]  rme32 segfault fix
#   
#   RME32 driver
#   - disables buffer prefill in halfduplex mode, which fixes segmentation fault
#     of rme32 for playback in halfduplex mode
#   
#   Signed-Off-By: Martin Langer <martin-langer@gmx.de>
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme32.c
#   2004/09/20 05:10:47+02:00 perex@suse.cz +1 -1
#   [ALSA]  rme32 segfault fix
#   
#   D:2004/09/20 11:10:47
#   C:RME32 driver
#   F:pci/rme32.c:1.46->1.47 
#   L:- disables buffer prefill in halfduplex mode, which fixes segmentation fault
#   L:  of rme32 for playback in halfduplex mode
#   L:
#   L:Signed-Off-By: Martin Langer <martin-langer@gmx.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:53:57+02:00 perex@suse.cz 
#   [ALSA]  Added support of Mediastation
#   
#   ICE1712 driver
#   The support for Lionstracs Mediastation is added.
#   The model name is 'mediastation'.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/delta.h
#   2004/09/17 12:38:26+02:00 perex@suse.cz +3 -1
#   [ALSA]  Added support of Mediastation
#   
#   D:2004/09/17 18:38:26
#   C:ICE1712 driver
#   F:pci/ice1712/delta.c:1.18->1.19 
#   F:pci/ice1712/delta.h:1.6->1.7 
#   L:The support for Lionstracs Mediastation is added.
#   L:The model name is 'mediastation'.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/delta.c
#   2004/09/17 12:38:26+02:00 perex@suse.cz +13 -0
#   [ALSA]  Added support of Mediastation
#   
#   D:2004/09/17 18:38:26
#   C:ICE1712 driver
#   F:pci/ice1712/delta.c:1.18->1.19 
#   F:pci/ice1712/delta.h:1.6->1.7 
#   L:The support for Lionstracs Mediastation is added.
#   L:The model name is 'mediastation'.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:53:32+02:00 perex@suse.cz 
#   [ALSA]  Fix iomem variable type
#   
#   Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   RME9652 driver,PPC Tumbler driver
#   The type of iomem variables is changed to void __iomem *.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/ppc/tumbler.c
#   2004/09/16 13:40:26+02:00 perex@suse.cz +3 -3
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ymfpci/ymfpci_main.c
#   2004/09/16 13:40:26+02:00 perex@suse.cz +2 -2
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/rme9652.c
#   2004/09/16 13:40:26+02:00 perex@suse.cz +5 -5
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2004/09/16 13:40:26+02:00 perex@suse.cz +29 -29
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme96.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +8 -6
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme32.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +10 -10
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/nm256/nm256.c
#   2004/09/16 13:40:26+02:00 perex@suse.cz +17 -17
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/mixart/mixart.h
#   2004/09/16 13:40:25+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/mixart/mixart.c
#   2004/09/16 13:40:25+02:00 perex@suse.cz +3 -3
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/korg1212/korg1212.c
#   2004/09/16 13:40:25+02:00 perex@suse.cz +34 -33
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0m.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +10 -10
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +10 -10
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs46xx/dsp_spos_scb_lib.c
#   2004/09/16 13:40:25+02:00 perex@suse.cz +2 -2
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs46xx/dsp_spos.c
#   2004/09/16 13:40:25+02:00 perex@suse.cz +5 -5
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2004/09/16 13:40:25+02:00 perex@suse.cz +5 -5
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs4281.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +8 -8
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/au88x0/au88x0.h
#   2004/09/16 13:40:24+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/au88x0/au88x0.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp_modem.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +5 -5
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp.c
#   2004/09/16 13:40:24+02:00 perex@suse.cz +5 -5
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/opl3/opl3_lib.c
#   2004/09/16 13:40:23+02:00 perex@suse.cz +4 -4
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/mpu401/mpu401_uart.c
#   2004/09/16 13:40:23+02:00 perex@suse.cz +2 -2
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/memory.c
#   2004/09/16 13:40:23+02:00 perex@suse.cz +4 -4
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/ymfpci.h
#   2004/09/16 13:40:24+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/cs46xx.h
#   2004/09/16 13:40:24+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/core.h
#   2004/09/16 13:40:24+02:00 perex@suse.cz +2 -2
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
#   2004/09/16 13:40:23+02:00 perex@suse.cz +3 -4
#   [ALSA]  Fix iomem variable type
#   
#   D:2004/09/16 19:40:23
#   C:Documentation,ALSA Core,MPU401 UART,OPL3,CS46xx driver,YMFPCI driver
#   C:ATIIXP driver,ATIIXP-modem driver,CS4281 driver,Intel8x0 driver
#   C:Intel8x0-modem driver,RME32 driver,RME96 driver,au88x0 driver
#   C:KORG1212 driver,MIXART driver,NM256 driver,RME HDSP driver
#   C:RME9652 driver,PPC Tumbler driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.39->1.40 
#   F:core/memory.c:1.31->1.32 
#   F:drivers/mpu401/mpu401_uart.c:1.31->1.32 
#   F:drivers/opl3/opl3_lib.c:1.21->1.22 
#   F:include/core.h:1.57->1.58 
#   F:include/cs46xx.h:1.21->1.22 
#   F:include/ymfpci.h:1.16->1.17 
#   F:pci/atiixp.c:1.23->1.24 
#   F:pci/atiixp_modem.c:1.7->1.8 
#   F:pci/cs4281.c:1.63->1.64 
#   F:pci/intel8x0.c:1.169->1.170 
#   F:pci/intel8x0m.c:1.20->1.21 
#   F:pci/rme32.c:1.45->1.46 
#   F:pci/rme96.c:1.43->1.44 
#   F:pci/au88x0/au88x0.c:1.11->1.12 
#   F:pci/au88x0/au88x0.h:1.7->1.8 
#   F:pci/cs46xx/cs46xx_lib.c:1.84->1.85 
#   F:pci/cs46xx/dsp_spos.c:1.26->1.27 
#   F:pci/cs46xx/dsp_spos_scb_lib.c:1.24->1.25 
#   F:pci/korg1212/korg1212.c:1.48->1.49 
#   F:pci/mixart/mixart.c:1.17->1.18 
#   F:pci/mixart/mixart.h:1.5->1.6 
#   F:pci/nm256/nm256.c:1.50->1.51 
#   F:pci/rme9652/hdsp.c:1.67->1.68 
#   F:pci/rme9652/rme9652.c:1.52->1.53 
#   F:pci/ymfpci/ymfpci_main.c:1.57->1.58 
#   F:ppc/tumbler.c:1.33->1.34 
#   L:The type of iomem variables is changed to void __iomem *.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:53:03+02:00 perex@suse.cz 
#   [ALSA]  Fix auto-loading of sequencer modules
#   
#   ALSA sequencer
#   Allow auto-loading of sequencer modules except for module init time
#   (which may cause blocking).
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_clientmgr.c
#   2004/09/16 13:35:29+02:00 perex@suse.cz +5 -3
#   [ALSA]  Fix auto-loading of sequencer modules
#   
#   D:2004/09/16 19:35:29
#   C:ALSA sequencer
#   F:core/seq/seq.c:1.14->1.15 
#   F:core/seq/seq_clientmgr.c:1.36->1.37 
#   L:Allow auto-loading of sequencer modules except for module init time
#   L:(which may cause blocking).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq.c
#   2004/09/16 13:35:29+02:00 perex@suse.cz +4 -0
#   [ALSA]  Fix auto-loading of sequencer modules
#   
#   D:2004/09/16 19:35:29
#   C:ALSA sequencer
#   F:core/seq/seq.c:1.14->1.15 
#   F:core/seq/seq_clientmgr.c:1.36->1.37 
#   L:Allow auto-loading of sequencer modules except for module init time
#   L:(which may cause blocking).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:52:41+02:00 perex@suse.cz 
#   [ALSA]  Fixed the obsolete description in comments
#   
#   IOCTL32 emulation
#   
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/ioctl32.h
#   2004/09/16 07:27:18+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fixed the obsolete description in comments
#   
#   D:2004/09/16 13:27:18
#   C:IOCTL32 emulation
#   F:core/ioctl32/ioctl32.h:1.14->1.15 
#   L:
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:52:19+02:00 perex@suse.cz 
#   [ALSA]  Improved clock measurement
#   
#   Intel8x0 driver
#   Improved the clock measurement routine to allow the longer sleep time.
#   Now it invokes schedule_timeout() instead of a long mdelay().
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/09/16 07:26:16+02:00 perex@suse.cz +5 -6
#   [ALSA]  Improved clock measurement
#   
#   D:2004/09/16 13:26:16
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.168->1.169 
#   L:Improved the clock measurement routine to allow the longer sleep time.
#   L:Now it invokes schedule_timeout() instead of a long mdelay().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:51:57+02:00 perex@suse.cz 
#   [ALSA]  Remove delay() to improve latency
#   
#   ES1968 driver
#   - Removed mdelay() in ac97 codec handling.
#   - Improved the clock measurement routine to allow the longer sleep time.
#     Now it invokes schedule_timeout() instead of a long mdelay().
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/es1968.c
#   2004/09/16 07:25:25+02:00 perex@suse.cz +28 -20
#   [ALSA]  Remove delay() to improve latency
#   
#   D:2004/09/16 13:25:25
#   C:ES1968 driver
#   F:pci/es1968.c:1.75->1.76 
#   L:- Removed mdelay() in ac97 codec handling.
#   L:- Improved the clock measurement routine to allow the longer sleep time.
#   L:  Now it invokes schedule_timeout() instead of a long mdelay().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:51:34+02:00 perex@suse.cz 
#   [ALSA]  Support for capture of 16,32,64 channels on emu10k1 device 2
#   
#   EMU10K1/EMU10K2 driver
#   This patch changes default constraint on 'EFX voices mask' control and
#   allow capture of 1, 2, 4, 8, 16, 32, 64 channels instead of 1, 2, 4, 8.
#   
#   Signed-off-by: Peter Zubaj <pzad@pobox.sk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2004/09/16 05:36:44+02:00 perex@suse.cz +8 -1
#   [ALSA]  Support for capture of 16,32,64 channels on emu10k1 device 2
#   
#   D:2004/09/16 11:36:44
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emupcm.c:1.31->1.32 
#   L:This patch changes default constraint on 'EFX voices mask' control and
#   L:allow capture of 1, 2, 4, 8, 16, 32, 64 channels instead of 1, 2, 4, 8.
#   Signed-off-by: Peter Zubaj <pzad@pobox.sk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:35:51+02:00 perex@suse.cz 
#   [ALSA]  Fixes for PCM/control 32bit emulation
#   
#   PCM Midlevel,IOCTL32 emulation
#   - Size mismatch of control element struct due to packed attribute
#     is removed.
#   - A typo in PCM syncptr definition is fixed.
#   - Suppress the mmap of PCM status/control records on 32bit emulation
#     mode since the record size doesn't match.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_native.c
#   2004/09/15 04:30:08+02:00 perex@suse.cz +5 -0
#   [ALSA]  Fixes for PCM/control 32bit emulation
#   
#   D:2004/09/15 10:30:08
#   C:PCM Midlevel,IOCTL32 emulation
#   F:core/pcm_native.c:1.105->1.106 
#   F:core/ioctl32/ioctl32.c:1.21->1.22 
#   F:core/ioctl32/pcm32.c:1.20->1.21 
#   F:include/pcm.h:1.47->1.48 
#   L:- Size mismatch of control element struct due to packed attribute
#   L:  is removed.
#   L:- A typo in PCM syncptr definition is fixed.
#   L:- Suppress the mmap of PCM status/control records on 32bit emulation
#   L:  mode since the record size doesn't match.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/pcm32.c
#   2004/09/15 04:30:08+02:00 perex@suse.cz +27 -2
#   [ALSA]  Fixes for PCM/control 32bit emulation
#   
#   D:2004/09/15 10:30:08
#   C:PCM Midlevel,IOCTL32 emulation
#   F:core/pcm_native.c:1.105->1.106 
#   F:core/ioctl32/ioctl32.c:1.21->1.22 
#   F:core/ioctl32/pcm32.c:1.20->1.21 
#   F:include/pcm.h:1.47->1.48 
#   L:- Size mismatch of control element struct due to packed attribute
#   L:  is removed.
#   L:- A typo in PCM syncptr definition is fixed.
#   L:- Suppress the mmap of PCM status/control records on 32bit emulation
#   L:  mode since the record size doesn't match.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/ioctl32.c
#   2004/09/15 04:30:08+02:00 perex@suse.cz +1 -1
#   [ALSA]  Fixes for PCM/control 32bit emulation
#   
#   D:2004/09/15 10:30:08
#   C:PCM Midlevel,IOCTL32 emulation
#   F:core/pcm_native.c:1.105->1.106 
#   F:core/ioctl32/ioctl32.c:1.21->1.22 
#   F:core/ioctl32/pcm32.c:1.20->1.21 
#   F:include/pcm.h:1.47->1.48 
#   L:- Size mismatch of control element struct due to packed attribute
#   L:  is removed.
#   L:- A typo in PCM syncptr definition is fixed.
#   L:- Suppress the mmap of PCM status/control records on 32bit emulation
#   L:  mode since the record size doesn't match.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/pcm.h
#   2004/09/15 04:30:08+02:00 perex@suse.cz +2 -0
#   [ALSA]  Fixes for PCM/control 32bit emulation
#   
#   D:2004/09/15 10:30:08
#   C:PCM Midlevel,IOCTL32 emulation
#   F:core/pcm_native.c:1.105->1.106 
#   F:core/ioctl32/ioctl32.c:1.21->1.22 
#   F:core/ioctl32/pcm32.c:1.20->1.21 
#   F:include/pcm.h:1.47->1.48 
#   L:- Size mismatch of control element struct due to packed attribute
#   L:  is removed.
#   L:- A typo in PCM syncptr definition is fixed.
#   L:- Suppress the mmap of PCM status/control records on 32bit emulation
#   L:  mode since the record size doesn't match.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:35:27+02:00 perex@suse.cz 
#   [ALSA]  fix ALI M5451 description
#   
#   PCI drivers
#   modify ali5451 and intel8x0 help texts to better distinguish
#   between M5451 and M5455 AC97 controllers
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/Kconfig
#   2004/09/13 07:53:25+02:00 perex@suse.cz +8 -4
#   [ALSA]  fix ALI M5451 description
#   
#   D:2004/09/13 13:53:25
#   C:PCI drivers
#   F:pci/Kconfig:1.33->1.34 
#   L:modify ali5451 and intel8x0 help texts to better distinguish
#   L:between M5451 and M5455 AC97 controllers
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 09:35:05+02:00 perex@suse.cz 
#   [ALSA]  remove 'ALSA' from Kconfig USB menu name
#   
#   USB
#   make ISA, PCI and USB device look the same in {q,x,menu}config
#   
#   Signed-off-by: Thierry Vignaud <tvignaud@mandrakesoft.com>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/Kconfig
#   2004/09/13 05:53:20+02:00 perex@suse.cz +1 -1
#   [ALSA]  remove 'ALSA' from Kconfig USB menu name
#   
#   D:2004/09/13 11:53:20
#   C:USB
#   F:usb/Kconfig:1.6->1.7 
#   L:make ISA, PCI and USB device look the same in {q,x,menu}config
#   Signed-off-by: Thierry Vignaud <tvignaud@mandrakesoft.com>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 09:34:41+02:00 perex@suse.cz 
#   [ALSA]  enhance Kconfig help texts
#   
#   ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   USB
#   add module names and references to other documentation files
#   add more help for generic options
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/Kconfig
#   2004/09/13 02:15:00+02:00 perex@suse.cz +9 -2
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/ppc/Kconfig
#   2004/09/13 02:14:59+02:00 perex@suse.cz +5 -0
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pcmcia/Kconfig
#   2004/09/13 02:14:59+02:00 perex@suse.cz +15 -3
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/Kconfig
#   2004/09/13 02:14:59+02:00 perex@suse.cz +200 -63
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/parisc/Kconfig
#   2004/09/13 02:14:59+02:00 perex@suse.cz +4 -1
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/isa/Kconfig
#   2004/09/13 02:14:59+02:00 perex@suse.cz +141 -48
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/Kconfig
#   2004/09/13 02:14:59+02:00 perex@suse.cz +38 -10
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/Kconfig
#   2004/09/13 02:14:59+02:00 perex@suse.cz +57 -18
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/arm/Kconfig
#   2004/09/13 02:14:58+02:00 perex@suse.cz +6 -3
#   [ALSA]  enhance Kconfig help texts
#   
#   D:2004/09/13 08:14:58
#   C:ARM,ALSA Core,Generic drivers,ISA,PARISC,PCI drivers,PCMCIA Kconfig,PPC
#   C:USB
#   F:arm/Kconfig:1.2->1.3 
#   F:core/Kconfig:1.5->1.6 
#   F:drivers/Kconfig:1.6->1.7 
#   F:isa/Kconfig:1.13->1.14 
#   F:parisc/Kconfig:1.2->1.3 
#   F:pci/Kconfig:1.32->1.33 
#   F:pcmcia/Kconfig:1.7->1.8 
#   F:ppc/Kconfig:1.4->1.5 
#   F:usb/Kconfig:1.5->1.6 
#   L:add module names and references to other documentation files
#   L:add more help for generic options
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 09:34:18+02:00 perex@suse.cz 
#   [ALSA]  adjust intel8x0 joystick documentation
#   
#   Documentation
#   
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/Joystick.txt
#   2004/09/13 01:56:22+02:00 perex@suse.cz +4 -6
#   [ALSA]  adjust intel8x0 joystick documentation
#   
#   D:2004/09/13 07:56:22
#   C:Documentation
#   F:Documentation/Joystick.txt:1.3->1.4 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 09:33:57+02:00 perex@suse.cz 
#   [ALSA]  show codec name in card description
#   
#   AC97 Codec Core,ATIIXP driver,Intel8x0 driver,VIA82xx driver
#   Include the AC97 codec name in the card longname of
#   motherboard controllers.
#   (to enhance the chance of getting useful bug reports :)
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/via82xx.c
#   2004/09/10 09:19:29+02:00 perex@suse.cz +3 -2
#   [ALSA]  show codec name in card description
#   
#   D:2004/09/10 15:19:28
#   C:AC97 Codec Core,ATIIXP driver,Intel8x0 driver,VIA82xx driver
#   F:include/ac97_codec.h:1.55->1.56 
#   F:pci/atiixp.c:1.22->1.23 
#   F:pci/intel8x0.c:1.167->1.168 
#   F:pci/via82xx.c:1.121->1.122 
#   F:pci/ac97/ac97_codec.c:1.148->1.149 
#   L:Include the AC97 codec name in the card longname of
#   L:motherboard controllers.
#   L:(to enhance the chance of getting useful bug reports :)
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/intel8x0.c
#   2004/09/10 09:19:29+02:00 perex@suse.cz +3 -2
#   [ALSA]  show codec name in card description
#   
#   D:2004/09/10 15:19:28
#   C:AC97 Codec Core,ATIIXP driver,Intel8x0 driver,VIA82xx driver
#   F:include/ac97_codec.h:1.55->1.56 
#   F:pci/atiixp.c:1.22->1.23 
#   F:pci/intel8x0.c:1.167->1.168 
#   F:pci/via82xx.c:1.121->1.122 
#   F:pci/ac97/ac97_codec.c:1.148->1.149 
#   L:Include the AC97 codec name in the card longname of
#   L:motherboard controllers.
#   L:(to enhance the chance of getting useful bug reports :)
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/atiixp.c
#   2004/09/10 09:19:29+02:00 perex@suse.cz +4 -2
#   [ALSA]  show codec name in card description
#   
#   D:2004/09/10 15:19:28
#   C:AC97 Codec Core,ATIIXP driver,Intel8x0 driver,VIA82xx driver
#   F:include/ac97_codec.h:1.55->1.56 
#   F:pci/atiixp.c:1.22->1.23 
#   F:pci/intel8x0.c:1.167->1.168 
#   F:pci/via82xx.c:1.121->1.122 
#   F:pci/ac97/ac97_codec.c:1.148->1.149 
#   L:Include the AC97 codec name in the card longname of
#   L:motherboard controllers.
#   L:(to enhance the chance of getting useful bug reports :)
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/09/10 09:19:29+02:00 perex@suse.cz +17 -0
#   [ALSA]  show codec name in card description
#   
#   D:2004/09/10 15:19:28
#   C:AC97 Codec Core,ATIIXP driver,Intel8x0 driver,VIA82xx driver
#   F:include/ac97_codec.h:1.55->1.56 
#   F:pci/atiixp.c:1.22->1.23 
#   F:pci/intel8x0.c:1.167->1.168 
#   F:pci/via82xx.c:1.121->1.122 
#   F:pci/ac97/ac97_codec.c:1.148->1.149 
#   L:Include the AC97 codec name in the card longname of
#   L:motherboard controllers.
#   L:(to enhance the chance of getting useful bug reports :)
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# include/sound/ac97_codec.h
#   2004/09/10 09:19:28+02:00 perex@suse.cz +1 -0
#   [ALSA]  show codec name in card description
#   
#   D:2004/09/10 15:19:28
#   C:AC97 Codec Core,ATIIXP driver,Intel8x0 driver,VIA82xx driver
#   F:include/ac97_codec.h:1.55->1.56 
#   F:pci/atiixp.c:1.22->1.23 
#   F:pci/intel8x0.c:1.167->1.168 
#   F:pci/via82xx.c:1.121->1.122 
#   F:pci/ac97/ac97_codec.c:1.148->1.149 
#   L:Include the AC97 codec name in the card longname of
#   L:motherboard controllers.
#   L:(to enhance the chance of getting useful bug reports :)
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 09:33:34+02:00 perex@suse.cz 
#   [ALSA]  Fix driver name for nforce and clean-up
#   
#   Intel8x0-modem driver
#   Driver name is always ICH-MODEM as defined in alsa-lib config.
#   Cosmetic cleanups: unused include files, MODULE_DEVICE update.
#   
#   Signed-off-by: Sasha Khapyorsky <sashak@smlink.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0m.c
#   2004/09/08 10:23:50+02:00 perex@suse.cz +8 -13
#   [ALSA]  Fix driver name for nforce and clean-up
#   
#   D:2004/09/08 16:23:50
#   C:Intel8x0-modem driver
#   F:pci/intel8x0m.c:1.19->1.20 
#   L:Driver name is always ICH-MODEM as defined in alsa-lib config.
#   L:Cosmetic cleanups: unused include files, MODULE_DEVICE update.
#   Signed-off-by: Sasha Khapyorsky <sashak@smlink.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/22 09:33:11+02:00 perex@suse.cz 
#   [ALSA]  Added missing header file for AudioTrak Prodigy 192 cards
#   
#   ICE1712 driver
#   
#   
#   Signed-off-by: Kouichi ONO <co2b@ceres.dti.ne.jp>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/stac946x.h
#   2004/09/22 09:09:18+02:00 perex@suse.cz +25 -0
#   [ALSA]  Added missing header file for AudioTrak Prodigy 192 cards
#   
#   D:2004/09/08 12:28:25
#   C:ICE1712 driver
#   F:pci/ice1712/stac946x.h:INITIAL->1.1 
#   L:
#   Signed-off-by: Kouichi ONO <co2b@ceres.dti.ne.jp>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/stac946x.h
#   2004/09/22 09:09:18+02:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/stac946x.h
# 
# ChangeSet
#   2004/09/22 09:32:47+02:00 perex@suse.cz 
#   [ALSA]  copy_to_user() return value checking in snd_seq_read()
#   
#   ALSA sequencer
#   Here's a patch that ensures the copy_to_user() return value gets checked
#   and acted upon if it is != 0 (that is, if we failed to copy all data) in
#   snd_seq_read().
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/seq/seq_clientmgr.c
#   2004/09/07 14:22:28+02:00 perex@suse.cz +4 -1
#   [ALSA]  copy_to_user() return value checking in snd_seq_read()
#   
#   D:2004/09/07 20:22:28
#   C:ALSA sequencer
#   F:core/seq/seq_clientmgr.c:1.35->1.36 
#   L:Here's a patch that ensures the copy_to_user() return value gets checked
#   L:and acted upon if it is != 0 (that is, if we failed to copy all data) in
#   L:snd_seq_read().
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/09/22 09:32:20+02:00 perex@suse.cz 
#   [ALSA]  [ac97 core] added AC97_SCAP_DETECT_BY_VENDOR flag
#   
#   AC97 Codec Core,Intel8x0 driver
#   This patch adds a AC97_SCAP_DETECT_BY_VENDOR flag for Xbox. If the flag
#   is set, the AC97 codec is detected only by reading of a reasonable
#   vendor ID. It seems that Xbox has accessible only vendor/device ID
#   registers for reading. Also, a new xbox parameter for snd-intel8x0
#   has been introduced to let user force this behaviour.
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/intel8x0.c
#   2004/09/07 10:58:24+02:00 perex@suse.cz +8 -0
#   [ALSA]  [ac97 core] added AC97_SCAP_DETECT_BY_VENDOR flag
#   
#   D:2004/09/07 16:58:24
#   C:AC97 Codec Core,Intel8x0 driver
#   F:include/ac97_codec.h:1.54->1.55 
#   F:pci/intel8x0.c:1.166->1.167 
#   F:pci/ac97/ac97_codec.c:1.147->1.148 
#   L:This patch adds a AC97_SCAP_DETECT_BY_VENDOR flag for Xbox. If the flag
#   L:is set, the AC97 codec is detected only by reading of a reasonable
#   L:vendor ID. It seems that Xbox has accessible only vendor/device ID
#   L:registers for reading. Also, a new xbox parameter for snd-intel8x0
#   L:has been introduced to let user force this behaviour.
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/09/07 10:58:24+02:00 perex@suse.cz +18 -10
#   [ALSA]  [ac97 core] added AC97_SCAP_DETECT_BY_VENDOR flag
#   
#   D:2004/09/07 16:58:24
#   C:AC97 Codec Core,Intel8x0 driver
#   F:include/ac97_codec.h:1.54->1.55 
#   F:pci/intel8x0.c:1.166->1.167 
#   F:pci/ac97/ac97_codec.c:1.147->1.148 
#   L:This patch adds a AC97_SCAP_DETECT_BY_VENDOR flag for Xbox. If the flag
#   L:is set, the AC97 codec is detected only by reading of a reasonable
#   L:vendor ID. It seems that Xbox has accessible only vendor/device ID
#   L:registers for reading. Also, a new xbox parameter for snd-intel8x0
#   L:has been introduced to let user force this behaviour.
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# include/sound/ac97_codec.h
#   2004/09/07 10:58:24+02:00 perex@suse.cz +1 -0
#   [ALSA]  [ac97 core] added AC97_SCAP_DETECT_BY_VENDOR flag
#   
#   D:2004/09/07 16:58:24
#   C:AC97 Codec Core,Intel8x0 driver
#   F:include/ac97_codec.h:1.54->1.55 
#   F:pci/intel8x0.c:1.166->1.167 
#   F:pci/ac97/ac97_codec.c:1.147->1.148 
#   L:This patch adds a AC97_SCAP_DETECT_BY_VENDOR flag for Xbox. If the flag
#   L:is set, the AC97 codec is detected only by reading of a reasonable
#   L:vendor ID. It seems that Xbox has accessible only vendor/device ID
#   L:registers for reading. Also, a new xbox parameter for snd-intel8x0
#   L:has been introduced to let user force this behaviour.
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/09/22 09:30:18+02:00 perex@suse.cz 
#   [ALSA]  mark snd_card_dummy_new_mixer() as static
#   
#   Generic drivers
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/drivers/dummy.c
#   2004/09/07 10:52:40+02:00 perex@suse.cz +1 -1
#   [ALSA]  mark snd_card_dummy_new_mixer() as static
#   
#   D:2004/09/07 16:52:40
#   C:Generic drivers
#   F:drivers/dummy.c:1.32->1.33 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/09/22 09:29:41+02:00 perex@suse.cz 
#   [ALSA]  add UA-1000 sample rate detection
#   
#   USB generic driver
#   Instead of assuming 48 kHz, the driver now detects
#   the current sample rate setting.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2004/09/07 10:09:08+02:00 perex@suse.cz +2 -28
#   [ALSA]  add UA-1000 sample rate detection
#   
#   D:2004/09/07 16:09:08
#   C:USB generic driver
#   F:usb/usbaudio.c:1.107->1.108 
#   F:usb/usbaudio.h:1.33->1.34 
#   F:usb/usbquirks.h:1.36->1.37 
#   L:Instead of assuming 48 kHz, the driver now detects
#   L:the current sample rate setting.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.h
#   2004/09/07 10:09:08+02:00 perex@suse.cz +2 -1
#   [ALSA]  add UA-1000 sample rate detection
#   
#   D:2004/09/07 16:09:08
#   C:USB generic driver
#   F:usb/usbaudio.c:1.107->1.108 
#   F:usb/usbaudio.h:1.33->1.34 
#   F:usb/usbquirks.h:1.36->1.37 
#   L:Instead of assuming 48 kHz, the driver now detects
#   L:the current sample rate setting.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.c
#   2004/09/07 10:09:08+02:00 perex@suse.cz +52 -0
#   [ALSA]  add UA-1000 sample rate detection
#   
#   D:2004/09/07 16:09:08
#   C:USB generic driver
#   F:usb/usbaudio.c:1.107->1.108 
#   F:usb/usbaudio.h:1.33->1.34 
#   F:usb/usbquirks.h:1.36->1.37 
#   L:Instead of assuming 48 kHz, the driver now detects
#   L:the current sample rate setting.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/22 09:29:10+02:00 perex@suse.cz 
#   [ALSA]  Added support for AudioTrak Prodigy 192 cards
#   
#   ICE1712 driver,ICE1724 driver
#   
#   
#   Signed-off-by: Kouichi ONO <co2b@ceres.dti.ne.jp>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/prodigy192.h
#   2004/09/22 09:08:13+02:00 perex@suse.cz +11 -0
#   [ALSA]  Added support for AudioTrak Prodigy 192 cards
#   
#   D:2004/09/07 16:02:49
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.13->1.14 
#   F:pci/ice1712/ice1724.c:1.44->1.45 
#   F:pci/ice1712/prodigy192.c:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.h:INITIAL->1.1 
#   L:
#   Signed-off-by: Kouichi ONO <co2b@ceres.dti.ne.jp>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/prodigy192.h
#   2004/09/22 09:08:13+02:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/prodigy192.h
# 
# sound/pci/ice1712/ice1724.c
#   2004/09/07 10:02:49+02:00 perex@suse.cz +3 -0
#   [ALSA]  Added support for AudioTrak Prodigy 192 cards
#   
#   D:2004/09/07 16:02:49
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.13->1.14 
#   F:pci/ice1712/ice1724.c:1.44->1.45 
#   F:pci/ice1712/prodigy192.c:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.h:INITIAL->1.1 
#   L:
#   Signed-off-by: Kouichi ONO <co2b@ceres.dti.ne.jp>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/Makefile
#   2004/09/07 10:02:49+02:00 perex@suse.cz +1 -1
#   [ALSA]  Added support for AudioTrak Prodigy 192 cards
#   
#   D:2004/09/07 16:02:49
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.13->1.14 
#   F:pci/ice1712/ice1724.c:1.44->1.45 
#   F:pci/ice1712/prodigy192.c:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.h:INITIAL->1.1 
#   L:
#   Signed-off-by: Kouichi ONO <co2b@ceres.dti.ne.jp>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/prodigy192.c
#   2004/09/22 09:08:08+02:00 perex@suse.cz +524 -0
#   [ALSA]  Added support for AudioTrak Prodigy 192 cards
#   
#   D:2004/09/07 16:02:49
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.13->1.14 
#   F:pci/ice1712/ice1724.c:1.44->1.45 
#   F:pci/ice1712/prodigy192.c:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.h:INITIAL->1.1 
#   L:
#   Signed-off-by: Kouichi ONO <co2b@ceres.dti.ne.jp>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/prodigy192.c
#   2004/09/22 09:08:08+02:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/prodigy192.c
# 
# ChangeSet
#   2004/09/22 09:28:40+02:00 perex@suse.cz 
#   [ALSA]  Fix the OSS PCM emulation - O_NONBLOCK write
#   
#   ALSA<-OSS emulation
#   This patch fixes the OSS PCM write() in O_NONBLOCK mode.
#   The previous code had not returned partial written bytes.
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/oss/pcm_oss.c
#   2004/09/07 09:17:48+02:00 perex@suse.cz +9 -1
#   [ALSA]  Fix the OSS PCM emulation - O_NONBLOCK write
#   
#   D:2004/09/07 15:17:48
#   C:ALSA<-OSS emulation
#   F:core/oss/pcm_oss.c:1.77->1.78 
#   L:This patch fixes the OSS PCM write() in O_NONBLOCK mode.
#   L:The previous code had not returned partial written bytes.
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2004/09/20 15:29:26-04:00 jgarzik@pobox.com 
#   Merge
# 
# drivers/net/smc91x.h
#   2004/09/20 15:29:25-04:00 jgarzik@pobox.com +0 -0
#   SCCS merged
# 
# drivers/net/Kconfig
#   2004/09/20 15:28:07-04:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/09/20 15:17:45-04:00 ralf@linux-mips.org 
#   [PATCH] Stop queue on close in hdlcdrv
#   
#   The stop method of a driver should ensure queueing is stopped ...
# 
# drivers/net/hamradio/hdlcdrv.c
#   2004/05/04 07:47:17-04:00 ralf@linux-mips.org +2 -0
#   Stop queue on close in hdlcdrv
# 
# ChangeSet
#   2004/09/20 14:44:20-04:00 romieu@fr.zoreil.com 
#   [PATCH] via-velocity: wrong module name in Kconfig documentation
#   
#   Copy/paste abuse.
# 
# drivers/net/Kconfig
#   2004/08/14 06:11:16-04:00 romieu@fr.zoreil.com +1 -1
#   via-velocity: wrong module name in Kconfig documentation
# 
# ChangeSet
#   2004/09/20 14:34:45-04:00 pavel@ucw.cz 
#   [PATCH] swsuspend for ne2k-pci cards
#   
#   Author: Éric Brunet <Eric.Brunet@lps.ens.fr>
# 
# drivers/net/ne2k-pci.c
#   2004/08/21 06:24:27-04:00 pavel@ucw.cz +31 -0
#   PATCH: swsuspend for ne2k-pci cards
# 
# ChangeSet
#   2004/09/20 14:03:45-04:00 shemminger@osdl.org 
#   [PATCH] (4/4) acenic - don't spin forever in hard_start_xmit
#   
#   If driver is stuck due to ring full and hardware or link error, don't spin
#   forever in the hard_start_xmit routine.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.c
#   2004/09/20 13:47:22-04:00 shemminger@osdl.org +11 -3
#   (4/4) acenic - don't spin forever in hard_start_xmit
# 
# ChangeSet
#   2004/09/20 14:03:34-04:00 shemminger@osdl.org 
#   [PATCH] (3/4) acenic - __iomem warnings cleanup
#   
#   This cleans all the compile warnings and most of the sparse warnings
#   for the acenic driver relating to io memory space.
#   Remaining warnings are because tx_ring can be either in i/o or not
#   depending on the version of the card.
#   Not tested on old TIGON card.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.h
#   2004/09/20 13:47:00-04:00 shemminger@osdl.org +4 -4
#   (3/4) acenic - __iomem warnings cleanup
# 
# drivers/net/acenic.c
#   2004/09/20 13:47:00-04:00 shemminger@osdl.org +57 -80
#   (3/4) acenic - __iomem warnings cleanup
# 
# ChangeSet
#   2004/09/20 14:03:22-04:00 shemminger@osdl.org 
#   [PATCH] (2/4) acenic - eliminate MAX_SKB_FRAGS #if
#   
#   Since MAX_SKB_FRAGS is defined in both 2.4 and 2.6, it makes sense
#   to eliminate this old #if code.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.h
#   2004/09/20 13:46:46-04:00 shemminger@osdl.org +0 -11
#   (2/4) acenic - eliminate MAX_SKB_FRAGS #if
# 
# drivers/net/acenic.c
#   2004/09/20 13:46:46-04:00 shemminger@osdl.org +2 -8
#   (2/4) acenic - eliminate MAX_SKB_FRAGS #if
# 
# ChangeSet
#   2004/09/20 14:03:11-04:00 shemminger@osdl.org 
#   [PATCH] (1/4) acenic - use netdev_priv
#   
#   Trivial, use netdev_priv
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/acenic.h
#   2004/09/20 13:46:22-04:00 shemminger@osdl.org +2 -2
#   (1/4) acenic - use netdev_priv
# 
# drivers/net/acenic.c
#   2004/09/20 13:46:22-04:00 shemminger@osdl.org +1 -1
#   (1/4) acenic - use netdev_priv
# 
# ChangeSet
#   2004/09/17 10:37:55-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Ethtool -- 82545 do not support WoL
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -0
#   e1000 - Ethtool -- 82545 do not support WoL
# 
# ChangeSet
#   2004/09/17 10:37:43-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Polarity reversal workaround for 10F/10H links
# 
# drivers/net/e1000/e1000_osdep.h
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +6 -0
#   e1000 - Polarity reversal workaround for 10F/10H links
# 
# drivers/net/e1000/e1000_hw.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +115 -0
#   e1000 - Polarity reversal workaround for 10F/10H links
# 
# ChangeSet
#   2004/09/17 10:37:32-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Fix VLAN filter setup errors (while running on PPC)
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +4 -4
#   e1000 - Fix VLAN filter setup errors (while running on PPC)
# 
# ChangeSet
#   2004/09/17 10:37:20-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 Check value returned by from pci_enable_device
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -2
#   e1000 Check value returned by from pci_enable_device
# 
# drivers/net/e1000/e1000_ethtool.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -2
#   e1000 Check value returned by from pci_enable_device
# 
# ChangeSet
#   2004/09/17 10:37:08-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - Removed support for advanced TCO features
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +2 -9
#   e1000 - Removed support for advanced TCO features
# 
# ChangeSet
#   2004/09/17 10:36:56-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e1000 - use pci_device_name for syslog messages till
#   registering netdevice.
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +5 -11
#   e1000 - use pci_device_name for syslog messages till
#   registering netdevice.
# 
# drivers/net/e1000/e1000.h
#   2004/09/09 14:17:12-04:00 ganesh.venkatesan@intel.com +0 -2
#   e1000 - use pci_device_name for syslog messages till
#   registering netdevice.
# 
# ChangeSet
#   2004/09/17 10:26:28-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100 driver version number update
# 
# drivers/net/e100.c
#   2004/09/09 17:51:32-04:00 ganesh.venkatesan@intel.com +2 -2
#   e100 driver version number update
# 
# ChangeSet
#   2004/09/17 10:26:17-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100 - use NET_IP_ALIGN to set rx data buffer alignment
# 
# drivers/net/e100.c
#   2004/09/09 17:51:32-04:00 ganesh.venkatesan@intel.com +2 -4
#   e100 - use NET_IP_ALIGN to set rx data buffer alignment
# 
# ChangeSet
#   2004/09/17 10:26:04-04:00 ganesh.venkatesan@intel.com 
#   [PATCH] e100 - Use pci_device_name for syslog messages till registering netdevice
# 
# drivers/net/e100.c
#   2004/09/09 17:51:32-04:00 ganesh.venkatesan@intel.com +2 -0
#   e100 - Use pci_device_name for syslog messages till registering netdevice
# 
# ChangeSet
#   2004/09/16 20:21:15-04:00 akpm@osdl.org 
#   [PATCH] add missing pci_disable_device for e1000
#   
#   From: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
#   
#   This patch adds pci_disable_device() into e1000_remove().
#   
#   If your driver decides to stop using the device, it should call
#   pci_disable_device() to deallocate any IRQ resources, disable PCI
#   bus-mastering, etc.
#   
#   Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/e1000/e1000_main.c
#   2004/09/13 02:03:20-04:00 akpm@osdl.org +2 -0
#   add missing pci_disable_device for e1000
# 
# ChangeSet
#   2004/09/06 20:33:07+02:00 perex@suse.cz 
#   [ALSA]  [emu10k1] Audigy DSP support
#   
#   EMU10K1/EMU10K2 driver
#   This patch will add better support for Audigy DSP.  More gpr,
#   instruction and tram.  It will break binary compatibility for app
#   which use emu10k1 hwdep.
#   
#   Signed-off-by: Peter Zubaj <pzad@pobox.sk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emuproc.c
#   2004/09/06 10:05:19+02:00 perex@suse.cz +19 -11
#   [ALSA]  [emu10k1] Audigy DSP support
#   
#   D:2004/09/06 16:05:18
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.45->1.46 
#   F:pci/emu10k1/emufx.c:1.58->1.59 
#   F:pci/emu10k1/emuproc.c:1.20->1.21 
#   L:This patch will add better support for Audigy DSP.  More gpr,
#   L:instruction and tram.  It will break binary compatibility for app
#   L:which use emu10k1 hwdep.
#   Signed-off-by: Peter Zubaj <pzad@pobox.sk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emufx.c
#   2004/09/06 10:05:18+02:00 perex@suse.cz +25 -17
#   [ALSA]  [emu10k1] Audigy DSP support
#   
#   D:2004/09/06 16:05:18
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.45->1.46 
#   F:pci/emu10k1/emufx.c:1.58->1.59 
#   F:pci/emu10k1/emuproc.c:1.20->1.21 
#   L:This patch will add better support for Audigy DSP.  More gpr,
#   L:instruction and tram.  It will break binary compatibility for app
#   L:which use emu10k1 hwdep.
#   Signed-off-by: Peter Zubaj <pzad@pobox.sk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/emu10k1.h
#   2004/09/06 10:05:18+02:00 perex@suse.cz +37 -24
#   [ALSA]  [emu10k1] Audigy DSP support
#   
#   D:2004/09/06 16:05:18
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.45->1.46 
#   F:pci/emu10k1/emufx.c:1.58->1.59 
#   F:pci/emu10k1/emuproc.c:1.20->1.21 
#   L:This patch will add better support for Audigy DSP.  More gpr,
#   L:instruction and tram.  It will break binary compatibility for app
#   L:which use emu10k1 hwdep.
#   Signed-off-by: Peter Zubaj <pzad@pobox.sk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:25:33+02:00 perex@suse.cz 
#   [ALSA]  Added Compaq Evo W4000 quirk
#   
#   Intel8x0 driver
#   Added an AC97 quirk entry for Compaq Evo W4000.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/09/06 07:51:11+02:00 perex@suse.cz +6 -0
#   [ALSA]  Added Compaq Evo W4000 quirk
#   
#   D:2004/09/06 13:51:11
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.165->1.166 
#   L:Added an AC97 quirk entry for Compaq Evo W4000.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:24:49+02:00 perex@suse.cz 
#   [ALSA]  detect errors reported by the hardware
#   
#   BT87x driver
#   stop the PCM if the hardware reports FIFO/PCI errors
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/bt87x.c
#   2004/09/06 03:10:32+02:00 perex@suse.cz +3 -2
#   [ALSA]  detect errors reported by the hardware
#   
#   D:2004/09/06 09:10:32
#   C:BT87x driver
#   F:pci/bt87x.c:1.11->1.12 
#   L:stop the PCM if the hardware reports FIFO/PCI errors
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/06 20:24:04+02:00 perex@suse.cz 
#   [ALSA]  inverted EAPD support
#   
#   Documentation,AC97 Codec Core,Intel8x0 driver,CS46xx driver
#   Since there are more than one (broken) implementation of EAPD bit
#   on ac97 chips, the new scaps bit is added for the inverted EAPD.
#   Also, AC97_TUNE_INV_EAPD is used to tune this behavior later by
#   snd_ac97_tune_hardware().
#   
#   The ac97 quirk entry for Sony S1XP is added to turn this on.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2004/09/03 09:21:14+02:00 perex@suse.cz +6 -0
#   [ALSA]  inverted EAPD support
#   
#   D:2004/09/03 15:21:13
#   C:Documentation,AC97 Codec Core,Intel8x0 driver,CS46xx driver
#   F:Documentation/ALSA-Configuration.txt:1.51->1.52 
#   F:include/ac97_codec.h:1.53->1.54 
#   F:pci/intel8x0.c:1.164->1.165 
#   F:pci/ac97/ac97_codec.c:1.146->1.147 
#   F:pci/cs46xx/cs46xx_lib.c:1.83->1.84 
#   L:Since there are more than one (broken) implementation of EAPD bit
#   L:on ac97 chips, the new scaps bit is added for the inverted EAPD.
#   L:Also, AC97_TUNE_INV_EAPD is used to tune this behavior later by
#   L:snd_ac97_tune_hardware().
#   L:
#   L:The ac97 quirk entry for Sony S1XP is added to turn this on.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2004/09/03 09:21:24+02:00 perex@suse.cz +2 -12
#   [ALSA]  inverted EAPD support
#   
#   D:2004/09/03 15:21:13
#   C:Documentation,AC97 Codec Core,Intel8x0 driver,CS46xx driver
#   F:Documentation/ALSA-Configuration.txt:1.51->1.52 
#   F:include/ac97_codec.h:1.53->1.54 
#   F:pci/intel8x0.c:1.164->1.165 
#   F:pci/ac97/ac97_codec.c:1.146->1.147 
#   F:pci/cs46xx/cs46xx_lib.c:1.83->1.84 
#   L:Since there are more than one (broken) implementation of EAPD bit
#   L:on ac97 chips, the new scaps bit is added for the inverted EAPD.
#   L:Also, AC97_TUNE_INV_EAPD is used to tune this behavior later by
#   L:snd_ac97_tune_hardware().
#   L:
#   L:The ac97 quirk entry for Sony S1XP is added to turn this on.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/09/03 09:21:14+02:00 perex@suse.cz +30 -6
#   [ALSA]  inverted EAPD support
#   
#   D:2004/09/03 15:21:13
#   C:Documentation,AC97 Codec Core,Intel8x0 driver,CS46xx driver
#   F:Documentation/ALSA-Configuration.txt:1.51->1.52 
#   F:include/ac97_codec.h:1.53->1.54 
#   F:pci/intel8x0.c:1.164->1.165 
#   F:pci/ac97/ac97_codec.c:1.146->1.147 
#   F:pci/cs46xx/cs46xx_lib.c:1.83->1.84 
#   L:Since there are more than one (broken) implementation of EAPD bit
#   L:on ac97 chips, the new scaps bit is added for the inverted EAPD.
#   L:Also, AC97_TUNE_INV_EAPD is used to tune this behavior later by
#   L:snd_ac97_tune_hardware().
#   L:
#   L:The ac97 quirk entry for Sony S1XP is added to turn this on.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/ac97_codec.h
#   2004/09/03 09:21:14+02:00 perex@suse.cz +2 -0
#   [ALSA]  inverted EAPD support
#   
#   D:2004/09/03 15:21:13
#   C:Documentation,AC97 Codec Core,Intel8x0 driver,CS46xx driver
#   F:Documentation/ALSA-Configuration.txt:1.51->1.52 
#   F:include/ac97_codec.h:1.53->1.54 
#   F:pci/intel8x0.c:1.164->1.165 
#   F:pci/ac97/ac97_codec.c:1.146->1.147 
#   F:pci/cs46xx/cs46xx_lib.c:1.83->1.84 
#   L:Since there are more than one (broken) implementation of EAPD bit
#   L:on ac97 chips, the new scaps bit is added for the inverted EAPD.
#   L:Also, AC97_TUNE_INV_EAPD is used to tune this behavior later by
#   L:snd_ac97_tune_hardware().
#   L:
#   L:The ac97 quirk entry for Sony S1XP is added to turn this on.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2004/09/03 09:21:13+02:00 perex@suse.cz +1 -0
#   [ALSA]  inverted EAPD support
#   
#   D:2004/09/03 15:21:13
#   C:Documentation,AC97 Codec Core,Intel8x0 driver,CS46xx driver
#   F:Documentation/ALSA-Configuration.txt:1.51->1.52 
#   F:include/ac97_codec.h:1.53->1.54 
#   F:pci/intel8x0.c:1.164->1.165 
#   F:pci/ac97/ac97_codec.c:1.146->1.147 
#   F:pci/cs46xx/cs46xx_lib.c:1.83->1.84 
#   L:Since there are more than one (broken) implementation of EAPD bit
#   L:on ac97 chips, the new scaps bit is added for the inverted EAPD.
#   L:Also, AC97_TUNE_INV_EAPD is used to tune this behavior later by
#   L:snd_ac97_tune_hardware().
#   L:
#   L:The ac97 quirk entry for Sony S1XP is added to turn this on.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:23:17+02:00 perex@suse.cz 
#   [ALSA]  ac97 quirk entry for Soltek SL-75DRV5
#   
#   VIA82xx driver
#   Added an ac97 quirk entry for Soltek SL-75DRV5.
#   Since the PCI subsystem id is identical with ASRock K7VT2, codec_id is
#   used additionally to tell between them.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2004/09/03 09:17:29+02:00 perex@suse.cz +7 -0
#   [ALSA]  ac97 quirk entry for Soltek SL-75DRV5
#   
#   D:2004/09/03 15:17:29
#   C:VIA82xx driver
#   F:pci/via82xx.c:1.120->1.121 
#   L:Added an ac97 quirk entry for Soltek SL-75DRV5.
#   L:Since the PCI subsystem id is identical with ASRock K7VT2, codec_id is
#   L:used additionally to tell between them.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:22:32+02:00 perex@suse.cz 
#   [ALSA]  [ac97] Check ac97 codec id in quirk table
#   
#   AC97 Codec Core
#   Added codec_id field to ac97_quirk struct so that the devices with
#   the same PCI subsystem IDs but with different AC97 chips can be
#   distinguished properly.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/09/03 09:15:35+02:00 perex@suse.cz +2 -0
#   [ALSA]  [ac97] Check ac97 codec id in quirk table
#   
#   D:2004/09/03 15:15:35
#   C:AC97 Codec Core
#   F:include/ac97_codec.h:1.52->1.53 
#   F:pci/ac97/ac97_codec.c:1.145->1.146 
#   L:Added codec_id field to ac97_quirk struct so that the devices with
#   L:the same PCI subsystem IDs but with different AC97 chips can be
#   L:distinguished properly.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/ac97_codec.h
#   2004/09/03 09:15:35+02:00 perex@suse.cz +1 -0
#   [ALSA]  [ac97] Check ac97 codec id in quirk table
#   
#   D:2004/09/03 15:15:35
#   C:AC97 Codec Core
#   F:include/ac97_codec.h:1.52->1.53 
#   F:pci/ac97/ac97_codec.c:1.145->1.146 
#   L:Added codec_id field to ac97_quirk struct so that the devices with
#   L:the same PCI subsystem IDs but with different AC97 chips can be
#   L:distinguished properly.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:21:46+02:00 perex@suse.cz 
#   [ALSA]  [ac97] Added VIA shared type.
#   
#   AC97 Codec Core,VIA82xx driver
#   Added a new shared type AC97_SHARED_TYPE_VIA for via82xx southbridge
#   to share codecs between audio and modem drivers.
#   
#   Signed-off-by: Sasha Khapyorsky <sashak@smlink.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2004/09/03 08:50:25+02:00 perex@suse.cz +1 -0
#   [ALSA]  [ac97] Added VIA shared type.
#   
#   D:2004/09/03 14:50:25
#   C:AC97 Codec Core,VIA82xx driver
#   F:include/ac97_codec.h:1.51->1.52 
#   F:pci/via82xx.c:1.119->1.120 
#   L:Added a new shared type AC97_SHARED_TYPE_VIA for via82xx southbridge
#   L:to share codecs between audio and modem drivers.
#   Signed-off-by: Sasha Khapyorsky <sashak@smlink.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/ac97_codec.h
#   2004/09/03 08:50:25+02:00 perex@suse.cz +1 -0
#   [ALSA]  [ac97] Added VIA shared type.
#   
#   D:2004/09/03 14:50:25
#   C:AC97 Codec Core,VIA82xx driver
#   F:include/ac97_codec.h:1.51->1.52 
#   F:pci/via82xx.c:1.119->1.120 
#   L:Added a new shared type AC97_SHARED_TYPE_VIA for via82xx southbridge
#   L:to share codecs between audio and modem drivers.
#   Signed-off-by: Sasha Khapyorsky <sashak@smlink.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:21:03+02:00 perex@suse.cz 
#   [ALSA]  add mixer quirk for LineX FM Transmitter
#   
#   USB generic driver
#   The LineX FM Transmitter needs a mixer quirk entry
#   to ignore control errors.
#   
#   Signed-off-by: Lonnie Mendez <dignome@gmail.com>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmixer_maps.c
#   2004/09/03 07:33:11+02:00 perex@suse.cz +9 -0
#   [ALSA]  add mixer quirk for LineX FM Transmitter
#   
#   D:2004/09/03 13:33:11
#   C:USB generic driver
#   F:usb/usbmixer_maps.c:1.7->1.8 
#   L:The LineX FM Transmitter needs a mixer quirk entry
#   L:to ignore control errors.
#   Signed-off-by: Lonnie Mendez <dignome@gmail.com>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/06 20:20:18+02:00 perex@suse.cz 
#   [ALSA]  remove gameport/MIDI support
#   
#   Documentation,PCI drivers,Intel8x0 driver
#   snd-intel8x0's gameport/MIDI code has quite a few problems:  the port
#   addresses cannot be detected reliably (or not at all with newer LPC
#   bridge devices), joystick port address 0x208 isn't supported, the MIDI
#   interrupt isn't detected, PnP isn't supported, changing the port
#   addresses in the LPC bridge configuration doesn't affect the devices
#   in the Super-I/O chip connected to the LPC bus, and registering this
#   driver for the LPC bridge PCI device prevents other drivers using the
#   LPC's PCI id from loading later.
#   
#   All these problems can be cured by removing the offending code and
#   using the proper modules for these devices (ns558/snd-mpu401) instead.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/intel8x0.c
#   2004/09/03 05:32:02+02:00 perex@suse.cz +0 -146
#   [ALSA]  remove gameport/MIDI support
#   
#   D:2004/09/03 11:32:02
#   C:Documentation,PCI drivers,Intel8x0 driver
#   F:Documentation/ALSA-Configuration.txt:1.50->1.51 
#   F:pci/Kconfig:1.31->1.32 
#   F:pci/intel8x0.c:1.163->1.164 
#   L:snd-intel8x0's gameport/MIDI code has quite a few problems:  the port
#   L:addresses cannot be detected reliably (or not at all with newer LPC
#   L:bridge devices), joystick port address 0x208 isn't supported, the MIDI
#   L:interrupt isn't detected, PnP isn't supported, changing the port
#   L:addresses in the LPC bridge configuration doesn't affect the devices
#   L:in the Super-I/O chip connected to the LPC bus, and registering this
#   L:driver for the LPC bridge PCI device prevents other drivers using the
#   L:LPC's PCI id from loading later.
#   L:
#   L:All these problems can be cured by removing the offending code and
#   L:using the proper modules for these devices (ns558/snd-mpu401) instead.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/Kconfig
#   2004/09/03 05:32:02+02:00 perex@suse.cz +0 -1
#   [ALSA]  remove gameport/MIDI support
#   
#   D:2004/09/03 11:32:02
#   C:Documentation,PCI drivers,Intel8x0 driver
#   F:Documentation/ALSA-Configuration.txt:1.50->1.51 
#   F:pci/Kconfig:1.31->1.32 
#   F:pci/intel8x0.c:1.163->1.164 
#   L:snd-intel8x0's gameport/MIDI code has quite a few problems:  the port
#   L:addresses cannot be detected reliably (or not at all with newer LPC
#   L:bridge devices), joystick port address 0x208 isn't supported, the MIDI
#   L:interrupt isn't detected, PnP isn't supported, changing the port
#   L:addresses in the LPC bridge configuration doesn't affect the devices
#   L:in the Super-I/O chip connected to the LPC bus, and registering this
#   L:driver for the LPC bridge PCI device prevents other drivers using the
#   L:LPC's PCI id from loading later.
#   L:
#   L:All these problems can be cured by removing the offending code and
#   L:using the proper modules for these devices (ns558/snd-mpu401) instead.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2004/09/03 05:32:02+02:00 perex@suse.cz +3 -4
#   [ALSA]  remove gameport/MIDI support
#   
#   D:2004/09/03 11:32:02
#   C:Documentation,PCI drivers,Intel8x0 driver
#   F:Documentation/ALSA-Configuration.txt:1.50->1.51 
#   F:pci/Kconfig:1.31->1.32 
#   F:pci/intel8x0.c:1.163->1.164 
#   L:snd-intel8x0's gameport/MIDI code has quite a few problems:  the port
#   L:addresses cannot be detected reliably (or not at all with newer LPC
#   L:bridge devices), joystick port address 0x208 isn't supported, the MIDI
#   L:interrupt isn't detected, PnP isn't supported, changing the port
#   L:addresses in the LPC bridge configuration doesn't affect the devices
#   L:in the Super-I/O chip connected to the LPC bus, and registering this
#   L:driver for the LPC bridge PCI device prevents other drivers using the
#   L:LPC's PCI id from loading later.
#   L:
#   L:All these problems can be cured by removing the offending code and
#   L:using the proper modules for these devices (ns558/snd-mpu401) instead.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/06 20:19:32+02:00 perex@suse.cz 
#   [ALSA]  add AC97 quirk for Fujitsu-Siemens E4010
#   
#   Intel8x0 driver
#   
#   
#   Signed-off-by: <castet.matthieu@free.fr>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/intel8x0.c
#   2004/09/02 06:59:21+02:00 perex@suse.cz +6 -0
#   [ALSA]  add AC97 quirk for Fujitsu-Siemens E4010
#   
#   D:2004/09/02 12:59:21
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.162->1.163 
#   L:
#   Signed-off-by: <castet.matthieu@free.fr>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/06 20:18:46+02:00 perex@suse.cz 
#   [ALSA]  Fix latency in ens1371 driver
#   
#   ENS1370/1+ driver
#   The high latency in prepare callback of ens1371 driver is fixed.
#   The *_rate_set() functions are moved outside of spinlock, and
#   cond_resched() is inserted in the busy probing loop.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ens1370.c
#   2004/09/01 14:27:33+02:00 perex@suse.cz +18 -6
#   [ALSA]  Fix latency in ens1371 driver
#   
#   D:2004/09/01 20:27:33
#   C:ENS1370/1+ driver
#   F:pci/ens1370.c:1.68->1.69 
#   L:The high latency in prepare callback of ens1371 driver is fixed.
#   L:The *_rate_set() functions are moved outside of spinlock, and
#   L:cond_resched() is inserted in the busy probing loop.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:18:03+02:00 perex@suse.cz 
#   [ALSA]  suppress auto-loading of modules in module_init().
#   
#   ALSA sequencer
#   The auto-loading of sequencer modules is suppressed in module_init().
#   The recent module-init-tools may cause blocking.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_clientmgr.c
#   2004/09/01 14:25:27+02:00 perex@suse.cz +4 -1
#   [ALSA]  suppress auto-loading of modules in module_init().
#   
#   D:2004/09/01 20:25:27
#   C:ALSA sequencer
#   F:core/seq/seq_clientmgr.c:1.34->1.35 
#   L:The auto-loading of sequencer modules is suppressed in module_init().
#   L:The recent module-init-tools may cause blocking.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:17:20+02:00 perex@suse.cz 
#   [ALSA]  add missing ifdef for disabling MIDI
#   
#   Intel8x0 driver
#   
#   
#   Signed-off-by: <castet.matthieu@free.fr>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/intel8x0.c
#   2004/09/01 02:41:19+02:00 perex@suse.cz +2 -0
#   [ALSA]  add missing ifdef for disabling MIDI
#   
#   D:2004/09/01 08:41:19
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.161->1.162 
#   L:
#   Signed-off-by: <castet.matthieu@free.fr>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/06 20:16:34+02:00 perex@suse.cz 
#   [ALSA]  AC97 96 kHz sample rate support
#   
#   Documentation,AC97 Codec Core,Intel8x0 driver
#   
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/intel8x0.c
#   2004/09/01 02:30:56+02:00 perex@suse.cz +26 -11
#   [ALSA]  AC97 96 kHz sample rate support
#   
#   D:2004/09/01 08:30:56
#   C:Documentation,AC97 Codec Core,Intel8x0 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.38->1.39 
#   F:include/ac97_codec.h:1.50->1.51 
#   F:pci/intel8x0.c:1.160->1.161 
#   F:pci/ac97/ac97_codec.c:1.144->1.145 
#   F:pci/ac97/ac97_pcm.c:1.16->1.17 
#   F:pci/ac97/ac97_proc.c:1.10->1.11 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_proc.c
#   2004/09/01 02:30:57+02:00 perex@suse.cz +4 -0
#   [ALSA]  AC97 96 kHz sample rate support
#   
#   D:2004/09/01 08:30:56
#   C:Documentation,AC97 Codec Core,Intel8x0 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.38->1.39 
#   F:include/ac97_codec.h:1.50->1.51 
#   F:pci/intel8x0.c:1.160->1.161 
#   F:pci/ac97/ac97_codec.c:1.144->1.145 
#   F:pci/ac97/ac97_pcm.c:1.16->1.17 
#   F:pci/ac97/ac97_proc.c:1.10->1.11 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_pcm.c
#   2004/09/01 02:30:57+02:00 perex@suse.cz +120 -34
#   [ALSA]  AC97 96 kHz sample rate support
#   
#   D:2004/09/01 08:30:56
#   C:Documentation,AC97 Codec Core,Intel8x0 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.38->1.39 
#   F:include/ac97_codec.h:1.50->1.51 
#   F:pci/intel8x0.c:1.160->1.161 
#   F:pci/ac97/ac97_codec.c:1.144->1.145 
#   F:pci/ac97/ac97_pcm.c:1.16->1.17 
#   F:pci/ac97/ac97_proc.c:1.10->1.11 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2004/09/01 02:30:57+02:00 perex@suse.cz +31 -1
#   [ALSA]  AC97 96 kHz sample rate support
#   
#   D:2004/09/01 08:30:56
#   C:Documentation,AC97 Codec Core,Intel8x0 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.38->1.39 
#   F:include/ac97_codec.h:1.50->1.51 
#   F:pci/intel8x0.c:1.160->1.161 
#   F:pci/ac97/ac97_codec.c:1.144->1.145 
#   F:pci/ac97/ac97_pcm.c:1.16->1.17 
#   F:pci/ac97/ac97_proc.c:1.10->1.11 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# include/sound/ac97_codec.h
#   2004/09/01 02:30:56+02:00 perex@suse.cz +10 -1
#   [ALSA]  AC97 96 kHz sample rate support
#   
#   D:2004/09/01 08:30:56
#   C:Documentation,AC97 Codec Core,Intel8x0 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.38->1.39 
#   F:include/ac97_codec.h:1.50->1.51 
#   F:pci/intel8x0.c:1.160->1.161 
#   F:pci/ac97/ac97_codec.c:1.144->1.145 
#   F:pci/ac97/ac97_pcm.c:1.16->1.17 
#   F:pci/ac97/ac97_proc.c:1.10->1.11 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
#   2004/09/01 02:30:56+02:00 perex@suse.cz +2 -2
#   [ALSA]  AC97 96 kHz sample rate support
#   
#   D:2004/09/01 08:30:56
#   C:Documentation,AC97 Codec Core,Intel8x0 driver
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.38->1.39 
#   F:include/ac97_codec.h:1.50->1.51 
#   F:pci/intel8x0.c:1.160->1.161 
#   F:pci/ac97/ac97_codec.c:1.144->1.145 
#   F:pci/ac97/ac97_pcm.c:1.16->1.17 
#   F:pci/ac97/ac97_proc.c:1.10->1.11 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2004/09/06 20:15:40+02:00 perex@suse.cz 
#   [ALSA]  Korg1212 misc fixes
#   
#   KORG1212 driver
#   The DSP firmware download timeout has been increased;
#   Some concurrent device settings has been fixed (I have shameless copied
#   some code from RME9652); and
#   One debug message was fixed.
#   
#   Signed-off-by: Haroldo Gamal <gamal@alternex.com.br>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/korg1212/korg1212.c
#   2004/08/31 04:50:15+02:00 perex@suse.cz +59 -9
#   [ALSA]  Korg1212 misc fixes
#   
#   D:2004/08/31 10:50:15
#   C:KORG1212 driver
#   F:pci/korg1212/korg1212.c:1.47->1.48 
#   L:The DSP firmware download timeout has been increased;
#   L:Some concurrent device settings has been fixed (I have shameless copied
#   L:some code from RME9652); and
#   L:One debug message was fixed.
#   Signed-off-by: Haroldo Gamal <gamal@alternex.com.br>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:14:51+02:00 perex@suse.cz 
#   [ALSA]  Enable __GFP_NOWARN as default for buffer allocation
#   
#   Memalloc module
#   __GFP_NOWARN is enabled for DMA buffer allocation regardless of
#   its size.  The DMA buffer allocation is not a critical task.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/memalloc.c
#   2004/08/31 04:49:23+02:00 perex@suse.cz +3 -4
#   [ALSA]  Enable __GFP_NOWARN as default for buffer allocation
#   
#   D:2004/08/31 10:49:23
#   C:Memalloc module
#   F:core/memalloc.c:1.37->1.38 
#   L:__GFP_NOWARN is enabled for DMA buffer allocation regardless of
#   L:its size.  The DMA buffer allocation is not a critical task.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:14:05+02:00 perex@suse.cz 
#   [ALSA]  Added __GFP_NORETRY to avoid OOM-killer
#   
#   Memalloc module
#   __GFP_NORETRY is added to the DMA buffer allocator to avoid triggering
#   OOM-killer.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/memalloc.c
#   2004/08/30 12:39:22+02:00 perex@suse.cz +1 -0
#   [ALSA]  Added __GFP_NORETRY to avoid OOM-killer
#   
#   D:2004/08/30 18:39:22
#   C:Memalloc module
#   F:core/memalloc.c:1.36->1.37 
#   L:__GFP_NORETRY is added to the DMA buffer allocator to avoid triggering
#   L:OOM-killer.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:13:09+02:00 perex@suse.cz 
#   ALSA CVS update
#   ES18xx driver
#   Fixed a bug in setting the filter register.
#   
#   A fix from the kernel OSS driver.  The original report/patch is from
#   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=204147
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/es18xx.c
#   2004/08/26 10:57:47+02:00 perex@suse.cz +5 -0
#   ALSA CVS update
#   D:2004/08/26 16:57:47
#   C:ES18xx driver
#   F:isa/es18xx.c:1.48->1.49 
#   L:Fixed a bug in setting the filter register.
#   L:
#   L:A fix from the kernel OSS driver.  The original report/patch is from
#   L:http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=204147
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:12:22+02:00 perex@suse.cz 
#   ALSA CVS update
#   ICE1712 driver
#   Allow the private EEPROM image for evaluation boards
#   
#   The driver may have a private EEPROM image instead of reading
#   from the board (as well as ice1724 does).  It'll be helpful for
#   test boards.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1712.c
#   2004/08/26 10:55:43+02:00 perex@suse.cz +39 -19
#   ALSA CVS update
#   D:2004/08/26 16:55:43
#   C:ICE1712 driver
#   F:pci/ice1712/ice1712.c:1.61->1.62 
#   L:Allow the private EEPROM image for evaluation boards
#   L:
#   L:The driver may have a private EEPROM image instead of reading
#   L:from the board (as well as ice1724 does).  It'll be helpful for
#   L:test boards.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/09/06 20:11:34+02:00 perex@suse.cz 
#   ALSA CVS update
#   ENS1370/1+ driver
#   Fixed AC3-passthru on ens1371/1373 boards.
#   
#   SRC is bypassed when the sample rate is 48k, so that the non-audio
#   signal won't be broken.  The other sample rates still need SRC.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ens1370.c
#   2004/08/26 10:53:55+02:00 perex@suse.cz +7 -0
#   ALSA CVS update
#   D:2004/08/26 16:53:55
#   C:ENS1370/1+ driver
#   F:pci/ens1370.c:1.67->1.68 
#   L:Fixed AC3-passthru on ens1371/1373 boards.
#   L:
#   L:SRC is bypassed when the sample rate is 48k, so that the non-audio
#   L:signal won't be broken.  The other sample rates still need SRC.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2004/08/29 16:37:18-04:00 jgarzik@pobox.com 
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/wireless/netwave_cs.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -12
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/wan/lmc/lmc_main.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/sk_mca.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/meth.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -26
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/net/ibmlana.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# drivers/media/dvb/dvb-core/dvb_net.c
#   2004/08/29 16:37:11-04:00 jgarzik@pobox.com +0 -9
#   [netdev] Remove no-op in-driver implementations of ->set_config()
# 
# ChangeSet
#   2004/08/28 19:25:49-04:00 olh@suse.de 
#   [PATCH] remove old version check from mac8390
#   
#   This 'netdevice' define will end up in the 'tags' file.
#   Its not used, so just remove it.
# 
# drivers/net/mac8390.c
#   2004/08/21 11:45:12-04:00 olh@suse.de +0 -4
#   remove old version check from mac8390
# 
# ChangeSet
#   2004/08/28 19:00:51-04:00 akpm@osdl.org 
#   [PATCH] de4x5 warning fix
#   
#   Ugh.
#   
#   drivers/net/tulip/de4x5.c: In function `mii_get_phy':
#   drivers/net/tulip/de4x5.c:5092: warning: operation on `i' may be undefined
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/tulip/de4x5.c
#   2004/08/26 03:24:25-04:00 akpm@osdl.org +1 -1
#   de4x5 warning fix
# 
# ChangeSet
#   2004/08/28 18:53:53-04:00 akpm@osdl.org 
#   [PATCH] sparse: fix warnings in net/irda/*
#   
#   From: "Mika Kukkonen" <mika@osdl.org>
#   
#     CHECK   net/irda/irlan/irlan_client.c
#   net/irda/irlan/irlan_client.c:237:14: warning: assignment expression in
#   conditional
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# net/irda/irlan/irlan_client.c
#   2004/08/27 02:30:32-04:00 akpm@osdl.org +1 -1
#   sparse: fix warnings in net/irda/*
# 
# ChangeSet
#   2004/08/28 18:52:23-04:00 akpm@osdl.org 
#   [PATCH] defxx device name fixes
#   
#   From: "Maciej W. Rozycki" <macro@linux-mips.org>
#   
#   This is a fix for the "fddi%d" device name reported literally due to the
#   switch from init_fddidev() to alloc_fddidev().  Plus related updates to
#   module information.  Applies on top of the 2.4.27-defxx-sync2681 or
#   2.6.8.1-defxx-misc patches, respectively.  Please apply.
#   
#   Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/defxx.c
#   2004/08/24 22:18:36-04:00 akpm@osdl.org +68 -68
#   defxx device name fixes
# 
# ChangeSet
#   2004/08/28 18:52:12-04:00 akpm@osdl.org 
#   [PATCH] defxx trivial updates
#   
#   From: "Maciej W. Rozycki" <macro@linux-mips.org>
#   
#   Here are a few obvious clean-ups I did to the driver.
#   
#   Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/net/defxx.h
#   2004/08/24 22:18:36-04:00 akpm@osdl.org +1 -1
#   defxx trivial updates
# 
# drivers/net/defxx.c
#   2004/08/24 22:18:36-04:00 akpm@osdl.org +5 -5
#   defxx trivial updates
# 
diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	2004-10-28 22:25:58 -07:00
+++ b/CREDITS	2004-10-28 22:25:58 -07:00
@@ -46,13 +46,11 @@
 S: United Kingdom
 
 N: Werner Almesberger
-E: werner.almesberger@epfl.ch
+E: werner@almesberger.net
+W: http://www.almesberger.net/
 D: dosfs, LILO, some fd features, ATM, various other hacks here and there
-S: Ecole Polytechnique Federale de Lausanne
-S: DSC ICA
-S: INN (Ecublens)
-S: CH-1015 Lausanne
-S: Switzerland
+S: Buenos Aires
+S: Argentina
 
 N: Tim Alpaerts
 E: tim_alpaerts@toyota-motor-europe.com
@@ -495,6 +493,14 @@
 N: Matthias Bruestle
 E: m@mbsks.franken.de
 D: REINER SCT cyberJack pinpad/e-com USB chipcard reader driver
+S: Germany
+
+N: Adrian Bunk
+E: bunk@stusta.de
+P: 1024D/4F12B400  B29C E71E FE19 6755 5C8A  84D4 99FC EA98 4F12 B400
+D: misc kernel hacking and testing
+S: Grasmeierstrasse 11
+S: 80805 Muenchen
 S: Germany
 
 N: Ray Burr
diff -Nru a/Documentation/00-INDEX b/Documentation/00-INDEX
--- a/Documentation/00-INDEX	2004-10-28 22:25:57 -07:00
+++ b/Documentation/00-INDEX	2004-10-28 22:25:57 -07:00
@@ -20,6 +20,8 @@
 	- list of changes that break older software packages.
 CodingStyle
 	- how the boss likes the C code in the kernel to look.
+DMA-API.txt
+	- DMA API, pci_ API & extensions for non-consistent memory machines.
 DMA-mapping.txt
 	- info for PCI drivers using DMA portably across all platforms.
 DocBook/
@@ -30,8 +32,12 @@
 	- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
 IRQ-affinity.txt
 	- how to select which CPU(s) handle which interrupt events on SMP.
+ManagementStyle
+	- how to (attempt to) manage kernel hackers.
 MSI-HOWTO.txt
 	- the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ.
+RCU/
+	- directory with info on RCU (read-copy update).
 README.DAC960
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux.
 README.moxa
@@ -46,8 +52,6 @@
 	- how to change your VGA cursor from a blinking underscore.
 arm/
 	- directory with info about Linux on the ARM architecture.
-as-iosched.txt
-	- info on anticipatory IO scheduler.
 basic_profiling.txt
 	- basic instructions for those who wants to profile Linux kernel.
 binfmt_misc.txt
@@ -60,16 +64,22 @@
 	- info, major/minor #'s for Compaq's SMART Array Controllers.
 cdrom/
 	- directory with information on the CD-ROM drivers that Linux has.
+cli-sti-removal.txt
+	- cli()/sti() removal guide.
 computone.txt
 	- info on Computone Intelliport II/Plus Multiport Serial Driver.
 cpqarray.txt
 	- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
-cpufreq/
+cpu-freq/
 	- info on CPU frequency and voltage scaling.
 cris/
 	- directory with info about Linux on CRIS architecture.
+crypto/
+	- directory with info on the Crypto API.
 debugging-modules.txt
 	- some notes on debugging modules after Linux 2.6.3.
+device-mapper/
+	- directory with info on Device Mapper.
 devices.txt
 	- plain ASCII listing of all the nodes in /dev/ with major minor #'s.
 digiboard.txt
@@ -92,6 +102,8 @@
 	- directory with info on the frame buffer graphics abstraction layer.
 filesystems/
 	- directory with info on the various filesystems that Linux supports.
+firmware_class/
+	- request_firmware() hotplug interface info.
 floppy.txt
 	- notes and driver options for the floppy disk driver.
 ftape.txt
@@ -100,10 +112,14 @@
 	- info on using the Hayes ESP serial driver.
 highuid.txt
 	- notes on the change from 16 bit to 32 bit user/group IDs.
+hpet.txt
+	- High Precision Event Timer Driver for Linux.
 hw_random.txt
 	- info on Linux support for random number generator in i8xx chipsets.
 i2c/
 	- directory with info about the I2C bus/protocol (2 wire, kHz speed).
+i2o/
+	- directory with info about the Linux I2O subsystem.
 i386/
 	- directory with info about Linux on Intel 32 bit architecture.
 ia64/
@@ -114,6 +130,8 @@
 	- how to use the RAM disk as an initial/temporary root filesystem.
 input/
 	- info on Linux input device support.
+io_ordering.txt
+	- info on ordering I/O writes to memory-mapped addresses.
 ioctl-number.txt
 	- how to implement and register device/driver ioctl calls.
 iostats.txt
@@ -134,6 +152,8 @@
 	- summary listing of command line / boot prompt args for the kernel.
 kobject.txt
 	- info of the kobject infrastructure of the Linux kernel.
+laptop-mode.txt
+	- How to conserve battery power using laptop-mode.
 ldm.txt
 	- a brief description of LDM (Windows Dynamic Disks).
 locks.txt
@@ -160,6 +180,8 @@
 	- script to make /dev entries for SMART controllers (see cciss.txt).
 mkdev.ida
 	- script to make /dev entries for Intelligent Disk Array Controllers.
+mono.txt
+	- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
 moxa-smartio
 	- info on installing/using Moxa multiport serial driver.
 mtrr.txt
@@ -172,6 +194,8 @@
 	- short guide on setting up a diskless box with NFS root filesystem.
 nmi_watchdog.txt
 	- info on NMI watchdog for SMP systems.
+numastat.txt
+	- info on how to read Numa policy hit/miss statistics in sysfs.
 oops-tracing.txt
 	- how to decode those nasty internal kernel error dump messages.
 paride.txt
@@ -199,17 +223,25 @@
 riscom8.txt
 	- notes on using the RISCom/8 multi-port serial driver.
 rocket.txt
-	- info on installing/using the Comtrol RocketPort multiport serial driver.
+	- info on the Comtrol RocketPort multiport serial driver.
 rpc-cache.txt
 	- introduction to the caching mechanisms in the sunrpc layer.
 rtc.txt
 	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
 s390/
 	- directory with info on using Linux on the IBM S390.
+sched-coding.txt
+	- reference for various scheduler-related methods in the O(1) scheduler.
 sched-design.txt
 	- goals, design and implementation of the Linux O(1) scheduler.
+sched-domains.txt
+	- information on scheduling domains.
+sched-stats.txt
+	- information on schedstats (Linux Scheduler Statistics).
 scsi/
 	- directory with info on Linux scsi support.
+serial/
+	- directory with info on the low level serial API.
 serial-console.txt
 	- how to set up Linux with a serial line console as the default.
 sgi-visws.txt
@@ -242,14 +274,24 @@
 	- info on the magic SysRq key.
 telephony/
 	- directory with info on telephony (e.g. voice over IP) support.
+time_interpolators.txt
+	- info on time interpolators.
+tipar.txt
+	- information about Parallel link cable for Texas Instruments handhelds.
+tty.txt
+	- guide to the locking policies of the tty layer.
 unicode.txt
 	- info on the Unicode character/font mapping used in Linux.
+uml/
+	- directory with infomation about User Mode Linux.
 usb/
 	- directory with info regarding the Universal Serial Bus.
 video4linux/
 	- directory with info regarding video/TV/radio cards and linux.
 vm/
 	- directory with info on the Linux vm code.
+voyager.txt
+	- guide to running Linux on the Voyager architecture.
 watchdog/
 	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
 x86_64/
diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
--- a/Documentation/DocBook/Makefile	2004-10-28 22:25:58 -07:00
+++ b/Documentation/DocBook/Makefile	2004-10-28 22:25:58 -07:00
@@ -8,9 +8,9 @@
 
 DOCBOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
 	    kernel-hacking.sgml kernel-locking.sgml via-audio.sgml \
-	    mousedrivers.sgml deviceiobook.sgml procfs-guide.sgml \
-	    tulip-user.sgml writing_usb_driver.sgml scsidrivers.sgml \
-	    sis900.sgml kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \
+	    deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
+	    writing_usb_driver.sgml scsidrivers.sgml sis900.sgml \
+	    kernel-api.sgml journal-api.sgml lsm.sgml usb.sgml \
 	    gadget.sgml libata.sgml mtdnand.sgml librs.sgml
 
 ###
@@ -58,14 +58,14 @@
 # The following rules are used to generate the .sgml documentation
 # required to generate the final targets. (ps, pdf, html).
 quiet_cmd_docproc = DOCPROC $@
-      cmd_docproc = $(DOCPROC) doc $< >$@
+      cmd_docproc = SRCTREE=$(srctree)/ $(DOCPROC) doc $< >$@
 define rule_docproc
 	set -e;								\
         $(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))';) 	\
         $(cmd_$(1)); 							\
         ( 								\
           echo 'cmd_$@ := $(cmd_$(1))'; 				\
-          echo $@: `$(DOCPROC) depend $<`; 				\
+          echo $@: `SRCTREE=$(srctree) $(DOCPROC) depend $<`; 		\
         ) > $(dir $@).$(notdir $@).cmd
 endef
 
@@ -129,6 +129,9 @@
 # Rule to generate man files - output is placed in the man subdirectory
 
 %.9:	%.sgml
+ifneq ($(KBUILD_SRC),)
+	$(Q)mkdir -p $(objtree)/Documentation/DocBook/man
+endif
 	$(SPLITMAN) $< $(objtree)/Documentation/DocBook/man "$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)"
 	$(MAKEMAN) convert $(objtree)/Documentation/DocBook/man $<
 
diff -Nru a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl
--- a/Documentation/DocBook/deviceiobook.tmpl	2004-10-28 22:25:58 -07:00
+++ b/Documentation/DocBook/deviceiobook.tmpl	2004-10-28 22:25:58 -07:00
@@ -147,8 +147,7 @@
 	compiler is not permitted to reorder the I/O sequence. When the 
 	ordering can be compiler optimised, you can use <function>
 	__readb</function> and friends to indicate the relaxed ordering. Use 
-	this with care. The <function>rmb</function> provides a read memory 
-	barrier. The <function>wmb</function> provides a write memory barrier.
+	this with care.
       </para>
 
       <para>
@@ -159,10 +158,72 @@
 	asynchronously. A driver author must issue a read from the same
 	device to ensure that writes have occurred in the specific cases the
 	author cares. This kind of property cannot be hidden from driver
-	writers in the API.
+	writers in the API.  In some cases, the read used to flush the device
+	may be expected to fail (if the card is resetting, for example).  In
+	that case, the read should be done from config space, which is
+	guaranteed to soft-fail if the card doesn't respond.
       </para>
 
       <para>
+	The following is an example of flushing a write to a device when
+	the driver would like to ensure the write's effects are visible prior
+	to continuing execution.
+      </para>
+
+<programlisting>
+static inline void
+qla1280_disable_intrs(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg;
+
+	reg = ha->iobase;
+	/* disable risc and host interrupts */
+	WRT_REG_WORD(&amp;reg->ictrl, 0);
+	/*
+	 * The following read will ensure that the above write
+	 * has been received by the device before we return from this
+	 * function.
+	 */
+	RD_REG_WORD(&amp;reg->ictrl);
+	ha->flags.ints_enabled = 0;
+}
+</programlisting>
+
+      <para>
+	In addition to write posting, on some large multiprocessing systems
+	(e.g. SGI Challenge, Origin and Altix machines) posted writes won't
+	be strongly ordered coming from different CPUs.  Thus it's important
+	to properly protect parts of your driver that do memory-mapped writes
+	with locks and use the <function>mmiowb</function> to make sure they
+	arrive in the order intended.
+      </para>
+
+      <para>
+	Generally, one should use <function>mmiowb</function> prior to
+	releasing a spinlock that protects regions using <function>writeb
+	</function> or similar functions that aren't surrounded by <function>
+	readb</function> calls, which will ensure ordering and flushing.  The
+	following example (again from qla1280.c) illustrates its use.
+      </para>
+
+<programlisting>
+       sp->flags |= SRB_SENT;
+       ha->actthreads++;
+       WRT_REG_WORD(&amp;reg->mailbox4, ha->req_ring_index);
+
+       /*
+        * A Memory Mapped I/O Write Barrier is needed to ensure that this write
+        * of the request queue in register is ordered ahead of writes issued
+        * after this one by other CPUs.  Access to the register is protected
+        * by the host_lock.  Without the mmiowb, however, it is possible for
+        * this CPU to release the host lock, another CPU acquire the host lock,
+        * and write to the request queue in, and have the second write make it
+        * to the chip first.
+        */
+       mmiowb(); /* posted write ordering */
+</programlisting>
+
+      <para>
 	PCI ordering rules also guarantee that PIO read responses arrive
 	after any outstanding DMA writes on that bus, since for some devices
 	the result of a <function>readb</function> call may signal to the
@@ -171,7 +232,9 @@
 	<function>readb</function> call has no relation to any previous DMA
 	writes performed by the device.  The driver can use
 	<function>readb_relaxed</function> for these cases, although only
-	some platforms will honor the relaxed semantics.
+	some platforms will honor the relaxed semantics.  Using the relaxed
+	read functions will provide significant performance benefits on
+	platforms that support it.
       </para>
     </sect1>
 
diff -Nru a/Documentation/DocBook/mousedrivers.tmpl b/Documentation/DocBook/mousedrivers.tmpl
--- a/Documentation/DocBook/mousedrivers.tmpl	2004-10-28 22:25:59 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1022 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
-
-<book id="MouseGuide">
- <bookinfo>
-  <title>Mouse Drivers</title>
-  
-  <authorgroup>
-   <author>
-    <firstname>Alan</firstname>
-    <surname>Cox</surname>
-    <affiliation>
-     <address>
-      <email>alan@redhat.com</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>2000</year>
-   <holder>Alan Cox</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation 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.
-   </para>
-      
-   <para>
-     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.
-   </para>
-      
-   <para>
-     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
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
- <toc></toc>
-
- <chapter id="intro">
-  <title>Introduction</title>
-  <note>
-   <title>Earlier publication</title>
-    <para>
-      Parts of this document first appeared in Linux Magazine under a
-      ninety day exclusivity.
-   </para>
-  </note> 
-
-  <para>
-    Mice are conceptually one of the simplest device interfaces in the 
-    Linux operating system. Not all mice are handled by the kernel. 
-    Instead there is a two layer abstraction.
-  </para>
-
-  <para>
-    The kernel mouse drivers and userspace drivers for the serial mice are
-    all managed by a system daemon called <application>gpm</application> 
-    - the general purpose mouse driver. <application>gpm</application> 
-    handles cutting and pasting on the text consoles. It provides a 
-    general library for mouse-aware applications and it handles the 
-    sharing of mouse services with the 
-    <application>X Window System</application> user interface.
-  </para>
-  <para>
-    Sometimes a mouse speaks a sufficiently convoluted protocol that the
-    protocol is handled by <application>Gpm</application> itself. Most 
-    of the mouse drivers follow a common interface called the bus mouse 
-    protocol.
-  </para>
-  <para>
-    Each read from a bus mouse interface device returns a block of data. 
-    The first three bytes of each read are defined as follows: 
-
-   <table frame="all">
-    <title>Mouse Data Encoding</title>
-    <tgroup cols="2" align="left">
-     <tbody>
-      <row>
-       <entry>Byte 0</entry>
-       <entry>0x80 + the buttons currently down.</entry>
-      </row>
-      <row>
-       <entry>Byte 1</entry>
-       <entry>A signed value for the shift in X position</entry>
-      </row>
-      <row>
-       <entry>Byte 2</entry>
-       <entry>A signed value for the shift in Y position</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
-
-    An application can choose to read more than 3 bytes. The rest of the 
-    bytes will be zero, or may optionally return some additional 
-    device-specific information.
-  </para>
-  <para>
-    The position values are truncated if they exceed the 8bit range (that
-    is -127 &lt;= delta &lt;= 127). While the value -128 does fit into a 
-    byte is not allowed.
-  </para>
-  <para>
-    The <mousebutton>buttons</mousebutton> are numbered left to right as 
-    0, 1, 2, 3.. and each button sets the relevant bit. So a user pressing 
-    the left and right button of a three button mouse will set bits 0 and 2.
-  </para>
-  <para>
-    All mice are required to support the <function>poll</function> 
-    operation. Indeed pretty much every user of a mouse device uses 
-    <function>poll</function> to wait for mouse events to occur.
-  </para>
-  <para>
-    Finally the mice support asynchronous I/O. This is a topic we have not 
-    yet covered but which I will explain after looking at a simple mouse 
-    driver.
-  </para>
- </chapter>
-
- <chapter id="driver">
-  <title>A simple mouse driver</title>
-  <para>
-    First we will need the set up functions for our mouse device. To keep 
-    this simple our imaginary mouse device has three I/O ports fixed at I/O 
-    address 0x300 and always lives on interrupt 5.  The ports will be the X 
-    position, the Y position and the buttons in that order.
-  </para>
-
-  <programlisting>
-#define OURMOUSE_BASE        0x300
-
-static struct miscdevice our_mouse = {
-        OURMOUSE_MINOR, "ourmouse", &amp;our_mouse_fops
-};
-
-__init ourmouse_init(void)
-{
-
-        if (request_region(OURMOUSE_BASE, 3, "ourmouse") < 0) {
-		printk(KERN_ERR "ourmouse: request_region failed.\n");
-                return -ENODEV;
-	}
-
-        if (misc_register(&amp;our_mouse) < 0) {
-		printk(KERN_ERR "ourmouse: cannot register misc device.\n");
-		release_region(OURMOUSE_BASE, 3);
-		return -EBUSY;
-	}
-
-        return 0;
-}
-  </programlisting>
-
-  <para>
-    The <structname>miscdevice</structname> is new here. Linux normally 
-    parcels devices out by major number, and each device has 256 units. 
-    For things like mice this is extremely wasteful so a device exists 
-    which is used to accumulate all the odd individual devices that 
-    computers tend to have.
-  </para>
-  <para>
-    Minor numbers in this space are allocated by a central source, although 
-    you can look in the kernel <filename>Documentation/devices.txt</filename>
-    file and pick a free one for development use. This kernel file also 
-    carries instructions for registering a device. This may change over time 
-    so it is a good idea to obtain a current copy of this file first.
-  </para>
-  <para>
-    Our code then is fairly simple. We reserve our I/O address space with
-    request_region, checking to make sure that it succeeded (i.e. the
-    space wasn't reserved by anyone else). 
-  </para>
-  <para>
-    Then we ask the misc driver to allocate our minor device number. We also
-    hand it our name (which is used in 
-    <filename class="directory">/proc/misc</filename>) and a set of file 
-    operations that are to be used. The file operations work exactly like the 
-    file operations you would register for a normal character device. The misc 
-    device itself is simply acting as a redirector for requests.
-    Since misc_register can fail, it is important to check for failure
-    and act accordingly (which in the case of a mouse driver is to abort,
-    since you can't use the mouse without a working device node).
-  </para>
-  <para>
-    Next, in order to be able to use and test our code we need to add some 
-    module code to support it. This too is fairly simple:
-  </para>
-  <programlisting>
-#ifdef MODULE
-
-int init_module(void)
-{
-        if(ourmouse_init()&lt;0)
-                return -ENODEV:
-        return 0;
-}
-
-void cleanup_module(void)
-{
-        misc_deregister(&amp;our_mouse);
-        free_region(OURMOUSE_BASE, 3);
-}
-
-
-#endif
-  </programlisting>
-
-  <para>
-    The module code provides the normal two functions. The 
-    <function>init_module</function> function is called when the module is 
-    loaded. In our case it simply calls the initialising function we wrote 
-    and returns an error if this fails. This ensures the module will only 
-    be loaded if it was successfully set up.
-  </para>
-  <para>
-    The <function>cleanup_module</function> function is called when the 
-    module is unloaded. We give the miscellaneous device entry back, and 
-    then free our I/O resources. If we didn't free the I/O resources then 
-    the next time the module loaded it would think someone else had its I/O 
-    space.
-  </para>
-  <para>
-    Once the <function>misc_deregister</function> has been called any 
-    attempts to open the mouse device will fail with the error  
-    <errorcode>ENODEV</errorcode> (<errorname>No such device</errorname>).
-  </para>
-  <para>
-    Next we need to fill in our file operations. A mouse doesn't need many 
-    of these. We need to provide open, release, read and poll. That makes 
-    for a nice simple structure:
-  </para>
-
-  <programlisting>
-struct file_operations our_mouse_fops = {
-        owner: THIS_MODULE,            /* Automatic usage management */
-        read:  read_mouse,             /* You can read a mouse */
-        write: write_mouse,            /* This won't do a lot */
-        poll:  poll_mouse,             /* Poll */
-        open:  open_mouse,             /* Called on open */
-        release: close_mouse,          /* Called on close */
-};
-  </programlisting>
-
-  <para>
-    There is nothing particularly special needed here. We provide functions 
-    for all the relevant or required operations and little else. There is 
-    nothing stopping us providing an ioctl function for this mouse. Indeed 
-    if you have a configurable mouse it may be very appropriate to provide 
-    configuration interfaces via ioctl calls.
-  </para>
-  <para>
-    The syntax we use is not standard C as such. GCC provides the ability
-    to initialise fields by name, and this generally makes the method table
-    much easier to read than counting through NULL pointers and remembering
-    the order by hand.
-  </para>
-  <para>
-    The owner field is used to manage the locking of module load an
-    unloading. It is obviously important that a module is not unloaded while
-    in use. When your device is opened the module specified by "owner" is 
-    locked. When it is finally released the module is unlocked.
-  </para>
-  <para>
-    The open and close routines need to manage enabling and disabling the 
-    interrupts for the mouse as well as stopping the mouse being unloaded
-    when it is no longer required. 
-  </para>
-
-  <programlisting>
-static int mouse_users = 0;                /* User count */
-static int mouse_dx = 0;                   /* Position changes */
-static int mouse_dy = 0;
-static int mouse_event = 0;                /* Mouse has moved */
-
-static int open_mouse(struct inode *inode, struct file *file)
-{
-        if(mouse_users++)
-                return 0;
-
-        if(request_irq(mouse_intr, OURMOUSE_IRQ, 0, "ourmouse", NULL))
-        {
-                mouse_users--;
-                return -EBUSY;
-        }
-        mouse_dx = 0;
-        mouse_dy = 0;
-        mouse_event = 0;
-        mouse_buttons = 0;
-	return 0;
-}
-  </programlisting>
-  <para>
-    The open function has to do a small amount of housework. We keep a count 
-    of the number of times the mouse is open. This is because we do not want 
-    to request the interrupt multiple times. If the mouse has at least one 
-    user then it is set up and we simply add to the user count and return
-    <returnvalue>0</returnvalue> for success.
-  </para>
-  <para>
-    We grab the interrupt and thus start mouse interrupts. If the interrupt 
-    has been borrowed by some other driver then <function>request_irq</function>
-    will fail and we will return an error. If we were capable of sharing an 
-    interrupt line we would specify <constant>SA_SHIRQ</constant> instead of 
-    <constant>zero</constant>. Provided that everyone claiming an interrupt 
-    sets this flag, they get to share the line. <hardware>PCI</hardware> can 
-    share interrupts, <hardware>ISA</hardware> normally however cannot. 
-  </para>
-  <para>
-    We do the housekeeping. We make the current mouse position the starting
-    point for accumulated changes and declare that nothing has happened
-    since the mouse driver was opened.
-  </para>
-  <para>
-    The release function needs to unwind all these:
-  </para>
-  <programlisting>
-static int close_mouse(struct inode *inode, struct file *file)
-{
-        if(--mouse_users)
-                return 0;
-        free_irq(OURMOUSE_IRQ, NULL);
-        return 0;
-}
-  </programlisting>
-  <para>
-    We count off a user and provided that there are still other users need 
-    take no further action. The last person closing the mouse causes us to 
-    free up the interrupt. This stops interrupts from the mouse from using 
-    our CPU time, and ensures that the mouse can now be unloaded.
-  </para>
-  <para>
-    We can fill in the write handler at this point as the write function for 
-    our mouse simply declines to allow writes:
-  </para>
-
-  <programlisting>
-static ssize_t write_mouse(struct file *file, const char *buffer, size_t
-                                count, loff_t *ppos)
-{
-        return -EINVAL;
-}
-  </programlisting>
-
-  <para>
-    This is pretty much self-explanatory. Whenever you write you get told 
-    it was an invalid function.
-  </para>
-  <para>
-    To make the poll and read functions work we have to consider how we 
-    handle the mouse interrupt. 
-  </para>
-
-  <programlisting>
-static struct wait_queue *mouse_wait;
-static spinlock_t mouse_lock = SPIN_LOCK_UNLOCKED;
-
-static void ourmouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-        char delta_x;
-        char delta_y;
-        unsigned char new_buttons;
-
-        delta_x = inb(OURMOUSE_BASE);
-        delta_y = inb(OURMOUSE_BASE+1);
-        new_buttons = inb(OURMOUSE_BASE+2);
-
-        if(delta_x || delta_y || new_buttons != mouse_buttons)
-        {
-                /* Something happened */
-
-                spin_lock(&amp;mouse_lock);
-                mouse_event = 1;
-                mouse_dx += delta_x;
-                mouse_dy += delta_y;
-                mouse_buttons = new_buttons;
-                spin_unlock(&amp;mouse_lock);
-                
-                wake_up_interruptible(&amp;mouse_wait);
-        }
-}
-  </programlisting>
-
-  <para>
-    The interrupt handler reads the mouse status. The next thing we do is 
-    to check whether something has changed. If the mouse was smart it would
-    only interrupt us if something had changed, but let's assume our mouse 
-    is stupid as most mice actually tend to be. 
-  </para>
-  <para>
-    If the mouse has changed we need to update the status variables. What we
-    don't want is the mouse functions reading these variables to read them
-    during a change. We add a spinlock that protects these variables while we
-    play with them.
-  </para>
-  <para>
-    If a change has occurred we also need to wake sleeping processes, so we 
-    add a wakeup call and a <structname>wait_queue</structname> to use when 
-    we wish to await a mouse event.
-  </para>
-  <para>
-    Now we have the wait queue we can implement the poll function for the 
-    mouse relatively easily:
-  </para>
-
-  <programlisting>
-static unsigned int mouse_poll(struct file *file, poll_table *wait)
-{
-        poll_wait(file, &amp;mouse_wait, wait);
-        if(mouse_event)
-                return POLLIN | POLLRDNORM;
-        return 0;
-}
-  </programlisting>
-
-  <para>
-    This is fairly standard poll code. First we add the wait queue to the 
-    list of queues we want to monitor for an event. Secondly we check if an 
-    event has occurred. We only have one kind of event - the 
-    <varname>mouse_event</varname> flag tells us that something happened. 
-    We know that this something can only be mouse data. We return the flags 
-    indicating input and normal reading will succeed.
-  </para>
-  <para>
-    You may be wondering what happens if the function returns saying 'no 
-    event yet'. In this case the wake up from the wait queue we added to 
-    the poll table will cause the function to be called again. Eventually 
-    we will be woken up and have an event ready. At this point the 
-    <function>poll</function> call will exit back to the user.
-  </para>
-  <para>
-    After the poll completes the user will want to read the data. We now 
-    need to think about how our <function>mouse_read</function> function 
-    will work:
-  </para>
-  <programlisting>
-static ssize_t mouse_read(struct file *file, char *buffer, 
-                size_t count, loff_t *pos)
-{
-        int dx, dy;
-        unsigned char button;
-        unsigned long flags;
-        int n;
-
-        if(count&lt;3)
-                return -EINVAL;
-
-        /*
-          *        Wait for an event
-         */
-
-        while(!mouse_event)
-        {
-                if(file-&gt;f_flags&amp;O_NDELAY)
-                        return -EAGAIN;
-                interruptible_sleep_on(&amp;mouse_wait);
-                if(signal_pending(current))
-                        return -ERESTARTSYS;
-        }
-  </programlisting>
-
-  <para>
-    We start by validating that the user is reading enough data. We could 
-    handle partial reads if we wanted but it isn't terribly useful and the 
-    mouse drivers don't bother to try.
-  </para>
-  <para>
-    Next we wait for an event to occur. The loop is fairly standard event
-    waiting in Linux. Having checked that the event has not yet occurred, we
-    then check if an event is pending and if not we need to sleep. 
-  </para>
-  <para>
-    A user process can set the <constant>O_NDELAY</constant> flag on a file 
-    to indicate that it wishes to be told immediately if no event is 
-    pending. We check this and give the appropriate error if so. 
-  </para>
-  <para>
-    Next we sleep until the mouse or a signal awakens us. A signal will 
-    awaken us as we have used <function>wakeup_interruptible</function>. 
-    This is important as it means a user can kill processes waiting for 
-    the mouse - clearly a desirable property. If we are interrupted we 
-    exit the call and the kernel will then process signals and maybe 
-    restart the call again - from the beginning.
-  </para>
-  <para>
-    This code contains a classic Linux bug. All will be revealed later in this
-    article as well as explanations for how to avoid it.
-  </para>
-  <programlisting>
-        /* Grab the event */
-
-        spinlock_irqsave(&amp;mouse_lock, flags);
-
-        dx = mouse_dx;
-        dy = mouse_dy;
-        button = mouse_buttons;
-
-        if(dx&lt;=-127)
-                dx=-127;
-        if(dx&gt;=127)
-                dx=127;
-        if(dy&lt;=-127)
-                dy=-127;
-        if(dy&gt;=127)
-                dy=127;
-
-        mouse_dx -= dx;
-        mouse_dy -= dy;
-        
-        if(mouse_dx == 0 &amp;&amp; mouse_dy == 0)
-                mouse_event = 0;
-
-        spin_unlock_irqrestore(&amp;mouse_lock, flags);
-  </programlisting>
-  <para>
-    This is the next stage. Having established that there is an event 
-    going, we capture it. To be sure that the event is not being updated 
-    as we capture it we also take the spinlock and thus prevent parallel 
-    updates. Note here we use <function>spinlock_irqsave</function>. We 
-    need to disable interrupts on the local processor otherwise bad things 
-    will happen.
-  </para>
-  <para>
-    What will occur is that we take the spinlock. While we hold the lock 
-    an interrupt will occur. At this point our interrupt handler will try 
-    and take the spinlock. It will sit in a loop waiting for the read 
-    routine to release the lock. However because we are sitting in a loop 
-    in the interrupt handler we will never release the lock. The machine 
-    hangs and the user gets upset.
-  </para>
-  <para>
-    By blocking the interrupt on this processor we ensure that the lock 
-    holder will always give the lock back without deadlocking.
-  </para>
-  <para>
-    There is a little cleverness in the reporting mechanism too. We can 
-    only report a move of 127 per read. We don't however want to lose 
-    information by throwing away further movement. Instead we keep 
-    returning as much information as possible. Each time we return a 
-    report we remove the amount from the pending movement in 
-    <varname>mouse_dx</varname> and <varname>mouse_dy</varname>. Eventually 
-    when these counts hit zero we clear the <varname>mouse_event</varname>
-    flag as there is nothing else left to report.
-  </para>
-
-  <programlisting>
-        if(put_user(button|0x80, buffer))
-                return -EFAULT;
-        if(put_user((char)dx, buffer+1))
-                return -EFAULT;
-        if(put_user((char)dy, buffer+2))
-                return -EFAULT;
-
-        for(n=3; n < count; n++)
-                if(put_user(0x00, buffer+n))
-                        return -EFAULT;
-
-        return count;
-}
-  </programlisting>
-
-  <para>
-    Finally we must put the results in the user supplied buffer. We cannot 
-    do this while holding the lock as a write to user memory may sleep. 
-    For example the user memory may be residing on disk at this instant. 
-    Thus we did our computation beforehand and now copy the data. Each 
-    <function>put_user call</function> is filling in one byte of the buffer. 
-    If it returns an error we inform the program that it passed us an 
-    invalid buffer and abort.
-  </para>
-  <para>
-    Having written the data we blank the rest of the buffer that was read 
-    and report the read as being successful.
-  </para>
- </chapter>
-
- <chapter id="debugging">
-  <title>Debugging the mouse driver</title>
-
-  <para>
-    We now have an almost perfectly usable mouse driver. If you were to 
-    actually try and use it however you would eventually find a couple of 
-    problems with it. A few programs will also not work with as it does not 
-    yet support asynchronous I/O.
-  </para>
-  <para>
-    First let us look at the bugs. The most obvious one isn't really a driver
-    bug but a failure to consider the consequences. Imagine you bumped the 
-    mouse hard by accident and sent it skittering across the desk. The mouse 
-    interrupt routine will add up all that movement and report it in steps of 
-    127 until it has reported all of it. Clearly there is a point beyond 
-    which mouse movement isn't worth reporting. We need to add this as a 
-    limit to the interrupt handler:
-  </para>
-
-  <programlisting>
-static void ourmouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-        char delta_x;
-        char delta_y;
-        unsigned char new_buttons;
-
-        delta_x = inb(OURMOUSE_BASE);
-        delta_y = inb(OURMOUSE_BASE+1);
-        new_buttons = inb(OURMOUSE_BASE+2);
-
-        if(delta_x || delta_y || new_buttons != mouse_buttons)
-        {
-                /* Something happened */
-
-                spin_lock(&amp;mouse_lock);
-                mouse_event = 1;
-                mouse_dx += delta_x;
-                mouse_dy += delta_y;
-
-                if(mouse_dx &lt; -4096)
-                        mouse_dx = -4096;
-                if(mouse_dx &gt; 4096)
-                        mouse_dx = 4096;
-
-                if(mouse_dy &lt; -4096)
-                        mouse_dy = -4096;
-                if(mouse_dy &gt; 4096)
-                        mouse_dy = 4096;
-
-                mouse_buttons = new_buttons;
-                spin_unlock(&amp;mouse_lock);
-                
-                wake_up_interruptible(&amp;mouse_wait);
-        }
-}
-  </programlisting>
-
-  <para>
-    By adding these checks we limit the range of accumulated movement to
-    something sensible. 
-  </para>
-  <para>
-    The second bug is a bit more subtle, and that is perhaps why this is 
-    such a common mistake. Remember, I said the waiting loop for the read 
-    handler had a bug in it. Think about what happens when we execute:
-  </para>
-
-  <programlisting>
-        while(!mouse_event)
-        {
-  </programlisting>
-
-  <para>
-    and an interrupt occurs at this point here. This causes a mouse movement
-    and wakes up the queue. 
-  </para>
-
-  <programlisting>
-                interruptible_sleep_on(&amp;mouse_wait);
-  </programlisting>
-
-  <para>
-    Now we sleep on the queue. We missed the wake up and the application 
-    will not see an event until the next mouse event occurs. This will 
-    lead to just the odd instance when a mouse button gets delayed. The 
-    consequences to the user will probably be almost undetectable with a 
-    mouse driver. With other drivers this bug could be a lot more severe.
-  </para>
-  <para>
-    There are two ways to solve this. The first is to disable interrupts 
-    during the testing and the sleep. This works because when a task sleeps 
-    it ceases to disable interrupts, and when it resumes it disables them 
-    again. Our code thus becomes:
-  </para>
-
-  <programlisting>
-        save_flags(flags);
-        cli();
-
-        while(!mouse_event)
-        {
-                if(file-&gt;f_flags&amp;O_NDELAY)
-                {
-                        restore_flags(flags);
-                        return -EAGAIN;
-                }
-                interruptible_sleep_on(&amp;mouse_wait);
-                if(signal_pending(current))
-                {
-                        restore_flags(flags);
-                        return -ERESTARTSYS;
-                }
-        }
-        restore_flags(flags);
-  </programlisting>
-
-  <para>
-    This is the sledgehammer approach. It works but it means we spend a 
-    lot more time turning interrupts on and off. It also affects 
-    interrupts globally and has bad properties on multiprocessor machines 
-    where turning interrupts off globally is not a simple operation, but 
-    instead involves kicking each processor, waiting for them to disable 
-    interrupts and reply.
-  </para>
-  <para>
-    The real problem is the race between the event testing and the sleeping. 
-    We can avoid that by using the scheduling functions more directly. 
-    Indeed this is the way they generally should be used for an interrupt.
-  </para>
-
-  <programlisting>
-        struct wait_queue wait = { current, NULL };
-
-        add_wait_queue(&amp;mouse_wait, &amp;wait);
-        set_current_state(TASK_INTERRUPTIBLE);
-        
-        while(!mouse_event)
-        {
-                if(file-&gt;f_flags&amp;O_NDELAY)
-                {
-                        remove_wait_queue(&amp;mouse_wait, &amp;wait);
-                        set_current_state(TASK_RUNNING);
-                        return -EWOULDBLOCK;
-                }
-                if(signal_pending(current))
-                {
-                        remove_wait_queue(&amp;mouse_wait, &amp;wait);
-                        current-&gt;state = TASK_RUNNING;
-                        return -ERESTARTSYS;
-                }
-                schedule();
-                set_current_state(TASK_INTERRUPTIBLE);
-        }
-        
-        remove_wait_wait(&amp;mouse_wait, &amp;wait);
-        set_current_state(TASK_RUNNING);
-  </programlisting>
-
-  <para>
-    At first sight this probably looks like deep magic. To understand how 
-    this works you need to understand how scheduling and events work on 
-    Linux. Having a good grasp of this is one of the keys to writing clean 
-    efficient device drivers.
-  </para>
-  <para>
-    <function>add_wait_queue</function> does what its name suggests. It adds 
-    an entry to the <varname>mouse_wait</varname> list. The entry in this 
-    case is the entry for our current process (<varname>current</varname>
-    is the current task pointer). 
-  </para>
-  <para>
-    So we start by adding an entry for ourself onto the 
-    <varname>mouse_wait</varname> list. This does not put us to sleep 
-    however. We are merely tagged onto the list. 
-  </para>
-  <para>
-    Next we set our status to <constant>TASK_INTERRUPTIBLE</constant>. Again 
-    this does not mean we are now asleep. This flag says what should happen 
-    next time the process sleeps. <constant>TASK_INTERRUPTIBLE</constant> says 
-    that the process should not be rescheduled. It will run from now until it 
-    sleeps and then will need to be woken up.
-  </para>
-  <para>
-    The <function>wakeup_interruptible</function> call in the interrupt 
-    handler can now be explained in more detail. This function is also very 
-    simple. It goes along the list of processes on the queue it is given and 
-    any that are marked as <constant>TASK_INTERRUPTIBLE</constant> it changes 
-    to <constant>TASK_RUNNING</constant> and tells the kernel that new 
-    processes are runnable.
-  </para>
-  <para>
-    Behind all the wrappers in the original code what is happening is this
-  </para>
-
-  <procedure>
-   <step>
-    <para>
-      We add ourself to the mouse wait queue
-    </para>
-   </step>
-   <step>
-    <para>
-      We mark ourself as sleeping
-    </para>
-   </step>
-   <step>
-    <para>
-      We ask the kernel to schedule tasks again
-    </para>
-   </step>
-   <step>
-    <para>
-      The kernel sees we are asleep and schedules someone else.
-    </para>
-   </step>
-   <step>
-    <para>
-      The mouse interrupt sets our state to <constant>TASK_RUNNING</constant> 
-      and makes a note that the kernel should reschedule tasks
-    </para>
-   </step>
-   <step>
-    <para>
-      The kernel sees we are running again and continues our execution
-    </para>
-   </step>
-  </procedure>
-  <para>
-    This is why the apparent magic works. Because we mark ourself as
-    <constant>TASK_INTERRUPTIBLE</constant> and as we add ourselves 
-    to the queue before we check if there are events pending, the race 
-    condition is removed.
-  </para>
-  <para>
-    Now if an interrupt occurs after we check the queue status and before 
-    we call the <function>schedule</function> function in order to sleep, 
-    things work out. Instead of missing an event, we are set back to 
-    <constant>TASK_RUNNING</constant> by the mouse interrupt. We still call 
-    <function>schedule</function> but it will continue running our task. 
-    We go back around the loop and this time there may be an event.
-  </para>
-  <para>
-    There will not always be an event. Thus we set ourselves back to
-    <constant>TASK_INTERRUPTIBLE</constant> before resuming the loop. 
-    Another process doing a read may already have cleared the event flag, 
-    and if so we will need to go back to sleep again. Eventually we will 
-    get our event and escape.
-  </para>
-  <para>
-    Finally when we exit the loop we remove ourselves from the 
-    <varname>mouse_wait</varname> queue as we are no longer interested
-    in mouse events, and we set ourself back to 
-    <constant>TASK_RUNNABLE</constant> as we do not wish to go to sleep 
-    again just yet.
-  </para>
-  <note>
-   <title>Note</title> 
-   <para>
-     This isn't an easy topic. Don't be afraid to reread the description a 
-     few times and also look at other device drivers to see how it works. 
-     Finally if you can't grasp it just yet, you can use the code as 
-     boilerplate to write other drivers and trust me instead.
-   </para>
-  </note>
- </chapter>
-
- <chapter id="asyncio">
-  <title>Asynchronous I/O</title>
-  <para>
-    This leaves the missing feature - Asynchronous I/O. Normally UNIX 
-    programs use the <function>poll</function> call (or its variant form 
-    <function>select</function>) to wait for an event to occur on one of 
-    multiple input or output devices. This model works well for most tasks 
-    but because <function>poll</function> and <function>select</function> 
-    wait for an event isn't suitable for tasks that are also continually 
-    doing computation work. Such programs really want the kernel to kick 
-    them when something happens rather than watch for events.
-  </para>
-  <para>
-    Poll is akin to having a row of lights in front of you. You can see at a
-    glance which ones if any are lit. You cannot however get anything useful
-    done while watching them. Asynchronous I/O uses signals which work more 
-    like a door bell. Instead of you watching, it tells you that something 
-    is up.
-  </para>
-  <para>
-    Asynchronous I/O sends the signal SIGIO to a user process when the I/O 
-    events occur. In this case that means when people move the mouse. The 
-    SIGIO signal causes the user process to jump to its signal handler and 
-    execute code in that handler before returning to whatever was going on 
-    previously. It is the application equivalent of an interrupt handler.
-  </para>
-  <para>
-    Most of the code needed for this operation is common to all its users. 
-    The kernel provides a simple set of functions for managing asynchronous 
-    I/O.
-  </para>
-  <para>
-    Our first job is to allow users to set asynchronous I/O on file handles. 
-    To do that we need to add a new function to the file operations table for 
-    our mouse:
-  </para>
-
-  <programlisting>
-struct file_operations our_mouse_fops = {
-        owner: THIS_MODULE
-        read:  read_mouse,      /* You can read a mouse */
-        write: write_mouse,     /* This won't do a lot */
-        poll:  poll_mouse,      /* Poll */
-        open:  open_mouse,      /* Called on open */
-        release: close_mouse,   /* Called on close */
-        fasync: fasync_mouse,   /* Asynchronous I/O */
-};
-  </programlisting>
-
-  <para>
-    Once we have installed this entry the kernel knows we support 
-    asynchronous I/O and will allow all the relevant operations on the 
-    device. Whenever a user adds or removes asynchronous I/O notification 
-    on a file handle it calls our <function>fasync_mouse</function> routine 
-    we just added. This routine uses the helper functions to keep the queue 
-    of handles up to date:
-  </para>
-
-  <programlisting>
-static struct fasync_struct *mouse_fasync = NULL;
-
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-         int retval = fasync_helper(fd, filp, on, &amp;mouse_fasync);
-
-         if (retval &lt; 0)
-                 return retval;
-        return 0;
-}
-  </programlisting>
-
-  <para>
-    The fasync helper adds and deletes entries by managing the supplied 
-    list. We also need to remove entries from this list when the file is 
-    closed. This requires we add one line to our close function:
-  </para>
-
-  <programlisting>
-static int close_mouse(struct inode *inode, struct file *file)
-{
-        fasync_mouse(-1, file, 0)
-        if(--mouse_users)
-                return 0;
-        free_irq(OURMOUSE_IRQ, NULL);
-        return 0;
-}
-  </programlisting>
-
-  <para>
-    When we close the file we now call our own fasync handler as if the 
-    user had requested that this file cease to be used for asynchronous 
-    I/O. This rather neatly cleans up any loose ends. We certainly don't 
-    wait to deliver a signal for a file that no longer exists.
-  </para>
-  <para>
-    At this point the mouse driver supports all the asynchronous I/O 
-    operations, and applications using them will not error. They won't 
-    however work yet. We need to actually send the signals. Again the 
-    kernel provides a function for handling this.
-  </para>
-  <para>
-    We update our interrupt handler a little:
-  </para>
-
-  <programlisting>
-static void ourmouse_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-        char delta_x;
-        char delta_y;
-        unsigned char new_buttons;
-
-        delta_x = inb(OURMOUSE_BASE);
-        delta_y = inb(OURMOUSE_BASE+1);
-        new_buttons = inb(OURMOUSE_BASE+2);
-
-        if(delta_x || delta_y || new_buttons != mouse_buttons)
-        {
-                /* Something happened */
-
-                spin_lock(&amp;mouse_lock);
-                mouse_event = 1;
-                mouse_dx += delta_x;
-                mouse_dy += delta_y;
-
-                if(mouse_dx &lt; -4096)
-                        mouse_dx = -4096;
-                if(mouse_dx &gt; 4096)
-                        mouse_dx = 4096;
-
-                if(mouse_dy &lt; -4096)
-                        mouse_dy = -4096;
-                if(mouse_dy &gt; 4096)
-                        mouse_dy = 4096;
-
-                mouse_buttons = new_buttons;
-                spin_unlock(&amp;mouse_lock);
-
-                /* Now we do asynchronous I/O */
-                kill_fasync(&amp;mouse_fasync, SIGIO); 
-                
-                wake_up_interruptible(&amp;mouse_wait);
-        }
-}
-  </programlisting>
-
-  <para>
-    The new code simply calls the <function>kill_fasync</function> routine
-    provided by the kernel if the queue is non-empty. This sends the 
-    required signal (SIGIO in this case) to the process each file handle 
-    says should be informed about the exciting new mouse movement that 
-    just happened.
-  </para>
-  <para>
-    With this in place and the bugs in the original version fixed, you now 
-    have a fully functional mouse driver using the bus mouse protocol. It 
-    will work with the <application>X window system</application>, will work 
-    with <application>GPM</application> and should work with every other 
-    application you need. <application>Doom</application> is of course the 
-    ideal way to test your new mouse driver is functioning properly. Be sure 
-    to test it thoroughly.
-  </para>
- </chapter>
-</book>
-
diff -Nru a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl
--- a/Documentation/DocBook/videobook.tmpl	2004-10-28 22:25:59 -07:00
+++ b/Documentation/DocBook/videobook.tmpl	2004-10-28 22:25:59 -07:00
@@ -731,13 +731,14 @@
 
 static int io = -1;
 
+#endif
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("A driver for an imaginary radio card.");
-MODULE_PARM(io, "i");
+module_param(io, int, 0444);
 MODULE_PARM_DESC(io, "I/O address of the card.");
 
-int init_module(void)
+static int __init init(void)
 {
         if(io==-1)
         {
@@ -748,25 +749,26 @@
         return myradio_init(NULL);
 }
 
-void cleanup_module(void)
+static void __exit cleanup(void)
 {
         video_unregister_device(&amp;my_radio);
         release_region(io, MY_IO_SIZE);
 }
 
-#endif
+module_init(init);
+module_exit(cleanup);
 
   </programlisting>
   <para>
         In this example we set the IO base by default if the driver is compiled into
-        the kernel where you cannot pass a parameter. For the module we require the
+        the kernel: you can still set it using "my_radio.irq" if this file is called <filename>my_radio.c</filename>. For the module we require the
         user sets the parameter. We set io to a nonsense port (-1) so that we can
         tell if the user supplied an io parameter or not.
   </para>
   <para>
         We use MODULE_ defines to give an author for the card driver and a
         description. We also use them to declare that io is an integer and it is the
-        address of the card.
+        address of the card, and can be read by anyone from sysfs.
   </para>
   <para>
         The clean-up routine unregisters the video_device we registered, and frees
diff -Nru a/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt b/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt
--- a/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt	2004-10-28 22:25:59 -07:00
+++ b/Documentation/arm/Samsung-S3C24XX/EB2410ITX.txt	2004-10-28 22:25:59 -07:00
@@ -15,7 +15,7 @@
 -------------
 
   To set the default configuration, use `make bast_defconfig` which
-  supports the commonly used features of this board
+  supports the commonly used features of this board.
 
 
 Support
@@ -23,15 +23,23 @@
 
   Official support information can be found on the Simtec Electronics
   website, at the product page http://www.simtec.co.uk/products/EB2410ITX/
-  and http://www.simtec.co.uk/products/EB2410ITX/resources.html
+
+  Useful links:
+
+    - Resources Page http://www.simtec.co.uk/products/EB2410ITX/resources.html
+
+    - Board FAQ at http://www.simtec.co.uk/products/EB2410ITX/faq.html
+
+    - Bootloader info http://www.simtec.co.uk/products/SWABLE/resources.html
+      and FAQ http://www.simtec.co.uk/products/SWABLE/faq.html
 
 
 MTD
 ---
 
-  The NAND and NOR onboard are currently supported in the linux-mtd cvs,
-  and are awaiting merge in the mainline. see the linux-mtd project at
-  http://www.linux-mtd.infradead.org/ for more information.
+  The NAND and NOR support has been merged from the linux-mtd project.
+  Any prolbems, see http://www.linux-mtd.infradead.org/ for more
+  information or up-to-date versions of linux-mtd.
 
 
 IDE
@@ -39,6 +47,12 @@
 
   Both onboard IDE ports are supported, however there is no support for
   changing speed of devices, PIO Mode 4 capable drives should be used.
+
+
+Maintainers
+-----------
+
+  This board is maintained by Simtec Electronics.
 
 
 (c) 2004 Ben Dooks, Simtec Electronics
diff -Nru a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt	2004-10-28 22:25:59 -07:00
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt	2004-10-28 22:25:59 -07:00
@@ -48,9 +48,9 @@
 NAND
 ----
 
-  The current kernels do not have direct support for the NAND
-  controller, the latest linux-mtd CVS has support for this.
-  See http://www.linux-mtd.infradead.org/
+  The current kernels now have support for the s3c2410 NAND
+  controller. If there are any problems the latest linux-mtd
+  CVS can be found from http://www.linux-mtd.infradead.org/
 
 
 Serial
@@ -84,12 +84,21 @@
 Port Contributors
 -----------------
 
-  Ben Dooks
+  Ben Dooks (BJD)
   Vincent Sanders
   Herbert Potzl
-  Arnaud Patard
+  Arnaud Patard (RTP)
   Roc Wu
+  Klaus Fetscher
+  Dimitry Andric
 
+Document Changes
+----------------
+
+  05 Sep 2004 - BJD - Added Document Changes section
+  05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors
+  25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors
+  25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge
 
 Document Author
 ---------------
diff -Nru a/Documentation/arm/Samsung-S3C24XX/Suspend.txt b/Documentation/arm/Samsung-S3C24XX/Suspend.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/Samsung-S3C24XX/Suspend.txt	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,88 @@
+			S3C24XX Suspend Support
+			=======================
+
+
+Introduction
+------------
+
+  The S3C2410 supports a low-power suspend mode, where the SDRAM is kept
+  in Self-Refresh mode, and all but the esential peripheral blocks are
+  powered down. For more information on how this works, please look
+  at the S3C2410 datasheets from Samsung.
+
+
+Requirements
+------------
+
+  1) A bootloader that can support the necessary resume operation
+
+  2) Support for at least 1 source for resume
+
+  3) CONFIG_PM enabled in the kernel
+
+  4) Any peripherals that are going to be powered down at the same
+     time require suspend/resume support.
+
+
+Resuming
+--------
+
+  The S3C2410 user manual defines the process of sending the CPU to
+  sleep and how it resumes. The default behaviour of the Linux code
+  is to set the GSTATUS3 register to the physical address of the
+  code to resume Linux operation.
+
+  GSTATUS4 is currently left alone by the sleep code, and is free to
+  use for any other purposes.
+
+
+Machine Support
+---------------
+
+  The machine specific functions must call the s3c2410_pm_init() function
+  to say that it's bootloader is capable of resuming. This can be as
+  simple as adding the following to the file:
+
+  late_initcall(s3c2410_pm_init);
+
+  A board can do its own setup before calling s3c2410_pm_init, if it
+  needs to setup anything else for power management support.
+
+  There is currently no support for over-riding the default method of
+  saving the resume address, if your board requires it, then contact
+  the maintainer and discuss what is required.
+
+
+Configuration
+-------------
+
+  The S3C2410 specific configuration in `System Type` defines various
+  aspects of how the S3C2410 suspend and resume support is configured
+
+  `S3C2410 PM Suspend debug`
+
+    This option prints messages to the serial console before and after
+    the actual suspend, giving detailed information on what is
+    happening
+
+
+  `S3C2410 PM Suspend Memory CRC`
+
+    Allows the entire memory to be checksummed before and after the
+    suspend to see if there has been any corruption of the contents.
+
+    This support requires the CRC32 function to be enabled.
+
+
+  `S3C2410 PM Suspend CRC Chunksize (KiB)`
+
+    Defines the size of memory each CRC chunk covers. A smaller value
+    will mean that the CRC data block will take more memory, but will
+    identify any faults with better precision
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2004 Simtec Electronics
+
diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt
--- a/Documentation/devices.txt	2004-10-28 22:25:57 -07:00
+++ b/Documentation/devices.txt	2004-10-28 22:25:57 -07:00
@@ -2546,12 +2546,7 @@
 		  0 = /dev/usb/lp0	First USB printer
 		    ...
 		 15 = /dev/usb/lp15	16th USB printer
-		 16 = /dev/usb/mouse0	First USB mouse
-		    ...
-		 31 = /dev/usb/mouse15	16th USB mouse
-		 32 = /dev/usb/ez0	First USB firmware loader
-		    ...
-		 47 = /dev/usb/ez15	16th USB firmware loader
+		 32 = /dev/usb/mdc800	MDC800 USB camera
 		 48 = /dev/usb/scanner0	First USB scanner
 		    ...
 		 63 = /dev/usb/scanner15 16th USB scanner
@@ -2559,6 +2554,22 @@
 		 65 = /dev/usb/usblcd	USBLCD Interface (info@usblcd.de)
 		 66 = /dev/usb/cpad0	Synaptics cPad (mouse/LCD)
 
+		 96 = /dev/usb/hiddev0	1st USB HID device
+		    ...
+		111 = /dev/usb/hiddev15	16th USB HID device
+		112 = /dev/usb/auer0	1st auerswald ISDN device
+		    ...
+		127 = /dev/usb/auer15	16th auerswald ISDN device
+		128 = /dev/usb/brlvgr0	First Braille Voyager device
+		    ...
+		131 = /dev/usb/brlvgr3	Fourth Braille Voyager device
+		144 = /dev/usb/lcd	USB LCD device
+		160 = /dev/usb/legousbtower0	1st USB Legotower device
+		    ...
+		175 = /dev/usb/legousbtower15	16th USB Legotower device
+		240 = /dev/usb/dabusb0	First daubusb device
+		    ...
+		243 = /dev/usb/dabusb3	Fourth dabusb device
 
 181 char	Conrad Electronic parallel port radio clocks
 		  0 = /dev/pcfclock0	First Conrad radio clock
diff -Nru a/Documentation/dvb/README.dibusb b/Documentation/dvb/README.dibusb
--- a/Documentation/dvb/README.dibusb	2004-10-28 22:25:56 -07:00
+++ b/Documentation/dvb/README.dibusb	2004-10-28 22:25:56 -07:00
@@ -1,9 +1,11 @@
+
+
 Documentation for dib3000mb frontend driver and dibusb device driver
 
 The drivers should work with
 
 - Twinhan VisionPlus VisionDTV USB-Ter DVB-T Device (VP7041)
-	http://www.twinhan.com/visiontv-2_4.htm
+	http://www.twinhan.com/
 
 - CTS Portable (Chinese Television System)
 	http://www.2cts.tv/ctsportable/
@@ -19,6 +21,10 @@
 - Ultima Electronic/Artec T1 USB TVBOX
 	http://www.arteceuro.com/products-tvbox.html
 
+- Compro Videomate DVB-U2000 - DVB-T USB
+	http://www.comprousa.com/products/vmu2000.htm
+
+- Unknown USB DVB-T device with vendor ID Hyper-Paltek
 
 Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de),
 
@@ -32,6 +38,11 @@
 
 
 NEWS:
+  2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
+  2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
+               to Amaury Demol for reporting
+             - changed usb TS transfer method (several urbs, stopping transfer 
+               before setting a new pid)
   2004-09-13 - added support for a new device (Artec T1 USB TVBOX), thanks
                to Christian Motschke for reporting
   2004-09-05 - released the dibusb device and dib3000mb-frontend driver
@@ -85,8 +96,13 @@
 
 If you want to enable debug output, you have to load the driver manually.
 
-modprobe dvb-dibusb debug=1
-modprobe dib3000mb debug=1
+first have a look, which debug level are available:
+
+modinfo dvb-dibusb
+modinfo dib3000mb
+
+modprobe dvb-dibusb debug=<level> 
+modprobe dib3000mb debug=<level>
 
 should do the trick.
 
@@ -102,11 +118,13 @@
 2. Known problems and bugs
 
 TODO:
-- add some additional URBs for USB data transfer
-- due a firmware problem i2c writes during mpeg transfers destroy the stream
-  no i2c writes during streaming, interrupt streaming, when adding another pid
+- remote control tasklet
+- signal-quality and strength calculations
+- debug messages restructure
+- i2c address probing
+- 
 
-2.1. Adding new devices
+2.1. Adding support for devices 
 
 It is not possible to determine the range of devices based on the DiBcom
 reference design. This is because the reference design of DiBcom can be sold
@@ -122,7 +140,7 @@
 others.
 
 If you are familar with C you can also add the VID and PID of the device to
-the dvb-dibusb.[hc]-files and create a patch and send it over to me or to
+the dvb-dibusb.h-file and create a patch and send it over to me or to 
 the linux-dvb mailing list, _after_ you have tried compiling and modprobing
 it.
 
diff -Nru a/Documentation/dvb/readme.txt b/Documentation/dvb/readme.txt
--- a/Documentation/dvb/readme.txt	2004-10-28 22:25:56 -07:00
+++ b/Documentation/dvb/readme.txt	2004-10-28 22:25:56 -07:00
@@ -41,9 +41,9 @@
 various bt8xx based "budget" DVB cards
 (Nebula, Pinnacle PCTV, Twinhan DST)
 
-"vp7041.txt"
-contains detailed informations about the
-Visionplus VisionDTV USB-Ter DVB-T adapter.
+"README.dibusb"
+contains detailed information about adapters
+based on DiBcom reference design.
 
 "udev.txt"
 how to get DVB and udev up and running.
diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
--- a/Documentation/filesystems/proc.txt	2004-10-28 22:25:57 -07:00
+++ b/Documentation/filesystems/proc.txt	2004-10-28 22:25:57 -07:00
@@ -380,9 +380,7 @@
 Slab:           684068 kB
 CommitLimit:   7669796 kB
 Committed_AS:   100056 kB
-CommitAvail:   7569740 kB
 PageTables:      24448 kB
-ReverseMaps:   1080904
 VmallocTotal:   112216 kB
 VmallocUsed:       428 kB
 VmallocChunk:   111088 kB
@@ -446,20 +444,8 @@
               above) will not be permitted. This is useful if one needs
               to guarantee that processes will not fail due to lack of
               memory once that memory has been successfully allocated.
- CommitAvail: Based on the current overcommit ratio
-              ('vm.overcommit_ratio'), this is the amount of memory
-              currently available to be allocated under the overcommit
-              limit (the CommitLimit above). This is calculated as:
-              CommitAvail = CommitLimit - Committed_AS
-              This limit is only enforced if strict overcommit accounting
-              is enabled (mode 2 in 'vm.overcommit_memory'). CommitAvail
-              may be a negative number if strict accounting is not enabled
-              and the system's memory is currently overcommitted.
-              For more details, see the memory overcommit documentation
-              in vm/overcommit-accounting.
   PageTables: amount of memory dedicated to the lowest level of page
               tables.
- ReverseMaps: number of reverse mappings performed
 VmallocTotal: total size of vmalloc memory area
  VmallocUsed: amount of vmalloc area which is used
 VmallocChunk: largest contigious block of vmalloc area which is free
diff -Nru a/Documentation/ftape.txt b/Documentation/ftape.txt
--- a/Documentation/ftape.txt	2004-10-28 22:25:56 -07:00
+++ b/Documentation/ftape.txt	2004-10-28 22:25:56 -07:00
@@ -2,26 +2,21 @@
 =====
 
 This file describes some issues involved when using the "ftape"
-floppy tape device driver that comes with the Linux kernel. This
-document deals with ftape-3.04 and later. Please read the section
-"Changes" for the most striking differences between version 3.04 and
-2.08; the latter was the version of ftape delivered with the kernel
-until kernel version 2.0.30 and 2.1.57. ftape-3.x developed as the
-re-unification of ftape-2.x and zftape. zftape was developed in
-parallel with the stock ftape-2.x driver sharing the same hardware
-support but providing an enhanced file system interface. zftape also
-provided user transparent block-wise on-the-fly compression (regard it
-as a feature or bug of zftape).
+floppy tape device driver that comes with the Linux kernel.
 
 ftape has a home page at
 
-http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape
+http://ftape.dot-heine.de/
 
 which contains further information about ftape. Please cross check
 this WWW address against the address given (if any) in the MAINTAINERS
 file located in the top level directory of the Linux kernel source
 tree.
 
+NOTE: This is an unmaintained set of drivers, and it is not guaranteed to work.
+If you are interested in taking over maintenance, contact Claus-Justus Heine
+<ch@dot-heine.de>, the former maintainer.
+
 Contents
 ========
 
@@ -31,9 +26,8 @@
    1. Goal
    2. I/O Block Size
    3. Write Access when not at EOD (End Of Data) or BOT (Begin Of Tape)
-   4. MTBSF - backspace over file mark and position at its EOT side
-   5. Formatting
-   6. Interchanging cartridges with other operating systems
+   4. Formatting
+   5. Interchanging cartridges with other operating systems
 
 B. Debugging Output
    1. Introduction
@@ -58,7 +52,7 @@
 versions of ftape and useful links to related topics can be found at
 the ftape home page at
 
-http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape
+http://ftape.dot-heine.de/
 
 *******************************************************************************
 
@@ -70,7 +64,7 @@
    The goal of all that incompatibilities was to give ftape an interface
    that resembles the interface provided by SCSI tape drives as close
    as possible. Thus any Unix backup program that is known to work
-   with SCSI tape drives should also work with ftape-3.04 and above.
+   with SCSI tape drives should also work.
 
    The concept of a fixed block size for read/write transfers is
    rather unrelated to this SCSI tape compatibility at the file system
@@ -81,14 +75,8 @@
 
 2. I/O Block Size
    ~~~~~~~~~~~~~~
-   The probably most striking difference between ftape-2.x and
-   ftape-3.x with the zftape file system interface is the concept of a
-   fixed block size: data must be written to or read from the tape in
-   multiples of a fixed block size. The block size defaults to 10k
-   which is the default block size of GNU tar. While this is quite
-   usual for SCSI tapes (block size of 32k?) and the QIC-150 driver
-   `./drivers/char/tpqic02.c' ftape-2.x allowed data to be written in
-   arbitrary portions to the tape.
+   The block size defaults to 10k which is the default block size of
+   GNU tar.
 
    The block size can be tuned either during kernel configuration or
    at runtime with the MTIOCTOP ioctl using the MTSETBLK operation
@@ -109,53 +97,41 @@
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    zftape (the file system interface of ftape-3.x) denies write access
    to the tape cartridge when it isn't positioned either at BOT or
-   EOD. This inconvenience has been introduced as it was reported that
-   the former behavior of ftape-2.x which allowed write access at
-   arbitrary locations already has caused data loss with some backup
-   programs.
-
-4. MTBSF - backspace over file mark and position at its EOT side
-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   ftape-2.x didn't handle the MTBSF tape operation correctly. A MTBSF
-   call (i.e. "mt -f /dev/nqft0 bsf #COUNT") should space over #COUNT
-   file marks and then position at the EOT tape side of the file
-   mark. This has to be taken literally, i.e. "mt -f /dev/nqft0 bsf 1"
-   should simply position at the start of the current volume.
+   EOD.
 
-5. Formatting
+4. Formatting
    ~~~~~~~~~~
-   ftape-3.x DOES support formatting of floppy tape cartridges. You
-   need the `ftformat' program that is shipped with the modules version
-   of ftape-3.x. Please get the latest version of ftape from
+   ftape DOES support formatting of floppy tape cartridges. You need the
+   `ftformat' program that is shipped with the modules version of ftape.
+   Please get the latest version of ftape from
 
    ftp://sunsite.unc.edu/pub/Linux/kernel/tapes
 
    or from the ftape home page at
 
-   http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape
+   http://ftape.dot-heine.de/
 
    `ftformat' is contained in the `./contrib/' subdirectory of that
    separate ftape package.
 
-6. Interchanging cartridges with other operating systems
+5. Interchanging cartridges with other operating systems
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
    The internal emulation of Unix tape device file marks has changed
-   completely. ftape-3.x now uses the volume table segment as specified
+   completely. ftape now uses the volume table segment as specified
    by the QIC-40/80/3010/3020/113 standards to emulate file marks. As
    a consequence there is limited support to interchange cartridges
    with other operating systems.
 
    To be more precise: ftape will detect volumes written by other OS's
    programs and other OS's programs will detect volumes written by
-   ftape-3.x.
+   ftape.
 
    However, it isn't possible to extract the data dumped to the tape
-   by some MSDOG program with ftape-3.x. This exceeds the scope of a
+   by some MSDOS program with ftape. This exceeds the scope of a
    kernel device driver. If you need such functionality, then go ahead
-   and write a user space utility that is able to do
-   that. ftape-3.x/zftape already provides all kernel level support
-   necessary to do that.
+   and write a user space utility that is able to do that. ftape already
+   provides all kernel level support necessary to do that.
 
 *******************************************************************************
 
@@ -200,7 +176,7 @@
 
    ii) trim the debugging output at module load time with
 
-       insmod ftape.o ft_tracing=#DBGLVL
+       modprobe ftape ft_tracing=#DBGLVL
 
        Of course, this applies only if you have configured ftape to be
        compiled as a module.
@@ -240,7 +216,7 @@
 2. Module load time parameters
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Module parameters can be specified either directly when invoking
-   the program 'insmod' at the shell prompt:
+   the program 'modprobe' at the shell prompt:
 
    modprobe ftape ft_tracing=4
 
@@ -277,6 +253,12 @@
 	line documentation provided during that kernel configuration
 	process.
 
+	ft_probe_fc10 is set to a non-zero value if you wish for ftape to
+	probe for a Colorado FC-10 or FC-20 controller.
+
+	ft_mach2 is set to a non-zero value if you wish for ftape to probe
+	for a Mountain MACH-2 controller.
+
         module                 |  kernel command line
         -----------------------|----------------------
         ft_fdc_base=BASE       |  ftape=BASE,ioport
@@ -316,10 +298,10 @@
    page to query for the most recent documentation, related work and
    development versions of ftape.
 
+   Changelog:
+   ==========
+
+~1996:		Original Document
 
- LocalWords:  ftape Linux zftape http www rwth aachen LBFM claus EOD config
- LocalWords:  datarate LocalWords BOT MTBSF EOT HOWTO QIC tpqic menuconfig
- LocalWords:  MTIOCTOP MTSETBLK mt dev qft setblk BLKSZ bsf zftape's xconfig
- LocalWords:  nqft ftformat ftp sunsite unc edu contrib ft MSDOG fdc
- LocalWords:  dma setdensity DBGLVL insmod lilo LI nux ader conf txt
- LocalWords:  modprobe IRQ BOOL ioport irq fc mach THR
+10-24-2004:	General cleanup and updating, noting additional module options.
+		James Nelson <james4765@gmail.com>
diff -Nru a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
--- a/Documentation/i2c/writing-clients	2004-10-28 22:25:57 -07:00
+++ b/Documentation/i2c/writing-clients	2004-10-28 22:25:57 -07:00
@@ -571,7 +571,7 @@
      have to be cleaned up! */
   static int __initdata foo_initialized = 0;
 
-  int __init foo_init(void)
+  static int __init foo_init(void)
   {
     int res;
     printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
@@ -585,41 +585,27 @@
     return 0;
   }
 
-  int __init foo_cleanup(void)
+  void foo_cleanup(void)
   {
-    int res;
     if (foo_initialized == 1) {
       if ((res = i2c_del_driver(&foo_driver))) {
         printk("foo: Driver registration failed, module not removed.\n");
-        return res;
+        return;
       }
       foo_initialized --;
     }
-    return 0;
   }
 
-  #ifdef MODULE
-
   /* Substitute your own name and email address */
   MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
   MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
 
-  int init_module(void)
-  {
-    return foo_init();
-  }
-
-  int cleanup_module(void)
-  {
-    return foo_cleanup();
-  }
-
-  #endif /* def MODULE */
+  module_init(foo_init);
+  module_exit(foo_cleanup);
 
 Note that some functions are marked by `__init', and some data structures
-by `__init_data'. If this driver is compiled as part of the kernel (instead
-of as a module), those functions and structures can be removed after
-kernel booting is completed.
+by `__init_data'.  Hose functions and structures can be removed after
+kernel booting (or module loading) is completed.
 
 Command function
 ================
diff -Nru a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
--- a/Documentation/kbuild/makefiles.txt	2004-10-28 22:25:59 -07:00
+++ b/Documentation/kbuild/makefiles.txt	2004-10-28 22:25:59 -07:00
@@ -997,6 +997,21 @@
 	option. When $(biarch) equals to y the expanded variables $(aflags-y)
 	and $(cflags-y) will be assigned the values -a32 and -m32.
 
+    cc-option-align
+	gcc version >= 3.0 shifted type of options used to speify
+	alignment of functions, loops etc. $(cc-option-align) whrn used
+	as prefix to the align options will select the right prefix:
+	gcc < 3.00
+		cc-option-align = -malign
+	gcc >= 3.00
+		cc-option-align = -falign
+	
+	Example:
+		CFLAGS += $(cc-option-align)-functions=4
+
+	In the above example the option -falign-functions=4 is used for
+	gcc >= 3.00. For gcc < 3.00 -malign-functions=4 is used.
+	
     cc-version
 	cc-version return a numerical version of the $(CC) compiler version.
 	The format is <major><minor> where both are two digits. So for example
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	2004-10-28 22:25:59 -07:00
+++ b/Documentation/kernel-parameters.txt	2004-10-28 22:25:59 -07:00
@@ -1217,8 +1217,8 @@
 	sonycd535=	[HW,CD]
 			Format: <io>[,<irq>]
 
-	sonypi=		[HW] Sony Programmable I/O Control Device driver
-			Format: <minor>,<verbose>,<fnkeyinit>,<camera>,<compat>,<nojogdial>
+	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
+			See Documentation/sonypi.txt
 
 	specialix=	[HW,SERIAL] Specialix multi-serial port adapter
 			See Documentation/specialix.txt.
diff -Nru a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt
--- a/Documentation/networking/e100.txt	2004-10-28 22:25:59 -07:00
+++ b/Documentation/networking/e100.txt	2004-10-28 22:25:59 -07:00
@@ -1,14 +1,16 @@
 Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
 ==============================================================
 
-March 15, 2004
+September 13, 2004
 
 
 Contents
 ========
 
 - In This Release
-- Supported Adapters
+- Identifying Your Adapter
+- Driver Configuration Parameters
+- Additional Configurations
 - Support
 
 
@@ -16,26 +18,140 @@
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
-Adapters, version 3.x.x.  This driver includes support for Itanium(TM)-based 
-systems.
+Adapters, version 3.2.x.  This driver includes support for Itanium(TM)2 and
+EM64T systems.
 
 
-Supported Adapters
-==================
-
-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.
+Identifying Your Adapter
+========================
 
 For more information on how to identify your adapter, go to the Adapter & 
 Driver ID Guide at:
 
   http://support.intel.com/support/network/adapter/pro100/21397.htm
 
-For the latest Intel PRO/100 network driver for Linux, see:
+For the latest Intel network drivers for Linux, refer to the following 
+website. In the search field, enter your adapter name or type, or use the 
+networking link on the left to search for your adapter:
 
   http://downloadfinder.intel.com/scripts-df/support_intel.asp
 
+Driver Configuration Parameters
+===============================
+
+The default value for each parameter is generally the recommended setting,
+unless otherwise noted.
+
+Rx Descriptors: Number of receive descriptors. A receive descriptor is a data 
+   structure that describes a receive buffer and its attributes to the network 
+   controller. The data in the descriptor is used by the controller to write 
+   data from the controller to host memory. In the 3.0.x driver the valid
+   range for this parameter is 64-256. The default value is 64. This parameter 
+   can be changed using the command 
+ 
+   ethtool -G eth? rx n, where n is the number of desired rx descriptors.
+
+Tx Descriptors: Number of transmit descriptors. A transmit descriptor is a
+   data structure that describes a transmit buffer and its attributes to the
+   network controller. The data in the descriptor is used by the controller to 
+   read data from the host memory to the controller. In the 3.0.x driver the 
+   valid range for this parameter is 64-256. The default value is 64. This 
+   parameter can be changed using the command 
+
+   ethtool -G eth? tx n, where n is the number of desired tx descriptors.
+
+Speed/Duplex: The driver auto-negotiates the link speed and duplex settings by 
+   default. Ethtool can be used as follows to force speed/duplex. 
+
+   ethtool -s eth?  autoneg off speed {10|100} duplex {full|half}
+
+   NOTE: setting the speed/duplex to incorrect values will cause the link to
+   fail.
+
+Event Log Message Level:  The driver uses the message level flag to log events 
+   to syslog. The message level can be set at driver load time. It can also be 
+   set using the command
+
+   ethtool -s eth? msglvl n
+
+Additional Configurations
+=========================
+
+  Configuring the Driver on Different Distributions
+  -------------------------------------------------
+
+  Configuring a network driver to load properly when the system is started is 
+  distribution dependent. Typically, the configuration process involves adding 
+  an alias line to /etc/modules.conf as well as editing other system startup 
+  scripts and/or configuration files.  Many popular Linux distributions ship 
+  with tools to make these changes for you. To learn the proper way to 
+  configure a network device for your system, refer to your distribution 
+  documentation. If during this process you are asked for the driver or module 
+  name, the name for the Linux Base Driver for the Intel PRO/100 Family of 
+  Adapters is e100.
+
+  As an example, if you install the e100 driver for two PRO/100 adapters 
+  (eth0 and eth1), add the following to modules.conf:
+
+       alias eth0 e100
+       alias eth1 e100
+
+  Viewing Link Messages
+  ---------------------
+  In order to see link messages and other Intel driver information on your 
+  console, you must set the dmesg level up to six. This can be done by 
+  entering the following on the command line before loading the e100 driver: 
+
+       dmesg -n 8
+
+  If you wish to see all messages issued by the driver, including debug 
+  messages, set the dmesg level to eight.
+
+  NOTE: This setting is not saved across reboots.
+
+  Ethtool
+  -------
+
+  The driver utilizes the ethtool interface for driver configuration and
+  diagnostics, as well as displaying statistical information.  Ethtool
+  version 1.6 or later is required for this functionality.
+
+  The latest release of ethtool can be found at:
+  http://sf.net/projects/gkernel.  
+
+  After ethtool is installed, ethtool-copy.h must be copied and renamed to
+  ethtool.h in your kernel source tree at <linux_kernel_src>/include/linux.  
+  Backup the original ethtool.h as needed before copying.  The driver then 
+  must be recompiled in order to take advantage of the latest ethtool 
+  features.
+
+  NOTE: This driver uses mii support from the kernel. As a result, when 
+  there is no link, ethtool will report speed/duplex to be 10/half.
+
+  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support 
+  for a more complete ethtool feature set can be enabled by upgrading 
+  ethtool to ethtool-1.8.1. 
+
+  Enabling Wake on LAN* (WoL)
+  ---------------------------
+  WoL is provided through the Ethtool* utility. Ethtool is included with Red 
+  Hat* 8.0. For other Linux distributions, download and install Ethtool from 
+  the following website: http://sourceforge.net/projects/gkernel. 
+
+  For instructions on enabling WoL with Ethtool, refer to the Ethtool man
+  page.
+
+  WoL will be enabled on the system during the next shut down or reboot. For
+  this driver version, in order to enable WoL, the e100 driver must be 
+  loaded when shutting down or rebooting the system.
+
+  NAPI
+  ----
+
+  NAPI (Rx polling mode) is supported in the e100 driver. NAPI is enabled
+  or disabled based on the configuration of the kernel. 
+
+  See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
 
 Support
 =======
diff -Nru a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt
--- a/Documentation/networking/e1000.txt	2004-10-28 22:25:59 -07:00
+++ b/Documentation/networking/e1000.txt	2004-10-28 22:25:59 -07:00
@@ -1,14 +1,14 @@
 Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
 ===============================================================
 
-January 8, 2003
+September 13, 2004
 
 
 Contents
 ========
 
 - In This Release
-- Supported Adapters
+- Identifying Your Adapter
 - Command Line Parameters
 - Speed and Duplex Configuration
 - Additional Configurations
@@ -20,63 +20,29 @@
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
-of Adapters, version 5.0.x.  This driver includes support for 
-Itanium(TM)-based systems.
+of Adapters, version 5.x.x.  This driver includes support for Itanium(TM)2 
+and EM64T systems.
 
+For questions related to hardware requirements, refer to the documentation 
+supplied with your Intel PRO/1000 adapter. All hardware requirements listed 
+apply to use with Linux.
 
 Native VLANs are now available with supported kernels.
 
-
-Supported Adapters
-==================
-
-The following Intel network adapters are compatible with the drivers in this 
-release:
-
-   Controller  Adapter Name                         Board IDs
-   ----------  ------------                         ---------
-
-   82542       PRO/1000 Gigabit Server Adapter      700262-xxx, 717037-xxx
-
-   82543       PRO/1000 F Server Adapter            738640-xxx, A38888-xxx
-
-   82543       PRO/1000 T Server Adapter            A19845-xxx, A33948-xxx
-
-   82544       PRO/1000 XT Server Adapter           A51580-xxx
-
-   82544       PRO/1000 XF Server Adapter           A50484-xxx
-
-   82544       PRO/1000 T Desktop Adapter           A62947-xxx
-
-   82540       PRO/1000 MT Desktop Adapter          A78408-xxx
-   82541                                            C91016-xxx
-
-   82545       PRO/1000 MT Server Adapter           A92165-xxx
-
-   82546       PRO/1000 MT Dual Port Server Adapter A92111-xxx
-
-   82545       PRO/1000 MF Server Adapter           A91622-xxx
-
-   82545       PRO/1000 MF Server Adapter(LX)       A91624-xxx
-
-   82546       PRO/1000 MF Dual Port Server Adapter A91620-xxx
-
-
-
-To verify your Intel 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.
+Identifying Your Adapter
+========================
 
 For more information on how to identify your adapter, go to the Adapter & 
 Driver ID Guide at:
 
     http://support.intel.com/support/network/adapter/pro100/21397.htm
 
-For the latest Intel network drivers for Linux, refer to the following
+For the latest Intel network drivers for Linux, refer to the following 
+website. In the search field, enter your adapter name or type, or use the 
+networking link on the left to search for your adapter:
 
     http://downloadfinder.intel.com/scripts-df/support_intel.asp
 
-
 Command Line Parameters
 =======================
 
@@ -92,27 +58,39 @@
 
      insmod e1000 TxDescriptors=80,128
 
-loads the e1000 driver with 80 TX resources for the first adapter and 128 TX 
-resources for the second adapter.
+loads the e1000 driver with 80 TX descriptors for the first adapter and 128 TX 
+descriptors for the second adapter.
 
 The default value for each parameter is generally the recommended setting,
-unless otherwise noted.
-
-For more information about the AutoNeg, Duplex, and Speed parameters, see the
-"Speed and Duplex Configuration" section in this document.
+unless otherwise noted. Also, if the driver is statically built into the
+kernel, the driver is loaded with the default values for all the parameters.
+Ethtool can be used to change some of the parameters at runtime.
+
+    NOTES: For more information about the AutoNeg, Duplex, and Speed
+           parameters, see the "Speed and Duplex Configuration" section in 
+           this document.
+
+           For more information about the InterruptThrottleRate, RxIntDelay, 
+           TxIntDelay, RxAbsIntDelay, and TxAbsIntDelay parameters, see the 
+           application note at:
+           http://www.intel.com/design/network/applnots/ap450.htm
 
+           A descriptor describes a data buffer and attributes related to the 
+           data buffer. This information is accessed by the hardware.
 
 AutoNeg (adapters using copper connections only)
 Valid Range: 0x01-0x0F, 0x20-0x2F
 Default Value: 0x2F
     This parameter is a bit mask that specifies which speed and duplex
     settings the board advertises. When this parameter is used, the Speed and
-    Duplex parameters must not be specified.  
+    Duplex parameters must not be specified.
+    NOTE: Refer to the Speed and Duplex section of this readme for more 
+          information on the AutoNeg parameter.  
 
 Duplex (adapters using copper connections only)
 Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full)
 Default Value: 0
-    Defines the direction in which data is allowed to flow. Can by either one 
+    Defines the direction in which data is allowed to flow. Can be either one 
     or two-directional. If both Duplex and the link partner are set to auto-
     negotiate, the board auto-detects the correct duplex. If the link partner
     is forced (either full or half), Duplex defaults to half-duplex.
@@ -125,22 +103,46 @@
 
 InterruptThrottleRate
 Valid Range: 100-100000 (0=off, 1=dynamic)
-Default Value: 1
+Default Value: 8000
     This value represents the maximum number of interrupts per second the 
     controller generates. InterruptThrottleRate is another setting used in 
     interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust 
     InterruptThrottleRate based on the current traffic load.
+Un-supported Adapters: InterruptThrottleRate is NOT supported by 82542, 82543
+    or 82544-based adapters.
 
     NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and 
           RxAbsIntDelay parameters. In other words, minimizing the receive 
           and/or transmit absolute delays does not force the controller to 
           generate more interrupts than what the Interrupt Throttle Rate 
           allows.
+    CAUTION: If you are using the Intel PRO/1000 CT Network Connection 
+             (controller 82547), setting InterruptThrottleRate to a value 
+             greater than 75,000, may hang (stop transmitting) adapters under 
+             certain network conditions. If this occurs a NETDEV WATCHDOG 
+             message is logged in the system event log. In addition, the 
+             controller is automatically reset, restoring the network 
+             connection. To eliminate the potential for the hang, ensure 
+             that InterruptThrottleRate is set no greater than 75,000 and is 
+             not set to 0.
+    NOTE: When e1000 is loaded with default settings and multiple adapters are 
+          in use simultaneously, the CPU utilization may increase non-linearly. 
+          In order to limit the CPU utilization without impacting the overall 
+          throughput, we recommend that you load the driver as follows:
+
+              insmod e1000.o InterruptThrottleRate=3000,3000,3000
+
+          This sets the InterruptThrottleRate to 3000 interrupts/sec for the 
+          first, second, and third instances of the driver. The range of 2000 to 
+          3000 interrupts per second works on a majority of systems and is a 
+          good starting point, but the optimal value will be platform-specific. 
+          If CPU utilization is not a concern, use RX_POLLING (NAPI) and default 
+          driver settings.
 
 RxDescriptors
 Valid Range: 80-256 for 82542 and 82543-based adapters
-             80-4096 for 82540, 82544, 82545, and 82546-based adapters
-Default Value: 80
+             80-4096 for all other supported adapters
+Default Value: 256
     This value is the number of receive descriptors allocated by the driver. 
     Increasing this value allows the driver to buffer more incoming packets. 
     Each descriptor is 16 bytes.  A receive buffer is also allocated for each
@@ -149,6 +151,9 @@
 
     NOTE: MTU designates the frame size. It only needs to be set for Jumbo 
           Frames.
+    NOTE: Depending on the available system resources, the request for a
+    higher number of receive descriptors may be denied.  In this case,
+    use a lower number.
 
 RxIntDelay
 Valid Range: 0-65535 (0=off)
@@ -168,11 +173,11 @@
              restoring the network connection. To eliminate the potential for
              the hang ensure that RxIntDelay is set to 0.
 
-RxAbsIntDelay (82540, 82545, and 82546-based adapters only)
+RxAbsIntDelay (82540, 82545 and later adapters only)
 Valid Range: 0-65535 (0=off)
 Default Value: 128
     This value, in units of 1.024 microseconds, limits the delay in which a 
-    transmit interrupt is generated. Useful only if RxIntDelay is non-zero, 
+    receive interrupt is generated. Useful only if RxIntDelay is non-zero, 
     this value ensures that an interrupt is generated after the initial 
     packet is received within the set amount of time.  Proper tuning,
     along with RxIntDelay, may improve traffic throughput in specific network
@@ -188,12 +193,16 @@
 
 TxDescriptors
 Valid Range: 80-256 for 82542 and 82543-based adapters
-             80-4096 for 82540, 82544, 82545, and 82546-based adapters
+             80-4096 for all other supported adapters
 Default Value: 256
     This value is the number of transmit descriptors allocated by the driver.
     Increasing this value allows the driver to queue more transmits. Each 
     descriptor is 16 bytes.
 
+    NOTE: Depending on the available system resources, the request for a
+    higher number of transmit descriptors may be denied.  In this case,
+    use a lower number.
+
 TxIntDelay
 Valid Range: 0-65535 (0=off)
 Default Value: 64
@@ -203,7 +212,7 @@
     system is reporting dropped transmits, this value may be set too high
     causing the driver to run out of available transmit descriptors.
 
-TxAbsIntDelay (82540, 82545, and 82546-based adapters only)
+TxAbsIntDelay (82540, 82545 and later adapters only)
 Valid Range: 0-65535 (0=off)
 Default Value: 64
     This value, in units of 1.024 microseconds, limits the delay in which a 
@@ -219,7 +228,6 @@
     A value of '1' indicates that the driver should enable IP checksum
     offload for received packets (both UDP and TCP) to the adapter hardware.
 
-
 Speed and Duplex Configuration
 ==============================
 
@@ -251,6 +259,10 @@
 Speed (Mbps)   N/A    N/A    1000    N/A     100    100    10      10
 Duplex                       Full            Full   Half   Full    Half
 
+For example to limit the negotiated speed/duplex on the interface to 10 Mbps 
+Half or Full duplex, set AutoNeg to 0x02: 
+    insmod e1000 AutoNeg=0x02
+
 Note that setting AutoNeg does not guarantee that the board will link at the 
 highest specified speed or duplex mode, but the board will link at the 
 highest possible speed/duplex of the link partner IF the link partner is also
@@ -261,6 +273,38 @@
 Additional Configurations
 =========================
 
+  Configuring the Driver on Different Distributions
+  -------------------------------------------------
+
+  Configuring a network driver to load properly when the system is started is
+  distribution dependent. Typically, the configuration process involves adding
+  an alias line to /etc/modules.conf as well as editing other system startup 
+  scripts and/or configuration files. Many popular Linux distributions ship 
+  with tools to make these changes for you. To learn the proper way to 
+  configure a network device for your system, refer to your distribution 
+  documentation. If during this process you are asked for the driver or module 
+  name, the name for the Linux Base Driver for the Intel PRO/1000 Family of 
+  Adapters is e1000.
+
+  As an example, if you install the e1000 driver for two PRO/1000 adapters 
+  (eth0 and eth1) and set the speed and duplex to 10full and 100half, add the 
+  following to modules.conf:
+
+       alias eth0 e1000
+       alias eth1 e1000
+       options e1000 Speed=10,100 Duplex=2,1
+
+  Viewing Link Messages
+  ---------------------
+
+  Link messages will not be displayed to the console if the distribution is 
+  restricting system messages. In order to see network driver link messages on 
+  your console, set dmesg to eight by entering the following:
+
+       dmesg -n 8
+
+  NOTE: This setting is not saved across reboots.
+
   Jumbo Frames
   ------------
 
@@ -278,6 +322,51 @@
   10 or 100 Mbps may result in poor performance or loss of link.
 
 
+  NOTE: MTU designates the frame size. To enable Jumbo Frames, increase the
+  MTU size on the interface beyond 1500.
+
+  Ethtool
+  -------
+
+  The driver utilizes the ethtool interface for driver configuration and
+  diagnostics, as well as displaying statistical information.  Ethtool
+  version 1.6 or later is required for this functionality.
+
+  The latest release of ethtool can be found from
+  http://sf.net/projects/gkernel.  After ethtool is installed,
+  ethtool-copy.h must be copied and renamed to ethtool.h in your kernel
+  source tree at <linux_kernel_src>/include/linux.  Backup the original
+  ethtool.h as needed before copying.  The driver then must be recompiled
+  in order to take advantage of the latest ethtool features.
+
+  NOTE: Ethtool 1.6 only supports a limited set of ethtool options. Support 
+  for a more complete ethtool feature set can be enabled by upgrading 
+  ethtool to ethtool-1.8.1. 
+
+  Enabling Wake on LAN* (WoL)
+  ---------------------------
+
+  WoL is configured through the Ethtool* utility. Ethtool is included with
+  all versions of Red Hat after Red Hat 7.2. For other Linux distributions, 
+  download and install Ethtool from the following website: 
+  http://sourceforge.net/projects/gkernel.
+
+  For instructions on enabling WoL with Ethtool, refer to the website listed 
+  above.
+
+  WoL will be enabled on the system during the next shut down or reboot. 
+  For this driver version, in order to enable WoL, the e1000 driver must be 
+  loaded when shutting down or rebooting the system.
+
+  NAPI
+  ----
+
+  NAPI (Rx polling mode) is supported in the e1000 driver. NAPI is enabled
+  or disabled based on the configuration of the kernel. 
+
+  See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
+
+
 Known Issues
 ============
 
@@ -285,9 +374,9 @@
   -------------------------------
 
   Memory allocation failures have been observed on Linux systems with 64 MB 
-  of RAM or less that are running Jumbo Frames. If you are using Jumbo 
-  Frames, your system may require more than the advertised minimum 
-  requirement of 64 MB of system memory.
+  of RAM or less that are running Jumbo Frames. If you are using Jumbo Frames,
+  your system may require more than the advertised minimum requirement of 64 MB
+  of system memory.
 
 
 Support
diff -Nru a/Documentation/networking/ixgb.txt b/Documentation/networking/ixgb.txt
--- a/Documentation/networking/ixgb.txt	2004-10-28 22:25:58 -07:00
+++ b/Documentation/networking/ixgb.txt	2004-10-28 22:25:58 -07:00
@@ -1,14 +1,14 @@
 Linux* Base Driver for the Intel(R) PRO/10GbE Family of Adapters
 ================================================================
 
-January 06, 2003
+September 13, 2004
 
 
 Contents
 ========
 
 - In This Release
-- Supported Adapters
+- Identifying Your Adapter
 - Command Line Parameters
 - Improving Performance
 - Support
@@ -18,36 +18,23 @@
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/10GbE Family 
-of Adapters, version 1.0.x. This driver is intended for 2.4.x kernels; it is 
-known to build properly on 2.4.x kernels through 2.4.18. Intel focused 
-testing on Intel architectures running kernels 2.4.18. This driver includes 
-support for Itanium(TM)-based systems.
+of Adapters, version 1.0.x.  This driver includes support for Itanium(TM)2 and
+EM64T systems.
 
 For questions related to hardware requirements, refer to the documentation 
 supplied with your Intel PRO/10GbE adapter. All hardware requirements listed 
 apply to use with Linux.
 
-
-Supported Adapters
-==================
-
-The following Intel network adapters are compatible with the drivers in this 
-release:
-
-   Controller  Adapter Name                           Board IDs
-   ----------  ------------                           ---------
-
-   82597EX     Intel(R) PRO/10GbE LR Server Adapter   A82505-xxx
-
+Identifying Your Adapter
+========================
 
 To verify your Intel 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.
+A12345-001. 
 
-For more information on how to identify your adapter, go to the Adapter & 
-Driver ID Guide at:
+Use the above information and the Adapter & Driver ID Guide at:
 
-    http://support.intel.com/support/network/adapter/pro100/21397.htm
+  http://support.intel.com/support/network/adapter/pro100/21397.htm
 
 For the latest Intel network drivers for Linux, go to:
 
@@ -72,8 +59,9 @@
 resources for the second adapter.
 
 The default value for each parameter is generally the recommended setting,
-unless otherwise noted.
-
+unless otherwise noted. Also, if the driver is statically built into the
+kernel, the driver is loaded with the default values for all the parameters.
+Ethtool can be used to change some of the parameters at runtime.
 
 FlowControl
 Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
@@ -124,7 +112,6 @@
     A value of '1' indicates that the driver should enable IP checksum
     offload for transmitted packets (both UDP and TCP) to the adapter 
     hardware.
-
 
 Improving Performance
 =====================
diff -Nru a/Documentation/networking/proc_net_tcp.txt b/Documentation/networking/proc_net_tcp.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/networking/proc_net_tcp.txt	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,47 @@
+This document describes the interfaces /proc/net/tcp and /proc/net/tcp6.
+
+These /proc interfaces provide information about currently active TCP 
+connections, and are implemented by tcp_get_info() in net/ipv4/tcp_ipv4.c and
+tcp6_get_info() in net/ipv6/tcp_ipv6.c, respectively.
+
+It will first list all listening TCP sockets, and next list all established
+TCP connections. A typical entry of /proc/net/tcp would look like this (split 
+up into 3 parts because of the length of the line):
+
+   46: 010310AC:9C4C 030310AC:1770 01 
+   |      |      |      |      |   |--> connection state
+   |      |      |      |      |------> remote TCP port number
+   |      |      |      |-------------> remote IPv4 address
+   |      |      |--------------------> local TCP port number
+   |      |---------------------------> local IPv4 address
+   |----------------------------------> number of entry
+
+   00000150:00000000 01:00000019 00000000  
+      |        |     |     |       |--> number of unrecovered RTO timeouts
+      |        |     |     |----------> number of jiffies until timer expires
+      |        |     |----------------> timer_active (see below)
+      |        |----------------------> receive-queue
+      |-------------------------------> transmit-queue
+
+   1000        0 54165785 4 cd1e6040 25 4 27 3 -1
+    |          |    |     |    |     |  | |  | |--> slow start size threshold, 
+    |          |    |     |    |     |  | |  |      or -1 if the treshold
+    |          |    |     |    |     |  | |  |      is >= 0xFFFF
+    |          |    |     |    |     |  | |  |----> sending congestion window
+    |          |    |     |    |     |  | |-------> (ack.quick<<1)|ack.pingpong
+    |          |    |     |    |     |  |---------> Predicted tick of soft clock
+    |          |    |     |    |     |              (delayed ACK control data)
+    |          |    |     |    |     |------------> retransmit timeout
+    |          |    |     |    |------------------> location of socket in memory
+    |          |    |     |-----------------------> socket reference count
+    |          |    |-----------------------------> inode
+    |          |----------------------------------> unanswered 0-window probes
+    |---------------------------------------------> uid
+
+timer_active:
+  0  no timer is pending
+  1  retransmit-timer is pending
+  2  another timer (e.g. delayed ack or keepalive) is pending
+  3  this is a socket in TIME_WAIT state. Not all fields will contain 
+     data (or even exist)
+  4  zero window probe timer is pending
diff -Nru a/Documentation/pm.txt b/Documentation/pm.txt
--- a/Documentation/pm.txt	2004-10-28 22:25:57 -07:00
+++ b/Documentation/pm.txt	2004-10-28 22:25:57 -07:00
@@ -36,8 +36,8 @@
   apmd:   http://worldvisions.ca/~apenwarr/apmd/
   acpid:  http://acpid.sf.net/
 
-Driver Interface
-----------------
+Driver Interface -- OBSOLETE, DO NOT USE!
+----------------*************************
 If you are writing a new driver or maintaining an old driver, it
 should include power management support.  Without power management
 support, a single driver may prevent a system with power management
@@ -262,8 +262,8 @@
 
 ACPI Development mailing list: acpi-devel@lists.sourceforge.net
 
-System Interface
-----------------
+System Interface -- OBSOLETE, DO NOT USE!
+----------------*************************
 If you are providing new power management support to Linux (ie.
 adding support for something like APM or ACPI), you should
 communicate with drivers through the existing generic power
diff -Nru a/Documentation/ramdisk.txt b/Documentation/ramdisk.txt
--- a/Documentation/ramdisk.txt	2004-10-28 22:25:56 -07:00
+++ b/Documentation/ramdisk.txt	2004-10-28 22:25:56 -07:00
@@ -5,115 +5,66 @@
 
 	1) Overview
 	2) Kernel Command Line Parameters
-	3) Using "rdev -r" With New Kernels
+	3) Using "rdev -r"
 	4) An Example of Creating a Compressed RAM Disk 
 
 
 1) Overview
 -----------
 
-As of kernel v1.3.48, the RAM disk driver was substantially changed.
-
-The older versions would grab a chunk of memory off the top before
-handing the remainder to the kernel at boot time. Thus a size parameter
-had to be specified via "ramdisk=1440" or "rdev -r /dev/fd0 1440" so
-that the driver knew how much memory to grab.
-
-Now the RAM disk dynamically grows as more space is required. It does
-this by using RAM from the buffer cache. The driver marks the buffers
-it is using with a new "BH_Protected" flag so that the kernel does 
-not try to reuse them later. This means that the old size parameter
-is no longer used, new command line parameters exist, and the behavior
-of the "rdev -r" or "ramsize" (usually a symbolic link to "rdev")
-command has changed.
-
-Also, the new RAM disk supports up to 16 RAM disks out of the box, and can
-be reconfigured in rd.c to support up to 255 RAM disks.  To use multiple
-RAM disk support with your system, run 'mknod /dev/ramX b 1 X' and chmod
-(to change its permissions) it to your liking.  The default /dev/ram(disk)
-uses minor #1, so start with ram2 and go from there.
-
-The old "ramdisk=<ram_size>" has been changed to "ramdisk_size=<ram_size>"
-to make it clearer.  The original "ramdisk=<ram_size>" has been kept around
-for compatibility reasons, but it will probably be removed in 2.1.x.
+The RAM disk driver is a way to use main system memory as a block device.  It
+is required for initrd, an initial filesystem used if you need to load modules
+in order to access the root filesystem (see Documentation/initrd.txt).  It can
+also be used for a temporary filesystem for crypto work, since the contents
+are erased on reboot.
+
+The RAM disk dynamically grows as more space is required. It does this by using
+RAM from the buffer cache. The driver marks the buffers it is using as dirty
+so that the VM subsystem does not try to reclaim them later.
+
+Also, the RAM disk supports up to 16 RAM disks out of the box, and can
+be reconfigured to support up to 255 RAM disks - change "#define NUM_RAMDISKS"
+in drivers/block/rd.c.  To use RAM disk support with your system, run
+'./MAKEDEV ram' from the /dev directory.  RAM disks are all major number 1, and
+start with minor number 0 for /dev/ram0, etc.  If used, modern kernels use
+/dev/ram0 for an initrd.
+
+The old "ramdisk=<ram_size>" has been changed to "ramdisk_size=<ram_size>" to
+make it clearer.  The original "ramdisk=<ram_size>" has been kept around for
+compatibility reasons, but it may be removed in the future.
 
 The new RAM disk also has the ability to load compressed RAM disk images,
 allowing one to squeeze more programs onto an average installation or 
 rescue floppy disk.
 
-Notes: You may have "/dev/ram" or "/dev/ramdisk" or both. They are
-equivalent from the standpoint of this document. Also, the new RAM disk
-is a config option. When running "make config", make sure you enable
-RAM disk support for the kernel with which you intend to use the RAM disk.
-
 
 2) Kernel Command Line Parameters
 ---------------------------------
 
-	ramdisk_start=NNN
-	=================
-
-To allow a kernel image to reside on a floppy disk along with a compressed
-RAM disk image, the "ramdisk_start=<offset>" command was added. The kernel
-can't be included into the compressed RAM disk filesystem image, because
-it needs to be stored starting at block zero so that the BIOS can load the 
-boot sector and then the kernel can bootstrap itself to get going.
-
-Note: If you are using an uncompressed RAM disk image, then the kernel can
-be a part of the filesystem image that is being loaded into the RAM disk,
-and the floppy can be booted with LILO, or the two can be separate as
-is done for the compressed images.
-
-If you are using a two-disk boot/root setup (kernel on #1, RAM disk image
-on #2) then the RAM disk would start at block zero, and an offset of
-zero would be used. Since this is the default value, you would not need
-to actually use the command at all.
-
-If instead, you have a "zImage" of about 350 kB, and a "fs_image.gz" of
-say about 1 MB, and you want them both on the same disk, then you
-would use an offset. If you stored the "fs_image.gz" onto the floppy
-starting at an offset of 400 kB, you would use "ramdisk_start=400".
-
-
-	load_ramdisk=N
-	==============
-
-This parameter tells the kernel whether it is to try to load a
-RAM disk image or not. Specifying "load_ramdisk=1" will tell the
-kernel to load a floppy into the RAM disk. The default value is
-zero, meaning that the kernel should not try to load a RAM disk.
-
-
-	prompt_ramdisk=N
-	================
-
-This parameter tells the kernel whether or not to give you a prompt
-asking you to insert the floppy containing the RAM disk image. In
-a single floppy configuration the RAM disk image is on the same floppy
-as the kernel that just finished loading/booting and so a prompt
-is not needed. In this case one can use "prompt_ramdisk=0". In a
-two floppy configuration, you will need the chance to switch disks,
-and thus "prompt_ramdisk=1" can be used. Since this is the default 
-value, it doesn't really need to be specified.
-
 	ramdisk_size=N
 	==============
 
 This parameter tells the RAM disk driver to set up RAM disks of N k size.  The
-default is 4096 (4 MB). 
+default is 4096 (4 MB) (8192 (8 MB) on S390).
+
+	ramdisk_blocksize=N
+	===================
 
-3) Using "rdev -r" With New Kernels
------------------------------------
+This parameter tells the RAM disk driver how many bytes to use per block.  The
+default is 512.
 
-The usage of the word (two bytes) that "rdev -r" sets in the kernel image
-has changed. The low 11 bits (0 -> 10) specify an offset (in 1 k blocks) 
-of up to 2 MB (2^11) of where to find the RAM disk (this used to be the 
-size). Bit 14 indicates that a RAM disk is to be loaded, and bit 15
-indicates whether a prompt/wait sequence is to be given before trying
-to read the RAM disk. Since the RAM disk dynamically grows as data is
-being written into it, a size field is no longer required. Bits 11
-to 13 are not currently used and may as well be zero. These numbers
-are no magical secrets, as seen below:
+
+3) Using "rdev -r"
+------------------
+
+The usage of the word (two bytes) that "rdev -r" sets in the kernel image is
+as follows. The low 11 bits (0 -> 10) specify an offset (in 1 k blocks) of up
+to 2 MB (2^11) of where to find the RAM disk (this used to be the size). Bit
+14 indicates that a RAM disk is to be loaded, and bit 15 indicates whether a
+prompt/wait sequence is to be given before trying to read the RAM disk. Since
+the RAM disk dynamically grows as data is being written into it, a size field
+is not required. Bits 11 to 13 are not currently used and may as well be zero.
+These numbers are no magical secrets, as seen below:
 
 ./arch/i386/kernel/setup.c:#define RAMDISK_IMAGE_START_MASK     0x07FF
 ./arch/i386/kernel/setup.c:#define RAMDISK_PROMPT_FLAG          0x8000
@@ -152,10 +103,10 @@
 To create a RAM disk image, you will need a spare block device to
 construct it on. This can be the RAM disk device itself, or an
 unused disk partition (such as an unmounted swap partition). For this 
-example, we will use the RAM disk device, "/dev/ram".
+example, we will use the RAM disk device, "/dev/ram0".
 
 Note: This technique should not be done on a machine with less than 8 MB
-of RAM. If using a spare disk partition instead of /dev/ram, then this
+of RAM. If using a spare disk partition instead of /dev/ram0, then this
 restriction does not apply.
 
 a) Decide on the RAM disk size that you want. Say 2 MB for this example.
@@ -164,11 +115,11 @@
    area (esp. for disks) so that maximal compression is achieved for
    the unused blocks of the image that you are about to create.
 
-	dd if=/dev/zero of=/dev/ram bs=1k count=2048
+	dd if=/dev/zero of=/dev/ram0 bs=1k count=2048
 
 b) Make a filesystem on it. Say ext2fs for this example.
 
-	mke2fs -vm0 /dev/ram 2048
+	mke2fs -vm0 /dev/ram0 2048
 
 c) Mount it, copy the files you want to it (eg: /etc/* /dev/* ...)
    and unmount it again.
@@ -177,7 +128,7 @@
    will be approximately 50% of the space used by the files. Unused
    space on the RAM disk will compress to almost nothing.
 
-	dd if=/dev/ram bs=1k count=2048 | gzip -v9 > /tmp/ram_image.gz
+	dd if=/dev/ram0 bs=1k count=2048 | gzip -v9 > /tmp/ram_image.gz
 
 e) Put the kernel onto the floppy
 
@@ -203,4 +154,14 @@
 users may wish to combine steps (d) and (f) by using a pipe.
 
 --------------------------------------------------------------------------
-						Paul Gortmaker 12/95	
+						Paul Gortmaker 12/95
+
+Changelog:
+----------
+
+10-22-04 :	Updated to reflect changes in command line options, remove
+		obsolete references, general cleanup.
+		James Nelson (james4765@gmail.com)
+
+
+12-95 :		Original Document
diff -Nru a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
--- a/Documentation/s390/s390dbf.txt	2004-10-28 22:25:58 -07:00
+++ b/Documentation/s390/s390dbf.txt	2004-10-28 22:25:58 -07:00
@@ -78,6 +78,23 @@
 
 > echo "-" > /proc/s390dbf/dasd/level
 
+It is also possible to deactivate the debug feature globally for every
+debug log. You can change the behavior using  2 sysctl parameters in
+/proc/sys/s390dbf:
+There are currently 2 possible triggers, which stop the  debug feature
+globally. The first possbility is to use the "debug_active" sysctl. If
+set to 1 the debug feature is running. If "debug_active" is set to 0 the
+debug feature is turned off.
+The second trigger which stops the debug feature is an kernel oops.
+That prevents the debug feature from overwriting debug information that
+happened before the oops. After an oops you can reactivate the debug feature
+by piping 1 to /proc/sys/s390dbf/debug_active. Nevertheless, its not
+suggested to use an oopsed kernel in an production environment.
+If you want to disallow the deactivation of the debug feature, you can use
+the "debug_stoppable" sysctl. If you set "debug_stoppable" to 0 the debug
+feature cannot be stopped. If the debug feature is already stopped, it
+will stay deactivated.
+
 Kernel Interfaces:
 ------------------
 
@@ -115,6 +132,17 @@
 Return Value:  none 
 
 Description:   Sets new actual debug level if new_level is valid. 
+
+---------------------------------------------------------------------------
++void debug_stop_all(void);
+
+Parameter:     none
+
+Return Value:  none
+
+Description:   stops the debug feature if stopping is allowed. Currently
+               used in case of a kernel oops.
+
 ---------------------------------------------------------------------------
 debug_entry_t* debug_event (debug_info_t* id, int level, void* data, 
                             int length);
@@ -271,12 +299,12 @@
  * hex_ascii- + raw-view Example
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <asm/debug.h>
 
 static debug_info_t* debug_info;
 
-int init_module(void)
+static int init(void)
 {
     /* register 4 debug areas with one page each and 4 byte data field */
 
@@ -291,23 +319,26 @@
     return 0;
 }
 
-void cleanup_module(void)
+static void cleanup(void)
 {
     debug_unregister (debug_info);
 }
 
+module_init(init);
+module_exit(cleanup);
+
 ---------------------------------------------------------------------------
 
 /*
  * sprintf-view Example
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <asm/debug.h>
 
 static debug_info_t* debug_info;
 
-int init_module(void)
+static int init(void)
 {
     /* register 4 debug areas with one page each and data field for */
     /* format string pointer + 2 varargs (= 3 * sizeof(long))       */
@@ -321,11 +352,14 @@
     return 0;
 }
 
-void cleanup_module(void)
+static void cleanup(void)
 {
     debug_unregister (debug_info);
 }
 
+module_init(init);
+module_exit(cleanup);
+
 
 
 ProcFS Interface
@@ -376,6 +410,15 @@
 
 2. Flush all debug areas:
 > echo "-" > /proc/s390dbf/dasd/flush
+
+Stooping the debug feature
+--------------------------
+Example:
+
+1. Check if stopping is allowed
+> cat /proc/sys/s390dbf/debug_stoppable
+2. Stop debug feature
+> echo 0 > /proc/sys/s390dbf/debug_active
 
 lcrash Interface
 ----------------
diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt
--- a/Documentation/sonypi.txt	2004-10-28 22:25:56 -07:00
+++ b/Documentation/sonypi.txt	2004-10-28 22:25:56 -07:00
@@ -42,13 +42,10 @@
 Driver options:
 ---------------
 
-Several options can be passed to the sonypi driver, either by adding them
-to /etc/modprobe.conf file, when the driver is compiled as a module or by
-adding the following to the kernel command line (in your bootloader):
-
-	sonypi=minor[,verbose[,fnkeyinit[,camera[,compat[,mask[,useinput]]]]]]
-
-where:
+Several options can be passed to the sonypi driver using the standard
+module argument syntax (<param>=<value> when passing the option to the
+module or sonypi.<param>=<value> on the kernel boot line when sonypi is
+statically linked into the kernel). Those options are:
 
 	minor: 		minor number of the misc device /dev/sonypi, 
 			default is -1 (automatic allocation, see /proc/misc
diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
--- a/Documentation/sound/alsa/ALSA-Configuration.txt	2004-10-28 22:25:56 -07:00
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt	2004-10-28 22:25:56 -07:00
@@ -661,8 +661,6 @@
 			* ALi m5455
 
     ac97_clock	  - AC'97 codec clock base (0 = auto-detect)
-    joystick      - Enable joystick (default off)
-    mpu_port      - MPU401 port # (0 = disabled, 0x330,0x300)
     ac97_quirk    - AC'97 workaround for strange hardware (-1 = default)
                     -1 = default, don't override
                      0 = disable
@@ -670,6 +668,7 @@
                      2 = swap headphone and master controls
                      3 = for AD1985, turn on OMS bit and use headphone
                      4 = for ALC65x, turn on the jack sense mode
+                     5 = inverted EAPD implementation
     buggy_irq      - Enable workaround for buggy interrupts on some
                      motherboards (default off)
 
@@ -679,8 +678,9 @@
     if you still encounter too fast playback, specify the clock
     explicitly via the module option "ac97_clock=41194".
 
-    The joystick and MPU-401 are supported only certain hardwares.
-    MPU401 is experimental,  It doesn't work perfectly.
+    Joystick/MIDI ports are not supported by this driver.  If your
+    motherboard has these devices, use the ns558 or snd-mpu401
+    modules, respectively.
 
     The ac97_quirk option is used to enable/override the workaround
     for specific devices.  Some hardware have swapped output pins
@@ -809,6 +809,7 @@
     buffer_top       - specify buffer top address
     use_cache        - 0 or 1 (disabled by default)
     vaio_hack        - alias buffer_top=0x25a800
+    reset_workaround - enable AC97 RESET workaround for some laptops
 
     Module supports autoprobe and multiple chips (max 8).
 
@@ -833,6 +834,11 @@
     other drivers, e.g. snd-cs4232 or snd-opl3sa2.  Some has ISA-PnP
     but some doesn't have ISA PnP.  You'll need to speicfy isapnp=0
     and proper hardware parameters in the case without ISA PnP.
+
+    Note: some laptops need a workaround for AC97 RESET.  For the
+    known hardware like Dell Latitude LS and Sony PCG-F305, this
+    workaround is enabled automatically.  For other laptops with a
+    hard freeze, you can try reset_workaround=1 option.
 
     Note: This driver is really crappy.  It's a porting from the
     OSS driver, which is a result of black-magic reverse engineering.
diff -Nru a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	2004-10-28 22:25:57 -07:00
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	2004-10-28 22:25:57 -07:00
@@ -1479,7 +1479,7 @@
   struct snd_mychip {
           ....
           unsigned long iobase_phys;
-          unsigned long iobase_virt;
+          void __iomem *iobase_virt;
   };
 ]]>
           </programlisting>
@@ -1495,8 +1495,7 @@
           return err;
   }
   chip->iobase_phys = pci_resource_start(pci, 0);
-  chip->iobase_virt = (unsigned long)
-                      ioremap_nocache(chip->iobase_phys,
+  chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
                                       pci_resource_len(pci, 0));
 ]]>
           </programlisting>
@@ -1511,7 +1510,7 @@
   {
           ....
           if (chip->iobase_virt)
-                  iounmap((void *)chip->iobase_virt);
+                  iounmap(chip->iobase_virt);
           ....
           pci_release_regions(chip->pci);
           ....
@@ -4060,8 +4059,8 @@
       <para>
         Also, there is a function to change the sample rate (of a
         certain register such as
-        <constant>AC97_PCM_FRONT_DAC_RATE</constant>) when VRA is
-        supported by the codec:
+        <constant>AC97_PCM_FRONT_DAC_RATE</constant>) when VRA or
+        DRA is supported by the codec:
         <function>snd_ac97_set_rate()</function>. 
 
         <informalexample>
@@ -4341,7 +4340,39 @@
       </para>
 
       <para>
-        If this function returns successfully with 0, then create a
+        When the accessing to the hardware requires special method
+        instead of the standard I/O access, you can create opl3 instance
+        separately with <function>snd_opl3_new()</function>.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  opl3_t *opl3;
+  snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+	Then set <structfield>command</structfield>,
+	<structfield>private_data</structfield> and
+	<structfield>private_free</structfield> for the private
+	access function, the private data and the destructor.
+	The l_port and r_port are not necessarily set.  Only the
+	command must be set properly.  You can retrieve the data
+	from opl3-&gt;private_data field.
+      </para>
+
+      <para>
+	After creating the opl3 instance via <function>snd_opl3_new()</function>,
+	call <function>snd_opl3_init()</function> to initialize the chip to the
+	proper state.  Note that <function>snd_opl3_create()</function> always
+	calls it internally.
+      </para>
+
+      <para>
+        If the opl3 instance is created successfully, then create a
         hwdep device for this opl3. 
 
         <informalexample>
diff -Nru a/Documentation/sound/alsa/Joystick.txt b/Documentation/sound/alsa/Joystick.txt
--- a/Documentation/sound/alsa/Joystick.txt	2004-10-28 22:25:58 -07:00
+++ b/Documentation/sound/alsa/Joystick.txt	2004-10-28 22:25:58 -07:00
@@ -49,17 +49,15 @@
     cs46xx	N/A		N/A
     es1938	N/A		N/A
     es1968	joystick	0 = disable (default), 1 = enable
-    intel8x0(*1)joystick	0 = disable (default), 1 = enable
     sonicvibes	N/A		N/A
     trident	N/A		N/A
-    via82xx(*2)	joystick	0 = disable (default), 1 = enable
+    via82xx(*1)	joystick	0 = disable (default), 1 = enable
     ymfpci	joystick_port	0 = disable (default), 1 = auto-detect,
-                                manual: 0x201, 0x202, 0x204, 0x205(*3)
+                                manual: 0x201, 0x202, 0x204, 0x205(*2)
     ---------------------------------------------------------------------------
 
-    *1)  not all chips support joystick
-    *2)  VIA686A/B only
-    *3)  With YMF744/754 chips, the port address can be chosen arbitrarily
+    *1)  VIA686A/B only
+    *2)  With YMF744/754 chips, the port address can be chosen arbitrarily
 
 The following drivers don't support gameport natively, but there are
 additional modules.  Load the corresponding module to add the gameport
diff -Nru a/Documentation/sound/oss/README.modules b/Documentation/sound/oss/README.modules
--- a/Documentation/sound/oss/README.modules	2004-10-28 22:25:59 -07:00
+++ b/Documentation/sound/oss/README.modules	2004-10-28 22:25:59 -07:00
@@ -59,8 +59,9 @@
 uart401.o # Used by sb, maybe other cards
 
  Whichever card you have, try feeding it the options that would be the
-default if you were making the driver wired, not as modules. You can look
-at the init_module() code for the card to see what args are expected.
+default if you were making the driver wired, not as modules. You can
+look at function referred to by module_init() for the card to see what
+args are expected.
 
  Note that at present there is no way to configure the io, irq and other
 parameters for the modular drivers as one does for the wired drivers.. One
diff -Nru a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
--- a/Documentation/usb/error-codes.txt	2004-10-28 22:25:56 -07:00
+++ b/Documentation/usb/error-codes.txt	2004-10-28 22:25:56 -07:00
@@ -1,11 +1,12 @@
-Revised: 2002-Feb-09.
+Revised: 2004-Oct-21
 
 This is the documentation of (hopefully) all possible error codes (and
 their interpretation) that can be returned from usbcore.
 
 Some of them are returned by the Host Controller Drivers (HCDs), which
 device drivers only see through usbcore.  As a rule, all the HCDs should
-behave the same except for transfer speed dependent behaviors.
+behave the same except for transfer speed dependent behaviors and the
+way certain faults are reported.
 
 
 **************************************************************************
@@ -26,29 +27,35 @@
 		of urb.  (treat as a host controller bug.)
 
 -EINVAL		a) Invalid transfer type specified (or not supported)
-		b) Invalid interrupt interval (0<=n<256)
-		c) more than one interrupt packet requested
+		b) Invalid or unsupported periodic transfer interval
+		c) ISO: attempted to change transfer interval
 		d) ISO: number_of_packets is < 0
+		e) various other cases
 
 -EAGAIN		a) specified ISO start frame too early
 		b) (using ISO-ASAP) too much scheduled for the future
 		   wait some time and try again.
 
--EFBIG		too much ISO frames requested (currently uhci>900)
+-EFBIG		Host controller driver can't schedule that many ISO frames.
 
 -EPIPE		Specified endpoint is stalled.  For non-control endpoints,
 		reset this status with usb_clear_halt().
 
--EMSGSIZE	endpoint message size is zero, do interface/alternate setting
+-EMSGSIZE	(a) endpoint maxpacket size is zero; it is not usable
+		    in the current interface altsetting.
+		(b) ISO packet is biger than endpoint maxpacket
+		(c) requested data transfer size is invalid (negative)
 
--ENOSPC		The host controller's bandwidth is already consumed and
-		this request would push it past its allowed limit.
+-ENOSPC		This request would overcommit the usb bandwidth reserved
+		for periodic transfers (interrupt, isochronous).
 
--ESHUTDOWN	The host controller has been disabled due to some
+-ESHUTDOWN	The device or host controller has been disabled due to some
 		problem that could not be worked around.
 
 -EPERM		Submission failed because urb->reject was set.
 
+-EHOSTUNREACH	URB was rejected because the device is suspended.
+
 
 **************************************************************************
 *                   Error codes returned by in urb->status               *
@@ -71,14 +78,14 @@
 -EINPROGRESS		URB still pending, no results yet
 			(That is, if drivers see this it's a bug.)
 
--EPROTO (*)		a) bitstuff error
+-EPROTO (*, **)		a) bitstuff error
 			b) no response packet received within the
 			   prescribed bus turn-around time
 			c) unknown USB error 
 
--EILSEQ (*)		CRC mismatch
+-EILSEQ (*, **)		CRC mismatch
 
--EPIPE			Endpoint stalled.  For non-control endpoints,
+-EPIPE (**)		Endpoint stalled.  For non-control endpoints,
 			reset this status with usb_clear_halt().
 
 -ECOMM			During an IN transfer, the host controller
@@ -97,7 +104,7 @@
 			specified buffer, and URB_SHORT_NOT_OK was set in
 			urb->transfer_flags.
 
--ETIMEDOUT		transfer timed out, NAK
+-ETIMEDOUT (**)		transfer timed out, NAK
 
 -ENODEV			Device was removed.  Often preceded by a burst of
 			other errors, since the hub driver does't detect
@@ -110,12 +117,18 @@
 
 -ECONNRESET		URB was asynchronously unlinked by usb_unlink_urb
 
--ESHUTDOWN		The host controller has been disabled due to some
-			problem that could not be worked around.
+-ESHUTDOWN		The device or host controller has been disabled due
+			to some problem that could not be worked around,
+			such as a physical disconnect.
 
 
 (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate
 hardware problems such as bad devices (including firmware) or cables.
+
+(**) This is also one of several codes that different kinds of host
+controller use to to indicate a transfer has failed because of device
+disconnect.  In the interval before the hub driver starts disconnect
+processing, devices may receive such fault reports for every request.
 
 
 
diff -Nru a/Documentation/usb/silverlink.txt b/Documentation/usb/silverlink.txt
--- a/Documentation/usb/silverlink.txt	2004-10-28 22:25:57 -07:00
+++ b/Documentation/usb/silverlink.txt	2004-10-28 22:25:57 -07:00
@@ -1,5 +1,6 @@
 -------------------------------------------------------------------------
 Readme for Linux device driver for the Texas Instruments SilverLink cable
+and direct USB cable provided by some TI's handhelds.
 -------------------------------------------------------------------------
 
 Author: Romain Liévin & Julien Blache
@@ -9,7 +10,8 @@
 
 This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable 
 designed by TI for connecting their TI8x/9x calculators to a computer 
-(PC or Mac usually).
+(PC or Mac usually). It has been extended to support the USB port offered by
+some latest TI handhelds (TI84+ and TI89 Titanium).
 
 If you need more information, please visit the 'SilverLink drivers' homepage 
 at the above URL.
@@ -73,4 +75,4 @@
 CREDITS:
 
 The code is based on dabusb.c, printer.c and scanner.c !
-The driver has been developed independently of Texas Instruments.
+The driver has been developed independently of Texas Instruments Inc.
diff -Nru a/Documentation/usb/w9968cf.txt b/Documentation/usb/w9968cf.txt
--- a/Documentation/usb/w9968cf.txt	2004-10-28 22:25:58 -07:00
+++ b/Documentation/usb/w9968cf.txt	2004-10-28 22:25:58 -07:00
@@ -8,26 +8,30 @@
 
 Index
 =====
-1. Copyright
-2. License
-3. Overview
-4. Supported devices
-5. Module dependencies
-6. Module loading
-7. Module paramaters
-8. Contact information
-9. Credits
+1.  Copyright
+2.  Disclaimer
+3.  License
+4.  Overview
+5.  Supported devices
+6.  Module dependencies
+7.  Module loading
+8.  Module paramaters
+9.  Contact information
+10. Credits
 
 
 1. Copyright
 ============
 Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it>
 
+
+2. Disclaimer
+=============
 Winbond is a trademark of Winbond Electronics Corporation.
-This driver is not sponsored or developed by Winbond.
+This software is not sponsored or developed by Winbond.
 
 
-2. License
+3. License
 ==========
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -44,7 +48,7 @@
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 
-3. Overview
+4. Overview
 ===========
 This driver supports the video streaming capabilities of the devices mounting
 Winbond W9967CF and Winbond W9968CF JPEG USB Dual Mode Camera Chips. OV681
@@ -57,7 +61,7 @@
 every time an application tries to open a recognized device, "w9968cf" checks
 the presence of the "w9968cf-vpp" module and loads it automatically by default.
 
-Please keep in mind that official kernels do NOT include the second module for
+Please keep in mind that official kernels do not include the second module for
 performance purposes. However it is always recommended to download and install
 the latest and complete release of the driver, replacing the existing one, if
 present: it will be still even possible not to load the "w9968cf-vpp" module at
@@ -65,7 +69,7 @@
 the official Linux 2.4 kernels is the writeable /proc filesystem interface.
 
 The latest and full-featured version of the W996[87]CF driver can be found at:
-http://go.lamarinapunto.com/ . Please refer to the documentation included in
+http://www.linux-projects.org. Please refer to the documentation included in
 that package, if you are going to use it.
 
 Up to 32 cameras can be handled at the same time. They can be connected and
@@ -83,7 +87,7 @@
 compiled with the automatic module loading option).
 
 
-4. Supported devices
+5. Supported devices
 ====================
 At the moment, known W996[87]CF and OV681 based devices are:
 - Aroma Digi Pen VGA Dual Mode ADG-5000 (unknown image sensor)
@@ -99,11 +103,9 @@
 
 If you know any other W996[87]CF or OV681 based cameras, please contact me.
 
-The list above does NOT imply that all those devices work with this driver: up
+The list above does not imply that all those devices work with this driver: up
 until now only webcams that have an image sensor supported by the "ovcamchip"
-module work. 
-For a list of supported image sensors, please visit the author's homepage on
-this module: http://alpha.dyndns.org/ov511/
+module work. Kernel messages will always tell you whether this is case.
 
 Possible external microcontrollers of those webcams are not supported: this
 means that still images cannot be downloaded from the device memory.
@@ -113,7 +115,7 @@
 additional testing and full support, would be much appreciated.
 
 
-5. Module dependencies
+6. Module dependencies
 ======================
 For it to work properly, the driver needs kernel support for Video4Linux, USB
 and I2C, and the "ovcamchip" module for the image sensor. Make sure you are not
@@ -157,7 +159,7 @@
 	CONFIG_USB_W9968CF=m
 
 
-6. Module loading
+7. Module loading
 =================
 To use the driver, it is necessary to load the "w9968cf" module into memory
 after every other module required.
@@ -166,6 +168,7 @@
 
 	[root@localhost home]# modprobe usbcore
 	[root@localhost home]# modprobe i2c-core
+	[root@localhost home]# modprobe videodev
 	[root@localhost home]# modprobe w9968cf
 
 At this point the pertinent devices should be recognized: "dmesg" can be used
@@ -181,7 +184,7 @@
 	[root@locahost home]# modinfo w9968cf
 
 
-7. Module parameters
+8. Module parameters
 ====================
 Module parameters are listed below:
 -------------------------------------------------------------------------------
@@ -452,7 +455,7 @@
 -------------------------------------------------------------------------------
 
 
-8. Contact information
+9. Contact information
 ======================
 I may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
 
@@ -461,7 +464,7 @@
 is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
 
 
-9. Credits
+10. Credits
 ==========
 The development would not have proceed much further without having looked at
 the source code of other drivers and without the help of several persons; in
diff -Nru a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting
--- a/Documentation/vm/overcommit-accounting	2004-10-28 22:25:59 -07:00
+++ b/Documentation/vm/overcommit-accounting	2004-10-28 22:25:59 -07:00
@@ -22,9 +22,8 @@
 
 The overcommit percentage is set via `vm.overcommit_ratio'.
 
-The current overcommit limit, amount used, and amount remaining below
-the limit are viewable in /proc/meminfo as CommitLimit, Committed_AS, and
-CommitAvail respectively.
+The current overcommit limit and amount committed are viewable in
+/proc/meminfo as CommitLimit and Committed_AS respectively.
 
 Gotchas
 -------
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2004-10-28 22:25:58 -07:00
+++ b/MAINTAINERS	2004-10-28 22:25:58 -07:00
@@ -858,11 +858,9 @@
 S:	Maintained
 
 FTAPE/QIC-117
-P:	Claus-Justus Heine
-M:	claus@momo.math.rwth-aachen.de
 L:	linux-tape@vger.kernel.org
-W:	http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape/
-S:	Maintained
+W:	http://sourceforge.net/projects/ftape
+S:	Orphan
 
 FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
 P:	Rik Faith
@@ -1760,6 +1758,13 @@
 W:	ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
 S:	Supported
 
+PRISM54 WIRELESS DRIVER
+P:	Prism54 Development Team
+M:	prism54-private@prism54.org
+L:	netdev@oss.sgi.com
+W:	http://prism54.org
+S:	Maintained
+
 PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
 P:	Peter Denison
 M:	promise@pnd-pc.demon.co.uk
@@ -2371,7 +2376,7 @@
 P:	Luca Risolia
 M:	luca.risolia@studio.unibo.it
 L:	linux-usb-devel@lists.sourceforge.net
-W:	http://go.lamarinapunto.com
+W:	http://www.linux-projects.org
 S:	Maintained
 
 USB SUBSYSTEM
@@ -2399,7 +2404,7 @@
 P:	Luca Risolia
 M:	luca.risolia@studio.unibo.it
 L:	linux-usb-devel@lists.sourceforge.net
-W:	http://go.lamarinapunto.com
+W:	http://www.linux-projects.org
 S:	Maintained
 
 USER-MODE LINUX
diff -Nru a/Makefile b/Makefile
--- a/Makefile	2004-10-28 22:25:58 -07:00
+++ b/Makefile	2004-10-28 22:25:58 -07:00
@@ -157,7 +157,7 @@
 
 LOCALVERSION = $(subst $(space),, \
 	       $(shell cat /dev/null $(localversion-files)) \
-	       $(subst ",,$(CONFIG_LOCALVERSION)))
+	       $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
 
@@ -295,6 +295,11 @@
 cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
                 > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
 
+# cc-option-align
+# Prefix align with either -falign or -malign
+cc-option-align = $(subst -functions=0,,\
+	$(call cc-option,-falign-functions=0,-malign-functions=0))
+
 # cc-version
 # Usage gcc-ver := $(call cc-version $(CC))
 cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
@@ -379,6 +384,18 @@
 scripts_basic:
 	$(Q)$(MAKE) $(build)=scripts/basic
 
+.PHONY: outputmakefile
+# outputmakefile generate a Makefile to be placed in output directory, if
+# using a seperate output directory. This allows convinient use
+# of make in output directory
+outputmakefile:
+	$(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \
+	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile              \
+	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)         \
+	    > $(objtree)/Makefile;                                 \
+	    echo '  GEN    $(objtree)/Makefile';                   \
+	fi
+
 # To make sure we do not include .config for any of the *config targets
 # catch them early, and hand them over to scripts/kconfig/Makefile
 # It is allowed to specify more targets when calling make, including
@@ -423,9 +440,9 @@
 # *config targets only - make sure prerequisites are updated, and descend
 # in scripts/kconfig to make the *config target
 
-config: scripts_basic FORCE
+config: scripts_basic outputmakefile FORCE
 	$(Q)$(MAKE) $(build)=scripts/kconfig $@
-%config: scripts_basic FORCE
+%config: scripts_basic outputmakefile FORCE
 	$(Q)$(MAKE) $(build)=scripts/kconfig $@
 
 else
@@ -486,7 +503,16 @@
 CFLAGS		+= -O2
 endif
 
-ifndef CONFIG_FRAME_POINTER
+#Add align options if CONFIG_CC_* is not equal to 0
+add-align = $(if $(filter-out 0,$($(1))),$(cc-option-align)$(2)=$($(1)))
+CFLAGS		+= $(call add-align,CONFIG_CC_ALIGN_FUNCTIONS,-functions)
+CFLAGS		+= $(call add-align,CONFIG_CC_ALIGN_LABELS,-labels)
+CFLAGS		+= $(call add-align,CONFIG_CC_ALIGN_LOOPS,-loops)
+CFLAGS		+= $(call add-align,CONFIG_CC_ALIGN_JUMPS,-jumps)
+
+ifdef CONFIG_FRAME_POINTER
+CFLAGS		+= -fno-omit-frame-pointer
+else
 CFLAGS		+= -fomit-frame-pointer
 endif
 
@@ -494,11 +520,11 @@
 CFLAGS		+= -g
 endif
 
+include $(srctree)/arch/$(ARCH)/Makefile
+
 # warn about C99 declaration after statement
 CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 
-include $(srctree)/arch/$(ARCH)/Makefile
-
 # Default kernel image to build when no specific target is given.
 # KBUILD_IMAGE may be overruled on the commandline or
 # set in the environment
@@ -711,22 +737,12 @@
 
 .PHONY: prepare-all prepare prepare0 prepare1 prepare2
 
-# prepare 2 generate Makefile to be placed in output directory, if
-# using a seperate output directory. This allows convinient use
-# of make in output directory
-prepare2:
-	$(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \
-	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile              \
-	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)         \
-	    > $(objtree)/Makefile;                                 \
-	fi
-
-# prepare1 is used to check if we are building in a separate output directory,
+# prepare2 is used to check if we are building in a separate output directory,
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
 # 2) Create the include2 directory, used for the second asm symlink
 
-prepare1: prepare2
+prepare2:
 ifneq ($(KBUILD_SRC),)
 	@echo '  Using $(srctree) as source for kernel'
 	$(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \
@@ -737,6 +753,9 @@
 	$(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
 	$(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm
 endif
+
+# prepare1 creates a makefile if using a separate output directory
+prepare1: prepare2 outputmakefile
 
 prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
 ifneq ($(KBUILD_MODULES),)
diff -Nru a/arch/alpha/boot/bootloader.lds b/arch/alpha/boot/bootloader.lds
--- a/arch/alpha/boot/bootloader.lds	2004-10-28 22:25:59 -07:00
+++ b/arch/alpha/boot/bootloader.lds	2004-10-28 22:25:59 -07:00
@@ -1,5 +1,6 @@
 OUTPUT_FORMAT("elf64-alpha")
 ENTRY(__start)
+printk = srm_printk;
 SECTIONS
 {
   . = 0x20000000;
diff -Nru a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c
--- a/arch/alpha/boot/bootp.c	2004-10-28 22:25:59 -07:00
+++ b/arch/alpha/boot/bootp.c	2004-10-28 22:25:59 -07:00
@@ -26,6 +26,8 @@
 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
 	unsigned long *vptb);
 
+extern void move_stack(unsigned long new_stack);
+
 struct hwrpb_struct *hwrpb = INIT_HWRPB;
 static struct pcb_struct pcb_va[1];
 
@@ -118,12 +120,10 @@
 runkernel(void)
 {
 	__asm__ __volatile__(
-		"bis %1,%1,$30\n\t"
 		"bis %0,%0,$27\n\t"
 		"jmp ($27)"
 		: /* no outputs: it doesn't even return */
-		: "r" (START_ADDR),
-		  "r" (PAGE_SIZE + INIT_STACK));
+		: "r" (START_ADDR));
 }
 
 extern char _end;
@@ -147,9 +147,7 @@
 	 */
 	static long nbytes;
 	static char envval[256] __attribute__((aligned(8)));
-#ifdef INITRD_IMAGE_SIZE
 	static unsigned long initrd_start;
-#endif
 
 	srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
 	if (INIT_HWRPB->pagesize != 8192) {
@@ -164,12 +162,19 @@
 	}
 	pal_init();
 
-#ifdef INITRD_IMAGE_SIZE
 	/* The initrd must be page-aligned.  See below for the 
 	   cause of the magic number 5.  */
-	initrd_start = ((START_ADDR + 5*KERNEL_SIZE) | (PAGE_SIZE-1)) + 1;
+	initrd_start = ((START_ADDR + 5*KERNEL_SIZE + PAGE_SIZE) |
+			(PAGE_SIZE-1)) + 1;
+#ifdef INITRD_IMAGE_SIZE
 	srm_printk("Initrd positioned at %#lx\n", initrd_start);
 #endif
+
+	/*
+	 * Move the stack to a safe place to ensure it won't be
+	 * overwritten by kernel image.
+	 */
+	move_stack(initrd_start - PAGE_SIZE);
 
 	nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
 	if (nbytes < 0 || nbytes >= sizeof(envval)) {
diff -Nru a/arch/alpha/boot/bootpz.c b/arch/alpha/boot/bootpz.c
--- a/arch/alpha/boot/bootpz.c	2004-10-28 22:25:56 -07:00
+++ b/arch/alpha/boot/bootpz.c	2004-10-28 22:25:56 -07:00
@@ -41,9 +41,6 @@
 #undef DEBUG_ADDRESSES
 #undef DEBUG_LAST_STEPS
 
-#define DEBUG_SP(x) \
-    {register long sp asm("30"); srm_printk("%s (sp=%lx)\n", x, sp);}
-
 extern unsigned long switch_to_osf_pal(unsigned long nr,
 	struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
 	unsigned long *vptb);
@@ -51,6 +48,8 @@
 extern int decompress_kernel(void* destination, void *source,
 			     size_t ksize, size_t kzsize);
 
+extern void move_stack(unsigned long new_stack);
+
 struct hwrpb_struct *hwrpb = INIT_HWRPB;
 static struct pcb_struct pcb_va[1];
 
@@ -163,12 +162,10 @@
 runkernel(void)
 {
 	__asm__ __volatile__(
-		"bis %1,%1,$30\n\t"
 		"bis %0,%0,$27\n\t"
 		"jmp ($27)"
 		: /* no outputs: it doesn't even return */
-		: "r" (START_ADDR),
-		  "r" (PAGE_SIZE + INIT_STACK));
+		: "r" (START_ADDR));
 }
 
 /* Must record the SP (it is virtual) on entry, so we can make sure
@@ -253,7 +250,9 @@
    for "bootmem" anyway.
 */
 #define K_COPY_IMAGE_START	NEXT_PAGE(K_KERNEL_IMAGE_END)
-#define K_INITRD_START		NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE)
+/* Reserve one page below INITRD for the new stack. */
+#define K_INITRD_START \
+    NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE)
 #define K_COPY_IMAGE_END \
     (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
 #define K_COPY_IMAGE_SIZE \
@@ -419,8 +418,7 @@
 		   initrd_image_start,
 		   INITRD_IMAGE_SIZE);
 #endif
-	memcpy((void *)initrd_image_start,
-	       (void *)V_INITRD_START,
+	memcpy((void *)initrd_image_start, (void *)V_INITRD_START,
 	       INITRD_IMAGE_SIZE);
 
 #endif /* INITRD_IMAGE_SIZE */
@@ -436,9 +434,14 @@
 			   K_KERNEL_IMAGE_START,
 			   (unsigned)KERNEL_SIZE);
 #endif
+		/*
+		 * Move the stack to a safe place to ensure it won't be
+		 * overwritten by kernel image.
+		 */
+		move_stack(initrd_image_start - PAGE_SIZE);
+
 		memcpy((void *)K_KERNEL_IMAGE_START,
-		       (void *)uncompressed_image_start,
-		       KERNEL_SIZE);
+		       (void *)uncompressed_image_start, KERNEL_SIZE);
 	}
 	
 	/* Clear the zero page, then move the argument list in. */
diff -Nru a/arch/alpha/boot/head.S b/arch/alpha/boot/head.S
--- a/arch/alpha/boot/head.S	2004-10-28 22:25:59 -07:00
+++ b/arch/alpha/boot/head.S	2004-10-28 22:25:59 -07:00
@@ -100,3 +100,24 @@
 	.prologue 0
 	call_pal PAL_halt
 	.end halt
+
+/* $16 - new stack page */
+	.align 3
+	.globl	move_stack
+	.ent	move_stack
+move_stack:
+	.prologue 0
+	lda	$0, 0x1fff($31)
+	and	$0, $30, $1			/* Stack offset */
+	or	$1, $16, $16			/* New stack pointer */
+	mov	$30, $1
+	mov	$16, $2
+1:	ldq	$3, 0($1)			/* Move the stack */
+	addq	$1, 8, $1
+	stq	$3, 0($2)
+	and	$0, $1, $4
+	addq	$2, 8, $2
+	bne	$4, 1b
+	mov	$16, $30
+	ret	($26)
+	.end move_stack
diff -Nru a/arch/alpha/boot/misc.c b/arch/alpha/boot/misc.c
--- a/arch/alpha/boot/misc.c	2004-10-28 22:25:57 -07:00
+++ b/arch/alpha/boot/misc.c	2004-10-28 22:25:57 -07:00
@@ -205,15 +205,3 @@
 /*	puts(" done, booting the kernel.\n"); */
 	return output_ptr;
 }
-
-/* dummy-up printk */
-asmlinkage int printk(const char *fmt, ...)
-{
-        va_list args;
-	long ret;
-
-        va_start(args, fmt);
-        ret = srm_printk(fmt, args);
-        va_end(args);
-	return ret;
-}
diff -Nru a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
--- a/arch/alpha/lib/csum_partial_copy.c	2004-10-28 22:25:58 -07:00
+++ b/arch/alpha/lib/csum_partial_copy.c	2004-10-28 22:25:58 -07:00
@@ -251,7 +251,8 @@
  * look at this too closely, you'll go blind.
  */
 static inline unsigned long
-csum_partial_cfu_unaligned(const unsigned long * src, unsigned long * dst,
+csum_partial_cfu_unaligned(const unsigned long __user * src,
+			   unsigned long * dst,
 			   unsigned long soff, unsigned long doff,
 			   long len, unsigned long checksum,
 			   unsigned long partial_dest,
@@ -383,7 +384,8 @@
 }
 
 unsigned int
-csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
+csum_partial_copy_nocheck(const char __user *src, char *dst, int len,
+			  unsigned int sum)
 {
 	return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
 }
diff -Nru a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
--- a/arch/arm/Kconfig.debug	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/Kconfig.debug	2004-10-28 22:25:59 -07:00
@@ -104,12 +104,15 @@
 	  before it is used.
 
 config DEBUG_S3C2410_UART
-	depends on DEBUG_LL && ARCH_S3C2410
-	int "S3C2410 UART to use for low-level debug"
+	depends on ARCH_S3C2410
+	int "S3C2410 UART to use for low-level messages and debug"
 	default "0"
 	help
 	  Choice for UART for kernel low-level using S3C2410 UARTS,
 	  should be between zero and two. The port must have been
 	  initalised by the boot-loader before use.
+
+	  This will affect the port that the uncompressor code uses
+	  to send debug information to.
 
 endmenu
diff -Nru a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
--- a/arch/arm/boot/compressed/head.S	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/boot/compressed/head.S	2004-10-28 22:25:59 -07:00
@@ -117,6 +117,15 @@
 		.macro	writeb, rb
 		str	\rb, [r3, #0]
 		.endm
+#elif defined(CONFIG_ARCH_S3C2410)
+#include <config/debug/s3c2410/port.h>
+			.macro loadsp, rb
+		mov	\rb, #0x50000000
+		add	\rb, \rb, #0x4000 * CONFIG_DEBUG_S3C2410_UART
+		.endm
+		.macro	writeb, rb
+		strb	\rb, [r3, #0x20]
+		.endm
 #else
 #error no serial architecture defined
 #endif
diff -Nru a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig
--- a/arch/arm/configs/bast_defconfig	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/configs/bast_defconfig	2004-10-28 22:25:57 -07:00
@@ -1,31 +1,35 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-rc1-bk2
+# Wed Oct 27 11:31:14 2004
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 # CONFIG_CLEAN_COMPILE is not set
-CONFIG_STANDALONE=y
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=17
+CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
@@ -33,11 +37,9 @@
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -46,6 +48,7 @@
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
@@ -60,6 +63,7 @@
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -69,14 +73,29 @@
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
 
 #
-# S3C2410 Implementations
+# S3C24XX Implementations
 #
 CONFIG_ARCH_BAST=y
-# CONFIG_ARCH_H1940 is not set
-# CONFIG_ARCH_SMDK2410 is not set
+CONFIG_ARCH_H1940=y
+CONFIG_ARCH_SMDK2410=y
 CONFIG_MACH_VR1000=y
+CONFIG_CPU_S3C2410=y
+
+#
+# S3C2410 Setup
+#
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+# CONFIG_S3C2410_PM_DEBUG is not set
+# CONFIG_S3C2410_PM_CHECK is not set
+
+#
+# h720x Implementations
+#
 
 #
 # Processor Type
@@ -108,9 +127,8 @@
 # At least one math emulation must be selected
 #
 CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_NWFPE_XP is not set
 # CONFIG_FPE_FASTFPE is not set
-# CONFIG_VFP is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_AOUT=y
 # CONFIG_BINFMT_MISC is not set
@@ -118,13 +136,13 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
-# CONFIG_PM is not set
+CONFIG_PM=y
 # CONFIG_PREEMPT is not set
+CONFIG_APM=y
 # CONFIG_ARTHUR is not set
-CONFIG_S3C2410_DMA=y
-# CONFIG_S3C2410_DMA_DEBUG is not set
 CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
 CONFIG_ALIGNMENT_TRAP=y
 
@@ -164,9 +182,20 @@
 # CONFIG_MTD_JEDECPROBE is not set
 CONFIG_MTD_GEN_PROBE=y
 # CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
@@ -179,11 +208,13 @@
 # CONFIG_MTD_PHYSMAP is not set
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_BAST is not set
 
 #
 # Self-contained MTD device drivers
 #
 # CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLKMTD is not set
 
@@ -214,6 +245,16 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 
 #
 # Multi-device support (RAID and LVM)
@@ -246,6 +287,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -338,13 +380,13 @@
 CONFIG_BLK_DEV_IDETAPE=m
 CONFIG_BLK_DEV_IDEFLOPPY=m
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
 # CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDE_BAST=y
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -395,16 +437,16 @@
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_SUNKBD is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
@@ -431,8 +473,6 @@
 # CONFIG_DIGI is not set
 # CONFIG_MOXA_INTELLIO is not set
 # CONFIG_MOXA_SMARTIO is not set
-# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_RISCOM8 is not set
@@ -459,7 +499,7 @@
 #
 CONFIG_SERIAL_S3C2410=y
 CONFIG_SERIAL_S3C2410_CONSOLE=y
-# CONFIG_SERIAL_BAST_SIO is not set
+CONFIG_SERIAL_BAST_SIO=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
@@ -469,7 +509,6 @@
 # CONFIG_LP_CONSOLE is not set
 CONFIG_PPDEV=y
 # CONFIG_TIPAR is not set
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -492,12 +531,9 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
-
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -512,35 +548,41 @@
 #
 CONFIG_I2C_ALGOBIT=m
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
 #
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_ISA is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_S3C2410=y
 # CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Hardware Sensors Chip support
 #
 CONFIG_I2C_SENSOR=m
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
 CONFIG_SENSORS_LM75=m
+# CONFIG_SENSORS_LM77 is not set
 CONFIG_SENSORS_LM78=m
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 CONFIG_SENSORS_LM85=m
+# CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
@@ -628,9 +670,14 @@
 # CONFIG_EFS_FS is not set
 CONFIG_JFFS_FS=y
 CONFIG_JFFS_FS_VERBOSE=0
+# CONFIG_JFFS_PROC_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 # CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -651,6 +698,7 @@
 # CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -661,13 +709,7 @@
 # Partition Types
 #
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_ACORN_PARTITION=y
-CONFIG_ACORN_PARTITION_CUMANA=y
-CONFIG_ACORN_PARTITION_EESOX=y
-CONFIG_ACORN_PARTITION_ICS=y
-CONFIG_ACORN_PARTITION_ADFS=y
-CONFIG_ACORN_PARTITION_POWERTEC=y
-CONFIG_ACORN_PARTITION_RISCIX=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
@@ -736,13 +778,14 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE is not set
 
@@ -763,6 +806,9 @@
 #
 # USB support
 #
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
 # USB Gadget Support
@@ -770,17 +816,24 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
 # Kernel hacking
 #
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
@@ -790,6 +843,7 @@
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
diff -Nru a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
--- a/arch/arm/configs/s3c2410_defconfig	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/configs/s3c2410_defconfig	2004-10-28 22:25:57 -07:00
@@ -1,10 +1,13 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.10-rc1-bk2
+# Wed Oct 27 11:30:39 2004
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
@@ -17,6 +20,7 @@
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -25,6 +29,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
@@ -32,11 +37,9 @@
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -45,6 +48,7 @@
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
@@ -59,6 +63,7 @@
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
@@ -68,20 +73,29 @@
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
 
 #
-# S3C2410 Implementations
+# S3C24XX Implementations
 #
 CONFIG_ARCH_BAST=y
 CONFIG_ARCH_H1940=y
 CONFIG_ARCH_SMDK2410=y
 CONFIG_MACH_VR1000=y
+CONFIG_CPU_S3C2410=y
 
 #
 # S3C2410 Setup
 #
 CONFIG_S3C2410_DMA=y
 # CONFIG_S3C2410_DMA_DEBUG is not set
+# CONFIG_S3C2410_PM_DEBUG is not set
+# CONFIG_S3C2410_PM_CHECK is not set
+
+#
+# h720x Implementations
+#
 
 #
 # Processor Type
@@ -113,9 +127,8 @@
 # At least one math emulation must be selected
 #
 CONFIG_FPE_NWFPE=y
-CONFIG_FPE_NWFPE_XP=y
+# CONFIG_FPE_NWFPE_XP is not set
 # CONFIG_FPE_FASTFPE is not set
-# CONFIG_VFP is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_AOUT=y
 # CONFIG_BINFMT_MISC is not set
@@ -126,8 +139,9 @@
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
-# CONFIG_PM is not set
+CONFIG_PM=y
 # CONFIG_PREEMPT is not set
+CONFIG_APM=y
 # CONFIG_ARTHUR is not set
 CONFIG_CMDLINE="root=/dev/hda1 ro init=/bin/bash console=ttySAC0"
 CONFIG_ALIGNMENT_TRAP=y
@@ -194,6 +208,7 @@
 # CONFIG_MTD_PHYSMAP is not set
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_BAST is not set
 
 #
 # Self-contained MTD device drivers
@@ -230,6 +245,16 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 
 #
 # Multi-device support (RAID and LVM)
@@ -262,6 +287,7 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -354,13 +380,13 @@
 CONFIG_BLK_DEV_IDETAPE=m
 CONFIG_BLK_DEV_IDEFLOPPY=m
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
 # CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDE_BAST is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -411,10 +437,10 @@
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -483,7 +509,6 @@
 # CONFIG_LP_CONSOLE is not set
 CONFIG_PPDEV=y
 # CONFIG_TIPAR is not set
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -509,7 +534,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -524,16 +548,18 @@
 #
 CONFIG_I2C_ALGOBIT=m
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
 #
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
 # CONFIG_I2C_ISA is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
+CONFIG_I2C_S3C2410=y
 # CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Hardware Sensors Chip support
@@ -553,8 +579,10 @@
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 CONFIG_SENSORS_LM85=m
+# CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
@@ -670,6 +698,7 @@
 # CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -749,13 +778,14 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE is not set
 
@@ -776,6 +806,9 @@
 #
 # USB support
 #
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
 # USB Gadget Support
@@ -783,17 +816,24 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
 # Kernel hacking
 #
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
 # CONFIG_DEBUG_ERRORS is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
@@ -803,6 +843,7 @@
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
diff -Nru a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
--- a/arch/arm/kernel/debug.S	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/kernel/debug.S	2004-10-28 22:25:57 -07:00
@@ -538,6 +538,9 @@
 #elif defined(CONFIG_ARCH_S3C2410)
 #include <asm/arch/map.h>
 #include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#define S3C2410_UART1_OFF (0x4000)
+#define SHIFT_2440TXF (14-9)
 
 		.macro addruart, rx
 		mrc	p15, 0, \rx, c1, c0
@@ -559,7 +562,17 @@
 		beq	1001f				@
 		@ FIFO enabled...
 1003:
+		mrc	p15, 0, \rd, c1, c0
+		tst	\rd, #1
+		addeq	\rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
+		addne	\rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+		bic	\rd, \rd, #0xff000
+		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
+		and	\rd, \rd, #0x00ff0000
+		teq	\rd, #0x00440000		@ is it 2440?
+
 		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
+		moveq	\rd, \rd, lsr #SHIFT_2440TXF
 		tst	\rd, #S3C2410_UFSTAT_TXFULL
 		bne	1003b
 		b	1002f
@@ -580,8 +593,19 @@
 		beq	1001f				@
 		@ FIFO enabled...
 1003:
+		mrc	p15, 0, \rd, c1, c0
+		tst	\rd, #1
+		addeq	\rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
+		addne	\rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+		bic	\rd, \rd, #0xff000
+		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
+		and	\rd, \rd, #0x00ff0000
+		teq	\rd, #0x00440000		@ is it 2440?
+
 		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
-		ands	\rd, \rd, #15<<S3C2410_UFSTAT_TXSHIFT
+		andne	\rd, \rd, #S3C2410_UFSTAT_TXMASK
+		andeq	\rd, \rd, #S3C2440_UFSTAT_TXMASK
+		teq	\rd, #0
 		bne	1003b
 		b	1002f
 
diff -Nru a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
--- a/arch/arm/lib/Makefile	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/lib/Makefile	2004-10-28 22:25:58 -07:00
@@ -12,12 +12,12 @@
 		   testclearbit.o testsetbit.o uaccess.o getuser.o    \
 		   putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o   \
 		   ucmpdi2.o udivdi3.o lib1funcs.o div64.o	      \
-		   io-readsb.o io-writesb.o io-writesl.o
+		   io-readsb.o io-writesb.o io-readsl.o io-writesl.o
 
 ifeq ($(CONFIG_CPU_32v3),y)
-  lib-y	+= io-readsw-armv3.o io-writesw-armv3.o io-readsl-armv3.o
+  lib-y	+= io-readsw-armv3.o io-writesw-armv3.o
 else
-  lib-y	+= io-readsw-armv4.o io-writesw-armv4.o io-readsl-armv4.o
+  lib-y	+= io-readsw-armv4.o io-writesw-armv4.o
 endif
 
 lib-$(CONFIG_ARCH_RPC)		+= ecard.o io-acorn.o floppydma.o
diff -Nru a/arch/arm/lib/io-readsl-armv3.S b/arch/arm/lib/io-readsl-armv3.S
--- a/arch/arm/lib/io-readsl-armv3.S	2004-10-28 22:25:59 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,78 +0,0 @@
-/*
- *  linux/arch/arm/lib/io-readsl-armv3.S
- *
- *  Copyright (C) 1995-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/hardware.h>
-
-/*
- * Note that some reads can be aligned on half-word boundaries.
- */
-ENTRY(__raw_readsl)
-		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
-		ands	ip, r1, #3
-		bne	2f
-
-1:		ldr	r3, [r0]
-		str	r3, [r1], #4
-		subs	r2, r2, #1
-		bne	1b
-		mov	pc, lr
-
-2:		cmp	ip, #2
-		ldr	ip, [r0]
-		blt	4f
-		bgt	6f
-
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-3:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #16
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #16
-		bne	3b
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1
-		mov	pc, lr
-
-4:		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-5:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #8
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #24
-		bne	5b
-		strb	ip, [r1], #1
-		mov	pc, lr
-
-6:		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-7:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #24
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #8
-		bne	7b
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1
-		mov	pc, lr
-
diff -Nru a/arch/arm/lib/io-readsl-armv4.S b/arch/arm/lib/io-readsl-armv4.S
--- a/arch/arm/lib/io-readsl-armv4.S	2004-10-28 22:25:59 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,132 +0,0 @@
-/*
- *  linux/arch/arm/lib/io-readsl-armv4.S
- *
- *  Copyright (C) 1995-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-/*
- * Note that some reads can be aligned on half-word boundaries.
- */
-ENTRY(__raw_readsl)
-		teq	r2, #0		@ do we have to check for the zero len?
-		moveq	pc, lr
-		ands	ip, r1, #3
-		bne	2f
-
-		subs	r2, r2, #4
-		bmi	1001f
-		stmfd	sp!, {r4, lr}
-1000:		ldr	r3, [r0, #0]
-		ldr	r4, [r0, #0]
-		ldr	ip, [r0, #0]
-		ldr	lr, [r0, #0]
-		subs	r2, r2, #4
-		stmia	r1!, {r3, r4, ip, lr}
-		bpl	1000b
-		ldmfd	sp!, {r4, lr}
-1001:		tst	r2, #2
-		ldrne	r3, [r0, #0]
-		ldrne	ip, [r0, #0]
-		stmneia	r1!, {r3, ip}
-		tst	r2, #1
-		ldrne	r3, [r0, #0]
-		strne	r3, [r1, #0]
-		mov	pc, lr
-
-2:		cmp	ip, #2
-		ldr	ip, [r0]
-		blt	4f
-		bgt	6f
-
-#ifndef	__ARMEB__
-
-		/* little endian code */
-
-		strh	ip, [r1], #2
-		mov	ip, ip, lsr #16
-3:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #16
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #16
-		bne	3b
-		strh	ip, [r1], #2
-		mov	pc, lr
-
-4:		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strh	ip, [r1], #2
-		mov	ip, ip, lsr #16
-5:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #8
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #24
-		bne	5b
-		strb	ip, [r1], #1
-		mov	pc, lr
-
-6:		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-7:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #24
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #8
-		bne	7b
-		strh	ip, [r1], #2
-		mov	ip, ip, lsr #16
-		strb	ip, [r1]
-		mov	pc, lr
-
-#else
-
-		/* big endian code */
-
-
-		mov	r3, ip, lsr #16
-		strh	r3, [r1], #2
-3:		mov	r3, ip, lsl #16
-		subs	r2, r2, #1
-		ldrne	ip, [r0]
-		orrne	r3, r3, ip, lsr #16
-		strne	r3, [r1], #4
-		bne	3b
- 		strh	ip, [r1], #2
- 		mov	pc, lr
-
-4:		mov	r3, ip, lsr #24
-		strb	r3, [r1], #1
-		mov	r3, ip, lsr #8
-		strh	r3, [r1], #2
-5:		mov	r3, ip, lsl #24
-		subs	r2, r2, #1
-		ldrne	ip, [r0]
-		orrne	r3, r3, ip, lsr #8
-		strne	r3, [r1], #4
-		bne	5b
-		strb	ip, [r1], #1
-		mov	pc, lr
-
-6:		mov	r3, ip, lsr #24
-		strb	r3, [r1], #1
-7:		mov	r3, ip, lsl #8
-		subs	r2, r2, #1
-		ldrne	ip, [r0]
-		orrne	r3, r3, ip, lsr #24
-		strne	r3, [r1], #4
-		bne	7b
-		mov	r3, ip, lsr #8
-		strh	r3, [r1], #2
-		strb	ip, [r1], #1
-		mov	pc, lr
-
-#endif
-
-
diff -Nru a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/lib/io-readsl.S	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,79 @@
+/*
+ *  linux/arch/arm/lib/io-readsl.S
+ *
+ *  Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(__raw_readsl)
+		teq	r2, #0		@ do we have to check for the zero len?
+		moveq	pc, lr
+		ands	ip, r1, #3
+		bne	3f
+
+		subs	r2, r2, #4
+		bmi	2f
+		stmfd	sp!, {r4, lr}
+1:		ldr	r3, [r0, #0]
+		ldr	r4, [r0, #0]
+		ldr	ip, [r0, #0]
+		ldr	lr, [r0, #0]
+		subs	r2, r2, #4
+		stmia	r1!, {r3, r4, ip, lr}
+		bpl	1b
+		ldmfd	sp!, {r4, lr}
+2:		tst	r2, #2
+		ldrne	r3, [r0, #0]
+		ldrne	ip, [r0, #0]
+		stmneia	r1!, {r3, ip}
+		tst	r2, #1
+		ldrne	r3, [r0, #0]
+		strne	r3, [r1, #0]
+		mov	pc, lr
+
+3:		ldr	r3, [r0]
+		cmp	ip, #2
+		mov	ip, r3, get_byte_0
+		strb	ip, [r1], #1
+		bgt	6f
+		mov	ip, r3, get_byte_1
+		strb	ip, [r1], #1
+		beq	5f
+		mov	ip, r3, get_byte_2
+		strb	ip, [r1], #1
+
+4:		subs	r2, r2, #1
+		mov	ip, r3, pull #24
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, push #8
+		strne	ip, [r1], #4
+		bne	4b
+		b	8f
+
+5:		subs	r2, r2, #1
+		mov	ip, r3, pull #16
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, push #16
+		strne	ip, [r1], #4
+		bne	5b
+		b	7f
+
+6:		subs	r2, r2, #1
+		mov	ip, r3, pull #8
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, push #24
+		strne	ip, [r1], #4
+		bne	6b
+
+		mov	r3, ip, get_byte_2
+		strb	r3, [r1, #2]
+7:		mov	r3, ip, get_byte_1
+		strb	r3, [r1, #1]
+8:		mov	r3, ip, get_byte_0
+		strb	r3, [r1, #0]
+		mov	pc, lr
diff -Nru a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S
--- a/arch/arm/lib/io-writesl.S	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/lib/io-writesl.S	2004-10-28 22:25:59 -07:00
@@ -9,53 +9,59 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
-#include <asm/hardware.h>
 
 ENTRY(__raw_writesl)
 		teq	r2, #0		@ do we have to check for the zero len?
 		moveq	pc, lr
 		ands	ip, r1, #3
-		bne	2f
+		bne	3f
 
+		subs	r2, r2, #4
+		bmi	2f
+		stmfd	sp!, {r4, lr}
+1:		ldmia	r1!, {r3, r4, ip, lr}
+		subs	r2, r2, #4
+		str	r3, [r0, #0]
+		str	r4, [r0, #0]
+		str	ip, [r0, #0]
+		str	lr, [r0, #0]
+		bpl	1b
+		ldmfd	sp!, {r4, lr}
+2:		tst	r2, #2
+		ldmneia	r1!, {r3, ip}
+		strne	r3, [r0, #0]
+		strne	ip, [r0, #0]
 		tst	r2, #1
-		ldrne	r3, [r1], #4
+		ldrne	r3, [r1, #0]
 		strne	r3, [r0, #0]
-1:		subs	r2, r2, #2
-		ldrcs	r3, [r1], #4
-		ldrcs	ip, [r1], #4
-		strcs	r3, [r0, #0]
-		strcs	ip, [r0, #0]
-		bcs	1b
 		mov	pc, lr
 
-2:		bic	r1, r1, #3
-		cmp	ip, #2
+3:		bic	r1, r1, #3
 		ldr	r3, [r1], #4
-		bgt	4f
+		cmp	ip, #2
 		blt	5f
+		bgt	6f
 
-3:		mov	ip, r3, lsr #16
+4:		mov	ip, r3, pull #16
 		ldr	r3, [r1], #4
 		subs	r2, r2, #1
-		orr	ip, ip, r3, lsl #16
-		str	ip, [r0, #0]
-		bne	3b
+		orr	ip, ip, r3, push #16
+		str	ip, [r0]
+		bne	4b
 		mov	pc, lr
 
-4:		mov	ip, r3, lsr #24
+5:		mov	ip, r3, pull #8
 		ldr	r3, [r1], #4
 		subs	r2, r2, #1
-		orr	ip, ip, r3, lsl #8
-		str	ip, [r0, #0]
-		bne	4b
+		orr	ip, ip, r3, push #24
+		str	ip, [r0]
+		bne	5b
 		mov	pc, lr
 
-5:		mov	ip, r3, lsr #8
+6:		mov	ip, r3, pull #24
 		ldr	r3, [r1], #4
 		subs	r2, r2, #1
-		orr	ip, ip, r3, lsl #24
-		str	ip, [r0, #0]
-		bne	5b
+		orr	ip, ip, r3, push #8
+		str	ip, [r0]
+		bne	6b
 		mov	pc, lr
-
-
diff -Nru a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
--- a/arch/arm/mach-omap/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-omap/Kconfig	2004-10-28 22:25:57 -07:00
@@ -1,62 +1,59 @@
-if ARCH_OMAP
 
 menu "TI OMAP Implementations"
 
 comment "OMAP Core Type"
 
 config ARCH_OMAP730
+	depends on ARCH_OMAP
 	bool "OMAP730 Based System"
-	select CPU_ARM926T
+	select ARCH_OMAP_OTG
 
 config ARCH_OMAP1510
+	depends on ARCH_OMAP
 	default y
 	bool "OMAP1510 Based System"
-	select CPU_ARM925T
-	select CPU_DCACHE_WRITETHROUGH
 
-config ARCH_OMAP1610
-	bool "OMAP1610 Based System"
-	select CPU_ARM926T
-
-config ARCH_OMAP5912
-	bool "OMAP5912 Based System"
-	select CPU_ARM926T
+config ARCH_OMAP16XX
+	depends on ARCH_OMAP
+	bool "OMAP16XX Based System"
+	select ARCH_OMAP_OTG
+
+config ARCH_OMAP_OTG
+	bool
 
 comment "OMAP Board Type"
 
 config MACH_OMAP_INNOVATOR
 	bool "TI Innovator"
-	default y
-	depends on ARCH_OMAP1510 || ARCH_OMAP1610
+	depends on ARCH_OMAP1510 || ARCH_OMAP16XX
 	help
           TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
           have such a board.
 
 config MACH_OMAP_H2
 	bool "TI H2 Support"
-	depends on ARCH_OMAP1610
-        select MACH_OMAP_INNOVATOR
+	depends on ARCH_OMAP16XX
     	help
-	  TI OMAP 1610 H2 board support. Say Y here if you have such
+	  TI OMAP 1610/1611B H2 board support. Say Y here if you have such
 	  a board.
 
 config MACH_OMAP_H3
 	bool "TI H3 Support"
-	depends on ARCH_OMAP1610
+	depends on ARCH_OMAP16XX
     	help
-	  TI OMAP 1610 H3 board support. Say Y here if you have such
+	  TI OMAP 1710 H3 board support. Say Y here if you have such
 	  a board.
 
 config MACH_OMAP_H4
 	bool "TI H4 Support"
-	depends on ARCH_OMAP1610
+	depends on ARCH_OMAP16XX
     	help
 	  TI OMAP 1610 H4 board support. Say Y here if you have such
 	  a board.
 
 config MACH_OMAP_OSK
 	bool "TI OSK Support"
-	depends on ARCH_OMAP5912
+	depends on ARCH_OMAP16XX
     	help
 	  TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
           if you have such a board.
@@ -64,19 +61,16 @@
 config MACH_OMAP_PERSEUS2
 	bool "TI Perseus2"
 	depends on ARCH_OMAP730
-	select LEDS
-	select LEDS_TIMER
-	select LEDS_CPU
     	help
 	  Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
 	  a board.
 
 config MACH_OMAP_GENERIC
 	bool "Generic OMAP board"
-	depends on ARCH_OMAP1510 || ARCH_OMAP1610
+	depends on ARCH_OMAP1510 || ARCH_OMAP16XX
 	help
-          Support for generic OMAP-1510 or 1610 board with no
-          FPGA. Can be used as template for porting Linux to
+          Support for generic OMAP-1510, 1610 or 1710 board with
+          no FPGA. Can be used as template for porting Linux to
           custom OMAP boards. Say Y here if you have a custom
           board.
 
@@ -84,6 +78,7 @@
 
 #config OMAP_BOOT_TAG
 #	bool "OMAP bootloader information passing"
+#        depends on ARCH_OMAP
 #        default n
 #        help
 #          Say Y, if you have a bootloader which passes information
@@ -91,6 +86,7 @@
 
 config OMAP_MUX
 	bool "OMAP multiplexing support"
+        depends on ARCH_OMAP
 	default y
         help
           Pin multiplexing support for OMAP boards. If your bootloader
@@ -106,8 +102,18 @@
           This is useful if you want to find out the correct values of the
           multiplexing registers.
 
+config OMAP_MUX_WARNINGS
+	bool "Warn about pins the bootloader didn't set up"
+        depends on OMAP_MUX
+        default y
+        help
+	  Choose Y here to warn whenever driver initialization logic needs
+	  to change the pin multiplexing setup.  When there are no warnings
+	  printed, it's safe to deselect OMAP_MUX for your product.
+
 choice
 	prompt "Low-level debug console UART"
+	depends on ARCH_OMAP
 	default OMAP_LL_DEBUG_UART1
 
 config OMAP_LL_DEBUG_UART1
@@ -129,7 +135,7 @@
 
 config OMAP_ARM_192MHZ
 	bool "OMAP ARM 192 MHz CPU"
-	depends on ARCH_OMAP1610 || ARCH_OMAP5912
+	depends on ARCH_OMAP16XX
 	help
           Enable 192MHz clock for OMAP CPU. If unsure, say N.
 
@@ -141,29 +147,27 @@
 
 config OMAP_ARM_168MHZ
 	bool "OMAP ARM 168 MHz CPU"
-	depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730 || ARCH_OMAP5912
+	depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
 	help
           Enable 168MHz clock for OMAP CPU. If unsure, say N.
 
 config OMAP_ARM_120MHZ
 	bool "OMAP ARM 120 MHz CPU"
-	depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730
+	depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
 	help
           Enable 120MHz clock for OMAP CPU. If unsure, say N.
 
 config OMAP_ARM_60MHZ
 	bool "OMAP ARM 60 MHz CPU"
-	depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730
+	depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
         default y
 	help
           Enable 60MHz clock for OMAP CPU. If unsure, say Y.
 
 config OMAP_ARM_30MHZ
 	bool "OMAP ARM 30 MHz CPU"
-	depends on ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_OMAP730
+	depends on ARCH_OMAP1510 || ARCH_OMAP16XX || ARCH_OMAP730
 	help
           Enable 30MHz clock for OMAP CPU. If unsure, say N.
 
 endmenu
-
-endif
diff -Nru a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
--- a/arch/arm/mach-omap/Makefile	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-omap/Makefile	2004-10-28 22:25:57 -07:00
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := common.o time.o irq.o dma.o clocks.o mux.o gpio.o mcbsp.o
+obj-y := common.o time.o irq.o dma.o clock.o mux.o gpio.o mcbsp.o usb.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -18,9 +18,7 @@
 obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
 
 # OCPI interconnect support for 1710, 1610 and 5912
-obj-$(CONFIG_ARCH_OMAP1710) += ocpi.o
-obj-$(CONFIG_ARCH_OMAP1610) += ocpi.o
-obj-$(CONFIG_ARCH_OMAP5912) += ocpi.o
+obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o
 
 # LEDs support
 led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
diff -Nru a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c
--- a/arch/arm/mach-omap/board-generic.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-omap/board-generic.c	2004-10-28 22:25:58 -07:00
@@ -22,42 +22,21 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/usb.h>
 #include <asm/arch/board.h>
+#include <asm/arch/serial.h>
 
 #include "common.h"
 
+static int __initdata generic_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+
 static void __init omap_generic_init_irq(void)
 {
 	omap_init_irq();
 }
 
-/*
- * Muxes the serial ports on
- */
-#ifdef CONFIG_ARCH_OMAP1510
-static void __init omap_early_serial_init(void)
-{
-#ifdef CONFIG_OMAP_LL_DEBUG_UART1
-	omap_cfg_reg(UART1_TX);
-	omap_cfg_reg(UART1_RTS);
-#endif
-
-#ifdef CONFIG_OMAP_LL_DEBUG_UART2
-	omap_cfg_reg(UART2_TX);
-	omap_cfg_reg(UART2_RTS);
-#endif
-
-#ifdef CONFIG_OMAP_LL_DEBUG_UART1
-	omap_cfg_reg(UART3_TX);
-	omap_cfg_reg(UART3_RX);
-#endif
-}
-#endif
-
 /* assume no Mini-AB port */
 
 #ifdef CONFIG_ARCH_OMAP1510
@@ -69,7 +48,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1610
+#if defined(CONFIG_ARCH_OMAP16XX)
 static struct omap_usb_config generic1610_usb_config __initdata = {
 	.register_host	= 1,
 	.register_dev	= 1,
@@ -91,17 +70,17 @@
 	 */
 #ifdef CONFIG_ARCH_OMAP1510
 	if (cpu_is_omap1510()) {
-		omap_early_serial_init();
 		generic_config[0].data = &generic1510_usb_config;
 	}
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
+#if defined(CONFIG_ARCH_OMAP16XX)
 	if (!cpu_is_omap1510()) {
 		generic_config[0].data = &generic1610_usb_config;
 	}
 #endif
 	omap_board_config = generic_config;
 	omap_board_config_size = ARRAY_SIZE(generic_config);
+	omap_serial_init(generic_serial_ports);
 }
 
 static void __init omap_generic_map_io(void)
diff -Nru a/arch/arm/mach-omap/board-h2.c b/arch/arm/mach-omap/board-h2.c
--- a/arch/arm/mach-omap/board-h2.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-omap/board-h2.c	2004-10-28 22:25:59 -07:00
@@ -32,14 +32,11 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/serial.h>
 
 #include "common.h"
 
-static struct map_desc h2_io_desc[] __initdata = {
-{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE },
-{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE,
-	MT_DEVICE },
-};
+static int __initdata h2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
 
 static struct resource h2_smc91x_resources[] = {
 	[0] = {
@@ -78,15 +75,22 @@
 	.hmc_mode	= 19,	// 0:host(off) 1:dev|otg 2:disabled
 	// .hmc_mode	= 21,	// 0:host(off) 1:dev(loopback) 2:host(loopback)
 #elif	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-	/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+	/* needs OTG cable, or NONSTANDARD (B-to-MiniB) */
 	.hmc_mode	= 20,	// 1:dev|otg(off) 1:host 2:disabled
 #endif
 
 	.pins[1]	= 3,
 };
 
+static struct omap_mmc_config h2_mmc_config __initdata = {
+	.mmc_blocks		= 1,
+	.mmc1_power_pin		= -1,	/* tps65010 gpio3 */
+	.mmc1_switch_pin	= OMAP_MPUIO(1),
+};
+
 static struct omap_board_config_kernel h2_config[] = {
 	{ OMAP_TAG_USB,           &h2_usb_config },
+	{ OMAP_TAG_MMC,           &h2_mmc_config },
 };
 
 static void __init h2_init(void)
@@ -99,7 +103,7 @@
 static void __init h2_map_io(void)
 {
 	omap_map_io();
-	iotable_init(h2_io_desc, ARRAY_SIZE(h2_io_desc));
+	omap_serial_init(h2_serial_ports);
 }
 
 MACHINE_START(OMAP_H2, "TI-H2")
diff -Nru a/arch/arm/mach-omap/board-h3.c b/arch/arm/mach-omap/board-h3.c
--- a/arch/arm/mach-omap/board-h3.c	2004-10-28 22:25:56 -07:00
+++ b/arch/arm/mach-omap/board-h3.c	2004-10-28 22:25:56 -07:00
@@ -30,6 +30,8 @@
 #include <asm/arch/irqs.h>
 #include <asm/arch/gpio.h>
 #include <asm/mach-types.h>
+#include <asm/arch/serial.h>
+
 #include "common.h"
 
 void h3_init_irq(void)
@@ -37,6 +39,8 @@
 	omap_init_irq();
 }
 
+static int __initdata h3_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+
 static struct resource smc91x_resources[] = {
 	[0] = {
 		.start	= OMAP1710_ETHR_START,		/* Physical */
@@ -66,15 +70,10 @@
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
-static struct map_desc h3_io_desc[] __initdata = {
-{ OMAP1710_ETHR_BASE,  OMAP1710_ETHR_START,  OMAP1710_ETHR_SIZE,  MT_DEVICE },
-{ OMAP_NOR_FLASH_BASE, OMAP_NOR_FLASH_START, OMAP_NOR_FLASH_SIZE, MT_DEVICE },
-};
-
 static void __init h3_map_io(void)
 {
 	omap_map_io();
-	iotable_init(h3_io_desc, ARRAY_SIZE(h3_io_desc));
+	omap_serial_init(h3_serial_ports);
 }
 
 MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
diff -Nru a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c
--- a/arch/arm/mach-omap/board-innovator.c	2004-10-28 22:25:56 -07:00
+++ b/arch/arm/mach-omap/board-innovator.c	2004-10-28 22:25:56 -07:00
@@ -30,6 +30,7 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/fpga.h>
 #include <asm/arch/usb.h>
+#include <asm/arch/serial.h>
 
 #include "common.h"
 
@@ -43,6 +44,8 @@
 	MT_DEVICE },
 };
 
+static int __initdata innovator_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1};
+
 static struct resource innovator1510_smc91x_resources[] = {
 	[0] = {
 		.start	= OMAP1510_FPGA_ETHR_START,	/* Physical */
@@ -69,18 +72,12 @@
 
 #endif /* CONFIG_ARCH_OMAP1510 */
 
-#ifdef CONFIG_ARCH_OMAP1610
-
-static struct map_desc innovator1610_io_desc[] __initdata = {
-{ OMAP1610_ETHR_BASE, OMAP1610_ETHR_START, OMAP1610_ETHR_SIZE,MT_DEVICE },
-{ OMAP1610_NOR_FLASH_BASE, OMAP1610_NOR_FLASH_START, OMAP1610_NOR_FLASH_SIZE,
-	MT_DEVICE },
-};
+#ifdef CONFIG_ARCH_OMAP16XX
 
 static struct resource innovator1610_smc91x_resources[] = {
 	[0] = {
-		.start	= OMAP1610_ETHR_START,		/* Physical */
-		.end	= OMAP1610_ETHR_START + SZ_4K,
+		.start	= INNOVATOR1610_ETHR_START,		/* Physical */
+		.end	= INNOVATOR1610_ETHR_START + SZ_4K,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -101,7 +98,7 @@
 	&innovator1610_smc91x_device,
 };
 
-#endif /* CONFIG_ARCH_OMAP1610 */
+#endif /* CONFIG_ARCH_OMAP16XX */
 
 void innovator_init_irq(void)
 {
@@ -116,16 +113,19 @@
 
 #ifdef CONFIG_ARCH_OMAP1510
 static struct omap_usb_config innovator1510_usb_config __initdata = {
-	/* has usb host and device, but no Mini-AB port */
+	/* for bundled non-standard host and peripheral cables */
+	.hmc_mode	= 4,
+
 	.register_host	= 1,
+	.pins[1]	= 6,
+	.pins[2]	= 6,		/* Conflicts with UART2 */
+
 	.register_dev	= 1,
-	/* Assume bad Innovator wiring; Use internal host only with custom cable */
-	.hmc_mode	= 16,
 	.pins[0]	= 2,
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1610
+#ifdef CONFIG_ARCH_OMAP16XX
 static struct omap_usb_config h2_usb_config __initdata = {
 	/* usb1 has a Mini-AB port and external isp1301 transceiver */
 	.otg		= 2,
@@ -153,7 +153,7 @@
 		platform_add_devices(innovator1510_devices, ARRAY_SIZE(innovator1510_devices));
 	}
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
+#ifdef CONFIG_ARCH_OMAP16XX
 	if (!cpu_is_omap1510()) {
 		platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
 	}
@@ -163,7 +163,7 @@
 	if (cpu_is_omap1510())
 		innovator_config[0].data = &innovator1510_usb_config;
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
+#ifdef CONFIG_ARCH_OMAP16XX
 	if (cpu_is_omap1610())
 		innovator_config[0].data = &h2_usb_config;
 #endif
@@ -187,11 +187,7 @@
 		       fpga_read(OMAP1510_FPGA_BOARD_REV));
 	}
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
-	if (!cpu_is_omap1510()) {
-		iotable_init(innovator1610_io_desc, ARRAY_SIZE(innovator1610_io_desc));
-	}
-#endif
+	omap_serial_init(innovator_serial_ports);
 }
 
 MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
diff -Nru a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c
--- a/arch/arm/mach-omap/board-osk.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-omap/board-osk.c	2004-10-28 22:25:59 -07:00
@@ -38,15 +38,18 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/fpga.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/serial.h>
 
 #include "common.h"
 
 static struct map_desc osk5912_io_desc[] __initdata = {
-{ OMAP_OSK_ETHR_BASE, OMAP_OSK_ETHR_START, OMAP_OSK_ETHR_SIZE,MT_DEVICE },
 { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
 	MT_DEVICE },
 };
 
+static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0};
+
 static struct resource osk5912_smc91x_resources[] = {
 	[0] = {
 		.start	= OMAP_OSK_ETHR_START,		/* Physical */
@@ -76,16 +79,29 @@
 	omap_init_irq();
 }
 
+static struct omap_usb_config osk_usb_config __initdata = {
+	/* has usb host and device, but no Mini-AB port */
+	.register_host	= 1,
+	.hmc_mode	= 16,
+	.pins[0]	= 2,
+};
+
+static struct omap_board_config_kernel osk_config[] = {
+	{ OMAP_TAG_USB,           &osk_usb_config },
+};
+
 static void __init osk_init(void)
 {
         platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices));
+	omap_board_config = osk_config;
+	omap_board_config_size = ARRAY_SIZE(osk_config);
 }
 
 static void __init osk_map_io(void)
 {
 	omap_map_io();
 	iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc));
-
+	omap_serial_init(osk_serial_ports);
 }
 
 MACHINE_START(OMAP_OSK, "TI-OSK")
diff -Nru a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c
--- a/arch/arm/mach-omap/board-perseus2.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-omap/board-perseus2.c	2004-10-28 22:25:58 -07:00
@@ -24,6 +24,7 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/fpga.h>
+#include <asm/arch/serial.h>
 
 #include "common.h"
 
@@ -45,6 +46,8 @@
 	},
 };
 
+static int __initdata p2_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 0};
+
 static struct platform_device smc91x_device = {
 	.name		= "smc91x",
 	.id		= 0,
@@ -104,6 +107,7 @@
 	 * It is used as the Ethernet controller interrupt
 	 */
 	omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9);
+	omap_serial_init(p2_serial_ports);
 }
 
 MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
diff -Nru a/arch/arm/mach-omap/clock.c b/arch/arm/mach-omap/clock.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/clock.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,947 @@
+/*
+ *  linux/arch/arm/mach-omap/clock.c
+ *
+ *  Copyright (C) 2004 Nokia corporation
+ *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware/clock.h>
+#include <asm/arch/board.h>
+
+#include "clock.h"
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+static spinlock_t clockfw_lock = SPIN_LOCK_UNLOCKED;
+static void propagate_rate(struct clk *  clk);
+/* MPU virtual clock functions */
+static int select_table_rate(unsigned long rate);
+static long round_to_table_rate(unsigned long rate);
+void clk_setdpll(__u16, __u16);
+
+struct mpu_rate rate_table[] = {
+	/* MPU MHz, xtal MHz, dpll1 MHz, CKCTL, DPLL_CTL
+	 * armdiv, dspdiv, dspmmu, tcdiv, perdiv, lcddiv
+	 */
+#if defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
+	{ 195000000, 13000000, 195000000, 0x050e, 0x2790 }, /* 1/1/2/2/4/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_192MHZ) && defined(CONFIG_ARCH_OMAP16XX)
+	{ 192000000, 19200000, 192000000, 0x050f, 0x2510 }, /* 1/1/2/2/8/8 */
+	{ 192000000, 12000000, 192000000, 0x050f, 0x2810 }, /* 1/1/2/2/8/8 */
+	{  96000000, 12000000, 192000000, 0x055f, 0x2810 }, /* 2/2/2/2/8/8 */
+	{  48000000, 12000000, 192000000, 0x0ccf, 0x2810 }, /* 4/4/4/4/8/8 */
+	{  24000000, 12000000, 192000000, 0x0fff, 0x2810 }, /* 8/8/8/8/8/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
+	{ 182000000, 13000000, 182000000, 0x050e, 0x2710 }, /* 1/1/2/2/4/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_168MHZ)
+	{ 168000000, 12000000, 168000000, 0x010f, 0x2710 }, /* 1/1/1/2/8/8 */
+#endif
+#if defined(CONFIG_OMAP_ARM_120MHZ)
+	{ 120000000, 12000000, 120000000, 0x010a, 0x2510 }, /* 1/1/1/2/4/4 */
+#endif
+#if defined(CONFIG_OMAP_ARM_96MHZ)
+	{  96000000, 12000000,  96000000, 0x0005, 0x2410 }, /* 1/1/1/1/2/2 */
+#endif
+#if defined(CONFIG_OMAP_ARM_60MHZ)
+	{  60000000, 12000000,  60000000, 0x0005, 0x2290 }, /* 1/1/1/1/2/2 */
+#endif
+#if defined(CONFIG_OMAP_ARM_30MHZ)
+	{  30000000, 12000000,  60000000, 0x0555, 0x2290 }, /* 2/2/2/2/2/2 */
+#endif
+	{ 0, 0, 0, 0, 0 },
+};
+
+
+static void ckctl_recalc(struct clk *  clk)
+{
+	int dsor;
+
+	/* Calculate divisor encoded as 2-bit exponent */
+	dsor = 1 << (3 & (omap_readw(ARM_CKCTL) >> clk->rate_offset));
+	if (unlikely(clk->rate == clk->parent->rate / dsor))
+		return; /* No change, quick exit */
+	clk->rate = clk->parent->rate / dsor;
+
+	if (unlikely(clk->flags & RATE_PROPAGATES))
+		propagate_rate(clk);
+}
+
+
+static void followparent_recalc(struct clk *  clk)
+{
+	clk->rate = clk->parent->rate;
+}
+
+
+static void watchdog_recalc(struct clk *  clk)
+{
+	clk->rate = clk->parent->rate / 14;
+}
+
+
+static struct clk ck_ref = {
+	.name		= "ck_ref",
+	.rate		= 12000000,
+	.flags		= ALWAYS_ENABLED,
+};
+
+static struct clk ck_dpll1 = {
+	.name		= "ck_dpll1",
+	.parent		= &ck_ref,
+	.flags		= RATE_PROPAGATES | ALWAYS_ENABLED,
+};
+
+static struct clk ck_dpll1out = {
+	.name		= "ck_dpll1out",
+	.parent		= &ck_dpll1,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_CKOUT_ARM,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk arm_ck = {
+	.name		= "arm_ck",
+	.parent		= &ck_dpll1,
+	.flags		= RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.rate_offset	= CKCTL_ARMDIV_OFFSET,
+	.recalc		= &ckctl_recalc,
+};
+
+static struct clk armper_ck = {
+	.name		= "armper_ck",
+	.parent		= &ck_dpll1,
+	.flags		= RATE_CKCTL,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_PERCK,
+	.rate_offset	= CKCTL_PERDIV_OFFSET,
+	.recalc		= &ckctl_recalc,
+};
+
+static struct clk arm_gpio_ck = {
+	.name		= "arm_gpio_ck",
+	.parent		= &ck_dpll1,
+	.flags		= DOES_NOT_EXIST_ON_1610,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_GPIOCK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk armxor_ck = {
+	.name		= "armxor_ck",
+	.parent		= &ck_ref,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_XORPCK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk armtim_ck = {
+	.name		= "armtim_ck",
+	.parent		= &ck_ref,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_TIMCK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk armwdt_ck = {
+	.name		= "armwdt_ck",
+	.parent		= &ck_ref,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_WDTCK,
+	.recalc		= &watchdog_recalc,
+};
+
+static struct clk arminth_ck1610 = {
+	.name		= "arminth_ck",
+	.parent		= &arm_ck,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.recalc		= &followparent_recalc,
+	/* Note: On 1610/1710 frequency can be divided by 2 by programming
+	 * ARM_CKCTL:ARM_INTHCK_SEL(14) to 1
+	 *
+	 * 1510 version is in TC clocks.
+	 */
+};
+
+static struct clk dsp_ck = {
+	.name		= "dsp_ck",
+	.parent		= &ck_dpll1,
+	.flags		= RATE_CKCTL,
+	.enable_reg	= ARM_CKCTL,
+	.enable_bit	= EN_DSPCK,
+	.rate_offset	= CKCTL_DSPDIV_OFFSET,
+	.recalc		= &ckctl_recalc,
+};
+
+static struct clk dspmmu_ck = {
+	.name		= "dspmmu_ck",
+	.parent		= &ck_dpll1,
+	.flags		= RATE_CKCTL | ALWAYS_ENABLED,
+	.rate_offset	= CKCTL_DSPMMUDIV_OFFSET,
+	.recalc		= &ckctl_recalc,
+};
+
+static struct clk tc_ck = {
+	.name		= "tc_ck",
+	.parent		= &ck_dpll1,
+	.flags		= RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
+	.rate_offset	= CKCTL_TCDIV_OFFSET,
+	.recalc		= &ckctl_recalc,
+};
+
+static struct clk arminth_ck1510 = {
+	.name		= "arminth_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1610,
+	.recalc		= &followparent_recalc,
+	/* Note: On 1510 frequency follows TC_CK
+	 *
+	 * 1610/1710 version is in MPU clocks.
+	 */
+};
+
+static struct clk tipb_ck = {
+	.name		= "tibp_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1610,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk l3_ocpi_ck = {
+	.name		= "l3_ocpi_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.enable_reg	= ARM_IDLECT3,
+	.enable_bit	= EN_OCPI_CK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk tc1_ck = {
+	.name		= "tc1_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.enable_reg	= ARM_IDLECT3,
+	.enable_bit	= EN_TC1_CK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk tc2_ck = {
+	.name		= "tc2_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.enable_reg	= ARM_IDLECT3,
+	.enable_bit	= EN_TC2_CK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk dma_ck = {
+	.name		= "dma_ck",
+	.parent		= &tc_ck,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk dma_lcdfree_ck = {
+	.name		= "dma_lcdfree_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk api_ck = {
+	.name		= "api_ck",
+	.parent		= &tc_ck,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_APICK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk lb_ck = {
+	.name		= "lb_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1610,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_LBCK,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk rhea1_ck = {
+	.name		= "rhea1_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk rhea2_ck = {
+	.name		= "rhea2_ck",
+	.parent		= &tc_ck,
+	.flags		= DOES_NOT_EXIST_ON_1510,
+	.recalc		= &followparent_recalc,
+};
+
+static struct clk lcd_ck = {
+	.name		= "lcd_ck",
+	.parent		= &ck_dpll1,
+	.flags		= RATE_CKCTL,
+	.enable_reg	= ARM_IDLECT2,
+	.enable_bit	= EN_LCDCK,
+	.rate_offset	= CKCTL_LCDDIV_OFFSET,
+	.recalc		= &ckctl_recalc,
+};
+
+static struct clk uart1_ck = {
+	.name		= "uart1_ck",
+	/* Direct from ULPD, no parent */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT,
+	.enable_reg	= MOD_CONF_CTRL_0,
+	.enable_bit	= 29,
+	/* (Only on 1510)
+	 * The "enable bit" actually chooses between 48MHz and 12MHz.
+	 */
+};
+
+static struct clk uart2_ck = {
+	.name		= "uart2_ck",
+	/* Direct from ULPD, no parent */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT,
+	.enable_reg	= MOD_CONF_CTRL_0,
+	.enable_bit	= 30,
+	/* (1510/1610/1710)
+	 * The "enable bit" actually chooses between 48MHz and 12MHz/32kHz.
+	 */
+};
+
+static struct clk uart3_ck = {
+	.name		= "uart3_ck",
+	/* Direct from ULPD, no parent */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT,
+	.enable_reg	= MOD_CONF_CTRL_0,
+	.enable_bit	= 31,
+	/* (Only on 1510)
+	 * The "enable bit" actually chooses between 48MHz and 12MHz.
+	 */
+};
+
+static struct clk usb_ck1610 = {
+	.name		= "usb_ck",
+	/* Direct from ULPD, no parent */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT |
+			  DOES_NOT_EXIST_ON_1510,
+	.enable_reg	= ULPD_CLOCK_CTRL,
+	.enable_bit	= USB_MCLK_EN,
+};
+
+static struct clk usb_ck1510 = {
+	.name		= "usb_ck",
+	/* Direct from ULPD, no parent */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | DOES_NOT_EXIST_ON_1610,
+};
+
+static struct clk usb_hhc_ck = {
+	.name		= "usb_hhc_ck",
+	/* Direct from ULPD, no parent */
+	.rate		= 48000000, /* Actually 2 clocks, 12MHz and 48MHz */
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT,
+	.enable_reg	= MOD_CONF_CTRL_0,
+	.enable_bit	= USB_HOST_HHC_UHOST_EN,
+};
+
+/* To be done --
+static struct clk mclk = {
+	.name		= "mclk",
+};
+
+static struct clk bclk = {
+	.name		= "bclk",
+};
+-- to be done */
+
+static struct clk mmc_ck = {
+	.name		= "mmc1_ck",
+	.parent		= &armxor_ck, /* (1510) */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT |
+			  DOES_NOT_EXIST_ON_1610,
+	.enable_reg	= MOD_CONF_CTRL_0,
+	.enable_bit	= 23,
+};
+
+static struct clk mmc1_ck = {
+	.name		= "mmc1_ck",
+	/* Direct from ULPD, no parent (1610/1710) */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT |
+			  DOES_NOT_EXIST_ON_1510,
+	.enable_reg	= MOD_CONF_CTRL_0,
+	.enable_bit	= 23,
+};
+
+static struct clk mmc2_ck = {
+	.name		= "mmc2_ck",
+	/* Direct from ULPD, no parent */
+	.rate		= 48000000,
+	.flags		= RATE_FIXED | ENABLE_REG_32BIT |
+			  DOES_NOT_EXIST_ON_1510,
+	.enable_reg	= MOD_CONF_CTRL_0,
+	.enable_bit	= 20,
+};
+
+static struct clk virtual_ck_mpu = {
+	.name		= "mpu",
+	.flags		= VIRTUAL_CLOCK | ALWAYS_ENABLED,
+	.parent		= &arm_ck, /* Is smarter alias for */
+	.recalc		= &followparent_recalc,
+	.set_rate	= &select_table_rate,
+	.round_rate	= &round_to_table_rate,
+};
+
+
+static struct clk *  onchip_clks[] = {
+	/* non-ULPD clocks */
+	&ck_ref,
+	&ck_dpll1,
+	/* CK_GEN1 clocks */
+	&ck_dpll1out,
+	&arm_ck,
+	&armper_ck,
+	&arm_gpio_ck,
+	&armxor_ck,
+	&armtim_ck,
+	&armwdt_ck,
+	&arminth_ck1510,
+	&arminth_ck1610,
+	/* CK_GEN2 clocks */
+	&dsp_ck,
+	&dspmmu_ck,
+	/* CK_GEN3 clocks */
+	&tc_ck,
+	&tipb_ck,
+	&l3_ocpi_ck,
+	&tc1_ck,
+	&tc2_ck,
+	&dma_ck,
+	&dma_lcdfree_ck,
+	&api_ck,
+	&lb_ck,
+	&rhea1_ck,
+	&rhea2_ck,
+	&lcd_ck,
+	/* ULPD clocks */
+	&uart1_ck,
+	&uart2_ck,
+	&uart3_ck,
+	&usb_ck1510,
+	&usb_ck1610,
+	&usb_hhc_ck,
+	/* To be done --
+	&mclk,
+	&bclk,
+	-- to be done */
+	&mmc_ck, /* 1510 */
+	&mmc1_ck, /* 1610/1710 */
+	&mmc2_ck,
+	/* Virtual clocks */
+	&virtual_ck_mpu,
+};
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+	down(&clocks_sem);
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+	up(&clocks_sem);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+
+void clk_put(struct clk *clk)
+{
+	if (clk && !IS_ERR(clk))
+		module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+
+int __clk_enable(struct clk *clk)
+{
+	__u16 regval16;
+	__u32 regval32;
+
+	if (clk->flags & ALWAYS_ENABLED)
+		return 0;
+
+	if (unlikely(clk->enable_reg == 0)) {
+		printk("Enable for %s without enable enabled\n", clk->name);
+		return 0;
+	}
+
+	if (clk->flags & ENABLE_REG_32BIT) {
+		regval32 = omap_readl(clk->enable_reg);
+		regval32 |= (1 << clk->enable_bit);
+		omap_writel(regval32, clk->enable_reg);
+	} else {
+		regval16 = omap_readw(clk->enable_reg);
+		regval16 |= (1 << clk->enable_bit);
+		omap_writew(regval16, clk->enable_reg);
+	}
+
+	return 0;
+}
+
+
+void __clk_disable(struct clk *clk)
+{
+	__u16 regval16;
+	__u32 regval32;
+
+	if (clk->enable_reg == 0)
+		return;
+
+	if (clk->flags & ENABLE_REG_32BIT) {
+		regval32 = omap_readl(clk->enable_reg);
+		regval32 &= ~(1 << clk->enable_bit);
+		omap_writel(regval32, clk->enable_reg);
+	} else {
+		regval16 = omap_readw(clk->enable_reg);
+		regval16 &= ~(1 << clk->enable_bit);
+		omap_writew(regval16, clk->enable_reg);
+	}
+}
+
+
+void __clk_unuse(struct clk *clk)
+{
+	if (clk->usecount > 0 && !(--clk->usecount)) {
+		__clk_disable(clk);
+		if (likely(clk->parent))
+			__clk_unuse(clk->parent);
+	}
+}
+
+
+int __clk_use(struct clk *clk)
+{
+	int ret = 0;
+	if (clk->usecount++ == 0) {
+		if (likely(clk->parent))
+			ret = __clk_use(clk->parent);
+
+		if (unlikely(ret != 0)) {
+			clk->usecount--;
+			return ret;
+		}
+
+		ret = __clk_enable(clk);
+
+		if (unlikely(ret != 0) && clk->parent) {
+			__clk_unuse(clk->parent);
+			clk->usecount--;
+		}
+	}
+
+	return ret;
+}
+
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	ret = __clk_enable(clk);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	__clk_disable(clk);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+
+int clk_use(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	ret = __clk_use(clk);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(clk_use);
+
+
+void clk_unuse(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	__clk_unuse(clk);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_unuse);
+
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->rate == 0) {
+		printk("Get rate for %s without cached clock\n", clk->name);
+	}
+
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+
+static __u16 verify_ckctl_value(__u16 newval)
+{
+	/* This function checks for following limitations set
+	 * by the hardware (all conditions must be true):
+	 * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
+	 * ARM_CK >= TC_CK
+	 * DSP_CK >= TC_CK
+	 * DSPMMU_CK >= TC_CK
+	 *
+	 * In addition following rules are enforced:
+	 * LCD_CK <= TC_CK
+	 * ARMPER_CK <= TC_CK
+	 *
+	 * However, maximum frequencies are not checked for!
+	 */
+	__u8 per_exp;
+	__u8 lcd_exp;
+	__u8 arm_exp;
+	__u8 dsp_exp;
+	__u8 tc_exp;
+	__u8 dspmmu_exp;
+
+	per_exp = (newval >> CKCTL_PERDIV_OFFSET) & 3;
+	lcd_exp = (newval >> CKCTL_LCDDIV_OFFSET) & 3;
+	arm_exp = (newval >> CKCTL_ARMDIV_OFFSET) & 3;
+	dsp_exp = (newval >> CKCTL_DSPDIV_OFFSET) & 3;
+	tc_exp = (newval >> CKCTL_TCDIV_OFFSET) & 3;
+	dspmmu_exp = (newval >> CKCTL_DSPMMUDIV_OFFSET) & 3;
+
+	if (dspmmu_exp < dsp_exp)
+		dspmmu_exp = dsp_exp;
+	if (dspmmu_exp > dsp_exp+1)
+		dspmmu_exp = dsp_exp+1;
+	if (tc_exp < arm_exp)
+		tc_exp = arm_exp;
+	if (tc_exp < dspmmu_exp)
+		tc_exp = dspmmu_exp;
+	if (tc_exp > lcd_exp)
+		lcd_exp = tc_exp;
+	if (tc_exp > per_exp)
+		per_exp = tc_exp;
+
+	newval &= 0xf000;
+	newval |= per_exp << CKCTL_PERDIV_OFFSET;
+	newval |= lcd_exp << CKCTL_LCDDIV_OFFSET;
+	newval |= arm_exp << CKCTL_ARMDIV_OFFSET;
+	newval |= dsp_exp << CKCTL_DSPDIV_OFFSET;
+	newval |= tc_exp << CKCTL_TCDIV_OFFSET;
+	newval |= dspmmu_exp << CKCTL_DSPMMUDIV_OFFSET;
+
+	return newval;
+}
+
+
+static int calc_dsor_exp(struct clk *clk, unsigned long rate)
+{
+	/* Note: If target frequency is too low, this function will return 4,
+	 * which is invalid value. Caller must check for this value and act
+	 * accordingly.
+	 *
+	 * Note: This function does not check for following limitations set
+	 * by the hardware (all conditions must be true):
+	 * DSPMMU_CK == DSP_CK  or  DSPMMU_CK == DSP_CK/2
+	 * ARM_CK >= TC_CK
+	 * DSP_CK >= TC_CK
+	 * DSPMMU_CK >= TC_CK
+	 */
+	unsigned long realrate;
+	struct clk *  parent;
+	unsigned  dsor_exp;
+
+	if (unlikely(!(clk->flags & RATE_CKCTL)))
+		return -EINVAL;
+
+	parent = clk->parent;
+	if (unlikely(parent == 0))
+		return -EIO;
+
+	realrate = parent->rate;
+	for (dsor_exp=0; dsor_exp<4; dsor_exp++) {
+		if (realrate <= rate)
+			break;
+
+		realrate /= 2;
+	}
+
+	return dsor_exp;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	int dsor_exp;
+
+	if (clk->flags & RATE_FIXED)
+		return clk->rate;
+
+	if (clk->flags & RATE_CKCTL) {
+		dsor_exp = calc_dsor_exp(clk, rate);
+		if (dsor_exp < 0)
+			return dsor_exp;
+		if (dsor_exp > 3)
+			dsor_exp = 3;
+		return clk->parent->rate / (1 << dsor_exp);
+	}
+
+	if(clk->round_rate != 0)
+		return clk->round_rate(rate);
+
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+
+static void propagate_rate(struct clk *  clk)
+{
+	struct clk **  clkp;
+
+	for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
+		if (likely((*clkp)->parent != clk)) continue;
+		if (likely((*clkp)->recalc))
+			(*clkp)->recalc(*clkp);
+	}
+}
+
+
+static int select_table_rate(unsigned long rate)
+{
+	/* Find the highest supported frequency <= rate and switch to it */
+	struct mpu_rate *  ptr;
+
+	for (ptr = rate_table; ptr->rate; ptr++) {
+		if (ptr->xtal != ck_ref.rate)
+			continue;
+
+		/* DPLL1 cannot be reprogrammed without risking system crash */
+		if (likely(ck_dpll1.rate!=0) && ptr->pll_rate != ck_dpll1.rate)
+			continue;
+
+		/* Can check only after xtal frequency check */
+		if (ptr->rate <= rate)
+			break;
+	}
+
+	if (!ptr->rate)
+		return -EINVAL;
+
+	if (unlikely(ck_dpll1.rate == 0)) {
+		omap_writew(ptr->dpllctl_val, DPLL_CTL);
+		ck_dpll1.rate = ptr->pll_rate;
+	}
+	omap_writew(ptr->ckctl_val, ARM_CKCTL);
+	propagate_rate(&ck_dpll1);
+	return 0;
+}
+
+
+static long round_to_table_rate(unsigned long rate)
+{
+	/* Find the highest supported frequency <= rate */
+	struct mpu_rate *  ptr;
+	long  highest_rate;
+
+	highest_rate = -EINVAL;
+
+	for (ptr = rate_table; ptr->rate; ptr++) {
+		if (ptr->xtal != ck_ref.rate)
+			continue;
+
+		highest_rate = ptr->rate;
+
+		/* Can check only after xtal frequency check */
+		if (ptr->rate <= rate)
+			break;
+	}
+
+	return highest_rate;
+}
+
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int  ret = -EINVAL;
+	int  dsor_exp;
+	__u16  regval;
+	unsigned long  flags;
+
+	if (clk->flags & RATE_CKCTL) {
+		dsor_exp = calc_dsor_exp(clk, rate);
+		if (dsor_exp > 3)
+			dsor_exp = -EINVAL;
+		if (dsor_exp < 0)
+			return dsor_exp;
+
+		spin_lock_irqsave(&clockfw_lock, flags);
+		regval = omap_readw(ARM_CKCTL);
+		regval &= ~(3 << clk->rate_offset);
+		regval |= dsor_exp << clk->rate_offset;
+		regval = verify_ckctl_value(regval);
+		omap_writew(regval, ARM_CKCTL);
+		clk->rate = clk->parent->rate / (1 << dsor_exp);
+		spin_unlock_irqrestore(&clockfw_lock, flags);
+		ret = 0;
+	} else if(clk->set_rate != 0) {
+		spin_lock_irqsave(&clockfw_lock, flags);
+		ret = clk->set_rate(rate);
+		spin_unlock_irqrestore(&clockfw_lock, flags);
+	}
+
+	if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES)))
+		propagate_rate(clk);
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+
+int clk_register(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_add(&clk->node, &clocks);
+	up(&clocks_sem);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	down(&clocks_sem);
+	list_del(&clk->node);
+	up(&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+
+
+int __init clk_init(void)
+{
+	struct clk **  clkp;
+	const struct omap_clock_config *info;
+	int crystal_type = 0; /* Default 12 MHz */
+
+	for (clkp = onchip_clks; clkp < onchip_clks+ARRAY_SIZE(onchip_clks); clkp++) {
+		if ((((*clkp)->flags & DOES_NOT_EXIST_ON_1510) &&
+		     cpu_is_omap1510()) ||
+		    (((*clkp)->flags & DOES_NOT_EXIST_ON_1610) &&
+		     (cpu_is_omap1610() || cpu_is_omap1710()))) {
+			(*clkp)->parent = 0;
+			continue;
+		}
+		clk_register(*clkp);
+	}
+
+	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
+	if (info != NULL) {
+		if (!cpu_is_omap1510())
+			crystal_type = info->system_clock_type;
+	}
+
+#if defined(CONFIG_ARCH_OMAP730)
+	ck_ref.rate = 13000000;
+#elif defined(CONFIG_ARCH_OMAP16XX)
+	if (crystal_type == 2)
+		ck_ref.rate = 19200000;
+#endif
+
+	/* We want to be in syncronous scalable mode */
+	omap_writew(0x1000, ARM_SYSST);
+
+	/* Find the highest supported frequency and enable it */
+	if (select_table_rate(~0)) {
+		printk("System frequencies not set. Check your config.\n");
+		/* Guess sane values (60MHz) */
+		omap_writew(0x2290, DPLL_CTL);
+		omap_writew(0x1005, ARM_CKCTL);
+		ck_dpll1.rate = 60000000;
+		propagate_rate(&ck_dpll1);
+		printk("Clocking rate (xtal/DPLL1/MPU): %ld/%ld/%ld\n",
+			ck_ref.rate, ck_dpll1.rate, arm_ck.rate);
+	}
+
+	/* Cache rates for clocks connected to ck_ref (not dpll1) */
+	propagate_rate(&ck_ref);
+
+#ifdef CONFIG_MACH_OMAP_PERSEUS2
+	/* Select slicer output as OMAP input clock */
+	omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
+#endif
+
+	/* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */
+	omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
+
+	/* Put DSP/MPUI into reset until needed */
+	omap_writew(0, ARM_RSTCT1);
+	omap_writew(1, ARM_RSTCT2);
+	omap_writew(0x400, ARM_IDLECT1);
+
+	/*
+	 * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
+	 * of the ARM_IDLECT2 register must be set to zero. The power-on
+	 * default value of this bit is one.
+	 */
+	omap_writew(0x0000, ARM_IDLECT2);	/* Turn LCD clock off also */
+
+	/*
+	 * Only enable those clocks we will need, let the drivers
+	 * enable other clocks as necessary
+	 */
+	clk_use(&armper_ck);
+	clk_use(&armxor_ck);
+	clk_use(&armtim_ck);
+
+	if (cpu_is_omap1510())
+		clk_enable(&arm_gpio_ck);
+
+	start_mputimer1(0xffffffff);
+
+	return 0;
+}
diff -Nru a/arch/arm/mach-omap/clock.h b/arch/arm/mach-omap/clock.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/clock.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,106 @@
+/*
+ *  linux/arch/arm/mach-omap/clock.h
+ *
+ *  Copyright (C) 2004 Nokia corporation
+ *  Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *  Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_OMAP_CLOCK_H
+#define __ARCH_ARM_OMAP_CLOCK_H
+
+struct module;
+
+struct clk {
+	struct list_head	node;
+	struct module		*owner;
+	const char		*name;
+	struct clk		*parent;
+	unsigned long		rate;
+	__s8			usecount;
+	__u8			flags;
+	__u32			enable_reg;
+	__u8			enable_bit;
+	__u8			rate_offset;
+	void			(*recalc)(struct clk *);
+	int			(*set_rate)(unsigned long);
+	long			(*round_rate)(unsigned long);
+};
+
+
+struct mpu_rate {
+	unsigned long		rate;
+	unsigned long		xtal;
+	unsigned long		pll_rate;
+	__u16			ckctl_val;
+	__u16			dpllctl_val;
+};
+
+
+/* Clock flags */
+#define RATE_CKCTL		1
+#define RATE_FIXED		2
+#define RATE_PROPAGATES		4
+#define VIRTUAL_CLOCK		8
+#define ALWAYS_ENABLED		16
+#define ENABLE_REG_32BIT	32
+#define DOES_NOT_EXIST_ON_1510	64
+#define DOES_NOT_EXIST_ON_1610	128 /* Including 1710 */
+
+/* ARM_CKCTL bit shifts */
+#define CKCTL_PERDIV_OFFSET	0
+#define CKCTL_LCDDIV_OFFSET	2
+#define CKCTL_ARMDIV_OFFSET	4
+#define CKCTL_DSPDIV_OFFSET	6
+#define CKCTL_TCDIV_OFFSET	8
+#define CKCTL_DSPMMUDIV_OFFSET	10
+/*#define ARM_TIMXO		12*/
+#define EN_DSPCK		13
+/*#define ARM_INTHCK_SEL	14*/ /* Divide-by-2 for mpu inth_ck */
+
+/* ARM_IDLECT1 bit shifts */
+/*#define IDLWDT_ARM	0*/
+/*#define IDLXORP_ARM	1*/
+/*#define IDLPER_ARM	2*/
+/*#define IDLLCD_ARM	3*/
+/*#define IDLLB_ARM	4*/
+/*#define IDLHSAB_ARM	5*/
+/*#define IDLIF_ARM	6*/
+/*#define IDLDPLL_ARM	7*/
+/*#define IDLAPI_ARM	8*/
+/*#define IDLTIM_ARM	9*/
+/*#define SETARM_IDLE	11*/
+
+/* ARM_IDLECT2 bit shifts */
+#define EN_WDTCK	0
+#define EN_XORPCK	1
+#define EN_PERCK	2
+#define EN_LCDCK	3
+#define EN_LBCK		4 /* Not on 1610/1710 */
+/*#define EN_HSABCK	5*/
+#define EN_APICK	6
+#define EN_TIMCK	7
+#define DMACK_REQ	8
+#define EN_GPIOCK	9 /* Not on 1610/1710 */
+/*#define EN_LBFREECK	10*/
+#define EN_CKOUT_ARM	11
+
+/* ARM_IDLECT3 bit shifts */
+#define EN_OCPI_CK	0
+#define EN_TC1_CK	2
+#define EN_TC2_CK	4
+
+/* Various register defines for clock controls scattered around OMAP chip */
+#define USB_MCLK_EN		4	/* In ULPD_CLKC_CTRL */
+#define USB_HOST_HHC_UHOST_EN	9	/* In MOD_CONF_CTRL_0 */
+
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+int clk_init(void);
+
+#endif
diff -Nru a/arch/arm/mach-omap/clocks.c b/arch/arm/mach-omap/clocks.c
--- a/arch/arm/mach-omap/clocks.c	2004-10-28 22:25:58 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,705 +0,0 @@
-/*
- * Clock interface for OMAP
- *
- * Copyright (C) 2001 RidgeRun, Inc
- * Written by Gordon McNutt <gmcnutt@ridgerun.com>
- * Updated 2004 for Linux 2.6 by Tony Lindgren <tony@atomide.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/arch/clocks.h>
-#include <asm/arch/board.h>
-
-extern void start_mputimer1(unsigned long load_val);
-
-/* Input clock in MHz */
-static unsigned int source_clock = 12;
-
-/*
- * We use one spinlock for all clock registers for now. We may want to
- * change this to be clock register specific later on. Before we can do
- * that, we need to map out the shared clock registers.
- */
-static spinlock_t clock_lock = SPIN_LOCK_UNLOCKED;
-
-typedef struct {
-	char		*name;
-	__u8		flags;
-	ck_t		parent;
-	unsigned long	rate_reg;	/* Clock rate register */
-	unsigned long	enbl_reg;	/* Enable register */
-	unsigned long	idle_reg;	/* Idle register */
-	unsigned long	slct_reg;	/* Select register */
-	__s8		rate_shift;	/* Clock rate bit shift */
-	__s8		enbl_shift;	/* Clock enable bit shift */
-	__s8		idle_shift;	/* Clock idle bit shift */
-	__s8		slct_shift;	/* Clock select bit shift */
-} ck_info_t;
-
-#define CK_NAME(ck)		ck_info_table[ck].name
-#define CK_FLAGS(ck)		ck_info_table[ck].flags
-#define CK_PARENT(ck)		ck_info_table[ck].parent
-#define CK_RATE_REG(ck)		ck_info_table[ck].rate_reg
-#define CK_ENABLE_REG(ck)	ck_info_table[ck].enbl_reg
-#define CK_IDLE_REG(ck)		ck_info_table[ck].idle_reg
-#define CK_SELECT_REG(ck)	ck_info_table[ck].slct_reg
-#define CK_RATE_SHIFT(ck)	ck_info_table[ck].rate_shift
-#define CK_ENABLE_SHIFT(ck)	ck_info_table[ck].enbl_shift
-#define CK_IDLE_SHIFT(ck)	ck_info_table[ck].idle_shift
-#define CK_SELECT_SHIFT(ck)	ck_info_table[ck].slct_shift
-#define CK_CAN_CHANGE_RATE(cl)	(CK_FLAGS(ck) & CK_RATEF)
-#define CK_CAN_DISABLE(cl)	(CK_FLAGS(ck) & CK_ENABLEF)
-#define CK_CAN_IDLE(cl)		(CK_FLAGS(ck) & CK_IDLEF)
-#define CK_CAN_SWITCH(cl)	(CK_FLAGS(ck) & CK_SELECTF)
-
-static ck_info_t ck_info_table[] = {
-	{
-		.name		= "clkin",
-		.flags		= 0,
-		.parent		= OMAP_CLKIN,
-	}, {
-		.name		= "ck_gen1",
-		.flags		= CK_RATEF | CK_IDLEF,
-		.rate_reg	= DPLL_CTL,
-		.idle_reg	= ARM_IDLECT1,
-		.idle_shift	= IDLDPLL_ARM,
-		.parent		= OMAP_CLKIN,
-	}, {
-		.name		= "ck_gen2",
-		.flags		= 0,
-		.parent		= OMAP_CK_GEN1,
-	}, {
-		.name		= "ck_gen3",
-		.flags		= 0,
-		.parent		= OMAP_CK_GEN1,
-	}, {
-		.name		= "tc_ck",
-		.flags		= CK_RATEF | CK_IDLEF,
-		.parent		= OMAP_CK_GEN3,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[TCDIV(9:8)] */
-		.idle_reg	= ARM_IDLECT1,
-		.rate_shift	= TCDIV,
-		.idle_shift	= IDLIF_ARM
-	}, {
-		.name		= "arm_ck",
-		.flags		= CK_IDLEF | CK_RATEF,
-		.parent		= OMAP_CK_GEN1,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[ARMDIV(5:4)] */
-		.idle_reg	= ARM_IDLECT1,
-		.rate_shift	= ARMDIV,
-		.idle_shift	= SETARM_IDLE,
-	}, {
-		.name		= "mpuper_ck",
-		.flags		= CK_RATEF | CK_IDLEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN1,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[PERDIV(1:0)] */
-		.enbl_reg	= ARM_IDLECT2,
-		.idle_reg	= ARM_IDLECT1,
-		.rate_shift	= PERDIV,
-		.enbl_shift	= EN_PERCK,
-		.idle_shift	= IDLPER_ARM
-	}, {
-		.name		= "arm_gpio_ck",
-		.flags		= CK_ENABLEF,
-		.parent		= OMAP_CK_GEN1,
-		.enbl_reg	= ARM_IDLECT2,
-		.enbl_shift	= EN_GPIOCK
-	}, {
-		.name		= "mpuxor_ck",
-		.flags		= CK_ENABLEF | CK_IDLEF,
-		.parent		= OMAP_CLKIN,
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.idle_shift	= IDLXORP_ARM,
-		.enbl_shift	= EN_XORPCK
-	}, {
-		.name		= "mputim_ck",
-		.flags		= CK_IDLEF | CK_ENABLEF | CK_SELECTF,
-		.parent		= OMAP_CLKIN,
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.slct_reg	= ARM_CKCTL,
-		.idle_shift	= IDLTIM_ARM,
-		.enbl_shift	= EN_TIMCK,
-		.slct_shift	= ARM_TIMXO
-	}, {
-		.name		= "mpuwd_ck",
-		.flags		= CK_IDLEF | CK_ENABLEF,
-		.parent		= OMAP_CLKIN,
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.idle_shift	= IDLWDT_ARM,
-		.enbl_shift	= EN_WDTCK,
-	}, {
-		.name		= "dsp_ck",
-		.flags		= CK_RATEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN2,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[DSPDIV(7:6)] */
-		.enbl_reg	= ARM_CKCTL,
-		.rate_shift	= DSPDIV,
-		.enbl_shift	= EN_DSPCK,
-	}, {
-		.name		= "dspmmu_ck",
-		.flags		= CK_RATEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN2,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[DSPMMUDIV(11:10)] */
-		.enbl_reg	= ARM_CKCTL,
-		.rate_shift	= DSPMMUDIV,
-		.enbl_shift	= EN_DSPCK,
-	}, {
-		.name		= "dma_ck",
-		.flags		= CK_RATEF | CK_IDLEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN3,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[TCDIV(9:8)] */
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.rate_shift	= TCDIV,
-		.idle_shift	= IDLIF_ARM,
-		.enbl_shift	= DMACK_REQ
-	}, {
-		.name		= "api_ck",
-		.flags		= CK_RATEF | CK_IDLEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN3,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[TCDIV(9:8)] */
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.rate_shift	= TCDIV,
-		.idle_shift	= IDLAPI_ARM,
-		.enbl_shift	= EN_APICK,
-	}, {
-		.name		= "hsab_ck",
-		.flags		= CK_RATEF | CK_IDLEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN3,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[TCDIV(9:8)] */
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.rate_shift	= TCDIV,
-		.idle_shift	= IDLHSAB_ARM,
-		.enbl_shift	= EN_HSABCK,
-	}, {
-		.name		= "lbfree_ck",
-		.flags		= CK_RATEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN3,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[TCDIV(9:8)] */
-		.enbl_reg	= ARM_IDLECT2,
-		.rate_shift	= TCDIV,
-		.enbl_shift	= EN_LBFREECK,
-	}, {
-		.name		= "lb_ck",
-		.flags		= CK_RATEF | CK_IDLEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN3,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[TCDIV(9:8)] */
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.rate_shift	= TCDIV,
-		.idle_shift	= IDLLB_ARM,
-		.enbl_shift	= EN_LBCK,
-	}, {
-		.name		= "lcd_ck",
-		.flags		= CK_RATEF | CK_IDLEF | CK_ENABLEF,
-		.parent		= OMAP_CK_GEN3,
-		.rate_reg	= ARM_CKCTL,	/* ARM_CKCTL[LCDDIV(3:2)] */
-		.idle_reg	= ARM_IDLECT1,
-		.enbl_reg	= ARM_IDLECT2,
-		.rate_shift	= LCDDIV,
-		.idle_shift	= IDLLCD_ARM,
-		.enbl_shift	= EN_LCDCK,
-	},
-};
-
-/*****************************************************************************/
-
-#define CK_IN_RANGE(ck)		(!((ck < OMAP_CK_MIN) || (ck > OMAP_CK_MAX)))
-
-int ck_auto_unclock = 1;
-int ck_debug = 0;
-
-#define CK_MAX_PLL_FREQ		OMAP_CK_MAX_RATE
-static __u32 ck_valid_table[CK_MAX_PLL_FREQ / 32 + 1];
-static __u8 ck_lookup_table[CK_MAX_PLL_FREQ];
-
-int
-ck_set_input(ck_t ck, ck_t input)
-{
-	int ret = 0, shift;
-	unsigned short reg;
-	unsigned long flags;
-
-	if (!CK_IN_RANGE(ck) || !CK_CAN_SWITCH(ck)) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	reg = omap_readw(CK_SELECT_REG(ck));
-	shift = CK_SELECT_SHIFT(ck);
-
-	spin_lock_irqsave(&clock_lock, flags);
-	if (input == OMAP_CLKIN) {
-		reg &= ~(1 << shift);
-		omap_writew(reg, CK_SELECT_REG(ck));
-		goto exit;
-	} else if (input == CK_PARENT(ck)) {
-		reg |= (1 << shift);
-		omap_writew(reg, CK_SELECT_REG(ck));
-		goto exit;
-	}
-
-	ret = -EINVAL;
- exit:
-	spin_unlock_irqrestore(&clock_lock, flags);
-	return ret;
-}
-
-int
-ck_get_input(ck_t ck, ck_t * input)
-{
-	int ret = -EINVAL;
-	unsigned long flags;
-
-	if (!CK_IN_RANGE(ck))
-		goto exit;
-
-	ret = 0;
-
-	spin_lock_irqsave(&clock_lock, flags);
-	if (CK_CAN_SWITCH(ck)) {
-		int shift;
-		unsigned short reg;
-
-		reg = omap_readw(CK_SELECT_REG(ck));
-		shift = CK_SELECT_SHIFT(ck);
-		if (reg & (1 << shift)) {
-			*input = CK_PARENT(ck);
-			goto exit;
-		}
-	}
-
-	*input = OMAP_CLKIN;
-
- exit:
-	spin_unlock_irqrestore(&clock_lock, flags);
-	return ret;
-}
-
-static int
-__ck_set_pll_rate(ck_t ck, int rate)
-{
-	unsigned short pll;
-	unsigned long flags;
-
-	if ((rate < 0) || (rate > CK_MAX_PLL_FREQ))
-		return -EINVAL;
-
-	/* Scan downward for the closest matching frequency */
-	while (rate && !test_bit(rate, (unsigned long *)&ck_valid_table))
-		rate--;
-
-	if (!rate) {
-		printk(KERN_ERR "%s: couldn't find a matching rate\n",
-			__FUNCTION__);
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&clock_lock, flags);
-	pll = omap_readw(CK_RATE_REG(ck));
-
-	/* Clear the rate bits */
-	pll &= ~(0x1f << 5);
-
-	/* Set the rate bits */
-	pll |= (ck_lookup_table[rate - 1] << 5);
-
-	omap_writew(pll, CK_RATE_REG(ck));
-
-	spin_unlock_irqrestore(&clock_lock, flags);
-
-	return 0;
-}
-
-static int
-__ck_set_clkm_rate(ck_t ck, int rate)
-{
-	int shift, prate, div, ret;
-	unsigned short reg;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clock_lock, flags);
-
-	/*
-	 * We can only set this clock's value to a fraction of its
-	 * parent's value. The interface says I'll round down when necessary.
-	 * So first let's get the parent's current rate.
-	 */
-	prate = ck_get_rate(CK_PARENT(ck));
-
-	/*
-	 * Let's just start with the highest fraction and keep searching
-	 * down through available rates until we find one less than or equal
-	 * to the desired rate.
-	 */
-	for (div = 0; div < 4; div++) {
-		if (prate <= rate)
-			break;
-		prate = prate / 2;
-	}
-
-	/*
-	 * Oops. Looks like the caller wants a rate lower than we can support.
-	 */
-	if (div == 5) {
-		printk(KERN_ERR "%s: %d is too low\n",
-			__FUNCTION__, rate);
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	/*
-	 * One more detail: if this clock supports more than one parent, then
-	 * we're going to automatically switch over to the parent which runs
-	 * through the divisor. For omap this is not ambiguous because for all
-	 * such clocks one choice is always OMAP_CLKIN (which doesn't run
-	 * through the divisor) and the other is whatever I encoded as
-	 * CK_PARENT. Note that I wait until we get this far because I don't
-	 * want to switch the input until we're sure this is going to work.
-	 */
-	if (CK_CAN_SWITCH(ck))
-		if ((ret = ck_set_input(ck, CK_PARENT(ck))) < 0) {
-			BUG();
-			goto exit;
-		}
-
-	/*
-	 * At last, we can set the divisor. Clear the old rate bits and
-	 * set the new ones.
-	 */
-	reg = omap_readw(CK_RATE_REG(ck));
-	shift = CK_RATE_SHIFT(ck);
-	reg &= ~(3 << shift);
-	reg |= (div << shift);
-	omap_writew(reg, CK_RATE_REG(ck));
-
-	/* And return the new (actual, after rounding down) rate. */
-	ret = prate;
-
- exit:
-	spin_unlock_irqrestore(&clock_lock, flags);
-	return ret;
-}
-
-int
-ck_set_rate(ck_t ck, int rate)
-{
-	int ret = -EINVAL;
-
-	if (!CK_IN_RANGE(ck) || !CK_CAN_CHANGE_RATE(ck))
-		goto exit;
-
-	switch (ck) {
-
-	default:
-		ret = __ck_set_clkm_rate(ck, rate);
-		break;
-
-	case OMAP_CK_GEN1:
-		ret = __ck_set_pll_rate(ck, rate);
-		break;
-
-	};
-
- exit:
-	return ret;
-}
-
-static int
-__ck_get_pll_rate(ck_t ck)
-{
-	int m, d;
-
-	unsigned short pll = omap_readw(CK_RATE_REG(ck));
-
-	m = (pll & (0x1f << 7)) >> 7;
-	m = m ? m : 1;
-	d = (pll & (3 << 5)) >> 5;
-	d++;
-
-	return ((source_clock * m) / d);
-}
-
-static int
-__ck_get_clkm_rate(ck_t ck)
-{
-	static int bits2div[] = { 1, 2, 4, 8 };
-	int in, bits, reg, shift;
-
-	reg = omap_readw(CK_RATE_REG(ck));
-	shift = CK_RATE_SHIFT(ck);
-
-	in = ck_get_rate(CK_PARENT(ck));
-	bits = (reg & (3 << shift)) >> shift;
-
-	return (in / bits2div[bits]);
-}
-
-int
-ck_get_rate(ck_t ck)
-{
-	int ret = 0;
-	ck_t parent;
-
-	if (!CK_IN_RANGE(ck)) {
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	switch (ck) {
-
-	case OMAP_CK_GEN1:
-		ret = __ck_get_pll_rate(ck);
-		break;
-
-	case OMAP_CLKIN:
-		ret = source_clock;
-		break;
-
-	case OMAP_MPUXOR_CK:
-	case OMAP_CK_GEN2:
-	case OMAP_CK_GEN3:
-	case OMAP_ARM_GPIO_CK:
-		ret = ck_get_rate(CK_PARENT(ck));
-		break;
-
-	case OMAP_ARM_CK:
-	case OMAP_MPUPER_CK:
-	case OMAP_DSP_CK:
-	case OMAP_DSPMMU_CK:
-	case OMAP_LCD_CK:
-	case OMAP_TC_CK:
-	case OMAP_DMA_CK:
-	case OMAP_API_CK:
-	case OMAP_HSAB_CK:
-	case OMAP_LBFREE_CK:
-	case OMAP_LB_CK:
-		ret = __ck_get_clkm_rate(ck);
-		break;
-
-	case OMAP_MPUTIM_CK:
-		ck_get_input(ck, &parent);
-		ret = ck_get_rate(parent);
-		break;
-
-	case OMAP_MPUWD_CK:
-		/* Note that this evaluates to zero if source_clock is 12MHz. */
-		ret = source_clock / 14;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
- exit:
-	return ret;
-}
-
-int
-ck_enable(ck_t ck)
-{
-	unsigned short reg;
-	int ret = -EINVAL, shift;
-	unsigned long flags;
-
-	if (!CK_IN_RANGE(ck))
-		goto exit;
-
-	if (ck_debug)
-		printk(KERN_DEBUG "%s: %s\n", __FUNCTION__, CK_NAME(ck));
-
-	ret = 0;
-
-	if (!CK_CAN_DISABLE(ck))
-		/* Then it must be on... */
-		goto exit;
-
-	spin_lock_irqsave(&clock_lock, flags);
-	reg = omap_readw(CK_ENABLE_REG(ck));
-	shift = CK_ENABLE_SHIFT(ck);
-	reg |= (1 << shift);
-	omap_writew(reg, CK_ENABLE_REG(ck));
-	spin_unlock_irqrestore(&clock_lock, flags);
-
- exit:
-	return ret;
-}
-
-int
-ck_disable(ck_t ck)
-{
-	unsigned short reg;
-	int ret = -EINVAL, shift;
-	unsigned long flags;
-
-	if (!CK_IN_RANGE(ck))
-		goto exit;
-
-	if (ck_debug)
-		printk(KERN_DEBUG "%s: %s\n", __FUNCTION__, CK_NAME(ck));
-
-	if (!CK_CAN_DISABLE(ck))
-		goto exit;
-
-	ret = 0;
-
-	if (ck == OMAP_CLKIN)
-		return -EINVAL;
-
-	spin_lock_irqsave(&clock_lock, flags);
-	reg = omap_readw(CK_ENABLE_REG(ck));
-	shift = CK_ENABLE_SHIFT(ck);
-	reg &= ~(1 << shift);
-	omap_writew(reg, CK_ENABLE_REG(ck));
-	spin_unlock_irqrestore(&clock_lock, flags);
-
- exit:
-	return ret;
-}
-
-int ck_valid_rate(int rate)
-{
-	return test_bit(rate, (unsigned long *)&ck_valid_table);
-}
-
-static void
-__ck_make_lookup_table(void)
-{
-	__u8 m, d;
-
-	memset(ck_valid_table, 0, sizeof (ck_valid_table));
-
-	for (m = 1; m < 32; m++)
-		for (d = 1; d < 5; d++) {
-
-			int rate = ((source_clock * m) / (d));
-
-			if (rate > CK_MAX_PLL_FREQ)
-				continue;
-			if (test_bit(rate, (unsigned long *)&ck_valid_table))
-				continue;
-			set_bit(rate, (unsigned long *)&ck_valid_table);
-			ck_lookup_table[rate - 1] = (m << 2) | (d - 1);
-		}
-}
-
-int __init
-init_ck(void)
-{
-	const struct omap_clock_config *info;
-	int crystal_type = 0; /* Default 12 MHz */
-
-	__ck_make_lookup_table();
-	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
-	if (info != NULL) {
-		if (!cpu_is_omap1510())
-			crystal_type = info->system_clock_type;
-	}
-
-	/* We want to be in syncronous scalable mode */
-	omap_writew(0x1000, ARM_SYSST);
-#if defined(CONFIG_OMAP_ARM_30MHZ)
-	omap_writew(0x1555, ARM_CKCTL);
-	omap_writew(0x2290, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_60MHZ)
-	omap_writew(0x1005, ARM_CKCTL);
-	omap_writew(0x2290, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_96MHZ)
-	omap_writew(0x1005, ARM_CKCTL);
-	omap_writew(0x2410, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_120MHZ)
-	omap_writew(0x110a, ARM_CKCTL);
-	omap_writew(0x2510, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_168MHZ)
-	omap_writew(0x110f, ARM_CKCTL);
-	omap_writew(0x2710, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
-	omap_writew(0x250E, ARM_CKCTL);
-	omap_writew(0x2710, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
-					  || defined(CONFIG_ARCH_OMAP1710))
-	omap_writew(0x150f, ARM_CKCTL);
-	if (crystal_type == 2) {
-		source_clock = 13;	/* MHz */
-		omap_writew(0x2510, DPLL_CTL);
-	} else
-		omap_writew(0x2810, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_195MHZ) && defined(CONFIG_ARCH_OMAP730)
-	omap_writew(0x250E, ARM_CKCTL);
-	omap_writew(0x2790, DPLL_CTL);
-#else
-#error "OMAP MHZ not set, please run make xconfig"
-#endif
-
-#ifdef CONFIG_MACH_OMAP_PERSEUS2
-	/* Select slicer output as OMAP input clock */
-	omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL);
-#endif
-
-	/* Turn off some other junk the bootloader might have turned on */
-
-	/* Turn off DSP, ARM_INTHCK, ARM_TIMXO */
-	omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL);
-
-	/* Put DSP/MPUI into reset until needed */
-	omap_writew(0, ARM_RSTCT1);
-	omap_writew(1, ARM_RSTCT2);
-	omap_writew(0x400, ARM_IDLECT1);
-
-	/*
-	 * According to OMAP5910 Erratum SYS_DMA_1, bit DMACK_REQ (bit 8)
-	 * of the ARM_IDLECT2 register must be set to zero. The power-on
-	 * default value of this bit is one.
-	 */
-	omap_writew(0x0000, ARM_IDLECT2);	/* Turn LCD clock off also */
-
-	/*
-	 * Only enable those clocks we will need, let the drivers
-	 * enable other clocks as necessary
-	 */
-	ck_enable(OMAP_MPUPER_CK);
-	ck_enable(OMAP_ARM_GPIO_CK);
-	ck_enable(OMAP_MPUXOR_CK);
-	//ck_set_rate(OMAP_MPUTIM_CK, OMAP_CLKIN);
-	ck_enable(OMAP_MPUTIM_CK);
-	start_mputimer1(0xffffffff);
-
-	return 0;
-}
-
-
-EXPORT_SYMBOL(ck_get_rate);
-EXPORT_SYMBOL(ck_set_rate);
-EXPORT_SYMBOL(ck_enable);
-EXPORT_SYMBOL(ck_disable);
diff -Nru a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c
--- a/arch/arm/mach-omap/common.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-omap/common.c	2004-10-28 22:25:59 -07:00
@@ -14,65 +14,194 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
 
 #include <asm/hardware.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <asm/arch/clocks.h>
-#include <asm/arch/board.h>
+#include <asm/hardware/clock.h>
 #include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/serial.h>
+
+
+#include "clock.h"
+
+#define DEBUG 1
+
+struct omap_id {
+	u16	jtag_id;	/* Used to determine OMAP type */
+	u8	die_rev;	/* Processor revision */
+	u32	omap_id;	/* OMAP revision */
+	u32	type;		/* Cpu id bits [31:08], cpu class bits [07:00] */
+};
+
+/* Register values to detect the OMAP version */
+static struct omap_id omap_ids[] __initdata = {
+	{ .jtag_id = 0x355f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300100},
+	{ .jtag_id = 0xb55f, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x07300300},
+	{ .jtag_id = 0xb470, .die_rev = 0x0, .omap_id = 0x03310100, .type = 0x15100000},
+	{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320000, .type = 0x16100000},
+	{ .jtag_id = 0xb576, .die_rev = 0x2, .omap_id = 0x03320100, .type = 0x16110000},
+	{ .jtag_id = 0xb576, .die_rev = 0x3, .omap_id = 0x03320100, .type = 0x16100c00},
+	{ .jtag_id = 0xb576, .die_rev = 0x0, .omap_id = 0x03320200, .type = 0x16100d00},
+	{ .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
+	{ .jtag_id = 0xb613, .die_rev = 0x0, .omap_id = 0x03320300, .type = 0x1610ef00},
+	{ .jtag_id = 0xb576, .die_rev = 0x1, .omap_id = 0x03320100, .type = 0x16110000},
+	{ .jtag_id = 0xb58c, .die_rev = 0x2, .omap_id = 0x03320200, .type = 0x16110b00},
+	{ .jtag_id = 0xb58c, .die_rev = 0x3, .omap_id = 0x03320200, .type = 0x16110c00},
+	{ .jtag_id = 0xb65f, .die_rev = 0x0, .omap_id = 0x03320400, .type = 0x16212300},
+	{ .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320400, .type = 0x16212300},
+	{ .jtag_id = 0xb65f, .die_rev = 0x1, .omap_id = 0x03320500, .type = 0x16212300},
+	{ .jtag_id = 0xb5f7, .die_rev = 0x0, .omap_id = 0x03330000, .type = 0x17100000},
+	{ .jtag_id = 0xb5f7, .die_rev = 0x1, .omap_id = 0x03330100, .type = 0x17100000},
+	{ .jtag_id = 0xb5f7, .die_rev = 0x2, .omap_id = 0x03330100, .type = 0x17100000},
+};
 
 /*
- * ----------------------------------------------------------------------------
- * OMAP revision check
- *
- * Since we use the cpu_is_omapnnnn() macros, there's a chance that a board
- * switches to an updated core. We want to print out the OMAP revision early.
- *
- * We use the system_serial registers for the revision information so we
- * can see it in /proc/cpuinfo.
- *
- * If the OMAP detection gets more complicated, we may want to expand this
- * to store the OMAP version and replace the current cpu_is_omapnnnn() macros.
- *
- * ----------------------------------------------------------------------------
+ * Get OMAP type from PROD_ID.
+ * 1710 has the PROD_ID in bits 15:00, not in 16:01 as documented in TRM.
+ * 1510 PROD_ID is empty, and 1610 PROD_ID does not make sense.
+ * Undocumented register in TEST BLOCK is used as fallback; This seems to
+ * work on 1510, 1610 & 1710. The official way hopefully will work in future
+ * processors.
+ */
+static u16 __init omap_get_jtag_id(void)
+{
+	u32 prod_id, omap_id;
+
+	prod_id = omap_readl(OMAP_PRODUCTION_ID_1);
+	omap_id = omap_readl(OMAP32_ID_1);
+
+	/* Check for unusable OMAP_PRODUCTION_ID_1 on 1611B/5912 and 730 */
+	if (((prod_id >> 20) == 0) || (prod_id == omap_id))
+		prod_id = 0;
+	else
+		prod_id &= 0xffff;
+
+	if (prod_id)
+		return prod_id;
+
+	/* Use OMAP32_ID_1 as fallback */
+	prod_id = ((omap_id >> 12) & 0xffff);
+
+	return prod_id;
+}
+
+/*
+ * Get OMAP revision from DIE_REV.
+ * Early 1710 processors may have broken OMAP_DIE_ID, it contains PROD_ID.
+ * Undocumented register in the TEST BLOCK is used as fallback.
+ * REVISIT: This does not seem to work on 1510
  */
+static u8 __init omap_get_die_rev(void)
+{
+	u32 die_rev;
+
+	die_rev = omap_readl(OMAP_DIE_ID_1);
+
+	/* Check for broken OMAP_DIE_ID on early 1710 */
+	if (((die_rev >> 12) & 0xffff) == omap_get_jtag_id())
+		die_rev = 0;
+
+	die_rev = (die_rev >> 17) & 0xf;
+	if (die_rev)
+		return die_rev;
+
+	die_rev = (omap_readl(OMAP32_ID_1) >> 28) & 0xf;
+
+	return die_rev;
+}
+
 static void __init omap_check_revision(void)
 {
-	system_serial_high = omap_readl(OMAP_ID_BASE);
-	system_serial_low = OMAP_ID_REG;
-	system_rev = (OMAP_ID_REG >> ID_SHIFT) & ID_MASK;
-
-	printk("OMAP revision: %d.%d (0x%08x) id: 0x%08x detected as OMAP-",
-	       (system_serial_high >> 20) & 0xf,
-	       (system_serial_high >> 16) & 0xf,
-	       system_serial_high, system_serial_low);
-
-	switch (system_rev) {
-	case OMAP_ID_730:
-		printk("730\n");
-		system_rev = 0x730;
-		break;
-	case OMAP_ID_1510:
-		printk("1510\n");
-		system_rev = 0x1510;
+	int i;
+	u16 jtag_id;
+	u8 die_rev;
+	u32 omap_id;
+	u8 cpu_type;
+
+	jtag_id = omap_get_jtag_id();
+	die_rev = omap_get_die_rev();
+	omap_id = omap_readl(OMAP32_ID_0);
+
+#ifdef DEBUG
+	printk("OMAP_DIE_ID_0: 0x%08x\n", omap_readl(OMAP_DIE_ID_0));
+	printk("OMAP_DIE_ID_1: 0x%08x DIE_REV: %i\n",
+		omap_readl(OMAP_DIE_ID_1),
+	       (omap_readl(OMAP_DIE_ID_1) >> 17) & 0xf);
+	printk("OMAP_PRODUCTION_ID_0: 0x%08x\n", omap_readl(OMAP_PRODUCTION_ID_0));
+	printk("OMAP_PRODUCTION_ID_1: 0x%08x JTAG_ID: 0x%04x\n",
+		omap_readl(OMAP_PRODUCTION_ID_1),
+		omap_readl(OMAP_PRODUCTION_ID_1) & 0xffff);
+	printk("OMAP32_ID_0: 0x%08x\n", omap_readl(OMAP32_ID_0));
+	printk("OMAP32_ID_1: 0x%08x\n", omap_readl(OMAP32_ID_1));
+	printk("JTAG_ID: 0x%04x DIE_REV: %i\n", jtag_id, die_rev);
+#endif
+
+	system_serial_high = omap_readl(OMAP_DIE_ID_0);
+	system_serial_low = omap_readl(OMAP_DIE_ID_1);
+
+	/* First check only the major version in a safe way */
+	for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+		if (jtag_id == (omap_ids[i].jtag_id)) {
+			system_rev = omap_ids[i].type;
+			break;
+		}
+	}
+
+	/* Check if we can find the die revision */
+	for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+		if (jtag_id == omap_ids[i].jtag_id && die_rev == omap_ids[i].die_rev) {
+			system_rev = omap_ids[i].type;
+			break;
+		}
+	}
+
+	/* Finally check also the omap_id */
+	for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
+		if (jtag_id == omap_ids[i].jtag_id
+		    && die_rev == omap_ids[i].die_rev
+		    && omap_id == omap_ids[i].omap_id) {
+			system_rev = omap_ids[i].type;
+			break;
+		}
+	}
+
+	/* Add the cpu class info (7xx, 15xx, 16xx, 24xx) */
+	cpu_type = system_rev >> 24;
+
+	switch (cpu_type) {
+	case 0x07:
+		system_rev |= 0x07;
 		break;
-	case OMAP_ID_1610:
-		printk("1610\n");
-		system_rev = 0x1610;
+	case 0x15:
+		system_rev |= 0x15;
 		break;
-	case OMAP_ID_1710:
-		printk("1710\n");
-		system_rev = 0x1710;
+	case 0x16:
+	case 0x17:
+		system_rev |= 0x16;
 		break;
-	case OMAP_ID_5912:
-		printk("5912/1611B\n");
-		system_rev = 0x5912;
+	case 0x24:
+		system_rev |= 0x24;
 		break;
 	default:
-		printk("unknown, please add support!\n");
+		printk("Unknown OMAP cpu type: 0x%02x\n", cpu_type);
 	}
+
+	printk("OMAP%04x", system_rev >> 16);
+	if ((system_rev >> 8) & 0xff)
+		printk("%x", (system_rev >> 8) & 0xff);
+	printk(" revision %i handled as %02xxx id: %08x%08x\n",
+	       die_rev, system_rev & 0xff, system_serial_low,
+	       system_serial_high);
 }
 
 /*
@@ -104,25 +233,23 @@
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+#if defined(CONFIG_ARCH_OMAP16XX)
 static struct map_desc omap1610_io_desc[] __initdata = {
- { OMAP1610_DSP_BASE,    OMAP1610_DSP_START,    OMAP1610_DSP_SIZE,    MT_DEVICE },
- { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
- { OMAP1610_SRAM_BASE,   OMAP1610_SRAM_START,   OMAP1610_SRAM_SIZE,   MT_DEVICE }
+ { OMAP16XX_DSP_BASE,    OMAP16XX_DSP_START,    OMAP16XX_DSP_SIZE,    MT_DEVICE },
+ { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
+ { OMAP16XX_SRAM_BASE,   OMAP16XX_SRAM_START,   OMAP1610_SRAM_SIZE,   MT_DEVICE }
 };
-#endif
 
-#ifdef CONFIG_ARCH_OMAP5912
 static struct map_desc omap5912_io_desc[] __initdata = {
- { OMAP5912_DSP_BASE,    OMAP5912_DSP_START,    OMAP5912_DSP_SIZE,    MT_DEVICE },
- { OMAP5912_DSPREG_BASE, OMAP5912_DSPREG_START, OMAP5912_DSPREG_SIZE, MT_DEVICE },
+ { OMAP16XX_DSP_BASE,    OMAP16XX_DSP_START,    OMAP16XX_DSP_SIZE,    MT_DEVICE },
+ { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE },
 /*
  * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page
  * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped.
  * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte
  * can be used.
  */
- { OMAP5912_SRAM_BASE,   OMAP5912_SRAM_START,   OMAP5912_SRAM_SIZE + 0x800,   MT_DEVICE }
+ { OMAP16XX_SRAM_BASE,   OMAP16XX_SRAM_START,   OMAP5912_SRAM_SIZE + 0x800,   MT_DEVICE }
 };
 #endif
 
@@ -137,6 +264,9 @@
 	iotable_init(omap_io_desc, ARRAY_SIZE(omap_io_desc));
 	omap_check_revision();
 
+	/* clear BM to canonicalize CS0 (not CS3) at 0000:0000 */
+	omap_writel(omap_readl(EMIFS_CONFIG) & 0x0d, EMIFS_CONFIG);
+
 #ifdef CONFIG_ARCH_OMAP730
 	if (cpu_is_omap730()) {
 		iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc));
@@ -147,12 +277,10 @@
 		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+#if defined(CONFIG_ARCH_OMAP16XX)
 	if (cpu_is_omap1610() || cpu_is_omap1710()) {
 		iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
 	}
-#endif
-#ifdef CONFIG_ARCH_OMAP5912
 	if (cpu_is_omap5912()) {
 		iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc));
 	}
@@ -166,7 +294,7 @@
 
 	/* Must init clocks early to assure that timer interrupt works
 	 */
-	init_ck();
+	clk_init();
 }
 
 /*
@@ -178,26 +306,144 @@
 		_omap_map_io();
 }
 
+static struct uart_port omap_serial_ports[] = {
+	{
+		.membase	= (char*)IO_ADDRESS(OMAP_UART1_BASE),
+		.mapbase	= (unsigned long)OMAP_UART1_BASE,
+		.irq		= INT_UART1,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= OMAP16XX_BASE_BAUD * 16,
+		.line		= 0,
+		.type		= PORT_OMAP,
+		.fifosize	= 64
+	} , {
+		.membase	= (char*)IO_ADDRESS(OMAP_UART2_BASE),
+		.mapbase	= (unsigned long)OMAP_UART2_BASE,
+		.irq		= INT_UART2,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= OMAP16XX_BASE_BAUD * 16,
+		.line		= 1,
+		.type		= PORT_OMAP,
+		.fifosize	= 64
+	} , {
+		.membase	= (char*)IO_ADDRESS(OMAP_UART3_BASE),
+		.mapbase	= (unsigned long)OMAP_UART3_BASE,
+		.irq		= INT_UART3,
+		.flags		= UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= OMAP16XX_BASE_BAUD * 16,
+		.line		= 2,
+		.type		= PORT_OMAP,
+		.fifosize	= 64
+	}
+};
+
+/*
+ * Note that on Innovator-1510 UART2 pins conflict with USB2.
+ * By default UART2 does not work on Innovator-1510 if you have
+ * USB OHCI enabled. To use UART2, you must disable USB2 first.
+ */
+void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS])
+{
+	int i;
+
+	if (cpu_is_omap730()) {
+		omap_serial_ports[0].regshift = 0;
+		omap_serial_ports[1].regshift = 0;
+		omap_serial_ports[0].irq = INT_730_UART_MODEM_1;
+		omap_serial_ports[1].irq = INT_730_UART_MODEM_IRDA_2;
+	}
+
+	if (cpu_is_omap1510()) {
+		omap_serial_ports[0].uartclk = OMAP1510_BASE_BAUD * 16;
+		omap_serial_ports[1].uartclk = OMAP1510_BASE_BAUD * 16;
+		omap_serial_ports[2].uartclk = OMAP1510_BASE_BAUD * 16;
+	}
+
+	for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
+		unsigned long port;
+		unsigned char regshift;
+		unsigned char reg;
+
+		if (ports[i] != 1)
+			continue;
+
+		switch (i) {
+		case 0:
+			if (cpu_is_omap1510()) {
+				omap_cfg_reg(UART1_TX);
+				omap_cfg_reg(UART1_RTS);
+				if (machine_is_omap_innovator()) {
+					reg = fpga_read(OMAP1510_FPGA_POWER);
+					reg |= OMAP1510_FPGA_PCR_COM1_EN;
+					fpga_write(reg, OMAP1510_FPGA_POWER);
+					udelay(1);
+				}
+			}
+			break;
+		case 1:
+			if (cpu_is_omap1510()) {
+				omap_cfg_reg(UART2_TX);
+				omap_cfg_reg(UART2_RTS);
+				if (machine_is_omap_innovator()) {
+					reg = fpga_read(OMAP1510_FPGA_POWER);
+					reg |= OMAP1510_FPGA_PCR_COM2_EN;
+					fpga_write(reg, OMAP1510_FPGA_POWER);
+					udelay(1);
+				}
+			}
+			break;
+		case 2:
+			if (cpu_is_omap1510()) {
+				omap_cfg_reg(UART3_TX);
+				omap_cfg_reg(UART3_RX);
+			}
+			break;
+		}
+
+		/* Reset port */
+		if (!cpu_is_omap1510()) {
+			port = (unsigned long)omap_serial_ports[i].membase;
+			regshift = omap_serial_ports[i].regshift;
+			writeb(0x01, port + (UART_SYSC << regshift));
+			while (!(readb(port + (UART_SYSC << regshift)) & 0x01));
+		}
+
+		//early_serial_setup(&omap_serial_ports[i]);
+	}
+}
+
+#define NO_LENGTH_CHECK 0xffffffff
+
 extern int omap_bootloader_tag_len;
 extern u8 omap_bootloader_tag[];
 
 struct omap_board_config_kernel *omap_board_config;
 int omap_board_config_size = 0;
 
-const void *__omap_get_config(u16 tag, size_t len)
+static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
 {
-	struct omap_board_config_entry *info = NULL;
 	struct omap_board_config_kernel *kinfo = NULL;
 	int i;
 
 #ifdef CONFIG_OMAP_BOOT_TAG
+	struct omap_board_config_entry *info = NULL;
+
 	if (omap_bootloader_tag_len > 4)
 		info = (struct omap_board_config_entry *) omap_bootloader_tag;
 	while (info != NULL) {
 		u8 *next;
 
-		if (info->tag == tag)
-			break;
+		if (info->tag == tag) {
+			if (skip == 0)
+				break;
+			skip--;
+		}
 
 		next = (u8 *) info + sizeof(*info) + info->len;
 		if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
@@ -208,11 +454,13 @@
 	if (info != NULL) {
 		/* Check the length as a lame attempt to check for
 		 * binary inconsistancy. */
-		if (info->len != len) {
+		if (len != NO_LENGTH_CHECK && info->len != len) {
 			printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
 			       tag, len, info->len);
 			return NULL;
 		}
+		if (len_out != NULL)
+			*len_out = info->len;
 		return info->data;
 	}
 #endif
@@ -228,7 +476,18 @@
 		return NULL;
 	return kinfo->data;
 }
+
+const void *__omap_get_config(u16 tag, size_t len, int nr)
+{
+        return get_config(tag, len, nr, NULL);
+}
 EXPORT_SYMBOL(__omap_get_config);
+
+const void *omap_get_var_config(u16 tag, size_t *len)
+{
+        return get_config(tag, NO_LENGTH_CHECK, 0, len);
+}
+EXPORT_SYMBOL(omap_get_var_config);
 
 static int __init omap_add_serial_console(void)
 {
diff -Nru a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h
--- a/arch/arm/mach-omap/common.h	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-omap/common.h	2004-10-28 22:25:58 -07:00
@@ -31,5 +31,6 @@
 
 extern void omap_map_io(void);
 extern struct sys_timer omap_timer;
+extern void omap_serial_init(int ports[]);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
diff -Nru a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c
--- a/arch/arm/mach-omap/dma.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-omap/dma.c	2004-10-28 22:25:59 -07:00
@@ -4,6 +4,8 @@
  * Copyright (C) 2003 Nokia Corporation
  * Author: Juha Yrjölä <juha.yrjola@nokia.com>
  * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
+ * Graphics DMA and LCD DMA graphics tranformations
+ * by Imre Deak <imre.deak@nokia.com>
  *
  * Support functions for the OMAP internal DMA channels.
  *
@@ -26,6 +28,8 @@
 #include <asm/dma.h>
 #include <asm/io.h>
 
+#include <asm/arch/tc.h>
+
 #define OMAP_DMA_ACTIVE		0x01
 
 #define OMAP_DMA_CCR_EN		(1 << 7)
@@ -87,6 +91,34 @@
 		omap_writew(0, lch_base + i);
 }
 
+void omap_set_dma_priority(int dst_port, int priority)
+{
+	unsigned long reg;
+	u32 l;
+
+	switch (dst_port) {
+	case OMAP_DMA_PORT_OCP_T1:	/* FFFECC00 */
+		reg = OMAP_TC_OCPT1_PRIOR;
+		break;
+	case OMAP_DMA_PORT_OCP_T2:	/* FFFECCD0 */
+		reg = OMAP_TC_OCPT2_PRIOR;
+		break;
+	case OMAP_DMA_PORT_EMIFF:	/* FFFECC08 */
+		reg = OMAP_TC_EMIFF_PRIOR;
+		break;
+	case OMAP_DMA_PORT_EMIFS:	/* FFFECC04 */
+		reg = OMAP_TC_EMIFS_PRIOR;
+		break;
+	default:
+		BUG();
+		return;
+	}
+	l = omap_readl(reg);
+	l &= ~(0xf << 8);
+	l |= (priority & 0xf) << 8;
+	omap_writel(l, reg);
+}
+
 void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
 				  int frame_count, int sync_mode)
 {
@@ -113,51 +145,38 @@
 	omap_writew(frame_count, OMAP_DMA_CFN(lch));
 
 }
-void omap_set_dma_constant_fill(int lch, u32 color)
+void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
 {
 	u16 w;
 
-#ifdef CONFIG_DEBUG_KERNEL
-	if (omap_dma_in_1510_mode()) {
-		printk(KERN_ERR "OMAP DMA constant fill not available in 1510 mode.");
-		BUG();
-		return;
-	}
-#endif
-	w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03;
-	w |= 0x01;
-	omap_writew(w, OMAP_DMA_CCR2(lch));
-
-	omap_writew((u16)color, OMAP_DMA_COLOR_L(lch));
-	omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch));
-
-	w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f;
-	w |= 1;		/* Channel type G */
-	omap_writew(w, OMAP_DMA_LCH_CTRL(lch));
-}
-
-void omap_set_dma_transparent_copy(int lch, u32 color)
-{
-	u16 w;
+	BUG_ON(omap_dma_in_1510_mode());
 
-#ifdef CONFIG_DEBUG_KERNEL
-	if (omap_dma_in_1510_mode()) {
-		printk(KERN_ERR "OMAP DMA transparent copy not available in 1510 mode.");
+	w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03;
+	switch (mode) {
+	case OMAP_DMA_CONSTANT_FILL:
+		w |= 0x01;
+		break;
+	case OMAP_DMA_TRANSPARENT_COPY:
+		w |= 0x02;
+		break;
+	case OMAP_DMA_COLOR_DIS:
+		break;
+	default:
 		BUG();
 	}
-#endif
-	w = omap_readw(OMAP_DMA_CCR2(lch)) & ~0x03;
-	w |= 0x02;
 	omap_writew(w, OMAP_DMA_CCR2(lch));
 
-	omap_writew((u16)color, OMAP_DMA_COLOR_L(lch));
-	omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch));
-
 	w = omap_readw(OMAP_DMA_LCH_CTRL(lch)) & ~0x0f;
-	w |= 1;		/* Channel type G */
+	/* Default is channel type 2D */
+	if (mode) {
+		omap_writew((u16)color, OMAP_DMA_COLOR_L(lch));
+		omap_writew((u16)(color >> 16), OMAP_DMA_COLOR_U(lch));
+		w |= 1;		/* Channel type G */
+	}
 	omap_writew(w, OMAP_DMA_LCH_CTRL(lch));
 }
 
+
 void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 			     unsigned long src_start)
 {
@@ -192,22 +211,24 @@
 	omap_writew(w, OMAP_DMA_CSDP(lch));
 }
 
-void omap_set_dma_src_burst_mode(int lch, int burst_mode)
+void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 {
 	u16 w;
 
 	w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 7);
 	switch (burst_mode) {
+	case OMAP_DMA_DATA_BURST_DIS:
+		break;
 	case OMAP_DMA_DATA_BURST_4:
 		w |= (0x01 << 7);
 		break;
 	case OMAP_DMA_DATA_BURST_8:
-		w |= (0x03 << 7);
-		break;
+		/* not supported by current hardware
+		 * w |= (0x03 << 7);
+		 * fall through
+		 */
 	default:
-		printk(KERN_ERR "Invalid DMA burst mode\n");
 		BUG();
-		return;
 	}
 	omap_writew(w, OMAP_DMA_CSDP(lch));
 }
@@ -246,12 +267,14 @@
 	omap_writew(w, OMAP_DMA_CSDP(lch));
 }
 
-void omap_set_dma_dest_burst_mode(int lch, int burst_mode)
+void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
 {
 	u16 w;
 
 	w = omap_readw(OMAP_DMA_CSDP(lch)) & ~(0x03 << 14);
 	switch (burst_mode) {
+	case OMAP_DMA_DATA_BURST_DIS:
+		break;
 	case OMAP_DMA_DATA_BURST_4:
 		w |= (0x01 << 14);
 		break;
@@ -474,7 +497,7 @@
 	chan->data = data;
 	chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
 
-	if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
+	if (cpu_is_omap16xx() || cpu_is_omap730()) {
 		/* If the sync device is set, configure it dynamically. */
 		if (dev_id != 0) {
 			set_gdma_dev(free_ch + 1, dev_id);
@@ -571,8 +594,15 @@
 	void (* callback)(u16 status, void *data);
 	void *cb_data;
 
+	int active;
 	unsigned long addr, size;
 	int rotate, data_type, xres, yres;
+	int vxres;
+	int mirror;
+	int xscale, yscale;
+	int ext_ctrl;
+	int src_port;
+	int single_transfer;
 } lcd_dma;
 
 void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
@@ -584,14 +614,70 @@
 	lcd_dma.yres = fb_yres;
 }
 
+void omap_set_lcd_dma_src_port(int port)
+{
+	lcd_dma.src_port = port;
+}
+
+void omap_set_lcd_dma_ext_controller(int external)
+{
+	lcd_dma.ext_ctrl = external;
+}
+
+void omap_set_lcd_dma_single_transfer(int single)
+{
+	lcd_dma.single_transfer = single;
+}
+
+
+void omap_set_lcd_dma_b1_rotation(int rotate)
+{
+	if (omap_dma_in_1510_mode()) {
+		printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");
+		BUG();
+		return;
+	}
+	lcd_dma.rotate = rotate;
+}
+
+void omap_set_lcd_dma_b1_mirror(int mirror)
+{
+	if (omap_dma_in_1510_mode()) {
+		printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n");
+		BUG();
+	}
+	lcd_dma.mirror = mirror;
+}
+
+void omap_set_lcd_dma_b1_vxres(unsigned long vxres)
+{
+	if (omap_dma_in_1510_mode()) {
+		printk(KERN_ERR "DMA virtual resulotion is not supported "
+				"in 1510 mode\n");
+		BUG();
+	}
+	lcd_dma.vxres = vxres;
+}
+
+void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale)
+{
+	if (omap_dma_in_1510_mode()) {
+		printk(KERN_ERR "DMA scale is not supported in 1510 mode\n");
+		BUG();
+	}
+	lcd_dma.xscale = xscale;
+	lcd_dma.yscale = yscale;
+}
+
 static void set_b1_regs(void)
 {
 	unsigned long top, bottom;
 	int es;
-	u16 w, en, fn;
-	s16 ei;
-	s32 fi;
-	u32 l;
+	u16 w;
+	unsigned long en, fn;
+	long ei, fi;
+	unsigned long vxres;
+	unsigned int xscale, yscale;
 
 	switch (lcd_dma.data_type) {
 	case OMAP_DMA_DATA_TYPE_S8:
@@ -608,25 +694,81 @@
 		return;
 	}
 
-	if (lcd_dma.rotate == 0) {
-		top = lcd_dma.addr;
-		bottom = lcd_dma.addr + (lcd_dma.xres * lcd_dma.yres - 1) * es;
-		/* 1510 DMA requires the bottom address to be 2 more than the
-		 * actual last memory access location. */
-		if (omap_dma_in_1510_mode() &&
-		    lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)
-			bottom += 2;
+	vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres;
+	xscale = lcd_dma.xscale ? lcd_dma.xscale : 1;
+	yscale = lcd_dma.yscale ? lcd_dma.yscale : 1;
+	BUG_ON(vxres < lcd_dma.xres);
+#define PIXADDR(x,y) (lcd_dma.addr + ((y) * vxres * yscale + (x) * xscale) * es)
+#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1)
+	switch (lcd_dma.rotate) {
+	case 0:
+		if (!lcd_dma.mirror) {
+			top = PIXADDR(0, 0);
+			bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+			/* 1510 DMA requires the bottom address to be 2 more
+			 * than the actual last memory access location. */
+			if (omap_dma_in_1510_mode() &&
+			    lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32)
+				bottom += 2;
+			ei = PIXSTEP(0, 0, 1, 0);
+			fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1);
+		} else {
+			top = PIXADDR(lcd_dma.xres - 1, 0);
+			bottom = PIXADDR(0, lcd_dma.yres - 1);
+			ei = PIXSTEP(1, 0, 0, 0);
+			fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1);
+		}
 		en = lcd_dma.xres;
 		fn = lcd_dma.yres;
-		ei = 0;
-		fi = 0;
-	} else {
-		top = lcd_dma.addr + (lcd_dma.xres - 1) * es;
-		bottom = lcd_dma.addr + (lcd_dma.yres - 1) * lcd_dma.xres * es;
+		break;
+	case 90:
+		if (!lcd_dma.mirror) {
+			top = PIXADDR(0, lcd_dma.yres - 1);
+			bottom = PIXADDR(lcd_dma.xres - 1, 0);
+			ei = PIXSTEP(0, 1, 0, 0);
+			fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1);
+		} else {
+			top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+			bottom = PIXADDR(0, 0);
+			ei = PIXSTEP(0, 1, 0, 0);
+			fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1);
+		}
+		en = lcd_dma.yres;
+		fn = lcd_dma.xres;
+		break;
+	case 180:
+		if (!lcd_dma.mirror) {
+			top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+			bottom = PIXADDR(0, 0);
+			ei = PIXSTEP(1, 0, 0, 0);
+			fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0);
+		} else {
+			top = PIXADDR(0, lcd_dma.yres - 1);
+			bottom = PIXADDR(lcd_dma.xres - 1, 0);
+			ei = PIXSTEP(0, 0, 1, 0);
+			fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0);
+		}
+		en = lcd_dma.xres;
+		fn = lcd_dma.yres;
+		break;
+	case 270:
+		if (!lcd_dma.mirror) {
+			top = PIXADDR(lcd_dma.xres - 1, 0);
+			bottom = PIXADDR(0, lcd_dma.yres - 1);
+			ei = PIXSTEP(0, 0, 0, 1);
+			fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0);
+		} else {
+			top = PIXADDR(0, 0);
+			bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1);
+			ei = PIXSTEP(0, 0, 0, 1);
+			fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0);
+		}
 		en = lcd_dma.yres;
 		fn = lcd_dma.xres;
-		ei = (lcd_dma.xres - 1) * es + 1;
-		fi = -(lcd_dma.xres * (lcd_dma.yres - 1) + 2) * 2 + 1;
+		break;
+	default:
+		BUG();
+		return;	/* Supress warning about uninitialized vars */
 	}
 
 	if (omap_dma_in_1510_mode()) {
@@ -652,33 +794,50 @@
 	w |= lcd_dma.data_type;
 	omap_writew(w, OMAP1610_DMA_LCD_CSDP);
 
-	if (!lcd_dma.rotate)
-		return;
+	w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+	/* Always set the source port as SDRAM for now*/
+	w &= ~(0x03 << 6);
+	if (lcd_dma.ext_ctrl)
+		w |= 1 << 8;
+	else
+		w &= ~(1 << 8);
+	if (lcd_dma.callback != NULL)
+		w |= 1 << 1;            /* Block interrupt enable */
+	else
+		w &= ~(1 << 1);
+	omap_writew(w, OMAP1610_DMA_LCD_CTRL);
 
-	/* Rotation stuff */
-	l = omap_readw(OMAP1610_DMA_LCD_CSDP);
-	/* Disable burst access */
-	l &= ~(0x03 << 7);
-	omap_writew(l, OMAP1610_DMA_LCD_CSDP);
+	if (!(lcd_dma.rotate || lcd_dma.mirror ||
+	      lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale))
+		return;
 
-	l = omap_readw(OMAP1610_DMA_LCD_CCR);
+	w = omap_readw(OMAP1610_DMA_LCD_CCR);
 	/* Set the double-indexed addressing mode */
-	l |= (0x03 << 12);
-	omap_writew(l, OMAP1610_DMA_LCD_CCR);
+	w |= (0x03 << 12);
+	omap_writew(w, OMAP1610_DMA_LCD_CCR);
 
 	omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1);
 	omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U);
 	omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L);
 }
 
-void omap_set_lcd_dma_b1_rotation(int rotate)
+static irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
-	if (omap_dma_in_1510_mode()) {
-		printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n");
-		BUG();
-		return;
-	}
-	lcd_dma.rotate = rotate;
+	u16 w;
+
+	w = omap_readw(OMAP1610_DMA_LCD_CTRL);
+	if (unlikely(!(w & (1 << 3)))) {
+		printk(KERN_WARNING "Spurious LCD DMA IRQ\n");
+		return IRQ_NONE;
+	}
+	/* Ack the IRQ */
+	w |= (1 << 3);
+	omap_writew(w, OMAP1610_DMA_LCD_CTRL);
+	lcd_dma.active = 0;
+	if (lcd_dma.callback != NULL)
+		lcd_dma.callback(w, lcd_dma.cb_data);
+
+	return IRQ_HANDLED;
 }
 
 int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
@@ -695,6 +854,15 @@
 	spin_unlock_irq(&lcd_dma.lock);
 	lcd_dma.callback = callback;
 	lcd_dma.cb_data = data;
+	lcd_dma.active = 0;
+	lcd_dma.single_transfer = 0;
+	lcd_dma.rotate = 0;
+	lcd_dma.vxres = 0;
+	lcd_dma.mirror = 0;
+	lcd_dma.xscale = 0;
+	lcd_dma.yscale = 0;
+	lcd_dma.ext_ctrl = 0;
+	lcd_dma.src_port = 0;
 
 	return 0;
 }
@@ -714,23 +882,53 @@
 	spin_unlock(&lcd_dma.lock);
 }
 
-void omap_start_lcd_dma(void)
+void omap_enable_lcd_dma(void)
 {
+	u16 w;
+
+	/* Set the Enable bit only if an external controller is
+	 * connected. Otherwise the OMAP internal controller will
+	 * start the transfer when it gets enabled.
+	 */
+	if (enable_1510_mode || !lcd_dma.ext_ctrl)
+		return;
+	w = omap_readw(OMAP1610_DMA_LCD_CCR);
+	w |= 1 << 7;
+	omap_writew(w, OMAP1610_DMA_LCD_CCR);
+	lcd_dma.active = 1;
+}
+
+void omap_setup_lcd_dma(void)
+{
+	BUG_ON(lcd_dma.active);
 	if (!enable_1510_mode) {
 		/* Set some reasonable defaults */
+		omap_writew(0x5440, OMAP1610_DMA_LCD_CCR);
 		omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP);
 		omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL);
-		omap_writew(0x5740, OMAP1610_DMA_LCD_CCR);
 	}
 	set_b1_regs();
-	if (!enable_1510_mode)
-		omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) | 1, OMAP1610_DMA_LCD_CCR);
+	if (!enable_1510_mode) {
+		u16 w;
+
+		w = omap_readw(OMAP1610_DMA_LCD_CCR);
+		/* If DMA was already active set the end_prog bit to have
+		 * the programmed register set loaded into the active
+		 * register set.
+		 */
+		w |= 1 << 11;		/* End_prog */
+		if (!lcd_dma.single_transfer)
+	        	w |= (3 << 8);	/* Auto_init, repeat */
+		omap_writew(w, OMAP1610_DMA_LCD_CCR);
+	}
 }
 
 void omap_stop_lcd_dma(void)
 {
-	if (!enable_1510_mode)
-		omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR);
+	lcd_dma.active = 0;
+	if (!enable_1510_mode && lcd_dma.ext_ctrl)
+		omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~(1 << 7),
+			    OMAP1610_DMA_LCD_CCR);
 }
 
 static int __init omap_init_dma(void)
@@ -741,7 +939,7 @@
 		printk(KERN_INFO "DMA support for OMAP1510 initialized\n");
 		dma_chan_count = 9;
 		enable_1510_mode = 1;
-	} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
+	} else if (cpu_is_omap16xx() || cpu_is_omap730()) {
 		printk(KERN_INFO "OMAP DMA hardware version %d\n",
 		       omap_readw(OMAP_DMA_HW_ID));
 		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
@@ -756,7 +954,7 @@
 			w = omap_readw(OMAP_DMA_GSCR);
 			w |= 1 << 3;
 			omap_writew(w, OMAP_DMA_GSCR);
-			dma_chan_count = OMAP_LOGICAL_DMA_CH_COUNT;
+			dma_chan_count = 16;
 		} else
 			dma_chan_count = 9;
 	} else {
@@ -790,11 +988,21 @@
 			return r;
 		}
 	}
-
+	r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, "LCD DMA", NULL);
+	if (r != 0) {
+		int i;
+
+		printk(KERN_ERR "unable to request IRQ for LCD DMA (error %d)\n", r);
+		for (i = 0; i < dma_chan_count; i++)
+			free_irq(dma_irq[i], (void *) (i + 1));
+		return r;
+	}
 	return 0;
 }
 arch_initcall(omap_init_dma);
 
+
+EXPORT_SYMBOL(omap_set_dma_priority);
 EXPORT_SYMBOL(omap_request_dma);
 EXPORT_SYMBOL(omap_free_dma);
 EXPORT_SYMBOL(omap_start_dma);
@@ -803,8 +1011,7 @@
 EXPORT_SYMBOL(omap_disable_dma_irq);
 
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
-EXPORT_SYMBOL(omap_set_dma_constant_fill);
-EXPORT_SYMBOL(omap_set_dma_transparent_copy);
+EXPORT_SYMBOL(omap_set_dma_color_mode);
 
 EXPORT_SYMBOL(omap_set_dma_src_params);
 EXPORT_SYMBOL(omap_set_dma_src_index);
@@ -821,7 +1028,14 @@
 
 EXPORT_SYMBOL(omap_request_lcd_dma);
 EXPORT_SYMBOL(omap_free_lcd_dma);
-EXPORT_SYMBOL(omap_start_lcd_dma);
+EXPORT_SYMBOL(omap_enable_lcd_dma);
+EXPORT_SYMBOL(omap_setup_lcd_dma);
 EXPORT_SYMBOL(omap_stop_lcd_dma);
 EXPORT_SYMBOL(omap_set_lcd_dma_b1);
+EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer);
+EXPORT_SYMBOL(omap_set_lcd_dma_ext_controller);
 EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation);
+EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres);
+EXPORT_SYMBOL(omap_set_lcd_dma_b1_scale);
+EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror);
+
diff -Nru a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c
--- a/arch/arm/mach-omap/gpio.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-omap/gpio.c	2004-10-28 22:25:58 -07:00
@@ -94,7 +94,7 @@
 #define METHOD_GPIO_1610	2
 #define METHOD_GPIO_730		3
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP16XX)
 static struct gpio_bank gpio_bank_1610[5] = {
 	{ OMAP_MPUIO_BASE,     INT_MPUIO,	    IH_MPUIO_BASE,     METHOD_MPUIO},
 	{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1,	    IH_GPIO_BASE,      METHOD_GPIO_1610 },
@@ -135,8 +135,8 @@
 		return &gpio_bank[1];
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP16XX)
+	if (cpu_is_omap16xx()) {
 		if (OMAP_GPIO_IS_MPUIO(gpio))
 			return &gpio_bank[0];
 		return &gpio_bank[1 + (gpio >> 4)];
@@ -172,8 +172,8 @@
 	if (cpu_is_omap1510() && gpio < 16)
 		return 0;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
-	if ((cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) && gpio < 64)
+#if defined(CONFIG_ARCH_OMAP16XX)
+	if ((cpu_is_omap16xx()) && gpio < 64)
 		return 0;
 #endif
 #ifdef CONFIG_ARCH_OMAP730
@@ -554,7 +554,7 @@
 	if (bank->method == METHOD_GPIO_1510)
 		isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP16XX)
 	if (bank->method == METHOD_GPIO_1610)
 		isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
 #endif
@@ -588,7 +588,7 @@
 	if (bank->method == METHOD_GPIO_1510)
 		__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS);
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP16XX)
 	if (bank->method == METHOD_GPIO_1610)
 		__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1);
 #endif
@@ -668,8 +668,8 @@
 		gpio_bank = gpio_bank_1510;
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP16XX)
+	if (cpu_is_omap16xx()) {
 		int rev;
 
 		gpio_bank_count = 5;
@@ -702,7 +702,7 @@
 			__raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
 		}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP16XX)
 		if (bank->method == METHOD_GPIO_1610) {
 			__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
 			__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
@@ -722,7 +722,7 @@
 				set_irq_chip(j, &mpuio_irq_chip);
 			else
 				set_irq_chip(j, &gpio_irq_chip);
-			set_irq_handler(j, do_level_IRQ);
+			set_irq_handler(j, do_edge_IRQ);
 			set_irq_flags(j, IRQF_VALID);
 		}
 		set_irq_chained_handler(bank->irq, gpio_irq_handler);
diff -Nru a/arch/arm/mach-omap/irq.c b/arch/arm/mach-omap/irq.c
--- a/arch/arm/mach-omap/irq.c	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-omap/irq.c	2004-10-28 22:25:57 -07:00
@@ -140,12 +140,11 @@
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
-				  || defined(CONFIG_ARCH_OMAP1710)
+#if defined(CONFIG_ARCH_OMAP16XX)
 
 static struct omap_irq_bank omap1610_irq_banks[] = {
 	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3fefe8f },
-	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfffff7ff },
+	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfdb7c1fd },
 	{ .base_reg = OMAP_IH2_BASE + 0x100,	.trigger_map = 0xfffff7ff },
 	{ .base_reg = OMAP_IH2_BASE + 0x200,	.trigger_map = 0xffffffff },
 };
@@ -173,9 +172,8 @@
 		irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
-				  || defined(CONFIG_ARCH_OMAP1710)
-	if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+#if defined(CONFIG_ARCH_OMAP16XX)
+	if (cpu_is_omap16xx()) {
 		irq_banks = omap1610_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
 	}
diff -Nru a/arch/arm/mach-omap/mcbsp.c b/arch/arm/mach-omap/mcbsp.c
--- a/arch/arm/mach-omap/mcbsp.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-omap/mcbsp.c	2004-10-28 22:25:58 -07:00
@@ -18,6 +18,7 @@
 #include <linux/wait.h>
 #include <linux/completion.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 
 #include <asm/delay.h>
 #include <asm/io.h>
@@ -28,6 +29,8 @@
 #include <asm/arch/irqs.h>
 #include <asm/arch/mcbsp.h>
 
+#include <asm/hardware/clock.h>
+
 #ifdef CONFIG_MCBSP_DEBUG
 #define DBG(x...)	printk(x)
 #else
@@ -61,6 +64,8 @@
 };
 
 static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
+static struct clk *mcbsp_dsp_ck = 0;
+static struct clk *mcbsp_api_ck = 0;
 
 
 static void omap_mcbsp_dump_reg(u8 id)
@@ -153,8 +158,8 @@
 	OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
 	OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
 	OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
-	OMAP_MCBSP_WRITE(io_base, SRGR2, config->mcr2);
-	OMAP_MCBSP_WRITE(io_base, SRGR1, config->mcr1);
+	OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
+	OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
 	OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
 }
 
@@ -181,6 +186,7 @@
 	return -1;
 }
 
+#define EN_XORPCK		1
 #define DSP_RSTCT2              0xe1008014
 
 static void omap_mcbsp_dsp_request(void)
@@ -188,10 +194,8 @@
 	if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {
 		omap_writew((omap_readw(ARM_RSTCT1) | (1 << 1) | (1 << 2)),
 			    ARM_RSTCT1);
-		omap_writew((omap_readw(ARM_CKCTL) | 1 << EN_DSPCK),
-			    ARM_CKCTL);
-		omap_writew((omap_readw(ARM_IDLECT2) | (1 << EN_APICK)),
-			    ARM_IDLECT2);
+		clk_enable(mcbsp_dsp_ck);
+		clk_enable(mcbsp_api_ck);
 
 		/* enable 12MHz clock to mcbsp 1 & 3 */
 		__raw_writew(__raw_readw(DSP_IDLECT2) | (1 << EN_XORPCK),
@@ -588,7 +592,7 @@
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+#if defined(CONFIG_ARCH_OMAP16XX)
 static const struct omap_mcbsp_info mcbsp_1610[] = {
 	[0] = { .virt_base = OMAP1610_MCBSP1_BASE,
 		.dma_rx_sync = OMAP_DMA_MCBSP1_RX,
@@ -614,6 +618,18 @@
 	static const struct omap_mcbsp_info *mcbsp_info;
 
 	printk("Initializing OMAP McBSP system\n");
+
+	mcbsp_dsp_ck = clk_get(0, "dsp_ck");
+	if (IS_ERR(mcbsp_dsp_ck)) {
+		printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
+		return PTR_ERR(mcbsp_dsp_ck);
+	}
+	mcbsp_api_ck = clk_get(0, "api_ck");
+	if (IS_ERR(mcbsp_dsp_ck)) {
+		printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");
+		return PTR_ERR(mcbsp_api_ck);
+	}
+
 #ifdef CONFIG_ARCH_OMAP730
 	if (cpu_is_omap730()) {
 		mcbsp_info = mcbsp_730;
@@ -626,7 +642,7 @@
 		mcbsp_count = ARRAY_SIZE(mcbsp_1510);
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+#if defined(CONFIG_ARCH_OMAP16XX)
 	if (cpu_is_omap1610() || cpu_is_omap1710()) {
 		mcbsp_info = mcbsp_1610;
 		mcbsp_count = ARRAY_SIZE(mcbsp_1610);
diff -Nru a/arch/arm/mach-omap/mux.c b/arch/arm/mach-omap/mux.c
--- a/arch/arm/mach-omap/mux.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-omap/mux.c	2004-10-28 22:25:59 -07:00
@@ -32,18 +32,26 @@
 #define __MUX_C__
 #include <asm/arch/mux.h>
 
+#ifdef CONFIG_OMAP_MUX
+
 /*
  * Sets the Omap MUX and PULL_DWN registers based on the table
  */
-int omap_cfg_reg(const reg_cfg_t reg_cfg)
+int __init_or_module
+omap_cfg_reg(const reg_cfg_t reg_cfg)
 {
-#ifdef CONFIG_OMAP_MUX
 	static spinlock_t mux_spin_lock = SPIN_LOCK_UNLOCKED;
 
 	unsigned long flags;
 	reg_cfg_set *cfg;
 	unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
 		pull_orig = 0, pull = 0;
+	unsigned int mask, warn = 0;
+
+	if (reg_cfg > ARRAY_SIZE(reg_cfg_table)) {
+		printk(KERN_ERR "MUX: reg_cfg %d\n", reg_cfg);
+		return -EINVAL;
+	}
 
 	cfg = &reg_cfg_table[reg_cfg];
 
@@ -56,12 +64,20 @@
 
 	/* Check the mux register in question */
 	if (cfg->mux_reg) {
+		unsigned	tmp1, tmp2;
+
 		reg_orig = omap_readl(cfg->mux_reg);
 
 		/* The mux registers always seem to be 3 bits long */
-		reg = reg_orig & ~(0x7 << cfg->mask_offset);
+		mask = (0x7 << cfg->mask_offset);
+		tmp1 = reg_orig & mask;
+		reg = reg_orig & ~mask;
+
+		tmp2 = (cfg->mask << cfg->mask_offset);
+		reg |= tmp2;
 
-		reg |= (cfg->mask << cfg->mask_offset);
+		if (tmp1 != tmp2)
+			warn = 1;
 
 		omap_writel(reg, cfg->mux_reg);
 	}
@@ -70,12 +86,18 @@
 	if (!cpu_is_omap1510()) {
 		if (cfg->pu_pd_reg && cfg->pull_val) {
 			pu_pd_orig = omap_readl(cfg->pu_pd_reg);
+			mask = 1 << cfg->pull_bit;
+
 			if (cfg->pu_pd_val) {
+				if (!(pu_pd_orig & mask))
+					warn = 1;
 				/* Use pull up */
-				pu_pd = pu_pd_orig | (1 << cfg->pull_bit);
+				pu_pd = pu_pd_orig | mask;
 			} else {
+				if (pu_pd_orig & mask)
+					warn = 1;
 				/* Use pull down */
-				pu_pd = pu_pd_orig & ~(1 << cfg->pull_bit);
+				pu_pd = pu_pd_orig & ~mask;
 			}
 			omap_writel(pu_pd, cfg->pu_pd_reg);
 		}
@@ -84,21 +106,32 @@
 	/* Check for an associated pull down register */
 	if (cfg->pull_reg) {
 		pull_orig = omap_readl(cfg->pull_reg);
+		mask = 1 << cfg->pull_bit;
 
 		if (cfg->pull_val) {
+			if (pull_orig & mask)
+				warn = 1;
 			/* Low bit = pull enabled */
-			pull = pull_orig & ~(1 << cfg->pull_bit);
+			pull = pull_orig & ~mask;
 		} else {
+			if (!(pull_orig & mask))
+				warn = 1;
 			/* High bit = pull disabled */
-			pull = pull_orig | (1 << cfg->pull_bit);
+			pull = pull_orig | mask;
 		}
 
 		omap_writel(pull, cfg->pull_reg);
 	}
 
+	if (warn) {
+#ifdef CONFIG_OMAP_MUX_WARNINGS
+		printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+#endif
+	}
+
 #ifdef CONFIG_OMAP_MUX_DEBUG
-	if (cfg->debug) {
-		printk("Omap: Setting register %s\n", cfg->name);
+	if (cfg->debug || warn) {
+		printk("MUX: Setting register %s\n", cfg->name);
 		printk("      %s (0x%08x) = 0x%08x -> 0x%08x\n",
 		       cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
 
@@ -118,8 +151,13 @@
 
 	spin_unlock_irqrestore(&mux_spin_lock, flags);
 
-#endif
+#ifdef CONFIG_OMAP_MUX_ERRORS
+	return warn ? -ETXTBSY : 0;
+#else
 	return 0;
+#endif
 }
 
 EXPORT_SYMBOL(omap_cfg_reg);
+
+#endif	/* CONFIG_OMAP_MUX */
diff -Nru a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c
--- a/arch/arm/mach-omap/ocpi.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-omap/ocpi.c	2004-10-28 22:25:59 -07:00
@@ -59,20 +59,12 @@
 
 	/* Make sure there's clock for OCPI */
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+#if defined(CONFIG_ARCH_OMAP16XX)
         if (cpu_is_omap1610() || cpu_is_omap1710()) {
-		val = omap_readl(OMAP1610_ARM_IDLECT3);
+		val = omap_readl(OMAP16XX_ARM_IDLECT3);
 		val |= EN_OCPI_CK;
 		val &= ~IDLOCPI_ARM;
-		omap_writel(val, OMAP1610_ARM_IDLECT3);
-        }
-#endif
-#ifdef CONFIG_ARCH_OMAP5912
-        if (cpu_is_omap5912()) {
-		val = omap_readl(OMAP5912_ARM_IDLECT3);
-		val |= EN_OCPI_CK;
-		val &= ~IDLOCPI_ARM;
-		omap_writel(val, OMAP5912_ARM_IDLECT3);
+		omap_writel(val, OMAP16XX_ARM_IDLECT3);
         }
 #endif
 	/* Enable access for OHCI in OCPI */
diff -Nru a/arch/arm/mach-omap/pm.c b/arch/arm/mach-omap/pm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/pm.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,621 @@
+/*
+ * linux/arch/arm/mach-omap/pm.c
+ *
+ * OMAP Power Management Routines
+ *
+ * Original code for the SA11x0:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Modified for the PXA250 by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Modified for the OMAP1510 by David Singleton:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Cleanup 2004 for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/arch/omap16xx.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+
+#include "clock.h"
+
+static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE];
+static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE];
+static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE];
+static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE];
+
+/*
+ * Let's power down on idle, but only if we are really
+ * idle, because once we start down the path of
+ * going idle we continue to do idle even if we get
+ * a clock tick interrupt . .
+ */
+void omap_pm_idle(void)
+{
+	int (*func_ptr)(void) = 0;
+	unsigned int mask32 = 0;
+
+	/*
+	 * If the DSP is being used let's just idle the CPU, the overhead
+	 * to wake up from Big Sleep is big, milliseconds versus micro
+	 * seconds for wait for interrupt.
+	 */
+
+	local_irq_disable();
+	local_fiq_disable();
+	if (need_resched()) {
+		local_fiq_enable();
+		local_irq_enable();
+		return;
+	}
+	mask32 = omap_readl(ARM_SYSST);
+	local_fiq_enable();
+	local_irq_enable();
+	if ((mask32 & DSP_IDLE) == 0) {
+		__asm__ volatile ("mcr	p15, 0, r0, c7, c0, 4");
+	} else {
+
+		if (cpu_is_omap1510()) {
+			func_ptr = (void *)(OMAP1510_SRAM_IDLE_SUSPEND);
+		} else if (cpu_is_omap1610() || cpu_is_omap1710()) {
+			func_ptr = (void *)(OMAP1610_SRAM_IDLE_SUSPEND);
+		} else if (cpu_is_omap5912()) {
+			func_ptr = (void *)(OMAP5912_SRAM_IDLE_SUSPEND);
+		}
+
+		func_ptr();
+	}
+}
+
+/*
+ * Configuration of the wakeup event is board specific. For the
+ * moment we put it into this helper function. Later it may move
+ * to board specific files.
+ */
+static void omap_pm_wakeup_setup(void)
+{
+	/*
+	 * Enable ARM XOR clock and release peripheral from reset by
+	 * writing 1 to PER_EN bit in ARM_RSTCT2, this is required
+	 * for UART configuration to use UART2 to wake up.
+	 */
+
+	omap_writel(omap_readl(ARM_IDLECT2) | ENABLE_XORCLK, ARM_IDLECT2);
+	omap_writel(omap_readl(ARM_RSTCT2) | PER_EN, ARM_RSTCT2);
+	omap_writew(MODEM_32K_EN, ULPD_CLOCK_CTRL);
+
+	/*
+	 * Turn off all interrupts except L1-2nd level cascade,
+	 * and the L2 wakeup interrupts: keypad and UART2.
+	 */
+
+	omap_writel(~IRQ_LEVEL2, OMAP_IH1_MIR);
+
+	if (cpu_is_omap1510()) {
+		omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD),  OMAP_IH2_MIR);
+	}
+
+	if (cpu_is_omap16xx()) {
+		omap_writel(~(IRQ_UART2 | IRQ_KEYBOARD), OMAP_IH2_0_MIR);
+
+		omap_writel(~0x0, OMAP_IH2_1_MIR);
+		omap_writel(~0x0, OMAP_IH2_2_MIR);
+		omap_writel(~0x0, OMAP_IH2_3_MIR);
+	}
+
+	/*  New IRQ agreement */
+ 	omap_writel(1, OMAP_IH1_CONTROL);
+
+	/* external PULL to down, bit 22 = 0 */
+	omap_writel(omap_readl(PULL_DWN_CTRL_2) & ~(1<<22), PULL_DWN_CTRL_2);
+}
+
+void omap_pm_suspend(void)
+{
+	unsigned int mask32 = 0;
+	unsigned long arg0 = 0, arg1 = 0;
+	int (*func_ptr)(unsigned short, unsigned short) = 0;
+	unsigned short save_dsp_idlect2;
+
+	printk("PM: OMAP%x is entering deep sleep now ...\n", system_rev);
+
+	if (machine_is_omap_osk()) {
+		/* Stop LED1 (D9) blink */
+		tps65010_set_led(LED1, OFF);
+	}
+
+	/*
+	 * Step 1: turn off interrupts
+	 */
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	/*
+	 * Step 2: save registers
+	 *
+	 * The omap is a strange/beautiful device. The caches, memory
+	 * and register state are preserved across power saves.
+	 * We have to save and restore very little register state to
+	 * idle the omap.
+         *
+ 	 * Save interrupt, MPUI, ARM and UPLD control registers.
+	 */
+
+	if (cpu_is_omap1510()) {
+		MPUI1510_SAVE(OMAP_IH1_MIR);
+		MPUI1510_SAVE(OMAP_IH2_MIR);
+		MPUI1510_SAVE(MPUI_CTRL);
+		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1510_SAVE(EMIFS_CONFIG);
+		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_SAVE(OMAP_IH1_MIR);
+		MPUI1610_SAVE(OMAP_IH2_0_MIR);
+		MPUI1610_SAVE(OMAP_IH2_1_MIR);
+		MPUI1610_SAVE(OMAP_IH2_2_MIR);
+		MPUI1610_SAVE(OMAP_IH2_3_MIR);
+		MPUI1610_SAVE(MPUI_CTRL);
+		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1610_SAVE(EMIFS_CONFIG);
+		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+	}
+
+	ARM_SAVE(ARM_CKCTL);
+	ARM_SAVE(ARM_IDLECT1);
+	ARM_SAVE(ARM_IDLECT2);
+	ARM_SAVE(ARM_EWUPCT);
+	ARM_SAVE(ARM_RSTCT1);
+	ARM_SAVE(ARM_RSTCT2);
+	ARM_SAVE(ARM_SYSST);
+	ULPD_SAVE(ULPD_CLOCK_CTRL);
+	ULPD_SAVE(ULPD_STATUS_REQ);
+
+	/*
+	 * Step 3: LOW_PWR signal enabling
+	 *
+	 * Allow the LOW_PWR signal to be visible on MPUIO5 ball.
+	 */
+	if (cpu_is_omap1510()) {
+		/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
+		omap_writew(omap_readw(ULPD_POWER_CTRL) |
+			    OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
+	} else if (cpu_is_omap16xx()) {
+		/* POWER_CTRL_REG = 0x1 (LOW_POWER is available) */
+		omap_writew(omap_readw(ULPD_POWER_CTRL) |
+			    OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
+	}
+
+	/* configure LOW_PWR pin */
+	omap_cfg_reg(T20_1610_LOW_PWR);
+
+	/*
+	 * Step 4: OMAP DSP Shutdown
+	 */
+
+	/* Set DSP_RST = 1 and DSP_EN = 0, put DSP block into reset */
+	omap_writel((omap_readl(ARM_RSTCT1) | DSP_RST) & ~DSP_ENABLE,
+		    ARM_RSTCT1);
+
+	/* Set DSP boot mode to DSP-IDLE, DSP_BOOT_MODE = 0x2 */
+        omap_writel(DSP_IDLE_MODE, MPUI_DSP_BOOT_CONFIG);
+
+	/* Set EN_DSPCK = 0, stop DSP block clock */
+	omap_writel(omap_readl(ARM_CKCTL) & ~DSP_CLOCK_ENABLE, ARM_CKCTL);
+
+	/* Stop any DSP domain clocks */
+	omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
+	save_dsp_idlect2 = __raw_readw(DSP_IDLECT2);
+	__raw_writew(0, DSP_IDLECT2);
+
+	/*
+	 * Step 5: Wakeup Event Setup
+	 */
+
+	omap_pm_wakeup_setup();
+
+	/*
+	 * Step 6a: ARM and Traffic controller shutdown
+	 *
+	 * Step 6 starts here with clock and watchdog disable
+	 */
+
+	/* stop clocks */
+	mask32 = omap_readl(ARM_IDLECT2);
+	mask32 &= ~(1<<EN_WDTCK);  /* bit 0 -> 0 (WDT clock) */
+	mask32 |=  (1<<EN_XORPCK); /* bit 1 -> 1 (XORPCK clock) */
+	mask32 &= ~(1<<EN_PERCK);  /* bit 2 -> 0 (MPUPER_CK clock) */
+	mask32 &= ~(1<<EN_LCDCK);  /* bit 3 -> 0 (LCDC clock) */
+	mask32 &= ~(1<<EN_LBCK);   /* bit 4 -> 0 (local bus clock) */
+	mask32 |=  (1<<EN_APICK);  /* bit 6 -> 1 (MPUI clock) */
+	mask32 &= ~(1<<EN_TIMCK);  /* bit 7 -> 0 (MPU timer clock) */
+	mask32 &= ~(1<<DMACK_REQ); /* bit 8 -> 0 (DMAC clock) */
+	mask32 &= ~(1<<EN_GPIOCK); /* bit 9 -> 0 (GPIO clock) */
+	omap_writel(mask32, ARM_IDLECT2);
+
+	/* disable ARM watchdog */
+	omap_writel(0x00F5, OMAP_WDT_TIMER_MODE);
+	omap_writel(0x00A0, OMAP_WDT_TIMER_MODE);
+
+	/*
+	 * Step 6b: ARM and Traffic controller shutdown
+	 *
+	 * Step 6 continues here. Prepare jump to power management
+	 * assembly code in internal SRAM.
+	 *
+	 * Since the omap_cpu_suspend routine has been copied to
+	 * SRAM, we'll do an indirect procedure call to it and pass the
+	 * contents of arm_idlect1 and arm_idlect2 so it can restore
+	 * them when it wakes up and it will return.
+	 */
+
+	arg0 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT1];
+	arg1 = arm_sleep_save[ARM_SLEEP_SAVE_ARM_IDLECT2];
+
+	if (cpu_is_omap1510()) {
+		func_ptr = (void *)(OMAP1510_SRAM_API_SUSPEND);
+	} else if (cpu_is_omap1610() || cpu_is_omap1710()) {
+		func_ptr = (void *)(OMAP1610_SRAM_API_SUSPEND);
+	} else if (cpu_is_omap5912()) {
+		func_ptr = (void *)(OMAP5912_SRAM_API_SUSPEND);
+	}
+
+	/*
+	 * Step 6c: ARM and Traffic controller shutdown
+	 *
+	 * Jump to assembly code. The processor will stay there
+ 	 * until wake up.
+	 */
+
+        func_ptr(arg0, arg1);
+
+	/*
+	 * If we are here, processor is woken up!
+	 */
+
+	if (cpu_is_omap1510()) {
+		/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
+		omap_writew(omap_readw(ULPD_POWER_CTRL) &
+			    ~OMAP1510_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
+	} else if (cpu_is_omap16xx()) {
+		/* POWER_CTRL_REG = 0x0 (LOW_POWER is disabled) */
+		omap_writew(omap_readw(ULPD_POWER_CTRL) &
+			    ~OMAP1610_ULPD_LOW_POWER_REQ, ULPD_POWER_CTRL);
+	}
+
+
+	/* Restore DSP clocks */
+	omap_writel(omap_readl(ARM_IDLECT2) | (1<<EN_APICK), ARM_IDLECT2);
+	__raw_writew(save_dsp_idlect2, DSP_IDLECT2);
+	ARM_RESTORE(ARM_IDLECT2);
+
+	/*
+	 * Restore ARM state, except ARM_IDLECT1/2 which omap_cpu_suspend did
+	 */
+
+	ARM_RESTORE(ARM_CKCTL);
+	ARM_RESTORE(ARM_EWUPCT);
+	ARM_RESTORE(ARM_RSTCT1);
+	ARM_RESTORE(ARM_RSTCT2);
+	ARM_RESTORE(ARM_SYSST);
+	ULPD_RESTORE(ULPD_CLOCK_CTRL);
+	ULPD_RESTORE(ULPD_STATUS_REQ);
+
+	if (cpu_is_omap1510()) {
+		MPUI1510_RESTORE(MPUI_CTRL);
+		MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_RESTORE(MPUI_DSP_API_CONFIG);
+		MPUI1510_RESTORE(EMIFS_CONFIG);
+		MPUI1510_RESTORE(EMIFF_SDRAM_CONFIG);
+		MPUI1510_RESTORE(OMAP_IH1_MIR);
+		MPUI1510_RESTORE(OMAP_IH2_MIR);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_RESTORE(MPUI_CTRL);
+		MPUI1610_RESTORE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_RESTORE(MPUI_DSP_API_CONFIG);
+		MPUI1610_RESTORE(EMIFS_CONFIG);
+		MPUI1610_RESTORE(EMIFF_SDRAM_CONFIG);
+
+		MPUI1610_RESTORE(OMAP_IH1_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_0_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_1_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_2_MIR);
+		MPUI1610_RESTORE(OMAP_IH2_3_MIR);
+	}
+
+	/*
+	 * Reenable interrupts
+	 */
+
+	local_irq_enable();
+	local_fiq_enable();
+
+	printk("PM: OMAP%x is re-starting from deep sleep...\n", system_rev);
+
+	if (machine_is_omap_osk()) {
+		/* Let LED1 (D9) blink again */
+		tps65010_set_led(LED1, BLINK);
+	}
+}
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+static int g_read_completed;
+
+/*
+ * Read system PM registers for debugging
+ */
+static int omap_pm_read_proc(
+	char *page_buffer,
+	char **my_first_byte,
+	off_t virtual_start,
+	int length,
+	int *eof,
+	void *data)
+{
+	int my_buffer_offset = 0;
+	char * const my_base = page_buffer;
+
+	ARM_SAVE(ARM_CKCTL);
+	ARM_SAVE(ARM_IDLECT1);
+	ARM_SAVE(ARM_IDLECT2);
+	ARM_SAVE(ARM_EWUPCT);
+	ARM_SAVE(ARM_RSTCT1);
+	ARM_SAVE(ARM_RSTCT2);
+	ARM_SAVE(ARM_SYSST);
+
+	ULPD_SAVE(ULPD_IT_STATUS);
+	ULPD_SAVE(ULPD_CLOCK_CTRL);
+	ULPD_SAVE(ULPD_SOFT_REQ);
+	ULPD_SAVE(ULPD_STATUS_REQ);
+	ULPD_SAVE(ULPD_DPLL_CTRL);
+	ULPD_SAVE(ULPD_POWER_CTRL);
+
+	if (cpu_is_omap1510()) {
+		MPUI1510_SAVE(MPUI_CTRL);
+		MPUI1510_SAVE(MPUI_DSP_STATUS);
+		MPUI1510_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1510_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1510_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI1510_SAVE(EMIFS_CONFIG);
+	} else if (cpu_is_omap16xx()) {
+		MPUI1610_SAVE(MPUI_CTRL);
+		MPUI1610_SAVE(MPUI_DSP_STATUS);
+		MPUI1610_SAVE(MPUI_DSP_BOOT_CONFIG);
+		MPUI1610_SAVE(MPUI_DSP_API_CONFIG);
+		MPUI1610_SAVE(EMIFF_SDRAM_CONFIG);
+		MPUI1610_SAVE(EMIFS_CONFIG);
+	}
+
+	if (virtual_start == 0) {
+		g_read_completed = 0;
+
+		my_buffer_offset += sprintf(my_base + my_buffer_offset,
+		   "ARM_CKCTL_REG:            0x%-8x     \n"
+		   "ARM_IDLECT1_REG:          0x%-8x     \n"
+		   "ARM_IDLECT2_REG:          0x%-8x     \n"
+		   "ARM_EWUPCT_REG:           0x%-8x     \n"
+		   "ARM_RSTCT1_REG:           0x%-8x     \n"
+		   "ARM_RSTCT2_REG:           0x%-8x     \n"
+		   "ARM_SYSST_REG:            0x%-8x     \n"
+		   "ULPD_IT_STATUS_REG:       0x%-4x     \n"
+		   "ULPD_CLOCK_CTRL_REG:      0x%-4x     \n"
+		   "ULPD_SOFT_REQ_REG:        0x%-4x     \n"
+		   "ULPD_DPLL_CTRL_REG:       0x%-4x     \n"
+		   "ULPD_STATUS_REQ_REG:      0x%-4x     \n"
+		   "ULPD_POWER_CTRL_REG:      0x%-4x     \n",
+		   ARM_SHOW(ARM_CKCTL),
+		   ARM_SHOW(ARM_IDLECT1),
+		   ARM_SHOW(ARM_IDLECT2),
+		   ARM_SHOW(ARM_EWUPCT),
+		   ARM_SHOW(ARM_RSTCT1),
+		   ARM_SHOW(ARM_RSTCT2),
+		   ARM_SHOW(ARM_SYSST),
+		   ULPD_SHOW(ULPD_IT_STATUS),
+		   ULPD_SHOW(ULPD_CLOCK_CTRL),
+		   ULPD_SHOW(ULPD_SOFT_REQ),
+		   ULPD_SHOW(ULPD_DPLL_CTRL),
+		   ULPD_SHOW(ULPD_STATUS_REQ),
+		   ULPD_SHOW(ULPD_POWER_CTRL));
+
+		if (cpu_is_omap1510()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI1510_CTRL_REG             0x%-8x \n"
+			   "MPUI1510_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI1510_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+		   	   "MPUI1510_DSP_API_CONFIG_REG:  0x%-8x \n"
+		   	   "MPUI1510_SDRAM_CONFIG_REG:    0x%-8x \n"
+		   	   "MPUI1510_EMIFS_CONFIG_REG:    0x%-8x \n",
+		   	   MPUI1510_SHOW(MPUI_CTRL),
+		   	   MPUI1510_SHOW(MPUI_DSP_STATUS),
+		   	   MPUI1510_SHOW(MPUI_DSP_BOOT_CONFIG),
+		   	   MPUI1510_SHOW(MPUI_DSP_API_CONFIG),
+		   	   MPUI1510_SHOW(EMIFF_SDRAM_CONFIG),
+		   	   MPUI1510_SHOW(EMIFS_CONFIG));
+		} else if (cpu_is_omap16xx()) {
+			my_buffer_offset += sprintf(my_base + my_buffer_offset,
+			   "MPUI1610_CTRL_REG             0x%-8x \n"
+			   "MPUI1610_DSP_STATUS_REG:      0x%-8x \n"
+			   "MPUI1610_DSP_BOOT_CONFIG_REG: 0x%-8x \n"
+		   	   "MPUI1610_DSP_API_CONFIG_REG:  0x%-8x \n"
+		   	   "MPUI1610_SDRAM_CONFIG_REG:    0x%-8x \n"
+		   	   "MPUI1610_EMIFS_CONFIG_REG:    0x%-8x \n",
+		   	   MPUI1610_SHOW(MPUI_CTRL),
+		   	   MPUI1610_SHOW(MPUI_DSP_STATUS),
+		   	   MPUI1610_SHOW(MPUI_DSP_BOOT_CONFIG),
+		   	   MPUI1610_SHOW(MPUI_DSP_API_CONFIG),
+		   	   MPUI1610_SHOW(EMIFF_SDRAM_CONFIG),
+		   	   MPUI1610_SHOW(EMIFS_CONFIG));
+		}
+
+		g_read_completed++;
+	} else if (g_read_completed >= 1) {
+		 *eof = 1;
+		 return 0;
+	}
+	g_read_completed++;
+
+	*my_first_byte = page_buffer;
+	return  my_buffer_offset;
+}
+
+static void omap_pm_init_proc(void)
+{
+	struct proc_dir_entry *entry;
+
+	entry = create_proc_read_entry("driver/omap_pm",
+				       S_IWUSR | S_IRUGO, NULL,
+				       omap_pm_read_proc, 0);
+}
+
+#endif /* DEBUG && CONFIG_PROC_FS */
+
+/*
+ *	omap_pm_prepare - Do preliminary suspend work.
+ *	@state:		suspend state we're entering.
+ *
+ */
+//#include <asm/arch/hardware.h>
+
+static int omap_pm_prepare(u32 state)
+{
+	int error = 0;
+
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return error;
+}
+
+
+/*
+ *	omap_pm_enter - Actually enter a sleep state.
+ *	@state:		State we're entering.
+ *
+ */
+
+static int omap_pm_enter(u32 state)
+{
+	switch (state)
+	{
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		omap_pm_suspend();
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/**
+ *	omap_pm_finish - Finish up suspend sequence.
+ *	@state:		State we're coming out of.
+ *
+ *	This is called after we wake back up (or if entering the sleep state
+ *	failed).
+ */
+
+static int omap_pm_finish(u32 state)
+{
+	return 0;
+}
+
+
+struct pm_ops omap_pm_ops ={
+	.pm_disk_mode = 0,
+        .prepare        = omap_pm_prepare,
+        .enter          = omap_pm_enter,
+        .finish         = omap_pm_finish,
+};
+
+static int __init omap_pm_init(void)
+{
+	printk("Power Management for TI OMAP.\n");
+	pm_idle = omap_pm_idle;
+	/*
+	 * We copy the assembler sleep/wakeup routines to SRAM.
+	 * These routines need to be in SRAM as that's the only
+	 * memory the MPU can see when it wakes up.
+	 */
+
+#ifdef	CONFIG_ARCH_OMAP1510
+	if (cpu_is_omap1510()) {
+		memcpy((void *)OMAP1510_SRAM_IDLE_SUSPEND,
+		       omap1510_idle_loop_suspend,
+		       omap1510_idle_loop_suspend_sz);
+		memcpy((void *)OMAP1510_SRAM_API_SUSPEND, omap1510_cpu_suspend,
+		       omap1510_cpu_suspend_sz);
+	} else
+#endif
+	if (cpu_is_omap1610() || cpu_is_omap1710()) {
+		memcpy((void *)OMAP1610_SRAM_IDLE_SUSPEND,
+		       omap1610_idle_loop_suspend,
+		       omap1610_idle_loop_suspend_sz);
+		memcpy((void *)OMAP1610_SRAM_API_SUSPEND, omap1610_cpu_suspend,
+		       omap1610_cpu_suspend_sz);
+	} else if (cpu_is_omap5912()) {
+		memcpy((void *)OMAP5912_SRAM_IDLE_SUSPEND,
+		       omap1610_idle_loop_suspend,
+		       omap1610_idle_loop_suspend_sz);
+		memcpy((void *)OMAP5912_SRAM_API_SUSPEND, omap1610_cpu_suspend,
+		       omap1610_cpu_suspend_sz);
+	}
+
+	pm_set_ops(&omap_pm_ops);
+
+#if defined(DEBUG) && defined(CONFIG_PROC_FS)
+	omap_pm_init_proc();
+#endif
+
+	return 0;
+}
+__initcall(omap_pm_init);
+
diff -Nru a/arch/arm/mach-omap/sleep.S b/arch/arm/mach-omap/sleep.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-omap/sleep.S	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,314 @@
+/*
+ * linux/arch/arm/mach-omap/sleep.S
+ *
+ * Low-level OMAP1510/1610 sleep/wakeUp support
+ *
+ * Initial SA1110 code:
+ * Copyright (c) 2001 Cliff Brake <cbrake@accelent.com>
+ *
+ * Adapted for PXA by Nicolas Pitre:
+ * Copyright (c) 2002 Monta Vista Software, Inc.
+ *
+ * Support for OMAP1510/1610 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/arch/io.h>
+#include <asm/arch/pm.h>
+
+		.text
+
+/*
+ * Forces OMAP into idle state
+ *
+ * omapXXXX_idle_loop_suspend()
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *	 wakes up it continues execution at the point it went to sleep.
+ *
+ * Note: Because of slightly different configuration values we have
+ *       processor specific functions here.
+ */
+
+#ifdef CONFIG_ARCH_OMAP1510
+ENTRY(omap1510_idle_loop_suspend)
+
+	stmfd	sp!, {r0 - r12, lr}		@ save registers on stack
+
+	@ load base address of ARM_IDLECT1 and ARM_IDLECT2
+	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
+
+	@ turn off clock domains
+	@ get ARM_IDLECT2 into r2
+	ldrh	r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+	mov	r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
+ 	orr	r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
+	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+	@ request ARM idle
+	@ get ARM_IDLECT1 into r1
+	ldrh	r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+	orr	r3, r1, #OMAP1510_IDLE_LOOP_REQUEST & 0xffff
+	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	mov	r5, #IDLE_WAIT_CYCLES & 0xff
+	orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+l_1510:	subs	r5, r5, #1
+	bne	l_1510
+/*
+ * Let's wait for the next clock tick to wake us up.
+ */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c0, 4		@ wait for interrupt
+/*
+ * omap1510_idle_loop_suspend()'s resume point.
+ *
+ * It will just start executing here, so we'll restore stuff from the
+ * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
+ */
+
+	@ restore ARM_IDLECT1 and ARM_IDLECT2 and return
+	@ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
+	strh	r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+	strh	r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
+
+ENTRY(omap1510_idle_loop_suspend_sz)
+	.word	. - omap1510_idle_loop_suspend
+#endif /* CONFIG_ARCH_OMAP1510 */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+ENTRY(omap1610_idle_loop_suspend)
+
+	stmfd	sp!, {r0 - r12, lr}		@ save registers on stack
+
+	@ load base address of ARM_IDLECT1 and ARM_IDLECT2
+	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
+
+	@ turn off clock domains
+	@ get ARM_IDLECT2 into r2
+	ldrh	r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+	mov	r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
+ 	orr	r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
+	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+	@ request ARM idle
+	@ get ARM_IDLECT1 into r1
+	ldrh	r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+	orr	r3, r1, #OMAP1610_IDLE_LOOP_REQUEST & 0xffff
+	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	mov	r5, #IDLE_WAIT_CYCLES & 0xff
+	orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+l_1610:	subs	r5, r5, #1
+	bne	l_1610
+/*
+ * Let's wait for the next clock tick to wake us up.
+ */
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c0, 4		@ wait for interrupt
+/*
+ * omap1610_idle_loop_suspend()'s resume point.
+ *
+ * It will just start executing here, so we'll restore stuff from the
+ * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
+ */
+
+	@ restore ARM_IDLECT1 and ARM_IDLECT2 and return
+	@ r1 has ARM_IDLECT1 and r2 still has ARM_IDLECT2
+	strh	r2, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+	strh	r1, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	ldmfd   sp!, {r0 - r12, pc}     @ restore regs and return
+
+ENTRY(omap1610_idle_loop_suspend_sz)
+	.word	. - omap1610_idle_loop_suspend
+#endif /* CONFIG_ARCH_OMAP16XX */
+
+/*
+ * Forces OMAP into deep sleep state
+ *
+ * omapXXXX_cpu_suspend()
+ *
+ * The values of the registers ARM_IDLECT1 and ARM_IDLECT2 are passed
+ * as arg0 and arg1 from caller. arg0 is stored in register r0 and arg1
+ * in register r1.
+ *
+ * Note: This code get's copied to internal SRAM at boot. When the OMAP
+ *	 wakes up it continues execution at the point it went to sleep.
+ *
+ * Note: Because of errata work arounds we have processor specific functions
+ *       here. They are mostly the same, but slightly different.
+ *
+ */
+
+#ifdef CONFIG_ARCH_OMAP1510
+ENTRY(omap1510_cpu_suspend)
+
+	@ save registers on stack
+	stmfd	sp!, {r0 - r12, lr}
+
+	@ load base address of Traffic Controller
+	mov	r4, #TCMIF_ASM_BASE & 0xff000000
+	orr	r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
+	orr	r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
+
+	@ work around errata of OMAP1510 PDE bit for TC shut down
+	@ clear PDE bit
+	ldr	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+	bic	r5, r5, #PDE_BIT & 0xff
+	str	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+	@ set PWD_EN bit
+	and	r5, r5, #PWD_EN_BIT & 0xff
+	str	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+	@ prepare to put SDRAM into self-refresh manually
+	ldr	r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+	orr	r5, r5, #SELF_REFRESH_MODE & 0xff000000
+	orr	r5, r5, #SELF_REFRESH_MODE & 0x000000ff
+	str	r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+
+	@ prepare to put EMIFS to Sleep
+	ldr	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+	orr	r5, r5, #IDLE_EMIFS_REQUEST & 0xff
+	str	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+	@ load base address of ARM_IDLECT1 and ARM_IDLECT2
+	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
+
+	@ turn off clock domains
+	mov	r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff
+ 	orr	r5,r5, #OMAP1510_IDLE_CLOCK_DOMAINS & 0xff00
+	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+	@ request ARM idle
+	mov	r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff
+	orr	r3, r3, #OMAP1510_DEEP_SLEEP_REQUEST & 0xff00
+	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	mov	r5, #IDLE_WAIT_CYCLES & 0xff
+	orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+l_1510_2:
+	subs	r5, r5, #1
+	bne	l_1510_2
+/*
+ * Let's wait for the next wake up event to wake us up. r0 can't be
+ * used here because r0 holds ARM_IDLECT1
+ */
+	mov	r2, #0
+	mcr	p15, 0, r2, c7, c0, 4		@ wait for interrupt
+/*
+ * omap1510_cpu_suspend()'s resume point.
+ *
+ * It will just start executing here, so we'll restore stuff from the
+ * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
+ */
+	strh	r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+	strh	r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	@ restore regs and return
+	ldmfd   sp!, {r0 - r12, pc}
+
+ENTRY(omap1510_cpu_suspend_sz)
+	.word	. - omap1510_cpu_suspend
+#endif /* CONFIG_ARCH_OMAP1510 */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+ENTRY(omap1610_cpu_suspend)
+
+	@ save registers on stack
+	stmfd	sp!, {r0 - r12, lr}
+
+	@ load base address of Traffic Controller
+	mov	r4, #TCMIF_ASM_BASE & 0xff000000
+	orr	r4, r4, #TCMIF_ASM_BASE & 0x00ff0000
+	orr	r4, r4, #TCMIF_ASM_BASE & 0x0000ff00
+
+	@ prepare to put SDRAM into self-refresh manually
+	ldr	r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+	orr	r5, r5, #SELF_REFRESH_MODE & 0xff000000
+	orr	r5, r5, #SELF_REFRESH_MODE & 0x000000ff
+	str	r5, [r4, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
+
+	@ prepare to put EMIFS to Sleep
+	ldr	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+	orr	r5, r5, #IDLE_EMIFS_REQUEST & 0xff
+	str	r5, [r4, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
+
+	@ load base address of ARM_IDLECT1 and ARM_IDLECT2
+	mov	r4, #CLKGEN_REG_ASM_BASE & 0xff000000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
+	orr	r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00
+
+	@ turn off clock domains
+	mov	r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff
+ 	orr	r5,r5, #OMAP1610_IDLE_CLOCK_DOMAINS & 0xff00
+	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+	@ work around errata of OMAP1610/5912. Enable (!) peripheral
+	@ clock to let the chip go into deep sleep
+	ldrh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+ 	orr	r5,r5, #EN_PERCK_BIT & 0xff
+	strh	r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+
+	@ request ARM idle
+	mov	r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff
+	orr	r3, r3, #OMAP1610_DEEP_SLEEP_REQUEST & 0xff00
+	strh	r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	mov	r5, #IDLE_WAIT_CYCLES & 0xff
+	orr     r5, r5, #IDLE_WAIT_CYCLES & 0xff00
+l_1610_2:
+	subs	r5, r5, #1
+	bne	l_1610_2
+/*
+ * Let's wait for the next wake up event to wake us up. r0 can't be
+ * used here because r0 holds ARM_IDLECT1
+ */
+	mov	r2, #0
+	mcr	p15, 0, r2, c7, c0, 4		@ wait for interrupt
+/*
+ * omap1610_cpu_suspend()'s resume point.
+ *
+ * It will just start executing here, so we'll restore stuff from the
+ * stack, reset the ARM_IDLECT1 and ARM_IDLECT2.
+ */
+	strh	r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
+	strh	r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]
+
+	@ restore regs and return
+	ldmfd   sp!, {r0 - r12, pc}
+
+ENTRY(omap1610_cpu_suspend_sz)
+	.word	. - omap1610_cpu_suspend
+#endif /* CONFIG_ARCH_OMAP16XX */
diff -Nru a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
--- a/arch/arm/mach-omap/time.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-omap/time.c	2004-10-28 22:25:58 -07:00
@@ -41,7 +41,6 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
-#include <asm/arch/clocks.h>
 
 #ifndef __instrument
 #define __instrument
diff -Nru a/arch/arm/mach-omap/usb.c b/arch/arm/mach-omap/usb.c
--- a/arch/arm/mach-omap/usb.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-omap/usb.c	2004-10-28 22:25:59 -07:00
@@ -48,8 +48,10 @@
  */
 
 /* TESTED ON:
- *  - 1611B H2 (with usb1 mini-AB)
- *  - 1510 Innovator with built-in transceiver (custom cable feeding 5V VBUS)
+ *  - 1611B H2 (with usb1 mini-AB) using standard Mini-B or OTG cables
+ *  - 1510 Innovator UDC with bundled usb0 cable
+ *  - 1510 Innovator OHCI with bundled usb1/usb2 cable
+ *  - 1510 Innovator OHCI with custom usb0 cable, feeding 5V VBUS
  *  - 1710 custom development board using alternate pin group
  */
 
@@ -92,7 +94,10 @@
 	u32	syscon1 = 0;
 
 	if (nwires == 0) {
-		USB_TRANSCEIVER_CTRL_REG &= ~(1 << 3);
+		if (!cpu_is_omap15xx()) {
+			/* pulldown D+/D- */
+			USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
+		}
 		return 0;
 	}
 
@@ -101,36 +106,30 @@
 	 * USB0_VP and USB0_VM are always set on 1510, there's no muxing
 	 * available for them.
 	 */
-	if (nwires >= 2 && !cpu_is_omap1510()) {
+	if (nwires >= 2 && !cpu_is_omap15xx()) {
 		omap_cfg_reg(AA9_USB0_VP);
 		omap_cfg_reg(R9_USB0_VM);
 	}
+	if (is_device)
+		omap_cfg_reg(W4_USB_PUEN);
 
 	/* internal transceiver */
 	if (nwires == 2) {
-		if (cpu_is_omap1510()) {
-			/* This works for OHCI on 1510-Innovator, nothing to mux */
+		if (cpu_is_omap15xx()) {
+			/* This works for OHCI on 1510-Innovator */
 			return 0;
 		}
 
-#if 0
 		/* NOTE:  host OR device mode for now, no OTG */
-		USB_TRANSCEIVER_CTRL_REG &= ~(3 << 4);
+		USB_TRANSCEIVER_CTRL_REG &= ~(7 << 4);
 		if (is_device) {
-			omap_cfg_reg(W4_USB_PUEN);
 			omap_cfg_reg(R18_1510_USB_GPIO0);
 			// omap_cfg_reg(USB0_VBUS);
-			// omap_cfg_reg(USB0_PUEN);
 			// USB_TRANSCEIVER_CTRL_REG.CONF_USB0_PORT_R = 7
-			// when USB0_PUEN is needed
 		} else /* host mode needs D+ and D- pulldowns */
 			USB_TRANSCEIVER_CTRL_REG &= ~(3 << 1);
+
 		return 3 << 16;
-#else
-		/* FIXME: 1610 needs to return the right value here */
-		printk(KERN_ERR "usb0 internal transceiver, nyet\n");
-		return 0;
-#endif
 	}
 
 	/* alternate pin config, external transceiver */
@@ -170,7 +169,7 @@
 {
 	u32	syscon1 = 0;
 
-	if (nwires != 6)
+	if (nwires != 6 && !cpu_is_omap15xx())
 		USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB1_UNI_R;
 	if (nwires == 0)
 		return 0;
@@ -178,11 +177,11 @@
 	/* external transceiver */
 	omap_cfg_reg(USB1_TXD);
 	omap_cfg_reg(USB1_TXEN);
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		omap_cfg_reg(USB1_SEO);
 		omap_cfg_reg(USB1_SPEED);
 		// SUSP
-	} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+	} else if (cpu_is_omap16xx()) {
 		omap_cfg_reg(W13_1610_USB1_SE0);
 		omap_cfg_reg(R13_1610_USB1_SPEED);
 		// SUSP
@@ -203,7 +202,8 @@
 		syscon1 = 3;
 		omap_cfg_reg(USB1_VP);
 		omap_cfg_reg(USB1_VM);
-		USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
+		if (!cpu_is_omap15xx())
+			USB_TRANSCEIVER_CTRL_REG |= CONF_USB1_UNI_R;
 		break;
 	default:
 		printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
@@ -216,31 +216,32 @@
 {
 	u32	syscon1 = 0;
 
-	if (alt_pingroup)
+	if (alt_pingroup || nwires == 0)
 		return 0;
-	if (nwires != 6)
+	if (nwires != 6 && !cpu_is_omap15xx())
 		USB_TRANSCEIVER_CTRL_REG &= ~CONF_USB2_UNI_R;
 	if (nwires == 0)
 		return 0;
 
 	/* external transceiver */
-	if (cpu_is_omap1510()) {
+	if (cpu_is_omap15xx()) {
 		omap_cfg_reg(USB2_TXD);
 		omap_cfg_reg(USB2_TXEN);
 		omap_cfg_reg(USB2_SEO);
 		if (nwires != 3)
 			omap_cfg_reg(USB2_RCV);
-	} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
+		/* there is no USB2_SPEED */
+	} else if (cpu_is_omap16xx()) {
 		omap_cfg_reg(V6_USB2_TXD);
 		omap_cfg_reg(W9_USB2_TXEN);
 		omap_cfg_reg(W5_USB2_SE0);
 		if (nwires != 3)
 			omap_cfg_reg(Y5_USB2_RCV);
+		// FIXME omap_cfg_reg(USB2_SPEED);
 	} else {
 		pr_debug("usb unrecognized\n");
 	}
 	// omap_cfg_reg(USB2_SUSP);
-	// FIXME omap_cfg_reg(USB2_SPEED);
 
 	switch (nwires) {
 	case 3:
@@ -251,14 +252,14 @@
 		break;
 	case 6:
 		syscon1 = 3;
-		if (cpu_is_omap1510()) {
+		if (cpu_is_omap15xx()) {
 			omap_cfg_reg(USB2_VP);
 			omap_cfg_reg(USB2_VM);
 		} else {
 			omap_cfg_reg(AA9_USB2_VP);
 			omap_cfg_reg(R9_USB2_VM);
+			USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
 		}
-		USB_TRANSCEIVER_CTRL_REG |= CONF_USB2_UNI_R;
 		break;
 	default:
 		printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
@@ -337,7 +338,7 @@
 	.dev = {
 		.release		= usb_release,
 		.dma_mask		= &ohci_dmamask,
-		.coherent_dma_mask	= 0x0fffffff,
+		.coherent_dma_mask	= 0xffffffff,
 	},
 	.num_resources	= ARRAY_SIZE(ohci_resources),
 	.resource		= ohci_resources,
@@ -375,7 +376,11 @@
 
 // FIXME correct answer depends on hmc_mode,
 // as does any nonzero value for config->otg port number
+#ifdef	CONFIG_USB_GADGET_OMAP
+#define	is_usb0_device(config)	1
+#else
 #define	is_usb0_device(config)	0
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -420,7 +425,7 @@
 	if (alt_pingroup)
 		printk(", usb2 alt %d wires", config->pins[2]);
 	else if (config->pins[0])
-		printk(", usb0 %d wires%s", config->pins[2],
+		printk(", usb0 %d wires%s", config->pins[0],
 			is_usb0_device(config) ? " (dev)" : "");
 	if (config->pins[1])
 		printk(", usb1 %d wires", config->pins[1]);
@@ -477,6 +482,19 @@
 
 #ifdef	CONFIG_ARCH_OMAP1510
 
+#define ULPD_SOFT_REQ_REG	__REG16(ULPD_SOFT_REQ)
+#define SOFT_UDC_REQ		(1 << 4)
+#define SOFT_DPLL_REQ		(1 << 0)
+
+#define ULPD_DPLL_CTRL_REG	__REG16(ULPD_DPLL_CTRL)
+#define DPLL_IOB		(1 << 13)
+#define DPLL_PLL_ENABLE		(1 << 4)
+#define DPLL_LOCK		(1 << 0)
+
+#define ULPD_APLL_CTRL_REG	__REG16(ULPD_APLL_CTRL)
+#define APLL_NDPLL_SWITCH	(1 << 0)
+
+
 static void __init omap_1510_usb_init(struct omap_usb_config *config)
 {
 	int status;
@@ -490,16 +508,43 @@
 	val |= (config->hmc_mode << 1);
 	omap_writel(val, MOD_CONF_CTRL_0);
 
-	// FIXME this has a UDC controller too
+	printk("USB: hmc %d", config->hmc_mode);
+	if (config->pins[0])
+		printk(", usb0 %d wires%s", config->pins[0],
+			is_usb0_device(config) ? " (dev)" : "");
+	if (config->pins[1])
+		printk(", usb1 %d wires", config->pins[1]);
+	if (config->pins[2])
+		printk(", usb2 %d wires", config->pins[2]);
+	printk("\n");
+
+	/* use DPLL for 48 MHz function clock */
+	pr_debug("APLL %04x DPLL %04x REQ %04x\n", ULPD_APLL_CTRL_REG,
+			ULPD_DPLL_CTRL_REG, ULPD_SOFT_REQ_REG);
+	ULPD_APLL_CTRL_REG &= ~APLL_NDPLL_SWITCH;
+	ULPD_DPLL_CTRL_REG |= DPLL_IOB | DPLL_PLL_ENABLE;
+	ULPD_SOFT_REQ_REG |= SOFT_UDC_REQ | SOFT_DPLL_REQ;
+	while (!(ULPD_DPLL_CTRL_REG & DPLL_LOCK))
+		cpu_relax();
+
+#ifdef	CONFIG_USB_GADGET_OMAP
+	if (config->register_dev) {
+		udc_device.dev.platform_data = config;
+		status = platform_device_register(&udc_device);
+		if (status)
+			pr_debug("can't register UDC device, %d\n", status);
+		/* udc driver gates 48MHz by D+ pullup */
+	}
+#endif
 
 #if	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-	if (config->otg || config->register_host) {
+	if (config->register_host) {
 		ohci_device.dev.platform_data = config;
 		status = platform_device_register(&ohci_device);
 		if (status)
 			pr_debug("can't register OHCI device, %d\n", status);
+		/* hcd explicitly gates 48MHz */
 	}
-	// FIXME completely untested ...
 #endif
 
 }
@@ -524,12 +569,9 @@
 	}
 	platform_data = *config;
 
-	if (cpu_is_omap730()
-			|| cpu_is_omap1610()
-			|| cpu_is_omap1710()
-			|| cpu_is_omap5912())
+	if (cpu_is_omap730() || cpu_is_omap16xx())
 		omap_otg_init(&platform_data);
-	else if (cpu_is_omap1510())
+	else if (cpu_is_omap15xx())
 		omap_1510_usb_init(&platform_data);
 	else {
 		printk(KERN_ERR "USB: No init for your chip yet\n");
diff -Nru a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
--- a/arch/arm/mach-s3c2410/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-s3c2410/Kconfig	2004-10-28 22:25:57 -07:00
@@ -72,4 +72,31 @@
 	  the CPU time doing so.
 
 
+config S3C2410_PM_DEBUG
+	bool "S3C2410 PM Suspend debug"
+	depends on ARCH_S3C2410 && PM
+	help
+	  Say Y here if you want verbose debugging from the PM Suspend and
+	  Resume code. See `Documentation/arm/Samsing-S3C24XX/Suspend.txt`
+	  for more information.
+
+config S3C2410_PM_CHECK
+	bool "S3C2410 PM Suspend Memory CRC"
+	depends on ARCH_S3C2410 && PM && CRC32
+	help
+ 	  Enable the PM code's memory area checksum over sleep. This option
+	  will generate CRCs of all blocks of memory, and store them before
+	  going to sleep. The blocks are then checked on resume for any
+	  errors.
+
+config S3C2410_PM_CHECK_CHUNKSIZE
+	int "S3C2410 PM Suspend CRC Chunksize (KiB)"
+	depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
+	default 64
+	help
+	  Set the chunksize in Kilobytes of the CRC for checking memory
+	  corruption over suspend and resume. A smaller value will mean that
+	  the CRC data block will take more memory, but wil identify any
+	  faults with better precision.
+
 endif
diff -Nru a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
--- a/arch/arm/mach-s3c2410/Makefile	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-s3c2410/Makefile	2004-10-28 22:25:57 -07:00
@@ -15,6 +15,10 @@
 obj-$(CONFIG_CPU_S3C2410)  += s3c2410.o
 obj-$(CONFIG_S3C2410_DMA)  += dma.o
 
+# Power Management support
+
+obj-$(CONFIG_PM)	   += pm.o sleep.o
+
 # S3C2440 support
 
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
diff -Nru a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
--- a/arch/arm/mach-s3c2410/clock.c	2004-10-28 22:25:56 -07:00
+++ b/arch/arm/mach-s3c2410/clock.c	2004-10-28 22:25:56 -07:00
@@ -59,7 +59,7 @@
 
 /* old functions */
 
-void s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
+void inline s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
 {
 	unsigned long clkcon;
 	unsigned long flags;
@@ -72,11 +72,26 @@
 	if (enable)
 		clkcon |= clocks;
 
+	/* ensure none of the special function bits set */
+	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
+
 	__raw_writel(clkcon, S3C2410_CLKCON);
 
 	local_irq_restore(flags);
 }
 
+/* enable and disable calls for use with the clk struct */
+
+static int clk_null_enable(struct clk *clk, int enable)
+{
+	return 0;
+}
+
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
+{
+	s3c2410_clk_enable(clk->ctrlbit, enable);
+	return 0;
+}
 
 /* Clock API calls */
 
@@ -105,15 +120,16 @@
 
 int clk_enable(struct clk *clk)
 {
-	if (clk->ctrlbit != 0)
-		s3c2410_clk_enable(clk->ctrlbit, 1);
+	if (IS_ERR(clk))
+		return -EINVAL;
 
-	return 0;
+	return (clk->enable)(clk, 1);
 }
 
 void clk_disable(struct clk *clk)
 {
-	s3c2410_clk_enable(clk->ctrlbit, 0);
+	if (!IS_ERR(clk))
+		(clk->enable)(clk, 0);
 }
 
 
@@ -131,8 +147,11 @@
 
 unsigned long clk_get_rate(struct clk *clk)
 {
-	if (clk->parent != NULL)
-		return clk->parent->rate;
+	if (clk->rate != 0)
+		return clk->rate;
+
+	while (clk->parent != NULL && clk->rate == 0)
+		clk = clk->parent;
 
 	return clk->rate;
 }
@@ -186,67 +205,105 @@
 	.ctrlbit       = 0
 };
 
+/* clocks that could be registered by external code */
+
+struct clk s3c24xx_dclk0 = {
+	.name		= "dclk0",
+};
+
+struct clk s3c24xx_dclk1 = {
+	.name		= "dclk1",
+};
+
+struct clk s3c24xx_clkout0 = {
+	.name		= "clkout1",
+};
+
+struct clk s3c24xx_clkout1 = {
+	.name		= "clkout1",
+};
+
+struct clk s3c24xx_uclk = {
+	.name		= "uclk",
+};
+
+
 /* clock definitions */
 
 static struct clk init_clocks[] = {
 	{ .name    = "nand",
 	  .parent  = &clk_h,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_NAND
 	},
 	{ .name    = "lcd",
 	  .parent  = &clk_h,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_LCDC
 	},
 	{ .name    = "usb-host",
 	  .parent  = &clk_h,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit =   S3C2410_CLKCON_USBH
 	},
 	{ .name    = "usb-device",
 	  .parent  = &clk_h,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_USBD
 	},
 	{ .name    = "timers",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_PWMT
 	},
 	{ .name    = "sdi",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_SDI
 	},
 	{ .name    = "uart0",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_UART0
 	},
 	{ .name    = "uart1",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_UART1
 	},
 	{ .name    = "uart2",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_UART2
 	},
 	{ .name    = "gpio",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_GPIO
 	},
 	{ .name    = "rtc",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_RTC
 	},
 	{ .name    = "adc",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_ADC
 	},
 	{ .name    = "i2c",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_IIC
 	},
 	{ .name    = "iis",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_IIS
 	},
 	{ .name    = "spi",
 	  .parent  = &clk_p,
+	  .enable  = s3c2410_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_SPI
 	},
 	{ .name    = "watchdog",
@@ -262,6 +319,9 @@
 	clk->owner = THIS_MODULE;
 	atomic_set(&clk->used, 0);
 
+	if (clk->enable == NULL)
+		clk->enable = clk_null_enable;
+
 	/* add to the list of available clocks */
 
 	down(&clocks_sem);
@@ -273,7 +333,7 @@
 
 /* initalise all the clocks */
 
-static int __init s3c2410_init_clocks(void)
+int __init s3c2410_init_clocks(void)
 {
 	struct clk *clkp = init_clocks;
 	int ptr;
@@ -287,8 +347,25 @@
 	clk_p.rate = s3c24xx_pclk;
 	clk_f.rate = s3c24xx_fclk;
 
-	/* set the enabled clocks to a minimal (known) state */
-	__raw_writel(S3C2410_CLKCON_PWMT | S3C2410_CLKCON_UART0 | S3C2410_CLKCON_UART1 | S3C2410_CLKCON_UART2 | S3C2410_CLKCON_GPIO | S3C2410_CLKCON_RTC, S3C2410_CLKCON);
+	/* it looks like just setting the register here is not good
+	 * enough, and causes the odd hang at initial boot time, so
+	 * do all of them indivdually.
+	 *
+	 * I think disabling the LCD clock if the LCD is active is
+	 * very dangerous, and therefore the bootloader should be
+	 * careful to not enable the LCD clock if it is not needed.
+	 *
+	 * and of course, this looks neater
+	 */
+
+	s3c2410_clk_enable(S3C2410_CLKCON_NAND, 0);
+	s3c2410_clk_enable(S3C2410_CLKCON_USBH, 0);
+	s3c2410_clk_enable(S3C2410_CLKCON_USBD, 0);
+	s3c2410_clk_enable(S3C2410_CLKCON_ADC, 0);
+	s3c2410_clk_enable(S3C2410_CLKCON_IIC, 0);
+	s3c2410_clk_enable(S3C2410_CLKCON_SPI, 0);
+
+	/* assume uart clocks are correctly setup */
 
 	/* register our clocks */
 
@@ -312,5 +389,4 @@
 	return 0;
 }
 
-arch_initcall(s3c2410_init_clocks);
 
diff -Nru a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
--- a/arch/arm/mach-s3c2410/clock.h	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-s3c2410/clock.h	2004-10-28 22:25:58 -07:00
@@ -2,7 +2,7 @@
  * linux/arch/arm/mach-s3c2410/clock.h
  *
  * Copyright (c) 2004 Simtec Electronics
- * Written by Ben Dooks, <ben@simtec.co.uk>
+ *	Written by Ben Dooks, <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -17,11 +17,30 @@
 	atomic_t              used;
 	unsigned long         rate;
 	unsigned long         ctrlbit;
+	int		    (*enable)(struct clk *, int enable);
 };
 
+/* other clocks which may be registered by board support */
+
+extern struct clk s3c24xx_dclk0;
+extern struct clk s3c24xx_dclk1;
+extern struct clk s3c24xx_clkout0;
+extern struct clk s3c24xx_clkout1;
+extern struct clk s3c24xx_uclk;
+
 /* processor clock settings, in Hz */
 
 extern unsigned long s3c24xx_xtal;
 extern unsigned long s3c24xx_pclk;
 extern unsigned long s3c24xx_hclk;
 extern unsigned long s3c24xx_fclk;
+
+/* exports for arch/arm/mach-s3c2410
+ *
+ * Please DO NOT use these outside of arch/arm/mach-s3c2410
+*/
+
+extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
+extern int s3c2410_register_clock(struct clk *clk);
+extern int s3c2410_init_clocks(void);
+
diff -Nru a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
--- a/arch/arm/mach-s3c2410/cpu.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-s3c2410/cpu.c	2004-10-28 22:25:58 -07:00
@@ -38,6 +38,7 @@
 #include <asm/arch/regs-gpio.h>
 
 #include "cpu.h"
+#include "clock.h"
 #include "s3c2410.h"
 #include "s3c2440.h"
 
@@ -112,6 +113,26 @@
 	return NULL;
 }
 
+/* board information */
+
+static struct s3c24xx_board *board;
+
+void s3c24xx_set_board(struct s3c24xx_board *b)
+{
+	int i;
+
+	board = b;
+
+	if (b->clocks_count != 0) {
+		struct clk **ptr = b->clocks;;
+
+		for (i = b->clocks_count; i > 0; i--, ptr++)
+			s3c2410_register_clock(*ptr);
+	}
+}
+
+/* cpu information */
+
 static struct cpu_table *cpu;
 
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
@@ -141,12 +162,29 @@
 
 static int __init s3c_arch_init(void)
 {
+	int ret;
+
 	// do the correct init for cpu
 
 	if (cpu == NULL)
 		panic("s3c_arch_init: NULL cpu\n");
 
-	return (cpu->init)();
+	ret = (cpu->init)();
+	if (ret != 0)
+		return ret;
+
+	if (board != NULL) {
+		ret = platform_add_devices(board->devices, board->devices_count);
+		if (ret) {
+			printk(KERN_ERR "s3c24xx: failed to add board devices (%d)\n", ret);
+		}
+
+		/* mask any error, we may not need all these board
+		 * devices */
+		ret = 0;
+	}
+
+	return ret;
 }
 
 arch_initcall(s3c_arch_init);
diff -Nru a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
--- a/arch/arm/mach-s3c2410/cpu.h	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-s3c2410/cpu.h	2004-10-28 22:25:57 -07:00
@@ -11,6 +11,7 @@
  *
  * Modifications:
  *     24-Aug-2004 BJD  Start of generic S3C24XX support
+ *     18-Oct-2004 BJD  Moved board struct into this file
 */
 
 #define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
@@ -38,3 +39,21 @@
 #endif
 
 extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
+
+/* the board structure is used at first initialsation time
+ * to get info such as the devices to register for this
+ * board. This is done because platfrom_add_devices() cannot
+ * be called from the map_io entry.
+*/
+
+struct s3c24xx_board {
+	struct platform_device  **devices;
+	unsigned int              devices_count;
+
+	struct clk		**clocks;
+	unsigned int		  clocks_count;
+};
+
+extern void s3c24xx_set_board(struct s3c24xx_board *board);
+
+
diff -Nru a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
--- a/arch/arm/mach-s3c2410/irq.c	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-s3c2410/irq.c	2004-10-28 22:25:57 -07:00
@@ -33,9 +33,11 @@
  *
  *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
  *		  Tidy up KF's patch and sort out new release
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *		  Add support for power management controls
 */
 
-
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -52,10 +54,73 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
+#include "pm.h"
 
 #define irqdbf(x...)
 #define irqdbf2(x...)
 
+#define EXTINT_OFF (IRQ_EINT4 - 4)
+
+/* wakeup irq control */
+
+#ifdef CONFIG_PM
+
+/* state for IRQs over sleep */
+
+/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
+ *
+ * set bit to 1 in allow bitfield to enable the wakeup settings on it
+*/
+
+unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
+unsigned long s3c_irqwake_intmask	= 0xffffffffL;
+unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
+unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
+
+static int
+s3c_irq_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
+
+	if (!(s3c_irqwake_intallow & irqbit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_intmask |= irqbit;
+	else
+		s3c_irqwake_intmask &= irqbit;
+
+	return 0;
+}
+
+static int
+s3c_irqext_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long bit = 1L << (irqno - EXTINT_OFF);
+
+	if (!(s3c_irqwake_eintallow & bit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_eintmask |= bit;
+	else
+		s3c_irqwake_eintmask &= ~bit;
+
+	return 0;
+}
+
+#else
+#define s3c_irqext_wake NULL
+#define s3c_irq_wake NULL
+#endif
+
+
 static void
 s3c_irq_mask(unsigned int irqno)
 {
@@ -109,21 +174,21 @@
 static struct irqchip s3c_irq_level_chip = {
 	.ack	   = s3c_irq_maskack,
 	.mask	   = s3c_irq_mask,
-	.unmask	   = s3c_irq_unmask
+	.unmask	   = s3c_irq_unmask,
+	.wake	   = s3c_irq_wake
 };
 
 static struct irqchip s3c_irq_chip = {
 	.ack	   = s3c_irq_ack,
 	.mask	   = s3c_irq_mask,
-	.unmask	   = s3c_irq_unmask
+	.unmask	   = s3c_irq_unmask,
+	.wake	   = s3c_irq_wake
 };
 
 /* S3C2410_EINTMASK
  * S3C2410_EINTPEND
  */
 
-#define EXTINT_OFF (IRQ_EINT4 - 4)
-
 static void
 s3c_irqext_mask(unsigned int irqno)
 {
@@ -276,14 +341,16 @@
 	.mask	    = s3c_irqext_mask,
 	.unmask	    = s3c_irqext_unmask,
 	.ack	    = s3c_irqext_ack,
-	.type	    = s3c_irqext_type
+	.type	    = s3c_irqext_type,
+	.wake	    = s3c_irqext_wake
 };
 
 static struct irqchip s3c_irq_eint0t4 = {
 	.ack	   = s3c_irq_ack,
 	.mask	   = s3c_irq_mask,
 	.unmask	   = s3c_irq_unmask,
-	.type	   = s3c_irqext_type
+	.wake	   = s3c_irq_wake,
+	.type	   = s3c_irqext_type,
 };
 
 /* mask values for the parent registers for each of the interrupt types */
diff -Nru a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
--- a/arch/arm/mach-s3c2410/mach-bast.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-s3c2410/mach-bast.c	2004-10-28 22:25:58 -07:00
@@ -18,6 +18,7 @@
  *     05-Sep-2003 BJD  Moved to v2.6 kernel
  *     06-Jan-2003 BJD  Updates for <arch/map.h>
  *     18-Jan-2003 BJD  Added serial port configuration
+ *     05-Oct-2004 BJD  Power management code
 */
 
 #include <linux/kernel.h>
@@ -33,6 +34,7 @@
 #include <asm/mach/irq.h>
 
 #include <asm/arch/bast-map.h>
+#include <asm/arch/bast-irq.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -41,11 +43,16 @@
 
 //#include <asm/debug-ll.h>
 #include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
 
 #include "s3c2410.h"
 #include "devs.h"
 #include "cpu.h"
 #include "usb-simtec.h"
+#include "pm.h"
+
+#define COPYRIGHT ", (c) 2004 Simtec Electronics"
 
 /* macros for virtual address mods for the io space entries */
 #define VA_C5(item) ((item) + BAST_VAM_CS5)
@@ -207,7 +214,7 @@
 	&bast_device_nor
 };
 
-static struct s3c2410_board bast_board __initdata = {
+static struct s3c24xx_board bast_board __initdata = {
 	.devices       = bast_devices,
 	.devices_count = ARRAY_SIZE(bast_devices)
 };
@@ -216,7 +223,7 @@
 {
 	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
 	s3c2410_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
-	s3c2410_set_board(&bast_board);
+	s3c24xx_set_board(&bast_board);
 	usb_simtec_init();
 }
 
@@ -224,6 +231,36 @@
 {
 	s3c2410_init_irq();
 }
+
+#ifdef CONFIG_PM
+
+/* bast_init_pm
+ *
+ * enable the power management functions for the EB2410ITX
+*/
+
+static __init int bast_init_pm(void)
+{
+	unsigned long gstatus4;
+
+	if (!machine_is_bast())
+		return 0;
+
+	printk(KERN_INFO "BAST Power Manangement" COPYRIGHT "\n");
+
+	gstatus4  = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30;
+	gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28;
+	gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK);
+
+	printk(KERN_DEBUG "setting GSTATUS4 to %08lx\n", gstatus4);
+	__raw_writel(gstatus4, S3C2410_GSTATUS4);
+
+	return s3c2410_pm_init();
+}
+
+late_initcall(bast_init_pm);
+#endif
+
 
 MACHINE_START(BAST, "Simtec-BAST")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
diff -Nru a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
--- a/arch/arm/mach-s3c2410/mach-h1940.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-s3c2410/mach-h1940.c	2004-10-28 22:25:59 -07:00
@@ -18,6 +18,7 @@
  *     17-Feb-2003 BJD  Copied to mach-ipaq.c
  *     21-Aug-2004 BJD  Added struct s3c2410_board
  *     04-Sep-2004 BJD  Changed uart init, renamed ipaq_ -> h1940_
+ *     18-Oct-2004 BJD  Updated new board structure name
 */
 
 #include <linux/kernel.h>
@@ -92,7 +93,7 @@
 	&s3c_device_iis,
 };
 
-static struct s3c2410_board h1940_board __initdata = {
+static struct s3c24xx_board h1940_board __initdata = {
 	.devices       = h1940_devices,
 	.devices_count = ARRAY_SIZE(h1940_devices)
 };
@@ -101,7 +102,7 @@
 {
 	s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
 	s3c2410_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
-	s3c2410_set_board(&h1940_board);
+	s3c24xx_set_board(&h1940_board);
 }
 
 void __init h1940_init_irq(void)
diff -Nru a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c	2004-10-28 22:25:58 -07:00
@@ -96,7 +96,7 @@
 	&s3c_device_iis,
 };
 
-static struct s3c2410_board smdk2410_board __initdata = {
+static struct s3c24xx_board smdk2410_board __initdata = {
 	.devices       = smdk2410_devices,
 	.devices_count = ARRAY_SIZE(smdk2410_devices)
 };
@@ -105,7 +105,7 @@
 {
 	s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
 	s3c2410_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
-	s3c2410_set_board(&smdk2410_board);
+	s3c24xx_set_board(&smdk2410_board);
 }
 
 void __init smdk2410_init_irq(void)
diff -Nru a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
--- a/arch/arm/mach-s3c2410/mach-vr1000.c	2004-10-28 22:25:59 -07:00
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c	2004-10-28 22:25:59 -07:00
@@ -16,6 +16,7 @@
  *     21-Aug-2004 BJD  Added struct s3c2410_board
  *     06-Aug-2004 BJD  Fixed call to time initialisation
  *     05-Apr-2004 BJD  Copied to make mach-vr1000.c
+ *     18-Oct-2004 BJD  Updated board struct
 */
 
 #include <linux/kernel.h>
@@ -151,7 +152,7 @@
 	&s3c_device_iis,
 };
 
-static struct s3c2410_board vr1000_board __initdata = {
+static struct s3c24xx_board vr1000_board __initdata = {
 	.devices       = vr1000_devices,
 	.devices_count = ARRAY_SIZE(vr1000_devices)
 };
@@ -161,7 +162,7 @@
 {
 	s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
 	s3c2410_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
-	s3c2410_set_board(&vr1000_board);
+	s3c24xx_set_board(&vr1000_board);
 	usb_simtec_init();
 }
 
diff -Nru a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/pm.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,585 @@
+/* linux/arch/arm/mach-s3c2410/pm.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ * Parts based on arch/arm/mach-pxa/pm.c
+ *
+*/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/crc32.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-irq.h>
+
+#include <asm/mach/time.h>
+
+#include "pm.h"
+
+/* for external use */
+
+unsigned long s3c_pm_flags;
+
+/* cache functions from arch/arm/mm/proc-arm920.S */
+
+extern void arm920_flush_kern_cache_all(void);
+
+#define PFX "s3c24xx-pm: "
+
+/* sleep save info */
+
+struct sleep_save {
+	unsigned long	reg;
+	unsigned long	val;
+};
+
+#define SAVE_ITEM(x) \
+	{ .reg = (x) }
+
+static struct sleep_save core_save[] = {
+	SAVE_ITEM(S3C2410_LOCKTIME),
+	SAVE_ITEM(S3C2410_CLKCON)
+};
+
+/* this lot should be really saved by the IRQ code */
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S3C2410_EINTMASK),
+	SAVE_ITEM(S3C2410_INTMSK),
+	SAVE_ITEM(S3C2410_EINFLT0),
+	SAVE_ITEM(S3C2410_EINFLT1),
+	SAVE_ITEM(S3C2410_EINFLT2),
+	SAVE_ITEM(S3C2410_EINFLT3)
+};
+
+static struct sleep_save gpio_save[] = {
+	SAVE_ITEM(S3C2410_GPACON),
+	SAVE_ITEM(S3C2410_GPADAT),
+
+	SAVE_ITEM(S3C2410_GPBCON),
+	SAVE_ITEM(S3C2410_GPBDAT),
+	SAVE_ITEM(S3C2410_GPBUP),
+
+	SAVE_ITEM(S3C2410_GPCCON),
+	SAVE_ITEM(S3C2410_GPCDAT),
+	SAVE_ITEM(S3C2410_GPCUP),
+
+	SAVE_ITEM(S3C2410_GPDCON),
+	SAVE_ITEM(S3C2410_GPDDAT),
+	SAVE_ITEM(S3C2410_GPDUP),
+
+	SAVE_ITEM(S3C2410_GPECON),
+	SAVE_ITEM(S3C2410_GPEDAT),
+	SAVE_ITEM(S3C2410_GPEUP),
+
+	SAVE_ITEM(S3C2410_GPFCON),
+	SAVE_ITEM(S3C2410_GPFDAT),
+	SAVE_ITEM(S3C2410_GPFUP),
+
+	SAVE_ITEM(S3C2410_GPGCON),
+	SAVE_ITEM(S3C2410_GPGDAT),
+	SAVE_ITEM(S3C2410_GPGUP),
+
+	SAVE_ITEM(S3C2410_GPHCON),
+	SAVE_ITEM(S3C2410_GPHDAT),
+	SAVE_ITEM(S3C2410_GPHUP),
+};
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+/* debug
+ *
+ * we send the debug to printascii() to allow it to be seen if the
+ * system never wakes up from the sleep
+*/
+
+extern void printascii(const char *);
+
+static void pm_dbg(const char *fmt, ...)
+{
+	va_list va;
+	char buff[256];
+
+	va_start(va, fmt);
+	vsprintf(buff, fmt, va);
+	va_end(va);
+
+	printascii(buff);
+}
+
+
+#define DBG(fmt...) pm_dbg(fmt)
+#else
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
+#endif
+
+#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size;	/* size needed for the crc block */
+static u32 *crcs;	/* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c2410_pm_run_res
+ *
+ * go thorugh the given resource list, and look for system ram
+*/
+
+static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+	while (ptr != NULL) {
+		if (ptr->child != NULL)
+			s3c2410_pm_run_res(ptr->child, fn, arg);
+
+		if ((ptr->flags & IORESOURCE_MEM) &&
+		    strcmp(ptr->name, "System RAM") == 0) {
+			DBG("Found system RAM at %08lx..%08lx\n",
+			    ptr->start, ptr->end);
+			arg = (fn)(ptr, arg);
+		}
+
+		ptr = ptr->sibling;
+	}
+}
+
+static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+	s3c2410_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
+{
+	u32 size = (u32)(res->end - res->start)+1;
+
+	size += CHECK_CHUNKSIZE-1;
+	size /= CHECK_CHUNKSIZE;
+
+	DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
+
+	*val += size * sizeof(u32);
+	return val;
+}
+
+/* s3c2410_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+static void s3c2410_pm_check_prepare(void)
+{
+	crc_size = 0;
+
+	s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+
+	DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+
+	crcs = kmalloc(crc_size+4, GFP_KERNEL);
+	if (crcs == NULL)
+		printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
+{
+	unsigned long addr, left;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		*val = crc32_le(~0, phys_to_virt(addr), left);
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c2410_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+static void s3c2410_pm_check_store(void)
+{
+	if (crcs != NULL)
+		s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contatins the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+	if ((what+whatsz) < ptr)
+		return 0;
+
+	if (what > (ptr+size))
+		return 0;
+
+	return 1;
+}
+
+static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
+{
+	void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
+	unsigned long addr;
+	unsigned long left;
+	void *ptr;
+	u32 calc;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		ptr = phys_to_virt(addr);
+
+		if (in_region(ptr, left, crcs, crc_size)) {
+			DBG("skipping %08lx, has crc block in\n", addr);
+			goto skip_check;
+		}
+
+		if (in_region(ptr, left, save_at, 32*4 )) {
+			DBG("skipping %08lx, has save block in\n", addr);
+			goto skip_check;
+		}
+
+		/* calculate and check the checksum */
+
+		calc = crc32_le(~0, ptr, left);
+		if (calc != *val) {
+			printk(KERN_ERR PFX "Restore CRC error at "
+			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+			DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+			    addr, calc, *val);
+		}
+
+	skip_check:
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c2410_pm_check_restore
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+
+static void s3c2410_pm_check_restore(void)
+{
+	if (crcs != NULL) {
+		s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
+		kfree(crcs);
+		crcs = NULL;
+	}
+}
+
+#else
+#define s3c2410_pm_check_prepare() do { } while(0)
+#define s3c2410_pm_check_restore() do { } while(0)
+#define s3c2410_pm_check_store()   do { } while(0)
+#endif
+
+/* helper functions to save and restore register state */
+
+static void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		ptr->val = __raw_readl(ptr->reg);
+		DBG("saved %08lx value %08lx\n", ptr->reg, ptr->val);
+	}
+}
+
+
+static void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		DBG("restore %08lx (restore %08lx, current %08x)\n",
+		    ptr->reg, ptr->val, __raw_readl(ptr->reg));
+		__raw_writel(ptr->val, ptr->reg);
+	}
+}
+
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+
+static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
+					unsigned long mask)
+{
+	int i;
+
+	which &= ~mask;
+
+	for (i = 0; i <= 31; i++) {
+		if ((which) & (1L<<i)) {
+			DBG("IRQ %d asserted at resume\n", start+i);
+		}
+	}
+}
+
+/* s3c2410_pm_check_resume_pin
+ *
+ * check to see if the pin is configured correctly for sleep mode, and
+ * make any necessary adjustments if it is not
+*/
+
+static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
+{
+	unsigned long irqstate;
+	unsigned long pinstate;
+	int irq = s3c2410_gpio_getirq(pin);
+
+	if (irqoffs < 4)
+		irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
+	else
+		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
+
+	pinstate = s3c2410_gpio_getcfg(pin);
+	pinstate >>= S3C2410_GPIO_OFFSET(pin)*2;
+
+	if (!irqstate) {
+		if (pinstate == 0x02)
+			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
+	} else {
+		if (pinstate == 0x02) {
+			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
+			s3c2410_gpio_cfgpin(pin, 0x00);
+		}
+	}
+}
+
+/* s3c2410_pm_configure_extint
+ *
+ * configure all external interrupt pins
+*/
+
+static void s3c2410_pm_configure_extint(void)
+{
+	int pin;
+
+	/* for each of the external interrupts (EINT0..EINT15) we
+	 * need to check wether it is an external interrupt source,
+	 * and then configure it as an input if it is not
+	*/
+
+	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
+		s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
+	}
+
+	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
+		s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
+	}
+}
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c2410_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c2410_pm_enter(u32 state)
+{
+	unsigned long regs_save[16];
+	unsigned long tmp;
+
+	DBG("s3c2410_pm_enter(%d)\n", state);
+
+	if (state != PM_SUSPEND_MEM) {
+		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
+		return -EINVAL;
+	}
+
+	/* check if we have anything to wake-up with... bad things seem
+	 * to happen if you suspend with no wakeup (system will often
+	 * require a full power-cycle)
+	*/
+
+	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+		printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
+		printk(KERN_ERR PFX "Aborting sleep\n");
+		return -EINVAL;
+	}
+
+	/* prepare check area if configured */
+
+	s3c2410_pm_check_prepare();
+
+	/* store the physical address of the register recovery block */
+
+	s3c2410_sleep_save_phys = virt_to_phys(regs_save);
+
+	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
+
+	/* ensure at least GESTATUS3 has the resume address */
+
+	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
+
+	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
+
+	/* save all necessary core registers not covered by the drivers */
+
+	s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
+	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
+
+	/* set the irq configuration for wake */
+
+	s3c2410_pm_configure_extint();
+
+	DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+	/* ack any outstanding external interrupts before we go to sleep */
+
+	__raw_writel(S3C2410_EINTPEND, __raw_readl(S3C2410_EINTPEND));
+
+	/* flush cache back to ram */
+
+	arm920_flush_kern_cache_all();
+
+	s3c2410_pm_check_store();
+
+	// need to make some form of time-delta
+
+	/* send the cpu to sleep... */
+
+	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
+
+	s3c2410_cpu_suspend(regs_save);
+
+	/* unset the return-from-sleep flag, to ensure reset */
+
+	tmp = __raw_readl(S3C2410_GSTATUS2);
+	tmp &= S3C2410_GSTATUs2_OFFRESET;
+	__raw_writel(tmp, S3C2410_GSTATUS2);
+
+	/* check what irq (if any) restored the system */
+
+	DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+	    __raw_readl(S3C2410_SRCPND),
+	    __raw_readl(S3C2410_EINTPEND));
+
+	s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+				    s3c_irqwake_intmask);
+
+	s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+				    s3c_irqwake_eintmask);
+
+	DBG("post sleep, restoring state...\n");
+
+	s3c2410_pm_do_restore(core_save, ARRAY_SIZE(core_save));
+	s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
+	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+
+	DBG("post sleep, preparing to return\n");
+
+	s3c2410_pm_check_restore();
+
+	/* ok, let's return from sleep */
+
+	DBG("S3C2410 PM Resume (post-restore)\n");
+	return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int s3c2410_pm_prepare(u32 state)
+{
+	return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int s3c2410_pm_finish(u32 state)
+{
+	return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops s3c2410_pm_ops = {
+	.pm_disk_mode	= PM_DISK_FIRMWARE,
+	.prepare	= s3c2410_pm_prepare,
+	.enter		= s3c2410_pm_enter,
+	.finish		= s3c2410_pm_finish,
+};
+
+/* s3c2410_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c2410_pm_init(void)
+{
+	printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
+
+	pm_set_ops(&s3c2410_pm_ops);
+	return 0;
+}
diff -Nru a/arch/arm/mach-s3c2410/pm.h b/arch/arm/mach-s3c2410/pm.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/pm.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,36 @@
+/* linux/arch/arm/mach-s3c2410/pm.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Written by Ben Dooks, <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* s3c2410_pm_init
+ *
+ * called from board at initialisation time to setup the power
+ * management
+*/
+
+extern __init int s3c2410_pm_init(void);
+
+/* configuration for the IRQ mask over sleep */
+extern unsigned long s3c_irqwake_intmask;
+extern unsigned long s3c_irqwake_eintmask;
+
+/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
+extern unsigned long s3c_irqwake_intallow;
+extern unsigned long s3c_irqwake_eintallow;
+
+/* Flags for PM Control */
+
+extern unsigned long s3c_pm_flags;
+
+/* from sleep.S */
+
+extern void s3c2410_cpu_suspend(unsigned long *saveblk);
+extern void s3c2410_cpu_resume(void);
+
+extern unsigned long s3c2410_sleep_save_phys;
diff -Nru a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
--- a/arch/arm/mach-s3c2410/s3c2410.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2410.c	2004-10-28 22:25:58 -07:00
@@ -189,13 +189,12 @@
 	printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
 	       print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
 	       print_mhz(s3c24xx_pclk));
-}
 
-static struct s3c2410_board *board;
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them
+	 */
 
-void s3c2410_set_board(struct s3c2410_board *b)
-{
-	board = b;
+	s3c2410_init_clocks();
 }
 
 int __init s3c2410_init(void)
@@ -205,22 +204,5 @@
 	printk("S3C2410: Initialising architecture\n");
 
 	ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
-	if (ret)
-		return ret;
-
-	if (board != NULL) {
-		if (board->devices != NULL) {
-			ret = platform_add_devices(board->devices,
-						   board->devices_count);
-
-			if (ret) {
-				printk(KERN_ERR "s3c2410: failed to add board devices (%d)\n", ret);
-			}
-		}
-
-		/* not adding board devices may not be fatal */
-		ret = 0;
-	}
-
 	return ret;
 }
diff -Nru a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
--- a/arch/arm/mach-s3c2410/s3c2410.h	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2410.h	2004-10-28 22:25:58 -07:00
@@ -13,6 +13,7 @@
  *     18-Aug-2004 BJD  Created initial version
  *     20-Aug-2004 BJD  Added s3c2410_board struct
  *     04-Sep-2004 BJD  Added s3c2410_init_uarts() call
+ *     17-Oct-2004 BJD  Moved board out to cpu
 */
 
 struct s3c2410_uartcfg;
@@ -25,19 +26,5 @@
 
 struct sys_timer;
 extern struct sys_timer s3c2410_timer;
-
-/* the board structure is used at first initialsation time
- * to get info such as the devices to register for this
- * board. This is done because platfrom_add_devices() cannot
- * be called from the map_io entry.
- *
-*/
-
-struct s3c2410_board {
-	struct platform_device  **devices;
-	unsigned int              devices_count;
-};
-
-extern void s3c2410_set_board(struct s3c2410_board *board);
 
 extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
diff -Nru a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
--- a/arch/arm/mach-s3c2410/s3c2440.c	2004-10-28 22:25:56 -07:00
+++ b/arch/arm/mach-s3c2410/s3c2440.c	2004-10-28 22:25:56 -07:00
@@ -120,6 +120,20 @@
 	&s3c_uart2
 };
 
+/* s3c2440 specific clock sources */
+
+static struct clk s3c2440_clk_cam = {
+	.name		= "camera",
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA
+};
+
+static struct clk s3c2440_clk_ac97 = {
+	.name		= "ac97",
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA
+};
+
 void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
 {
 	unsigned long clkdiv;
@@ -167,6 +181,23 @@
 	printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
 	       print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
 	       print_mhz(s3c24xx_pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them, and to add new ones after the initialisation
+	 */
+
+	s3c2410_init_clocks();
+
+	/* add s3c2440 specific clocks */
+
+	s3c2440_clk_cam.parent = clk_get(NULL, "hclk");
+	s3c2440_clk_ac97.parent = clk_get(NULL, "pclk");
+
+	s3c2410_register_clock(&clk_ac97);
+	s3c2410_register_clock(&clk_cam);
+
+	clk_disable(&clk_ac97);
+	clk_disable(&clk_cam);
 }
 
 
@@ -178,11 +209,6 @@
 	printk("S3C2440: Initialising architecture\n");
 
 	ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
-	if (ret)
-		return ret;
-
-	// todo: board specific inits?
-
 	return ret;
 }
 
diff -Nru a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/sleep.S	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,168 @@
+/* linux/arch/arm/mach-s3c2410/sleep.S
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *	Cliff Brake, (c) 2001
+ *
+ * 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/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-serial.h>
+
+#define CONFIG_DEBUG_RESUME
+
+	.text
+
+	/* s3c2410_cpu_suspend
+	 *
+	 * put the cpu into sleep mode
+	 *
+	 * entry:
+	 *	r0 = sleep save block
+	*/
+
+ENTRY(s3c2410_cpu_suspend)
+	stmfd	sp!, { r4 - r12, lr }
+
+	@@ store co-processor registers
+
+	mrc	p15, 0, r4, c15, c1, 0	@ CP access register
+	mrc	p15, 0, r5, c13, c0, 0	@ PID
+	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r7, c2, c0, 0	@ translation table base address
+	mrc	p15, 0, r8, c2, c0, 0	@ auxiliary control register
+	mrc	p15, 0, r9, c1, c0, 0	@ control register
+
+	stmia	r0, { r4 - r13 }
+
+	@@ flush the caches to ensure everything is back out to
+	@@ SDRAM before the core powers down
+
+	bl	arm920_flush_kern_cache_all
+
+	@@ prepare cpu to sleep
+
+	ldr	r4, =S3C2410_REFRESH
+	ldr	r5, =S3C2410_MISCCR
+	ldr	r6, =S3C2410_CLKCON
+	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
+	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
+	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
+
+	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
+	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
+	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command
+
+	teq	pc, #0			@ first as a trial-run to load cache
+	bl	s3c2410_do_sleep
+	teq	r0, r0			@ now do it for real
+	b	s3c2410_do_sleep	@
+
+	@@ align next bit of code to cache line
+	.align	8
+s3c2410_do_sleep:
+	streq	r7, [ r4 ]			@ SDRAM sleep command
+	streq	r8, [ r5 ]			@ SDRAM power-down config
+	streq	r9, [ r6 ]			@ CPU sleep
+1:	beq	1b
+	mov	pc, r14
+
+	@@ return to the caller, after having the MMU
+	@@ turned on, this restores the last bits from the
+	@@ stack
+resume_with_mmu:
+	ldmfd	sp!, { r4 - r12, pc }
+
+	.ltorg
+
+	@@ the next bits sit in the .data segment, even though they
+	@@ happen to be code... the s3c2410_sleep_save_phys needs to be
+	@@ accessed by the resume code before it can restore the MMU.
+	@@ This means that the variable has to be close enough for the
+	@@ code to read it... since the .text segment needs to be RO,
+	@@ the data segment can be the only place to put this code.
+
+	.data
+
+	.global	s3c2410_sleep_save_phys
+s3c2410_sleep_save_phys:
+	.word	0
+
+	/* s3c2410_cpu_resume
+	 *
+	 * resume code entry for bootloader to call
+	 *
+	 * we must put this code here in the data segment as we have no
+	 * other way of restoring the stack pointer after sleep, and we
+	 * must not write to the code segment (code is read-only)
+	*/
+
+ENTRY(s3c2410_cpu_resume)
+	mov	r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC
+	msr	cpsr_c, r0
+
+	@@ load UART to allow us to print the two characters for
+	@@ resume debug
+
+	mov	r2, #S3C2410_PA_UART & 0xff000000
+	orr	r2, r2, #S3C2410_PA_UART & 0xff000
+
+#ifdef CONFIG_DEBUG_RESUME
+	mov	r3, #'L'
+	strb	r3, [ r2, #S3C2410_UTXH ]
+1001:
+	ldrb	r14, [ r3, #S3C2410_UTRSTAT ]
+	tst	r14, #S3C2410_UTRSTAT_TXE
+	beq	1001b
+#endif /* CONFIG_DEBUG_RESUME */
+
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
+
+	ldr	r0, s3c2410_sleep_save_phys	@ address of restore block
+	ldmia	r0, { r4 - r13 }
+
+	mcr	p15, 0, r4, c15, c1, 0		@ CP access register
+	mcr	p15, 0, r5, c13, c0, 0		@ PID
+	mcr	p15, 0, r6, c3, c0, 0		@ Domain ID
+	mcr	p15, 0, r7, c2, c0, 0		@ translation table base
+	mcr	p15, 0, r8, c1, c1, 0		@ auxilliary control
+
+#ifdef CONFIG_DEBUG_RESUME
+	mov	r3, #'R'
+	strb	r3, [ r2, #S3C2410_UTXH ]
+#endif
+
+	ldr	r2, =resume_with_mmu
+	mcr	p15, 0, r9, c1, c0, 0		@ turn on MMU, etc
+	nop					@ second-to-last before mmu
+	mov	pc, r2				@ go back to virtual address
+
+	.ltorg
diff -Nru a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
--- a/arch/arm/mach-s3c2410/time.c	2004-10-28 22:25:57 -07:00
+++ b/arch/arm/mach-s3c2410/time.c	2004-10-28 22:25:57 -07:00
@@ -1,7 +1,7 @@
-/* linux/include/asm-arm/arch-s3c2410/time.h
+/* linux/arch/arm/mach-s3c2410/time.c
  *
- *  Copyright (C) 2003 Simtec Electronics <linux@simtec.co.uk>
- *    Ben Dooks, <ben@simtec.co.uk>
+ * Copyright (C) 2003,2004 Simtec Electronics
+ *	Ben Dooks, <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -39,10 +39,6 @@
 static unsigned long timer_startval;
 static unsigned long timer_ticks_usec;
 
-/* with an 12MHz clock, we get 12 ticks per-usec
- */
-
-
 /***
  * Returns microsecond  since last clock interrupt.  Note that interrupts
  * will have been disabled by do_gettimeoffset()
@@ -106,7 +102,7 @@
  * Currently we only use timer4, as it is the only timer which has no
  * other function that can be exploited externally
  */
-static void __init s3c2410_timer_init (void)
+static void s3c2410_timer_setup (void)
 {
 	unsigned long tcon;
 	unsigned long tcnt;
@@ -126,6 +122,9 @@
 	if (machine_is_bast() || machine_is_vr1000()) {
 		timer_ticks_usec = 12;	      /* timer is at 12MHz */
 		tcnt = (timer_ticks_usec * (1000*1000)) / HZ;
+
+		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
+		tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
 	}
 
 	/* for the h1940, we use the pclk from the core to generate
@@ -138,7 +137,8 @@
 	 *   of 11.25MHz, and a tcnt of 56250.
 	 */
 
-	if (machine_is_h1940() || machine_is_smdk2410() ) {
+	if (machine_is_h1940() || machine_is_smdk2410() ||
+	    machine_is_rx3715()) {
 		timer_ticks_usec = s3c24xx_pclk / (1000*1000);
 		timer_ticks_usec /= 6;
 
@@ -151,7 +151,6 @@
 		tcnt = (s3c24xx_pclk / 6) / HZ;
 	}
 
-
 	printk("setup_timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx\n",
 	       tcon, tcnt, tcfg0, tcfg1);
 
@@ -177,15 +176,20 @@
 	__raw_writel(tcnt, S3C2410_TCNTB(4));
 	__raw_writel(tcnt, S3C2410_TCMPB(4));
 
-	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
-
 	/* start the timer running */
 	tcon |= S3C2410_TCON_T4START;
 	tcon &= ~S3C2410_TCON_T4MANUALUPD;
 	__raw_writel(tcon, S3C2410_TCON);
 }
 
+static void __init s3c2410_timer_init (void)
+{
+	s3c2410_timer_setup();
+	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+}
+
 struct sys_timer s3c2410_timer = {
 	.init		= s3c2410_timer_init,
 	.offset		= s3c2410_gettimeoffset,
+	.resume		= s3c2410_timer_setup
 };
diff -Nru a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
--- a/arch/arm/mach-s3c2410/usb-simtec.c	2004-10-28 22:25:58 -07:00
+++ b/arch/arm/mach-s3c2410/usb-simtec.c	2004-10-28 22:25:58 -07:00
@@ -13,6 +13,7 @@
  *
  * Modifications:
  *	14-Sep-2004 BJD  Created
+ *	18-Oct-2004 BJD  Cleanups, and added code to report OC cleared
 */
 
 #define DEBUG
@@ -51,10 +52,8 @@
 {
 	pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
 
-	if (port == 1) {
+	if (port == 1)
 		s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
-		pr_debug("GPBDAT now %08x\n", __raw_readl(S3C2410_GPBDAT));
-	}
 }
 
 static irqreturn_t
@@ -67,6 +66,7 @@
 		s3c2410_report_oc(info, 3);
 	} else {
 		pr_debug("usb_simtec: over-current irq (oc cleared)\n");
+		s3c2410_report_oc(info, 0);
 	}
 
 	return IRQ_HANDLED;
@@ -77,16 +77,15 @@
 	int ret;
 
 	if (on) {
-		pr_debug("claiming usb overccurent\n");
 		ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT,
-				  "usb-oc", info);
+				  "USB Over-current", info);
 		if (ret != 0) {
 			printk(KERN_ERR "failed to request usb oc irq\n");
 		}
 
 		set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE);
 	} else {
-		free_irq(IRQ_USBOC, NULL);
+		free_irq(IRQ_USBOC, info);
 	}
 }
 
@@ -110,14 +109,5 @@
 
 	s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP);
 	s3c2410_gpio_setpin(S3C2410_GPB4, 1);
-
-	pr_debug("GPB: CON=%08x, DAT=%08x\n",
-		 __raw_readl(S3C2410_GPBCON), __raw_readl(S3C2410_GPBDAT));
-
-	if (0) {
-		s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
-				      S3C2410_MISCCR_USBDEV);
-	}
-
 	return 0;
 }
diff -Nru a/arch/cris/arch-v10/drivers/ide.c b/arch/cris/arch-v10/drivers/ide.c
--- a/arch/cris/arch-v10/drivers/ide.c	2004-10-28 22:25:58 -07:00
+++ b/arch/cris/arch-v10/drivers/ide.c	2004-10-28 22:25:58 -07:00
@@ -656,15 +656,9 @@
 
 	ata_tot_size = 0;
 
-	if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE) {
-		sg_init_one(&sg[0], rq->buffer, rq->nr_sectors * SECTOR_SIZE);
-		hwif->sg_nents = i = 1;
-	}
-	else
-	{
-		hwif->sg_nents = i = blk_rq_map_sg(drive->queue, rq, hwif->sg_table);
-	}
+	ide_map_sg(drive, rq);
 
+	i = hwif->sg_nents;
 
 	while(i) {
 		/*
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	2004-10-28 22:25:57 -07:00
+++ b/arch/i386/Makefile	2004-10-28 22:25:57 -07:00
@@ -25,7 +25,7 @@
 # prevent gcc from keeping the stack 16 byte aligned
 CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
 
-align := $(subst -functions=0,,$(call cc-option,-falign-functions=0,-malign-functions=0))
+align := $(cc-option-align)
 cflags-$(CONFIG_M386)		+= -march=i386
 cflags-$(CONFIG_M486)		+= -march=i486
 cflags-$(CONFIG_M586)		+= -march=i586
diff -Nru a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S
--- a/arch/i386/crypto/aes-i586-asm.S	2004-10-28 22:25:58 -07:00
+++ b/arch/i386/crypto/aes-i586-asm.S	2004-10-28 22:25:58 -07:00
@@ -61,7 +61,6 @@
 #define r3  edx
 #define r4  esi
 #define r5  edi
-#define r6  ebp
 
 #define eaxl  al
 #define eaxh  ah
@@ -84,60 +83,63 @@
 // output registers r0, r1, r4 or r5.  
 
 // Parameters:
+// table table base address
 //   %1  out_state[0]
 //   %2  out_state[1]
 //   %3  out_state[2]
 //   %4  out_state[3]
-//   %5  table base address
-//   %6  input register for the round (destroyed)
-//   %7  scratch register for the round
-
-#define do_col(a1, a2, a3, a4, a5, a6, a7)	\
-	movzx   %l(a6),%a7;			\
-	xor     a5(,%a7,4),%a1;			\
-	movzx   %h(a6),%a7;			\
-	shr     $16,%a6;			\
-	xor     a5+tlen(,%a7,4),%a2;		\
-	movzx   %l(a6),%a7;			\
-	movzx   %h(a6),%a6;			\
-	xor     a5+2*tlen(,%a7,4),%a3;		\
-	xor     a5+3*tlen(,%a6,4),%a4;
+//   idx input register for the round (destroyed)
+//   tmp scratch register for the round
+// sched key schedule
+
+#define do_col(table, a1,a2,a3,a4, idx, tmp)	\
+	movzx   %l(idx),%tmp;			\
+	xor     table(,%tmp,4),%a1;		\
+	movzx   %h(idx),%tmp;			\
+	shr     $16,%idx;			\
+	xor     table+tlen(,%tmp,4),%a2;	\
+	movzx   %l(idx),%tmp;			\
+	movzx   %h(idx),%idx;			\
+	xor     table+2*tlen(,%tmp,4),%a3;	\
+	xor     table+3*tlen(,%idx,4),%a4;
 
 // initialise output registers from the key schedule
-
-#define do_fcol(a1, a2, a3, a4, a5, a6, a7, a8)	\
-	mov     0 a8,%a1;			\
-	movzx   %l(a6),%a7;			\
-	mov     12 a8,%a2;			\
-	xor     a5(,%a7,4),%a1;			\
-	mov     4 a8,%a4;			\
-	movzx   %h(a6),%a7;			\
-	shr     $16,%a6;			\
-	xor     a5+tlen(,%a7,4),%a2;		\
-	movzx   %l(a6),%a7;			\
-	movzx   %h(a6),%a6;			\
-	xor     a5+3*tlen(,%a6,4),%a4;		\
-	mov     %a3,%a6;			\
-	mov     8 a8,%a3;			\
-	xor     a5+2*tlen(,%a7,4),%a3;
+// NB1: original value of a3 is in idx on exit
+// NB2: original values of a1,a2,a4 aren't used
+#define do_fcol(table, a1,a2,a3,a4, idx, tmp, sched) \
+	mov     0 sched,%a1;			\
+	movzx   %l(idx),%tmp;			\
+	mov     12 sched,%a2;			\
+	xor     table(,%tmp,4),%a1;		\
+	mov     4 sched,%a4;			\
+	movzx   %h(idx),%tmp;			\
+	shr     $16,%idx;			\
+	xor     table+tlen(,%tmp,4),%a2;	\
+	movzx   %l(idx),%tmp;			\
+	movzx   %h(idx),%idx;			\
+	xor     table+3*tlen(,%idx,4),%a4;	\
+	mov     %a3,%idx;			\
+	mov     8 sched,%a3;			\
+	xor     table+2*tlen(,%tmp,4),%a3;
 
 // initialise output registers from the key schedule
-
-#define do_icol(a1, a2, a3, a4, a5, a6, a7, a8)	\
-	mov     0 a8,%a1;			\
-	movzx   %l(a6),%a7;			\
-	mov     4 a8,%a2;			\
-	xor     a5(,%a7,4),%a1;			\
-	mov     12 a8,%a4;			\
-	movzx   %h(a6),%a7;			\
-	shr     $16,%a6;			\
-	xor     a5+tlen(,%a7,4),%a2;		\
-	movzx   %l(a6),%a7;			\
-	movzx   %h(a6),%a6;			\
-	xor     a5+3*tlen(,%a6,4),%a4;		\
-	mov     %a3,%a6;			\
-	mov     8 a8,%a3;			\
-	xor     a5+2*tlen(,%a7,4),%a3;
+// NB1: original value of a3 is in idx on exit
+// NB2: original values of a1,a2,a4 aren't used
+#define do_icol(table, a1,a2,a3,a4, idx, tmp, sched) \
+	mov     0 sched,%a1;			\
+	movzx   %l(idx),%tmp;			\
+	mov     4 sched,%a2;			\
+	xor     table(,%tmp,4),%a1;		\
+	mov     12 sched,%a4;			\
+	movzx   %h(idx),%tmp;			\
+	shr     $16,%idx;			\
+	xor     table+tlen(,%tmp,4),%a2;	\
+	movzx   %l(idx),%tmp;			\
+	movzx   %h(idx),%idx;			\
+	xor     table+3*tlen(,%idx,4),%a4;	\
+	mov     %a3,%idx;			\
+	mov     8 sched,%a3;			\
+	xor     table+2*tlen(,%tmp,4),%a3;
 
 
 // original Gladman had conditional saves to MMX regs.
@@ -147,44 +149,75 @@
 #define restore(a1, a2)		\
 	mov     4*a2(%esp),%a1
 
-// This macro performs a forward encryption cycle. It is entered with
-// the first previous round column values in r0, r1, r4 and r5 and
-// exits with the final values in the same registers, using the MMX
-// registers mm0-mm1 or the stack for temporary storage
-
-// mov current column values into the MMX registers
-#define fwd_rnd(arg, table)					\
-	/* mov current column values into the MMX registers */	\
-	mov     %r0,%r2;					\
-	save   (0,r1);						\
-	save   (1,r5);						\
-								\
-	/* compute new column values */				\
-	do_fcol(r0,r5,r4,r1,table, r2,r3, arg);			\
-	do_col (r4,r1,r0,r5,table, r2,r3);			\
-	restore(r2,0);						\
-	do_col (r1,r0,r5,r4,table, r2,r3);			\
-	restore(r2,1);						\
-	do_col (r5,r4,r1,r0,table, r2,r3);
-
-// This macro performs an inverse encryption cycle. It is entered with
-// the first previous round column values in r0, r1, r4 and r5 and
-// exits with the final values in the same registers, using the MMX
-// registers mm0-mm1 or the stack for temporary storage
-
-#define inv_rnd(arg, table)					\
-	/* mov current column values into the MMX registers */	\
-	mov     %r0,%r2;					\
-	save    (0,r1);						\
-	save    (1,r5);						\
-								\
-	/* compute new column values */				\
-	do_icol(r0,r1,r4,r5, table, r2,r3, arg);		\
-	do_col (r4,r5,r0,r1, table, r2,r3);			\
-	restore(r2,0);						\
-	do_col (r1,r4,r5,r0, table, r2,r3);			\
-	restore(r2,1);						\
-	do_col (r5,r0,r1,r4, table, r2,r3);
+// These macros perform a forward encryption cycle. They are entered with
+// the first previous round column values in r0,r1,r4,r5 and
+// exit with the final values in the same registers, using stack
+// for temporary storage.
+
+// round column values
+// on entry: r0,r1,r4,r5
+// on exit:  r2,r1,r4,r5
+#define fwd_rnd1(arg, table)						\
+	save   (0,r1);							\
+	save   (1,r5);							\
+									\
+	/* compute new column values */					\
+	do_fcol(table, r2,r5,r4,r1, r0,r3, arg);	/* idx=r0 */	\
+	do_col (table, r4,r1,r2,r5, r0,r3);		/* idx=r4 */	\
+	restore(r0,0);							\
+	do_col (table, r1,r2,r5,r4, r0,r3);		/* idx=r1 */	\
+	restore(r0,1);							\
+	do_col (table, r5,r4,r1,r2, r0,r3);		/* idx=r5 */
+
+// round column values
+// on entry: r2,r1,r4,r5
+// on exit:  r0,r1,r4,r5
+#define fwd_rnd2(arg, table)						\
+	save   (0,r1);							\
+	save   (1,r5);							\
+									\
+	/* compute new column values */					\
+	do_fcol(table, r0,r5,r4,r1, r2,r3, arg);	/* idx=r2 */	\
+	do_col (table, r4,r1,r0,r5, r2,r3);		/* idx=r4 */	\
+	restore(r2,0);							\
+	do_col (table, r1,r0,r5,r4, r2,r3);		/* idx=r1 */	\
+	restore(r2,1);							\
+	do_col (table, r5,r4,r1,r0, r2,r3);		/* idx=r5 */
+
+// These macros performs an inverse encryption cycle. They are entered with
+// the first previous round column values in r0,r1,r4,r5 and
+// exit with the final values in the same registers, using stack
+// for temporary storage
+
+// round column values
+// on entry: r0,r1,r4,r5
+// on exit:  r2,r1,r4,r5
+#define inv_rnd1(arg, table)						\
+	save    (0,r1);							\
+	save    (1,r5);							\
+									\
+	/* compute new column values */					\
+	do_icol(table, r2,r1,r4,r5, r0,r3, arg);	/* idx=r0 */	\
+	do_col (table, r4,r5,r2,r1, r0,r3);		/* idx=r4 */	\
+	restore(r0,0);							\
+	do_col (table, r1,r4,r5,r2, r0,r3);		/* idx=r1 */	\
+	restore(r0,1);							\
+	do_col (table, r5,r2,r1,r4, r0,r3);		/* idx=r5 */
+
+// round column values
+// on entry: r2,r1,r4,r5
+// on exit:  r0,r1,r4,r5
+#define inv_rnd2(arg, table)						\
+	save    (0,r1);							\
+	save    (1,r5);							\
+									\
+	/* compute new column values */					\
+	do_icol(table, r0,r1,r4,r5, r2,r3, arg);	/* idx=r2 */	\
+	do_col (table, r4,r5,r0,r1, r2,r3);		/* idx=r4 */	\
+	restore(r2,0);							\
+	do_col (table, r1,r4,r5,r0, r2,r3);		/* idx=r1 */	\
+	restore(r2,1);							\
+	do_col (table, r5,r0,r1,r4, r2,r3);		/* idx=r5 */
 
 // AES (Rijndael) Encryption Subroutine
 
@@ -198,7 +231,6 @@
 aes_enc_blk:
 	push    %ebp
 	mov     ctx(%esp),%ebp      // pointer to context
-	xor     %eax,%eax
 
 // CAUTION: the order and the values used in these assigns 
 // rely on the register mappings
@@ -208,7 +240,9 @@
 	push    %esi
 	mov     nrnd(%ebp),%r3   // number of rounds
 	push    %edi
-	lea     ekey(%ebp),%r6   // key pointer
+#if ekey != 0
+	lea     ekey(%ebp),%ebp  // key pointer
+#endif
 
 // input four columns and xor in first round key
 
@@ -216,47 +250,47 @@
 	mov     4(%r2),%r1
 	mov     8(%r2),%r4
 	mov     12(%r2),%r5
-	xor     (%r6),%r0
-	xor     4(%r6),%r1
-	xor     8(%r6),%r4
-	xor     12(%r6),%r5
+	xor     (%ebp),%r0
+	xor     4(%ebp),%r1
+	xor     8(%ebp),%r4
+	xor     12(%ebp),%r5
 
 	sub     $8,%esp           // space for register saves on stack
-	add     $16,%r6           // increment to next round key   
+	add     $16,%ebp          // increment to next round key
 	sub     $10,%r3          
 	je      4f              // 10 rounds for 128-bit key
-	add     $32,%r6
+	add     $32,%ebp
 	sub     $2,%r3
 	je      3f              // 12 rounds for 128-bit key
-	add     $32,%r6
+	add     $32,%ebp
 
-2:	fwd_rnd( -64(%r6) ,ft_tab)	// 14 rounds for 128-bit key
-	fwd_rnd( -48(%r6) ,ft_tab)
-3:	fwd_rnd( -32(%r6) ,ft_tab)	// 12 rounds for 128-bit key
-	fwd_rnd( -16(%r6) ,ft_tab)
-4:	fwd_rnd(    (%r6) ,ft_tab)	// 10 rounds for 128-bit key
-	fwd_rnd( +16(%r6) ,ft_tab)
-	fwd_rnd( +32(%r6) ,ft_tab)
-	fwd_rnd( +48(%r6) ,ft_tab)
-	fwd_rnd( +64(%r6) ,ft_tab)
-	fwd_rnd( +80(%r6) ,ft_tab)
-	fwd_rnd( +96(%r6) ,ft_tab)
-	fwd_rnd(+112(%r6) ,ft_tab)
-	fwd_rnd(+128(%r6) ,ft_tab)
-	fwd_rnd(+144(%r6) ,fl_tab)	// last round uses a different table
+2:	fwd_rnd1( -64(%ebp) ,ft_tab)	// 14 rounds for 128-bit key
+	fwd_rnd2( -48(%ebp) ,ft_tab)
+3:	fwd_rnd1( -32(%ebp) ,ft_tab)	// 12 rounds for 128-bit key
+	fwd_rnd2( -16(%ebp) ,ft_tab)
+4:	fwd_rnd1(    (%ebp) ,ft_tab)	// 10 rounds for 128-bit key
+	fwd_rnd2( +16(%ebp) ,ft_tab)
+	fwd_rnd1( +32(%ebp) ,ft_tab)
+	fwd_rnd2( +48(%ebp) ,ft_tab)
+	fwd_rnd1( +64(%ebp) ,ft_tab)
+	fwd_rnd2( +80(%ebp) ,ft_tab)
+	fwd_rnd1( +96(%ebp) ,ft_tab)
+	fwd_rnd2(+112(%ebp) ,ft_tab)
+	fwd_rnd1(+128(%ebp) ,ft_tab)
+	fwd_rnd2(+144(%ebp) ,fl_tab)	// last round uses a different table
 
 // move final values to the output array.  CAUTION: the 
 // order of these assigns rely on the register mappings
 
 	add     $8,%esp
-	mov     out_blk+12(%esp),%r6
-	mov     %r5,12(%r6)
+	mov     out_blk+12(%esp),%ebp
+	mov     %r5,12(%ebp)
 	pop     %edi
-	mov     %r4,8(%r6)
+	mov     %r4,8(%ebp)
 	pop     %esi
-	mov     %r1,4(%r6)
+	mov     %r1,4(%ebp)
 	pop     %ebx
-	mov     %r0,(%r6)
+	mov     %r0,(%ebp)
 	pop     %ebp
 	mov     $1,%eax
 	ret
@@ -273,7 +307,6 @@
 aes_dec_blk:
 	push    %ebp
 	mov     ctx(%esp),%ebp       // pointer to context
-	xor     %eax,%eax
 
 // CAUTION: the order and the values used in these assigns 
 // rely on the register mappings
@@ -283,10 +316,12 @@
 	push    %esi
 	mov     nrnd(%ebp),%r3   // number of rounds
 	push    %edi
-	lea     dkey(%ebp),%r6   // key pointer
+#if dkey != 0
+	lea     dkey(%ebp),%ebp  // key pointer
+#endif
 	mov     %r3,%r0
 	shl     $4,%r0
-	add     %r0,%r6
+	add     %r0,%ebp
 	
 // input four columns and xor in first round key
 
@@ -294,47 +329,47 @@
 	mov     4(%r2),%r1
 	mov     8(%r2),%r4
 	mov     12(%r2),%r5
-	xor     (%r6),%r0
-	xor     4(%r6),%r1
-	xor     8(%r6),%r4
-	xor     12(%r6),%r5
+	xor     (%ebp),%r0
+	xor     4(%ebp),%r1
+	xor     8(%ebp),%r4
+	xor     12(%ebp),%r5
 
-	sub     $8,%esp           // space for register saves on stack
-	sub     $16,%r6           // increment to next round key   
+	sub     $8,%esp         // space for register saves on stack
+	sub     $16,%ebp        // increment to next round key
 	sub     $10,%r3          
 	je      4f              // 10 rounds for 128-bit key
-	sub     $32,%r6
+	sub     $32,%ebp
 	sub     $2,%r3
 	je      3f              // 12 rounds for 128-bit key
-	sub     $32,%r6
+	sub     $32,%ebp
 
-2:	inv_rnd( +64(%r6), it_tab)	// 14 rounds for 128-bit key 
-	inv_rnd( +48(%r6), it_tab)
-3:	inv_rnd( +32(%r6), it_tab)	// 12 rounds for 128-bit key
-	inv_rnd( +16(%r6), it_tab)
-4:	inv_rnd(    (%r6), it_tab)	// 10 rounds for 128-bit key
-	inv_rnd( -16(%r6), it_tab)
-	inv_rnd( -32(%r6), it_tab)
-	inv_rnd( -48(%r6), it_tab)
-	inv_rnd( -64(%r6), it_tab)
-	inv_rnd( -80(%r6), it_tab)
-	inv_rnd( -96(%r6), it_tab)
-	inv_rnd(-112(%r6), it_tab)
-	inv_rnd(-128(%r6), it_tab)
-	inv_rnd(-144(%r6), il_tab)	// last round uses a different table
+2:	inv_rnd1( +64(%ebp), it_tab)	// 14 rounds for 128-bit key
+	inv_rnd2( +48(%ebp), it_tab)
+3:	inv_rnd1( +32(%ebp), it_tab)	// 12 rounds for 128-bit key
+	inv_rnd2( +16(%ebp), it_tab)
+4:	inv_rnd1(    (%ebp), it_tab)	// 10 rounds for 128-bit key
+	inv_rnd2( -16(%ebp), it_tab)
+	inv_rnd1( -32(%ebp), it_tab)
+	inv_rnd2( -48(%ebp), it_tab)
+	inv_rnd1( -64(%ebp), it_tab)
+	inv_rnd2( -80(%ebp), it_tab)
+	inv_rnd1( -96(%ebp), it_tab)
+	inv_rnd2(-112(%ebp), it_tab)
+	inv_rnd1(-128(%ebp), it_tab)
+	inv_rnd2(-144(%ebp), il_tab)	// last round uses a different table
 
 // move final values to the output array.  CAUTION: the 
 // order of these assigns rely on the register mappings
 
 	add     $8,%esp
-	mov     out_blk+12(%esp),%r6
-	mov     %r5,12(%r6)
+	mov     out_blk+12(%esp),%ebp
+	mov     %r5,12(%ebp)
 	pop     %edi
-	mov     %r4,8(%r6)
+	mov     %r4,8(%ebp)
 	pop     %esi
-	mov     %r1,4(%r6)
+	mov     %r1,4(%ebp)
 	pop     %ebx
-	mov     %r0,(%r6)
+	mov     %r0,(%ebp)
 	pop     %ebp
 	mov     $1,%eax
 	ret
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	2004-10-28 22:25:57 -07:00
+++ b/arch/i386/kernel/Makefile	2004-10-28 22:25:57 -07:00
@@ -5,9 +5,9 @@
 extra-y := head.o init_task.o vmlinux.lds
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
-		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
+		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
 		pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
-		doublefault.o
+		doublefault.o quirks.o
 
 obj-y				+= cpu/
 obj-y				+= timers/
diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
--- a/arch/i386/kernel/acpi/boot.c	2004-10-28 22:25:59 -07:00
+++ b/arch/i386/kernel/acpi/boot.c	2004-10-28 22:25:59 -07:00
@@ -40,7 +40,7 @@
 #ifdef	CONFIG_X86_64
 
 static inline void  acpi_madt_oem_check(char *oem_id, char *oem_table_id) { }
-static inline void clustered_apic_check(void) { }
+extern void __init clustered_apic_check(void);
 static inline int ioapic_setup_disabled(void) { return 0; }
 #include <asm/proto.h>
 
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c	2004-10-28 22:25:59 -07:00
+++ b/arch/i386/kernel/apic.c	2004-10-28 22:25:59 -07:00
@@ -300,6 +300,10 @@
 
 void __init sync_Arb_IDs(void)
 {
+	/* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
+	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
+	if (ver >= 0x14)	/* P4 or higher */
+		return;
 	/*
 	 * Wait for idle.
 	 */
diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
--- a/arch/i386/kernel/apm.c	2004-10-28 22:25:56 -07:00
+++ b/arch/i386/kernel/apm.c	2004-10-28 22:25:56 -07:00
@@ -2393,27 +2393,27 @@
 MODULE_AUTHOR("Stephen Rothwell");
 MODULE_DESCRIPTION("Advanced Power Management");
 MODULE_LICENSE("GPL");
-MODULE_PARM(debug, "i");
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Enable debug mode");
-MODULE_PARM(power_off, "i");
+module_param(power_off, bool, 0444);
 MODULE_PARM_DESC(power_off, "Enable power off");
-MODULE_PARM(bounce_interval, "i");
+module_param(bounce_interval, int, 0444);
 MODULE_PARM_DESC(bounce_interval,
 		"Set the number of ticks to ignore suspend bounces");
-MODULE_PARM(allow_ints, "i");
+module_param(allow_ints, bool, 0444);
 MODULE_PARM_DESC(allow_ints, "Allow interrupts during BIOS calls");
-MODULE_PARM(broken_psr, "i");
+module_param(broken_psr, bool, 0444);
 MODULE_PARM_DESC(broken_psr, "BIOS has a broken GetPowerStatus call");
-MODULE_PARM(realmode_power_off, "i");
+module_param(realmode_power_off, bool, 0444);
 MODULE_PARM_DESC(realmode_power_off,
 		"Switch to real mode before powering off");
-MODULE_PARM(idle_threshold, "i");
+module_param(idle_threshold, int, 0444);
 MODULE_PARM_DESC(idle_threshold,
 	"System idle percentage above which to make APM BIOS idle calls");
-MODULE_PARM(idle_period, "i");
+module_param(idle_period, int, 0444);
 MODULE_PARM_DESC(idle_period,
 	"Period (in sec/100) over which to caculate the idle percentage");
-MODULE_PARM(smp, "i");
+module_param(smp, bool, 0444);
 MODULE_PARM_DESC(smp,
 	"Set this to enable APM use on an SMP platform. Use with caution on older systems");
 MODULE_ALIAS_MISCDEV(APM_MINOR_DEV);
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	2004-10-28 22:25:57 -07:00
+++ b/arch/i386/kernel/entry.S	2004-10-28 22:25:57 -07:00
@@ -187,8 +187,8 @@
 	movl $PREEMPT_ACTIVE,TI_preempt_count(%ebp)
 	sti
 	call schedule
-	movl $0,TI_preempt_count(%ebp)
 	cli
+	movl $0,TI_preempt_count(%ebp)
 	jmp need_resched
 #endif
 
@@ -867,7 +867,7 @@
 	.long sys_mq_getsetattr
 	.long sys_ni_syscall		/* reserved for kexec */
 	.long sys_waitid
-	.long sys_setaltroot		/* 285 */
+	.long sys_ni_syscall		/* 285 */ /* available */
 	.long sys_add_key
 	.long sys_request_key
 	.long sys_keyctl
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	2004-10-28 22:25:59 -07:00
+++ b/arch/i386/kernel/i386_ksyms.c	2004-10-28 22:25:59 -07:00
@@ -71,7 +71,6 @@
 #endif
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(dump_extended_fpu);
 EXPORT_SYMBOL_GPL(kernel_fpu_begin);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(ioremap_nocache);
diff -Nru a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
--- a/arch/i386/kernel/i387.c	2004-10-28 22:25:59 -07:00
+++ b/arch/i386/kernel/i387.c	2004-10-28 22:25:59 -07:00
@@ -519,21 +519,6 @@
 	return fpvalid;
 }
 
-int dump_extended_fpu( struct pt_regs *regs, struct user_fxsr_struct *fpu )
-{
-	int fpvalid;
-	struct task_struct *tsk = current;
-
-	fpvalid = tsk->used_math && cpu_has_fxsr;
-	if ( fpvalid ) {
-		unlazy_fpu( tsk );
-		memcpy( fpu, &tsk->thread.i387.fxsave,
-			sizeof(struct user_fxsr_struct) );
-	}
-
-	return fpvalid;
-}
-
 int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
 {
 	int fpvalid = tsk->used_math;
diff -Nru a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/i386/kernel/quirks.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,49 @@
+/*
+ * This file contains work-arounds for x86 and x86_64 platform bugs.
+ */
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
+
+void __init quirk_intel_irqbalance(struct pci_dev *dev)
+{
+	u8 config, rev;
+	u32 word;
+
+	/* BIOS may enable hardware IRQ balancing for
+	 * E7520/E7320/E7525(revision ID 0x9 and below)
+	 * based platforms.
+	 * Disable SW irqbalance/affinity on those platforms.
+	 */
+	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
+	if (rev > 0x9)
+		return;
+
+	printk(KERN_INFO "Intel E7520/7320/7525 detected.");
+
+	/* enable access to config space*/
+	pci_read_config_byte(dev, 0xf4, &config);
+	config |= 0x2;
+	pci_write_config_byte(dev, 0xf4, config);
+
+	/* read xTPR register */
+	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+
+	if (!(word & (1 << 13))) {
+		printk(KERN_INFO "Disabling irq balancing and affinity\n");
+#ifdef CONFIG_IRQBALANCE
+		irqbalance_disable("");
+#endif
+		noirqdebug_setup("");
+		no_irq_affinity = 1;
+	}
+
+	config &= ~0x2;
+	/* disable access to config space*/
+	pci_write_config_byte(dev, 0xf4, config);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_intel_irqbalance);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_SMCH,	quirk_intel_irqbalance);
+#endif
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	2004-10-28 22:25:58 -07:00
+++ b/arch/i386/kernel/signal.c	2004-10-28 22:25:58 -07:00
@@ -600,7 +600,9 @@
 		 * have been cleared if the watchpoint triggered
 		 * inside the kernel.
 		 */
-		__asm__("movl %0,%%db7"	: : "r" (current->thread.debugreg[7]));
+		if (unlikely(current->thread.debugreg[7])) {
+			__asm__("movl %0,%%db7"	: : "r" (current->thread.debugreg[7]));
+		}
 
 		/* Whee!  Actually deliver the signal.  */
 		handle_signal(signr, &info, &ka, oldset, regs);
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c	2004-10-28 22:25:58 -07:00
+++ b/arch/i386/kernel/time.c	2004-10-28 22:25:58 -07:00
@@ -321,7 +321,7 @@
 
 static long clock_cmos_diff, sleep_start;
 
-static int time_suspend(struct sys_device *dev, u32 state)
+static int timer_suspend(struct sys_device *dev, u32 state)
 {
 	/*
 	 * Estimate time zone so that set_time can update the clock
@@ -332,12 +332,18 @@
 	return 0;
 }
 
-static int time_resume(struct sys_device *dev)
+static int timer_resume(struct sys_device *dev)
 {
 	unsigned long flags;
-	unsigned long sec = get_cmos_time() + clock_cmos_diff;
-	unsigned long sleep_length = get_cmos_time() - sleep_start;
+	unsigned long sec;
+	unsigned long sleep_length;
 
+#ifdef CONFIG_HPET_TIMER
+	if (is_hpet_enabled())
+		hpet_reenable();
+#endif
+	sec = get_cmos_time() + clock_cmos_diff;
+	sleep_length = get_cmos_time() - sleep_start;
 	write_seqlock_irqsave(&xtime_lock, flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
@@ -346,24 +352,24 @@
 	return 0;
 }
 
-static struct sysdev_class pit_sysclass = {
-	.resume = time_resume,
-	.suspend = time_suspend,
-	set_kset_name("pit"),
+static struct sysdev_class timer_sysclass = {
+	.resume = timer_resume,
+	.suspend = timer_suspend,
+	set_kset_name("timer"),
 };
 
 
 /* XXX this driverfs stuff should probably go elsewhere later -john */
-static struct sys_device device_i8253 = {
+static struct sys_device device_timer = {
 	.id	= 0,
-	.cls	= &pit_sysclass,
+	.cls	= &timer_sysclass,
 };
 
 static int time_init_device(void)
 {
-	int error = sysdev_class_register(&pit_sysclass);
+	int error = sysdev_class_register(&timer_sysclass);
 	if (!error)
-		error = sysdev_register(&device_i8253);
+		error = sysdev_register(&device_timer);
 	return error;
 }
 
diff -Nru a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
--- a/arch/i386/kernel/time_hpet.c	2004-10-28 22:25:57 -07:00
+++ b/arch/i386/kernel/time_hpet.c	2004-10-28 22:25:57 -07:00
@@ -60,13 +60,46 @@
 }
 #endif
 
+static int hpet_timer_stop_set_go(unsigned long tick)
+{
+	unsigned int cfg;
+
+	/*
+	 * Stop the timers and reset the main counter.
+	 */
+	cfg = hpet_readl(HPET_CFG);
+	cfg &= ~HPET_CFG_ENABLE;
+	hpet_writel(cfg, HPET_CFG);
+	hpet_writel(0, HPET_COUNTER);
+	hpet_writel(0, HPET_COUNTER + 4);
+
+	/*
+	 * Set up timer 0, as periodic with first interrupt to happen at
+	 * hpet_tick, and period also hpet_tick.
+	 */
+	cfg = hpet_readl(HPET_T0_CFG);
+	cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
+	       HPET_TN_SETVAL | HPET_TN_32BIT;
+	hpet_writel(cfg, HPET_T0_CFG);
+	hpet_writel(tick, HPET_T0_CMP);
+
+	/*
+ 	 * Go!
+ 	 */
+	cfg = hpet_readl(HPET_CFG);
+	cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
+	hpet_writel(cfg, HPET_CFG);
+
+	return 0;
+}
+
 /*
  * Check whether HPET was found by ACPI boot parse. If yes setup HPET
  * counter 0 for kernel base timer.
  */
 int __init hpet_enable(void)
 {
-	unsigned int cfg, id;
+	unsigned int id;
 	unsigned long tick_fsec_low, tick_fsec_high; /* tick in femto sec */
 	unsigned long hpet_tick_rem;
 
@@ -108,31 +141,8 @@
 	if (hpet_tick_rem > (hpet_period >> 1))
 		hpet_tick++; /* rounding the result */
 
-	/*
-	 * Stop the timers and reset the main counter.
-	 */
-	cfg = hpet_readl(HPET_CFG);
-	cfg &= ~HPET_CFG_ENABLE;
-	hpet_writel(cfg, HPET_CFG);
-	hpet_writel(0, HPET_COUNTER);
-	hpet_writel(0, HPET_COUNTER + 4);
-
-	/*
-	 * Set up timer 0, as periodic with first interrupt to happen at
-	 * hpet_tick, and period also hpet_tick.
-	 */
-	cfg = hpet_readl(HPET_T0_CFG);
-	cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
-	       HPET_TN_SETVAL | HPET_TN_32BIT;
-	hpet_writel(cfg, HPET_T0_CFG);
-	hpet_writel(hpet_tick, HPET_T0_CMP);
-
-	/*
- 	 * Go!
- 	 */
-	cfg = hpet_readl(HPET_CFG);
-	cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
-	hpet_writel(cfg, HPET_CFG);
+	if (hpet_timer_stop_set_go(hpet_tick))
+		return -1;
 
 	use_hpet = 1;
 
@@ -183,6 +193,11 @@
 	wait_timer_tick = wait_hpet_tick;
 #endif
 	return 0;
+}
+
+int hpet_reenable(void)
+{
+	return hpet_timer_stop_set_go(hpet_tick);
 }
 
 int is_hpet_enabled(void)
diff -Nru a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c
--- a/arch/i386/mach-voyager/voyager_basic.c	2004-10-28 22:25:57 -07:00
+++ b/arch/i386/mach-voyager/voyager_basic.c	2004-10-28 22:25:57 -07:00
@@ -53,7 +53,7 @@
 static struct sysrq_key_op sysrq_voyager_dump_op = {
 	.handler	= voyager_dump,
 	.help_msg	= "Voyager",
-	.action_msg	= "Dump Voyager Status\n",
+	.action_msg	= "Dump Voyager Status",
 };
 #endif
 
diff -Nru a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
--- a/arch/i386/mm/hugetlbpage.c	2004-10-28 22:25:59 -07:00
+++ b/arch/i386/mm/hugetlbpage.c	2004-10-28 22:25:59 -07:00
@@ -282,3 +282,143 @@
 	spin_unlock(&mm->page_table_lock);
 	return ret;
 }
+
+/* x86_64 also uses this file */
+
+#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
+		unsigned long addr, unsigned long len,
+		unsigned long pgoff, unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long start_addr;
+
+	start_addr = mm->free_area_cache;
+
+full_search:
+	addr = ALIGN(start_addr, HPAGE_SIZE);
+
+	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+		/* At this point:  (!vma || addr < vma->vm_end). */
+		if (TASK_SIZE - len < addr) {
+			/*
+			 * Start a new search - just in case we missed
+			 * some holes.
+			 */
+			if (start_addr != TASK_UNMAPPED_BASE) {
+				start_addr = TASK_UNMAPPED_BASE;
+				goto full_search;
+			}
+			return -ENOMEM;
+		}
+		if (!vma || addr + len <= vma->vm_start) {
+			mm->free_area_cache = addr + len;
+			return addr;
+		}
+		addr = ALIGN(vma->vm_end, HPAGE_SIZE);
+	}
+}
+
+static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
+		unsigned long addr0, unsigned long len,
+		unsigned long pgoff, unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma, *prev_vma;
+	unsigned long base = mm->mmap_base, addr = addr0;
+	int first_time = 1;
+
+	/* don't allow allocations above current base */
+	if (mm->free_area_cache > base)
+		mm->free_area_cache = base;
+
+try_again:
+	/* make sure it can fit in the remaining address space */
+	if (mm->free_area_cache < len)
+		goto fail;
+
+	/* either no address requested or cant fit in requested address hole */
+	addr = (mm->free_area_cache - len) & HPAGE_MASK;
+	do {
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * i.e. return with success:
+		 */
+		if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+			return addr;
+
+		/*
+		 * new region fits between prev_vma->vm_end and
+		 * vma->vm_start, use it:
+		 */
+		if (addr + len <= vma->vm_start &&
+				(!prev_vma || (addr >= prev_vma->vm_end)))
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+		else
+			/* pull free_area_cache down to the first hole */
+			if (mm->free_area_cache == vma->vm_end)
+				mm->free_area_cache = vma->vm_start;
+
+		/* try just below the current vma->vm_start */
+		addr = (vma->vm_start - len) & HPAGE_MASK;
+	} while (len <= vma->vm_start);
+
+fail:
+	/*
+	 * if hint left us with no space for the requested
+	 * mapping then try again:
+	 */
+	if (first_time) {
+		mm->free_area_cache = base;
+		first_time = 0;
+		goto try_again;
+	}
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
+			len, pgoff, flags);
+
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = base;
+
+	return addr;
+}
+
+unsigned long
+hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+
+	if (len & ~HPAGE_MASK)
+		return -EINVAL;
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (addr) {
+		addr = ALIGN(addr, HPAGE_SIZE);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+	if (mm->get_unmapped_area == arch_get_unmapped_area)
+		return hugetlb_get_unmapped_area_bottomup(file, addr, len,
+				pgoff, flags);
+	else
+		return hugetlb_get_unmapped_area_topdown(file, addr, len,
+				pgoff, flags);
+}
+
+#endif /*HAVE_ARCH_HUGETLB_UNMAPPED_AREA*/
+
diff -Nru a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
--- a/arch/ia64/ia32/elfcore32.h	2004-10-28 22:25:58 -07:00
+++ b/arch/ia64/ia32/elfcore32.h	2004-10-28 22:25:58 -07:00
@@ -9,6 +9,7 @@
 #define _ELFCORE32_H_
 
 #include <asm/intrinsics.h>
+#include <asm/uaccess.h>
 
 #define USE_ELF_CORE_DUMP 1
 
diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
--- a/arch/ia64/kernel/efi.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ia64/kernel/efi.c	2004-10-28 22:25:56 -07:00
@@ -28,6 +28,7 @@
 
 #include <asm/io.h>
 #include <asm/kregs.h>
+#include <asm/meminit.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/mca.h>
@@ -324,12 +325,12 @@
 		 * [granule_addr - first_non_wb_addr) is guaranteed to
 		 * be contiguous WB memory.
 		 */
-		granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1);
+		granule_addr = GRANULEROUNDDOWN(md->phys_addr);
 		first_non_wb_addr = max(first_non_wb_addr, granule_addr);
 
 		if (first_non_wb_addr < md->phys_addr) {
 			trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
-			granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1);
+			granule_addr = GRANULEROUNDDOWN(md->phys_addr);
 			first_non_wb_addr = max(first_non_wb_addr, granule_addr);
 		}
 
@@ -343,24 +344,36 @@
 				break;		/* non-WB or hole */
 		}
 
-		last_granule_addr = first_non_wb_addr & ~(IA64_GRANULE_SIZE - 1);
+		last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr);
 		if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT))
 			trim_top(md, last_granule_addr);
 
 		if (is_available_memory(md)) {
-			if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > max_addr) {
-				if (md->phys_addr > max_addr)
+			if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) {
+				if (md->phys_addr >= max_addr)
 					continue;
 				md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
+				first_non_wb_addr = max_addr;
 			}
 
 			if (total_mem >= mem_limit)
 				continue;
-			total_mem += (md->num_pages << EFI_PAGE_SHIFT);
-			if (total_mem > mem_limit) {
-				md->num_pages -= ((total_mem - mem_limit) >> EFI_PAGE_SHIFT);
-				max_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+
+			if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
+				unsigned long limit_addr = md->phys_addr;
+
+				limit_addr += mem_limit - total_mem;
+				limit_addr = GRANULEROUNDDOWN(limit_addr);
+
+				if (md->phys_addr > limit_addr)
+					continue;
+
+				md->num_pages = (limit_addr - md->phys_addr) >>
+				                EFI_PAGE_SHIFT;
+				first_non_wb_addr = max_addr = md->phys_addr +
+				              (md->num_pages << EFI_PAGE_SHIFT);
 			}
+			total_mem += (md->num_pages << EFI_PAGE_SHIFT);
 
 			if (md->num_pages == 0)
 				continue;
@@ -495,13 +508,13 @@
 	for (cp = saved_command_line; *cp; ) {
 		if (memcmp(cp, "mem=", 4) == 0) {
 			cp += 4;
-			mem_limit = memparse(cp, &end) - 2;
+			mem_limit = memparse(cp, &end);
 			if (end != cp)
 				break;
 			cp = end;
 		} else if (memcmp(cp, "max_addr=", 9) == 0) {
 			cp += 9;
-			max_addr = memparse(cp, &end) - 1;
+			max_addr = GRANULEROUNDDOWN(memparse(cp, &end));
 			if (end != cp)
 				break;
 			cp = end;
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	2004-10-28 22:25:57 -07:00
+++ b/arch/ia64/kernel/entry.S	2004-10-28 22:25:57 -07:00
@@ -1527,7 +1527,7 @@
 	data8 sys_mq_getsetattr
 	data8 sys_ni_syscall			// reserved for kexec_load
 	data8 sys_ni_syscall
-	data8 sys_setaltroot			// 1270
+	data8 sys_ni_syscall			// 1270
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
diff -Nru a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
--- a/arch/ia64/kernel/mca_asm.S	2004-10-28 22:25:59 -07:00
+++ b/arch/ia64/kernel/mca_asm.S	2004-10-28 22:25:59 -07:00
@@ -868,7 +868,7 @@
 
 
 GLOBAL_ENTRY(ia64_monarch_init_handler)
-
+	.prologue
 	// stash the information the SAL passed to os
 	SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)
 	;;
@@ -907,6 +907,7 @@
 	adds out0=16,sp				// out0 = pointer to pt_regs
 	;;
 	DO_SAVE_SWITCH_STACK
+	.body
 	adds out1=16,sp				// out0 = pointer to switch_stack
 
 	br.call.sptk.many rp=ia64_init_handler
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ia64/kernel/perfmon.c	2004-10-28 22:25:59 -07:00
@@ -1638,7 +1638,7 @@
 }
 
 /*
- * context is locked when coming here and interrupts are disabled
+ * interrupt cannot be masked when coming here
  */
 static inline int
 pfm_do_fasync(int fd, struct file *filp, pfm_context_t *ctx, int on)
@@ -2270,7 +2270,7 @@
 	 * 	return -ENOMEM;
 	 */
 	if (size > task->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
-		return -EAGAIN;
+		return -ENOMEM;
 
 	/*
 	 * We do the easy to undo allocations first.
@@ -2295,10 +2295,6 @@
 
 	/*
 	 * partially initialize the vma for the sampling buffer
-	 *
-	 * The VM_DONTCOPY flag is very important as it ensures that the mapping
-	 * will never be inherited for any child process (via fork()) which is always
-	 * what we want.
 	 */
 	vma->vm_mm	     = mm;
 	vma->vm_flags	     = VM_READ| VM_MAYREAD |VM_RESERVED;
@@ -2328,6 +2324,7 @@
 		goto error;
 	}
 	vma->vm_end = vma->vm_start + size;
+	vma->vm_pgoff = vma->vm_start >> PAGE_SHIFT;
 
 	DPRINT(("aligned size=%ld, hdr=%p mapped @0x%lx\n", size, ctx->ctx_smpl_hdr, vma->vm_start));
 
@@ -3060,11 +3057,12 @@
 #endif
 		}
 
-		DPRINT(("pmc[%u]=0x%lx loaded=%d access_pmu=%d all_pmcs=0x%lx used_pmds=0x%lx eventid=%ld smpl_pmds=0x%lx reset_pmds=0x%lx reloads_pmcs=0x%lx used_monitors=0x%lx ovfl_regs=0x%lx\n",
+		DPRINT(("pmc[%u]=0x%lx ld=%d apmu=%d flags=0x%lx all_pmcs=0x%lx used_pmds=0x%lx eventid=%ld smpl_pmds=0x%lx reset_pmds=0x%lx reloads_pmcs=0x%lx used_monitors=0x%lx ovfl_regs=0x%lx\n",
 			  cnum,
 			  value,
 			  is_loaded,
 			  can_access_pmu,
+			  flags,
 			  ctx->ctx_all_pmcs[0],
 			  ctx->ctx_used_pmds[0],
 			  ctx->ctx_pmds[cnum].eventid,
@@ -3240,8 +3238,8 @@
 			}
 		}
 
-		DPRINT(("pmd[%u]=0x%lx loaded=%d access_pmu=%d, hw_value=0x%lx ctx_pmd=0x%lx  short_reset=0x%lx "
-			  "long_reset=0x%lx notify=%c used_pmds=0x%lx reset_pmds=0x%lx reload_pmds=0x%lx all_pmds=0x%lx ovfl_regs=0x%lx\n",
+		DPRINT(("pmd[%u]=0x%lx ld=%d apmu=%d, hw_value=0x%lx ctx_pmd=0x%lx  short_reset=0x%lx "
+			  "long_reset=0x%lx notify=%c seed=0x%lx mask=0x%lx used_pmds=0x%lx reset_pmds=0x%lx reload_pmds=0x%lx all_pmds=0x%lx ovfl_regs=0x%lx\n",
 			cnum,
 			value,
 			is_loaded,
@@ -3251,6 +3249,8 @@
 			ctx->ctx_pmds[cnum].short_reset,
 			ctx->ctx_pmds[cnum].long_reset,
 			PMC_OVFL_NOTIFY(ctx, cnum) ? 'Y':'N',
+			ctx->ctx_pmds[cnum].seed,
+			ctx->ctx_pmds[cnum].mask,
 			ctx->ctx_used_pmds[0],
 			ctx->ctx_pmds[cnum].reset_pmds[0],
 			ctx->ctx_reload_pmds[0],
@@ -3328,7 +3328,7 @@
 	}
 	expert_mode = pfm_sysctl.expert_mode; 
 
-	DPRINT(("loaded=%d access_pmu=%d ctx_state=%d\n",
+	DPRINT(("ld=%d apmu=%d ctx_state=%d\n",
 		is_loaded,
 		can_access_pmu,
 		state));
@@ -3868,7 +3868,7 @@
 
 			ctx->ctx_ibrs[rnum] = dbreg.val;
 
-			DPRINT(("write ibr%u=0x%lx used_ibrs=0x%x is_loaded=%d access_pmu=%d\n",
+			DPRINT(("write ibr%u=0x%lx used_ibrs=0x%x ld=%d apmu=%d\n",
 				rnum, dbreg.val, ctx->ctx_used_ibrs[0], is_loaded, can_access_pmu));
 		} else {
 			CTX_USED_DBR(ctx, rnum);
@@ -3879,7 +3879,7 @@
 			}
 			ctx->ctx_dbrs[rnum] = dbreg.val;
 
-			DPRINT(("write dbr%u=0x%lx used_dbrs=0x%x is_loaded=%d access_pmu=%d\n",
+			DPRINT(("write dbr%u=0x%lx used_dbrs=0x%x ld=%d apmu=%d\n",
 				rnum, dbreg.val, ctx->ctx_used_dbrs[0], is_loaded, can_access_pmu));
 		}
 	}
@@ -5851,14 +5851,6 @@
 		pfm_unprotect_ctx_ctxsw(ctx, flags);
 
 		pfm_context_free(ctx);
-		return;
-	}
-
-	/*
-	 * sanity check
-	 */
-	if (ctx->ctx_last_activation != GET_ACTIVATION()) {
-		pfm_unprotect_ctx_ctxsw(ctx, flags);
 		return;
 	}
 
diff -Nru a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c
--- a/arch/ia64/lib/io.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ia64/lib/io.c	2004-10-28 22:25:56 -07:00
@@ -73,6 +73,7 @@
 #undef __ia64_writew
 #undef __ia64_writel
 #undef __ia64_writeq
+#undef __ia64_mmiowb
 
 unsigned int
 __ia64_inb (unsigned long port)
@@ -156,6 +157,12 @@
 __ia64_readq_relaxed (void __iomem *addr)
 {
 	return ___ia64_readq (addr);
+}
+
+void
+__ia64_mmiowb(void)
+{
+	___ia64_mmiowb();
 }
 
 #endif /* CONFIG_IA64_GENERIC */
diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
--- a/arch/ia64/mm/discontig.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ia64/mm/discontig.c	2004-10-28 22:25:59 -07:00
@@ -602,7 +602,7 @@
  * for each piece of usable memory and will setup these values for each node.
  * Very similar to build_maps().
  */
-static int count_node_pages(unsigned long start, unsigned long len, int node)
+static __init int count_node_pages(unsigned long start, unsigned long len, int node)
 {
 	unsigned long end = start + len;
 
@@ -627,7 +627,7 @@
  * paging_init() sets up the page tables for each node of the system and frees
  * the bootmem allocator memory for general use.
  */
-void paging_init(void)
+void __init paging_init(void)
 {
 	unsigned long max_dma;
 	unsigned long zones_size[MAX_NR_ZONES];
diff -Nru a/arch/ia64/sn/kernel/idle.c b/arch/ia64/sn/kernel/idle.c
--- a/arch/ia64/sn/kernel/idle.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ia64/sn/kernel/idle.c	2004-10-28 22:25:59 -07:00
@@ -3,14 +3,13 @@
  * 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) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
  */
 
-#include <linux/config.h>
 #include <asm/sn/leds.h>
-#include <asm/sn/simulator.h>
 
-void snidle(int state) {
+void snidle(int state)
+{
 	if (state) {
 		if (pda->idle_flag == 0) {
 			/* 
@@ -18,11 +17,6 @@
 			 */
 			set_led_bits(0, LED_CPU_ACTIVITY);
 		}
-
-#ifdef CONFIG_IA64_SGI_SN_SIM
-		if (IS_RUNNING_ON_SIMULATOR())
-			SIMULATOR_SLEEP();
-#endif
 
 		pda->idle_flag = 1;
 	} else {
diff -Nru a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
--- a/arch/ia64/sn/kernel/io_init.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ia64/sn/kernel/io_init.c	2004-10-28 22:25:58 -07:00
@@ -204,10 +204,12 @@
 	SN_PCIDEV_INFO(dev) = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
 	if (SN_PCIDEV_INFO(dev) <= 0)
 		BUG();		/* Cannot afford to run out of memory */
+	memset(SN_PCIDEV_INFO(dev), 0, sizeof(struct pcidev_info));
 
 	sn_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
 	if (sn_irq_info <= 0)
 		BUG();		/* Cannot afford to run out of memory */
+	memset(sn_irq_info, 0, sizeof(struct sn_irq_info));
 
 	/* Call to retrieve pci device information needed by kernel. */
 	status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, 
@@ -248,7 +250,7 @@
 	SN_PCIDEV_INFO(dev)->pdi_pcibus_info = SN_PCIBUS_BUSSOFT(dev->bus);
 
 	/* Only set up IRQ stuff if this device has a host bus context */
-	if (SN_PCIDEV_BUSSOFT(dev)) {
+	if (SN_PCIDEV_BUSSOFT(dev) && sn_irq_info->irq_irq) {
 		SN_PCIDEV_INFO(dev)->pdi_sn_irq_info = sn_irq_info;
 		dev->irq = SN_PCIDEV_INFO(dev)->pdi_sn_irq_info->irq_irq;
 		sn_irq_fixup(dev, sn_irq_info);
diff -Nru a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c
--- a/arch/ia64/sn/kernel/iomv.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ia64/sn/kernel/iomv.c	2004-10-28 22:25:58 -07:00
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <asm/io.h>
 #include <asm/delay.h>
+#include <asm/sn/nodepda.h>
 #include <asm/sn/simulator.h>
 #include <asm/sn/pda.h>
 #include <asm/sn/sn_cpuid.h>
@@ -54,19 +55,16 @@
 EXPORT_SYMBOL(sn_io_addr);
 
 /**
- * sn_mmiob - I/O space memory barrier
+ * __sn_mmiowb - I/O space memory barrier
  *
- * Acts as a memory mapped I/O barrier for platforms that queue writes to 
- * I/O space.  This ensures that subsequent writes to I/O space arrive after
- * all previous writes.  For most ia64 platforms, this is a simple
- * 'mf.a' instruction.  For other platforms, mmiob() may have to read
- * a chipset register to ensure ordering.
+ * See include/asm-ia64/io.h and Documentation/DocBook/deviceiobook.tmpl
+ * for details.
  *
  * On SN2, we wait for the PIO_WRITE_STATUS SHub register to clear.
  * See PV 871084 for details about the WAR about zero value.
  *
  */
-void sn_mmiob(void)
+void __sn_mmiowb(void)
 {
 	while ((((volatile unsigned long)(*pda->pio_write_status_addr)) &
 		SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) !=
@@ -74,4 +72,4 @@
 		cpu_relax();
 }
 
-EXPORT_SYMBOL(sn_mmiob);
+EXPORT_SYMBOL(__sn_mmiowb);
diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
--- a/arch/ia64/sn/kernel/irq.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ia64/sn/kernel/irq.c	2004-10-28 22:25:57 -07:00
@@ -79,7 +79,7 @@
 	int nasid;
 
 	irq = irq & 0xff;
-	nasid = smp_physical_node_id();
+	nasid = get_nasid();
 	event_occurred =
 	    HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED));
 	if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
@@ -109,7 +109,7 @@
 
 	ivec = irq & 0xff;
 	if (ivec == SGI_UART_VECTOR) {
-		nasid = smp_physical_node_id();
+		nasid = get_nasid();
 		event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR
 				       (nasid, SH_EVENT_OCCURRED));
 		/* If the UART bit is set here, we may have received an 
@@ -141,8 +141,8 @@
 
 	cpuid = first_cpu(mask);
 	cpuphys = cpu_physical_id(cpuid);
-	t_nasid = cpu_physical_id_to_nasid(cpuphys);
-	t_slice = cpu_physical_id_to_slice(cpuphys);
+	t_nasid = cpuid_to_nasid(cpuid);
+	t_slice = cpuid_to_slice(cpuid);
 
 	while (sn_irq_info) {
 		int status;
diff -Nru a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c
--- a/arch/ia64/sn/kernel/mca.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ia64/sn/kernel/mca.c	2004-10-28 22:25:57 -07:00
@@ -94,15 +94,11 @@
 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;
 	sn_oemdata_bufsize = 0;
-	ia64_sn_plat_specific_err_print(print_hook, (char *)psei);
+	ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header);
 	up(&sn_oemdata_mutex);
 	return 0;
 }
@@ -110,18 +106,24 @@
 /* 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)
+int sn_salinfo_platform_oemdata(const u8 *sect_header, u8 **oemdata, u64 *oemdata_size)
 {
-	efi_guid_t guid = *(efi_guid_t *) sect_header;
+	efi_guid_t guid = *(efi_guid_t *)sect_header;
+	int valid = 0;
 	*oemdata_size = 0;
 	vfree(*oemdata);
 	*oemdata = NULL;
-	if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0 ||
-	    efi_guidcmp(guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0)
-		return sn_platform_plat_specific_err_print(sect_header, oemdata,
-							   oemdata_size);
-	return 0;
+	if (efi_guidcmp(guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) {
+		sal_log_plat_specific_err_info_t *psei = (sal_log_plat_specific_err_info_t *)sect_header;
+		valid = psei->valid.oem_data;
+	} else if (efi_guidcmp(guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) {
+		sal_log_mem_dev_err_info_t *mdei = (sal_log_mem_dev_err_info_t *)sect_header;
+		valid = mdei->valid.oem_data;
+	}
+	if (valid)
+		return sn_platform_plat_specific_err_print(sect_header, oemdata, oemdata_size);
+	else
+		return 0;
 }
 
 static int __init sn_salinfo_init(void)
diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ia64/sn/kernel/setup.c	2004-10-28 22:25:57 -07:00
@@ -128,6 +128,19 @@
 #endif
 
 /*
+ * Get nasid of current cpu early in boot before nodepda is initialized
+ */
+static int
+boot_get_nasid(void)
+{
+	int nasid;
+
+	if (ia64_sn_get_sapic_info(get_sapicid(), &nasid, NULL, NULL))
+		BUG();
+	return nasid;
+}
+
+/*
  * This routine can only be used during init, since
  * smp_boot_data is an init data structure.
  * We have to use smp_boot_data.cpu_phys_id to find
@@ -197,7 +210,7 @@
 
 	if (IS_RUNNING_ON_SIMULATOR()) {
 		master_node_bedrock_address = (u64 __iomem *)
-			REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0);
+			REMOTE_HUB(boot_get_nasid(), SH_JUNK_BUS_UART0);
 		printk(KERN_DEBUG "early_sn_setup: setting "
 		       "master_node_bedrock_address to 0x%p\n",
 		       master_node_bedrock_address);
@@ -297,7 +310,7 @@
 		panic("PROM version too old\n");
 	}
 
-	master_nasid = get_nasid();
+	master_nasid = boot_get_nasid();
 
 	status =
 	    ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
@@ -314,7 +327,7 @@
 
 	if (IS_RUNNING_ON_SIMULATOR()) {
 		master_node_bedrock_address = (u64 __iomem *)
-			REMOTE_HUB(get_nasid(), SH_JUNK_BUS_UART0);
+			REMOTE_HUB(boot_get_nasid(), SH_JUNK_BUS_UART0);
 		printk(KERN_DEBUG "sn_setup: setting "
 		       "master_node_bedrock_address to 0x%p\n",
 		       master_node_bedrock_address);
@@ -372,6 +385,8 @@
 		nodepdaindr[cnode] =
 		    alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t));
 		memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
+		memset(nodepdaindr[cnode]->phys_cpuid, -1, 
+		    sizeof(nodepdaindr[cnode]->phys_cpuid));
 	}
 
 	/*
@@ -422,8 +437,10 @@
 	int cpuid;
 	int cpuphyid;
 	int nasid;
+	int subnode;
 	int slice;
 	int cnode;
+	int i;
 	static int wars_have_been_checked;
 
 	/*
@@ -434,10 +451,20 @@
 		return;
 
 	cpuid = smp_processor_id();
-	cpuphyid = ((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff);
-	nasid = cpu_physical_id_to_nasid(cpuphyid);
+	cpuphyid = get_sapicid();
+
+	if (ia64_sn_get_sapic_info(cpuphyid, &nasid, &subnode, &slice))
+		BUG();
+
+	for (i=0; i < NR_NODES; i++) {
+		if (nodepdaindr[i]) {
+			nodepdaindr[i]->phys_cpuid[cpuid].nasid = nasid;
+			nodepdaindr[i]->phys_cpuid[cpuid].slice = slice;
+			nodepdaindr[i]->phys_cpuid[cpuid].subnode = subnode;
+		}
+	}
+
 	cnode = nasid_to_cnodeid(nasid);
-	slice = cpu_physical_id_to_slice(cpuphyid);
 
 	memset(pda, 0, sizeof(pda));
 	pda->p_nodepda = nodepdaindr[cnode];
@@ -574,4 +601,16 @@
 		}
 	}
 
+}
+
+int
+nasid_slice_to_cpuid(int nasid, int slice)
+{
+	long cpu;
+	
+	for (cpu=0; cpu < NR_CPUS; cpu++) 
+		if (nodepda->phys_cpuid[cpu].nasid == nasid && nodepda->phys_cpuid[cpu].slice == slice)
+			return cpu;
+
+	return -1;
 }
diff -Nru a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c	2004-10-28 22:25:59 -07:00
@@ -32,6 +32,7 @@
 #include <asm/hw_irq.h>
 #include <asm/current.h>
 #include <asm/sn/sn_cpuid.h>
+#include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/shub_mmr.h>
 #include <asm/sn/nodepda.h>
@@ -136,7 +137,7 @@
 	ptc0 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_0);
 	ptc1 = (long *)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1);
 
-	mynasid = smp_physical_node_id();
+	mynasid = get_nasid();
 
 	spin_lock_irqsave(&sn2_global_ptc_lock, flags);
 
@@ -205,6 +206,7 @@
 
 /**
  * sn_send_IPI_phys - send an IPI to a Nasid and slice
+ * @nasid: nasid to receive the interrupt (may be outside partition)
  * @physid: physical cpuid to receive the interrupt.
  * @vector: command to send
  * @delivery_mode: delivery mechanism
@@ -219,15 +221,12 @@
  * %IA64_IPI_DM_NMI - pend an NMI
  * %IA64_IPI_DM_INIT - pend an INIT interrupt
  */
-void sn_send_IPI_phys(long physid, int vector, int delivery_mode)
+void sn_send_IPI_phys(int nasid, long physid, int vector, int delivery_mode)
 {
-	long nasid, slice, val;
+	long val;
 	unsigned long flags = 0;
 	volatile long *p;
 
-	nasid = cpu_physical_id_to_nasid(physid);
-	slice = cpu_physical_id_to_slice(physid);
-
 	p = (long *)GLOBAL_MMR_PHYS_ADDR(nasid, SH_IPI_INT);
 	val = (1UL << SH_IPI_INT_SEND_SHFT) |
 	    (physid << SH_IPI_INT_PID_SHFT) |
@@ -268,8 +267,14 @@
 void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
 {
 	long physid;
+	int nasid;
 
 	physid = cpu_physical_id(cpuid);
+	nasid = cpuid_to_nasid(cpuid);
+
+	/* the following is used only when starting cpus at boot time */
+	if (unlikely(nasid == -1))
+		ia64_sn_get_sapic_info(physid, &nasid, NULL, NULL);
 
-	sn_send_IPI_phys(physid, vector, delivery_mode);
+	sn_send_IPI_phys(nasid, physid, vector, delivery_mode);
 }
diff -Nru a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2004-10-28 22:25:59 -07:00
@@ -99,7 +99,7 @@
 		this_slot = MODULE_GET_BPOS(module_id);
 		this_slab = geo_slab(geoid);
 		if (rack == this_rack && slot == this_slot && slab == this_slab)
-				break;
+			break;
 	}
 
 	return cnode < numionodes ? cnode : -1;
@@ -121,41 +121,35 @@
 	for (ordinal=0, p=objs; p != obj; p++) {
 		if (SN_HWPERF_FOREIGN(p))
 			continue;
-		if (p->location[3] == obj->location[3])
+		if (SN_HWPERF_SAME_OBJTYPE(p, obj))
 			ordinal++;
 	}
 
 	return ordinal;
 }
 
-static struct {
-        char	*brick_chars;
-        char	*brick_name;
-} brick_names[] = {
-        {"c^jbf",   	"node"		},
-        {"r",   	"router"	},	
-	{NULL,		"?-brick"	}
-};
+static const char *slabname_node =	"node"; /* SHub asic */
+static const char *slabname_ionode =	"ionode"; /* TIO asic */
+static const char *slabname_router =	"router"; /* NL3R or NL4R */
+static const char *slabname_other =	"other"; /* unknown asic */
 
-static char *sn_hwperf_get_brickname(struct sn_hwperf_object_info *obj,
+static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj,
 			struct sn_hwperf_object_info *objs, int *ordinal)
 {
-	int i;
-
-	for (i=0; brick_names[i].brick_chars; i++) {
-		if (strchr(brick_names[i].brick_chars, obj->location[3]))
-			break;
-	}
+	int isnode;
+	const char *slabname = slabname_other;
 
-	if (strcmp(brick_names[i].brick_name, "node") == 0)
+	if ((isnode = SN_HWPERF_IS_NODE(obj)) || SN_HWPERF_IS_IONODE(obj)) {
+	    	slabname = isnode ? slabname_node : slabname_ionode;
 		*ordinal = sn_hwperf_obj_to_cnode(obj);
+	}
 	else {
 		*ordinal = sn_hwperf_generic_ordinal(obj, objs);
-		if (!brick_names[i].brick_chars)
-			brick_names[i].brick_name[0] = obj->location[3];
+		if (SN_HWPERF_IS_ROUTER(obj))
+			slabname = slabname_router;
 	}
 
-	return brick_names[i].brick_name;
+	return slabname;
 }
 
 static int sn_topology_show(struct seq_file *s, void *d)
@@ -165,7 +159,7 @@
 	int e;
 	int i;
 	int j;
-	const char *brickname;
+	const char *slabname;
 	int ordinal;
 	cpumask_t cpumask;
 	char slice;
@@ -191,11 +185,11 @@
 			obj->name[i] = '_';
 	}
 
-	brickname = sn_hwperf_get_brickname(obj, objs, &ordinal);
-	seq_printf(s, "%s %d %s %s asic %s", brickname, ordinal, obj->location,
+	slabname = sn_hwperf_get_slabname(obj, objs, &ordinal);
+	seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location,
 		obj->sn_hwp_this_part ? "local" : "shared", obj->name);
 
-	if (strcmp(brickname, "node") != 0)
+	if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
 		seq_putc(s, '\n');
 	else {
 		seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal));
@@ -206,7 +200,7 @@
 		seq_putc(s, '\n');
 
 		/*
-		 * CPUs on this node
+		 * CPUs on this node, if any
 		 */
 		cpumask = node_to_cpumask(ordinal);
 		for_each_online_cpu(i) {
@@ -278,9 +272,8 @@
 			 */
 			seq_printf(s, " endpoint %s-%d, protocol %s\n",
 				p->location, ptdata[pt].conn_port,
-				strcmp(obj->name, "NL3Router") == 0 ||
-				strcmp(p->name, "NL3Router") == 0 ?
-				"LLP3" : "LLP4");
+				(SN_HWPERF_IS_NL3ROUTER(obj) ||
+				SN_HWPERF_IS_NL3ROUTER(p)) ?  "LLP3" : "LLP4");
 		}
 		vfree(ptdata);
 	}
diff -Nru a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2004-10-28 22:25:59 -07:00
@@ -80,7 +80,8 @@
 
 static int coherence_id_show(struct seq_file *s, void *p)
 {
-	seq_printf(s, "%d\n", cpuid_to_coherence_id(smp_processor_id()));
+	seq_printf(s, "%d\n", partition_coherence_id());
+
 	return 0;
 }
 
diff -Nru a/arch/m68knommu/kernel/module.c b/arch/m68knommu/kernel/module.c
--- a/arch/m68knommu/kernel/module.c	2004-10-28 22:25:57 -07:00
+++ b/arch/m68knommu/kernel/module.c	2004-10-28 22:25:57 -07:00
@@ -82,9 +82,38 @@
 		       unsigned int relsec,
 		       struct module *me)
 {
-	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate_add section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_68K_32:
+			/* We add the value into the location given */
+			*location = rel[i].r_addend + sym->st_value;
+			break;
+		case R_68K_PC32:
+			/* Add the value, subtract its postition */
+			*location = rel[i].r_addend + sym->st_value - (uint32_t)location;
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
 }
 
 int module_finalize(const Elf_Ehdr *hdr,
diff -Nru a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c
--- a/arch/m68knommu/mm/init.c	2004-10-28 22:25:58 -07:00
+++ b/arch/m68knommu/mm/init.c	2004-10-28 22:25:58 -07:00
@@ -38,7 +38,6 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/machdep.h>
-#include <asm/shglcore.h>
 
 #undef DEBUG
 
diff -Nru a/arch/m68knommu/mm/memory.c b/arch/m68knommu/mm/memory.c
--- a/arch/m68knommu/mm/memory.c	2004-10-28 22:25:59 -07:00
+++ b/arch/m68knommu/mm/memory.c	2004-10-28 22:25:59 -07:00
@@ -24,7 +24,6 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/traps.h>
-#include <asm/shglcore.h>
 #include <asm/io.h>
 
 /*
diff -Nru a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c
--- a/arch/m68knommu/platform/5206e/config.c	2004-10-28 22:25:57 -07:00
+++ b/arch/m68knommu/platform/5206e/config.c	2004-10-28 22:25:57 -07:00
@@ -22,7 +22,6 @@
 #include <asm/mcfsim.h>
 #include <asm/mcfdma.h>
 #include <asm/irq.h>
-#include <asm/delay.h>
 
 /***************************************************************************/
 
diff -Nru a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c
--- a/arch/m68knommu/platform/5249/config.c	2004-10-28 22:25:58 -07:00
+++ b/arch/m68knommu/platform/5249/config.c	2004-10-28 22:25:58 -07:00
@@ -21,7 +21,6 @@
 #include <asm/mcftimer.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfdma.h>
-#include <asm/delay.h>
 
 /***************************************************************************/
 
diff -Nru a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
--- a/arch/m68knommu/platform/5307/config.c	2004-10-28 22:25:57 -07:00
+++ b/arch/m68knommu/platform/5307/config.c	2004-10-28 22:25:57 -07:00
@@ -23,7 +23,6 @@
 #include <asm/mcftimer.h>
 #include <asm/mcfsim.h>
 #include <asm/mcfdma.h>
-#include <asm/delay.h>
 #include <asm/mcfwdebug.h>
 
 /***************************************************************************/
diff -Nru a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
--- a/arch/ppc/boot/lib/Makefile	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/boot/lib/Makefile	2004-10-28 22:25:59 -07:00
@@ -4,13 +4,7 @@
 
 CFLAGS_kbd.o	+= -Idrivers/char
 
-ZLIB_DIR := ../../../../lib/zlib_inflate/
-
-lib-y := $(addprefix $(ZLIB_DIR), \
+lib-y := $(addprefix ../../../../lib/zlib_inflate/, \
            infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o)
 lib-y += div64.o
 lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
-
-ifneq ($(KBUILD_SRC),)
-_make_zlib_dir := $(shell [ -d $(obj)/$(ZLIB_DIR) ] || mkdir -p $(obj)/$(ZLIB_DIR) )
-endif
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc/boot/simple/Makefile	2004-10-28 22:25:56 -07:00
@@ -41,7 +41,7 @@
 # if present on 'classic' PPC.
 cacheflag-y	:= -DCLEAR_CACHES=""
 # This file will flush / disable the L2, and L3 if present.
-clear_L2_L3	:= $(boot)/simple/clear.S
+clear_L2_L3	:= $(srctree)/$(boot)/simple/clear.S
 
 #
 # See arch/ppc/kconfig and arch/ppc/platforms/Kconfig
diff -Nru a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c
--- a/arch/ppc/boot/utils/mkbugboot.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc/boot/utils/mkbugboot.c	2004-10-28 22:25:58 -07:00
@@ -96,7 +96,7 @@
   uint8_t header_block[HEADER_SIZE];
   bug_boot_header_t *bbh = (bug_boot_header_t *)&header_block[0];
 
-  bzero(header_block, HEADER_SIZE);
+  memset(header_block, 0, HEADER_SIZE);
 
   /* Fill in the PPCBUG ROM boot header */
   strncpy(bbh->magic_word, "BOOT", 4);		/* PPCBUG magic word */
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/kernel/misc.S	2004-10-28 22:25:59 -07:00
@@ -1447,3 +1447,6 @@
 	.long sys_mq_notify
 	.long sys_mq_getsetattr
 	.long sys_ni_syscall		/* 268 reserved for sys_kexec_load */
+	.long sys_add_key
+	.long sys_request_key		/* 270 */
+	.long sys_keyctl
diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
--- a/arch/ppc/kernel/signal.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/kernel/signal.c	2004-10-28 22:25:59 -07:00
@@ -290,7 +290,7 @@
 
 	/* force the process to reload the FP registers from
 	   current->thread when it next does FP instructions */
-	regs->msr &= ~MSR_FP;
+	regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
 	if (__copy_from_user(current->thread.fpr, &sr->mc_fregs,
 			     sizeof(sr->mc_fregs)))
 		return 1;
@@ -330,9 +330,14 @@
 #endif /* CONFIG_SPE */
 
 #ifndef CONFIG_SMP
-	last_task_used_math = NULL;
-	last_task_used_altivec = NULL;
-	last_task_used_spe = NULL;
+	preempt_disable();
+	if (last_task_used_math == current)
+		last_task_used_math = NULL;
+	if (last_task_used_altivec == current)
+		last_task_used_altivec = NULL;
+	if (last_task_used_spe == current)
+		last_task_used_spe = NULL;
+	preempt_enable();
 #endif
 	return 0;
 }
diff -Nru a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
--- a/arch/ppc/platforms/4xx/ocotea.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/platforms/4xx/ocotea.c	2004-10-28 22:25:59 -07:00
@@ -350,8 +350,12 @@
 	ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
 	ocp_sys_info.opb_bus_freq = clocks.opb;
 
-	/* Disable L2-Cache on broken hardware, enable it otherwise */
-	ibm440gx_l2c_setup(&clocks);
+	/*
+	 * Always disable L2 cache. All revs/speeds of silicon
+	 * have parity error problems despite errata claims to
+	 * the contrary.
+	 */
+	ibm440gx_l2c_disable();
 
 	ibm44x_platform_init();
 
diff -Nru a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
--- a/arch/ppc/platforms/chrp_setup.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/platforms/chrp_setup.c	2004-10-28 22:25:59 -07:00
@@ -371,6 +371,16 @@
 	}
 }
 
+static int __init
+chrp_request_cascade(void)
+{
+	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			       i8259_irq);
+	return 0;
+}
+arch_initcall(chrp_request_cascade);
+
 void __init chrp_init_IRQ(void)
 {
 	struct device_node *np;
@@ -400,9 +410,6 @@
 	OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
 
 	openpic_init(NUM_8259_INTERRUPTS);
-	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
-	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-			       i8259_irq);
 
 	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
 		irq_desc[i].handler = &i8259_pic;
diff -Nru a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c
--- a/arch/ppc/platforms/lopec.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc/platforms/lopec.c	2004-10-28 22:25:58 -07:00
@@ -258,6 +258,17 @@
 }
 #endif /* BLK_DEV_IDE */
 
+static int __init
+lopec_request_cascade(void)
+{
+	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			&i8259_irq);
+
+	return 0;
+}
+arch_initcall(lopec_request_cascade);
+
 static void __init
 lopec_init_IRQ(void)
 {
@@ -270,10 +281,6 @@
 	OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses);
 
 	mpc10x_set_openpic();
-
-	/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
-	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-			&i8259_irq);
 
 	/* Map i8259 interrupts */
 	for(i = 0; i < NUM_8259_INTERRUPTS; i++)
diff -Nru a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c
--- a/arch/ppc/platforms/mcpn765.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc/platforms/mcpn765.c	2004-10-28 22:25:58 -07:00
@@ -363,6 +363,15 @@
 	return;
 }
 
+static int __init
+mcpn765_request_cascade(void)
+{
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			i8259_irq);
+	return 0;
+}
+arch_initcall(mcpn765_request_cascade);
+
 /*
  * Interrupt setup and service.
  * Have MPIC on HAWK and cascaded 8259s on VIA 82586 cascaded to MPIC.
@@ -376,8 +385,6 @@
 		ppc_md.progress("init_irq: enter", 0);
 
 	openpic_init(NUM_8259_INTERRUPTS);
-	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-			i8259_irq);
 
 	for(i=0; i < NUM_8259_INTERRUPTS; i++)
 		irq_desc[i].handler = &i8259_pic;
diff -Nru a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c
--- a/arch/ppc/platforms/mvme5100.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc/platforms/mvme5100.c	2004-10-28 22:25:57 -07:00
@@ -204,6 +204,17 @@
 	return;
 }
 
+static int __init
+mvme5100_request_cascade(void)
+{
+#ifdef CONFIG_MVME5100_IPMC761_PRESENT
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			&i8259_irq);
+#endif
+	return 0;
+}
+arch_initcall(mvme5100_request_cascade);
+
 /*
  * Interrupt setup and service.
  * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC.
@@ -221,14 +232,12 @@
 	openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
 #ifdef CONFIG_MVME5100_IPMC761_PRESENT
 	openpic_init(NUM_8259_INTERRUPTS);
-	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-			&i8259_irq);
 
 	/* Map i8259 interrupts. */
 	for (i = 0; i < NUM_8259_INTERRUPTS; i++)
 		irq_desc[i].handler = &i8259_pic;
 
-	i8259_init(NULL);
+	i8259_init((long)NULL);
 #else
 	openpic_init(0);
 #endif
diff -Nru a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
--- a/arch/ppc/platforms/pplus.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/platforms/pplus.c	2004-10-28 22:25:59 -07:00
@@ -654,6 +654,16 @@
 		return irq;
 }
 
+static int __init
+pplus_request_cascade(void)
+{
+	if (OpenPIC_Addr != NULL)
+		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+				i8259_irq);
+	return 0;
+}
+arch_initcall(pplus_request_cascade);
+
 static void __init pplus_init_IRQ(void)
 {
 	int i;
@@ -668,8 +678,6 @@
 
 		openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000);
 		openpic_init(NUM_8259_INTERRUPTS);
-		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-					i8259_irq);
 		ppc_md.get_irq = openpic_get_irq;
 	}
 
diff -Nru a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
--- a/arch/ppc/platforms/prep_setup.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/platforms/prep_setup.c	2004-10-28 22:25:59 -07:00
@@ -958,6 +958,17 @@
 	}
 }
 
+static int __init
+prep_request_cascade(void)
+{
+	if (OpenPIC_Addr != NULL)
+		/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
+		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+				i8259_irq);
+	return 0;
+}
+arch_initcall(prep_request_cascade);
+
 static void __init
 prep_init_IRQ(void)
 {
@@ -966,9 +977,6 @@
 
 	if (OpenPIC_Addr != NULL) {
 		openpic_init(NUM_8259_INTERRUPTS);
-		/* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */
-		openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-				       i8259_irq);
 	}
 	for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
 		irq_desc[i].handler = &i8259_pic;
diff -Nru a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
--- a/arch/ppc/platforms/sandpoint.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc/platforms/sandpoint.c	2004-10-28 22:25:59 -07:00
@@ -252,38 +252,6 @@
 	return;
 }
 
-#if defined(CONFIG_SERIAL_8250) && \
-	(defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
-static void __init
-sandpoint_early_serial_map(void)
-{
-	struct uart_port serial_req;
-
-	/* Setup serial port access */
-	memset(&serial_req, 0, sizeof(serial_req));
-	serial_req.uartclk = UART_CLK;
-	serial_req.irq = 4;
-	serial_req.flags = STD_COM_FLAGS;
-	serial_req.iotype = SERIAL_IO_MEM;
-	serial_req.membase = (u_char *)SANDPOINT_SERIAL_0;
-
-	gen550_init(0, &serial_req);
-
-	if (early_serial_setup(&serial_req) != 0)
-		printk(KERN_ERR "Early serial init of port 0 failed\n");
-
-	/* Assume early_serial_setup() doesn't modify serial_req */
-	serial_req.line = 1;
-	serial_req.irq = 3; /* XXXX */
-	serial_req.membase = (u_char *)SANDPOINT_SERIAL_1;
-
-	gen550_init(1, &serial_req);
-
-	if (early_serial_setup(&serial_req) != 0)
-		printk(KERN_ERR "Early serial init of port 1 failed\n");
-}
-#endif
-
 static void __init
 sandpoint_setup_arch(void)
 {
@@ -415,6 +383,15 @@
 
 arch_initcall(sandpoint_request_io);
 
+static int __init
+sandpoint_request_cascade(void)
+{
+	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
+			i8259_irq);
+	return 0;
+}
+arch_initcall(sandpoint_request_cascade);
+
 /*
  * Interrupt setup and service.  Interrrupts on the Sandpoint come
  * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
@@ -430,8 +407,6 @@
 	OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
 
 	mpc10x_set_openpic();
-	openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade",
-			i8259_irq);
 
 	/*
 	 * openpic_init() has set up irq_desc[16-31] to be openpic
@@ -689,15 +664,11 @@
 	ppc_md.nvram_read_val = todc_mc146818_read_val;
 	ppc_md.nvram_write_val = todc_mc146818_write_val;
 
-#if defined(CONFIG_SERIAL_8250) && \
-	(defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
-	sandpoint_early_serial_map();
 #ifdef CONFIG_KGDB
 	ppc_md.kgdb_map_scc = gen550_kgdb_map_scc;
 #endif
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	ppc_md.progress = gen550_progress;
-#endif
 #endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc/syslib/Makefile	2004-10-28 22:25:56 -07:00
@@ -52,7 +52,8 @@
 obj-$(CONFIG_MENF1)		+= todc_time.o i8259.o mpc10x_common.o \
 					pci_auto.o indirect_pci.o
 obj-$(CONFIG_MVME5100)		+= open_pic.o todc_time.o indirect_pci.o \
-					i8259.o pci_auto.o hawk_common.o
+					pci_auto.o hawk_common.o
+obj-$(CONFIG_MVME5100_IPMC761_PRESENT)	+= i8259.o
 obj-$(CONFIG_OCOTEA)		+= indirect_pci.o pci_auto.o todc_time.o
 obj-$(CONFIG_PAL4)		+= cpc700_pic.o
 obj-$(CONFIG_PCORE)		+= todc_time.o i8259.o pci_auto.o
diff -Nru a/arch/ppc/syslib/gen550_dbg.c b/arch/ppc/syslib/gen550_dbg.c
--- a/arch/ppc/syslib/gen550_dbg.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc/syslib/gen550_dbg.c	2004-10-28 22:25:57 -07:00
@@ -40,12 +40,12 @@
 
 unsigned long direct_inb(unsigned long addr)
 {
-	return readb(addr);
+	return readb((void __iomem *)addr);
 }
 
 void direct_outb(unsigned long addr, unsigned char val)
 {
-	writeb(val, addr);
+	writeb(val, (void __iomem *)addr);
 }
 
 unsigned long io_inb(unsigned long port)
diff -Nru a/arch/ppc/syslib/i8259.c b/arch/ppc/syslib/i8259.c
--- a/arch/ppc/syslib/i8259.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc/syslib/i8259.c	2004-10-28 22:25:58 -07:00
@@ -151,6 +151,17 @@
 	"8259 edge control", 0x4d0, 0x4d1, IORESOURCE_BUSY
 };
 
+static int __init
+i8259_hook_cascade(void)
+{
+	/* reserve our resources */
+	request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
+				"82c59 secondary cascade", NULL );
+	return 0;
+}
+
+arch_initcall(i8259_hook_cascade);
+
 /*
  * i8259_init()
  * intack_addr - PCI interrupt acknowledge (real) address which will return
@@ -184,9 +195,6 @@
 
 	spin_unlock_irqrestore(&i8259_lock, flags);
 
-	/* reserve our resources */
-	request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
-				"82c59 secondary cascade", NULL );
 	request_resource(&ioport_resource, &pic1_iores);
 	request_resource(&ioport_resource, &pic2_iores);
 	request_resource(&ioport_resource, &pic_edgectrl_iores);
diff -Nru a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
--- a/arch/ppc/xmon/start.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc/xmon/start.c	2004-10-28 22:25:56 -07:00
@@ -102,7 +102,7 @@
 {
 	.handler =	sysrq_handle_xmon,
 	.help_msg =	"Xmon",
-	.action_msg =	"Entering xmon\n",
+	.action_msg =	"Entering xmon",
 };
 #endif
 
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/Kconfig	2004-10-28 22:25:58 -07:00
@@ -80,6 +80,16 @@
 	select ADB_PMU
 	select U3_DART
 
+config PPC_MAPLE
+	depends on PPC_MULTIPLATFORM
+	bool "  Maple 970FX Evaluation Board"
+	select U3_DART
+	select MPIC_BROKEN_U3
+	default n
+	help
+          This option enables support for the Maple 970FX Evaluation Board.
+	  For more informations, refer to http://www.970eval.com
+
 config PPC
 	bool
 	default y
@@ -110,11 +120,21 @@
 	  processors, that is, which share physical processors between
 	  two or more partitions.
 
+config IBMVIO
+	depends on PPC_PSERIES || PPC_ISERIES
+	bool
+	default y
+
 config U3_DART
 	bool 
 	depends on PPC_MULTIPLATFORM
 	default n
 
+config MPIC_BROKEN_U3
+	bool
+	depends on PPC_MAPLE
+	default y
+
 config PPC_PMAC64
 	bool
 	depends on PPC_PMAC
@@ -355,6 +375,11 @@
 source "arch/ppc64/Kconfig.debug"
 
 source "security/Kconfig"
+
+config KEYS_COMPAT
+	bool
+	depends on COMPAT && KEYS
+	default y
 
 source "crypto/Kconfig"
 
diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile
--- a/arch/ppc64/Makefile	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/Makefile	2004-10-28 22:25:57 -07:00
@@ -55,11 +55,13 @@
 boot := arch/ppc64/boot
 
 boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd
+boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd
 boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm
 $(boottarget-y): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 bootimage-$(CONFIG_PPC_PSERIES) := zImage
+bootimage-$(CONFIG_PPC_MAPLE) := zImage
 bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
 BOOTIMAGE := $(bootimage-y)
 install: vmlinux
diff -Nru a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/configs/maple_defconfig	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,921 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9
+# Wed Oct 20 15:39:14 2004
+#
+CONFIG_64BIT=y
+CONFIG_MMU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_COMPAT=y
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCE_MAX_ZONEORDER=13
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
+
+#
+# Platform support
+#
+# CONFIG_PPC_ISERIES is not set
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_PSERIES is not set
+# CONFIG_PPC_PMAC is not set
+CONFIG_PPC_MAPLE=y
+CONFIG_PPC=y
+CONFIG_PPC64=y
+CONFIG_PPC_OF=y
+# CONFIG_ALTIVEC is not set
+CONFIG_U3_DART=y
+CONFIG_MPIC_BROKEN_U3=y
+CONFIG_BOOTX_TEXT=y
+CONFIG_POWER4_ONLY=y
+CONFIG_IOMMU_VMERGE=y
+CONFIG_SMP=y
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_NR_CPUS=2
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
+
+#
+# General setup
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_TASKFILE_IO=y
+
+#
+# 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=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 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
+# 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_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_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+CONFIG_AMD8111_ETH=y
+# CONFIG_AMD8111E_NAPI 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 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
+# CONFIG_VIA_VELOCITY is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1600
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=y
+# 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
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=y
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_CONSOLE is not set
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# 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 is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_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 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# 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=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf-8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+# CONFIG_PPCDBG is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_SCHEDSTATS is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+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_WP512 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
--- a/arch/ppc64/kernel/LparData.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/LparData.c	2004-10-28 22:25:57 -07:00
@@ -6,9 +6,8 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#include <asm/types.h>
-#include <asm/page.h>
-#include <stddef.h>
+#include <linux/config.h>
+#include <linux/types.h>
 #include <linux/threads.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/Makefile	2004-10-28 22:25:59 -07:00
@@ -11,12 +11,11 @@
 			udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
 			ptrace32.o signal32.o rtc.o init_task.o \
 			lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
-			iommu.o sysfs.o vio.o
+			iommu.o sysfs.o
 
 obj-$(CONFIG_PPC_OF) +=	of_device.o
 
-pci-obj-$(CONFIG_PPC_ISERIES)	+= iSeries_pci.o iSeries_pci_reset.o \
-				     iSeries_IoMmTable.o
+pci-obj-$(CONFIG_PPC_ISERIES)	+= iSeries_pci.o iSeries_pci_reset.o
 pci-obj-$(CONFIG_PPC_MULTIPLATFORM)	+= pci_dn.o pci_dma_direct.o
 
 obj-$(CONFIG_PCI)	+= pci.o pci_iommu.o iomap.o $(pci-obj-y)
@@ -28,7 +27,7 @@
 			     mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
 			     iSeries_iommu.o
 
-obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o open_pic.o i8259.o prom_init.o prom.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o
 
 obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
 			     eeh.o pSeries_nvram.o rtasd.o ras.o \
@@ -45,14 +44,20 @@
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
+obj-$(CONFIG_IBMVIO)		+= vio.o
 
 obj-$(CONFIG_PPC_PMAC)		+= pmac_setup.o pmac_feature.o pmac_pci.o \
-				   pmac_time.o pmac_nvram.o pmac_low_i2c.o \
-				   open_pic_u3.o
+				   pmac_time.o pmac_nvram.o pmac_low_i2c.o
+
+obj-$(CONFIG_PPC_MAPLE)		+= maple_setup.o maple_pci.o maple_time.o
+
 obj-$(CONFIG_U3_DART)		+= u3_iommu.o
 
 ifdef CONFIG_SMP
 obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o smp-tbsync.o
+obj-$(CONFIG_PPC_ISERIES)	+= iSeries_smp.o
+obj-$(CONFIG_PPC_PSERIES)	+= pSeries_smp.o
+obj-$(CONFIG_PPC_MAPLE)		+= smp-tbsync.o
 endif
 
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
diff -Nru a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/ppc64/kernel/cpu_setup_power4.S
--- a/arch/ppc64/kernel/cpu_setup_power4.S	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc64/kernel/cpu_setup_power4.S	2004-10-28 22:25:56 -07:00
@@ -156,6 +156,15 @@
 	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	bne	1f
 
+	/* Before accessing memory, we make sure rm_ci is clear */
+	li	r0,0
+	mfspr	r3,SPRN_HID4
+	rldimi	r3,r0,40,23	/* clear bit 23 (rm_ci) */
+	sync
+	mtspr	SPRN_HID4,r3
+	isync
+	sync
+
 	/* Clear interrupt prefix */
 	li	r0,0
 	sync
diff -Nru a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
--- a/arch/ppc64/kernel/dma.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc64/kernel/dma.c	2004-10-28 22:25:56 -07:00
@@ -17,8 +17,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		return pci_dma_supported(to_pci_dev(dev), mask);
+#ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return vio_dma_supported(to_vio_dev(dev), mask);
+#endif /* CONFIG_IBMVIO */
 	BUG();
 	return 0;
 }
@@ -28,8 +30,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+#ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return vio_set_dma_mask(to_vio_dev(dev), dma_mask);
+#endif /* CONFIG_IBMVIO */
 	BUG();
 	return 0;
 }
@@ -40,8 +44,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
+#ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle);
+#endif /* CONFIG_IBMVIO */
 	BUG();
 	return NULL;
 }
@@ -52,8 +58,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
+#ifdef CONFIG_IBMVIO
 	else if (dev->bus == &vio_bus_type)
 		vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle);
+#endif /* CONFIG_IBMVIO */
 	else
 		BUG();
 }
@@ -64,8 +72,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
+#ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return vio_map_single(to_vio_dev(dev), cpu_addr, size, direction);
+#endif /* CONFIG_IBMVIO */
 	BUG();
 	return (dma_addr_t)0;
 }
@@ -76,8 +86,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
+#ifdef CONFIG_IBMVIO
 	else if (dev->bus == &vio_bus_type)
 		vio_unmap_single(to_vio_dev(dev), dma_addr, size, direction);
+#endif /* CONFIG_IBMVIO */
 	else
 		BUG();
 }
@@ -89,8 +101,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
+#ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return vio_map_page(to_vio_dev(dev), page, offset, size, direction);
+#endif /* CONFIG_IBMVIO */
 	BUG();
 	return (dma_addr_t)0;
 }
@@ -101,8 +115,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
+#ifdef CONFIG_IBMVIO
 	else if (dev->bus == &vio_bus_type)
 		vio_unmap_page(to_vio_dev(dev), dma_address, size, direction);
+#endif /* CONFIG_IBMVIO */
 	else
 		BUG();
 }
@@ -113,8 +129,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
+#ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return vio_map_sg(to_vio_dev(dev), sg, nents, direction);
+#endif /* CONFIG_IBMVIO */
 	BUG();
 	return 0;
 }
@@ -125,8 +143,10 @@
 {
 	if (dev->bus == &pci_bus_type)
 		pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
+#ifdef CONFIG_IBMVIO
 	else if (dev->bus == &vio_bus_type)
 		vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, direction);
+#endif /* CONFIG_IBMVIO */
 	else
 		BUG();
 }
diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
--- a/arch/ppc64/kernel/eeh.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/eeh.c	2004-10-28 22:25:58 -07:00
@@ -17,29 +17,79 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/bootmem.h>
 #include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/notifier.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 <linux/spinlock.h>
+#include <asm/eeh.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/pgtable.h>
 #include <asm/rtas.h>
+#include <asm/atomic.h>
 #include "pci.h"
 
 #undef DEBUG
 
+/** Overview:
+ *  EEH, or "Extended Error Handling" is a PCI bridge technology for
+ *  dealing with PCI bus errors that can't be dealt with within the
+ *  usual PCI framework, except by check-stopping the CPU.  Systems
+ *  that are designed for high-availability/reliability cannot afford
+ *  to crash due to a "mere" PCI error, thus the need for EEH.
+ *  An EEH-capable bridge operates by converting a detected error
+ *  into a "slot freeze", taking the PCI adapter off-line, making
+ *  the slot behave, from the OS'es point of view, as if the slot
+ *  were "empty": all reads return 0xff's and all writes are silently
+ *  ignored.  EEH slot isolation events can be triggered by parity
+ *  errors on the address or data busses (e.g. during posted writes),
+ *  which in turn might be caused by dust, vibration, humidity,
+ *  radioactivity or plain-old failed hardware.
+ *
+ *  Note, however, that one of the leading causes of EEH slot
+ *  freeze events are buggy device drivers, buggy device microcode,
+ *  or buggy device hardware.  This is because any attempt by the
+ *  device to bus-master data to a memory address that is not
+ *  assigned to the device will trigger a slot freeze.   (The idea
+ *  is to prevent devices-gone-wild from corrupting system memory).
+ *  Buggy hardware/drivers will have a miserable time co-existing
+ *  with EEH.
+ *
+ *  Ideally, a PCI device driver, when suspecting that an isolation
+ *  event has occured (e.g. by reading 0xff's), will then ask EEH
+ *  whether this is the case, and then take appropriate steps to
+ *  reset the PCI slot, the PCI device, and then resume operations.
+ *  However, until that day,  the checking is done here, with the
+ *  eeh_check_failure() routine embedded in the MMIO macros.  If
+ *  the slot is found to be isolated, an "EEH Event" is synthesized
+ *  and sent out for processing.
+ */
+
+/** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */
 #define BUID_HI(buid) ((buid) >> 32)
 #define BUID_LO(buid) ((buid) & 0xffffffff)
-#define CONFIG_ADDR(busno, devfn) \
-		(((((busno) & 0xff) << 8) | ((devfn) & 0xf8)) << 8)
+
+/* EEH event workqueue setup. */
+static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(eeh_eventlist);
+static void eeh_event_handler(void *);
+DECLARE_WORK(eeh_event_wq, eeh_event_handler, NULL);
+
+static struct notifier_block *eeh_notifier_chain;
+
+/*
+ * If a device driver keeps reading an MMIO register in an interrupt
+ * handler after a slot isolation event has occurred, we assume it
+ * is broken and panic.  This sets the threshold for how many read
+ * attempts we allow before panicking.
+ */
+#define EEH_MAX_FAILS	1000
+static atomic_t eeh_fail_count;
 
 /* RTAS tokens */
 static int ibm_set_eeh_option;
@@ -58,13 +108,15 @@
 static DEFINE_PER_CPU(unsigned long, total_mmio_ffs);
 static DEFINE_PER_CPU(unsigned long, false_positives);
 static DEFINE_PER_CPU(unsigned long, ignored_failures);
+static DEFINE_PER_CPU(unsigned long, slot_resets);
 
 /**
  * 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.
+ * found. It is safe to perform an address lookup in an interrupt
+ * context; this ability is an important feature.
  *
  * Currently, the only customer of this code is the EEH subsystem;
  * thus, this code has been somewhat tailored to suit EEH better.
@@ -333,6 +385,94 @@
 #endif
 }
 
+/* --------------------------------------------------------------- */
+/* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */
+
+/**
+ * eeh_register_notifier - Register to find out about EEH events.
+ * @nb: notifier block to callback on events
+ */
+int eeh_register_notifier(struct notifier_block *nb)
+{
+	return notifier_chain_register(&eeh_notifier_chain, nb);
+}
+
+/**
+ * eeh_unregister_notifier - Unregister to an EEH event notifier.
+ * @nb: notifier block to callback on events
+ */
+int eeh_unregister_notifier(struct notifier_block *nb)
+{
+	return notifier_chain_unregister(&eeh_notifier_chain, nb);
+}
+
+/**
+ * eeh_panic - call panic() for an eeh event that cannot be handled.
+ * The philosophy of this routine is that it is better to panic and
+ * halt the OS than it is to risk possible data corruption by
+ * oblivious device drivers that don't know better.
+ *
+ * @dev pci device that had an eeh event
+ * @reset_state current reset state of the device slot
+ */
+static void eeh_panic(struct pci_dev *dev, int reset_state)
+{
+	/*
+	 * 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 (%d) on device:%s %s\n", reset_state,
+		      pci_name(dev), pci_pretty_name(dev));
+	else {
+		__get_cpu_var(ignored_failures)++;
+		printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s %s\n",
+		       reset_state, pci_name(dev), pci_pretty_name(dev));
+	}
+}
+
+/**
+ * eeh_event_handler - dispatch EEH events.  The detection of a frozen
+ * slot can occur inside an interrupt, where it can be hard to do
+ * anything about it.  The goal of this routine is to pull these
+ * detection events out of the context of the interrupt handler, and
+ * re-dispatch them for processing at a later time in a normal context.
+ *
+ * @dummy - unused
+ */
+static void eeh_event_handler(void *dummy)
+{
+	unsigned long flags;
+	struct eeh_event	*event;
+
+	while (1) {
+		spin_lock_irqsave(&eeh_eventlist_lock, flags);
+		event = NULL;
+		if (!list_empty(&eeh_eventlist)) {
+			event = list_entry(eeh_eventlist.next, struct eeh_event, list);
+			list_del(&event->list);
+		}
+		spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+		if (event == NULL)
+			break;
+
+		printk(KERN_INFO "EEH: MMIO failure (%d), notifiying device "
+		       "%s %s\n", event->reset_state,
+		       pci_name(event->dev), pci_pretty_name(event->dev));
+
+		atomic_set(&eeh_fail_count, 0);
+		notifier_call_chain (&eeh_notifier_chain,
+				     EEH_NOTIFY_FREEZE, event);
+
+		__get_cpu_var(slot_resets)++;
+
+		pci_dev_put(event->dev);
+		kfree(event);
+	}
+}
+
 /**
  * eeh_token_to_phys - convert EEH address token to phys address
  * @token i/o token, should be address in the form 0xE....
@@ -357,11 +497,11 @@
  *
  * Check for an EEH failure for the given device node.  Call this
  * routine if the result of a read was all 0xff's and you want to
- * find out if this is due to an EEH slot freeze event.  This routine
+ * find out if this is due to an EEH slot freeze.  This routine
  * will query firmware for the EEH status.
  *
  * Returns 0 if there has not been an EEH error; otherwise returns
- * an error code.
+ * a non-zero value and queues up a solt isolation event notification.
  *
  * It is safe to call this routine in an interrupt context.
  */
@@ -370,6 +510,8 @@
 	int ret;
 	int rets[2];
 	unsigned long flags;
+	int rc, reset_state;
+	struct eeh_event  *event;
 
 	__get_cpu_var(total_mmio_ffs)++;
 
@@ -390,6 +532,24 @@
 	}
 
 	/*
+	 * If we already have a pending isolation event for this
+	 * slot, we know it's bad already, we don't need to check...
+	 */
+	if (dn->eeh_mode & EEH_MODE_ISOLATED) {
+		atomic_inc(&eeh_fail_count);
+		if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) {
+			/* re-read the slot reset state */
+			rets[0] = -1;
+			rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
+				  dn->eeh_config_addr,
+				  BUID_HI(dn->phb->buid),
+				  BUID_LO(dn->phb->buid));
+			eeh_panic(dev, rets[0]);
+		}
+		return 0;
+	}
+
+	/*
 	 * 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
@@ -400,47 +560,54 @@
 			dn->eeh_config_addr, BUID_HI(dn->phb->buid),
 			BUID_LO(dn->phb->buid));
 
-	if (ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4)) {
-		int log_event;
-
-		spin_lock_irqsave(&slot_errbuf_lock, flags);
-		memset(slot_errbuf, 0, eeh_error_buf_size);
-
-		log_event = rtas_call(ibm_slot_error_detail,
-		                      8, 1, NULL, dn->eeh_config_addr,
-		                      BUID_HI(dn->phb->buid),
-		                      BUID_LO(dn->phb->buid), NULL, 0,
-		                      virt_to_phys(slot_errbuf),
-		                      eeh_error_buf_size,
-		                      1 /* Temporary Error */);
-
-		if (log_event == 0)
-			log_error(slot_errbuf, ERR_TYPE_RTAS_LOG,
-				  1 /* Fatal */);
-
-		spin_unlock_irqrestore(&slot_errbuf_lock, flags);
-
-		printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n",
-		       rets[0], dn->name, dn->full_name);
-		WARN_ON(1);
-
-		/*
-		 * XXX We should create a separate sysctl for this.
-		 *
-		 * 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 (%d) on device: %s %s\n",
-			      rets[0], dn->name, dn->full_name);
-		} else {
-			__get_cpu_var(ignored_failures)++;
-		}
-	} else {
+	if (!(ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4))) {
 		__get_cpu_var(false_positives)++;
+		return 0;
 	}
 
+	/* prevent repeated reports of this failure */
+	dn->eeh_mode |= EEH_MODE_ISOLATED;
+
+	reset_state = rets[0];
+
+	spin_lock_irqsave(&slot_errbuf_lock, flags);
+	memset(slot_errbuf, 0, eeh_error_buf_size);
+
+	rc = rtas_call(ibm_slot_error_detail,
+	               8, 1, NULL, dn->eeh_config_addr,
+	               BUID_HI(dn->phb->buid),
+	               BUID_LO(dn->phb->buid), NULL, 0,
+	               virt_to_phys(slot_errbuf),
+	               eeh_error_buf_size,
+	               1 /* Temporary Error */);
+
+	if (rc == 0)
+		log_error(slot_errbuf, ERR_TYPE_RTAS_LOG, 0);
+	spin_unlock_irqrestore(&slot_errbuf_lock, flags);
+
+	printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n",
+	       rets[0], dn->name, dn->full_name);
+	event = kmalloc(sizeof(*event), GFP_ATOMIC);
+	if (event == NULL) {
+		eeh_panic(dev, reset_state);
+		return 1;
+ 	}
+
+	event->dev = dev;
+	event->dn = dn;
+	event->reset_state = reset_state;
+
+	/* We may or may not be called in an interrupt context */
+	spin_lock_irqsave(&eeh_eventlist_lock, flags);
+	list_add(&event->list, &eeh_eventlist);
+	spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+
+	/* Most EEH events are due to device driver bugs.  Having
+	 * a stack trace will help the device-driver authors figure
+	 * out what happened.  So print that out. */
+	dump_stack();
+	schedule_work(&eeh_event_wq);
+
 	return 0;
 }
 
@@ -701,11 +868,13 @@
 {
 	unsigned int cpu;
 	unsigned long ffs = 0, positives = 0, failures = 0;
+	unsigned long resets = 0;
 
 	for_each_cpu(cpu) {
 		ffs += per_cpu(total_mmio_ffs, cpu);
 		positives += per_cpu(false_positives, cpu);
 		failures += per_cpu(ignored_failures, cpu);
+		resets += per_cpu(slot_resets, cpu);
 	}
 
 	if (0 == eeh_subsystem_enabled) {
@@ -715,8 +884,11 @@
 		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);
+			   "eeh_ignored_failures=%ld\n"
+			   "eeh_slot_resets=%ld\n"
+				"eeh_fail_count=%d\n",
+			   ffs, positives, failures, resets,
+				eeh_fail_count.counter);
 	}
 
 	return 0;
diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/head.S	2004-10-28 22:25:58 -07:00
@@ -1195,18 +1195,20 @@
  * At entry, r3 = this processor's number (in Linux terms, not hardware).
  */
 _GLOBAL(pseries_secondary_smp_init)
+	mr	r24,r3
+	
 	/* turn on 64-bit mode */
 	bl	.enable_64b_mode
 	isync
 
-	/* Set up a paca value for this processor. */
-	LOADADDR(r24, paca) 		/* Get base vaddr of paca array	 */
-	mulli	r13,r3,PACA_SIZE	/* Calculate vaddr of right paca */
-	add	r13,r13,r24		/* for this processor.		 */
+	/* Copy some CPU settings from CPU 0 */
+	bl	.__restore_cpu_setup
 
+	/* Set up a paca value for this processor. */
+	LOADADDR(r5, paca) 		/* Get base vaddr of paca array	 */
+	mulli	r13,r24,PACA_SIZE	/* Calculate vaddr of right paca */
+	add	r13,r13,r5		/* for this processor.		 */
 	mtspr	SPRG3,r13		/* Save vaddr of paca in SPRG3	 */
-	mr	r24,r3			/* __secondary_start needs cpu#	 */
-
 1:
 	HMT_LOW
 	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor should */
@@ -1886,19 +1888,6 @@
 91:
 #endif
 
-#ifdef CONFIG_SMP
-	/* All secondary cpus are now spinning on a common
-	 * spinloop, release them all now so they can start
-	 * to spin on their individual paca spinloops.
-	 * For non SMP kernels, the secondary cpus never
-	 * get out of the common spinloop.
-	 */
-	li	r3,1
-	LOADADDR(r5,__secondary_hold_spinloop)
-	tophys(r4,r5)
-	std	r3,0(r4)
-#endif
-
 	/* The following gets the stack and TOC set up with the regs */
 	/* pointing to the real addr of the kernel stack.  This is   */
 	/* all done to support the C function call below which sets  */
@@ -1913,7 +1902,7 @@
 	li	r0,0
 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
 
-		/* set up the TOC (physical address) */
+	/* set up the TOC (physical address) */
 	LOADADDR(r2,__toc_start)
 	addi	r2,r2,0x4000
 	addi	r2,r2,0x4000
@@ -1925,6 +1914,25 @@
 	sub	r4,r4,r26
 	mr	r5,r26
 	bl	.identify_cpu
+
+	/* Save some low level config HIDs of CPU0 to be copied to
+	 * other CPUs later on, or used for suspend/resume
+	 */
+	bl	.__save_cpu_setup
+	sync
+
+#ifdef CONFIG_SMP
+	/* All secondary cpus are now spinning on a common
+	 * spinloop, release them all now so they can start
+	 * to spin on their individual paca spinloops.
+	 * For non SMP kernels, the secondary cpus never
+	 * get out of the common spinloop.
+	 */
+	li	r3,1
+	LOADADDR(r5,__secondary_hold_spinloop)
+	tophys(r4,r5)
+	std	r3,0(r4)
+#endif
 
 	/* Setup a valid physical PACA pointer in SPRG3 for early_setup
 	 * note that boot_cpuid can always be 0 nowadays since there is
diff -Nru a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c
--- a/arch/ppc64/kernel/i8259.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/i8259.c	2004-10-28 22:25:59 -07:00
@@ -23,7 +23,8 @@
 
 static spinlock_t i8259_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
-int i8259_pic_irq_offset;
+static int i8259_pic_irq_offset;
+static int i8259_present;
 
 int i8259_irq(int cpu)
 {
@@ -140,11 +141,13 @@
         NULL
 };
 
-void __init i8259_init(void)
+void __init i8259_init(int offset)
 {
 	unsigned long flags;
 	
 	spin_lock_irqsave(&i8259_lock, flags);
+	i8259_pic_irq_offset = offset;
+	i8259_present = 1;
         /* init master interrupt controller */
         outb(0x11, 0x20); /* Start init sequence */
         outb(0x00, 0x21); /* Vector base */
@@ -160,7 +163,18 @@
         outb(cached_A1, 0xA1);
         outb(cached_21, 0x21);
 	spin_unlock_irqrestore(&i8259_lock, flags);
+        
+}
+
+static int i8259_request_cascade(void)
+{
+	if (!i8259_present)
+		return -ENODEV;
+
         request_irq( i8259_pic_irq_offset + 2, no_action, SA_INTERRUPT,
                      "82c59 secondary cascade", NULL );
-        
+
+	return 0;
 }
+
+arch_initcall(i8259_request_cascade);
diff -Nru a/arch/ppc64/kernel/i8259.h b/arch/ppc64/kernel/i8259.h
--- a/arch/ppc64/kernel/i8259.h	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/i8259.h	2004-10-28 22:25:57 -07:00
@@ -11,7 +11,7 @@
 
 extern struct hw_interrupt_type i8259_pic;
 
-void i8259_init(void);
-int i8259_irq(int);
+extern void i8259_init(int offset);
+extern int i8259_irq(int);
 
 #endif /* _PPC_KERNEL_i8259_H */
diff -Nru a/arch/ppc64/kernel/iSeries_IoMmTable.c b/arch/ppc64/kernel/iSeries_IoMmTable.c
--- a/arch/ppc64/kernel/iSeries_IoMmTable.c	2004-10-28 22:25:59 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,169 +0,0 @@
-#define PCIFR(...)
-/************************************************************************/
-/* This module supports the iSeries I/O Address translation mapping     */
-/* Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    */
-/*                                                                      */
-/* This program is free software; you can redistribute it and/or modify */
-/* it under the terms of the GNU General Public License as published by */
-/* the Free Software Foundation; either version 2 of the License, or    */
-/* (at your option) any later version.                                  */
-/*                                                                      */
-/* 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:                                                     */
-/*   Created, December 14, 2000                                         */
-/*   Added Bar table for IoMm performance.                              */
-/*   Ported to ppc64                                                    */
-/*   Added dynamic table allocation                                     */
-/* End Change Activity                                                  */
-/************************************************************************/
-#include <asm/types.h>
-#include <asm/resource.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <asm/ppcdebug.h>
-#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/iSeries_pci.h>
-
-#include "iSeries_IoMmTable.h"
-#include "pci.h"
-
-/*
- * Table defines
- * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
- */
-#define Max_Entries 1024
-unsigned long iSeries_IoMmTable_Entry_Size = 0x0000000000400000; 
-unsigned long iSeries_Base_Io_Memory       = 0xE000000000000000;
-unsigned long iSeries_Max_Io_Memory        = 0xE000000000000000;
-static   long iSeries_CurrentIndex         = 0;
-
-/*
- * Lookup Tables.
- */
-struct iSeries_Device_Node **iSeries_IoMmTable;
-u8 *iSeries_IoBarTable;
-
-/*
- * Static and Global variables
- */
-static char *iSeriesPciIoText = "iSeries PCI I/O";
-static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED;
-
-/*
- * iSeries_IoMmTable_Initialize
- *
- * Allocates and initalizes the Address Translation Table and Bar
- * Tables to get them ready for use.  Must be called before any
- * I/O space is handed out to the device BARs.
- * A follow up method,iSeries_IoMmTable_Status can be called to
- * adjust the table after the device BARs have been assiged to
- * resize the table.
- */
-void iSeries_IoMmTable_Initialize(void)
-{
-	spin_lock(&iSeriesIoMmTableLock);
-	iSeries_IoMmTable  = kmalloc(sizeof(void *) * Max_Entries, GFP_KERNEL);
-	iSeries_IoBarTable = kmalloc(sizeof(u8) * Max_Entries, GFP_KERNEL);
-	spin_unlock(&iSeriesIoMmTableLock);
-	PCIFR("IoMmTable Initialized 0x%p", iSeries_IoMmTable);
-	if ((iSeries_IoMmTable == NULL) || (iSeries_IoBarTable == NULL))
-		panic("PCI: I/O tables allocation failed.\n");
-}
-
-/*
- * iSeries_IoMmTable_AllocateEntry
- *
- * Adds pci_dev entry in address translation table
- *
- * - Allocates the number of entries required in table base on BAR
- *   size.
- * - Allocates starting at iSeries_Base_Io_Memory and increases.
- * - The size is round up to be a multiple of entry size.
- * - CurrentIndex is incremented to keep track of the last entry.
- * - Builds the resource entry for allocated BARs.
- */
-static void iSeries_IoMmTable_AllocateEntry(struct pci_dev *PciDev,
-		int BarNumber)
-{
-	struct resource *BarResource = &PciDev->resource[BarNumber];
-	long BarSize = pci_resource_len(PciDev, BarNumber);
-
-	/*
-	 * No space to allocate, quick exit, skip Allocation.
-	 */
-	if (BarSize == 0)
-		return;
-	/*
-	 * Set Resource values.
-	 */
-	spin_lock(&iSeriesIoMmTableLock);
-	BarResource->name = iSeriesPciIoText;
-	BarResource->start =
-		iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex;
-	BarResource->start += iSeries_Base_Io_Memory;
-	BarResource->end = BarResource->start+BarSize-1;
-	/*
-	 * Allocate the number of table entries needed for BAR.
-	 */
-	while (BarSize > 0 ) {
-		*(iSeries_IoMmTable + iSeries_CurrentIndex) =
-			(struct iSeries_Device_Node *)PciDev->sysdata;
-		*(iSeries_IoBarTable + iSeries_CurrentIndex) = BarNumber;
-		BarSize -= iSeries_IoMmTable_Entry_Size;
-		++iSeries_CurrentIndex;
-	}
-	iSeries_Max_Io_Memory = iSeries_Base_Io_Memory +
-		(iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex);
-	spin_unlock(&iSeriesIoMmTableLock);
-}
-
-/*
- * iSeries_allocateDeviceBars
- *
- * - Allocates ALL pci_dev BAR's and updates the resources with the
- *   BAR value.  BARS with zero length will have the resources
- *   The HvCallPci_getBarParms is used to get the size of the BAR
- *   space.  It calls iSeries_IoMmTable_AllocateEntry to allocate
- *   each entry.
- * - Loops through The Bar resources(0 - 5) including the ROM
- *   is resource(6).
- */
-void iSeries_allocateDeviceBars(struct pci_dev *PciDev)
-{
-	struct resource *BarResource;
-	int BarNumber;
-
-	for (BarNumber = 0; BarNumber <= PCI_ROM_RESOURCE; ++BarNumber) {
-		BarResource = &PciDev->resource[BarNumber];
-		iSeries_IoMmTable_AllocateEntry(PciDev, BarNumber);
-    	}
-}
-
-/*
- * Translates the IoAddress to the device that is mapped to IoSpace.
- * This code is inlined, see the iSeries_pci.c file for the replacement.
- */
-struct iSeries_Device_Node *iSeries_xlateIoMmAddress(void *IoAddress)
-{
-	return NULL;	   
-}
-
-/*
- * Status hook for IoMmTable
- */
-void iSeries_IoMmTable_Status(void)
-{
-	PCIFR("IoMmTable......: 0x%p", iSeries_IoMmTable);
-	PCIFR("IoMmTable Range: 0x%p to 0x%p", iSeries_Base_Io_Memory,
-			iSeries_Max_Io_Memory);
-}
diff -Nru a/arch/ppc64/kernel/iSeries_IoMmTable.h b/arch/ppc64/kernel/iSeries_IoMmTable.h
--- a/arch/ppc64/kernel/iSeries_IoMmTable.h	2004-10-28 22:25:58 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,85 +0,0 @@
-#ifndef _ISERIES_IOMMTABLE_H
-#define _ISERIES_IOMMTABLE_H
-/************************************************************************/
-/* File iSeries_IoMmTable.h created by Allan Trautman on Dec 12 2001.   */
-/************************************************************************/
-/* Interfaces for the write/read Io address translation table.          */
-/* Copyright (C) 20yy  Allan H Trautman, 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:                                                     */
-/*   Created December 12, 2000                                          */
-/*   Ported to ppc64, August 30, 2001                                   */
-/* End Change Activity                                                  */
-/************************************************************************/
-
-struct pci_dev;
-struct iSeries_Device_Node;
-
-extern struct iSeries_Device_Node **iSeries_IoMmTable;
-extern u8 *iSeries_IoBarTable;
-extern unsigned long iSeries_Base_Io_Memory;
-extern unsigned long iSeries_Max_Io_Memory;
-extern unsigned long iSeries_Base_Io_Memory;
-extern unsigned long iSeries_IoMmTable_Entry_Size;
-/*
- * iSeries_IoMmTable_Initialize
- *
- * - Initalizes the Address Translation Table and get it ready for use.
- *   Must be called before any client calls any of the other methods.
- *
- * Parameters: None.
- *
- * Return: None.
- */
-extern void iSeries_IoMmTable_Initialize(void);
-extern void iSeries_IoMmTable_Status(void);
-
-/*
- * iSeries_allocateDeviceBars
- *
- * - Allocates ALL pci_dev BAR's and updates the resources with the BAR
- *   value.  BARS with zero length will not have the resources.  The
- *   HvCallPci_getBarParms is used to get the size of the BAR space.
- *   It calls iSeries_IoMmTable_AllocateEntry to allocate each entry.
- *
- * Parameters:
- * pci_dev = Pointer to pci_dev structure that will be mapped to pseudo
- *           I/O Address.
- *
- * Return:
- *   The pci_dev I/O resources updated with pseudo I/O Addresses.
- */
-extern void iSeries_allocateDeviceBars(struct pci_dev *);
-
-/*
- * iSeries_xlateIoMmAddress
- *
- * - Translates an I/O Memory address to Device Node that has been the
- *   allocated the psuedo I/O Address.
- *
- * Parameters:
- * IoAddress = I/O Memory Address.
- *
- * Return:
- *   An iSeries_Device_Node to the device mapped to the I/O address. The
- *   BarNumber and BarOffset are valid if the Device Node is returned.
- */
-extern struct iSeries_Device_Node *iSeries_xlateIoMmAddress(void *IoAddress);
-
-#endif /* _ISERIES_IOMMTABLE_H */
diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
--- a/arch/ppc64/kernel/iSeries_pci.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/iSeries_pci.c	2004-10-28 22:25:59 -07:00
@@ -1,4 +1,3 @@
-#define PCIFR(...)
 /*
  * iSeries_pci.c
  *
@@ -47,27 +46,19 @@
 #include <asm/iSeries/iSeries_pci.h>
 #include <asm/iSeries/mf.h>
 
-#include "iSeries_IoMmTable.h"
 #include "pci.h"
 
 extern int panic_timeout;
 
-extern unsigned long iSeries_Base_Io_Memory;    
-
-extern struct iommu_table *tceTables[256];
 extern unsigned long io_page_mask;
 
-extern void iSeries_MmIoTest(void);
-
 /*
  * Forward declares of prototypes. 
  */
 static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn);
-static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb);
-static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus,
-		int IdSel);
-static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
-		struct HvCallPci_BridgeInfo *Info);
+static void scan_PHB_slots(struct pci_controller *Phb);
+static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
+static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
 
 LIST_HEAD(iSeries_Global_Device_List);
 
@@ -88,7 +79,116 @@
 static struct pci_ops iSeries_pci_ops;
 
 /*
- * Log Error infor in Flight Recorder to system Console.
+ * Table defines
+ * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
+ */
+#define IOMM_TABLE_MAX_ENTRIES	1024
+#define IOMM_TABLE_ENTRY_SIZE	0x0000000000400000UL
+#define BASE_IO_MEMORY		0xE000000000000000UL
+
+static unsigned long max_io_memory = 0xE000000000000000UL;
+static long current_iomm_table_entry;
+
+/*
+ * Lookup Tables.
+ */
+static struct iSeries_Device_Node **iomm_table;
+static u8 *iobar_table;
+
+/*
+ * Static and Global variables
+ */
+static char *pci_io_text = "iSeries PCI I/O";
+static spinlock_t iomm_table_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * iomm_table_initialize
+ *
+ * Allocates and initalizes the Address Translation Table and Bar
+ * Tables to get them ready for use.  Must be called before any
+ * I/O space is handed out to the device BARs.
+ */
+static void iomm_table_initialize(void)
+{
+	spin_lock(&iomm_table_lock);
+	iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
+			GFP_KERNEL);
+	iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
+			GFP_KERNEL);
+	spin_unlock(&iomm_table_lock);
+	if ((iomm_table == NULL) || (iobar_table == NULL))
+		panic("PCI: I/O tables allocation failed.\n");
+}
+
+/*
+ * iomm_table_allocate_entry
+ *
+ * Adds pci_dev entry in address translation table
+ *
+ * - Allocates the number of entries required in table base on BAR
+ *   size.
+ * - Allocates starting at BASE_IO_MEMORY and increases.
+ * - The size is round up to be a multiple of entry size.
+ * - CurrentIndex is incremented to keep track of the last entry.
+ * - Builds the resource entry for allocated BARs.
+ */
+static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num)
+{
+	struct resource *bar_res = &dev->resource[bar_num];
+	long bar_size = pci_resource_len(dev, bar_num);
+
+	/*
+	 * No space to allocate, quick exit, skip Allocation.
+	 */
+	if (bar_size == 0)
+		return;
+	/*
+	 * Set Resource values.
+	 */
+	spin_lock(&iomm_table_lock);
+	bar_res->name = pci_io_text;
+	bar_res->start =
+		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
+	bar_res->start += BASE_IO_MEMORY;
+	bar_res->end = bar_res->start + bar_size - 1;
+	/*
+	 * Allocate the number of table entries needed for BAR.
+	 */
+	while (bar_size > 0 ) {
+		iomm_table[current_iomm_table_entry] = dev->sysdata;
+		iobar_table[current_iomm_table_entry] = bar_num;
+		bar_size -= IOMM_TABLE_ENTRY_SIZE;
+		++current_iomm_table_entry;
+	}
+	max_io_memory = BASE_IO_MEMORY +
+		(IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry);
+	spin_unlock(&iomm_table_lock);
+}
+
+/*
+ * allocate_device_bars
+ *
+ * - Allocates ALL pci_dev BAR's and updates the resources with the
+ *   BAR value.  BARS with zero length will have the resources
+ *   The HvCallPci_getBarParms is used to get the size of the BAR
+ *   space.  It calls iomm_table_allocate_entry to allocate
+ *   each entry.
+ * - Loops through The Bar resources(0 - 5) including the ROM
+ *   is resource(6).
+ */
+static void allocate_device_bars(struct pci_dev *dev)
+{
+	struct resource *bar_res;
+	int bar_num;
+
+	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) {
+		bar_res = &dev->resource[bar_num];
+		iomm_table_allocate_entry(dev, bar_num);
+    	}
+}
+
+/*
+ * Log error information to system console.
  * Filter out the device not there errors.
  * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx
  * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
@@ -99,7 +199,6 @@
 {
 	if (HvRc == 0x0302)
 		return;
-
 	printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
 	       Error_Text, Bus, SubBus, AgentId, HvRc);
 }
@@ -133,8 +232,6 @@
 	node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
 	node->IoRetry = 0;
 	iSeries_Get_Location_Code(node);
-	PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(node),
-			ISERIES_DEVFUN(node), node);
 	return node;
 }
 
@@ -160,10 +257,8 @@
 		if (ret == 0) {
 			printk("bus %d appears to exist\n", bus);
 			phb = pci_alloc_pci_controller(phb_type_hypervisor);
-			if (phb == NULL) {
-				PCIFR("Allocate pci_controller failed.");
+			if (phb == NULL)
 				return -1;
-			}
 			phb->pci_mem_offset = phb->local_number = bus;
 			phb->first_busno = bus;
 			phb->last_busno = bus;
@@ -171,10 +266,9 @@
 
 			PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",
 					phb, bus);
-			PCIFR("Create iSeries PHB controller: %04X", bus);
 
 			/* Find and connect the devices. */
-			iSeries_Scan_PHBs_Slots(phb);
+			scan_PHB_slots(phb);
 		}
 		/*
 		 * Check for Unexpected Return code, a clue that something
@@ -195,7 +289,7 @@
 void iSeries_pcibios_init(void)
 {
 	PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); 
-	iSeries_IoMmTable_Initialize();
+	iomm_table_initialize();
 	find_and_init_phbs();
 	io_page_mask = -1;
 	/* pci_assign_all_busses = 0;		SFRXXX*/
@@ -231,7 +325,7 @@
 			PPCDBG(PPCDBG_BUSWALK,
 					"pdev 0x%p <==> DevNode 0x%p\n",
 					pdev, node);
-			iSeries_allocateDeviceBars(pdev);
+			allocate_device_bars(pdev);
 			iSeries_Device_Information(pdev, Buffer,
 					sizeof(Buffer));
 			printk("%d. %s\n", DeviceCount, Buffer);
@@ -241,7 +335,6 @@
 					(unsigned long)pdev);
 		pdev->irq = node->Irq;
 	}
-	iSeries_IoMmTable_Status();
 	iSeries_activate_IRQs();
 	mf_displaySrc(0xC9000200);
 }
@@ -260,7 +353,7 @@
 /*
  * Loop through each node function to find usable EADs bridges.  
  */
-static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb)
+static void scan_PHB_slots(struct pci_controller *Phb)
 {
 	struct HvCallPci_DeviceInfo *DevInfo;
 	HvBusNumber bus = Phb->local_number;	/* System Bus */	
@@ -283,7 +376,7 @@
 				sizeof(struct HvCallPci_DeviceInfo));
 		if (HvRc == 0) {
 			if (DevInfo->deviceType == HvCallPci_NodeDevice)
-				iSeries_Scan_EADs_Bridge(bus, SubBus, IdSel);
+				scan_EADS_bridge(bus, SubBus, IdSel);
 			else
 				printk("PCI: Invalid System Configuration(0x%02X)"
 				       " for bus 0x%02x id 0x%02x.\n",
@@ -295,7 +388,7 @@
 	kfree(DevInfo);
 }
 
-static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus,
+static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
 		int IdSel)
 {
 	struct HvCallPci_BridgeInfo *BridgeInfo;
@@ -340,7 +433,7 @@
 				if (BridgeInfo->busUnitInfo.deviceType ==
 						HvCallPci_BridgeDevice)  {
 					/* Scan_Bridge_Slot...: 0x18.00.12 */
-					iSeries_Scan_Bridge_Slot(bus, BridgeInfo);
+					scan_bridge_slot(bus, BridgeInfo);
 				} else
 					printk("PCI: Invalid Bridge Configuration(0x%02X)",
 						BridgeInfo->busUnitInfo.deviceType);
@@ -355,7 +448,7 @@
 /*
  * This assumes that the node slot is always on the primary bus!
  */
-static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
+static int scan_bridge_slot(HvBusNumber Bus,
 		struct HvCallPci_BridgeInfo *BridgeInfo)
 {
 	struct iSeries_Device_Node *node;
@@ -593,12 +686,8 @@
 		return -1;	/* Retry Try */
 	}
 	/* If retry was in progress, log success and rest retry count */
-	if (DevNode->IoRetry > 0) {
-		PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).",
-				TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
-				DevNode->IoRetry);
+	if (DevNode->IoRetry > 0)
 		DevNode->IoRetry = 0;
-	}
 	return 0; 
 }
 
@@ -607,8 +696,9 @@
  * Note: Make sure the passed variable end up on the stack to avoid
  * the exposure of being device global.
  */
-static inline struct iSeries_Device_Node *xlateIoMmAddress(const volatile void __iomem *IoAddress,
-		 u64 *dsaptr, u64 *BarOffsetPtr)
+static inline struct iSeries_Device_Node *xlate_iomm_address(
+		const volatile void __iomem *IoAddress,
+		u64 *dsaptr, u64 *BarOffsetPtr)
 {
 	unsigned long OrigIoAddr;
 	unsigned long BaseIoAddr;
@@ -616,17 +706,16 @@
 	struct iSeries_Device_Node *DevNode;
 
 	OrigIoAddr = (unsigned long __force)IoAddress;
-	if ((OrigIoAddr < iSeries_Base_Io_Memory) ||
-			(OrigIoAddr >= iSeries_Max_Io_Memory))
+	if ((OrigIoAddr < BASE_IO_MEMORY) || (OrigIoAddr >= max_io_memory))
 		return NULL;
-	BaseIoAddr = OrigIoAddr - iSeries_Base_Io_Memory;
-	TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size;
-	DevNode = iSeries_IoMmTable[TableIndex];
+	BaseIoAddr = OrigIoAddr - BASE_IO_MEMORY;
+	TableIndex = BaseIoAddr / IOMM_TABLE_ENTRY_SIZE;
+	DevNode = iomm_table[TableIndex];
 
 	if (DevNode != NULL) {
-		int barnum = iSeries_IoBarTable[TableIndex];
+		int barnum = iobar_table[TableIndex];
 		*dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24);
-		*BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size;
+		*BarOffsetPtr = BaseIoAddr % IOMM_TABLE_ENTRY_SIZE;
 	} else
 		panic("PCI: Invalid PCI IoAddress detected!\n");
 	return DevNode;
@@ -647,7 +736,7 @@
 	u64 dsa;
 	struct HvCallPci_LoadReturn ret;
 	struct iSeries_Device_Node *DevNode =
-		xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
+		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
 
 	if (DevNode == NULL) {
 		static unsigned long last_jiffies;
@@ -676,7 +765,7 @@
 	u64 dsa;
 	struct HvCallPci_LoadReturn ret;
 	struct iSeries_Device_Node *DevNode =
-		xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
+		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
 
 	if (DevNode == NULL) {
 		static unsigned long last_jiffies;
@@ -706,7 +795,7 @@
 	u64 dsa;
 	struct HvCallPci_LoadReturn ret;
 	struct iSeries_Device_Node *DevNode =
-		xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
+		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
 
 	if (DevNode == NULL) {
 		static unsigned long last_jiffies;
@@ -743,7 +832,7 @@
 	u64 dsa;
 	u64 rc;
 	struct iSeries_Device_Node *DevNode =
-		xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
+		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
 
 	if (DevNode == NULL) {
 		static unsigned long last_jiffies;
@@ -770,7 +859,7 @@
 	u64 dsa;
 	u64 rc;
 	struct iSeries_Device_Node *DevNode =
-		xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
+		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
 
 	if (DevNode == NULL) {
 		static unsigned long last_jiffies;
@@ -797,7 +886,7 @@
 	u64 dsa;
 	u64 rc;
 	struct iSeries_Device_Node *DevNode =
-		xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
+		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
 
 	if (DevNode == NULL) {
 		static unsigned long last_jiffies;
diff -Nru a/arch/ppc64/kernel/iSeries_smp.c b/arch/ppc64/kernel/iSeries_smp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/iSeries_smp.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,151 @@
+/*
+ * SMP support for iSeries machines.
+ *
+ * Dave Engebretsen, Peter Bergner, and
+ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+ *
+ * Plus various changes from other IBM teams...
+ *
+ *      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.
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/naca.h>
+#include <asm/paca.h>
+#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/HvCall.h>
+#include <asm/iSeries/HvCallCfg.h>
+#include <asm/time.h>
+#include <asm/ppcdebug.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/system.h>
+
+static unsigned long iSeries_smp_message[NR_CPUS];
+
+void iSeries_smp_message_recv( struct pt_regs * regs )
+{
+	int cpu = smp_processor_id();
+	int msg;
+
+	if ( num_online_cpus() < 2 )
+		return;
+
+	for ( msg = 0; msg < 4; ++msg )
+		if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) )
+			smp_message_recv( msg, regs );
+}
+
+static inline void smp_iSeries_do_message(int cpu, int msg)
+{
+	set_bit(msg, &iSeries_smp_message[cpu]);
+	HvCall_sendIPI(&(paca[cpu]));
+}
+
+static void smp_iSeries_message_pass(int target, int msg)
+{
+	int i;
+
+	if (target < NR_CPUS)
+		smp_iSeries_do_message(target, msg);
+	else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_iSeries_do_message(i, msg);
+		}
+	}
+}
+
+static int smp_iSeries_numProcs(void)
+{
+	unsigned np, i;
+
+	np = 0;
+        for (i=0; i < NR_CPUS; ++i) {
+                if (paca[i].lppaca.xDynProcStatus < 2) {
+			cpu_set(i, cpu_possible_map);
+			cpu_set(i, cpu_present_map);
+                        ++np;
+                }
+        }
+	return np;
+}
+
+static int smp_iSeries_probe(void)
+{
+	unsigned i;
+	unsigned np = 0;
+
+	for (i=0; i < NR_CPUS; ++i) {
+		if (paca[i].lppaca.xDynProcStatus < 2) {
+			/*paca[i].active = 1;*/
+			++np;
+		}
+	}
+
+	return np;
+}
+
+static void smp_iSeries_kick_cpu(int nr)
+{
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+	/* Verify that our partition has a processor nr */
+	if (paca[nr].lppaca.xDynProcStatus >= 2)
+		return;
+
+	/* The processor is currently spinning, waiting
+	 * for the cpu_start field to become non-zero
+	 * After we set cpu_start, the processor will
+	 * continue on to secondary_start in iSeries_head.S
+	 */
+	paca[nr].cpu_start = 1;
+}
+
+static void __devinit smp_iSeries_setup_cpu(int nr)
+{
+}
+
+static struct smp_ops_t iSeries_smp_ops = {
+	.message_pass = smp_iSeries_message_pass,
+	.probe        = smp_iSeries_probe,
+	.kick_cpu     = smp_iSeries_kick_cpu,
+	.setup_cpu    = smp_iSeries_setup_cpu,
+};
+
+/* This is called very early. */
+void __init smp_init_iSeries(void)
+{
+	smp_ops = &iSeries_smp_ops;
+	systemcfg->processorCount	= smp_iSeries_numProcs();
+}
+
diff -Nru a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
--- a/arch/ppc64/kernel/idle.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/idle.c	2004-10-28 22:25:59 -07:00
@@ -22,6 +22,7 @@
 #include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/sysctl.h>
+#include <linux/smp.h>
 
 #include <asm/system.h>
 #include <asm/processor.h>
@@ -363,12 +364,13 @@
 		}
 	}
 #endif /* CONFIG_PPC_PSERIES */
-#ifdef CONFIG_PPC_PMAC
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
+#ifndef CONFIG_PPC_ISERIES
+	if (systemcfg->platform == PLATFORM_POWERMAC ||
+	    systemcfg->platform == PLATFORM_MAPLE) {
 		printk(KERN_INFO "Using native/NAP idle loop\n");
 		idle_loop = native_idle;
 	}
-#endif /* CONFIG_PPC_PMAC */
+#endif /* CONFIG_PPC_ISERIES */
 
 	return 1;
 }
diff -Nru a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
--- a/arch/ppc64/kernel/lparcfg.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/lparcfg.c	2004-10-28 22:25:57 -07:00
@@ -192,7 +192,7 @@
  * is coming, but at this time is still problematic, so for now this
  * function will return 0.
  */
-static unsigned long get_purr()
+static unsigned long get_purr(void)
 {
 	unsigned long sum_purr = 0;
 	return sum_purr;
@@ -524,10 +524,10 @@
 }
 
 struct file_operations lparcfg_fops = {
-      owner:THIS_MODULE,
-      read:seq_read,
-      open:lparcfg_open,
-      release:single_release,
+      .owner	= THIS_MODULE,
+      .read	= seq_read,
+      .open	= lparcfg_open,
+      .release	= single_release,
 };
 
 int __init lparcfg_init(void)
diff -Nru a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/maple_pci.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
+ *		      IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/iommu.h>
+
+#include "pci.h"
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern int pci_probe_only;
+extern int pci_read_irq_line(struct pci_dev *pci_dev);
+
+static struct pci_controller *u3_agp, *u3_ht;
+
+static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
+{
+	for (; node != 0;node = node->sibling) {
+		int * bus_range;
+		unsigned int *class_code;
+		int len;
+
+		/* For PCI<->PCI bridges or CardBus bridges, we go down */
+		class_code = (unsigned int *) get_property(node, "class-code", NULL);
+		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+			continue;
+		bus_range = (int *) get_property(node, "bus-range", &len);
+		if (bus_range != NULL && len > 2 * sizeof(int)) {
+			if (bus_range[1] > higher)
+				higher = bus_range[1];
+		}
+		higher = fixup_one_level_bus_range(node->child, higher);
+	}
+	return higher;
+}
+
+/* This routine fixes the "bus-range" property of all bridges in the
+ * system since they tend to have their "last" member wrong on macs
+ *
+ * Note that the bus numbers manipulated here are OF bus numbers, they
+ * are not Linux bus numbers.
+ */
+static void __init fixup_bus_range(struct device_node *bridge)
+{
+	int * bus_range;
+	int len;
+
+	/* Lookup the "bus-range" property for the hose */
+	bus_range = (int *) get_property(bridge, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s\n",
+			       bridge->full_name);
+		return;
+	}
+	bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
+}
+
+
+#define U3_AGP_CFA0(devfn, off)	\
+	((1 << (unsigned long)PCI_SLOT(dev_fn)) \
+	| (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
+	| (((unsigned long)(off)) & 0xFCUL))
+
+#define U3_AGP_CFA1(bus, devfn, off)	\
+	((((unsigned long)(bus)) << 16) \
+	|(((unsigned long)(devfn)) << 8) \
+	|(((unsigned long)(off)) & 0xFCUL) \
+	|1UL)
+
+static unsigned long u3_agp_cfg_access(struct pci_controller* hose,
+				       u8 bus, u8 dev_fn, u8 offset)
+{
+	unsigned int caddr;
+
+	if (bus == hose->first_busno) {
+		if (dev_fn < (11 << 3))
+			return 0;
+		caddr = U3_AGP_CFA0(dev_fn, offset);
+	} else
+		caddr = U3_AGP_CFA1(bus, dev_fn, offset);
+
+	/* Uninorth will return garbage if we don't read back the value ! */
+	do {
+		out_le32(hose->cfg_addr, caddr);
+	} while (in_le32(hose->cfg_addr) != caddr);
+
+	offset &= 0x07;
+	return ((unsigned long)hose->cfg_data) + offset;
+}
+
+static int u3_agp_read_config(struct pci_bus *bus, unsigned int devfn,
+			      int offset, int len, u32 *val)
+{
+	struct pci_controller *hose;
+	unsigned long addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val = in_8((u8 *)addr);
+		break;
+	case 2:
+		*val = in_le16((u16 *)addr);
+		break;
+	default:
+		*val = in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int u3_agp_write_config(struct pci_bus *bus, unsigned int devfn,
+			       int offset, int len, u32 val)
+{
+	struct pci_controller *hose;
+	unsigned long addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	addr = u3_agp_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		out_8((u8 *)addr, val);
+		(void) in_8((u8 *)addr);
+		break;
+	case 2:
+		out_le16((u16 *)addr, val);
+		(void) in_le16((u16 *)addr);
+		break;
+	default:
+		out_le32((u32 *)addr, val);
+		(void) in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops u3_agp_pci_ops =
+{
+	u3_agp_read_config,
+	u3_agp_write_config
+};
+
+
+#define U3_HT_CFA0(devfn, off)		\
+		((((unsigned long)devfn) << 8) | offset)
+#define U3_HT_CFA1(bus, devfn, off)	\
+		(U3_HT_CFA0(devfn, off) \
+		+ (((unsigned long)bus) << 16) \
+		+ 0x01000000UL)
+
+static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
+				      u8 bus, u8 devfn, u8 offset)
+{
+	if (bus == hose->first_busno) {
+		if (PCI_SLOT(devfn) == 0)
+			return 0;
+		return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
+	} else
+		return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset);
+}
+
+static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
+			     int offset, int len, u32 *val)
+{
+	struct pci_controller *hose;
+	unsigned long addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val = in_8((u8 *)addr);
+		break;
+	case 2:
+		*val = in_le16((u16 *)addr);
+		break;
+	default:
+		*val = in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
+			      int offset, int len, u32 val)
+{
+	struct pci_controller *hose;
+	unsigned long addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		out_8((u8 *)addr, val);
+		(void) in_8((u8 *)addr);
+		break;
+	case 2:
+		out_le16((u16 *)addr, val);
+		(void) in_le16((u16 *)addr);
+		break;
+	default:
+		out_le32((u32 *)addr, val);
+		(void) in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops u3_ht_pci_ops =
+{
+	u3_ht_read_config,
+	u3_ht_write_config
+};
+
+static void __init setup_u3_agp(struct pci_controller* hose)
+{
+	/* On G5, we move AGP up to high bus number so we don't need
+	 * to reassign bus numbers for HT. If we ever have P2P bridges
+	 * on AGP, we'll have to move pci_assign_all_busses to the
+	 * pci_controller structure so we enable it for AGP and not for
+	 * HT childs.
+	 * We hard code the address because of the different size of
+	 * the reg address cell, we shall fix that by killing struct
+	 * reg_property and using some accessor functions instead
+	 */
+       	hose->first_busno = 0xf0;
+	hose->last_busno = 0xff;
+	hose->ops = &u3_agp_pci_ops;
+	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+
+	u3_agp = hose;
+}
+
+static void __init setup_u3_ht(struct pci_controller* hose)
+{
+	hose->ops = &u3_ht_pci_ops;
+
+	/* We hard code the address because of the different size of
+	 * the reg address cell, we shall fix that by killing struct
+	 * reg_property and using some accessor functions instead
+	 */
+	hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xef;
+
+	u3_ht = hose;
+}
+
+static int __init add_bridge(struct device_node *dev)
+{
+	int len;
+	struct pci_controller *hose;
+	char* disp_name;
+	int *bus_range;
+	int primary = 1;
+ 	struct property *of_prop;
+
+	DBG("Adding PCI host bridge %s\n", dev->full_name);
+
+       	bus_range = (int *) get_property(dev, "bus-range", &len);
+       	if (bus_range == NULL || len < 2 * sizeof(int)) {
+       		printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+       			       dev->full_name);
+       	}
+
+       	hose = pci_alloc_pci_controller(phb_type_apple);
+       	if (!hose)
+       		return -ENOMEM;
+       	hose->arch_data = dev;
+       	hose->first_busno = bus_range ? bus_range[0] : 0;
+       	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+	of_prop = (struct property *)alloc_bootmem(sizeof(struct property) +
+			sizeof(hose->global_number));        
+	if (of_prop) {
+		memset(of_prop, 0, sizeof(struct property));
+		of_prop->name = "linux,pci-domain";
+		of_prop->length = sizeof(hose->global_number);
+		of_prop->value = (unsigned char *)&of_prop[1];
+		memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number));
+		prom_add_property(dev, of_prop);
+	}
+
+	disp_name = NULL;
+       	if (device_is_compatible(dev, "u3-agp")) {
+       		setup_u3_agp(hose);
+       		disp_name = "U3-AGP";
+       		primary = 0;
+       	} else if (device_is_compatible(dev, "u3-ht")) {
+       		setup_u3_ht(hose);
+       		disp_name = "U3-HT";
+       		primary = 1;
+       	}
+       	printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
+       		disp_name, hose->first_busno, hose->last_busno);
+
+       	/* Interpret the "ranges" property */
+       	/* This also maps the I/O region and sets isa_io/mem_base */
+       	pci_process_bridge_OF_ranges(hose, dev);
+	pci_setup_phb_io(hose, primary);
+
+       	/* Fixup "bus-range" OF property */
+       	fixup_bus_range(dev);
+
+	return 0;
+}
+
+
+void __init maple_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+
+	DBG(" -> maple_pcibios_fixup\n");
+
+	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+		pci_read_irq_line(dev);
+
+	/* Do the mapping of the IO space */
+	phbs_remap_io();
+
+	/* Fixup the pci_bus sysdata pointers */
+	pci_fix_bus_sysdata();
+
+	/* Setup the iommu */
+	iommu_setup_u3();
+
+	DBG(" <- maple_pcibios_fixup\n");
+}
+
+static void __init maple_fixup_phb_resources(void)
+{
+	struct pci_controller *hose, *tmp;
+	
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+		hose->io_resource.start += offset;
+		hose->io_resource.end += offset;
+		printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n",
+		       hose->global_number,
+		       hose->io_resource.start, hose->io_resource.end);
+	}
+}
+
+void __init maple_pci_init(void)
+{
+	struct device_node *np, *root;
+	struct device_node *ht = NULL;
+
+	/* Probe root PCI hosts, that is on U3 the AGP host and the
+	 * HyperTransport host. That one is actually "kept" around
+	 * and actually added last as it's resource management relies
+	 * on the AGP resources to have been setup first
+	 */
+	root = of_find_node_by_path("/");
+	if (root == NULL) {
+		printk(KERN_CRIT "maple_find_bridges: can't find root of device tree\n");
+		return;
+	}
+	for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
+		if (np->name == NULL)
+			continue;
+		if (strcmp(np->name, "pci") == 0) {
+			if (add_bridge(np) == 0)
+				of_node_get(np);
+		}
+		if (strcmp(np->name, "ht") == 0) {
+			of_node_get(np);
+			ht = np;
+		}
+	}
+	of_node_put(root);
+
+	/* Now setup the HyperTransport host if we found any
+	 */
+	if (ht && add_bridge(ht) != 0)
+		of_node_put(ht);
+
+	/* Fixup the IO resources on our host bridges as the common code
+	 * does it only for childs of the host bridges
+	 */
+	maple_fixup_phb_resources();
+
+	/* Setup the linkage between OF nodes and PHBs */ 
+	pci_devs_phb_init();
+
+	/* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
+	 * assume there is no P2P bridge on the AGP bus, which should be a
+	 * safe assumptions hopefully.
+	 */
+	if (u3_agp) {
+		struct device_node *np = u3_agp->arch_data;
+		np->busno = 0xf0;
+		for (np = np->child; np; np = np->sibling)
+			np->busno = 0xf0;
+	}
+
+	/* Tell pci.c to use the common resource allocation mecanism */
+	pci_probe_only = 0;
+	
+	/* Allow all IO */
+	io_page_mask = -1;
+}
+
+int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
+{
+	struct device_node *np;
+	int irq = channel ? 15 : 14;
+
+	if (pdev->vendor != PCI_VENDOR_ID_AMD ||
+	    pdev->device != PCI_DEVICE_ID_AMD_8111_IDE)
+		return irq;
+
+	np = pci_device_to_OF_node(pdev);
+	if (np == NULL)
+		return irq;
+	if (np->n_intrs < 2)
+		return irq;
+	return np->intrs[channel & 0x1].line;
+}
+
+/* XXX: To remove once all firmwares are ok */
+static void fixup_maple_ide(struct pci_dev* dev)
+{
+#if 0 /* Enable this to enable IDE port 0 */
+	{
+		u8 v;
+
+		pci_read_config_byte(dev, 0x40, &v);
+		v |= 2;
+		pci_write_config_byte(dev, 0x40, v);
+	}
+#endif
+#if 0 /* fix bus master base */
+	pci_write_config_dword(dev, 0x20, 0xcc01);
+	printk("old ide resource: %lx -> %lx \n",
+	       dev->resource[4].start, dev->resource[4].end);
+	dev->resource[4].start = 0xcc00;
+	dev->resource[4].end = 0xcc10;
+#endif
+#if 1 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
+	{
+		struct pci_dev *apicdev;
+		u32 v;
+
+		apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
+		if (apicdev == NULL)
+			printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
+		else {
+			pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
+			pci_read_config_dword(apicdev, 0xf4, &v);
+			v &= ~0x00000022;
+			pci_write_config_dword(apicdev, 0xf4, v);
+			pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
+			pci_read_config_dword(apicdev, 0xf4, &v);
+			v &= ~0x00000022;
+			pci_write_config_dword(apicdev, 0xf4, v);
+			pci_dev_put(apicdev);
+		}
+	}
+#endif
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
+			 fixup_maple_ide);
diff -Nru a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/maple_setup.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,243 @@
+/*
+ *  arch/ppc64/kernel/maple_setup.c
+ *
+ *  (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org),
+ *                     IBM Corp. 
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ */
+
+#define DEBUG
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/vt_kern.h>
+#include <linux/console.h>
+#include <linux/ide.h>
+#include <linux/pci.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/smp.h>
+
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/machdep.h>
+#include <asm/dma.h>
+#include <asm/cputable.h>
+#include <asm/time.h>
+#include <asm/of_device.h>
+#include <asm/lmb.h>
+
+#include "mpic.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+extern int maple_set_rtc_time(struct rtc_time *tm);
+extern void maple_get_rtc_time(struct rtc_time *tm);
+extern void maple_get_boot_time(struct rtc_time *tm);
+extern void maple_calibrate_decr(void);
+extern void maple_pci_init(void);
+extern void maple_pcibios_fixup(void);
+extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
+extern void generic_find_legacy_serial_ports(unsigned int *default_speed);
+
+
+static void maple_restart(char *cmd)
+{
+}
+
+static void maple_power_off(void)
+{
+}
+
+static void maple_halt(void)
+{
+}
+
+#ifdef CONFIG_SMP
+struct smp_ops_t maple_smp_ops = {
+	.probe		= smp_mpic_probe,
+	.message_pass	= smp_mpic_message_pass,
+	.kick_cpu	= smp_generic_kick_cpu,
+	.setup_cpu	= smp_mpic_setup_cpu,
+	.give_timebase	= smp_generic_give_timebase,
+	.take_timebase	= smp_generic_take_timebase,
+};
+#endif /* CONFIG_SMP */
+
+void __init maple_setup_arch(void)
+{
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	/* Setup SMP callback */
+#ifdef CONFIG_SMP
+	smp_ops = &maple_smp_ops;
+#endif
+	/* Setup the PCI DMA to "direct" by default. May be overriden
+	 * by iommu later on
+	 */
+	pci_dma_init_direct();
+
+	/* Lookup PCI hosts */
+       	maple_pci_init();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+}
+
+/* 
+ * Early initialization.
+ */
+static void __init maple_init_early(void)
+{
+	unsigned int default_speed;
+
+	DBG(" -> maple_init_early\n");
+
+	/* Initialize hash table, from now on, we can take hash faults
+	 * and call ioremap
+	 */
+	hpte_init_native();
+
+	/* Find the serial port */
+       	generic_find_legacy_serial_ports(&default_speed);
+
+	DBG("naca->serialPortAddr: %lx\n", (long)naca->serialPortAddr);
+
+	if (naca->serialPortAddr) {
+		void *comport;
+		/* Map the uart for udbg. */
+		comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
+		udbg_init_uart(comport, default_speed);
+
+		ppc_md.udbg_putc = udbg_putc;
+		ppc_md.udbg_getc = udbg_getc;
+		ppc_md.udbg_getc_poll = udbg_getc_poll;
+		DBG("Hello World !\n");
+	}
+
+	/* Setup interrupt mapping options */
+	naca->interrupt_controller = IC_OPEN_PIC;
+
+	DBG(" <- maple_init_early\n");
+}
+
+
+static __init void maple_init_IRQ(void)
+{
+	struct device_node *root;
+	unsigned int *opprop;
+	unsigned long opic_addr;
+	struct mpic *mpic;
+	unsigned char senses[128];
+	int n;
+
+	DBG(" -> maple_init_IRQ\n");
+
+	/* XXX: Non standard, replace that with a proper openpic/mpic node
+	 * in the device-tree. Find the Open PIC if present */
+	root = of_find_node_by_path("/");
+	opprop = (unsigned int *) get_property(root,
+				"platform-open-pic", NULL);
+	if (opprop == 0)
+		panic("OpenPIC not found !\n");
+
+	n = prom_n_addr_cells(root);
+	for (opic_addr = 0; n > 0; --n)
+		opic_addr = (opic_addr << 32) + *opprop++;
+	of_node_put(root);
+
+	/* Obtain sense values from device-tree */
+	prom_get_irq_senses(senses, 0, 128);
+
+	mpic = mpic_alloc(opic_addr,
+			  MPIC_PRIMARY | MPIC_BIG_ENDIAN |
+			  MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
+			  0, 0, 128, 128, senses, 128, "U3-MPIC");
+	BUG_ON(mpic == NULL);
+	mpic_init(mpic);
+
+	DBG(" <- maple_init_IRQ\n");
+}
+
+static void __init maple_progress(char *s, unsigned short hex)
+{
+	printk("*** %04x : %s\n", hex, s ? s : "");
+}
+
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init maple_probe(int platform)
+{
+	if (platform != PLATFORM_MAPLE)
+		return 0;
+	/*
+	 * On U3, the DART (iommu) must be allocated now since it
+	 * has an impact on htab_initialize (due to the large page it
+	 * occupies having to be broken up so the DART itself is not
+	 * part of the cacheable linar mapping
+	 */
+	alloc_u3_dart_table();
+
+	return 1;
+}
+
+struct machdep_calls __initdata maple_md = {
+	.probe			= maple_probe,
+	.setup_arch		= maple_setup_arch,
+	.init_early		= maple_init_early,
+	.init_IRQ		= maple_init_IRQ,
+	.get_irq		= mpic_get_irq,
+	.pcibios_fixup		= maple_pcibios_fixup,
+#if 0
+	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
+#endif
+	.restart		= maple_restart,
+	.power_off		= maple_power_off,
+	.halt			= maple_halt,
+       	.get_boot_time		= maple_get_boot_time,
+       	.set_rtc_time		= maple_set_rtc_time,
+       	.get_rtc_time		= maple_get_rtc_time,
+      	.calibrate_decr		= maple_calibrate_decr,
+	.progress		= maple_progress,
+};
diff -Nru a/arch/ppc64/kernel/maple_time.c b/arch/ppc64/kernel/maple_time.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/maple_time.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,226 @@
+/*
+ *  arch/ppc64/kernel/maple_time.c
+ *
+ *  (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org),
+ *                     IBM Corp. 
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/time.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+extern void setup_default_decr(void);
+extern void GregorianDay(struct rtc_time * tm);
+
+extern unsigned long ppc_tb_freq;
+extern unsigned long ppc_proc_freq;
+static int maple_rtc_addr;
+
+static int maple_clock_read(int addr)
+{
+	outb_p(addr, maple_rtc_addr);
+	return inb_p(maple_rtc_addr+1);
+}
+
+static void maple_clock_write(unsigned long val, int addr)
+{
+	outb_p(addr, maple_rtc_addr);
+	outb_p(val, maple_rtc_addr+1);
+}
+
+void maple_get_rtc_time(struct rtc_time *tm)
+{
+	int uip, i;
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+
+	/* Since the UIP flag is set for about 2.2 ms and the clock
+	 * is typically written with a precision of 1 jiffy, trying
+	 * to obtain a precision better than a few milliseconds is
+	 * an illusion. Only consistency is interesting, this also
+	 * allows to use the routine for /dev/rtc without a potential
+	 * 1 second kernel busy loop triggered by any reader of /dev/rtc.
+	 */
+
+	for (i = 0; i<1000000; i++) {
+		uip = maple_clock_read(RTC_FREQ_SELECT);
+		tm->tm_sec = maple_clock_read(RTC_SECONDS);
+		tm->tm_min = maple_clock_read(RTC_MINUTES);
+		tm->tm_hour = maple_clock_read(RTC_HOURS);
+		tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH);
+		tm->tm_mon = maple_clock_read(RTC_MONTH);
+		tm->tm_year = maple_clock_read(RTC_YEAR);
+		uip |= maple_clock_read(RTC_FREQ_SELECT);
+		if ((uip & RTC_UIP)==0)
+			break;
+	}
+
+	if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY)
+	    || RTC_ALWAYS_BCD) {
+		BCD_TO_BIN(tm->tm_sec);
+		BCD_TO_BIN(tm->tm_min);
+		BCD_TO_BIN(tm->tm_hour);
+		BCD_TO_BIN(tm->tm_mday);
+		BCD_TO_BIN(tm->tm_mon);
+		BCD_TO_BIN(tm->tm_year);
+	  }
+	if ((tm->tm_year + 1900) < 1970)
+		tm->tm_year += 100;
+
+	GregorianDay(tm);
+}
+
+int maple_set_rtc_time(struct rtc_time *tm)
+{
+	unsigned char save_control, save_freq_select;
+	int sec, min, hour, mon, mday, year;
+
+	spin_lock(&rtc_lock);
+
+	save_control = maple_clock_read(RTC_CONTROL); /* tell the clock it's being set */
+
+	maple_clock_write((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = maple_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+
+	maple_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	sec = tm->tm_sec;
+	min = tm->tm_min;
+	hour = tm->tm_hour;
+	mon = tm->tm_mon;
+	mday = tm->tm_mday;
+	year = tm->tm_year;
+
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BIN_TO_BCD(sec);
+		BIN_TO_BCD(min);
+		BIN_TO_BCD(hour);
+		BIN_TO_BCD(mon);
+		BIN_TO_BCD(mday);
+		BIN_TO_BCD(year);
+	}
+	maple_clock_write(sec, RTC_SECONDS);
+	maple_clock_write(min, RTC_MINUTES);
+	maple_clock_write(hour, RTC_HOURS);
+	maple_clock_write(mon, RTC_MONTH);
+	maple_clock_write(mday, RTC_DAY_OF_MONTH);
+	maple_clock_write(year, RTC_YEAR);
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	maple_clock_write(save_control, RTC_CONTROL);
+	maple_clock_write(save_freq_select, RTC_FREQ_SELECT);
+
+	spin_unlock(&rtc_lock);
+
+	return 0;
+}
+
+void __init maple_get_boot_time(struct rtc_time *tm)
+{
+	struct device_node *rtcs;
+
+	rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
+	if (rtcs && rtcs->addrs) {
+		maple_rtc_addr = rtcs->addrs[0].address;
+		printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr);
+	} else {
+		maple_rtc_addr = RTC_PORT(0); /* legacy address */
+		printk(KERN_INFO "Maple: No device node for RTC, assuming "
+		       "legacy address (0x%x)\n", maple_rtc_addr);
+	}
+	
+	maple_get_rtc_time(tm);
+}
+
+/* XXX FIXME: Some sane defaults: 125 MHz timebase, 1GHz processor */
+#define DEFAULT_TB_FREQ		125000000UL
+#define DEFAULT_PROC_FREQ	(DEFAULT_TB_FREQ * 8)
+
+void __init maple_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	struct div_result divres;
+	unsigned int *fp = NULL;
+
+	/*
+	 * The cpu node should have a timebase-frequency property
+	 * to tell us the rate at which the decrementer counts.
+	 */
+	cpu = of_find_node_by_type(NULL, "cpu");
+
+	ppc_tb_freq = DEFAULT_TB_FREQ;
+	if (cpu != 0)
+		fp = (unsigned int *)get_property(cpu, "timebase-frequency", NULL);
+	if (fp != NULL)
+		ppc_tb_freq = *fp;
+	else
+		printk(KERN_ERR "WARNING: Estimating decrementer frequency (not found)\n");
+	fp = NULL;
+	ppc_proc_freq = DEFAULT_PROC_FREQ;
+	if (cpu != 0)
+		fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);
+	if (fp != NULL)
+		ppc_proc_freq = *fp;
+	else
+		printk(KERN_ERR "WARNING: Estimating processor frequency (not found)\n");
+
+	of_node_put(cpu);
+
+	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       ppc_tb_freq/1000000, ppc_tb_freq%1000000);
+	printk(KERN_INFO "time_init: processor frequency   = %lu.%.6lu MHz\n",
+	       ppc_proc_freq/1000000, ppc_proc_freq%1000000);
+
+	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+	tb_ticks_per_usec = ppc_tb_freq / 1000000;
+	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
+	div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
+	tb_to_xs = divres.result_low;
+
+	setup_default_decr();
+}
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/misc.S	2004-10-28 22:25:59 -07:00
@@ -591,7 +591,7 @@
 	isync
 	b	1b
 
-#ifdef CONFIG_PPC_PMAC
+#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
 /*
  * Do an IO access in real mode
  */
@@ -653,7 +653,7 @@
 	sync
 	isync
 	blr
-#endif /* CONFIG_PPC_PMAC */
+#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
 
 /*
  * Create a kernel thread
@@ -963,6 +963,9 @@
 	.llong .compat_sys_mq_notify
 	.llong .compat_sys_mq_getsetattr
 	.llong .sys_ni_syscall		/* 268 reserved for sys_kexec_load */
+	.llong .sys32_add_key
+	.llong .sys32_request_key
+	.llong .compat_sys_keyctl
 
 	.balign 8
 _GLOBAL(sys_call_table)
@@ -1235,3 +1238,6 @@
 	.llong .sys_mq_notify
 	.llong .sys_mq_getsetattr
 	.llong .sys_ni_syscall		/* 268 reserved for sys_kexec_load */
+	.llong .sys_add_key
+	.llong .sys_request_key		/* 270 */
+	.llong .sys_keyctl
diff -Nru a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/mpic.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,861 @@
+/*
+ *  arch/ppc64/kernel/mpic.c
+ *
+ *  Driver for interrupt controllers following the OpenPIC standard, the
+ *  common implementation beeing IBM's MPIC. This driver also can deal
+ *  with various broken implementations of this HW.
+ *
+ *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
+ *
+ *  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.
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+
+#include "mpic.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static struct mpic *mpics;
+static struct mpic *mpic_primary;
+static spinlock_t mpic_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * Register accessor functions
+ */
+
+
+static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base,
+			    unsigned int reg)
+{
+	if (be)
+		return in_be32(base + (reg >> 2));
+	else
+		return in_le32(base + (reg >> 2));
+}
+
+static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
+			      unsigned int reg, u32 value)
+{
+	if (be)
+		out_be32(base + (reg >> 2), value);
+	else
+		out_le32(base + (reg >> 2), value);
+}
+
+static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
+{
+	unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
+	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+	if (mpic->flags & MPIC_BROKEN_IPI)
+		be = !be;
+	return _mpic_read(be, mpic->gregs, offset);
+}
+
+static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
+{
+	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
+}
+
+static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
+{
+	unsigned int cpu = 0;
+
+	if (mpic->flags & MPIC_PRIMARY)
+		cpu = hard_smp_processor_id();
+
+	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg);
+}
+
+static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
+{
+	unsigned int cpu = 0;
+
+	if (mpic->flags & MPIC_PRIMARY)
+		cpu = hard_smp_processor_id();
+
+	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, value);
+}
+
+static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigned int reg)
+{
+	unsigned int	isu = src_no >> mpic->isu_shift;
+	unsigned int	idx = src_no & mpic->isu_mask;
+
+	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+			  reg + (idx * MPIC_IRQ_STRIDE));
+}
+
+static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
+				   unsigned int reg, u32 value)
+{
+	unsigned int	isu = src_no >> mpic->isu_shift;
+	unsigned int	idx = src_no & mpic->isu_mask;
+
+	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+		    reg + (idx * MPIC_IRQ_STRIDE), value);
+}
+
+#define mpic_read(b,r)		_mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
+#define mpic_write(b,r,v)	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN,(b),(r),(v))
+#define mpic_ipi_read(i)	_mpic_ipi_read(mpic,(i))
+#define mpic_ipi_write(i,v)	_mpic_ipi_write(mpic,(i),(v))
+#define mpic_cpu_read(i)	_mpic_cpu_read(mpic,(i))
+#define mpic_cpu_write(i,v)	_mpic_cpu_write(mpic,(i),(v))
+#define mpic_irq_read(s,r)	_mpic_irq_read(mpic,(s),(r))
+#define mpic_irq_write(s,r,v)	_mpic_irq_write(mpic,(s),(r),(v))
+
+
+/*
+ * Low level utility functions
+ */
+
+
+
+/* Check if we have one of those nice broken MPICs with a flipped endian on
+ * reads from IPI registers
+ */
+static void __init mpic_test_broken_ipi(struct mpic *mpic)
+{
+	u32 r;
+
+	mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
+	r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+
+	if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
+		printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
+		mpic->flags |= MPIC_BROKEN_IPI;
+	}
+}
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+
+/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
+ * to force the edge setting on the MPIC and do the ack workaround.
+ */
+static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no)
+{
+	if (source_no >= 128 || !mpic->fixups)
+		return 0;
+	return mpic->fixups[source_no].base != NULL;
+}
+
+static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
+{
+	struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
+	u32 tmp;
+
+	spin_lock(&mpic->fixup_lock);
+	writeb(0x11 + 2 * fixup->irq, fixup->base);
+	tmp = readl(fixup->base + 2);
+	writel(tmp | 0x80000000ul, fixup->base + 2);
+	/* config writes shouldn't be posted but let's be safe ... */
+	(void)readl(fixup->base + 2);
+	spin_unlock(&mpic->fixup_lock);
+}
+
+
+static void __init mpic_amd8111_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+{
+	int i, irq;
+	u32 tmp;
+
+	printk(KERN_INFO "mpic:    - Workarounds on AMD 8111 @ %p\n", devbase);
+
+	for (i=0; i < 24; i++) {
+		writeb(0x10 + 2*i, devbase + 0xf2);
+		tmp = readl(devbase + 0xf4);
+		if ((tmp & 0x1) || !(tmp & 0x20))
+			continue;
+		irq = (tmp >> 16) & 0xff;
+		mpic->fixups[irq].irq = i;
+		mpic->fixups[irq].base = devbase + 0xf2;
+	}
+}
+ 
+static void __init mpic_amd8131_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+{
+	int i, irq;
+	u32 tmp;
+
+	printk(KERN_INFO "mpic:    - Workarounds on AMD 8131 @ %p\n", devbase);
+
+	for (i=0; i < 4; i++) {
+		writeb(0x10 + 2*i, devbase + 0xba);
+		tmp = readl(devbase + 0xbc);
+		if ((tmp & 0x1) || !(tmp & 0x20))
+			continue;
+		irq = (tmp >> 16) & 0xff;
+		mpic->fixups[irq].irq = i;
+		mpic->fixups[irq].base = devbase + 0xba;
+	}
+}
+ 
+static void __init mpic_scan_ioapics(struct mpic *mpic)
+{
+	unsigned int devfn;
+	u8 __iomem *cfgspace;
+
+	printk(KERN_INFO "mpic: Setting up IO-APICs workarounds for U3\n");
+
+	/* Allocate fixups array */
+	mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
+	BUG_ON(mpic->fixups == NULL);
+	memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
+
+	/* Init spinlock */
+	spin_lock_init(&mpic->fixup_lock);
+
+	/* Map u3 config space. We assume all IO-APICs are on the primary bus
+	 * and slot will never be above "0xf" so we only need to map 32k
+	 */
+	cfgspace = (unsigned char __iomem *)ioremap(0xf2000000, 0x8000);
+	BUG_ON(cfgspace == NULL);
+
+	/* Now we scan all slots. We do a very quick scan, we read the header type,
+	 * vendor ID and device ID only, that's plenty enough
+	 */
+	for (devfn = 0; devfn < PCI_DEVFN(0x10,0); devfn ++) {
+		u8 __iomem *devbase = cfgspace + (devfn << 8);
+		u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
+		u32 l = readl(devbase + PCI_VENDOR_ID);
+		u16 vendor_id, device_id;
+		int multifunc = 0;
+
+		DBG("devfn %x, l: %x\n", devfn, l);
+
+		/* If no device, skip */
+		if (l == 0xffffffff || l == 0x00000000 ||
+		    l == 0x0000ffff || l == 0xffff0000)
+			goto next;
+
+		/* Check if it's a multifunction device (only really used
+		 * to function 0 though
+		 */
+		multifunc = !!(hdr_type & 0x80);
+		vendor_id = l & 0xffff;
+		device_id = (l >> 16) & 0xffff;
+
+		/* If a known device, go to fixup setup code */
+		if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7460)
+			mpic_amd8111_read_irq(mpic, devbase);
+		if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7450)
+			mpic_amd8131_read_irq(mpic, devbase);
+	next:
+		/* next device, if function 0 */
+		if ((PCI_FUNC(devfn) == 0) && !multifunc)
+			devfn += 7;
+	}
+}
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+
+/* Find an mpic associated with a given linux interrupt */
+static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
+{
+	struct mpic *mpic = mpics;
+
+	while(mpic) {
+		/* search IPIs first since they may override the main interrupts */
+		if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) {
+			if (is_ipi)
+				*is_ipi = 1;
+			return mpic;
+		}
+		if (irq >= mpic->irq_offset &&
+		    irq < (mpic->irq_offset + mpic->irq_count)) {
+			if (is_ipi)
+				*is_ipi = 0;
+			return mpic;
+		}
+		mpic = mpic -> next;
+	}
+	return NULL;
+}
+
+/* Convert a cpu mask from logical to physical cpu numbers. */
+static inline u32 mpic_physmask(u32 cpumask)
+{
+	int i;
+	u32 mask = 0;
+
+	for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
+		mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
+	return mask;
+}
+
+#ifdef CONFIG_SMP
+/* Get the mpic structure from the IPI number */
+static inline struct mpic * mpic_from_ipi(unsigned int ipi)
+{
+	return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi);
+}
+#endif
+
+/* Get the mpic structure from the irq number */
+static inline struct mpic * mpic_from_irq(unsigned int irq)
+{
+	return container_of(irq_desc[irq].handler, struct mpic, hc_irq);
+}
+
+/* Send an EOI */
+static inline void mpic_eoi(struct mpic *mpic)
+{
+	mpic_cpu_write(MPIC_CPU_EOI, 0);
+	(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+}
+
+#ifdef CONFIG_SMP
+static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct mpic *mpic = dev_id;
+
+	smp_message_recv(irq - mpic->ipi_offset, regs);
+	return IRQ_HANDLED;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+
+static void mpic_enable_irq(unsigned int irq)
+{
+	unsigned int loops = 100000;
+	struct mpic *mpic = mpic_from_irq(irq);
+	unsigned int src = irq - mpic->irq_offset;
+
+	DBG("%s: enable_irq: %d (src %d)\n", mpic->name, irq, src);
+
+	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & ~MPIC_VECPRI_MASK);
+
+	/* make sure mask gets to controller before we return to user */
+	do {
+		if (!loops--) {
+			printk(KERN_ERR "mpic_enable_irq timeout\n");
+			break;
+		}
+	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	
+}
+
+static void mpic_disable_irq(unsigned int irq)
+{
+	unsigned int loops = 100000;
+	struct mpic *mpic = mpic_from_irq(irq);
+	unsigned int src = irq - mpic->irq_offset;
+
+	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
+
+	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | MPIC_VECPRI_MASK);
+
+	/* make sure mask gets to controller before we return to user */
+	do {
+		if (!loops--) {
+			printk(KERN_ERR "mpic_enable_irq timeout\n");
+			break;
+		}
+	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+}
+
+static void mpic_end_irq(unsigned int irq)
+{
+	struct mpic *mpic = mpic_from_irq(irq);
+
+	DBG("%s: end_irq: %d\n", mpic->name, irq);
+
+	/* We always EOI on end_irq() even for edge interrupts since that
+	 * should only lower the priority, the MPIC should have properly
+	 * latched another edge interrupt coming in anyway
+	 */
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	if (mpic->flags & MPIC_BROKEN_U3) {
+		unsigned int src = irq - mpic->irq_offset;
+		if (mpic_is_ht_interrupt(mpic, src))
+			mpic_apic_end_irq(mpic, src);
+	}
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+	mpic_eoi(mpic);
+}
+
+#ifdef CONFIG_SMP
+
+static void mpic_enable_ipi(unsigned int irq)
+{
+	struct mpic *mpic = mpic_from_ipi(irq);
+	unsigned int src = irq - mpic->ipi_offset;
+
+	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
+	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
+}
+
+static void mpic_disable_ipi(unsigned int irq)
+{
+	/* NEVER disable an IPI... that's just plain wrong! */
+}
+
+static void mpic_end_ipi(unsigned int irq)
+{
+	struct mpic *mpic = mpic_from_ipi(irq);
+
+	/*
+	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
+	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
+	 * applying to them. We EOI them late to avoid re-entering.
+	 * We mark IPI's with SA_INTERRUPT as they must run with
+	 * irqs disabled.
+	 */
+	mpic_eoi(mpic);
+}
+
+#endif /* CONFIG_SMP */
+
+static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+	struct mpic *mpic = mpic_from_irq(irq);
+
+	cpumask_t tmp;
+
+	cpus_and(tmp, cpumask, cpu_online_map);
+
+	mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
+		       mpic_physmask(cpus_addr(tmp)[0]));	
+}
+
+
+/*
+ * Exported functions
+ */
+
+
+struct mpic * __init mpic_alloc(unsigned long phys_addr,
+				unsigned int flags,
+				unsigned int isu_size,
+				unsigned int irq_offset,
+				unsigned int irq_count,
+				unsigned int ipi_offset,
+				unsigned char *senses,
+				unsigned int senses_count,
+				const char *name)
+{
+	struct mpic	*mpic;
+	u32		reg;
+	const char	*vers;
+	int		i;
+
+	mpic = (struct mpic *)alloc_bootmem(sizeof(struct mpic));
+	if (mpic == NULL)
+		return NULL;
+	
+	memset(mpic, 0, sizeof(struct mpic));
+	mpic->name = name;
+
+	mpic->hc_irq.typename = name;
+	mpic->hc_irq.enable = mpic_enable_irq;
+	mpic->hc_irq.disable = mpic_disable_irq;
+	mpic->hc_irq.end = mpic_end_irq;
+	if (flags & MPIC_PRIMARY)
+		mpic->hc_irq.set_affinity = mpic_set_affinity;
+#ifdef CONFIG_SMP
+	mpic->hc_ipi.typename = name;
+	mpic->hc_ipi.enable = mpic_enable_ipi;
+	mpic->hc_ipi.disable = mpic_disable_ipi;
+	mpic->hc_ipi.end = mpic_end_ipi;
+#endif /* CONFIG_SMP */
+
+	mpic->flags = flags;
+	mpic->isu_size = isu_size;
+	mpic->irq_offset = irq_offset;
+	mpic->irq_count = irq_count;
+	mpic->ipi_offset = ipi_offset;
+	mpic->num_sources = 0; /* so far */
+	mpic->senses = senses;
+	mpic->senses_count = senses_count;
+
+	/* Map the global registers */
+	mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
+	mpic->tmregs = mpic->gregs + (MPIC_TIMER_BASE >> 2);
+	BUG_ON(mpic->gregs == NULL);
+
+	/* Reset */
+	if (flags & MPIC_WANTS_RESET) {
+		mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+			   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+			   | MPIC_GREG_GCONF_RESET);
+		while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		       & MPIC_GREG_GCONF_RESET)
+			mb();
+	}
+
+	/* Read feature register, calculate num CPUs and, for non-ISU
+	 * MPICs, num sources as well. On ISU MPICs, sources are counted
+	 * as ISUs are added
+	 */
+	reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+	mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
+	if (isu_size == 0)
+		mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+				     >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+
+	/* Map the per-CPU registers */
+	for (i = 0; i < mpic->num_cpus; i++) {
+		mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
+					   i * MPIC_CPU_STRIDE, 0x1000);
+		BUG_ON(mpic->cpuregs[i] == NULL);
+	}
+
+	/* Initialize main ISU if none provided */
+	if (mpic->isu_size == 0) {
+		mpic->isu_size = mpic->num_sources;
+		mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
+					MPIC_IRQ_STRIDE * mpic->isu_size);
+		BUG_ON(mpic->isus[0] == NULL);
+	}
+	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
+	mpic->isu_mask = (1 << mpic->isu_shift) - 1;
+
+	/* Display version */
+	switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
+	case 1:
+		vers = "1.0";
+		break;
+	case 2:
+		vers = "1.2";
+		break;
+	case 3:
+		vers = "1.3";
+		break;
+	default:
+		vers = "<unknown>";
+		break;
+	}
+	printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n",
+	       name, vers, phys_addr, mpic->num_cpus);
+	printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size,
+	       mpic->isu_shift, mpic->isu_mask);
+
+	mpic->next = mpics;
+	mpics = mpic;
+
+	if (flags & MPIC_PRIMARY)
+		mpic_primary = mpic;
+
+	return mpic;
+}
+
+void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+			    unsigned long phys_addr)
+{
+	unsigned int isu_first = isu_num * mpic->isu_size;
+
+	BUG_ON(isu_num >= MPIC_MAX_ISU);
+
+	mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
+	if ((isu_first + mpic->isu_size) > mpic->num_sources)
+		mpic->num_sources = isu_first + mpic->isu_size;
+}
+
+void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
+			       void *data)
+{
+	struct mpic *mpic = mpic_find(irq, NULL);
+	unsigned long flags;
+
+	/* Synchronization here is a bit dodgy, so don't try to replace cascade
+	 * interrupts on the fly too often ... but normally it's set up at boot.
+	 */
+	spin_lock_irqsave(&mpic_lock, flags);
+	if (mpic->cascade)	       
+		mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
+	mpic->cascade = NULL;
+	wmb();
+	mpic->cascade_vec = irq - mpic->irq_offset;
+	mpic->cascade_data = data;
+	wmb();
+	mpic->cascade = handler;
+	mpic_enable_irq(irq);
+	spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+void __init mpic_init(struct mpic *mpic)
+{
+	int i;
+
+	BUG_ON(mpic->num_sources == 0);
+
+	printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
+
+	/* Set current processor priority to max */
+	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+	/* Initialize timers: just disable them all */
+	for (i = 0; i < 4; i++) {
+		mpic_write(mpic->tmregs,
+			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+		mpic_write(mpic->tmregs,
+			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+			   MPIC_VECPRI_MASK |
+			   (MPIC_VEC_TIMER_0 + i));
+	}
+
+	/* Initialize IPIs to our reserved vectors and mark them disabled for now */
+	mpic_test_broken_ipi(mpic);
+	for (i = 0; i < 4; i++) {
+		mpic_ipi_write(i,
+			       MPIC_VECPRI_MASK |
+			       (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
+			       (MPIC_VEC_IPI_0 + i));
+#ifdef CONFIG_SMP
+		if (!(mpic->flags & MPIC_PRIMARY))
+			continue;
+		irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
+		irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi;
+		
+#endif /* CONFIG_SMP */
+	}
+
+	/* Initialize interrupt sources */
+	if (mpic->irq_count == 0)
+		mpic->irq_count = mpic->num_sources;
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	/* Do the ioapic fixups on U3 broken mpic */
+	DBG("MPIC flags: %x\n", mpic->flags);
+	if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
+		mpic_scan_ioapics(mpic);
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+	for (i = 0; i < mpic->num_sources; i++) {
+		/* start with vector = source number, and masked */
+		u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
+		int level = 0;
+		
+		/* if it's an IPI, we skip it */
+		if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
+		    (mpic->irq_offset + i) <  (mpic->ipi_offset + i + 4))
+			continue;
+
+		/* do senses munging */
+		if (mpic->senses && i < mpic->senses_count) {
+			if (mpic->senses[i] & IRQ_SENSE_LEVEL)
+				vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+			if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
+				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+		} else
+			vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+
+		/* remember if it was a level interrupts */
+		level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
+
+		/* deal with broken U3 */
+		if (mpic->flags & MPIC_BROKEN_U3) {
+#ifdef CONFIG_MPIC_BROKEN_U3
+			if (mpic_is_ht_interrupt(mpic, i)) {
+				vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
+					    MPIC_VECPRI_POLARITY_MASK);
+				vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+			}
+#else
+			printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n");
+#endif
+		}
+
+		DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
+		    (level != 0));
+
+		/* init hw */
+		mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
+		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+			       1 << get_hard_smp_processor_id(boot_cpuid));
+
+		/* init linux descriptors */
+		if (i < mpic->irq_count) {
+			irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL : 0;
+			irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq;
+		}
+	}
+	
+	/* Init spurrious vector */
+	mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+
+	/* Disable 8259 passthrough */
+	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+		   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+
+	/* Set current processor priority to 0 */
+	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+}
+
+
+
+void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+{
+	int is_ipi;
+	struct mpic *mpic = mpic_find(irq, &is_ipi);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&mpic_lock, flags);
+	if (is_ipi) {
+		reg = mpic_ipi_read(irq - mpic->ipi_offset) & MPIC_VECPRI_PRIORITY_MASK;
+		mpic_ipi_write(irq - mpic->ipi_offset,
+			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+	} else {
+		reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI)
+			& MPIC_VECPRI_PRIORITY_MASK;
+		mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
+			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+	}
+	spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+unsigned int mpic_irq_get_priority(unsigned int irq)
+{
+	int is_ipi;
+	struct mpic *mpic = mpic_find(irq, &is_ipi);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&mpic_lock, flags);
+	if (is_ipi)
+		reg = mpic_ipi_read(irq - mpic->ipi_offset);
+	else
+		reg = mpic_irq_read(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI);
+	spin_unlock_irqrestore(&mpic_lock, flags);
+	return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
+}
+
+void mpic_setup_this_cpu(void)
+{
+#ifdef CONFIG_SMP
+	struct mpic *mpic = mpic_primary;
+	unsigned long flags;
+#ifdef CONFIG_IRQ_ALL_CPUS
+	u32 msk = 1 << hard_smp_processor_id();
+	unsigned int i;
+#endif
+
+	BUG_ON(mpic == NULL);
+
+	DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+
+	spin_lock_irqsave(&mpic_lock, flags);
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+ 	/* let the mpic know we want intrs. default affinity is 0xffffffff
+	 * until changed via /proc. That's how it's done on x86. If we want
+	 * it differently, then we should make sure we also change the default
+	 * values of irq_affinity in irq.c.
+ 	 */
+ 	for (i = 0; i < mpic->num_sources ; i++)
+		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+			mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+#endif /* CONFIG_IRQ_ALL_CPUS */
+
+	/* Set current processor priority to 0 */
+	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+
+	spin_unlock_irqrestore(&mpic_lock, flags);
+#endif /* CONFIG_SMP */
+}
+
+void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
+{
+	struct mpic *mpic = mpic_primary;
+
+	BUG_ON(mpic == NULL);
+
+	DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
+
+	mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
+}
+
+int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
+{
+	u32 irq;
+
+	irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+	DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
+
+	if (mpic->cascade && irq == mpic->cascade_vec) {
+		DBG("%s: cascading ...\n", mpic->name);
+		irq = mpic->cascade(regs, mpic->cascade_data);
+		mpic_eoi(mpic);
+		return irq;
+	}
+	if (unlikely(irq == MPIC_VEC_SPURRIOUS))
+		return -1;
+	if (irq < MPIC_VEC_IPI_0) 
+		return irq + mpic->irq_offset;
+       	DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
+	return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
+}
+
+int mpic_get_irq(struct pt_regs *regs)
+{
+	struct mpic *mpic = mpic_primary;
+
+	BUG_ON(mpic == NULL);
+
+	return mpic_get_one_irq(mpic, regs);
+}
+
+
+#ifdef CONFIG_SMP
+void mpic_request_ipis(void)
+{
+	struct mpic *mpic = mpic_primary;
+
+	BUG_ON(mpic == NULL);
+	
+	printk("requesting IPIs ... \n");
+
+	/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+	request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
+		    "IPI0 (call function)", mpic);
+	request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
+		   "IPI1 (reschedule)", mpic);
+	request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
+		   "IPI2 (unused)", mpic);
+	request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
+		   "IPI3 (debugger break)", mpic);
+
+	printk("IPIs requested... \n");
+}
+#endif /* CONFIG_SMP */
diff -Nru a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/mpic.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,267 @@
+#include <linux/irq.h>
+
+/*
+ * Global registers
+ */
+
+#define MPIC_GREG_BASE			0x01000
+
+#define MPIC_GREG_FEATURE_0		0x00000
+#define		MPIC_GREG_FEATURE_LAST_SRC_MASK		0x07ff0000
+#define		MPIC_GREG_FEATURE_LAST_SRC_SHIFT	16
+#define		MPIC_GREG_FEATURE_LAST_CPU_MASK		0x00001f00
+#define		MPIC_GREG_FEATURE_LAST_CPU_SHIFT	8
+#define		MPIC_GREG_FEATURE_VERSION_MASK		0xff
+#define MPIC_GREG_FEATURE_1		0x00010
+#define MPIC_GREG_GLOBAL_CONF_0		0x00020
+#define		MPIC_GREG_GCONF_RESET			0x80000000
+#define		MPIC_GREG_GCONF_8259_PTHROU_DIS		0x20000000
+#define		MPIC_GREG_GCONF_BASE_MASK		0x000fffff
+#define MPIC_GREG_GLOBAL_CONF_1		0x00030
+#define MPIC_GREG_VENDOR_0		0x00040
+#define MPIC_GREG_VENDOR_1		0x00050
+#define MPIC_GREG_VENDOR_2		0x00060
+#define MPIC_GREG_VENDOR_3		0x00070
+#define MPIC_GREG_VENDOR_ID		0x00080
+#define 	MPIC_GREG_VENDOR_ID_STEPPING_MASK	0x00ff0000
+#define 	MPIC_GREG_VENDOR_ID_STEPPING_SHIFT	16
+#define 	MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK	0x0000ff00
+#define 	MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT	8
+#define 	MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK	0x000000ff
+#define MPIC_GREG_PROCESSOR_INIT	0x00090
+#define MPIC_GREG_IPI_VECTOR_PRI_0	0x000a0
+#define MPIC_GREG_IPI_VECTOR_PRI_1	0x000b0
+#define MPIC_GREG_IPI_VECTOR_PRI_2	0x000c0
+#define MPIC_GREG_IPI_VECTOR_PRI_3	0x000d0
+#define MPIC_GREG_SPURIOUS		0x000e0
+#define MPIC_GREG_TIMER_FREQ		0x000f0
+
+/*
+ *
+ * Timer registers
+ */
+#define MPIC_TIMER_BASE			0x01100
+#define MPIC_TIMER_STRIDE		0x40
+
+#define MPIC_TIMER_CURRENT_CNT		0x00000
+#define MPIC_TIMER_BASE_CNT		0x00010
+#define MPIC_TIMER_VECTOR_PRI		0x00020
+#define MPIC_TIMER_DESTINATION		0x00030
+
+/*
+ * Per-Processor registers
+ */
+
+#define MPIC_CPU_THISBASE		0x00000
+#define MPIC_CPU_BASE			0x20000
+#define MPIC_CPU_STRIDE			0x01000
+
+#define MPIC_CPU_IPI_DISPATCH_0		0x00040
+#define MPIC_CPU_IPI_DISPATCH_1		0x00050
+#define MPIC_CPU_IPI_DISPATCH_2		0x00060
+#define MPIC_CPU_IPI_DISPATCH_3		0x00070
+#define MPIC_CPU_CURRENT_TASK_PRI	0x00080
+#define 	MPIC_CPU_TASKPRI_MASK			0x0000000f
+#define MPIC_CPU_WHOAMI			0x00090
+#define 	MPIC_CPU_WHOAMI_MASK			0x0000001f
+#define MPIC_CPU_INTACK			0x000a0
+#define MPIC_CPU_EOI			0x000b0
+
+/*
+ * Per-source registers
+ */
+
+#define MPIC_IRQ_BASE			0x10000
+#define MPIC_IRQ_STRIDE			0x00020
+#define MPIC_IRQ_VECTOR_PRI		0x00000
+#define 	MPIC_VECPRI_MASK			0x80000000
+#define 	MPIC_VECPRI_ACTIVITY			0x40000000	/* Read Only */
+#define 	MPIC_VECPRI_PRIORITY_MASK		0x000f0000
+#define 	MPIC_VECPRI_PRIORITY_SHIFT		16
+#define 	MPIC_VECPRI_VECTOR_MASK			0x000007ff
+#define 	MPIC_VECPRI_POLARITY_POSITIVE		0x00800000
+#define 	MPIC_VECPRI_POLARITY_NEGATIVE		0x00000000
+#define 	MPIC_VECPRI_POLARITY_MASK		0x00800000
+#define 	MPIC_VECPRI_SENSE_LEVEL			0x00400000
+#define 	MPIC_VECPRI_SENSE_EDGE			0x00000000
+#define 	MPIC_VECPRI_SENSE_MASK			0x00400000
+#define MPIC_IRQ_DESTINATION		0x00010
+
+#define MPIC_MAX_IRQ_SOURCES	2048
+#define MPIC_MAX_CPUS		32
+#define MPIC_MAX_ISU		32
+
+/*
+ * Special vector numbers (internal use only)
+ */
+#define MPIC_VEC_SPURRIOUS	255
+#define MPIC_VEC_IPI_3		254
+#define MPIC_VEC_IPI_2		253
+#define MPIC_VEC_IPI_1		252
+#define MPIC_VEC_IPI_0		251
+
+/* unused */
+#define MPIC_VEC_TIMER_3	250
+#define MPIC_VEC_TIMER_2	249
+#define MPIC_VEC_TIMER_1	248
+#define MPIC_VEC_TIMER_0	247
+
+/* Type definition of the cascade handler */
+typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+/* Fixup table entry */
+struct mpic_irq_fixup
+{
+	u8 __iomem	*base;
+	unsigned int   irq;
+};
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+
+/* The instance data of a given MPIC */
+struct mpic
+{
+	/* The "linux" controller struct */
+	hw_irq_controller	hc_irq;
+#ifdef CONFIG_SMP
+	hw_irq_controller	hc_ipi;
+#endif
+	const char		*name;
+	/* Flags */
+	unsigned int		flags;
+	/* How many irq sources in a given ISU */
+	unsigned int		isu_size;
+	unsigned int		isu_shift;
+	unsigned int		isu_mask;
+	/* Offset of irq vector numbers */
+	unsigned int		irq_offset;	
+	unsigned int		irq_count;
+	/* Offset of ipi vector numbers */
+	unsigned int		ipi_offset;
+	/* Number of sources */
+	unsigned int		num_sources;
+	/* Number of CPUs */
+	unsigned int		num_cpus;
+	/* cascade handler */
+	mpic_cascade_t		cascade;
+	void			*cascade_data;
+	unsigned int		cascade_vec;
+	/* senses array */
+	unsigned char		*senses;
+	unsigned int		senses_count;
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	/* The fixup table */
+	struct mpic_irq_fixup	*fixups;
+	spinlock_t		fixup_lock;
+#endif
+
+	/* The various ioremap'ed bases */
+	volatile u32 __iomem	*gregs;
+	volatile u32 __iomem	*tmregs;
+	volatile u32 __iomem	*cpuregs[MPIC_MAX_CPUS];
+	volatile u32 __iomem	*isus[MPIC_MAX_ISU];
+
+	/* link */
+	struct mpic		*next;
+};
+
+/* This is the primary controller, only that one has IPIs and
+ * has afinity control. A non-primary MPIC always uses CPU0
+ * registers only
+ */
+#define MPIC_PRIMARY			0x00000001
+/* Set this for a big-endian MPIC */
+#define MPIC_BIG_ENDIAN			0x00000002
+/* Broken U3 MPIC */
+#define MPIC_BROKEN_U3			0x00000004
+/* Broken IPI registers (autodetected) */
+#define MPIC_BROKEN_IPI			0x00000008
+/* MPIC wants a reset */
+#define MPIC_WANTS_RESET		0x00000010
+
+/* Allocate the controller structure and setup the linux irq descs
+ * for the range if interrupts passed in. No HW initialization is
+ * actually performed.
+ * 
+ * @phys_addr:	physial base address of the MPIC
+ * @flags:	flags, see constants above
+ * @isu_size:	number of interrupts in an ISU. Use 0 to use a
+ *              standard ISU-less setup (aka powermac)
+ * @irq_offset: first irq number to assign to this mpic
+ * @irq_count:  number of irqs to use with this mpic IRQ sources. Pass 0
+ *	        to match the number of sources
+ * @ipi_offset: first irq number to assign to this mpic IPI sources,
+ *		used only on primary mpic
+ * @senses:	array of sense values
+ * @senses_num: number of entries in the array
+ *
+ * Note about the sense array. If none is passed, all interrupts are
+ * setup to be level negative unless MPIC_BROKEN_U3 is set in which
+ * case they are edge positive (and the array is ignored anyway).
+ * The values in the array start at the first source of the MPIC,
+ * that is senses[0] correspond to linux irq "irq_offset".
+ */
+extern struct mpic *mpic_alloc(unsigned long phys_addr,
+			       unsigned int flags,
+			       unsigned int isu_size,
+			       unsigned int irq_offset,
+			       unsigned int irq_count,
+			       unsigned int ipi_offset,
+			       unsigned char *senses,
+			       unsigned int senses_num,
+			       const char *name);
+
+/* Assign ISUs, to call before mpic_init()
+ *
+ * @mpic:	controller structure as returned by mpic_alloc()
+ * @isu_num:	ISU number
+ * @phys_addr:	physical address of the ISU
+ */
+extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+			    unsigned long phys_addr);
+
+/* Initialize the controller. After this has been called, none of the above
+ * should be called again for this mpic
+ */
+extern void mpic_init(struct mpic *mpic);
+
+/* Setup a cascade. Currently, only one cascade is supported this
+ * way, though you can always do a normal request_irq() and add
+ * other cascades this way. You should call this _after_ having
+ * added all the ISUs
+ *
+ * @irq_no:	"linux" irq number of the cascade (that is offset'ed vector)
+ * @handler:	cascade handler function
+ */
+extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
+			       void *data);
+
+/*
+ * All of the following functions must only be used after the
+ * ISUs have been assigned and the controller fully initialized
+ * with mpic_init()
+ */
+
+
+/* Change/Read the priority of an interrupt. Default is 8 for irqs and
+ * 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the
+ * IPI number is then the offset'ed (linux irq number mapped to the IPI)
+ */
+extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri);
+extern unsigned int mpic_irq_get_priority(unsigned int irq);
+
+/* Setup a non-boot CPU */
+extern void mpic_setup_this_cpu(void);
+
+/* Request IPIs on primary mpic */
+extern void mpic_request_ipis(void);
+
+/* Send an IPI (non offseted number 0..3) */
+extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
+
+/* Fetch interrupt from a given mpic */
+extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
+/* This one gets to the primary mpic */
+extern int mpic_get_irq(struct pt_regs *regs);
diff -Nru a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
--- a/arch/ppc64/kernel/nvram.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc64/kernel/nvram.c	2004-10-28 22:25:56 -07:00
@@ -77,7 +77,7 @@
 }
 
 
-static ssize_t dev_nvram_read(struct file *file, char *buf,
+static ssize_t dev_nvram_read(struct file *file, char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	ssize_t len;
@@ -117,7 +117,7 @@
 
 }
 
-static ssize_t dev_nvram_write(struct file *file, const char *buf,
+static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
 			   size_t count, loff_t *ppos)
 {
 	ssize_t len;
@@ -711,7 +711,7 @@
 /* This doesn't actually zero anything, but it sets the event_logged
  * word to tell that this event is safely in syslog.
  */
-int nvram_clear_error_log()
+int nvram_clear_error_log(void)
 {
 	loff_t tmp_index;
 	int clear_word = ERR_FLAG_ALREADY_LOGGED;
diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c
--- a/arch/ppc64/kernel/open_pic.c	2004-10-28 22:25:58 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,886 +0,0 @@
-/*
- *  arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  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/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-
-#include <asm/machdep.h>
-
-#include "open_pic.h"
-#include "open_pic_defs.h"
-#include "i8259.h"
-#include <asm/ppcdebug.h>
-
-void* OpenPIC_Addr;
-static volatile struct OpenPIC *OpenPIC = NULL;
-u_int OpenPIC_NumInitSenses __initdata = 0;
-u_char *OpenPIC_InitSenses __initdata = NULL;
-
-/*
- *  Local (static) OpenPIC Operations
- */
-
-
-/* Global Operations */
-static void openpic_reset(void);
-static void openpic_enable_8259_pass_through(void);
-static void openpic_disable_8259_pass_through(void);
-static u_int openpic_irq(void);
-static void openpic_eoi(void);
-static u_int openpic_get_priority(void);
-static void openpic_set_priority(u_int pri);
-static u_int openpic_get_spurious(void);
-static void openpic_set_spurious(u_int vector);
-
-#ifdef CONFIG_SMP
-/* Interprocessor Interrupts */
-static void openpic_initipi(u_int ipi, u_int pri, u_int vector);
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
-					struct pt_regs *regs);
-#endif
-
-/* Timer Interrupts */
-static void openpic_inittimer(u_int timer, u_int pri, u_int vector);
-static void openpic_maptimer(u_int timer, u_int cpumask);
-
-/* Interrupt Sources */
-static void openpic_enable_irq(u_int irq);
-static void openpic_disable_irq(u_int irq);
-static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity,
-			    int is_level);
-static void openpic_mapirq(u_int irq, u_int cpumask);
-
-static void find_ISUs(void);
-
-static u_int NumProcessors;
-static u_int NumSources;
-static int NumISUs;
-static int open_pic_irq_offset;
-static volatile unsigned char* chrp_int_ack_special;
-
-OpenPIC_SourcePtr ISU[OPENPIC_MAX_ISU];
-
-static void openpic_end_irq(unsigned int irq_nr);
-static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask);
-
-struct hw_interrupt_type open_pic = {
-	" OpenPIC  ",
-	NULL,
-	NULL,
-	openpic_enable_irq,
-	openpic_disable_irq,
-	NULL,
-	openpic_end_irq,
-	openpic_set_affinity
-};
-
-#ifdef CONFIG_SMP
-static void openpic_end_ipi(unsigned int irq_nr);
-static void openpic_enable_ipi(unsigned int irq_nr);
-static void openpic_disable_ipi(unsigned int irq_nr);
-
-struct hw_interrupt_type open_pic_ipi = {
-	" OpenPIC  ",
-	NULL,
-	NULL,
-	openpic_enable_ipi,
-	openpic_disable_ipi,
-	NULL,
-	openpic_end_ipi,
-	NULL
-};
-#endif /* CONFIG_SMP */
-
-unsigned int openpic_vec_ipi;
-unsigned int openpic_vec_timer;
-unsigned int openpic_vec_spurious;
-
-/*
- *  Accesses to the current processor's openpic registers
- */
-#ifdef CONFIG_SMP
-#define THIS_CPU		Processor[cpu]
-#define DECL_THIS_CPU		int cpu = hard_smp_processor_id()
-#define CHECK_THIS_CPU		check_arg_cpu(cpu)
-#else
-#define THIS_CPU		Processor[hard_smp_processor_id()]
-#define DECL_THIS_CPU
-#define CHECK_THIS_CPU
-#endif /* CONFIG_SMP */
-
-#if 0
-#define check_arg_ipi(ipi) \
-    if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
-	printk(KERN_ERR "open_pic.c:%d: invalid ipi %d\n", __LINE__, ipi);
-#define check_arg_timer(timer) \
-    if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
-	printk(KERN_ERR "open_pic.c:%d: invalid timer %d\n", __LINE__, timer);
-#define check_arg_vec(vec) \
-    if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
-	printk(KERN_ERR "open_pic.c:%d: invalid vector %d\n", __LINE__, vec);
-#define check_arg_pri(pri) \
-    if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
-	printk(KERN_ERR "open_pic.c:%d: invalid priority %d\n", __LINE__, pri);
-/*
- * Print out a backtrace if it's out of range, since if it's larger than NR_IRQ's
- * data has probably been corrupted and we're going to panic or deadlock later
- * anyway --Troy
- */
-#define check_arg_irq(irq) \
-    if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \
-      printk(KERN_ERR "open_pic.c:%d: invalid irq %d\n", __LINE__, irq); \
-      dump_stack(); }
-#define check_arg_cpu(cpu) \
-    if (cpu < 0 || cpu >= OPENPIC_MAX_PROCESSORS){ \
-	printk(KERN_ERR "open_pic.c:%d: invalid cpu %d\n", __LINE__, cpu); \
-	dump_stack(); }
-#else
-#define check_arg_ipi(ipi)	do {} while (0)
-#define check_arg_timer(timer)	do {} while (0)
-#define check_arg_vec(vec)	do {} while (0)
-#define check_arg_pri(pri)	do {} while (0)
-#define check_arg_irq(irq)	do {} while (0)
-#define check_arg_cpu(cpu)	do {} while (0)
-#endif
-
-#define GET_ISU(source)	ISU[(source) >> 4][(source) & 0xf]
-
-void __init pSeries_init_openpic(void)
-{
-        struct device_node *np;
-        int i;
-        unsigned int *addrp;
-        unsigned char* chrp_int_ack_special = NULL;
-        unsigned char init_senses[NR_IRQS - NUM_ISA_INTERRUPTS];
-        int nmi_irq = -1;
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
-        struct device_node *kbd;
-#endif
-
-        if (!(np = of_find_node_by_name(NULL, "pci"))
-            || !(addrp = (unsigned int *)
-                 get_property(np, "8259-interrupt-acknowledge", NULL)))
-                printk(KERN_ERR "Cannot find pci to get ack address\n");
-        else
-		chrp_int_ack_special = (unsigned char *)
-			__ioremap(addrp[prom_n_addr_cells(np)-1], 1, _PAGE_NO_CACHE);
-        /* hydra still sets OpenPIC_InitSenses to a static set of values */
-        if (OpenPIC_InitSenses == NULL) {
-                prom_get_irq_senses(init_senses, NUM_ISA_INTERRUPTS, NR_IRQS);
-                OpenPIC_InitSenses = init_senses;
-                OpenPIC_NumInitSenses = NR_IRQS - NUM_ISA_INTERRUPTS;
-        }
-        openpic_init(1, NUM_ISA_INTERRUPTS, chrp_int_ack_special, nmi_irq);
-        for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
-                irq_desc[i].handler = &i8259_pic;
-	of_node_put(np);
-}
-
-static inline u_int openpic_read(volatile u_int *addr)
-{
-	u_int val;
-
-	val = in_le32(addr);
-	return val;
-}
-
-static inline void openpic_write(volatile u_int *addr, u_int val)
-{
-	out_le32(addr, val);
-}
-
-static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
-{
-	u_int val = openpic_read(addr);
-	return val & mask;
-}
-
-static inline void openpic_writefield(volatile u_int *addr, u_int mask,
-			       u_int field)
-{
-	u_int val = openpic_read(addr);
-	openpic_write(addr, (val & ~mask) | (field & mask));
-}
-
-static inline void openpic_clearfield(volatile u_int *addr, u_int mask)
-{
-	openpic_writefield(addr, mask, 0);
-}
-
-static inline void openpic_setfield(volatile u_int *addr, u_int mask)
-{
-	openpic_writefield(addr, mask, mask);
-}
-
-static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
-				    u_int field)
-{
-	unsigned int loops = 100000;
-
-	openpic_setfield(addr, OPENPIC_MASK);
-	while (openpic_read(addr) & OPENPIC_ACTIVITY) {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_safe_writefield timeout\n");
-			break;
-		}
-	}
-	openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
-}
-
-#ifdef CONFIG_SMP
-
-static int broken_ipi_registers;
-
-static u_int openpic_read_IPI(volatile u_int* addr)
-{
-        u_int val = 0;
-
-	if (broken_ipi_registers)
-		/* yes this is right ... bug, feature, you decide! -- tgall */
-		val = in_be32(addr);
-	else
-		val = in_le32(addr);
-
-        return val;
-}
-
-static void openpic_test_broken_IPI(void)
-{
-	u_int t;
-
-	openpic_write(&OpenPIC->Global.IPI_Vector_Priority(0), OPENPIC_MASK);
-	t = openpic_read(&OpenPIC->Global.IPI_Vector_Priority(0));
-	if (t == le32_to_cpu(OPENPIC_MASK)) {
-		printk(KERN_INFO "OpenPIC reversed IPI registers detected\n");
-		broken_ipi_registers = 1;
-	}
-}
-
-/* because of the power3 be / le above, this is needed */
-static inline void openpic_writefield_IPI(volatile u_int* addr, u_int mask, u_int field)
-{
-        u_int  val = openpic_read_IPI(addr);
-        openpic_write(addr, (val & ~mask) | (field & mask));
-}
-
-static inline void openpic_clearfield_IPI(volatile u_int *addr, u_int mask)
-{
-        openpic_writefield_IPI(addr, mask, 0);
-}
-
-static inline void openpic_setfield_IPI(volatile u_int *addr, u_int mask)
-{
-        openpic_writefield_IPI(addr, mask, mask);
-}
-
-static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int field)
-{
-	unsigned int loops = 100000;
-
-        openpic_setfield_IPI(addr, OPENPIC_MASK);
-
-        /* wait until it's not in use */
-        /* BenH: Is this code really enough ? I would rather check the result
-         *       and eventually retry ...
-         */
-        while(openpic_read_IPI(addr) & OPENPIC_ACTIVITY) {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_safe_writefield timeout\n");
-			break;
-		}
-	}
-
-        openpic_writefield_IPI(addr, mask, field | OPENPIC_MASK);
-}
-#endif /* CONFIG_SMP */
-
-void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
-			 int programmer_switch_irq)
-{
-	u_int t, i;
-	u_int timerfreq;
-	const char *version;
-
-	if (!OpenPIC_Addr) {
-		printk(KERN_INFO "No OpenPIC found !\n");
-		return;
-	}
-	OpenPIC = (volatile struct OpenPIC *)OpenPIC_Addr;
-
-	ppc64_boot_msg(0x20, "OpenPic Init");
-
-	t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
-	switch (t & OPENPIC_FEATURE_VERSION_MASK) {
-	case 1:
-		version = "1.0";
-		break;
-	case 2:
-		version = "1.2";
-		break;
-	case 3:
-		version = "1.3";
-		break;
-	default:
-		version = "?";
-		break;
-	}
-	NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
-			 OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
-	NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
-		      OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
-	printk(KERN_INFO "OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n",
-	       version, NumProcessors, NumSources, OpenPIC);
-	timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
-	if (timerfreq)
-		printk(KERN_INFO "OpenPIC timer frequency is %d.%06d MHz\n",
-		       timerfreq / 1000000, timerfreq % 1000000);
-
-	if (!main_pic)
-		return;
-
-	open_pic_irq_offset = offset;
-	chrp_int_ack_special = (volatile unsigned char*)chrp_ack;
-
-	find_ISUs();
-
-	/* Initialize timer interrupts */
-	for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
-		/* Disabled, Priority 0 */
-		openpic_inittimer(i, 0, openpic_vec_timer+i);
-		/* No processor */
-		openpic_maptimer(i, 0);
-	}
-
-#ifdef CONFIG_SMP
-	/* Initialize IPI interrupts */
-	openpic_test_broken_IPI();
-	for (i = 0; i < OPENPIC_NUM_IPI; i++) {
-		/* Disabled, Priority 10..13 */
-		openpic_initipi(i, 10+i, openpic_vec_ipi+i);
-		/* IPIs are per-CPU */
-		irq_desc[openpic_vec_ipi+i].status |= IRQ_PER_CPU;
-		irq_desc[openpic_vec_ipi+i].handler = &open_pic_ipi;
-	}
-#endif
-
-	/* Initialize external interrupts */
-	openpic_set_priority(0xf);
-
-	/* SIOint (8259 cascade) is special */
-	if (offset) {
-		openpic_initirq(0, 8, offset, 1, 1);
-		openpic_mapirq(0, 1 << get_hard_smp_processor_id(boot_cpuid));
-	}
-
-	/* Init all external sources */
-	for (i = 0; i < NumSources; i++) {
-		int pri, sense;
-
-		/* skip cascade if any */
-		if (offset && i == 0)
-			continue;
-		/* the bootloader may have left it enabled (bad !) */
-		openpic_disable_irq(i+offset);
-
-		pri = (i == programmer_switch_irq)? 9: 8;
-		sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1;
-		if (sense)
-			irq_desc[i+offset].status = IRQ_LEVEL;
-
-		/* Enabled, Priority 8 or 9 */
-		openpic_initirq(i, pri, i+offset, !sense, sense);
-		/* Processor 0 */
-		openpic_mapirq(i, 1 << get_hard_smp_processor_id(boot_cpuid));
-	}
-
-	/* Init descriptors */
-	for (i = offset; i < NumSources + offset; i++)
-		irq_desc[i].handler = &open_pic;
-
-	/* Initialize the spurious interrupt */
-	openpic_set_spurious(openpic_vec_spurious);
-
-	openpic_set_priority(0);
-	openpic_disable_8259_pass_through();
-
-	ppc64_boot_msg(0x25, "OpenPic Done");
-}
-
-/* 
- * We cant do this in init_IRQ because we need the memory subsystem up for
- * request_irq()
- */
-static int __init openpic_setup_i8259(void)
-{
-	if (systemcfg->platform == PLATFORM_POWERMAC)
-		return 0;
-
-	if (naca->interrupt_controller == IC_OPEN_PIC) {
-		/* Initialize the cascade */
-		if (request_irq(NUM_ISA_INTERRUPTS, no_action, SA_INTERRUPT,
-				"82c59 cascade", NULL))
-			printk(KERN_ERR "Unable to get OpenPIC IRQ 0 for cascade\n");
-		i8259_init();
-	}
-
-	return 0;
-}
-arch_initcall(openpic_setup_i8259);
-
-void openpic_setup_ISU(int isu_num, unsigned long addr)
-{
-	if (isu_num >= OPENPIC_MAX_ISU)
-		return;
-	ISU[isu_num] = (OpenPIC_SourcePtr) __ioremap(addr, 0x400, _PAGE_NO_CACHE);
-	if (isu_num >= NumISUs)
-		NumISUs = isu_num + 1;
-}
-
-void find_ISUs(void)
-{
-	/* For PowerMac, setup ISUs on base openpic */
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		int i;
-		for (i=0; i<128; i+=0x10) {
-			ISU[i>>4] = &((struct OpenPIC *)OpenPIC_Addr)->Source[i];
-			NumISUs++;
-		}
-	}
-        /* Use /interrupt-controller/reg and
-         * /interrupt-controller/interrupt-ranges from OF device tree
-	 * the ISU array is setup in chrp_pci.c in ibm_add_bridges
-	 * as a result
-	 * -- tgall
-         */
-
-	/* basically each ISU is a bus, and this assumes that
-	 * open_pic_isu_count interrupts per bus are possible 
-	 * ISU == Interrupt Source
-	 *
-	 * On G5, we keep the original NumSources provided by the controller,
-	 * it's below 128, so we have room to stuff the IPIs and timers like darwin
-	 * does. We put the spurrious vector up at 0xff though.
-	 */
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		openpic_vec_ipi = NumSources;
-		openpic_vec_timer = openpic_vec_ipi + 4; 
-		openpic_vec_spurious = 0xff;
-	} else {
-		NumSources = NumISUs * 0x10;
-
-		openpic_vec_ipi = NumSources + open_pic_irq_offset;
-		openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI; 
-		openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS;
-	}
-}
-
-static inline void openpic_reset(void)
-{
-	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_RESET);
-}
-
-static inline void openpic_enable_8259_pass_through(void)
-{
-	openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
-			   OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-static void openpic_disable_8259_pass_through(void)
-{
-	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-/*
- *  Find out the current interrupt
- */
-static u_int openpic_irq(void)
-{
-	u_int vec;
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
-				OPENPIC_VECTOR_MASK);
-	return vec;
-}
-
-static void openpic_eoi(void)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
-	/* Handle PCI write posting */
-	(void)openpic_read(&OpenPIC->THIS_CPU.EOI);
-}
-
-
-static inline u_int openpic_get_priority(void)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
-				 OPENPIC_CURRENT_TASK_PRIORITY_MASK);
-}
-
-static void openpic_set_priority(u_int pri)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	check_arg_pri(pri);
-	openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
-			   OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
-}
-
-/*
- *  Get/set the spurious vector
- */
-static inline u_int openpic_get_spurious(void)
-{
-	return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
-				 OPENPIC_VECTOR_MASK);
-}
-
-static void openpic_set_spurious(u_int vec)
-{
-	check_arg_vec(vec);
-	openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
-			   vec);
-}
-
-/*
- * Convert a cpu mask from logical to physical cpu numbers.
- */
-static inline u32 physmask(u32 cpumask)
-{
-	int i;
-	u32 mask = 0;
-
-	for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
-		mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
-	return mask;
-}
-
-void openpic_init_processor(u_int cpumask)
-{
-	openpic_write(&OpenPIC->Global.Processor_Initialization,
-		      physmask(cpumask & cpus_addr(cpu_online_map)[0]));
-}
-
-#ifdef CONFIG_SMP
-/*
- *  Initialize an interprocessor interrupt (and disable it)
- *
- *  ipi: OpenPIC interprocessor interrupt number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- */
-static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
-{
-	check_arg_ipi(ipi);
-	check_arg_pri(pri);
-	check_arg_vec(vec);
-	openpic_safe_writefield_IPI(&OpenPIC->Global.IPI_Vector_Priority(ipi),
-				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
-				(pri << OPENPIC_PRIORITY_SHIFT) | vec);
-}
-
-/*
- *  Send an IPI to one or more CPUs
- *  
- *  Externally called, however, it takes an IPI number (0...OPENPIC_NUM_IPI)
- *  and not a system-wide interrupt number
- */
-void openpic_cause_IPI(u_int ipi, u_int cpumask)
-{
-	DECL_THIS_CPU;
-
-	CHECK_THIS_CPU;
-	check_arg_ipi(ipi);
-	openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
-		      physmask(cpumask & cpus_addr(cpu_online_map)[0]));
-}
-
-void openpic_request_IPIs(void)
-{
-	int i;
-	
-	/*
-	 * Make sure this matches what is defined in smp.c for 
-	 * smp_message_{pass|recv}() or what shows up in 
-	 * /proc/interrupts will be wrong!!! --Troy */
-	
-	if (OpenPIC == NULL)
-		return;
-
-	/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
-	request_irq(openpic_vec_ipi, openpic_ipi_action, SA_INTERRUPT,
-		    "IPI0 (call function)", NULL);
-	request_irq(openpic_vec_ipi+1, openpic_ipi_action, SA_INTERRUPT,
-		   "IPI1 (reschedule)", NULL);
-	request_irq(openpic_vec_ipi+2, openpic_ipi_action, SA_INTERRUPT,
-		   "IPI2 (unused)", NULL);
-	request_irq(openpic_vec_ipi+3, openpic_ipi_action, SA_INTERRUPT,
-		   "IPI3 (debugger break)", NULL);
-
-	for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
-		openpic_enable_ipi(openpic_vec_ipi+i);
-}
-
-/*
- * Do per-cpu setup for SMP systems.
- *
- * Get IPI's working and start taking interrupts.
- *   -- Cort
- */
-static spinlock_t openpic_setup_lock __devinitdata = SPIN_LOCK_UNLOCKED;
-
-void __devinit do_openpic_setup_cpu(void)
-{
-#ifdef CONFIG_IRQ_ALL_CPUS
- 	int i;
-	u32 msk = 1 << hard_smp_processor_id();
-#endif
-
-	spin_lock(&openpic_setup_lock);
-
-#ifdef CONFIG_IRQ_ALL_CPUS
- 	/* let the openpic know we want intrs. default affinity
- 	 * is 0xffffffff until changed via /proc
- 	 * That's how it's done on x86. If we want it differently, then
- 	 * we should make sure we also change the default values of irq_affinity
- 	 * in irq.c.
- 	 */
- 	for (i = 0; i < NumSources ; i++)
-		openpic_mapirq(i, openpic_read(&GET_ISU(i).Destination) | msk);
-#endif /* CONFIG_IRQ_ALL_CPUS */
- 	openpic_set_priority(0);
-
-	spin_unlock(&openpic_setup_lock);
-}
-#endif /* CONFIG_SMP */
-
-/*
- *  Initialize a timer interrupt (and disable it)
- *
- *  timer: OpenPIC timer number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- */
-static void __init openpic_inittimer(u_int timer, u_int pri, u_int vec)
-{
-	check_arg_timer(timer);
-	check_arg_pri(pri);
-	check_arg_vec(vec);
-	openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
-				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
-				(pri << OPENPIC_PRIORITY_SHIFT) | vec);
-}
-
-/*
- *  Map a timer interrupt to one or more CPUs
- */
-static void __init openpic_maptimer(u_int timer, u_int cpumask)
-{
-	check_arg_timer(timer);
-	openpic_write(&OpenPIC->Global.Timer[timer].Destination,
-		      physmask(cpumask & cpus_addr(cpu_online_map)[0]));
-}
-
-
-/*
- *
- * All functions below take an offset'ed irq argument
- *
- */
-
-
-/*
- *  Enable/disable an external interrupt source
- *
- *  Externally called, irq is an offseted system-wide interrupt number
- */
-static void openpic_enable_irq(u_int irq)
-{
-	unsigned int loops = 100000;
-	check_arg_irq(irq);
-
-	openpic_clearfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_enable_irq timeout\n");
-			break;
-		}
-
-		mb(); /* sync is probably useless here */
-	} while(openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
-			OPENPIC_MASK));
-}
-
-static void openpic_disable_irq(u_int irq)
-{
-	u32 vp;
-	unsigned int loops = 100000;
-	
-	check_arg_irq(irq);
-
-	openpic_setfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority, OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_disable_irq timeout\n");
-			break;
-		}
-
-		mb();  /* sync is probably useless here */
-		vp = openpic_readfield(&GET_ISU(irq - open_pic_irq_offset).Vector_Priority,
-    			OPENPIC_MASK | OPENPIC_ACTIVITY);
-	} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
-}
-
-#ifdef CONFIG_SMP
-/*
- *  Enable/disable an IPI interrupt source
- *  
- *  Externally called, irq is an offseted system-wide interrupt number
- */
-void openpic_enable_ipi(u_int irq)
-{
-	irq -= openpic_vec_ipi;
-	check_arg_ipi(irq);
-	openpic_clearfield_IPI(&OpenPIC->Global.IPI_Vector_Priority(irq), OPENPIC_MASK);
-
-}
-void openpic_disable_ipi(u_int irq)
-{
-   /* NEVER disable an IPI... that's just plain wrong! */
-}
-
-#endif
-
-/*
- *  Initialize an interrupt source (and disable it!)
- *
- *  irq: OpenPIC interrupt number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- *  pol: polarity (1 for positive, 0 for negative)
- *  sense: 1 for level, 0 for edge
- */
-static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
-{
-	openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
-				OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
-				(pri << OPENPIC_PRIORITY_SHIFT) | vec |
-				(pol ? OPENPIC_POLARITY_POSITIVE :
-			    		OPENPIC_POLARITY_NEGATIVE) |
-				(sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
-}
-
-/*
- *  Map an interrupt source to one or more CPUs
- */
-static void openpic_mapirq(u_int irq, u_int physmask)
-{
-	openpic_write(&GET_ISU(irq).Destination, physmask);
-}
-
-/*
- *  Set the sense for an interrupt source (and disable it!)
- *
- *  sense: 1 for level, 0 for edge
- */
-#if 0	/* not used */
-static void openpic_set_sense(u_int irq, int sense)
-{
-	openpic_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				OPENPIC_SENSE_LEVEL,
-				(sense ? OPENPIC_SENSE_LEVEL : 0));
-}
-
-static int openpic_get_sense(u_int irq)
-{
-	return openpic_readfield(&GET_ISU(irq).Vector_Priority,
-				 OPENPIC_SENSE_LEVEL) != 0;
-}
-#endif
-
-static void openpic_end_irq(unsigned int irq_nr)
-{
-	openpic_eoi();
-}
-
-static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask)
-{
-	cpumask_t tmp;
-
-	cpus_and(tmp, cpumask, cpu_online_map);
-	openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpus_addr(tmp)[0]));
-}
-
-#ifdef CONFIG_SMP
-static void openpic_end_ipi(unsigned int irq_nr)
-{
-	/*
-	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
-	 * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
-	 * applying to them. We EOI them late to avoid re-entering.
-	 * We mark IPI's with SA_INTERRUPT as they must run with
-	 * irqs disabled.
-	 */
-	openpic_eoi();
-}
-
-static irqreturn_t openpic_ipi_action(int cpl, void *dev_id,
-					struct pt_regs *regs)
-{
-	smp_message_recv(cpl-openpic_vec_ipi, regs);
-	return IRQ_HANDLED;
-}
-
-#endif /* CONFIG_SMP */
-
-int openpic_get_irq(struct pt_regs *regs)
-{
-	extern int i8259_irq(int cpu);
-
-	int irq = openpic_irq();
-
-        if (open_pic_irq_offset && irq == open_pic_irq_offset) {
-                /*
-                 * This magic address generates a PCI IACK cycle.
-                 */
-		if ( chrp_int_ack_special )
-			irq = *chrp_int_ack_special;
-		else
-			irq = i8259_irq( smp_processor_id() );
-		openpic_eoi();
-        }
-	if (irq == openpic_vec_spurious)
-		irq = -1;
-	return irq;
-}
diff -Nru a/arch/ppc64/kernel/open_pic.h b/arch/ppc64/kernel/open_pic.h
--- a/arch/ppc64/kernel/open_pic.h	2004-10-28 22:25:57 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,42 +0,0 @@
-/*
- *  arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  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.
- *  
- */
-
-#ifndef _PPC64_KERNEL_OPEN_PIC_H
-#define _PPC64_KERNEL_OPEN_PIC_H
-
-#include <linux/config.h>
-#include <linux/cpumask.h>
-#include <linux/irq.h>
-
-#define OPENPIC_SIZE	0x40000
-
-/* OpenPIC IRQ controller structure */
-extern struct hw_interrupt_type open_pic;
-
-/* OpenPIC IPI controller structure */
-#ifdef CONFIG_SMP
-extern struct hw_interrupt_type open_pic_ipi;
-#endif /* CONFIG_SMP */
-
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-extern void* OpenPIC_Addr;
-
-/* Exported functions */
-extern void openpic_init(int, int, unsigned char *, int);
-extern void openpic_request_IPIs(void);
-extern void do_openpic_setup_cpu(void);
-extern int openpic_get_irq(struct pt_regs *regs);
-extern void openpic_init_processor(u_int cpumask);
-extern void openpic_setup_ISU(int isu_num, unsigned long addr);
-extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
-
-#endif /* _PPC64_KERNEL_OPEN_PIC_H */
diff -Nru a/arch/ppc64/kernel/open_pic_defs.h b/arch/ppc64/kernel/open_pic_defs.h
--- a/arch/ppc64/kernel/open_pic_defs.h	2004-10-28 22:25:58 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,283 +0,0 @@
-/*
- *  linux/openpic.h -- OpenPIC definitions
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is based on the following documentation:
- *
- *	The Open Programmable Interrupt Controller (PIC)
- *	Register Interface Specification Revision 1.2
- *
- *	Issue Date: October 1995
- *
- *	Issued jointly by Advanced Micro Devices and Cyrix Corporation
- *
- *	AMD is a registered trademark of Advanced Micro Devices, Inc.
- *	Copyright (C) 1995, Advanced Micro Devices, Inc. and Cyrix, Inc.
- *	All Rights Reserved.
- *
- *  To receive a copy of this documentation, send an email to openpic@amd.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.
- */
-
-#ifndef _LINUX_OPENPIC_H
-#define _LINUX_OPENPIC_H
-
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-
-/*
- *  OpenPIC supports up to 2048 interrupt sources and up to 32 processors
- */
-
-#define OPENPIC_MAX_SOURCES	2048
-#define OPENPIC_MAX_PROCESSORS	32
-#define OPENPIC_MAX_ISU		32
-
-#define OPENPIC_NUM_TIMERS	4
-#define OPENPIC_NUM_IPI		4
-#define OPENPIC_NUM_PRI		16
-#define OPENPIC_NUM_VECTORS	OPENPIC_MAX_SOURCES
-
-/*
- *  OpenPIC Registers are 32 bits and aligned on 128 bit boundaries
- */
-
-typedef struct _OpenPIC_Reg {
-	u_int Reg;					/* Little endian! */
-	char Pad[0xc];
-} OpenPIC_Reg;
-
-
-/*
- *  Per Processor Registers
- */
-
-typedef struct _OpenPIC_Processor {
-	/*
-	 *  Private Shadow Registers (for SLiC backwards compatibility)
-	 */
-	u_int IPI0_Dispatch_Shadow;			/* Write Only */
-	char Pad1[0x4];
-	u_int IPI0_Vector_Priority_Shadow;		/* Read/Write */
-	char Pad2[0x34];
-	/*
-	 *  Interprocessor Interrupt Command Ports
-	 */
-	OpenPIC_Reg _IPI_Dispatch[OPENPIC_NUM_IPI];	/* Write Only */
-	/*
-	 *  Current Task Priority Register
-	 */
-	OpenPIC_Reg _Current_Task_Priority;		/* Read/Write */
-	char Pad3[0x10];
-	/*
-	 *  Interrupt Acknowledge Register
-	 */
-	OpenPIC_Reg _Interrupt_Acknowledge;		/* Read Only */
-	/*
-	 *  End of Interrupt (EOI) Register
-	 */
-	OpenPIC_Reg _EOI;				/* Read/Write */
-	char Pad5[0xf40];
-} OpenPIC_Processor;
-
-
-    /*
-     *  Timer Registers
-     */
-
-typedef struct _OpenPIC_Timer {
-	OpenPIC_Reg _Current_Count;			/* Read Only */
-	OpenPIC_Reg _Base_Count;			/* Read/Write */
-	OpenPIC_Reg _Vector_Priority;			/* Read/Write */
-	OpenPIC_Reg _Destination;			/* Read/Write */
-} OpenPIC_Timer;
-
-
-    /*
-     *  Global Registers
-     */
-
-typedef struct _OpenPIC_Global {
-	/*
-	 *  Feature Reporting Registers
-	 */
-	OpenPIC_Reg _Feature_Reporting0;		/* Read Only */
-	OpenPIC_Reg _Feature_Reporting1;		/* Future Expansion */
-	/*
-	 *  Global Configuration Registers
-	 */
-	OpenPIC_Reg _Global_Configuration0;		/* Read/Write */
-	OpenPIC_Reg _Global_Configuration1;		/* Future Expansion */
-	/*
-	 *  Vendor Specific Registers
-	 */
-	OpenPIC_Reg _Vendor_Specific[4];
-	/*
-	 *  Vendor Identification Register
-	 */
-	OpenPIC_Reg _Vendor_Identification;		/* Read Only */
-	/*
-	 *  Processor Initialization Register
-	 */
-	OpenPIC_Reg _Processor_Initialization;		/* Read/Write */
-	/*
-	 *  IPI Vector/Priority Registers
-	 */
-	OpenPIC_Reg _IPI_Vector_Priority[OPENPIC_NUM_IPI]; /* Read/Write */
-	/*
-	 *  Spurious Vector Register
-	 */
-	OpenPIC_Reg _Spurious_Vector;			/* Read/Write */
-	/*
-	 *  Global Timer Registers
-	 */
-	OpenPIC_Reg _Timer_Frequency;			/* Read/Write */
-	OpenPIC_Timer Timer[OPENPIC_NUM_TIMERS];
-	char Pad1[0xee00];
-} OpenPIC_Global;
-
-
-    /*
-     *  Interrupt Source Registers
-     */
-
-typedef struct _OpenPIC_Source {
-	OpenPIC_Reg _Vector_Priority;			/* Read/Write */
-	OpenPIC_Reg _Destination;			/* Read/Write */
-} OpenPIC_Source, *OpenPIC_SourcePtr;
-
-
-    /*
-     *  OpenPIC Register Map
-     */
-
-struct OpenPIC {
-	char Pad1[0x1000];
-	/*
-	 *  Global Registers
-	 */
-	OpenPIC_Global Global;
-	/*
-	 *  Interrupt Source Configuration Registers
-	 */
-	OpenPIC_Source Source[OPENPIC_MAX_SOURCES];
-	/*
-	 *  Per Processor Registers
-	 */
-	OpenPIC_Processor Processor[OPENPIC_MAX_PROCESSORS];
-};
-
-
-/*
- *  Current Task Priority Register
- */
-
-#define OPENPIC_CURRENT_TASK_PRIORITY_MASK	0x0000000f
-
-/*
- *  Who Am I Register
- */
-
-#define OPENPIC_WHO_AM_I_ID_MASK		0x0000001f
-
-/*
- *  Feature Reporting Register 0
- */
-
-#define OPENPIC_FEATURE_LAST_SOURCE_MASK	0x07ff0000
-#define OPENPIC_FEATURE_LAST_SOURCE_SHIFT	16
-#define OPENPIC_FEATURE_LAST_PROCESSOR_MASK	0x00001f00
-#define OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT	8
-#define OPENPIC_FEATURE_VERSION_MASK		0x000000ff
-
-/*
- *  Global Configuration Register 0
- */
-
-#define OPENPIC_CONFIG_RESET			0x80000000
-#define OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE	0x20000000
-#define OPENPIC_CONFIG_BASE_MASK		0x000fffff
-
-/*
- *  Vendor Identification Register
- */
-
-#define OPENPIC_VENDOR_ID_STEPPING_MASK		0x00ff0000
-#define OPENPIC_VENDOR_ID_STEPPING_SHIFT	16
-#define OPENPIC_VENDOR_ID_DEVICE_ID_MASK	0x0000ff00
-#define OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT	8
-#define OPENPIC_VENDOR_ID_VENDOR_ID_MASK	0x000000ff
-
-/*
- *  Vector/Priority Registers
- */
-
-#define OPENPIC_MASK				0x80000000
-#define OPENPIC_ACTIVITY			0x40000000	/* Read Only */
-#define OPENPIC_PRIORITY_MASK			0x000f0000
-#define OPENPIC_PRIORITY_SHIFT			16
-#define OPENPIC_VECTOR_MASK			0x000007ff
-
-
-/*
- *  Interrupt Source Registers
- */
-
-#define OPENPIC_POLARITY_POSITIVE		0x00800000
-#define OPENPIC_POLARITY_NEGATIVE		0x00000000
-#define OPENPIC_POLARITY_MASK			0x00800000
-#define OPENPIC_SENSE_LEVEL			0x00400000
-#define OPENPIC_SENSE_EDGE			0x00000000
-#define OPENPIC_SENSE_MASK			0x00400000
-
-
-/*
- *  Timer Registers
- */
-
-#define OPENPIC_COUNT_MASK			0x7fffffff
-#define OPENPIC_TIMER_TOGGLE			0x80000000
-#define OPENPIC_TIMER_COUNT_INHIBIT		0x80000000
-
-
-/*
- *  Aliases to make life simpler
- */
-
-/* Per Processor Registers */
-#define IPI_Dispatch(i)			_IPI_Dispatch[i].Reg
-#define Current_Task_Priority		_Current_Task_Priority.Reg
-#define Interrupt_Acknowledge		_Interrupt_Acknowledge.Reg
-#define EOI				_EOI.Reg
-
-/* Global Registers */
-#define Feature_Reporting0		_Feature_Reporting0.Reg
-#define Feature_Reporting1		_Feature_Reporting1.Reg
-#define Global_Configuration0		_Global_Configuration0.Reg
-#define Global_Configuration1		_Global_Configuration1.Reg
-#define Vendor_Specific(i)		_Vendor_Specific[i].Reg
-#define Vendor_Identification		_Vendor_Identification.Reg
-#define Processor_Initialization	_Processor_Initialization.Reg
-#define IPI_Vector_Priority(i)		_IPI_Vector_Priority[i].Reg
-#define Spurious_Vector			_Spurious_Vector.Reg
-#define Timer_Frequency			_Timer_Frequency.Reg
-
-/* Timer Registers */
-#define Current_Count			_Current_Count.Reg
-#define Base_Count			_Base_Count.Reg
-#define Vector_Priority			_Vector_Priority.Reg
-#define Destination			_Destination.Reg
-
-/* Interrupt Source Registers */
-#define Vector_Priority			_Vector_Priority.Reg
-#define Destination			_Destination.Reg
-
-
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_OPENPIC_H */
diff -Nru a/arch/ppc64/kernel/open_pic_u3.c b/arch/ppc64/kernel/open_pic_u3.c
--- a/arch/ppc64/kernel/open_pic_u3.c	2004-10-28 22:25:56 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,348 +0,0 @@
-/*
- *  arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  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/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-
-#include <asm/machdep.h>
-
-#include "open_pic.h"
-#include "open_pic_defs.h"
-
-void* OpenPIC2_Addr;
-static volatile struct OpenPIC *OpenPIC2 = NULL;
-
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-
-static u_int NumSources;
-static int NumISUs;
-static int open_pic2_irq_offset;
-
-static OpenPIC_SourcePtr ISU2[OPENPIC_MAX_ISU];
-
-unsigned int openpic2_vec_spurious;
-
-/*
- *  Accesses to the current processor's openpic registers
- *  U3 secondary openpic has only one output
- */
-#define THIS_CPU		Processor[0]
-#define DECL_THIS_CPU
-#define CHECK_THIS_CPU
-
-#define GET_ISU(source)	ISU2[(source) >> 4][(source) & 0xf]
-
-static inline u_int openpic2_read(volatile u_int *addr)
-{
-	u_int val;
-
-	val = in_be32(addr);
-	return val;
-}
-
-static inline void openpic2_write(volatile u_int *addr, u_int val)
-{
-	out_be32(addr, val);
-}
-
-static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask)
-{
-	u_int val = openpic2_read(addr);
-	return val & mask;
-}
-
-static inline void openpic2_writefield(volatile u_int *addr, u_int mask,
-			       u_int field)
-{
-	u_int val = openpic2_read(addr);
-	openpic2_write(addr, (val & ~mask) | (field & mask));
-}
-
-static inline void openpic2_clearfield(volatile u_int *addr, u_int mask)
-{
-	openpic2_writefield(addr, mask, 0);
-}
-
-static inline void openpic2_setfield(volatile u_int *addr, u_int mask)
-{
-	openpic2_writefield(addr, mask, mask);
-}
-
-static void openpic2_safe_writefield(volatile u_int *addr, u_int mask,
-				    u_int field)
-{
-	unsigned int loops = 100000;
-
-	openpic2_setfield(addr, OPENPIC_MASK);
-	while (openpic2_read(addr) & OPENPIC_ACTIVITY) {
-		if (!loops--) {
-			printk(KERN_ERR "openpic2_safe_writefield timeout\n");
-			break;
-		}
-	}
-	openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
-}
-
-
-static inline void openpic2_reset(void)
-{
-	openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_RESET);
-}
-
-static void openpic2_disable_8259_pass_through(void)
-{
-	openpic2_setfield(&OpenPIC2->Global.Global_Configuration0,
-			 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-/*
- *  Find out the current interrupt
- */
-static u_int openpic2_irq(void)
-{
-	u_int vec;
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge,
-				 OPENPIC_VECTOR_MASK);
-	return vec;
-}
-
-static void openpic2_eoi(void)
-{
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0);
-	/* Handle PCI write posting */
-	(void)openpic2_read(&OpenPIC2->THIS_CPU.EOI);
-}
-
-
-static inline u_int openpic2_get_priority(void)
-{
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
-				  OPENPIC_CURRENT_TASK_PRIORITY_MASK);
-}
-
-static void openpic2_set_priority(u_int pri)
-{
-	DECL_THIS_CPU;
-	CHECK_THIS_CPU;
-	openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority,
-			    OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
-}
-
-/*
- *  Get/set the spurious vector
- */
-static inline u_int openpic2_get_spurious(void)
-{
-	return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector,
-				  OPENPIC_VECTOR_MASK);
-}
-
-static void openpic2_set_spurious(u_int vec)
-{
-	openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
-			    vec);
-}
-
-/*
- *  Enable/disable an external interrupt source
- *
- *  Externally called, irq is an offseted system-wide interrupt number
- */
-static void openpic2_enable_irq(u_int irq)
-{
-	unsigned int loops = 100000;
-
-	openpic2_clearfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_enable_irq timeout\n");
-			break;
-		}
-
-		mb(); /* sync is probably useless here */
-	} while(openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
-			OPENPIC_MASK));
-}
-
-static void openpic2_disable_irq(u_int irq)
-{
-	u32 vp;
-	unsigned int loops = 100000;
-	
-	openpic2_setfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
-			  OPENPIC_MASK);
-	/* make sure mask gets to controller before we return to user */
-	do {
-		if (!loops--) {
-			printk(KERN_ERR "openpic_disable_irq timeout\n");
-			break;
-		}
-
-		mb();  /* sync is probably useless here */
-		vp = openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority,
-    			OPENPIC_MASK | OPENPIC_ACTIVITY);
-	} while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));
-}
-
-/*
- *  Initialize an interrupt source (and disable it!)
- *
- *  irq: OpenPIC interrupt number
- *  pri: interrupt source priority
- *  vec: the vector it will produce
- *  pol: polarity (1 for positive, 0 for negative)
- *  sense: 1 for level, 0 for edge
- */
-static void openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
-{
-	openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				 OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
-				 OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
-				 (pri << OPENPIC_PRIORITY_SHIFT) | vec |
-				 (pol ? OPENPIC_POLARITY_POSITIVE :
-				  OPENPIC_POLARITY_NEGATIVE) |
-				 (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));
-}
-
-/*
- *  Map an interrupt source to one or more CPUs
- */
-static void openpic2_mapirq(u_int irq, u_int physmask)
-{
-	openpic2_write(&GET_ISU(irq).Destination, physmask);
-}
-
-/*
- *  Set the sense for an interrupt source (and disable it!)
- *
- *  sense: 1 for level, 0 for edge
- */
-static inline void openpic2_set_sense(u_int irq, int sense)
-{
-	openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority,
-				 OPENPIC_SENSE_LEVEL,
-				 (sense ? OPENPIC_SENSE_LEVEL : 0));
-}
-
-static void openpic2_end_irq(unsigned int irq_nr)
-{
-	openpic2_eoi();
-}
-
-int openpic2_get_irq(struct pt_regs *regs)
-{
-	int irq = openpic2_irq();
-
-	if (irq == openpic2_vec_spurious)
-		return -1;
-	return irq + open_pic2_irq_offset;
-}
-
-struct hw_interrupt_type open_pic2 = {
-	" OpenPIC2 ",
-	NULL,
-	NULL,
-	openpic2_enable_irq,
-	openpic2_disable_irq,
-	NULL,
-	openpic2_end_irq,
-};
-
-void __init openpic2_init(int offset)
-{
-	u_int t, i;
-	const char *version;
-
-	if (!OpenPIC2_Addr) {
-		printk(KERN_INFO "No OpenPIC2 found !\n");
-		return;
-	}
-	OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr;
-
-	ppc64_boot_msg(0x20, "OpenPic U3 Init");
-
-	t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0);
-	switch (t & OPENPIC_FEATURE_VERSION_MASK) {
-	case 1:
-		version = "1.0";
-		break;
-	case 2:
-		version = "1.2";
-		break;
-	case 3:
-		version = "1.3";
-		break;
-	default:
-		version = "?";
-		break;
-	}
-	printk(KERN_INFO "OpenPIC (U3) Version %s\n", version);
-
-	open_pic2_irq_offset = offset;
-
-	for (i=0; i<128; i+=0x10) {
-		ISU2[i>>4] = &((struct OpenPIC *)OpenPIC2_Addr)->Source[i];
-		NumISUs++;
-	}
-	NumSources = NumISUs * 0x10;
-	openpic2_vec_spurious = NumSources;
-
-	openpic2_set_priority(0xf);
-
-	/* Init all external sources */
-	for (i = 0; i < NumSources; i++) {
-		int pri, sense;
-
-		/* the bootloader may have left it enabled (bad !) */
-		openpic2_disable_irq(i+offset);
-
-		pri = 8;
-		sense = (i < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[i]: 1;
-		if (sense)
-			irq_desc[i+offset].status = IRQ_LEVEL;
-
-		/* Enabled, Priority 8 or 9 */
-		openpic2_initirq(i, pri, i, !sense, sense);
-		/* Processor 0 */
-		openpic2_mapirq(i, 0x1);
-	}
-
-	/* Init descriptors */
-	for (i = offset; i < NumSources + offset; i++)
-		irq_desc[i].handler = &open_pic2;
-
-	/* Initialize the spurious interrupt */
-	openpic2_set_spurious(openpic2_vec_spurious);
-
-	openpic2_set_priority(0);
-	openpic2_disable_8259_pass_through();
-
-	ppc64_boot_msg(0x25, "OpenPic U3 Done");
-}
diff -Nru a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
--- a/arch/ppc64/kernel/pSeries_iommu.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/pSeries_iommu.c	2004-10-28 22:25:57 -07:00
@@ -412,6 +412,38 @@
 	dn->iommu_table = iommu_init_table(tbl);
 }
 
+void iommu_free_table(struct device_node *dn)
+{
+	struct iommu_table *tbl = dn->iommu_table;
+	unsigned long bitmap_sz, i;
+	unsigned int order;
+
+	if (!tbl || !tbl->it_map) {
+		printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
+				dn->full_name);
+		return;
+	}
+
+	/* verify that table contains no entries */
+	/* it_mapsize is in entries, and we're examining 64 at a time */
+	for (i = 0; i < (tbl->it_mapsize/64); i++) {
+		if (tbl->it_map[i] != 0) {
+			printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
+				__FUNCTION__, dn->full_name);
+			break;
+		}
+	}
+
+	/* calculate bitmap size in bytes */
+	bitmap_sz = (tbl->it_mapsize + 7) / 8;
+
+	/* free bitmap */
+	order = get_order(bitmap_sz);
+	free_pages((unsigned long) tbl->it_map, order);
+
+	/* free table */
+	kfree(tbl);
+}
 
 void iommu_setup_pSeries(void)
 {
diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
--- a/arch/ppc64/kernel/pSeries_lpar.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/pSeries_lpar.c	2004-10-28 22:25:59 -07:00
@@ -59,6 +59,74 @@
 
 int vtermno;	/* virtual terminal# for udbg  */
 
+#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
+static void udbg_hvsi_putc(unsigned char c)
+{
+	/* packet's seqno isn't used anyways */
+	uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
+	int rc;
+
+	if (c == '\n')
+		udbg_hvsi_putc('\r');
+
+	do {
+		rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
+	} while (rc == H_Busy);
+}
+
+static long hvsi_udbg_buf_len;
+static uint8_t hvsi_udbg_buf[256];
+
+static int udbg_hvsi_getc_poll(void)
+{
+	unsigned char ch;
+	int rc, i;
+
+	if (hvsi_udbg_buf_len == 0) {
+		rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
+		if (rc != H_Success || hvsi_udbg_buf[0] != 0xff) {
+			/* bad read or non-data packet */
+			hvsi_udbg_buf_len = 0;
+		} else {
+			/* remove the packet header */
+			for (i = 4; i < hvsi_udbg_buf_len; i++)
+				hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
+			hvsi_udbg_buf_len -= 4;
+		}
+	}
+
+	if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
+		/* no data ready */
+		hvsi_udbg_buf_len = 0;
+		return -1;
+	}
+
+	ch = hvsi_udbg_buf[0];
+	/* shift remaining data down */
+	for (i = 1; i < hvsi_udbg_buf_len; i++) {
+		hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
+	}
+	hvsi_udbg_buf_len--;
+
+	return ch;
+}
+
+static unsigned char udbg_hvsi_getc(void)
+{
+	int ch;
+	for (;;) {
+		ch = udbg_hvsi_getc_poll();
+		if (ch == -1) {
+			/* This shouldn't be needed...but... */
+			volatile unsigned long delay;
+			for (delay=0; delay < 2000000; delay++)
+				;
+		} else {
+			return ch;
+		}
+	}
+}
+
 static void udbg_putcLP(unsigned char c)
 {
 	char buf[16];
@@ -166,11 +234,15 @@
 				ppc_md.udbg_getc_poll = udbg_getc_pollLP;
 				found = 1;
 			}
-		} else {
-			/* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */
-			printk(KERN_WARNING "%s doesn't speak hvterm1; "
-					"can't print udbg messages\n",
-			       stdout_node->full_name);
+		} else if (device_is_compatible(stdout_node, "hvterm-protocol")) {
+			termno = (u32 *)get_property(stdout_node, "reg", NULL);
+			if (termno) {
+				vtermno = termno[0];
+				ppc_md.udbg_putc = udbg_hvsi_putc;
+				ppc_md.udbg_getc = udbg_hvsi_getc;
+				ppc_md.udbg_getc_poll = udbg_hvsi_getc_poll;
+				found = 1;
+			}
 		}
 	} else if (strncmp(name, "serial", 6)) {
 		/* XXX fix ISA serial console */
diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
--- a/arch/ppc64/kernel/pSeries_pci.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/pSeries_pci.c	2004-10-28 22:25:59 -07:00
@@ -42,7 +42,7 @@
 #include <asm/iommu.h>
 #include <asm/rtas.h>
 
-#include "open_pic.h"
+#include "mpic.h"
 #include "pci.h"
 
 /* RTAS tokens */
@@ -54,6 +54,7 @@
 static int s7a_workaround;
 
 extern unsigned long pci_probe_only;
+extern struct mpic *pSeries_mpic;
 
 static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
 {
@@ -153,8 +154,8 @@
 
 static void python_countermeasures(unsigned long addr)
 {
-	void *chip_regs;
-	volatile u32 *tmp, i;
+	void __iomem *chip_regs;
+	volatile u32 val;
 
 	/* Python's register file is 1 MB in size. */
 	chip_regs = ioremap(addr & ~(0xfffffUL), 0x100000); 
@@ -166,17 +167,17 @@
 
 #define PRG_CL_RESET_VALID 0x00010000
 
-	tmp = (u32 *)((unsigned long)chip_regs + 0xf6030);
-
-	if (*tmp & PRG_CL_RESET_VALID) {
+	val = in_be32(chip_regs + 0xf6030);
+	if (val & PRG_CL_RESET_VALID) {
 		printk(KERN_INFO "Python workaround: ");
-		*tmp &= ~PRG_CL_RESET_VALID;
+		val &= ~PRG_CL_RESET_VALID;
+		out_be32(chip_regs + 0xf6030, val);
 		/*
 		 * We must read it back for changes to
 		 * take effect
 		 */
-		i = *tmp;
-		printk("reg0: %x\n", i);
+		val = in_be32(chip_regs + 0xf6030);
+		printk("reg0: %x\n", val);
 	}
 
 	iounmap(chip_regs);
@@ -399,9 +400,9 @@
 		pci_process_bridge_OF_ranges(phb, node);
 		pci_setup_phb_io(phb, index == 0);
 
-		if (naca->interrupt_controller == IC_OPEN_PIC) {
+		if (naca->interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
 			int addr = root_size_cells * (index + 2) - 1;
-			openpic_setup_ISU(index, opprop[addr]); 
+			mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
 		}
 
 		index++;
@@ -481,92 +482,6 @@
 	}
 }
 
-static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
-				unsigned long *start_virt, unsigned long *size)
-{
-	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
-	struct pci_bus_region region;
-	struct resource *res;
-
-	if (bus->self) {
-		res = bus->resource[0];
-		pcibios_resource_to_bus(bus->self, &region, res);
-		*start_phys = hose->io_base_phys + region.start;
-		*start_virt = (unsigned long) hose->io_base_virt + 
-				region.start;
-		if (region.end > region.start) 
-			*size = region.end - region.start + 1;
-		else {
-			printk("%s(): unexpected region 0x%lx->0x%lx\n", 
-					__FUNCTION__, region.start, region.end);
-			return 1;
-		}
-		
-	} else {
-		/* Root Bus */
-		res = &hose->io_resource;
-		*start_phys = hose->io_base_phys;
-		*start_virt = (unsigned long) hose->io_base_virt;
-		if (res->end > res->start)
-			*size = res->end - res->start + 1;
-		else {
-			printk("%s(): unexpected region 0x%lx->0x%lx\n", 
-					__FUNCTION__, res->start, res->end);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-int unmap_bus_range(struct pci_bus *bus)
-{
-	unsigned long start_phys;
-	unsigned long start_virt;
-	unsigned long size;
-
-	if (!bus) {
-		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-		return 1;
-	}
-	
-	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-		return 1;
-	if (iounmap_explicit((void *) start_virt, size))
-		return 1;
-
-	return 0;
-}
-EXPORT_SYMBOL(unmap_bus_range);
-
-int remap_bus_range(struct pci_bus *bus)
-{
-	unsigned long start_phys;
-	unsigned long start_virt;
-	unsigned long size;
-
-	if (!bus) {
-		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
-		return 1;
-	}
-	
-	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
-		return 1;
-	if (__ioremap_explicit(start_phys, start_virt, size, _PAGE_NO_CACHE))
-		return 1;
-
-	return 0;
-}
-EXPORT_SYMBOL(remap_bus_range);
-
-static void phbs_remap_io(void)
-{
-	struct pci_controller *hose, *tmp;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
-		remap_bus_range(hose->bus);
-}
-
 /* RPA-specific bits for removing PHBs */
 int pcibios_remove_root_bus(struct pci_controller *phb)
 {
@@ -619,25 +534,12 @@
 
 static void __init pSeries_request_regions(void)
 {
-	struct device_node *i8042;
-
 	request_region(0x20,0x20,"pic1");
 	request_region(0xa0,0x20,"pic2");
 	request_region(0x00,0x20,"dma1");
 	request_region(0x40,0x20,"timer");
 	request_region(0x80,0x10,"dma page reg");
 	request_region(0xc0,0x20,"dma2");
-
-#define I8042_DATA_REG 0x60
-
-	/*
-	 * Some machines have an unterminated i8042 so check the device
-	 * tree and reserve the region if it does not appear. Later on
-	 * the i8042 code will try and reserve this region and fail.
-	 */
-	if (!(i8042 = of_find_node_by_type(NULL, "8042")))
-		request_region(I8042_DATA_REG, 16, "reserved (no i8042)");
-	of_node_put(i8042);
 }
 
 void __init pSeries_final_fixup(void)
diff -Nru a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
--- a/arch/ppc64/kernel/pSeries_setup.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/pSeries_setup.c	2004-10-28 22:25:57 -07:00
@@ -61,19 +61,18 @@
 #include <asm/nvram.h>
 
 #include "i8259.h"
-#include "open_pic.h"
 #include <asm/xics.h>
 #include <asm/ppcdebug.h>
 #include <asm/cputable.h>
 
+#include "mpic.h"
+
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
 #else
 #define DBG(fmt...)
 #endif
 
-extern void pSeries_init_openpic(void);
-
 extern void find_and_init_phbs(void);
 extern void pSeries_final_fixup(void);
 
@@ -82,6 +81,8 @@
 extern int  pSeries_set_rtc_time(struct rtc_time *rtc_time);
 extern void find_udbg_vterm(void);
 extern void SystemReset_FWNMI(void), MachineCheck_FWNMI(void);	/* from head.S */
+extern void generic_find_legacy_serial_ports(unsigned int *default_speed);
+
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
 unsigned long  virtPython0Facilities = 0;  // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
@@ -91,6 +92,9 @@
 extern unsigned long ppc_proc_freq;
 extern unsigned long ppc_tb_freq;
 
+static volatile void __iomem * chrp_int_ack_special;
+struct mpic *pSeries_mpic;
+
 void pSeries_get_cpuinfo(struct seq_file *m)
 {
 	struct device_node *root;
@@ -120,15 +124,84 @@
 		fwnmi_active = 1;
 }
 
-static void __init pSeries_setup_arch(void)
+static int pSeries_irq_cascade(struct pt_regs *regs, void *data)
+{
+	if (chrp_int_ack_special)
+		return readb(chrp_int_ack_special);
+	else
+		return i8259_irq(smp_processor_id());
+}
+
+static void __init pSeries_init_mpic(void)
+{
+        unsigned int *addrp;
+	struct device_node *np;
+        int i;
+
+	/* All ISUs are setup, complete initialization */
+	mpic_init(pSeries_mpic);
+
+	/* Check what kind of cascade ACK we have */
+        if (!(np = of_find_node_by_name(NULL, "pci"))
+            || !(addrp = (unsigned int *)
+                 get_property(np, "8259-interrupt-acknowledge", NULL)))
+                printk(KERN_ERR "Cannot find pci to get ack address\n");
+        else
+		chrp_int_ack_special = ioremap(addrp[prom_n_addr_cells(np)-1], 1);
+	of_node_put(np);
+
+	/* Setup the legacy interrupts & controller */
+        for (i = 0; i < NUM_ISA_INTERRUPTS; i++)
+                irq_desc[i].handler = &i8259_pic;
+	i8259_init(0);
+
+	/* Hook cascade to mpic */
+	mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL);
+}
+
+static void __init pSeries_setup_mpic(void)
 {
-	struct device_node *root;
 	unsigned int *opprop;
+	unsigned long openpic_addr = 0;
+        unsigned char senses[NR_IRQS - NUM_ISA_INTERRUPTS];
+        struct device_node *root;
+	int irq_count;
+
+	/* Find the Open PIC if present */
+	root = of_find_node_by_path("/");
+	opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL);
+	if (opprop != 0) {
+		int n = prom_n_addr_cells(root);
+
+		for (openpic_addr = 0; n > 0; --n)
+			openpic_addr = (openpic_addr << 32) + *opprop++;
+		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
+	}
+	of_node_put(root);
+
+	BUG_ON(openpic_addr == 0);
+
+	/* Get the sense values from OF */
+	prom_get_irq_senses(senses, NUM_ISA_INTERRUPTS, NR_IRQS);
+	
+	/* Setup the openpic driver */
+	irq_count = NR_IRQS - NUM_ISA_INTERRUPTS - 4; /* leave room for IPIs */
+	pSeries_mpic = mpic_alloc(openpic_addr, MPIC_PRIMARY,
+				  16, 16, irq_count, /* isu size, irq offset, irq count */ 
+				  NR_IRQS - 4, /* ipi offset */
+				  senses, irq_count, /* sense & sense size */
+				  " MPIC     ");
+}
 
+static void __init pSeries_setup_arch(void)
+{
 	/* Fixup ppc_md depending on the type of interrupt controller */
 	if (naca->interrupt_controller == IC_OPEN_PIC) {
-		ppc_md.init_IRQ       = pSeries_init_openpic; 
-		ppc_md.get_irq        = openpic_get_irq;
+		ppc_md.init_IRQ       = pSeries_init_mpic; 
+		ppc_md.get_irq        = mpic_get_irq;
+		/* Allocate the mpic now, so that find_and_init_phbs() can
+		 * fill the ISUs */
+		pSeries_setup_mpic();
 	} else {
 		ppc_md.init_IRQ       = xics_init_IRQ;
 		ppc_md.get_irq        = xics_get_irq;
@@ -156,21 +229,6 @@
 	eeh_init();
 	find_and_init_phbs();
 
-	/* Find the Open PIC if present */
-	root = of_find_node_by_path("/");
-	opprop = (unsigned int *) get_property(root,
-				"platform-open-pic", NULL);
-	if (opprop != 0) {
-		int n = prom_n_addr_cells(root);
-		unsigned long openpic;
-
-		for (openpic = 0; n > 0; --n)
-			openpic = (openpic << 32) + *opprop++;
-		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic);
-		OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE);
-	}
-	of_node_put(root);
-
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
@@ -189,75 +247,6 @@
 arch_initcall(pSeries_init_panel);
 
 
-
-void __init pSeries_find_serial_port(void)
-{
-	struct device_node *np;
-	unsigned long encode_phys_size = 32;
-	u32 *sizeprop;
-
-	struct isa_reg_property {
-		u32 space;
-		u32 address;
-		u32 size;
-	};
-	struct pci_reg_property {
-		struct pci_address addr;
-		u32 size_hi;
-		u32 size_lo;
-	};                                                                        
-
-	DBG(" -> pSeries_find_serial_port()\n");
-
-	naca->serialPortAddr = 0;
-
-	np = of_find_node_by_path("/");
-	if (!np)
-		return;
-	sizeprop = (u32 *)get_property(np, "#size-cells", NULL);
-	if (sizeprop != NULL)
-		encode_phys_size = (*sizeprop) << 5;
-	
-	for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
-		struct device_node *isa, *pci;
-		struct isa_reg_property *reg;
-		union pci_range *rangesp;
-		char *typep;
-
-	 	typep = (char *)get_property(np, "ibm,aix-loc", NULL);
-		if ((typep == NULL) || (typep && strcmp(typep, "S1")))
-			continue;
-
-		reg = (struct isa_reg_property *)get_property(np, "reg", NULL);	
-
-		isa = of_get_parent(np);
-		if (!isa) {
-			DBG("no isa parent found\n");
-			break;
-		}
-		pci = of_get_parent(isa);
-		if (!pci) {
-			DBG("no pci parent found\n");
-			break;
-		}
-
-		rangesp = (union pci_range *)get_property(pci, "ranges", NULL);
-
-		if ( encode_phys_size == 32 )
-			naca->serialPortAddr = rangesp->pci32.phys+reg->address;
-		else {
-			naca->serialPortAddr =
-				((((unsigned long)rangesp->pci64.phys_hi) << 32)
-				|
-			(rangesp->pci64.phys_lo)) + reg->address;
-		}
-		break;
-	}
-
-	DBG(" <- pSeries_find_serial_port()\n");
-}
-
-
 /* Build up the firmware_features bitmask field
  * using contents of device-tree/ibm,hypertas-functions.
  * Ultimately this functionality may be moved into prom.c prom_init().
@@ -330,6 +319,20 @@
 	}
 }
 
+static void pSeries_cpu_die(void)
+{
+	local_irq_disable();
+	/* Some hardware requires clearing the CPPR, while other hardware does not
+	 * it is safe either way
+	 */
+	pSeriesLP_cppr_info(0, 0);
+	rtas_stop_self();
+	/* Should never get here... */
+	BUG();
+	for(;;);
+}
+
+
 /*
  * Early initialization.  Relocation is on but do not reference unbolted pages
  */
@@ -337,6 +340,7 @@
 {
 	void *comport;
 	int iommu_off = 0;
+	unsigned int default_speed;
 
 	DBG(" -> pSeries_init_early()\n");
 
@@ -350,14 +354,14 @@
 			     get_property(of_chosen, "linux,iommu-off", NULL));
 	}
 
-	pSeries_find_serial_port();
+	generic_find_legacy_serial_ports(&default_speed);
 
 	if (systemcfg->platform & PLATFORM_LPAR)
 		find_udbg_vterm();
 	else if (naca->serialPortAddr) {
 		/* Map the uart for udbg. */
 		comport = (void *)__ioremap(naca->serialPortAddr, 16, _PAGE_NO_CACHE);
-		udbg_init_uart(comport);
+		udbg_init_uart(comport, default_speed);
 
 		ppc_md.udbg_putc = udbg_putc;
 		ppc_md.udbg_getc = udbg_getc;
@@ -542,6 +546,31 @@
 	setup_default_decr();
 }
 
+static int pSeries_check_legacy_ioport(unsigned int baseport)
+{
+	struct device_node *np;
+
+#define I8042_DATA_REG	0x60
+#define FDC_BASE	0x3f0
+
+
+	switch(baseport) {
+	case I8042_DATA_REG:
+		np = of_find_node_by_type(NULL, "8042");
+		if (np == NULL)
+			return -ENODEV;
+		of_node_put(np);
+		break;
+	case FDC_BASE:
+		np = of_find_node_by_type(NULL, "fdc");
+		if (np == NULL)
+			return -ENODEV;
+		of_node_put(np);
+		break;
+	}
+	return 0;
+}
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
@@ -571,9 +600,11 @@
 	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.panic			= rtas_os_term,
+	.cpu_die		= pSeries_cpu_die,
 	.get_boot_time		= pSeries_get_boot_time,
 	.get_rtc_time		= pSeries_get_rtc_time,
 	.set_rtc_time		= pSeries_set_rtc_time,
 	.calibrate_decr		= pSeries_calibrate_decr,
 	.progress		= pSeries_progress,
+	.check_legacy_ioport	= pSeries_check_legacy_ioport,
 };
diff -Nru a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/pSeries_smp.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,393 @@
+/*
+ * SMP support for pSeries machines.
+ *
+ * Dave Engebretsen, Peter Bergner, and
+ * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
+ *
+ * Plus various changes from other IBM teams...
+ *
+ *      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.
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/naca.h>
+#include <asm/paca.h>
+#include <asm/time.h>
+#include <asm/ppcdebug.h>
+#include <asm/machdep.h>
+#include <asm/xics.h>
+#include <asm/cputable.h>
+#include <asm/system.h>
+#include <asm/rtas.h>
+#include <asm/plpar_wrappers.h>
+
+#include "mpic.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+extern void pseries_secondary_smp_init(unsigned long); 
+
+static void vpa_init(int cpu)
+{
+	unsigned long flags, pcpu = get_hard_smp_processor_id(cpu);
+
+	/* Register the Virtual Processor Area (VPA) */
+	flags = 1UL << (63 - 18);
+	register_vpa(flags, pcpu, __pa((unsigned long)&(paca[cpu].lppaca)));
+}
+
+
+/* Get state of physical CPU.
+ * Return codes:
+ *	0	- The processor is in the RTAS stopped state
+ *	1	- stop-self is in progress
+ *	2	- The processor is not in the RTAS stopped state
+ *	-1	- Hardware Error
+ *	-2	- Hardware Busy, Try again later.
+ */
+static int query_cpu_stopped(unsigned int pcpu)
+{
+	int cpu_status;
+	int status, qcss_tok;
+
+	qcss_tok = rtas_token("query-cpu-stopped-state");
+	if (qcss_tok == RTAS_UNKNOWN_SERVICE)
+		return -1;
+	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
+	if (status != 0) {
+		printk(KERN_ERR
+		       "RTAS query-cpu-stopped-state failed: %i\n", status);
+		return status;
+	}
+
+	return cpu_status;
+}
+
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+int __cpu_disable(void)
+{
+	/* FIXME: go put this in a header somewhere */
+	extern void xics_migrate_irqs_away(void);
+
+	systemcfg->processorCount--;
+
+	/*fix boot_cpuid here*/
+	if (smp_processor_id() == boot_cpuid)
+		boot_cpuid = any_online_cpu(cpu_online_map);
+
+	/* FIXME: abstract this to not be platform specific later on */
+	xics_migrate_irqs_away();
+	return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	int tries;
+	int cpu_status;
+	unsigned int pcpu = get_hard_smp_processor_id(cpu);
+
+	for (tries = 0; tries < 25; tries++) {
+		cpu_status = query_cpu_stopped(pcpu);
+		if (cpu_status == 0 || cpu_status == -1)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ/5);
+	}
+	if (cpu_status != 0) {
+		printk("Querying DEAD? cpu %i (%i) shows %i\n",
+		       cpu, pcpu, cpu_status);
+	}
+
+	/* Isolation and deallocation are definatly done by
+	 * drslot_chrp_cpu.  If they were not they would be
+	 * done here.  Change isolate state to Isolate and
+	 * change allocation-state to Unusable.
+	 */
+	paca[cpu].cpu_start = 0;
+}
+
+/* Search all cpu device nodes for an offline logical cpu.  If a
+ * device node has a "ibm,my-drc-index" property (meaning this is an
+ * LPAR), paranoid-check whether we own the cpu.  For each "thread"
+ * of a cpu, if it is offline and has the same hw index as before,
+ * grab that in preference.
+ */
+static unsigned int find_physical_cpu_to_start(unsigned int old_hwindex)
+{
+	struct device_node *np = NULL;
+	unsigned int best = -1U;
+
+	while ((np = of_find_node_by_type(np, "cpu"))) {
+		int nr_threads, len;
+		u32 *index = (u32 *)get_property(np, "ibm,my-drc-index", NULL);
+		u32 *tid = (u32 *)
+			get_property(np, "ibm,ppc-interrupt-server#s", &len);
+
+		if (!tid)
+			tid = (u32 *)get_property(np, "reg", &len);
+
+		if (!tid)
+			continue;
+
+		/* If there is a drc-index, make sure that we own
+		 * the cpu.
+		 */
+		if (index) {
+			int state;
+			int rc = rtas_get_sensor(9003, *index, &state);
+			if (rc != 0 || state != 1)
+				continue;
+		}
+
+		nr_threads = len / sizeof(u32);
+
+		while (nr_threads--) {
+			if (0 == query_cpu_stopped(tid[nr_threads])) {
+				best = tid[nr_threads];
+				if (best == old_hwindex)
+					goto out;
+			}
+		}
+	}
+out:
+	of_node_put(np);
+	return best;
+}
+
+/**
+ * smp_startup_cpu() - start the given cpu
+ *
+ * At boot time, there is nothing to do.  At run-time, call RTAS with
+ * the appropriate start location, if the cpu is in the RTAS stopped
+ * state.
+ *
+ * Returns:
+ *	0	- failure
+ *	1	- success
+ */
+static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+{
+	int status;
+	unsigned long start_here = __pa((u32)*((unsigned long *)
+					       pseries_secondary_smp_init));
+	unsigned int pcpu;
+
+	/* At boot time the cpus are already spinning in hold
+	 * loops, so nothing to do. */
+ 	if (system_state < SYSTEM_RUNNING)
+		return 1;
+
+	pcpu = find_physical_cpu_to_start(get_hard_smp_processor_id(lcpu));
+	if (pcpu == -1U) {
+		printk(KERN_INFO "No more cpus available, failing\n");
+		return 0;
+	}
+
+	/* Fixup atomic count: it exited inside IRQ handler. */
+	paca[lcpu].__current->thread_info->preempt_count	= 0;
+
+	/* At boot this is done in prom.c. */
+	paca[lcpu].hw_cpu_id = pcpu;
+
+	status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
+			   pcpu, start_here, lcpu);
+	if (status != 0) {
+		printk(KERN_ERR "start-cpu failed: %i\n", status);
+		return 0;
+	}
+	return 1;
+}
+#else /* ... CONFIG_HOTPLUG_CPU */
+static inline int __devinit smp_startup_cpu(unsigned int lcpu)
+{
+	return 1;
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static inline void smp_xics_do_message(int cpu, int msg)
+{
+	set_bit(msg, &xics_ipi_message[cpu].value);
+	mb();
+	xics_cause_IPI(cpu);
+}
+
+static void smp_xics_message_pass(int target, int msg)
+{
+	unsigned int i;
+
+	if (target < NR_CPUS) {
+		smp_xics_do_message(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			smp_xics_do_message(i, msg);
+		}
+	}
+}
+
+extern void xics_request_IPIs(void);
+
+static int __init smp_xics_probe(void)
+{
+	xics_request_IPIs();
+
+	return cpus_weight(cpu_possible_map);
+}
+
+static void __devinit smp_xics_setup_cpu(int cpu)
+{
+	if (cpu != boot_cpuid)
+		xics_setup_cpu();
+}
+
+static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long timebase = 0;
+
+static void __devinit pSeries_give_timebase(void)
+{
+	spin_lock(&timebase_lock);
+	rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
+	timebase = get_tb();
+	spin_unlock(&timebase_lock);
+
+	while (timebase)
+		barrier();
+	rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
+}
+
+static void __devinit pSeries_take_timebase(void)
+{
+	while (!timebase)
+		barrier();
+	spin_lock(&timebase_lock);
+	set_tb(timebase >> 32, timebase & 0xffffffff);
+	timebase = 0;
+	spin_unlock(&timebase_lock);
+}
+
+static void __devinit pSeries_late_setup_cpu(int cpu)
+{
+	extern unsigned int default_distrib_server;
+
+	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+		vpa_init(cpu); 
+	}
+
+#ifdef CONFIG_IRQ_ALL_CPUS
+	/* Put the calling processor into the GIQ.  This is really only
+	 * necessary from a secondary thread as the OF start-cpu interface
+	 * performs this function for us on primary threads.
+	 */
+	/* TODO: 9005 is #defined in rtas-proc.c -- move to a header */
+	rtas_set_indicator(9005, default_distrib_server, 1);
+#endif
+}
+
+
+void __devinit smp_pSeries_kick_cpu(int nr)
+{
+	BUG_ON(nr < 0 || nr >= NR_CPUS);
+
+	if (!smp_startup_cpu(nr))
+		return;
+
+	/*
+	 * The processor is currently spinning, waiting for the
+	 * cpu_start field to become non-zero After we set cpu_start,
+	 * the processor will continue on to secondary_start
+	 */
+	paca[nr].cpu_start = 1;
+}
+
+static struct smp_ops_t pSeries_mpic_smp_ops = {
+	.message_pass	= smp_mpic_message_pass,
+	.probe		= smp_mpic_probe,
+	.kick_cpu	= smp_pSeries_kick_cpu,
+	.setup_cpu	= smp_mpic_setup_cpu,
+	.late_setup_cpu	= pSeries_late_setup_cpu,
+};
+
+static struct smp_ops_t pSeries_xics_smp_ops = {
+	.message_pass	= smp_xics_message_pass,
+	.probe		= smp_xics_probe,
+	.kick_cpu	= smp_pSeries_kick_cpu,
+	.setup_cpu	= smp_xics_setup_cpu,
+	.late_setup_cpu	= pSeries_late_setup_cpu,
+};
+
+/* This is called very early */
+void __init smp_init_pSeries(void)
+{
+	int ret, i;
+
+	DBG(" -> smp_init_pSeries()\n");
+
+	if (naca->interrupt_controller == IC_OPEN_PIC)
+		smp_ops = &pSeries_mpic_smp_ops;
+	else
+		smp_ops = &pSeries_xics_smp_ops;
+
+	/* Start secondary threads on SMT systems; primary threads
+	 * are already in the running state.
+	 */
+	for_each_present_cpu(i) {
+		if (query_cpu_stopped(get_hard_smp_processor_id(i)) == 0) {
+			printk("%16.16x : starting thread\n", i);
+			DBG("%16.16x : starting thread\n", i);
+			rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
+				  get_hard_smp_processor_id(i),
+				  __pa((u32)*((unsigned long *)
+					      pseries_secondary_smp_init)),
+				  i);
+		}
+	}
+
+	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+		vpa_init(boot_cpuid);
+
+	/* Non-lpar has additional take/give timebase */
+	if (systemcfg->platform == PLATFORM_PSERIES) {
+		smp_ops->give_timebase = pSeries_give_timebase;
+		smp_ops->take_timebase = pSeries_take_timebase;
+	}
+
+
+	DBG(" <- smp_init_pSeries()\n");
+}
+
diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
--- a/arch/ppc64/kernel/pacaData.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/pacaData.c	2004-10-28 22:25:59 -07:00
@@ -7,13 +7,12 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#include <asm/types.h>
-#include <asm/page.h>
-#include <stddef.h>
 #include <linux/config.h>
+#include <linux/types.h>
 #include <linux/threads.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
+#include <asm/page.h>
 
 #include <asm/iSeries/ItLpPaca.h>
 #include <asm/iSeries/ItLpQueue.h>
diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/pci.c	2004-10-28 22:25:59 -07:00
@@ -11,6 +11,8 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -39,6 +41,12 @@
 
 #include "pci.h"
 
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
 unsigned long pci_probe_only = 1;
 unsigned long pci_assign_all_buses = 0;
 
@@ -106,11 +114,11 @@
 			dev->resource[i].flags &= ~IORESOURCE_IO;
 	}
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105,
+			 fixup_windbond_82c105);
 
-void 
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
-			struct resource *res)
+void  pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+			      struct resource *res)
 {
 	unsigned long offset = 0;
 	struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
@@ -215,8 +223,7 @@
 /*
  * Allocate pci_controller(phb) initialized common variables.
  */
-struct pci_controller * __init
-pci_alloc_pci_controller(enum phb_types controller_type)
+struct pci_controller * __init pci_alloc_pci_controller(enum phb_types controller_type)
 {
 	struct pci_controller *hose;
 
@@ -246,8 +253,7 @@
 /*
  * Dymnamically allocate pci_controller(phb), initialize common variables.
  */
-struct pci_controller *
-pci_alloc_phb_dynamic(enum phb_types controller_type)
+struct pci_controller * pci_alloc_phb_dynamic(enum phb_types controller_type)
 {
 	struct pci_controller *hose;
 
@@ -430,9 +436,9 @@
  *
  * Returns negative error code on failure, zero on success.
  */
-static __inline__ int
-__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
-		       enum pci_mmap_state mmap_state)
+static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev,
+					     struct vm_area_struct *vma,
+					     enum pci_mmap_state mmap_state)
 {
 	struct pci_controller *hose = PCI_GET_PHB_PTR(dev);
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
@@ -487,9 +493,9 @@
  * Set vm_flags of VMA, as appropriate for this architecture, for a pci device
  * mapping.
  */
-static __inline__ void
-__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
-		     enum pci_mmap_state mmap_state)
+static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev,
+					    struct vm_area_struct *vma,
+					    enum pci_mmap_state mmap_state)
 {
 	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
 }
@@ -498,9 +504,10 @@
  * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
  * device mapping.
  */
-static __inline__ void
-__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
-		      enum pci_mmap_state mmap_state, int write_combine)
+static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev,
+					     struct vm_area_struct *vma,
+					     enum pci_mmap_state mmap_state,
+					     int write_combine)
 {
 	long prot = pgprot_val(vma->vm_page_prot);
 
@@ -569,7 +576,7 @@
 
 static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
 				      unsigned long phb_io_base_phys,
-				      void * phb_io_base_virt)
+				      void __iomem * phb_io_base_virt)
 {
 	struct isa_range *range;
 	unsigned long pci_addr;
@@ -578,9 +585,11 @@
 	int rlen = 0;
 
 	range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
-	if (rlen < sizeof(struct isa_range)) {
-		printk(KERN_ERR "unexpected isa range size: %s\n", 
-				__FUNCTION__);
+	if (range == NULL || (rlen < sizeof(struct isa_range))) {
+		printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
+		       "mapping 64k\n");
+		__ioremap_explicit(phb_io_base_phys, (unsigned long)phb_io_base_virt, 
+				   0x10000, _PAGE_NO_CACHE);
 		return;	
 	}
 	
@@ -613,7 +622,7 @@
 }
 
 void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-					struct device_node *dev)
+					    struct device_node *dev)
 {
 	unsigned int *ranges;
 	unsigned long size;
@@ -645,8 +654,9 @@
 			cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
 
 		size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
-
-		switch (ranges[0] >> 24) {
+		if (size == 0)
+			continue;
+		switch ((ranges[0] >> 24) & 0x3) {
 		case 1:		/* I/O space */
 			hose->io_base_phys = cpu_phys_addr;
 			hose->pci_io_size = size;
@@ -654,6 +664,8 @@
 			res = &hose->io_resource;
 			res->flags = IORESOURCE_IO;
 			res->start = pci_addr;
+			DBG("phb%d: IO 0x%lx -> 0x%lx\n", hose->global_number,
+				    res->start, res->start + size - 1);
 			break;
 		case 2:		/* memory space */
 			memno = 0;
@@ -666,6 +678,8 @@
 				res = &hose->mem_resources[memno];
 				res->flags = IORESOURCE_MEM;
 				res->start = cpu_phys_addr;
+				DBG("phb%d: MEM 0x%lx -> 0x%lx\n", hose->global_number,
+					    res->start, res->start + size - 1);
 			}
 			break;
 		}
@@ -729,6 +743,96 @@
 	res->end += io_virt_offset;
 }
 
+
+static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys,
+				unsigned long *start_virt, unsigned long *size)
+{
+	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+	struct pci_bus_region region;
+	struct resource *res;
+
+	if (bus->self) {
+		res = bus->resource[0];
+		pcibios_resource_to_bus(bus->self, &region, res);
+		*start_phys = hose->io_base_phys + region.start;
+		*start_virt = (unsigned long) hose->io_base_virt + 
+				region.start;
+		if (region.end > region.start) 
+			*size = region.end - region.start + 1;
+		else {
+			printk("%s(): unexpected region 0x%lx->0x%lx\n", 
+					__FUNCTION__, region.start, region.end);
+			return 1;
+		}
+		
+	} else {
+		/* Root Bus */
+		res = &hose->io_resource;
+		*start_phys = hose->io_base_phys;
+		*start_virt = (unsigned long) hose->io_base_virt;
+		if (res->end > res->start)
+			*size = res->end - res->start + 1;
+		else {
+			printk("%s(): unexpected region 0x%lx->0x%lx\n", 
+					__FUNCTION__, res->start, res->end);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int unmap_bus_range(struct pci_bus *bus)
+{
+	unsigned long start_phys;
+	unsigned long start_virt;
+	unsigned long size;
+
+	if (!bus) {
+		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
+		return 1;
+	}
+	
+	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
+		return 1;
+	if (iounmap_explicit((void __iomem *) start_virt, size))
+		return 1;
+
+	return 0;
+}
+EXPORT_SYMBOL(unmap_bus_range);
+
+int remap_bus_range(struct pci_bus *bus)
+{
+	unsigned long start_phys;
+	unsigned long start_virt;
+	unsigned long size;
+
+	if (!bus) {
+		printk(KERN_ERR "%s() expected bus\n", __FUNCTION__);
+		return 1;
+	}
+	
+	
+	if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
+		return 1;
+	printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
+	if (__ioremap_explicit(start_phys, start_virt, size, _PAGE_NO_CACHE))
+		return 1;
+
+	return 0;
+}
+EXPORT_SYMBOL(remap_bus_range);
+
+void phbs_remap_io(void)
+{
+	struct pci_controller *hose, *tmp;
+
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+		remap_bus_range(hose->bus);
+}
+
+
 /*********************************************************************** 
  * pci_find_hose_for_OF_device
  *
@@ -761,6 +865,9 @@
        else
                busdn = bus->sysdata;   /* must be a phb */
 
+       if (busdn == NULL)
+	       return 0;
+
        /*
         * Check to see if there is any of the 8 functions are in the
         * device tree.  If they are then we need to scan all the
@@ -783,7 +890,8 @@
 
 	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 		if (dev->resource[i].flags & IORESOURCE_IO) {
-			unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+			unsigned long offset = (unsigned long)hose->io_base_virt
+				- pci_io_base;
                         unsigned long start, end, mask;
 
                         start = dev->resource[i].start += offset;
diff -Nru a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
--- a/arch/ppc64/kernel/pci_dn.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/pci_dn.c	2004-10-28 22:25:59 -07:00
@@ -46,29 +46,13 @@
 {
 	struct pci_controller *phb = data;
 	u32 *regs;
-	char *device_type = get_property(dn, "device_type", NULL);
-	char *model;
 
 	dn->phb = phb;
-	if (device_type && (strcmp(device_type, "pci") == 0) &&
-			(get_property(dn, "class-code", NULL) == 0)) {
-		/* special case for PHB's.  Sigh. */
-		regs = (u32 *)get_property(dn, "bus-range", NULL);
-		dn->busno = regs[0];
-
-		model = (char *)get_property(dn, "model", NULL);
-
-		if (strstr(model, "U3"))
-			dn->devfn = -1;
-		else
-			dn->devfn = 0;	/* assumption */
-	} else {
-		regs = (u32 *)get_property(dn, "reg", NULL);
-		if (regs) {
-			/* First register entry is addr (00BBSS00)  */
-			dn->busno = (regs[0] >> 16) & 0xff;
-			dn->devfn = (regs[0] >> 8) & 0xff;
-		}
+	regs = (u32 *)get_property(dn, "reg", NULL);
+	if (regs) {
+		/* First register entry is addr (00BBSS00)  */
+		dn->busno = (regs[0] >> 16) & 0xff;
+		dn->devfn = (regs[0] >> 8) & 0xff;
 	}
 	return NULL;
 }
@@ -97,20 +81,25 @@
 	struct device_node *dn, *nextdn;
 	void *ret;
 
-	if (pre && ((ret = pre(start, data)) != NULL))
-		return ret;
+	/* We started with a phb, iterate all childs */
 	for (dn = start->child; dn; dn = nextdn) {
+		u32 *classp, class;
+
 		nextdn = NULL;
-		if (get_property(dn, "class-code", NULL)) {
-			if (pre && ((ret = pre(dn, data)) != NULL))
-				return ret;
-			if (dn->child)
-				/* Depth first...do children */
-				nextdn = dn->child;
-			else if (dn->sibling)
-				/* ok, try next sibling instead. */
-				nextdn = dn->sibling;
-		}
+		classp = (u32 *)get_property(dn, "class-code", NULL);
+		class = classp ? *classp : 0;
+
+		if (pre && ((ret = pre(dn, data)) != NULL))
+			return ret;
+
+		/* If we are a PCI bridge, go down */
+		if (dn->child && ((class >> 8) == PCI_CLASS_BRIDGE_PCI ||
+				  (class >> 8) == PCI_CLASS_BRIDGE_CARDBUS))
+			/* Depth first...do children */
+			nextdn = dn->child;
+		else if (dn->sibling)
+			/* ok, try next sibling instead. */
+			nextdn = dn->sibling;
 		if (!nextdn) {
 			/* Walk up to next valid sibling. */
 			do {
@@ -124,26 +113,16 @@
 	return NULL;
 }
 
-/*
- * Same as traverse_pci_devices except this does it for all phbs.
- */
-static void *traverse_all_pci_devices(traverse_func pre)
+void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
 {
-	struct pci_controller *phb, *tmp;
-	void *ret;
+	struct device_node * dn = (struct device_node *) phb->arch_data;
 
-	list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
-		if ((ret = traverse_pci_devices(phb->arch_data, pre, phb))
-				!= NULL)
-			return ret;
-	return NULL;
-}
+	/* PHB nodes themselves must not match */
+	dn->devfn = dn->busno = -1;
+	dn->phb = phb;
 
-void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
-{
 	/* Update dn->phb ptrs for new phb and children devices */
-	traverse_pci_devices((struct device_node *)phb->arch_data,
-			update_dn_pci_info, phb);
+	traverse_pci_devices(dn, update_dn_pci_info, phb);
 }
 
 /*
@@ -154,6 +133,7 @@
 {
 	int busno = ((unsigned long)data >> 8) & 0xff;
 	int devfn = ((unsigned long)data) & 0xff;
+
 	return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL;
 }
 
@@ -180,10 +160,8 @@
 
 	phb_dn = phb->arch_data;
 	dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval);
-	if (dn) {
+	if (dn)
 		dev->sysdata = dn;
-		/* ToDo: call some device init hook here */
-	}
 	return dn;
 }
 EXPORT_SYMBOL(fetch_dev_dn);
@@ -195,8 +173,11 @@
  */
 void __init pci_devs_phb_init(void)
 {
+	struct pci_controller *phb, *tmp;
+
 	/* This must be done first so the device nodes have valid pci info! */
-	traverse_all_pci_devices(update_dn_pci_info);
+	list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
+		pci_devs_phb_init_dynamic(phb);
 }
 
 
diff -Nru a/arch/ppc64/kernel/pmac.h b/arch/ppc64/kernel/pmac.h
--- a/arch/ppc64/kernel/pmac.h	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/pmac.h	2004-10-28 22:25:58 -07:00
@@ -18,7 +18,6 @@
 extern void pmac_pcibios_fixup(void);
 extern void pmac_pci_init(void);
 extern void pmac_setup_pci_dma(void);
-extern void fixup_k2_sata(struct pci_dev* dev);
 extern void pmac_check_ht_link(void);
 
 extern void pmac_setup_smp(void);
diff -Nru a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
--- a/arch/ppc64/kernel/pmac_pci.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/pmac_pci.c	2004-10-28 22:25:58 -07:00
@@ -46,7 +46,6 @@
  * assuming we won't have both UniNorth and Bandit */
 static int has_uninorth;
 static struct pci_controller *u3_agp;
-u8 pci_cache_line_size;
 struct pci_dev *k2_skiplist[2];
 
 static int __init fixup_one_level_bus_range(struct device_node *node, int higher)
@@ -150,16 +149,9 @@
 				      int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	struct device_node *busdn;
 	unsigned long addr;
 
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
-	if (busdn == NULL)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	hose = busdn->phb;
+	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -188,16 +180,9 @@
 				       int offset, int len, u32 val)
 {
 	struct pci_controller *hose;
-	struct device_node *busdn;
 	unsigned long addr;
 
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
-	if (busdn == NULL)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	hose = busdn->phb;
+	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -236,14 +221,44 @@
  * implement self-view of the HT host yet
  */
 
-static int skip_k2_device(struct pci_bus *bus, unsigned int devfn)
+/*
+ * This function deals with some "special cases" devices.
+ *
+ *  0 -> No special case
+ *  1 -> Skip the device but act as if the access was successfull
+ *       (return 0xff's on reads, eventually, cache config space
+ *       accesses in a later version)
+ * -1 -> Hide the device (unsuccessful acess)
+ */
+static int u3_ht_skip_device(struct pci_controller *hose,
+			     struct pci_bus *bus, unsigned int devfn)
 {
+	struct device_node *busdn, *dn;
 	int i;
 
+	/*
+	 * When a device in K2 is powered down, we die on config
+	 * cycle accesses. Fix that here.
+	 */
 	for (i=0; i<2; i++)
 		if (k2_skiplist[i] && k2_skiplist[i]->bus == bus &&
 		    k2_skiplist[i]->devfn == devfn)
 			return 1;
+
+	/* We only allow config cycles to devices that are in OF device-tree
+	 * as we are apparently having some weird things going on with some
+	 * revs of K2 on recent G5s
+	 */
+	if (bus->self)
+		busdn = pci_device_to_OF_node(bus->self);
+	else
+		busdn = hose->arch_data;
+	for (dn = busdn->child; dn; dn = dn->sibling)
+		if (dn->devfn == devfn)
+			break;
+	if (dn == NULL)
+		return -1;
+
 	return 0;
 }
 
@@ -259,8 +274,7 @@
 {
 	if (bus == hose->first_busno) {
 		/* For now, we don't self probe U3 HT bridge */
-		if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 ||
-		    PCI_SLOT(devfn) < 1)
+		if (PCI_SLOT(devfn) == 0)
 			return 0;
 		return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
 	} else
@@ -271,39 +285,21 @@
 				    int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	struct device_node *busdn, *dn;
 	unsigned long addr;
 
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
-	if (busdn == NULL)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	hose = busdn->phb;
-	if (hose == NULL)
-		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	/* We only allow config cycles to devices that are in OF device-tree
-	 * as we are apparently having some weird things going on with some
-	 * revs of K2 on recent G5s
-	 */
-	for (dn = busdn->child; dn; dn = dn->sibling)
-		if (dn->devfn == devfn)
-			break;
-	if (dn == NULL)
+	hose = pci_bus_to_host(bus);      
+	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	/*
-	 * When a device in K2 is powered down, we die on config
-	 * cycle accesses. Fix that here. We may ultimately want
-	 * to cache the config space for those instead of returning
-	 * 0xffffffff's to make life easier to HW detection tools
-	 */
-	if (skip_k2_device(bus, devfn)) {
+
+	switch (u3_ht_skip_device(hose, bus, devfn)) {
+	case 0:
+		break;
+	case 1:
 		switch (len) {
 		case 1:
 			*val = 0xff; break;
@@ -313,6 +309,8 @@
 			*val = 0xfffffffful; break;
 		}
 		return PCIBIOS_SUCCESSFUL;
+	default:
+		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
 
 	/*
@@ -337,28 +335,24 @@
 				     int offset, int len, u32 val)
 {
 	struct pci_controller *hose;
-	struct device_node *busdn;
 	unsigned long addr;
 
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
-	if (busdn == NULL)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	hose = busdn->phb;
+	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	/*
-	 * When a device in K2 is powered down, we die on config
-	 * cycle accesses. Fix that here.
-	 */
-	if (skip_k2_device(bus, devfn))
+
+	switch (u3_ht_skip_device(hose, bus, devfn)) {
+	case 0:
+		break;
+	case 1:
 		return PCIBIOS_SUCCESSFUL;
+	default:
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
 
 	/*
 	 * Note: the caller has already checked that offset is
@@ -675,7 +669,6 @@
 	pci_fix_bus_sysdata();
 
 	iommu_setup_u3();
-
 }
 
 static void __init pmac_fixup_phb_resources(void)
@@ -750,11 +743,6 @@
 	/* Tell pci.c to use the common resource allocation mecanism */
 	pci_probe_only = 0;
 	
-	/* HT don't do more than 64 bytes transfers. FIXME: Deal with
-	 * the exception of U3/AGP (hook into pci_set_mwi)
-	 */
-	pci_cache_line_size = 16; /* 64 bytes */
-
 	/* Allow all IO */
 	io_page_mask = -1;
 }
@@ -763,7 +751,7 @@
  * Disable second function on K2-SATA, it's broken
  * and disable IO BARs on first one
  */
-void fixup_k2_sata(struct pci_dev* dev)
+static void fixup_k2_sata(struct pci_dev* dev)
 {
 	int i;
 	u16 cmd;
diff -Nru a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
--- a/arch/ppc64/kernel/pmac_setup.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/pmac_setup.c	2004-10-28 22:25:57 -07:00
@@ -72,6 +72,7 @@
 #include <asm/lmb.h>
 
 #include "pmac.h"
+#include "mpic.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -319,29 +320,9 @@
 	DBG(" <- pmac_init_early\n");
 }
 
-extern void* OpenPIC_Addr;
-extern void* OpenPIC2_Addr;
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-extern void openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
-			 int programmer_switch_irq);
-extern void openpic2_init(int offset);
-extern int openpic_get_irq(struct pt_regs *regs);
-extern int openpic2_get_irq(struct pt_regs *regs);
-
-static int pmac_cascade_irq = -1;
-
-static irqreturn_t pmac_u3_do_cascade(int cpl, void *dev_id, struct pt_regs *regs)
-{
-	int irq;
-
-	for (;;) {
-		irq = openpic2_get_irq(regs);
-		if (irq == -1)
-			break;
-		ppc_irq_dispatch_handler(regs, irq);
-	}
-	return IRQ_HANDLED;
+static int pmac_u3_cascade(struct pt_regs *regs, void *data)
+{
+	return mpic_get_one_irq((struct mpic *)data, regs);
 }
 
 static __init void pmac_init_IRQ(void)
@@ -349,6 +330,7 @@
         struct device_node *irqctrler  = NULL;
         struct device_node *irqctrler2 = NULL;
 	struct device_node *np = NULL;
+	struct mpic *mpic1, *mpic2;
 
 	/* We first try to detect Apple's new Core99 chipset, since mac-io
 	 * is quite different on those machines and contains an IBM MPIC2.
@@ -368,44 +350,37 @@
 		       (unsigned int)irqctrler->addrs[0].address);
 
 		prom_get_irq_senses(senses, 0, 128);
-		OpenPIC_InitSenses = senses;
-		OpenPIC_NumInitSenses = 128;
-		OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
-				       irqctrler->addrs[0].size);
-		openpic_init(1, 0, NULL, -1);
+		mpic1 = mpic_alloc(irqctrler->addrs[0].address,
+				   MPIC_PRIMARY | MPIC_WANTS_RESET,
+				   0, 0, 128, 256, senses, 128, " K2-MPIC  ");
+		BUG_ON(mpic1 == NULL);
+		mpic_init(mpic1);		
 
 		if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
 		    irqctrler2->n_addrs > 0) {
 			printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
 			       (u32)irqctrler2->addrs[0].address,
 			       irqctrler2->intrs[0].line);
+
 			pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
-			OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,
-						irqctrler2->addrs[0].size);
 			prom_get_irq_senses(senses, 128, 128 + 128);
-			OpenPIC_InitSenses = senses;
-			OpenPIC_NumInitSenses = 128;
-			openpic2_init(128);
-			pmac_cascade_irq = irqctrler2->intrs[0].line;
+
+			/* We don't need to set MPIC_BROKEN_U3 here since we don't have
+			 * hypertransport interrupts routed to it
+			 */
+			mpic2 = mpic_alloc(irqctrler2->addrs[0].address,
+					   MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
+					   0, 128, 128, 0, senses, 128, " U3-MPIC  ");
+			BUG_ON(mpic2 == NULL);
+			mpic_init(mpic2);
+			mpic_setup_cascade(irqctrler2->intrs[0].line,
+					   pmac_u3_cascade, mpic2);
 		}
 	}
 	of_node_put(irqctrler);
 	of_node_put(irqctrler2);
 }
 
-/* We cannot do request_irq too early ... Right now, we get the
- * cascade as a core_initcall, which should be fine for our needs
- */
-static int __init pmac_irq_cascade_init(void)
-{
-	if (request_irq(pmac_cascade_irq, pmac_u3_do_cascade, 0,
-			"U3->K2 Cascade", NULL))
-		printk(KERN_ERR "Unable to get OpenPIC IRQ for cascade\n");
-	return 0;
-}
-
-core_initcall(pmac_irq_cascade_init);
-
 static void __init pmac_progress(char *s, unsigned short hex)
 {
 	if (sccdbg) {
@@ -420,6 +395,15 @@
 #endif /* CONFIG_BOOTX_TEXT */
 }
 
+/*
+ * pmac has no legacy IO, anything calling this function has to
+ * fail or bad things will happen
+ */
+static int pmac_check_legacy_ioport(unsigned int baseport)
+{
+	return -ENODEV;
+}
+
 static int __init pmac_declare_of_platform_devices(void)
 {
 	struct device_node *np;
@@ -463,7 +447,7 @@
 	.init_early		= pmac_init_early,
        	.get_cpuinfo		= pmac_show_cpuinfo,
 	.init_IRQ		= pmac_init_IRQ,
-	.get_irq		= openpic_get_irq,
+	.get_irq		= mpic_get_irq,
 	.pcibios_fixup		= pmac_pcibios_fixup,
 	.restart		= pmac_restart,
 	.power_off		= pmac_power_off,
@@ -474,4 +458,5 @@
       	.calibrate_decr		= pmac_calibrate_decr,
 	.feature_call		= pmac_do_feature_call,
 	.progress		= pmac_progress,
+	.check_legacy_ioport	= pmac_check_legacy_ioport
 };
diff -Nru a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
--- a/arch/ppc64/kernel/pmac_smp.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc64/kernel/pmac_smp.c	2004-10-28 22:25:56 -07:00
@@ -21,6 +21,9 @@
  *  as published by the Free Software Foundation; either version
  *  2 of the License, or (at your option) any later version.
  */
+
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -32,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -48,14 +52,18 @@
 #include <asm/cacheflush.h>
 #include <asm/keylargo.h>
 
-#include "open_pic.h"
+#include "mpic.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
 extern void pmac_secondary_start_1(void);
 extern void pmac_secondary_start_2(void);
 extern void pmac_secondary_start_3(void);
 
-extern void smp_openpic_message_pass(int target, int msg);
-
 extern struct smp_ops_t *smp_ops;
 
 static int __init smp_core99_probe(void)
@@ -75,7 +83,7 @@
 	printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus);
 
 	if (ncpus > 1)
-		openpic_request_IPIs();
+		mpic_request_ipis();
 
 	return ncpus;
 }
@@ -102,15 +110,16 @@
 	 *   b .pmac_secondary_start - KERNELBASE
 	 */
 	switch(nr) {
-		case 1:
-			new_vector = (unsigned long)pmac_secondary_start_1;
-			break;
-		case 2:
-			new_vector = (unsigned long)pmac_secondary_start_2;
-			break;
-		case 3:
-			new_vector = (unsigned long)pmac_secondary_start_3;
-			break;
+	case 1:
+		new_vector = (unsigned long)pmac_secondary_start_1;
+		break;
+	case 2:
+		new_vector = (unsigned long)pmac_secondary_start_2;
+		break;			
+	case 3:
+	default:
+		new_vector = (unsigned long)pmac_secondary_start_3;
+		break;
 	}
 	*vector = 0x48000002 + (new_vector - KERNELBASE);
 
@@ -138,8 +147,8 @@
 
 static void __init smp_core99_setup_cpu(int cpu_nr)
 {
-	/* Setup openpic */
-	do_openpic_setup_cpu();
+	/* Setup MPIC */
+	mpic_setup_this_cpu();
 
 	if (cpu_nr == 0) {
 		extern void g5_phy_disable_cpu1(void);
@@ -149,15 +158,12 @@
 		 */
 		if (num_online_cpus() < 2)		
 			g5_phy_disable_cpu1();
-		if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+		if (ppc_md.progress) ppc_md.progress("smp_core99_setup_cpu 0 done", 0x349);
 	}
 }
 
-extern void smp_generic_give_timebase(void);
-extern void smp_generic_take_timebase(void);
-
 struct smp_ops_t core99_smp_ops __pmacdata = {
-	.message_pass	= smp_openpic_message_pass,
+	.message_pass	= smp_mpic_message_pass,
 	.probe		= smp_core99_probe,
 	.kick_cpu	= smp_core99_kick_cpu,
 	.setup_cpu	= smp_core99_setup_cpu,
diff -Nru a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c
--- a/arch/ppc64/kernel/proc_ppc64.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/proc_ppc64.c	2004-10-28 22:25:58 -07:00
@@ -33,7 +33,8 @@
 #include <asm/prom.h>
 
 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 ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
+			      loff_t *ppos);
 static int     page_map_mmap( struct file *file, struct vm_area_struct *vma );
 
 static struct file_operations page_map_fops = {
@@ -161,7 +162,8 @@
 	return (file->f_pos = new);
 }
 
-static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
+			      loff_t *ppos)
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
 	return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
@@ -208,7 +210,8 @@
  * whole nodes along with their properties.  Operations on individual
  * properties are not implemented (yet).
  */
-static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
+static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count,
+			  loff_t *off)
 {
 	int rv = 0;
 	char *kbuf;
@@ -302,7 +305,8 @@
 	return rv;
 }
 
-static struct property *new_property(const char *name, const int length, const unsigned char *value, struct property *last)
+static struct property *new_property(const char *name, const int length,
+				     const unsigned char *value, struct property *last)
 {
 	struct property *new = kmalloc(sizeof(*new), GFP_KERNEL);
 
@@ -343,7 +347,8 @@
  * this function does no allocation or copying of the data.  Return value
  * is set to the next name in buf, or NULL on error.
  */
-static char * parse_next_property(char *buf, char *end, char **name, int *length, unsigned char **value)
+static char * parse_next_property(char *buf, char *end, char **name, int *length,
+				  unsigned char **value)
 {
 	char *tmp;
 
@@ -351,13 +356,15 @@
 
 	tmp = strchr(buf, ' ');
 	if (!tmp) {
-		printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__);
+		printk(KERN_ERR "property parse failed in %s at line %d\n",
+		       __FUNCTION__, __LINE__);
 		return NULL;
 	}
 	*tmp = '\0';
 
 	if (++tmp >= end) {
-		printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__);
+		printk(KERN_ERR "property parse failed in %s at line %d\n",
+		       __FUNCTION__, __LINE__);
 		return NULL;
 	}
 
@@ -365,11 +372,13 @@
 	*length = -1;
 	*length = simple_strtoul(tmp, &tmp, 10);
 	if (*length == -1) {
-		printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__);
+		printk(KERN_ERR "property parse failed in %s at line %d\n", 
+		       __FUNCTION__, __LINE__);
 		return NULL;
 	}
 	if (*tmp != ' ' || ++tmp >= end) {
-		printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__);
+		printk(KERN_ERR "property parse failed in %s at line %d\n",
+		       __FUNCTION__, __LINE__);
 		return NULL;
 	}
 
@@ -377,11 +386,13 @@
 	*value = tmp;
 	tmp += *length;
 	if (tmp > end) {
-		printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__);
+		printk(KERN_ERR "property parse failed in %s at line %d\n",
+		       __FUNCTION__, __LINE__);
 		return NULL;
 	}
 	else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
-		printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__);
+		printk(KERN_ERR "property parse failed in %s at line %d\n",
+		       __FUNCTION__, __LINE__);
 		return NULL;
 	}
 	tmp++;
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/prom.c	2004-10-28 22:25:58 -07:00
@@ -52,7 +52,6 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
-#include "open_pic.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -1092,8 +1091,7 @@
  * Work out the sense (active-low level / active-high edge)
  * of each interrupt from the device tree.
  */
-void __init
-prom_get_irq_senses(unsigned char *senses, int off, int max)
+void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
 {
 	struct device_node *np;
 	int i, j;
@@ -1105,7 +1103,9 @@
 		for (j = 0; j < np->n_intrs; j++) {
 			i = np->intrs[j].line;
 			if (i >= off && i < max)
-				senses[i-off] = np->intrs[j].sense;
+				senses[i-off] = np->intrs[j].sense ?
+					IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
+					IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
 		}
 	}
 }
@@ -1817,6 +1817,14 @@
 		of_node_put(child);
 		return -EBUSY;
 	}
+
+	/* XXX This is a layering violation, should be moved to the caller
+	 * --BenH.
+	 */
+#ifdef CONFIG_PPC_PSERIES
+	if (np->iommu_table)
+		iommu_free_table(np);
+#endif /* CONFIG_PPC_PSERIES */
 
 	write_lock(&devtree_lock);
 	OF_MARK_STALE(np);
diff -Nru a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
--- a/arch/ppc64/kernel/prom_init.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/prom_init.c	2004-10-28 22:25:59 -07:00
@@ -51,7 +51,6 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
-#include "open_pic.h"
 
 #ifdef CONFIG_LOGO_LINUX_CLUT224
 #include <linux/linux_logo.h>
@@ -160,8 +159,6 @@
 
 extern unsigned long klimit;
 
-//int global_width = 640, global_height = 480, global_depth = 8, global_pitch;
-//unsigned global_address;
 /* prom structure */
 static struct prom_t __initdata prom;
 
@@ -706,46 +703,50 @@
 	struct prom_t *_prom = PTRRELOC(&prom);
 	phandle prom_rtas;
 	u64 base, entry = 0;
-        u32 size;
+        u32 size = 0;
 
 	prom_debug("prom_instantiate_rtas: start...\n");
 
 	prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-	if (prom_rtas != (phandle) -1) {
-		prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
-		if (size != 0) {
-			base = alloc_down(size, PAGE_SIZE, 0);
-			if (base == 0) {
-				prom_printf("RTAS allocation failed !\n");
-				return;
-			}
-			prom_printf("instantiating rtas at 0x%x", base);
+	prom_debug("prom_rtas: %x\n", prom_rtas);
+	if (prom_rtas == (phandle) -1)
+		return;
 
-			prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
-			prom_printf("...");
+	prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
+	if (size == 0)
+		return;
 
-			if (call_prom("call-method", 3, 2,
-				      ADDR("instantiate-rtas"),
-				      prom_rtas, base) != PROM_ERROR) {
-				entry = (long)_prom->args.rets[1];
-			}
-			if (entry == 0) {
-				prom_printf(" failed\n");
-				return;
-			}
-			prom_printf(" done\n");
+	base = alloc_down(size, PAGE_SIZE, 0);
+	if (base == 0) {
+		prom_printf("RTAS allocation failed !\n");
+		return;
+	}
+	prom_printf("instantiating rtas at 0x%x", base);
 
-	       		reserve_mem(base, size);
-		}
+	prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
+	prom_printf("...");
 
-		prom_setprop(_prom->chosen, "linux,rtas-base", &base, sizeof(base));
-		prom_setprop(_prom->chosen, "linux,rtas-entry", &entry, sizeof(entry));
-		prom_setprop(_prom->chosen, "linux,rtas-size", &size, sizeof(size));
-
-		prom_debug("rtas base     = 0x%x\n", base);
-		prom_debug("rtas entry    = 0x%x\n", entry);
-		prom_debug("rtas size     = 0x%x\n", (long)size);
+	if (call_prom("call-method", 3, 2,
+		      ADDR("instantiate-rtas"),
+		      prom_rtas, base) != PROM_ERROR) {
+		entry = (long)_prom->args.rets[1];
 	}
+	if (entry == 0) {
+		prom_printf(" failed\n");
+		return;
+	}
+	prom_printf(" done\n");
+
+	reserve_mem(base, size);
+
+	prom_setprop(_prom->chosen, "linux,rtas-base", &base, sizeof(base));
+	prom_setprop(_prom->chosen, "linux,rtas-entry", &entry, sizeof(entry));
+	prom_setprop(_prom->chosen, "linux,rtas-size", &size, sizeof(size));
+
+	prom_debug("rtas base     = 0x%x\n", base);
+	prom_debug("rtas entry    = 0x%x\n", entry);
+	prom_debug("rtas size     = 0x%x\n", (long)size);
+
 	prom_debug("prom_instantiate_rtas: end...\n");
 }
 
@@ -952,9 +953,9 @@
 			continue;
 
 		/* Skip non-configured cpus. */
-		prom_getprop(node, "status", type, sizeof(type));
-		if (strcmp(type, RELOC("okay")) != 0)
-			continue;
+		if (prom_getprop(node, "status", type, sizeof(type)) > 0)
+			if (strcmp(type, RELOC("okay")) != 0)
+				continue;
 
 		reg = -1;
 		prom_getprop(node, "reg", &reg, sizeof(reg));
@@ -994,7 +995,8 @@
 				  secondary_hold, cpuid);
 
 			for ( i = 0 ; (i < 100000000) && 
-			      (*acknowledge == ((unsigned long)-1)); i++ ) ;
+			      (*acknowledge == ((unsigned long)-1)); i++ )
+				mb();
 
 			if (*acknowledge == cpuid) {
 				prom_printf("done\n");
@@ -1130,6 +1132,8 @@
 			if (strstr(p, RELOC("Power Macintosh")) ||
 			    strstr(p, RELOC("MacRISC4")))
 				return PLATFORM_POWERMAC;
+			if (strstr(p, RELOC("Momentum,Maple")))
+				return PLATFORM_MAPLE;
 			i += sl + 1;
 		}
 	}
@@ -1161,7 +1165,7 @@
  * So we check whether we will need to open the display,
  * and if so, open it now.
  */
-static unsigned long __init prom_check_displays(void)
+static void __init prom_check_displays(void)
 {
 	unsigned long offset = reloc_offset();
 	struct prom_t *_prom = PTRRELOC(&prom);
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/rtas.c	2004-10-28 22:25:57 -07:00
@@ -516,7 +516,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 /* This version can't take the spinlock, because it never returns */
 
 struct rtas_args rtas_stop_self_args = {
@@ -541,7 +540,6 @@
 
 	panic("Alas, I survived.\n");
 }
-#endif /* CONFIG_HOTPLUG_CPU */
 
 /*
  * Return the firmware-specified size of the error log buffer
diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c
--- a/arch/ppc64/kernel/rtas_flash.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/rtas_flash.c	2004-10-28 22:25:59 -07:00
@@ -562,6 +562,7 @@
 		validate_flash(args_buf);
 	}
 
+	/* The matching atomic_inc was in rtas_excl_open() */
 	atomic_dec(&dp->count);
 
 	return 0;
@@ -572,7 +573,8 @@
 	if (dp) {
 		if (dp->data != NULL)
 			kfree(dp->data);
-		remove_proc_entry(dp->name, NULL);
+		dp->owner = NULL;
+		remove_proc_entry(dp->name, dp->parent);
 	}
 }
 
diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
--- a/arch/ppc64/kernel/rtasd.c	2004-10-28 22:25:57 -07:00
+++ b/arch/ppc64/kernel/rtasd.c	2004-10-28 22:25:57 -07:00
@@ -275,7 +275,7 @@
  * know that we can safely clear the events in NVRAM.
  * Next we'll sit and wait for something else to log.
  */
-static ssize_t rtas_log_read(struct file * file, char * buf,
+static ssize_t rtas_log_read(struct file * file, char __user * buf,
 			 size_t count, loff_t *ppos)
 {
 	int error;
diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
--- a/arch/ppc64/kernel/setup.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/setup.c	2004-10-28 22:25:58 -07:00
@@ -30,6 +30,8 @@
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/unistd.h>
+#include <linux/serial.h>
+#include <linux/8250.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -51,6 +53,7 @@
 #include <asm/system.h>
 #include <asm/rtas.h>
 #include <asm/iommu.h>
+#include <asm/serial.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -72,11 +75,14 @@
 extern void udbg_init_pmac_realmode(void);
 /* That's RTAS panel debug */
 extern void call_rtas_display_status_delay(unsigned char c);
+/* Here's maple real mode debug */
+extern void udbg_init_maple_realmode(void);
 
 #define EARLY_DEBUG_INIT() do {} while(0)
 
 #if 0
 #define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
+#define EARLY_DEBUG_INIT() udbg_init_maple_realmode()
 #define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
 #define EARLY_DEBUG_INIT()						\
 	do { ppc_md.udbg_putc = call_rtas_display_status_delay; } while(0)
@@ -323,6 +329,7 @@
 
 extern struct machdep_calls pSeries_md;
 extern struct machdep_calls pmac_md;
+extern struct machdep_calls maple_md;
 
 /* Ultimately, stuff them in an elf section like initcalls... */
 static struct machdep_calls __initdata *machines[] = {
@@ -332,6 +339,9 @@
 #ifdef CONFIG_PPC_PMAC
 	&pmac_md,
 #endif /* CONFIG_PPC_PMAC */
+#ifdef CONFIG_PPC_MAPLE
+	&maple_md,
+#endif /* CONFIG_PPC_MAPLE */
 	NULL
 };
 
@@ -630,6 +640,7 @@
 	printk("naca->debug_switch            = 0x%lx\n", naca->debug_switch);
 	printk("naca->interrupt_controller    = 0x%ld\n", naca->interrupt_controller);
 	printk("systemcfg                     = 0x%p\n", systemcfg);
+	printk("systemcfg->platform           = 0x%x\n", systemcfg->platform);
 	printk("systemcfg->processorCount     = 0x%lx\n", systemcfg->processorCount);
 	printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
 	printk("systemcfg->dCacheL1LineSize   = 0x%x\n", systemcfg->dCacheL1LineSize);
@@ -783,12 +794,11 @@
 #ifdef CONFIG_PPC_MULTIPLATFORM
 static int __init set_preferred_console(void)
 {
-	struct device_node *prom_stdout;
+	struct device_node *prom_stdout = NULL;
 	char *name;
+	u32 *spd;
 	int offset = 0;
-#if  0
-	phandle *stdout_ph;
-#endif
+
 	DBG(" -> set_preferred_console()\n");
 
 	/* The user has requested a console so this is already set up. */
@@ -802,20 +812,7 @@
 		return -ENODEV;
 	}
 	/* We are getting a weird phandle from OF ... */
-#if 0
-	stdout_ph = (phandle *)get_property(of_chosen, "linux,stdout-package", NULL);
-	if (stdout_ph == NULL) {
-		DBG(" no linux,stdout-package !\n");
-		return -ENODEV;
-	}
-	prom_stdout = of_find_node_by_phandle(*stdout_ph);
-	if (!prom_stdout) {
-		DBG(" can't find stdout package for phandle 0x%x !\n", *stdout_ph);
-		return -ENODEV;
-	}
-#endif
 	/* ... So use the full path instead */
-#if 1
 	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
 	if (name == NULL) {
 		DBG(" no linux,stdout-path !\n");
@@ -826,7 +823,6 @@
 		DBG(" can't find stdout package %s !\n", name);
 		return -ENODEV;
 	}	
-#endif
 	DBG("stdout is %s\n", prom_stdout->full_name);
 
 	name = (char *)get_property(prom_stdout, "name", NULL);
@@ -834,8 +830,12 @@
 		DBG(" stdout package has no name !\n");
 		goto not_found;
 	}
+	spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
 
-	if (strcmp(name, "serial") == 0) {
+	if (0)
+		;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+	else if (strcmp(name, "serial") == 0) {
 		int i;
 		u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
 		if (i > 8) {
@@ -858,6 +858,7 @@
 			}
 		}
 	}
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
 #ifdef CONFIG_PPC_PSERIES
 	else if (strcmp(name, "vty") == 0) {
  		u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
@@ -887,17 +888,24 @@
  		}
 	}
 #endif /* CONFIG_PPC_PSERIES */
+#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
 	else if (strcmp(name, "ch-a") == 0)
 		offset = 0;
 	else if (strcmp(name, "ch-b") == 0)
 		offset = 1;
+#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
 	else
 		goto not_found;
 	of_node_put(prom_stdout);
 
 	DBG("Found serial console at ttyS%d\n", offset);
 
-	return add_preferred_console("ttyS", offset, NULL);
+	if (spd) {
+		char opt[16];
+		sprintf(opt, "%d", *spd);
+		return add_preferred_console("ttyS", offset, opt);
+	} else
+		return add_preferred_console("ttyS", offset, NULL);
 
  not_found:
 	DBG("No preferred console found !\n");
@@ -1106,15 +1114,209 @@
 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
 __setup("decr_overclock=", set_decr_overclock );
 
+#ifndef CONFIG_PPC_ISERIES
+/*
+ * This function can be used by platforms to "find" legacy serial ports.
+ * It works for "serial" nodes under an "isa" node, and will try to
+ * respect the "ibm,aix-loc" property if any. It works with up to 8
+ * ports.
+ */
+
+#define MAX_LEGACY_SERIAL_PORTS	8
+static struct old_serial_port	old_serial_ports[MAX_LEGACY_SERIAL_PORTS];
+static unsigned int		old_serial_count;
+
+void __init generic_find_legacy_serial_ports(unsigned int *default_speed)
+{
+	struct device_node *np;
+	u32 *sizeprop;
+
+	struct isa_reg_property {
+		u32 space;
+		u32 address;
+		u32 size;
+	};
+	struct pci_reg_property {
+		struct pci_address addr;
+		u32 size_hi;
+		u32 size_lo;
+	};                                                                        
+
+	DBG(" -> generic_find_legacy_serial_port()\n");
+
+	naca->serialPortAddr = 0;
+	if (default_speed)
+		*default_speed = 0;
+
+	np = of_find_node_by_path("/");
+	if (!np)
+		return;
+
+	/* First fill our array */
+	for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
+		struct device_node *isa, *pci;
+		struct isa_reg_property *reg;
+		unsigned long phys_size, addr_size, io_base;
+		u32 *rangesp;
+		u32 *interrupts, *clk, *spd;
+		char *typep;
+		int index, rlen, rentsize;
+
+		/* Ok, first check if it's under an "isa" parent */
+		isa = of_get_parent(np);
+		if (!isa || strcmp(isa->name, "isa")) {
+			DBG("%s: no isa parent found\n", np->full_name);
+			continue;
+		}
+		
+		/* Now look for an "ibm,aix-loc" property that gives us ordering
+		 * if any...
+		 */
+	 	typep = (char *)get_property(np, "ibm,aix-loc", NULL);
+
+		/* Get the ISA port number */
+		reg = (struct isa_reg_property *)get_property(np, "reg", NULL);	
+		if (reg == NULL)
+			goto next_port;
+		/* We assume the interrupt number isn't translated ... */
+		interrupts = (u32 *)get_property(np, "interrupts", NULL);
+		/* get clock freq. if present */
+		clk = (u32 *)get_property(np, "clock-frequency", NULL);
+		/* get default speed if present */
+		spd = (u32 *)get_property(np, "current-speed", NULL);
+		/* Default to locate at end of array */
+		index = old_serial_count; /* end of the array by default */
+
+		/* If we have a location index, then use it */
+		if (typep && *typep == 'S') {
+			index = simple_strtol(typep+1, NULL, 0) - 1;
+			/* if index is out of range, use end of array instead */
+			if (index >= MAX_LEGACY_SERIAL_PORTS)
+				index = old_serial_count;
+			/* if our index is still out of range, that mean that
+			 * array is full, we could scan for a free slot but that
+			 * make little sense to bother, just skip the port
+			 */
+			if (index >= MAX_LEGACY_SERIAL_PORTS)
+				goto next_port;
+			if (index >= old_serial_count)
+				old_serial_count = index + 1;
+			/* Check if there is a port who already claimed our slot */
+			if (old_serial_ports[index].port != 0) {
+				/* if we still have some room, move it, else override */
+				if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
+					DBG("Moved legacy port %d -> %d\n", index,
+					    old_serial_count);
+					old_serial_ports[old_serial_count++] =
+						old_serial_ports[index];
+				} else {
+					DBG("Replacing legacy port %d\n", index);
+				}
+			}
+		}
+		if (index >= MAX_LEGACY_SERIAL_PORTS)
+			goto next_port;
+		if (index >= old_serial_count)
+			old_serial_count = index + 1;
+
+		/* Now fill the entry */
+		memset(&old_serial_ports[index], 0, sizeof(struct old_serial_port));
+		old_serial_ports[index].uart = 0;
+		old_serial_ports[index].baud_base = clk ? (*clk / 16) : BASE_BAUD;
+		old_serial_ports[index].port = reg->address;
+		old_serial_ports[index].irq = interrupts ? interrupts[0] : 0;
+		old_serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
+
+		DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
+		    index,
+		    old_serial_ports[index].port,
+		    old_serial_ports[index].irq,
+		    old_serial_ports[index].baud_base * 16);
+
+		/* Get phys address of IO reg for port 1 */
+		if (index != 0)
+			goto next_port;
+
+		pci = of_get_parent(isa);
+		if (!pci) {
+			DBG("%s: no pci parent found\n", np->full_name);
+			goto next_port;
+		}
+
+		rangesp = (u32 *)get_property(pci, "ranges", &rlen);
+		if (rangesp == NULL) {
+			of_node_put(pci);
+			goto next_port;
+		}
+		rlen /= 4;
+
+		/* we need the #size-cells of the PCI bridge node itself */
+		phys_size = 1;
+		sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
+		if (sizeprop != NULL)
+			phys_size = *sizeprop;
+		/* we need the parent #addr-cells */
+		addr_size = prom_n_addr_cells(pci);
+		rentsize = 3 + addr_size + phys_size;
+		io_base = 0;
+		for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
+			if (((rangesp[0] >> 24) & 0x3) != 1)
+				continue; /* not IO space */
+			io_base = rangesp[3];
+			if (addr_size == 2)
+				io_base = (io_base << 32) | rangesp[4];
+		}
+		if (io_base != 0) {
+			naca->serialPortAddr = io_base + reg->address;
+			if (default_speed && spd)
+				*default_speed = *spd;
+		}
+		of_node_put(pci);
+	next_port:
+		of_node_put(isa);
+	}
+
+	DBG(" <- generic_find_legacy_serial_port()\n");
+}
+
+struct old_serial_port *get_legacy_serial_ports(unsigned int *count)
+{
+	*count = old_serial_count;
+	return old_serial_ports;
+}
+#else
+struct old_serial_port *get_legacy_serial_ports(unsigned int *count)
+{
+	*count = 0;
+	return 0;
+}
+#endif /* CONFIG_PPC_ISERIES */
+EXPORT_SYMBOL(get_legacy_serial_ports);
+
+int check_legacy_ioport(unsigned long base_port)
+{
+	if (ppc_md.check_legacy_ioport == NULL)
+		return 0;
+	return ppc_md.check_legacy_ioport(base_port);
+}
+EXPORT_SYMBOL(check_legacy_ioport);
+
 #ifdef CONFIG_XMON
 static int __init early_xmon(char *p)
 {
 	/* ensure xmon is enabled */
 	xmon_init();
-	debugger(0);
+	debugger(NULL);
 
 	return 0;
 }
 early_param("xmon", early_xmon);
 #endif
 
+void cpu_die(void)
+{
+	if (ppc_md.cpu_die)
+		ppc_md.cpu_die();
+	local_irq_disable();
+	for (;;);
+}
diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
--- a/arch/ppc64/kernel/signal.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc64/kernel/signal.c	2004-10-28 22:25:56 -07:00
@@ -224,8 +224,12 @@
 #endif /* CONFIG_ALTIVEC */
 
 #ifndef CONFIG_SMP
-	last_task_used_math = NULL;
-	last_task_used_altivec = NULL;
+	preempt_disable();
+	if (last_task_used_math == current)
+		last_task_used_math = NULL;
+	if (last_task_used_altivec == current)
+		last_task_used_altivec = NULL;
+	preempt_enable();
 #endif
 	/* Force reload of FP/VEC */
 	regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/signal32.c	2004-10-28 22:25:59 -07:00
@@ -235,8 +235,12 @@
 #endif /* CONFIG_ALTIVEC */
 
 #ifndef CONFIG_SMP
-	last_task_used_math = NULL;
-	last_task_used_altivec = NULL;
+	preempt_disable();
+	if (last_task_used_math == current)
+		last_task_used_math = NULL;
+	if (last_task_used_altivec == current)
+		last_task_used_altivec = NULL;
+	preempt_enable();
 #endif
 	return 0;
 }
diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
--- a/arch/ppc64/kernel/smp.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/smp.c	2004-10-28 22:25:59 -07:00
@@ -43,18 +43,14 @@
 #include <asm/smp.h>
 #include <asm/naca.h>
 #include <asm/paca.h>
-#include <asm/iSeries/LparData.h>
-#include <asm/iSeries/HvCall.h>
-#include <asm/iSeries/HvCallCfg.h>
 #include <asm/time.h>
 #include <asm/ppcdebug.h>
-#include "open_pic.h"
 #include <asm/machdep.h>
-#include <asm/xics.h>
 #include <asm/cputable.h>
 #include <asm/system.h>
-#include <asm/rtas.h>
-#include <asm/plpar_wrappers.h>
+#include <asm/abs_addr.h>
+
+#include "mpic.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -88,113 +84,9 @@
 /* Low level assembly function used to backup CPU 0 state */
 extern void __save_cpu_setup(void);
 
-extern void pseries_secondary_smp_init(unsigned long); 
-
-#ifdef CONFIG_PPC_ISERIES
-static unsigned long iSeries_smp_message[NR_CPUS];
-
-void iSeries_smp_message_recv( struct pt_regs * regs )
-{
-	int cpu = smp_processor_id();
-	int msg;
-
-	if ( num_online_cpus() < 2 )
-		return;
-
-	for ( msg = 0; msg < 4; ++msg )
-		if ( test_and_clear_bit( msg, &iSeries_smp_message[cpu] ) )
-			smp_message_recv( msg, regs );
-}
-
-static inline void smp_iSeries_do_message(int cpu, int msg)
-{
-	set_bit(msg, &iSeries_smp_message[cpu]);
-	HvCall_sendIPI(&(paca[cpu]));
-}
-
-static void smp_iSeries_message_pass(int target, int msg)
-{
-	int i;
-
-	if (target < NR_CPUS)
-		smp_iSeries_do_message(target, msg);
-	else {
-		for_each_online_cpu(i) {
-			if (target == MSG_ALL_BUT_SELF
-			    && i == smp_processor_id())
-				continue;
-			smp_iSeries_do_message(i, msg);
-		}
-	}
-}
-
-static int smp_iSeries_numProcs(void)
-{
-	unsigned np, i;
-
-	np = 0;
-        for (i=0; i < NR_CPUS; ++i) {
-                if (paca[i].lppaca.xDynProcStatus < 2) {
-			cpu_set(i, cpu_possible_map);
-			cpu_set(i, cpu_present_map);
-                        ++np;
-                }
-        }
-	return np;
-}
-
-static int smp_iSeries_probe(void)
-{
-	unsigned i;
-	unsigned np = 0;
-
-	for (i=0; i < NR_CPUS; ++i) {
-		if (paca[i].lppaca.xDynProcStatus < 2) {
-			/*paca[i].active = 1;*/
-			++np;
-		}
-	}
-
-	return np;
-}
-
-static void smp_iSeries_kick_cpu(int nr)
-{
-	BUG_ON(nr < 0 || nr >= NR_CPUS);
-
-	/* Verify that our partition has a processor nr */
-	if (paca[nr].lppaca.xDynProcStatus >= 2)
-		return;
-
-	/* The processor is currently spinning, waiting
-	 * for the cpu_start field to become non-zero
-	 * After we set cpu_start, the processor will
-	 * continue on to secondary_start in iSeries_head.S
-	 */
-	paca[nr].cpu_start = 1;
-}
-
-static void __devinit smp_iSeries_setup_cpu(int nr)
-{
-}
-
-static struct smp_ops_t iSeries_smp_ops = {
-	.message_pass = smp_iSeries_message_pass,
-	.probe        = smp_iSeries_probe,
-	.kick_cpu     = smp_iSeries_kick_cpu,
-	.setup_cpu    = smp_iSeries_setup_cpu,
-};
-
-/* This is called very early. */
-void __init smp_init_iSeries(void)
-{
-	smp_ops = &iSeries_smp_ops;
-	systemcfg->processorCount	= smp_iSeries_numProcs();
-}
-#endif
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-void smp_openpic_message_pass(int target, int msg)
+void smp_mpic_message_pass(int target, int msg)
 {
 	/* make sure we're sending something that translates to an IPI */
 	if ( msg > 0x3 ){
@@ -205,242 +97,52 @@
 	switch ( target )
 	{
 	case MSG_ALL:
-		openpic_cause_IPI(msg, 0xffffffff);
+		mpic_send_ipi(msg, 0xffffffff);
 		break;
 	case MSG_ALL_BUT_SELF:
-		openpic_cause_IPI(msg,
-				  0xffffffff & ~(1 << smp_processor_id()));
+		mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
 		break;
 	default:
-		openpic_cause_IPI(msg, 1<<target);
+		mpic_send_ipi(msg, 1 << target);
 		break;
 	}
 }
 
-static int __init smp_openpic_probe(void)
+int __init smp_mpic_probe(void)
 {
 	int nr_cpus;
 
+	DBG("smp_mpic_probe()...\n");
+
 	nr_cpus = cpus_weight(cpu_possible_map);
 
+	DBG("nr_cpus: %d\n", nr_cpus);
+
 	if (nr_cpus > 1)
-		openpic_request_IPIs();
+		mpic_request_ipis();
 
 	return nr_cpus;
 }
 
-static void __devinit smp_openpic_setup_cpu(int cpu)
-{
-	do_openpic_setup_cpu();
-}
-
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
-#ifdef CONFIG_PPC_PSERIES
-
-/* Get state of physical CPU.
- * Return codes:
- *	0	- The processor is in the RTAS stopped state
- *	1	- stop-self is in progress
- *	2	- The processor is not in the RTAS stopped state
- *	-1	- Hardware Error
- *	-2	- Hardware Busy, Try again later.
- */
-int query_cpu_stopped(unsigned int pcpu)
-{
-	int cpu_status;
-	int status, qcss_tok;
-
-	DBG(" -> query_cpu_stopped(%d)\n", pcpu);
-	qcss_tok = rtas_token("query-cpu-stopped-state");
-	if (qcss_tok == RTAS_UNKNOWN_SERVICE)
-		return -1;
-	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
-	if (status != 0) {
-		printk(KERN_ERR
-		       "RTAS query-cpu-stopped-state failed: %i\n", status);
-		return status;
-	}
-
-	DBG(" <- query_cpu_stopped(), status: %d\n", cpu_status);
-
-	return cpu_status;
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-
-int __cpu_disable(void)
+void __devinit smp_mpic_setup_cpu(int cpu)
 {
-	/* FIXME: go put this in a header somewhere */
-	extern void xics_migrate_irqs_away(void);
-
-	systemcfg->processorCount--;
-
-	/*fix boot_cpuid here*/
-	if (smp_processor_id() == boot_cpuid)
-		boot_cpuid = any_online_cpu(cpu_online_map);
-
-	/* FIXME: abstract this to not be platform specific later on */
-	xics_migrate_irqs_away();
-	return 0;
+	mpic_setup_this_cpu();
 }
 
-void __cpu_die(unsigned int cpu)
-{
-	int tries;
-	int cpu_status;
-	unsigned int pcpu = get_hard_smp_processor_id(cpu);
-
-	for (tries = 0; tries < 25; tries++) {
-		cpu_status = query_cpu_stopped(pcpu);
-		if (cpu_status == 0 || cpu_status == -1)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/5);
-	}
-	if (cpu_status != 0) {
-		printk("Querying DEAD? cpu %i (%i) shows %i\n",
-		       cpu, pcpu, cpu_status);
-	}
-
-	/* Isolation and deallocation are definatly done by
-	 * drslot_chrp_cpu.  If they were not they would be
-	 * done here.  Change isolate state to Isolate and
-	 * change allocation-state to Unusable.
-	 */
-	paca[cpu].cpu_start = 0;
-
-	/* So we can recognize if it fails to come up next time. */
-	cpu_callin_map[cpu] = 0;
-}
-
-/* Kill this cpu */
-void cpu_die(void)
-{
-	local_irq_disable();
-	/* Some hardware requires clearing the CPPR, while other hardware does not
-	 * it is safe either way
-	 */
-	pSeriesLP_cppr_info(0, 0);
-	rtas_stop_self();
-	/* Should never get here... */
-	BUG();
-	for(;;);
-}
-
-/* Search all cpu device nodes for an offline logical cpu.  If a
- * device node has a "ibm,my-drc-index" property (meaning this is an
- * LPAR), paranoid-check whether we own the cpu.  For each "thread"
- * of a cpu, if it is offline and has the same hw index as before,
- * grab that in preference.
- */
-static unsigned int find_physical_cpu_to_start(unsigned int old_hwindex)
-{
-	struct device_node *np = NULL;
-	unsigned int best = -1U;
-
-	while ((np = of_find_node_by_type(np, "cpu"))) {
-		int nr_threads, len;
-		u32 *index = (u32 *)get_property(np, "ibm,my-drc-index", NULL);
-		u32 *tid = (u32 *)
-			get_property(np, "ibm,ppc-interrupt-server#s", &len);
-
-		if (!tid)
-			tid = (u32 *)get_property(np, "reg", &len);
-
-		if (!tid)
-			continue;
-
-		/* If there is a drc-index, make sure that we own
-		 * the cpu.
-		 */
-		if (index) {
-			int state;
-			int rc = rtas_get_sensor(9003, *index, &state);
-			if (rc != 0 || state != 1)
-				continue;
-		}
-
-		nr_threads = len / sizeof(u32);
-
-		while (nr_threads--) {
-			if (0 == query_cpu_stopped(tid[nr_threads])) {
-				best = tid[nr_threads];
-				if (best == old_hwindex)
-					goto out;
-			}
-		}
-	}
-out:
-	of_node_put(np);
-	return best;
-}
-
-/**
- * smp_startup_cpu() - start the given cpu
- *
- * At boot time, there is nothing to do.  At run-time, call RTAS with
- * the appropriate start location, if the cpu is in the RTAS stopped
- * state.
- *
- * Returns:
- *	0	- failure
- *	1	- success
- */
-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
-{
-	int status;
-	unsigned long start_here = __pa((u32)*((unsigned long *)
-					       pseries_secondary_smp_init));
-	unsigned int pcpu;
-
-	/* At boot time the cpus are already spinning in hold
-	 * loops, so nothing to do. */
- 	if (system_state < SYSTEM_RUNNING)
-		return 1;
-
-	pcpu = find_physical_cpu_to_start(get_hard_smp_processor_id(lcpu));
-	if (pcpu == -1U) {
-		printk(KERN_INFO "No more cpus available, failing\n");
-		return 0;
-	}
-
-	/* Fixup atomic count: it exited inside IRQ handler. */
-	paca[lcpu].__current->thread_info->preempt_count	= 0;
-
-	/* At boot this is done in prom.c. */
-	paca[lcpu].hw_cpu_id = pcpu;
-
-	status = rtas_call(rtas_token("start-cpu"), 3, 1, NULL,
-			   pcpu, start_here, lcpu);
-	if (status != 0) {
-		printk(KERN_ERR "start-cpu failed: %i\n", status);
-		return 0;
-	}
-	return 1;
-}
-#else /* ... CONFIG_HOTPLUG_CPU */
-static inline int __devinit smp_startup_cpu(unsigned int lcpu)
-{
-	return 1;
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
-static void smp_pSeries_kick_cpu(int nr)
+void __devinit smp_generic_kick_cpu(int nr)
 {
 	BUG_ON(nr < 0 || nr >= NR_CPUS);
 
-	if (!smp_startup_cpu(nr))
-		return;
-
 	/*
 	 * The processor is currently spinning, waiting for the
 	 * cpu_start field to become non-zero After we set cpu_start,
 	 * the processor will continue on to secondary_start
 	 */
 	paca[nr].cpu_start = 1;
+	mb();
 }
-#endif /* CONFIG_PPC_PSERIES */
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 static void __init smp_space_timers(unsigned int max_cpus)
 {
@@ -457,136 +159,6 @@
 	}
 }
 
-#ifdef CONFIG_PPC_PSERIES
-static void vpa_init(int cpu)
-{
-	unsigned long flags, pcpu = get_hard_smp_processor_id(cpu);
-
-	/* Register the Virtual Processor Area (VPA) */
-	flags = 1UL << (63 - 18);
-	register_vpa(flags, pcpu, __pa((unsigned long)&(paca[cpu].lppaca)));
-}
-
-static inline void smp_xics_do_message(int cpu, int msg)
-{
-	set_bit(msg, &xics_ipi_message[cpu].value);
-	mb();
-	xics_cause_IPI(cpu);
-}
-
-static void smp_xics_message_pass(int target, int msg)
-{
-	unsigned int i;
-
-	if (target < NR_CPUS) {
-		smp_xics_do_message(target, msg);
-	} else {
-		for_each_online_cpu(i) {
-			if (target == MSG_ALL_BUT_SELF
-			    && i == smp_processor_id())
-				continue;
-			smp_xics_do_message(i, msg);
-		}
-	}
-}
-
-extern void xics_request_IPIs(void);
-
-static int __init smp_xics_probe(void)
-{
-#ifdef CONFIG_SMP
-	xics_request_IPIs();
-#endif
-
-	return cpus_weight(cpu_possible_map);
-}
-
-static void __devinit smp_xics_setup_cpu(int cpu)
-{
-	if (cpu != boot_cpuid)
-		xics_setup_cpu();
-}
-
-static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED;
-static unsigned long timebase = 0;
-
-static void __devinit pSeries_give_timebase(void)
-{
-	spin_lock(&timebase_lock);
-	rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-	timebase = get_tb();
-	spin_unlock(&timebase_lock);
-
-	while (timebase)
-		barrier();
-	rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-static void __devinit pSeries_take_timebase(void)
-{
-	while (!timebase)
-		barrier();
-	spin_lock(&timebase_lock);
-	set_tb(timebase >> 32, timebase & 0xffffffff);
-	timebase = 0;
-	spin_unlock(&timebase_lock);
-}
-
-static struct smp_ops_t pSeries_openpic_smp_ops = {
-	.message_pass	= smp_openpic_message_pass,
-	.probe		= smp_openpic_probe,
-	.kick_cpu	= smp_pSeries_kick_cpu,
-	.setup_cpu	= smp_openpic_setup_cpu,
-};
-
-static struct smp_ops_t pSeries_xics_smp_ops = {
-	.message_pass	= smp_xics_message_pass,
-	.probe		= smp_xics_probe,
-	.kick_cpu	= smp_pSeries_kick_cpu,
-	.setup_cpu	= smp_xics_setup_cpu,
-};
-
-/* This is called very early */
-void __init smp_init_pSeries(void)
-{
-	int ret, i;
-
-	DBG(" -> smp_init_pSeries()\n");
-
-	if (naca->interrupt_controller == IC_OPEN_PIC)
-		smp_ops = &pSeries_openpic_smp_ops;
-	else
-		smp_ops = &pSeries_xics_smp_ops;
-
-	/* Start secondary threads on SMT systems; primary threads
-	 * are already in the running state.
-	 */
-	for_each_present_cpu(i) {
-		if (query_cpu_stopped(get_hard_smp_processor_id(i)) == 0) {
-			printk("%16.16x : starting thread\n", i);
-			DBG("%16.16x : starting thread\n", i);
-			rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
-				  get_hard_smp_processor_id(i),
-				  __pa((u32)*((unsigned long *)
-					      pseries_secondary_smp_init)),
-				  i);
-		}
-	}
-
-	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
-		vpa_init(boot_cpuid);
-
-	/* Non-lpar has additional take/give timebase */
-	if (systemcfg->platform == PLATFORM_PSERIES) {
-		smp_ops->give_timebase = pSeries_give_timebase;
-		smp_ops->take_timebase = pSeries_take_timebase;
-	}
-
-
-	DBG(" <- smp_init_pSeries()\n");
-}
-#endif /* CONFIG_PPC_PSERIES */
-
 void smp_local_timer_interrupt(struct pt_regs * regs)
 {
 	update_process_times(user_mode(regs));
@@ -809,6 +381,8 @@
 {
 	unsigned int cpu;
 
+	DBG("smp_prepare_cpus\n");
+
 	/* 
 	 * setup_cpu may need to be called on the boot cpu. We havent
 	 * spun any cpus up but lets be paranoid.
@@ -833,9 +407,6 @@
 
 	max_cpus = smp_ops->probe();
  
-	/* Backup CPU 0 state if necessary */
-	__save_cpu_setup();
-
 	smp_space_timers(max_cpus);
 
 	for_each_cpu(cpu)
@@ -876,6 +447,11 @@
 		paca[cpu].stab_real = virt_to_abs(tmp);
 	}
 
+	/* Make sure callin-map entry is 0 (can be leftover a CPU
+	 * hotplug
+	 */
+	cpu_callin_map[cpu] = 0;
+
 	/* The information for processor bringup must
 	 * be written out to main store before we release
 	 * the processor.
@@ -883,6 +459,7 @@
 	mb();
 
 	/* wake up cpus */
+	DBG("smp: kicking cpu %d\n", cpu);
 	smp_ops->kick_cpu(cpu);
 
 	/*
@@ -922,7 +499,7 @@
 	return 0;
 }
 
-extern unsigned int default_distrib_server;
+
 /* Activate a secondary processor. */
 int __devinit start_secondary(void *unused)
 {
@@ -939,20 +516,8 @@
 	if (smp_ops->take_timebase)
 		smp_ops->take_timebase();
 
-#ifdef CONFIG_PPC_PSERIES
-	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
-		vpa_init(cpu); 
-	}
-
-#ifdef CONFIG_IRQ_ALL_CPUS
-	/* Put the calling processor into the GIQ.  This is really only
-	 * necessary from a secondary thread as the OF start-cpu interface
-	 * performs this function for us on primary threads.
-	 */
-	/* TODO: 9005 is #defined in rtas-proc.c -- move to a header */
-	rtas_set_indicator(9005, default_distrib_server, 1);
-#endif
-#endif
+	if (smp_ops->late_setup_cpu)
+		smp_ops->late_setup_cpu(cpu);
 
 	spin_lock(&call_lock);
 	cpu_set(cpu, cpu_online_map);
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/sys_ppc32.c	2004-10-28 22:25:58 -07:00
@@ -1328,3 +1328,21 @@
 
 	return err;
 }
+
+asmlinkage long sys32_add_key(const char __user *_type,
+			      const char __user *_description,
+			      const void __user *_payload,
+			      u32 plen,
+			      u32 ringid)
+{
+	return sys_add_key(_type, _description, _payload, plen, ringid);
+}
+
+asmlinkage long sys32_request_key(const char __user *_type,
+				  const char __user *_description,
+				  const char __user *_callout_info,
+				  u32 destringid)
+{
+	return sys_request_key(_type, _description, _callout_info, destringid);
+}
+
diff -Nru a/arch/ppc64/kernel/u3_iommu.c b/arch/ppc64/kernel/u3_iommu.c
--- a/arch/ppc64/kernel/u3_iommu.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/kernel/u3_iommu.c	2004-10-28 22:25:59 -07:00
@@ -267,6 +267,7 @@
 
 void iommu_setup_u3(void)
 {
+	struct pci_controller *phb, *tmp;
 	struct pci_dev *dev = NULL;
 	struct device_node *dn;
 
@@ -298,6 +299,11 @@
 		struct device_node *dn = pci_device_to_OF_node(dev);
 		if (dn)
 			dn->iommu_table = &iommu_table_u3;
+	}
+	/* We also make sure we set all PHBs ... */
+	list_for_each_entry_safe(phb, tmp, &hose_list, list_node) {
+		dn = (struct device_node *)phb->arch_data;
+		dn->iommu_table = &iommu_table_u3;
 	}
 }
 
diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c
--- a/arch/ppc64/kernel/udbg.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc64/kernel/udbg.c	2004-10-28 22:25:56 -07:00
@@ -11,6 +11,8 @@
 
 #include <stdarg.h>
 #define WANT_PPCDBG_TAB /* Only defined here */
+#include <linux/config.h>
+#include <linux/types.h>
 #include <asm/ppcdebug.h>
 #include <asm/processor.h>
 #include <asm/naca.h>
@@ -20,6 +22,9 @@
 #include <asm/prom.h>
 #include <asm/pmac_feature.h>
 
+extern u8 real_readb(volatile u8 __iomem  *addr);
+extern void real_writeb(u8 data, volatile u8 __iomem *addr);
+
 struct NS16550 {
 	/* this struct must be packed */
 	unsigned char rbr;  /* 0 */
@@ -47,21 +52,36 @@
 #define LSR_TEMT 0x40  /* Xmitter empty */
 #define LSR_ERR  0x80  /* Error */
 
-static volatile struct NS16550 *udbg_comport;
+static volatile struct NS16550 __iomem *udbg_comport;
 
-void udbg_init_uart(void *comport)
+void udbg_init_uart(void __iomem *comport, unsigned int speed)
 {
+	u8 dll = 12;
+
+	switch(speed) {
+	case 115200:
+		dll = 1;
+		break;
+	case 57600:
+		dll = 2;
+		break;
+	case 38400:
+		dll = 3;
+		break;
+	}
 	if (comport) {
-		udbg_comport = (struct NS16550 *)comport;
-		udbg_comport->lcr = 0x00; eieio();
-		udbg_comport->ier = 0xFF; eieio();
-		udbg_comport->ier = 0x00; eieio();
-		udbg_comport->lcr = 0x80; eieio();	/* Access baud rate */
-		udbg_comport->dll = 12;   eieio();	/* 1 = 115200,  2 = 57600, 3 = 38400, 12 = 9600 baud */
-		udbg_comport->dlm = 0;    eieio();	/* dll >> 8 which should be zero for fast rates; */
-		udbg_comport->lcr = 0x03; eieio();	/* 8 data, 1 stop, no parity */
-		udbg_comport->mcr = 0x03; eieio();	/* RTS/DTR */
-		udbg_comport->fcr = 0x07; eieio();	/* Clear & enable FIFOs */
+		udbg_comport = (struct NS16550 __iomem *)comport;
+		out_8(&udbg_comport->lcr, 0x00);
+		out_8(&udbg_comport->ier, 0xff);
+		out_8(&udbg_comport->ier, 0x00);
+		out_8(&udbg_comport->lcr, 0x80);	/* Access baud rate */
+		out_8(&udbg_comport->dll,  dll);	/* 1 = 115200,  2 = 57600,
+							   3 = 38400, 12 = 9600 baud */
+		out_8(&udbg_comport->dlm, 0x00);	/* dll >> 8 which should be zero
+							   for fast rates; */
+		out_8(&udbg_comport->lcr, 0x03);	/* 8 data, 1 stop, no parity */
+		out_8(&udbg_comport->mcr, 0x03);	/* RTS/DTR */
+		out_8(&udbg_comport->fcr ,0x07);	/* Clear & enable FIFOs */
 	}
 }
 
@@ -70,7 +90,8 @@
 #define	SCC_TXRDY	4
 #define SCC_RXRDY	1
 
-static volatile u8 *sccc, *sccd;
+static volatile u8 __iomem *sccc;
+static volatile u8 __iomem *sccd;
 
 static unsigned char scc_inittab[] = {
     13, 0,		/* set baud rate divisor */
@@ -109,7 +130,7 @@
 
 	/* Setup for 57600 8N1 */
 	addr += 0x20;
-	sccc = (volatile u8 *) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
+	sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
 	sccc += addr & ~PAGE_MASK;
 	sccd = sccc + 0x10;
 
@@ -117,13 +138,11 @@
 	mb();
 
 	for (i = 20000; i != 0; --i)
-		x = *sccc; eieio();
-	*sccc = 9; eieio();		/* reset A or B side */
-	*sccc = 0xc0; eieio();
-	for (i = 0; i < sizeof(scc_inittab); ++i) {
-		*sccc = scc_inittab[i];
-		eieio();
-	}
+		x = in_8(sccc);
+	out_8(sccc, 0x09);		/* reset A or B side */
+	out_8(sccc, 0xc0);
+	for (i = 0; i < sizeof(scc_inittab); ++i)
+		out_8(sccc, scc_inittab[i]);
 
 	ppc_md.udbg_putc = udbg_putc;
 	ppc_md.udbg_getc = udbg_getc;
@@ -135,9 +154,6 @@
 #endif /* CONFIG_PPC_PMAC */
 
 #if CONFIG_PPC_PMAC
-extern u8 real_readb(volatile u8 *addr);
-extern void real_writeb(u8 data, volatile u8 *addr);
-
 static void udbg_real_putc(unsigned char c)
 {
 	while ((real_readb(sccc) & SCC_TXRDY) == 0)
@@ -149,8 +165,8 @@
 
 void udbg_init_pmac_realmode(void)
 {
-	sccc = (volatile u8 *)0x80013020ul;
-	sccd = (volatile u8 *)0x80013030ul;
+	sccc = (volatile u8 __iomem *)0x80013020ul;
+	sccd = (volatile u8 __iomem *)0x80013030ul;
 
 	ppc_md.udbg_putc = udbg_real_putc;
 	ppc_md.udbg_getc = NULL;
@@ -158,25 +174,50 @@
 }
 #endif /* CONFIG_PPC_PMAC */
 
-void udbg_putc(unsigned char c)
+#ifdef CONFIG_PPC_MAPLE
+void udbg_maple_real_putc(unsigned char c)
 {
 	if (udbg_comport) {
-		while ((udbg_comport->lsr & LSR_THRE) == 0)
+		while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
 			/* wait for idle */;
-		udbg_comport->thr = c; eieio();
+		real_writeb(c, &udbg_comport->thr); eieio();
 		if (c == '\n') {
 			/* Also put a CR.  This is for convenience. */
-			while ((udbg_comport->lsr & LSR_THRE) == 0)
+			while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
 				/* wait for idle */;
-			udbg_comport->thr = '\r'; eieio();
+			real_writeb('\r', &udbg_comport->thr); eieio();
+		}
+	}
+}
+
+void udbg_init_maple_realmode(void)
+{
+	udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
+
+	ppc_md.udbg_putc = udbg_maple_real_putc;
+	ppc_md.udbg_getc = NULL;
+	ppc_md.udbg_getc_poll = NULL;
+}
+#endif /* CONFIG_PPC_MAPLE */
+
+void udbg_putc(unsigned char c)
+{
+	if (udbg_comport) {
+		while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
+			/* wait for idle */;
+		out_8(&udbg_comport->thr, c);
+		if (c == '\n') {
+			/* Also put a CR.  This is for convenience. */
+			while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
+				/* wait for idle */; 
+			out_8(&udbg_comport->thr, '\r');
 		}
 	}
 #ifdef CONFIG_PPC_PMAC
 	else if (sccc) {
-		while ((*sccc & SCC_TXRDY) == 0)
-			eieio();
-		*sccd = c;		
-		eieio();
+		while ((in_8(sccc) & SCC_TXRDY) == 0)
+			;
+		out_8(sccd,  c);		
 		if (c == '\n')
 			udbg_putc('\r');
 	}
@@ -186,16 +227,15 @@
 int udbg_getc_poll(void)
 {
 	if (udbg_comport) {
-		if ((udbg_comport->lsr & LSR_DR) != 0)
-			return udbg_comport->rbr;
+		if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
+			return in_8(&udbg_comport->rbr);
 		else
 			return -1;
 	}
 #ifdef CONFIG_PPC_PMAC
 	else if (sccc) {
-		eieio();
-		if ((*sccc & SCC_RXRDY) != 0)
-			return *sccd;
+		if ((in_8(sccc) & SCC_RXRDY) != 0)
+			return in_8(sccd);
 		else
 			return -1;
 	}
@@ -206,16 +246,15 @@
 unsigned char udbg_getc(void)
 {
 	if (udbg_comport) {
-		while ((udbg_comport->lsr & LSR_DR) == 0)
+		while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
 			/* wait for char */;
-		return udbg_comport->rbr;
+		return in_8(&udbg_comport->rbr);
 	}
 #ifdef CONFIG_PPC_PMAC
 	else if (sccc) {
-		eieio();
-		while ((*sccc & SCC_RXRDY) == 0)
-			eieio();
-		return *sccd;
+		while ((in_8(sccc) & SCC_RXRDY) == 0)
+			;
+		return in_8(sccd);
 	}
 #endif /* CONFIG_PPC_PMAC */
 	return 0;
diff -Nru a/arch/ppc64/kernel/vecemu.c b/arch/ppc64/kernel/vecemu.c
--- a/arch/ppc64/kernel/vecemu.c	2004-10-28 22:25:56 -07:00
+++ b/arch/ppc64/kernel/vecemu.c	2004-10-28 22:25:56 -07:00
@@ -263,7 +263,7 @@
 	unsigned int va, vb, vc, vd;
 	vector128 *vrs;
 
-	if (get_user(instr, (unsigned int *) regs->nip))
+	if (get_user(instr, (unsigned int __user *) regs->nip))
 		return -EFAULT;
 	if ((instr >> 26) != 4)
 		return -EINVAL;		/* not an altivec instruction */
diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
--- a/arch/ppc64/kernel/xics.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/kernel/xics.c	2004-10-28 22:25:58 -07:00
@@ -85,7 +85,7 @@
 	} qirr;
 };
 
-static struct xics_ipl *xics_per_cpu[NR_CPUS];
+static struct xics_ipl __iomem *xics_per_cpu[NR_CPUS];
 
 static int xics_irq_8259_cascade = 0;
 static int xics_irq_8259_cascade_real = 0;
@@ -116,22 +116,22 @@
 
 static int pSeries_xirr_info_get(int n_cpu)
 {
-	return xics_per_cpu[n_cpu]->xirr.word;
+	return in_be32(&xics_per_cpu[n_cpu]->xirr.word);
 }
 
 static void pSeries_xirr_info_set(int n_cpu, int value)
 {
-	xics_per_cpu[n_cpu]->xirr.word = value;
+	out_be32(&xics_per_cpu[n_cpu]->xirr.word, value);
 }
 
 static void pSeries_cppr_info(int n_cpu, u8 value)
 {
-	xics_per_cpu[n_cpu]->xirr.bytes[0] = value;
+	out_8(&xics_per_cpu[n_cpu]->xirr.bytes[0], value);
 }
 
 static void pSeries_qirr_info(int n_cpu, u8 value)
 {
-	xics_per_cpu[n_cpu]->qirr.bytes[0] = value;
+	out_8(&xics_per_cpu[n_cpu]->qirr.bytes[0], value);
 }
 
 static xics_ops pSeries_ops = {
@@ -457,7 +457,7 @@
 	struct xics_interrupt_node {
 		unsigned long addr;
 		unsigned long size;
-	} inodes[NR_CPUS]; 
+	} intnodes[NR_CPUS]; 
 
 	ppc64_boot_msg(0x20, "XICS Init");
 
@@ -484,13 +484,13 @@
 		panic("xics_init_IRQ: can't find interrupt reg property");
 	
 	while (ilen) {
-		inodes[indx].addr = (unsigned long long)*ireg++ << 32;
+		intnodes[indx].addr = (unsigned long)*ireg++ << 32;
 		ilen -= sizeof(uint);
-		inodes[indx].addr |= *ireg++;
+		intnodes[indx].addr |= *ireg++;
 		ilen -= sizeof(uint);
-		inodes[indx].size = (unsigned long long)*ireg++ << 32;
+		intnodes[indx].size = (unsigned long)*ireg++ << 32;
 		ilen -= sizeof(uint);
-		inodes[indx].size |= *ireg++;
+		intnodes[indx].size |= *ireg++;
 		ilen -= sizeof(uint);
 		indx++;
 		if (indx >= NR_CPUS) break;
@@ -505,7 +505,8 @@
 	     np = of_find_node_by_type(np, "cpu")) {
 		ireg = (uint *)get_property(np, "reg", &ilen);
 		if (ireg && ireg[0] == hard_smp_processor_id()) {
-			ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
+			ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s",
+						    &ilen);
 			i = ilen / sizeof(int);
 			if (ireg && i > 0) {
 				default_server = ireg[0];
@@ -516,8 +517,8 @@
 	}
 	of_node_put(np);
 
-	intr_base = inodes[0].addr;
-	intr_size = (ulong)inodes[0].size;
+	intr_base = intnodes[0].addr;
+	intr_size = intnodes[0].size;
 
 	np = of_find_node_by_type(NULL, "interrupt-controller");
 	if (!np) {
@@ -538,16 +539,18 @@
 	if (systemcfg->platform == PLATFORM_PSERIES) {
 #ifdef CONFIG_SMP
 		for_each_cpu(i) {
+			int hard_id;
+
 			/* FIXME: Do this dynamically! --RR */
 			if (!cpu_present(i))
 				continue;
-			xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
-						    (ulong)inodes[get_hard_smp_processor_id(i)].size,
-						    _PAGE_NO_CACHE);
+
+			hard_id = get_hard_smp_processor_id(i);
+			xics_per_cpu[i] = ioremap(intnodes[hard_id].addr, 
+						  intnodes[hard_id].size);
 		}
 #else
-		xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size,
-					    _PAGE_NO_CACHE);
+		xics_per_cpu[0] = ioremap(intr_base, intr_size);
 #endif /* CONFIG_SMP */
 	} else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
 		ops = &pSeriesLP_ops;
@@ -578,7 +581,7 @@
 				no_action, 0, "8259 cascade", NULL))
 			printk(KERN_ERR "xics_setup_i8259: couldn't get 8259 "
 					"cascade\n");
-		i8259_init();
+		i8259_init(0);
 	}
 	return 0;
 }
diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
--- a/arch/ppc64/mm/hash_utils.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/mm/hash_utils.c	2004-10-28 22:25:58 -07:00
@@ -341,9 +341,7 @@
 		     int local)
 {
 	unsigned long vsid, vpn, va, hash, secondary, slot;
-
-	/* XXX fix for large ptes */
-	unsigned long large = 0;
+	unsigned long huge = pte_huge(pte);
 
 	if ((ea >= USER_START) && (ea <= USER_END))
 		vsid = get_vsid(context, ea);
@@ -351,18 +349,18 @@
 		vsid = get_kernel_vsid(ea);
 
 	va = (vsid << 28) | (ea & 0x0fffffff);
-	if (large)
+	if (huge)
 		vpn = va >> HPAGE_SHIFT;
 	else
 		vpn = va >> PAGE_SHIFT;
-	hash = hpt_hash(vpn, large);
+	hash = hpt_hash(vpn, huge);
 	secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15;
 	if (secondary)
 		hash = ~hash;
 	slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
 	slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12;
 
-	ppc_md.hpte_invalidate(slot, va, large, local);
+	ppc_md.hpte_invalidate(slot, va, huge, local);
 }
 
 void flush_hash_range(unsigned long context, unsigned long number, int local)
@@ -401,7 +399,7 @@
 		info.si_signo = SIGBUS;
 		info.si_errno = 0;
 		info.si_code = BUS_ADRERR;
-		info.si_addr = (void *)address;
+		info.si_addr = (void __user *)address;
 		force_sig_info(SIGBUS, &info, current);
 		return;
 	}
diff -Nru a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
--- a/arch/ppc64/mm/hugetlbpage.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/mm/hugetlbpage.c	2004-10-28 22:25:58 -07:00
@@ -27,116 +27,143 @@
 
 #include <linux/sysctl.h>
 
-/* HugePTE layout:
- *
- * 31 30 ... 15 14 13 12 10 9  8  7   6    5    4    3    2    1    0
- * PFN>>12..... -  -  -  -  -  -  HASH_IX....   2ND  HASH RW   -    HG=1
- */
+#define	HUGEPGDIR_SHIFT		(HPAGE_SHIFT + PAGE_SHIFT - 3)
+#define HUGEPGDIR_SIZE		(1UL << HUGEPGDIR_SHIFT)
+#define HUGEPGDIR_MASK		(~(HUGEPGDIR_SIZE-1))
+
+#define HUGEPTE_INDEX_SIZE	9
+#define HUGEPGD_INDEX_SIZE	10
+
+#define PTRS_PER_HUGEPTE	(1 << HUGEPTE_INDEX_SIZE)
+#define PTRS_PER_HUGEPGD	(1 << HUGEPGD_INDEX_SIZE)
 
-#define HUGEPTE_SHIFT	15
-#define _HUGEPAGE_PFN		0xffff8000
-#define _HUGEPAGE_BAD		0x00007f00
-#define _HUGEPAGE_HASHPTE	0x00000008
-#define _HUGEPAGE_SECONDARY	0x00000010
-#define _HUGEPAGE_GROUP_IX	0x000000e0
-#define _HUGEPAGE_HPTEFLAGS	(_HUGEPAGE_HASHPTE | _HUGEPAGE_SECONDARY | \
-				 _HUGEPAGE_GROUP_IX)
-#define _HUGEPAGE_RW		0x00000004
-
-typedef struct {unsigned int val;} hugepte_t;
-#define hugepte_val(hugepte)	((hugepte).val)
-#define __hugepte(x)		((hugepte_t) { (x) } )
-#define hugepte_pfn(x)		\
-	((unsigned long)(hugepte_val(x)>>HUGEPTE_SHIFT) << HUGETLB_PAGE_ORDER)
-#define mk_hugepte(page,wr)	__hugepte( \
-	((page_to_pfn(page)>>HUGETLB_PAGE_ORDER) << HUGEPTE_SHIFT ) \
-	| (!!(wr) * _HUGEPAGE_RW) | _PMD_HUGEPAGE )
-
-#define hugepte_bad(x)	( !(hugepte_val(x) & _PMD_HUGEPAGE) || \
-			  (hugepte_val(x) & _HUGEPAGE_BAD) )
-#define hugepte_page(x)	pfn_to_page(hugepte_pfn(x))
-#define hugepte_none(x)	(!(hugepte_val(x) & _HUGEPAGE_PFN))
-
-
-static void flush_hash_hugepage(mm_context_t context, unsigned long ea,
-				hugepte_t pte, int local);
-
-static inline unsigned int hugepte_update(hugepte_t *p, unsigned int clr,
-					  unsigned int set)
-{
-	unsigned int old, tmp;
-
-	__asm__ __volatile__(
-	"1:	lwarx	%0,0,%3		# pte_update\n\
-	andc	%1,%0,%4 \n\
-	or	%1,%1,%5 \n\
-	stwcx.	%1,0,%3 \n\
-	bne-	1b"
-	: "=&r" (old), "=&r" (tmp), "=m" (*p)
-	: "r" (p), "r" (clr), "r" (set), "m" (*p)
-	: "cc" );
-	return old;
+static inline int hugepgd_index(unsigned long addr)
+{
+	return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;
 }
 
-static inline void set_hugepte(hugepte_t *ptep, hugepte_t pte)
+static pgd_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
 {
-	hugepte_update(ptep, ~_HUGEPAGE_HPTEFLAGS,
-		       hugepte_val(pte) & ~_HUGEPAGE_HPTEFLAGS);
+	int index;
+
+	if (! mm->context.huge_pgdir)
+		return NULL;
+
+
+	index = hugepgd_index(addr);
+	BUG_ON(index >= PTRS_PER_HUGEPGD);
+	return mm->context.huge_pgdir + index;
 }
 
-static hugepte_t *hugepte_alloc(struct mm_struct *mm, unsigned long addr)
+static inline pte_t *hugepte_offset(pgd_t *dir, unsigned long addr)
 {
-	pgd_t *pgd;
-	pmd_t *pmd = NULL;
+	int index;
 
-	BUG_ON(!in_hugepage_area(mm->context, addr));
+	if (pgd_none(*dir))
+		return NULL;
 
-	pgd = pgd_offset(mm, addr);
-	pmd = pmd_alloc(mm, pgd, addr);
+	index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;
+	return (pte_t *)pgd_page(*dir) + index;
+}
 
-	/* We shouldn't find a (normal) PTE page pointer here */
-	BUG_ON(!pmd_none(*pmd) && !pmd_hugepage(*pmd));
-	
-	return (hugepte_t *)pmd;
+static pgd_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
+{
+	BUG_ON(! in_hugepage_area(mm->context, addr));
+
+	if (! mm->context.huge_pgdir) {
+		pgd_t *new;
+		spin_unlock(&mm->page_table_lock);
+		/* Don't use pgd_alloc(), because we want __GFP_REPEAT */
+		new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);
+		BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
+		spin_lock(&mm->page_table_lock);
+
+		/*
+		 * Because we dropped the lock, we should re-check the
+		 * entry, as somebody else could have populated it..
+		 */
+		if (mm->context.huge_pgdir)
+			pgd_free(new);
+		else
+			mm->context.huge_pgdir = new;
+	}
+	return hugepgd_offset(mm, addr);
 }
 
-static hugepte_t *hugepte_offset(struct mm_struct *mm, unsigned long addr)
+static pte_t *hugepte_alloc(struct mm_struct *mm, pgd_t *dir,
+			    unsigned long addr)
 {
-	pgd_t *pgd;
-	pmd_t *pmd = NULL;
+	if (! pgd_present(*dir)) {
+		pte_t *new;
 
-	BUG_ON(!in_hugepage_area(mm->context, addr));
+		spin_unlock(&mm->page_table_lock);
+		new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);
+		BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
+		spin_lock(&mm->page_table_lock);
+		/*
+		 * Because we dropped the lock, we should re-check the
+		 * entry, as somebody else could have populated it..
+		 */
+		if (pgd_present(*dir)) {
+			if (new)
+				kmem_cache_free(zero_cache, new);
+		} else {
+			struct page *ptepage;
 
-	pgd = pgd_offset(mm, addr);
-	if (pgd_none(*pgd))
-		return NULL;
+			if (! new)
+				return NULL;
+			ptepage = virt_to_page(new);
+			ptepage->mapping = (void *) mm;
+			ptepage->index = addr & HUGEPGDIR_MASK;
+			pgd_populate(mm, dir, new);
+		}
+	}
 
-	pmd = pmd_offset(pgd, addr);
+	return hugepte_offset(dir, addr);
+}
+
+static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
 
-	/* We shouldn't find a (normal) PTE page pointer here */
-	BUG_ON(!pmd_none(*pmd) && !pmd_hugepage(*pmd));
+	BUG_ON(! in_hugepage_area(mm->context, addr));
 
-	return (hugepte_t *)pmd;
+	pgd = hugepgd_offset(mm, addr);
+	if (! pgd)
+		return NULL;
+
+	return hugepte_offset(pgd, addr);
 }
 
-static void setup_huge_pte(struct mm_struct *mm, struct page *page,
-			   hugepte_t *ptep, int write_access)
+static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
-	hugepte_t entry;
-	int i;
+	pgd_t *pgd;
 
-	mm->rss += (HPAGE_SIZE / PAGE_SIZE);
-	entry = mk_hugepte(page, write_access);
-	for (i = 0; i < HUGEPTE_BATCH_SIZE; i++)
-		set_hugepte(ptep+i, entry);
+	BUG_ON(! in_hugepage_area(mm->context, addr));
+
+	pgd = hugepgd_alloc(mm, addr);
+	if (! pgd)
+		return NULL;
+
+	return hugepte_alloc(mm, pgd, addr);
 }
 
-static void teardown_huge_pte(hugepte_t *ptep)
+static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
+			 struct page *page, pte_t *ptep, int write_access)
 {
-	int i;
+	pte_t entry;
 
-	for (i = 0; i < HUGEPTE_BATCH_SIZE; i++)
-		pmd_clear((pmd_t *)(ptep+i));
+	mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	if (write_access) {
+		entry =
+		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+	} else {
+		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+	}
+	entry = pte_mkyoung(entry);
+	entry = pte_mkhuge(entry);
+
+	set_pte(ptep, entry);
 }
 
 /*
@@ -249,7 +276,7 @@
 {
 	if (within_hugepage_high_range(addr, len))
 		return 0;
-	else if ((addr < 0x100000000) && ((addr+len) < 0x100000000)) {
+	else if ((addr < 0x100000000UL) && ((addr+len) < 0x100000000UL)) {
 		int err;
 		/* Yes, we need both tests, in case addr+len overflows
 		 * 64-bit arithmetic */
@@ -268,34 +295,31 @@
 int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
 			struct vm_area_struct *vma)
 {
-	hugepte_t *src_pte, *dst_pte, entry;
+	pte_t *src_pte, *dst_pte, entry;
 	struct page *ptepage;
 	unsigned long addr = vma->vm_start;
 	unsigned long end = vma->vm_end;
+	int err = -ENOMEM;
 
 	while (addr < end) {
-		BUG_ON(! in_hugepage_area(src->context, addr));
-		BUG_ON(! in_hugepage_area(dst->context, addr));
-
-		dst_pte = hugepte_alloc(dst, addr);
+		dst_pte = huge_pte_alloc(dst, addr);
 		if (!dst_pte)
-			return -ENOMEM;
+			goto out;
 
-		src_pte = hugepte_offset(src, addr);
+		src_pte = huge_pte_offset(src, addr);
 		entry = *src_pte;
 		
-		if ((addr % HPAGE_SIZE) == 0) {
-			/* This is the first hugepte in a batch */
-			ptepage = hugepte_page(entry);
-			get_page(ptepage);
-			dst->rss += (HPAGE_SIZE / PAGE_SIZE);
-		}
-		set_hugepte(dst_pte, entry);
-
+		ptepage = pte_page(entry);
+		get_page(ptepage);
+		dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+		set_pte(dst_pte, entry);
 
-		addr += PMD_SIZE;
+		addr += HPAGE_SIZE;
 	}
-	return 0;
+
+	err = 0;
+ out:
+	return err;
 }
 
 int
@@ -310,18 +334,16 @@
 
 	vpfn = vaddr/PAGE_SIZE;
 	while (vaddr < vma->vm_end && remainder) {
-		BUG_ON(!in_hugepage_area(mm->context, vaddr));
-
 		if (pages) {
-			hugepte_t *pte;
+			pte_t *pte;
 			struct page *page;
 
-			pte = hugepte_offset(mm, vaddr);
+			pte = huge_pte_offset(mm, vaddr);
 
 			/* hugetlb should be locked, and hence, prefaulted */
-			WARN_ON(!pte || hugepte_none(*pte));
+			WARN_ON(!pte || pte_none(*pte));
 
-			page = &hugepte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
+			page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
 
 			WARN_ON(!PageCompound(page));
 
@@ -347,26 +369,31 @@
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
 {
-	return ERR_PTR(-EINVAL);
+	pte_t *ptep;
+	struct page *page;
+
+	if (! in_hugepage_area(mm->context, address))
+		return ERR_PTR(-EINVAL);
+
+	ptep = huge_pte_offset(mm, address);
+	page = pte_page(*ptep);
+	if (page)
+		page += (address % HPAGE_SIZE) / PAGE_SIZE;
+
+	return page;
 }
 
 int pmd_huge(pmd_t pmd)
 {
-	return pmd_hugepage(pmd);
+	return 0;
 }
 
 struct page *
 follow_huge_pmd(struct mm_struct *mm, unsigned long address,
 		pmd_t *pmd, int write)
 {
-	struct page *page;
-
-	BUG_ON(! pmd_hugepage(*pmd));
-
-	page = hugepte_page(*(hugepte_t *)pmd);
-	if (page)
-		page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT);
-	return page;
+	BUG();
+	return NULL;
 }
 
 void unmap_hugepage_range(struct vm_area_struct *vma,
@@ -374,44 +401,38 @@
 {
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long addr;
-	hugepte_t *ptep;
+	pte_t *ptep;
 	struct page *page;
-	int cpu;
-	int local = 0;
-	cpumask_t tmp;
 
 	WARN_ON(!is_vm_hugetlb_page(vma));
 	BUG_ON((start % HPAGE_SIZE) != 0);
 	BUG_ON((end % HPAGE_SIZE) != 0);
 
-	/* XXX are there races with checking cpu_vm_mask? - Anton */
-	cpu = get_cpu();
-	tmp = cpumask_of_cpu(cpu);
-	if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp))
-		local = 1;
-
 	for (addr = start; addr < end; addr += HPAGE_SIZE) {
-		hugepte_t pte;
-
-		BUG_ON(!in_hugepage_area(mm->context, addr));
+		pte_t pte;
 
-		ptep = hugepte_offset(mm, addr);
-		if (!ptep || hugepte_none(*ptep))
+		ptep = huge_pte_offset(mm, addr);
+		if (!ptep || pte_none(*ptep))
 			continue;
 
 		pte = *ptep;
-		page = hugepte_page(pte);
-		teardown_huge_pte(ptep);
-		
-		if (hugepte_val(pte) & _HUGEPAGE_HASHPTE)
-			flush_hash_hugepage(mm->context, addr,
-					    pte, local);
+		page = pte_page(pte);
+		pte_clear(ptep);
 
 		put_page(page);
 	}
-	put_cpu();
-
 	mm->rss -= (end - start) >> PAGE_SHIFT;
+	flush_tlb_pending();
+}
+
+void hugetlb_free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *prev,
+			   unsigned long start, unsigned long end)
+{
+	/* Because the huge pgtables are only 2 level, they can take
+	 * at most around 4M, much less than one hugepage which the
+	 * process is presumably entitled to use.  So we don't bother
+	 * freeing up the pagetables on unmap, and wait until
+	 * destroy_context() to clean up the lot. */
 }
 
 int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
@@ -427,16 +448,14 @@
 	spin_lock(&mm->page_table_lock);
 	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
 		unsigned long idx;
-		hugepte_t *pte = hugepte_alloc(mm, addr);
+		pte_t *pte = huge_pte_alloc(mm, addr);
 		struct page *page;
 
-		BUG_ON(!in_hugepage_area(mm->context, addr));
-
 		if (!pte) {
 			ret = -ENOMEM;
 			goto out;
 		}
-		if (!hugepte_none(*pte))
+		if (! pte_none(*pte))
 			continue;
 
 		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
@@ -463,7 +482,7 @@
 				goto out;
 			}
 		}
-		setup_huge_pte(mm, page, pte, vma->vm_flags & VM_WRITE);
+		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
 	}
 out:
 	spin_unlock(&mm->page_table_lock);
@@ -717,20 +736,55 @@
 	}
 }
 
+void hugetlb_mm_free_pgd(struct mm_struct *mm)
+{
+	int i;
+	pgd_t *pgdir;
+
+	spin_lock(&mm->page_table_lock);
+
+	pgdir = mm->context.huge_pgdir;
+	if (! pgdir)
+		return;
+
+	mm->context.huge_pgdir = NULL;
+
+	/* cleanup any hugepte pages leftover */
+	for (i = 0; i < PTRS_PER_HUGEPGD; i++) {
+		pgd_t *pgd = pgdir + i;
+
+		if (! pgd_none(*pgd)) {
+			pte_t *pte = (pte_t *)pgd_page(*pgd);
+			struct page *ptepage = virt_to_page(pte);
+
+			ptepage->mapping = NULL;
+
+			BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE));
+			kmem_cache_free(zero_cache, pte);
+		}
+		pgd_clear(pgd);
+	}
+
+	BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE));
+	kmem_cache_free(zero_cache, pgdir);
+
+	spin_unlock(&mm->page_table_lock);
+}
+
 int hash_huge_page(struct mm_struct *mm, unsigned long access,
 		   unsigned long ea, unsigned long vsid, int local)
 {
-	hugepte_t *ptep;
+	pte_t *ptep;
 	unsigned long va, vpn;
 	int is_write;
-	hugepte_t old_pte, new_pte;
-	unsigned long hpteflags, prpn, flags;
+	pte_t old_pte, new_pte;
+	unsigned long hpteflags, prpn;
 	long slot;
+	int err = 1;
+
+	spin_lock(&mm->page_table_lock);
 
-	/* We have to find the first hugepte in the batch, since
-	 * that's the one that will store the HPTE flags */
-	ea &= HPAGE_MASK;
-	ptep = hugepte_offset(mm, ea);
+	ptep = huge_pte_offset(mm, ea);
 
 	/* Search the Linux page table for a match with va */
 	va = (vsid << 28) | (ea & 0x0fffffff);
@@ -740,19 +794,18 @@
 	 * If no pte found or not present, send the problem up to
 	 * do_page_fault
 	 */
-	if (unlikely(!ptep || hugepte_none(*ptep)))
-		return 1;
+	if (unlikely(!ptep || pte_none(*ptep)))
+		goto out;
 
-	BUG_ON(hugepte_bad(*ptep));
+/* 	BUG_ON(pte_bad(*ptep)); */
 
 	/* 
 	 * Check the user's access rights to the page.  If access should be
 	 * prevented then send the problem up to do_page_fault.
 	 */
 	is_write = access & _PAGE_RW;
-	if (unlikely(is_write && !(hugepte_val(*ptep) & _HUGEPAGE_RW)))
-		return 1;
-
+	if (unlikely(is_write && !(pte_val(*ptep) & _PAGE_RW)))
+		goto out;
 	/*
 	 * At this point, we have a pte (old_pte) which can be used to build
 	 * or update an HPTE. There are 2 cases:
@@ -765,41 +818,40 @@
 	 *	page is currently not DIRTY. 
 	 */
 
-	spin_lock_irqsave(&mm->page_table_lock, flags);
 
 	old_pte = *ptep;
 	new_pte = old_pte;
 
-	hpteflags = 0x2 | (! (hugepte_val(new_pte) & _HUGEPAGE_RW));
+	hpteflags = 0x2 | (! (pte_val(new_pte) & _PAGE_RW));
 
 	/* Check if pte already has an hpte (case 2) */
-	if (unlikely(hugepte_val(old_pte) & _HUGEPAGE_HASHPTE)) {
+	if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) {
 		/* There MIGHT be an HPTE for this pte */
 		unsigned long hash, slot;
 
 		hash = hpt_hash(vpn, 1);
-		if (hugepte_val(old_pte) & _HUGEPAGE_SECONDARY)
+		if (pte_val(old_pte) & _PAGE_SECONDARY)
 			hash = ~hash;
 		slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-		slot += (hugepte_val(old_pte) & _HUGEPAGE_GROUP_IX) >> 5;
+		slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12;
 
 		if (ppc_md.hpte_updatepp(slot, hpteflags, va, 1, local) == -1)
-			hugepte_val(old_pte) &= ~_HUGEPAGE_HPTEFLAGS;
+			pte_val(old_pte) &= ~_PAGE_HPTEFLAGS;
 	}
 
-	if (likely(!(hugepte_val(old_pte) & _HUGEPAGE_HASHPTE))) {
+	if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) {
 		unsigned long hash = hpt_hash(vpn, 1);
 		unsigned long hpte_group;
 
-		prpn = hugepte_pfn(old_pte);
+		prpn = pte_pfn(old_pte);
 
 repeat:
 		hpte_group = ((hash & htab_data.htab_hash_mask) *
 			      HPTES_PER_GROUP) & ~0x7UL;
 
 		/* Update the linux pte with the HPTE slot */
-		hugepte_val(new_pte) &= ~_HUGEPAGE_HPTEFLAGS;
-		hugepte_val(new_pte) |= _HUGEPAGE_HASHPTE;
+		pte_val(new_pte) &= ~_PAGE_HPTEFLAGS;
+		pte_val(new_pte) |= _PAGE_HASHPTE;
 
 		/* Add in WIMG bits */
 		/* XXX We should store these in the pte */
@@ -810,7 +862,7 @@
 
 		/* Primary is full, try the secondary */
 		if (unlikely(slot == -1)) {
-			hugepte_val(new_pte) |= _HUGEPAGE_SECONDARY;
+			pte_val(new_pte) |= _PAGE_SECONDARY;
 			hpte_group = ((~hash & htab_data.htab_hash_mask) *
 				      HPTES_PER_GROUP) & ~0x7UL; 
 			slot = ppc_md.hpte_insert(hpte_group, va, prpn,
@@ -827,39 +879,20 @@
 		if (unlikely(slot == -2))
 			panic("hash_huge_page: pte_insert failed\n");
 
-		hugepte_val(new_pte) |= (slot<<5) & _HUGEPAGE_GROUP_IX;
+		pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX;
 
 		/* 
 		 * No need to use ldarx/stdcx here because all who
 		 * might be updating the pte will hold the
-		 * page_table_lock or the hash_table_lock
-		 * (we hold both)
+		 * page_table_lock
 		 */
 		*ptep = new_pte;
 	}
 
-	spin_unlock_irqrestore(&mm->page_table_lock, flags);
-
-	return 0;
-}
-
-static void flush_hash_hugepage(mm_context_t context, unsigned long ea,
-				hugepte_t pte, int local)
-{
-	unsigned long vsid, vpn, va, hash, slot;
-
-	BUG_ON(hugepte_bad(pte));
-	BUG_ON(!in_hugepage_area(context, ea));
-
-	vsid = get_vsid(context.id, ea);
+	err = 0;
 
-	va = (vsid << 28) | (ea & 0x0fffffff);
-	vpn = va >> HPAGE_SHIFT;
-	hash = hpt_hash(vpn, 1);
-	if (hugepte_val(pte) & _HUGEPAGE_SECONDARY)
-		hash = ~hash;
-	slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
-	slot += (hugepte_val(pte) & _HUGEPAGE_GROUP_IX) >> 5;
+ out:
+	spin_unlock(&mm->page_table_lock);
 
-	ppc_md.hpte_invalidate(slot, va, 1, local);
+	return err;
 }
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/mm/init.c	2004-10-28 22:25:58 -07:00
@@ -263,7 +263,8 @@
 		 */
 		;
 	} else {
-		area = im_get_area(ea, size, IM_REGION_UNUSED|IM_REGION_SUBSET);
+		area = im_get_area(ea, size,
+			IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS);
 		if (area == NULL) {
 			/* Expected when PHB-dlpar is in play */
 			return 1;
@@ -477,6 +478,12 @@
 	int index;
 	int err;
 
+#ifdef CONFIG_HUGETLB_PAGE
+	/* We leave htlb_segs as it was, but for a fork, we need to
+	 * clear the huge_pgdir. */
+	mm->context.huge_pgdir = NULL;
+#endif
+
 again:
 	if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
 		return -ENOMEM;
@@ -507,6 +514,8 @@
 	spin_unlock(&mmu_context_lock);
 
 	mm->context.id = NO_CONTEXT;
+
+	hugetlb_mm_free_pgd(mm);
 }
 
 static int __init mmu_context_init(void)
@@ -873,14 +882,14 @@
 	local_irq_restore(flags);
 }
 
-void * reserve_phb_iospace(unsigned long size)
+void __iomem * reserve_phb_iospace(unsigned long size)
 {
-	void *virt_addr;
+	void __iomem *virt_addr;
 		
 	if (phbs_io_bot >= IMALLOC_BASE) 
 		panic("reserve_phb_iospace(): phb io space overflow\n");
 			
-	virt_addr = (void *) phbs_io_bot;
+	virt_addr = (void __iomem *) phbs_io_bot;
 	phbs_io_bot += size;
 
 	return virt_addr;
diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
--- a/arch/ppc64/mm/numa.c	2004-10-28 22:25:58 -07:00
+++ b/arch/ppc64/mm/numa.c	2004-10-28 22:25:58 -07:00
@@ -15,6 +15,8 @@
 #include <linux/mmzone.h>
 #include <linux/module.h>
 #include <linux/nodemask.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
 #include <asm/lmb.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
@@ -39,6 +41,7 @@
 struct pglist_data *node_data[MAX_NUMNODES];
 bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
 static unsigned long node0_io_hole_size;
+static int min_common_depth;
 
 /*
  * We need somewhere to store start/span for each node until we have
@@ -64,7 +67,24 @@
 	}
 }
 
-static struct device_node * __init find_cpu_node(unsigned int cpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static void unmap_cpu_from_node(unsigned long cpu)
+{
+	int node = numa_cpu_lookup_table[cpu];
+
+	dbg("removing cpu %lu from node %d\n", cpu, node);
+
+	if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
+		cpu_clear(cpu, numa_cpumask_lookup_table[node]);
+		nr_cpus_in_node[node]--;
+	} else {
+		printk(KERN_ERR "WARNING: cpu %lu not found in node %d\n",
+		       cpu, node);
+	}
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static struct device_node * __devinit find_cpu_node(unsigned int cpu)
 {
 	unsigned int hw_cpuid = get_hard_smp_processor_id(cpu);
 	struct device_node *cpu_node = NULL;
@@ -96,26 +116,21 @@
 
 /* must hold reference to node during call */
 static int *of_get_associativity(struct device_node *dev)
- {
-	unsigned int *result;
-	int len;
-
-	result = (unsigned int *)get_property(dev, "ibm,associativity", &len);
-
-	if (len <= 0)
-		return NULL;
-
-	return result;
+{
+	return (unsigned int *)get_property(dev, "ibm,associativity", NULL);
 }
 
-static int of_node_numa_domain(struct device_node *device, int depth)
+static int of_node_numa_domain(struct device_node *device)
 {
 	int numa_domain;
 	unsigned int *tmp;
 
+	if (min_common_depth == -1)
+		return 0;
+
 	tmp = of_get_associativity(device);
-	if (tmp && (tmp[0] >= depth)) {
-		numa_domain = tmp[depth];
+	if (tmp && (tmp[0] >= min_common_depth)) {
+		numa_domain = tmp[min_common_depth];
 	} else {
 		dbg("WARNING: no NUMA information for %s\n",
 		    device->full_name);
@@ -138,7 +153,7 @@
  *
  * - Dave Hansen <haveblue@us.ibm.com>
  */
-static int find_min_common_depth(void)
+static int __init find_min_common_depth(void)
 {
 	int depth;
 	unsigned int *ref_points;
@@ -185,11 +200,72 @@
 	return result;
 }
 
+/*
+ * Figure out to which domain a cpu belongs and stick it there.
+ * Return the id of the domain used.
+ */
+static int numa_setup_cpu(unsigned long lcpu)
+{
+	int numa_domain = 0;
+	struct device_node *cpu = find_cpu_node(lcpu);
+
+	if (!cpu) {
+		WARN_ON(1);
+		goto out;
+	}
+
+	numa_domain = of_node_numa_domain(cpu);
+
+	if (numa_domain >= MAX_NUMNODES) {
+		/*
+		 * POWER4 LPAR uses 0xffff as invalid node,
+		 * dont warn in this case.
+		 */
+		if (numa_domain != 0xffff)
+			printk(KERN_ERR "WARNING: cpu %ld "
+			       "maps to invalid NUMA node %d\n",
+			       lcpu, numa_domain);
+		numa_domain = 0;
+	}
+out:
+	node_set_online(numa_domain);
+
+	map_cpu_to_node(lcpu, numa_domain);
+
+	of_node_put(cpu);
+
+	return numa_domain;
+}
+
+static int cpu_numa_callback(struct notifier_block *nfb,
+			     unsigned long action,
+			     void *hcpu)
+{
+	unsigned long lcpu = (unsigned long)hcpu;
+	int ret = NOTIFY_DONE;
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+		if (min_common_depth == -1 || !numa_enabled)
+			map_cpu_to_node(lcpu, 0);
+		else
+			numa_setup_cpu(lcpu);
+		ret = NOTIFY_OK;
+		break;
+#ifdef CONFIG_HOTPLUG_CPU
+	case CPU_DEAD:
+	case CPU_UP_CANCELED:
+		unmap_cpu_from_node(lcpu);
+		break;
+		ret = NOTIFY_OK;
+#endif
+	}
+	return ret;
+}
+
 static int __init parse_numa_properties(void)
 {
-	struct device_node *cpu = NULL;
 	struct device_node *memory = NULL;
-	int depth;
 	int max_domain = 0;
 	long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT;
 	unsigned long i;
@@ -206,44 +282,13 @@
 	for (i = 0; i < entries ; i++)
 		numa_memory_lookup_table[i] = ARRAY_INITIALISER;
 
-	depth = find_min_common_depth();
-
-	dbg("NUMA associativity depth for CPU/Memory: %d\n", depth);
-	if (depth < 0)
-		return depth;
-
-	for_each_cpu(i) {
-		int numa_domain;
-
-		cpu = find_cpu_node(i);
-
-		if (cpu) {
-			numa_domain = of_node_numa_domain(cpu, depth);
-			of_node_put(cpu);
-
-			if (numa_domain >= MAX_NUMNODES) {
-				/*
-			 	 * POWER4 LPAR uses 0xffff as invalid node,
-				 * dont warn in this case.
-			 	 */
-				if (numa_domain != 0xffff)
-					printk(KERN_ERR "WARNING: cpu %ld "
-					       "maps to invalid NUMA node %d\n",
-					       i, numa_domain);
-				numa_domain = 0;
-			}
-		} else {
-			dbg("WARNING: no NUMA information for cpu %ld\n", i);
-			numa_domain = 0;
-		}
-
-		node_set_online(numa_domain);
+	min_common_depth = find_min_common_depth();
 
-		if (max_domain < numa_domain)
-			max_domain = numa_domain;
+	dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth);
+	if (min_common_depth < 0)
+		return min_common_depth;
 
-		map_cpu_to_node(i, numa_domain);
-	}
+	max_domain = numa_setup_cpu(boot_cpuid);
 
 	memory = NULL;
 	while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
@@ -267,7 +312,7 @@
 		start = _ALIGN_DOWN(start, MEMORY_INCREMENT);
 		size = _ALIGN_UP(size, MEMORY_INCREMENT);
 
-		numa_domain = of_node_numa_domain(memory, depth);
+		numa_domain = of_node_numa_domain(memory);
 
 		if (numa_domain >= MAX_NUMNODES) {
 			if (numa_domain != 0xffff)
@@ -341,8 +386,7 @@
 			numa_memory_lookup_table[i] = ARRAY_INITIALISER;
 	}
 
-	for (i = 0; i < NR_CPUS; i++)
-		map_cpu_to_node(i, 0);
+	map_cpu_to_node(boot_cpuid, 0);
 
 	node_set_online(0);
 
@@ -358,35 +402,10 @@
 static void __init dump_numa_topology(void)
 {
 	unsigned int node;
-	unsigned int cpu, count;
+	unsigned int count;
 
-	for (node = 0; node < MAX_NUMNODES; node++) {
-		if (!node_online(node))
-			continue;
-
-		printk(KERN_INFO "Node %d CPUs:", node);
-
-		count = 0;
-		/*
-		 * If we used a CPU iterator here we would miss printing
-		 * the holes in the cpumap.
-		 */
-		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
-				if (count == 0)
-					printk(" %u", cpu);
-				++count;
-			} else {
-				if (count > 1)
-					printk("-%u", cpu - 1);
-				count = 0;
-			}
-		}
-
-		if (count > 1)
-			printk("-%u", NR_CPUS - 1);
-		printk("\n");
-	}
+	if (min_common_depth == -1 || !numa_enabled)
+		return;
 
 	for (node = 0; node < MAX_NUMNODES; node++) {
 		unsigned long i;
@@ -414,6 +433,7 @@
 			printk("-0x%lx", i);
 		printk("\n");
 	}
+	return;
 }
 
 /*
@@ -460,6 +480,10 @@
 void __init do_init_bootmem(void)
 {
 	int nid;
+	static struct notifier_block ppc64_numa_nb = {
+		.notifier_call = cpu_numa_callback,
+		.priority = 1 /* Must run before sched domains notifier. */
+	};
 
 	min_low_pfn = 0;
 	max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
@@ -469,6 +493,8 @@
 		setup_nonnuma();
 	else
 		dump_numa_topology();
+
+	register_cpu_notifier(&ppc64_numa_nb);
 
 	for (nid = 0; nid < numnodes; nid++) {
 		unsigned long start_paddr, end_paddr;
diff -Nru a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c
--- a/arch/ppc64/xmon/start.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/xmon/start.c	2004-10-28 22:25:59 -07:00
@@ -35,7 +35,7 @@
 {
 	.handler =	sysrq_handle_xmon,
 	.help_msg =	"Xmon",
-	.action_msg =	"Entering xmon\n",
+	.action_msg =	"Entering xmon",
 };
 
 static int __init setup_xmon_sysrq(void)
@@ -173,7 +173,7 @@
 		c = xmon_getchar();
 		if (c == -1) {
 			if (p == str)
-				return 0;
+				return NULL;
 			break;
 		}
 		*p++ = c;
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	2004-10-28 22:25:59 -07:00
+++ b/arch/ppc64/xmon/xmon.c	2004-10-28 22:25:59 -07:00
@@ -645,7 +645,7 @@
 	for (i = 0; i < NBPTS; ++i, ++bp)
 		if (bp->enabled && pc == bp->address)
 			return bp;
-	return 0;
+	return NULL;
 }
 
 static struct bpt *in_breakpoint_table(unsigned long nip, unsigned long *offp)
@@ -1582,7 +1582,7 @@
 extern char dec_exc;
 
 void
-super_regs()
+super_regs(void)
 {
 	int cmd;
 	unsigned long val;
@@ -1816,7 +1816,7 @@
     "";
 
 void
-memex()
+memex(void)
 {
 	int cmd, inc, i, nslash;
 	unsigned long n;
@@ -1967,7 +1967,7 @@
 }
 
 int
-bsesc()
+bsesc(void)
 {
 	int c;
 
@@ -1985,7 +1985,7 @@
 			 || ('a' <= (c) && (c) <= 'f') \
 			 || ('A' <= (c) && (c) <= 'F'))
 void
-dump()
+dump(void)
 {
 	int c;
 
@@ -2150,7 +2150,7 @@
 static unsigned mask;
 
 void
-memlocate()
+memlocate(void)
 {
 	unsigned a, n;
 	unsigned char val[4];
@@ -2183,7 +2183,7 @@
 static unsigned long mlim = 0xffffffff;
 
 void
-memzcan()
+memzcan(void)
 {
 	unsigned char v;
 	unsigned a;
@@ -2212,7 +2212,7 @@
 
 /* Input scanning routines */
 int
-skipbl()
+skipbl(void)
 {
 	int c;
 
@@ -2237,8 +2237,7 @@
 };
 
 int
-scanhex(vp)
-unsigned long *vp;
+scanhex(unsigned long *vp)
 {
 	int c, d;
 	unsigned long v;
@@ -2322,7 +2321,7 @@
 }
 
 void
-scannl()
+scannl(void)
 {
 	int c;
 
@@ -2365,13 +2364,13 @@
 static char *lineptr;
 
 void
-flush_input()
+flush_input(void)
 {
 	lineptr = NULL;
 }
 
 int
-inchar()
+inchar(void)
 {
 	if (lineptr == NULL || *lineptr == 0) {
 		if (fgets(line, sizeof(line), stdin) == NULL) {
@@ -2384,8 +2383,7 @@
 }
 
 void
-take_input(str)
-char *str;
+take_input(char *str)
 {
 	lineptr = str;
 }
diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig
--- a/arch/s390/defconfig	2004-10-28 22:25:59 -07:00
+++ b/arch/s390/defconfig	2004-10-28 22:25:59 -07:00
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc3
-# Fri Oct  8 19:17:35 2004
+# Linux kernel version: 2.6.9
+# Fri Oct 22 13:50:22 2004
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -26,6 +26,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
@@ -49,6 +50,7 @@
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
@@ -144,6 +146,7 @@
 # SCSI low-level drivers
 #
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_QLOGIC_1280_1040 is not set
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_ZFCP=y
 CONFIG_CCW=y
@@ -157,7 +160,9 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
 # S/390 block device drivers
@@ -224,6 +229,7 @@
 CONFIG_S390_TAPE_34XX=m
 # CONFIG_VMLOGRDR is not set
 # CONFIG_MONREADER is not set
+# CONFIG_DCSS_SHM is not set
 
 #
 # Cryptographic devices
@@ -427,6 +433,7 @@
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -506,6 +513,7 @@
 #
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_INFO is not set
@@ -513,6 +521,7 @@
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
diff -Nru a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
--- a/arch/s390/kernel/asm-offsets.c	2004-10-28 22:25:57 -07:00
+++ b/arch/s390/kernel/asm-offsets.c	2004-10-28 22:25:57 -07:00
@@ -22,6 +22,8 @@
 	DEFINE(__THREAD_mm_segment,
 	       offsetof(struct task_struct, thread.mm_segment),);
 	BLANK();
+	DEFINE(__TASK_pid, offsetof(struct task_struct, pid),);
+	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),);
diff -Nru a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
--- a/arch/s390/kernel/cpcmd.c	2004-10-28 22:25:58 -07:00
+++ b/arch/s390/kernel/cpcmd.c	2004-10-28 22:25:58 -07:00
@@ -15,7 +15,7 @@
 #include <asm/system.h>
 
 static spinlock_t cpcmd_lock = SPIN_LOCK_UNLOCKED;
-static char cpcmd_buf[128];
+static char cpcmd_buf[240];
 
 void cpcmd(char *cmd, char *response, int rlen)
 {
@@ -24,22 +24,23 @@
         int cmdlen;
 
 	spin_lock_irqsave(&cpcmd_lock, flags);
-        cmdlen = strlen(cmd);
-        strcpy(cpcmd_buf, cmd);
-        ASCEBC(cpcmd_buf, cmdlen);
+	cmdlen = strlen(cmd);
+	BUG_ON(cmdlen>240);
+	strcpy(cpcmd_buf, cmd);
+	ASCEBC(cpcmd_buf, cmdlen);
 
-        if (response != NULL && rlen > 0) {
+	if (response != NULL && rlen > 0) {
 #ifndef CONFIG_ARCH_S390X
                 asm volatile ("LRA   2,0(%0)\n\t"
                               "LR    4,%1\n\t"
                               "O     4,%4\n\t"
                               "LRA   3,0(%2)\n\t"
                               "LR    5,%3\n\t"
-                              ".long 0x83240008 # Diagnose 83\n\t"
+                              ".long 0x83240008 # Diagnose X'08'\n\t"
                               : /* no output */
                               : "a" (cpcmd_buf), "d" (cmdlen),
                                 "a" (response), "d" (rlen), "m" (mask)
-                              : "2", "3", "4", "5" );
+                              : "cc", "2", "3", "4", "5" );
 #else /* CONFIG_ARCH_S390X */
                 asm volatile ("   lrag  2,0(%0)\n"
                               "   lgr   4,%1\n"
@@ -47,19 +48,19 @@
                               "   lrag  3,0(%2)\n"
                               "   lgr   5,%3\n"
                               "   sam31\n"
-                              "   .long 0x83240008 # Diagnose 83\n"
+                              "   .long 0x83240008 # Diagnose X'08'\n"
                               "   sam64"
                               : /* no output */
                               : "a" (cpcmd_buf), "d" (cmdlen),
                                 "a" (response), "d" (rlen), "m" (mask)
-                              : "2", "3", "4", "5" );
+                              : "cc", "2", "3", "4", "5" );
 #endif /* CONFIG_ARCH_S390X */
                 EBCASC(response, rlen);
         } else {
 #ifndef CONFIG_ARCH_S390X
                 asm volatile ("LRA   2,0(%0)\n\t"
                               "LR    3,%1\n\t"
-                              ".long 0x83230008 # Diagnose 83\n\t"
+                              ".long 0x83230008 # Diagnose X'08'\n\t"
                               : /* no output */
                               : "a" (cpcmd_buf), "d" (cmdlen)
                               : "2", "3"  );
@@ -67,7 +68,7 @@
                 asm volatile ("   lrag  2,0(%0)\n"
                               "   lgr   3,%1\n"
                               "   sam31\n"
-                              "   .long 0x83230008 # Diagnose 83\n"
+                              "   .long 0x83230008 # Diagnose X'08'\n"
                               "   sam64"
                               : /* no output */
                               : "a" (cpcmd_buf), "d" (cmdlen)
diff -Nru a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
--- a/arch/s390/kernel/debug.c	2004-10-28 22:25:57 -07:00
+++ b/arch/s390/kernel/debug.c	2004-10-28 22:25:57 -07:00
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
+#include <linux/sysctl.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -708,6 +709,70 @@
 		proceed_active_area(id);
 }
 
+static int debug_stoppable=1;
+static int debug_active=1;
+
+#define CTL_S390DBF 5677
+#define CTL_S390DBF_STOPPABLE 5678
+#define CTL_S390DBF_ACTIVE 5679
+
+/*
+ * proc handler for the running debug_active sysctl
+ * always allow read, allow write only if debug_stoppable is set or
+ * if debug_active is already off
+ */
+static int s390dbf_procactive(ctl_table *table, int write, struct file *filp,
+                     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	if (!write || debug_stoppable || !debug_active)
+		return proc_dointvec(table, write, filp, buffer, lenp, ppos);
+	else
+		return 0;
+}
+
+
+static struct ctl_table s390dbf_table[] = {
+	{
+		.ctl_name       = CTL_S390DBF_STOPPABLE,
+		.procname       = "debug_stoppable",
+		.data		= &debug_stoppable,
+		.maxlen		= sizeof(int),
+		.mode           = S_IRUGO | S_IWUSR,
+		.proc_handler   = &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+	},
+	 {
+		.ctl_name       = CTL_S390DBF_ACTIVE,
+		.procname       = "debug_active",
+		.data		= &debug_active,
+		.maxlen		= sizeof(int),
+		.mode           = S_IRUGO | S_IWUSR,
+		.proc_handler   = &s390dbf_procactive,
+		.strategy	= &sysctl_intvec,
+	},
+	{ .ctl_name = 0 }
+};
+
+static struct ctl_table s390dbf_dir_table[] = {
+	{
+		.ctl_name       = CTL_S390DBF,
+		.procname       = "s390dbf",
+		.maxlen         = 0,
+		.mode           = S_IRUGO | S_IXUGO,
+		.child          = s390dbf_table,
+	},
+	{ .ctl_name = 0 }
+};
+
+struct ctl_table_header *s390dbf_sysctl_header;
+
+void debug_stop_all(void)
+{
+	if (debug_stoppable)
+		debug_active = 0;
+}
+
+
 /*
  * debug_event_common:
  * - write debug entry with given size
@@ -719,6 +784,8 @@
 	unsigned long flags;
 	debug_entry_t *active;
 
+	if (!debug_active)
+		return NULL;
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
 	memset(DEBUG_DATA(active), 0, id->buf_size);
@@ -740,6 +807,8 @@
 	unsigned long flags;
 	debug_entry_t *active;
 
+	if (!debug_active)
+		return NULL;
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
 	memset(DEBUG_DATA(active), 0, id->buf_size);
@@ -780,7 +849,8 @@
 
 	if((!id) || (level > id->level))
 		return NULL;
-
+	if (!debug_active)
+		return NULL;
 	numargs=debug_count_numargs(string);
 
 	spin_lock_irqsave(&id->lock, flags);
@@ -812,6 +882,8 @@
 
 	if((!id) || (level > id->level))
 		return NULL;
+	if (!debug_active)
+		return NULL;
 
 	numargs=debug_count_numargs(string);
 
@@ -838,6 +910,7 @@
 {
 	int rc = 0;
 
+	s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1);
 	down(&debug_lock);
 #ifdef CONFIG_PROC_FS
 	debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL);
@@ -1186,6 +1259,7 @@
 #ifdef CONFIG_PROC_FS
 	remove_proc_entry(debug_proc_root_entry->name, NULL);
 #endif /* CONFIG_PROC_FS */
+	unregister_sysctl_table(s390dbf_sysctl_header);
 	return;
 }
 
@@ -1199,6 +1273,7 @@
 EXPORT_SYMBOL(debug_register);
 EXPORT_SYMBOL(debug_unregister); 
 EXPORT_SYMBOL(debug_set_level);
+EXPORT_SYMBOL(debug_stop_all);
 EXPORT_SYMBOL(debug_register_view);
 EXPORT_SYMBOL(debug_unregister_view);
 EXPORT_SYMBOL(debug_event_common);
diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	2004-10-28 22:25:57 -07:00
+++ b/arch/s390/kernel/entry.S	2004-10-28 22:25:57 -07:00
@@ -144,6 +144,7 @@
 	l	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
 	lm	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	st	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
+	lctl	%c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
 	l	%r3,__THREAD_info(%r3)  # load thread_info from task struct
 	st	%r3,__LC_THREAD_INFO
 	ahi	%r3,STACK_SIZE
diff -Nru a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
--- a/arch/s390/kernel/entry64.S	2004-10-28 22:25:57 -07:00
+++ b/arch/s390/kernel/entry64.S	2004-10-28 22:25:57 -07:00
@@ -141,6 +141,7 @@
 	lg	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
         lmg     %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	stg	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
+	lctl	%c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4
 	lg	%r3,__THREAD_info(%r3)  # load thread_info from task struct
 	stg	%r3,__LC_THREAD_INFO
 	aghi	%r3,STACK_SIZE
diff -Nru a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
--- a/arch/s390/kernel/irq.c	2004-10-28 22:25:58 -07:00
+++ b/arch/s390/kernel/irq.c	2004-10-28 22:25:58 -07:00
@@ -86,7 +86,7 @@
 				     "   la    15,0(%1)\n"
 				     : : "a" (new), "a" (old),
 				         "a" (__do_softirq)
-				     : "0", "1", "2", "3", "4", "5",
+				     : "0", "1", "2", "3", "4", "5", "14",
 				       "cc", "memory" );
 		} else
 			/* We are already on the async stack. */
diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
--- a/arch/s390/kernel/traps.c	2004-10-28 22:25:57 -07:00
+++ b/arch/s390/kernel/traps.c	2004-10-28 22:25:57 -07:00
@@ -38,6 +38,7 @@
 #include <asm/cpcmd.h>
 #include <asm/s390_ext.h>
 #include <asm/lowcore.h>
+#include <asm/debug.h>
 
 /* Called from entry.S only */
 extern void handle_per_exception(struct pt_regs *regs);
@@ -277,8 +278,10 @@
 void die(const char * str, struct pt_regs * regs, long err)
 {
 	static int die_counter;
-        console_verbose();
-        spin_lock_irq(&die_lock);
+
+	debug_stop_all();
+	console_verbose();
+	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
         show_regs(regs);
@@ -630,6 +633,21 @@
 	}
 }
 
+asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code)
+{
+        siginfo_t info;
+
+	/* Set user psw back to home space mode. */
+	if (regs->psw.mask & PSW_MASK_PSTATE)
+		regs->psw.mask |= PSW_ASC_HOME;
+	/* Send SIGILL. */
+        info.si_signo = SIGILL;
+        info.si_errno = 0;
+        info.si_code = ILL_PRVOPC;
+        info.si_addr = get_check_address(regs);
+        do_trap(int_code, SIGILL, "space switch event", regs, &info);
+}
+
 asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
 {
 	die("Kernel stack overflow", regs, 0);
@@ -673,7 +691,7 @@
         pgm_check_table[0x3B] = &do_dat_exception;
 #endif /* CONFIG_ARCH_S390X */
         pgm_check_table[0x15] = &operand_exception;
-        pgm_check_table[0x1C] = &privileged_op;
+        pgm_check_table[0x1C] = &space_switch_exception;
         pgm_check_table[0x1D] = &hfp_sqrt_exception;
 	pgm_check_table[0x40] = &do_monitor_call;
 
diff -Nru a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
--- a/arch/s390/mm/extmem.c	2004-10-28 22:25:59 -07:00
+++ b/arch/s390/mm/extmem.c	2004-10-28 22:25:59 -07:00
@@ -1,11 +1,10 @@
 /*
- * File...........: arch/s390/mm/dcss.c
- * Author(s)......: Steven Shultz <shultzss@us.ibm.com>
- *                  Carsten Otte <cotte@de.ibm.com>
+ * File...........: arch/s390/mm/extmem.c
+ * Author(s)......: Carsten Otte <cotte@de.ibm.com>
+ * 		    Rob M van der Heij <rvdheij@nl.ibm.com>
+ * 		    Steven Shultz <shultzss@us.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * thanks to Rob M van der Heij
- * - he wrote the diag64 function
- * (C) IBM Corporation 2002
+ * (C) IBM Corporation 2002-2004
  */
 
 #include <linux/kernel.h>
@@ -43,18 +42,38 @@
 #define DCSS_SEGEXT     0x18
 #define DCSS_QACTV      0x0c
 
+struct qout64 {
+	int segstart;
+	int segend;
+	int segcnt;
+	int segrcnt;
+	char segout[8][6];
+};
+
+struct qin64 {
+	char qopcode;
+	char rsrv1[3];
+	char qrcode;
+	char rsrv2[3];
+	char qname[8];
+	unsigned int qoutptr;
+	short int qoutlen;
+};
+
 struct dcss_segment {
-        struct list_head list;
-        char dcss_name[8];
-        unsigned long start_addr;
-        unsigned long end;
-        atomic_t ref_count;
-        int dcss_attr;
-	int shared_attr;
+	struct list_head list;
+	char dcss_name[8];
+	unsigned long start_addr;
+	unsigned long end;
+	atomic_t ref_count;
+	int do_nonshared;
+	int vm_segtype;
 };
 
 static spinlock_t dcss_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list);
+static char *segtype_string[7] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC" };
+
 extern struct {
 	unsigned long addr, size, type;
 } memory_chunk[MEMORY_CHUNKS];
@@ -63,20 +82,46 @@
  * Create the 8 bytes, ebcdic VM segment name from
  * an ascii name.
  */
-static void inline dcss_mkname(char *name, char *dcss_name)
+static void inline
+dcss_mkname(char *name, char *dcss_name)
 {
-        int i;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		if (name[i] == '\0')
+			break;
+		dcss_name[i] = toupper(name[i]);
+	};
+	for (; i < 8; i++)
+		dcss_name[i] = ' ';
+	ASCEBC(dcss_name, 8);
+}
 
-        for (i = 0; i <= 8; i++) {
-                if (name[i] == '\0')
-                        break;
-                dcss_name[i] = toupper(name[i]);
-        };
-        for (; i <= 8; i++)
-                dcss_name[i] = ' ';
-        ASCEBC(dcss_name, 8);
+
+/*
+ * search all segments in dcss_list, and return the one
+ * namend *name. If not found, return NULL.
+ */
+static struct dcss_segment *
+segment_by_name (char *name)
+{
+	char dcss_name[9];
+	struct list_head *l;
+	struct dcss_segment *tmp, *retval = NULL;
+
+	BUG_ON (!spin_is_locked(&dcss_lock));
+	dcss_mkname (name, dcss_name);
+	list_for_each (l, &dcss_list) {
+		tmp = list_entry (l, struct dcss_segment, list);
+		if (memcmp(tmp->dcss_name, dcss_name, 8) == 0) {
+			retval = tmp;
+			break;
+		}
+	}
+	return retval;
 }
 
+
 /*
  * Perform a function on a dcss segment.
  */
@@ -84,337 +129,270 @@
 dcss_diag (__u8 func, void *parameter,
            unsigned long *ret1, unsigned long *ret2)
 {
-        unsigned long rx, ry;
-        int rc;
+	unsigned long rx, ry;
+	int rc;
 
-        rx = (unsigned long) parameter;
-        ry = (unsigned long) func;
-        __asm__ __volatile__(
+	rx = (unsigned long) parameter;
+	ry = (unsigned long) func;
+	__asm__ __volatile__(
 #ifdef CONFIG_ARCH_S390X
-                             "   sam31\n" // switch to 31 bit
-                             "   diag    %0,%1,0x64\n"
-                             "   sam64\n" // switch back to 64 bit
+		"   sam31\n" // switch to 31 bit
+		"   diag    %0,%1,0x64\n"
+		"   sam64\n" // switch back to 64 bit
 #else
-                             "   diag    %0,%1,0x64\n"
+		"   diag    %0,%1,0x64\n"
 #endif
-                             "   ipm     %2\n"
-                             "   srl     %2,28\n"
-                             : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
-        *ret1 = rx;
-        *ret2 = ry;
-        return rc;
+		"   ipm     %2\n"
+		"   srl     %2,28\n"
+		: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
+	*ret1 = rx;
+	*ret2 = ry;
+	return rc;
 }
 
-
-/* use to issue "extended" dcss query */
 static inline int
-dcss_diag_query(char *name, int *rwattr, int *shattr, unsigned long *segstart, unsigned long *segend)
+dcss_diag_translate_rc (int vm_rc) {
+	if (vm_rc == 44)
+		return -ENOENT;
+	return -EIO;
+}
+
+
+/* do a diag to get info about a segment.
+ * fills start_address, end and vm_segtype fields
+ */
+static int
+query_segment_info (struct dcss_segment *seg)
 {
-        int i,j,rc;
-        unsigned long  rx, ry;
+	struct qin64  *qin = kmalloc (sizeof(struct qin64), GFP_DMA);
+	struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA);
 
-        typedef struct segentry {
-                char thisseg[8];
-        } segentry;
-
-        struct qout64 {
-                int segstart;
-                int segend;
-                int segcnt;
-                int segrcnt;
-                segentry segout[6];
-        };
-
-        struct qin64 {
-                char qopcode;
-                char rsrv1[3];
-                char qrcode;
-                char rsrv2[3];
-                char qname[8];
-                unsigned int qoutptr;
-                short int qoutlen;
-        };
-
-
-        struct qin64  *qinarea;
-        struct qout64 *qoutarea;
-
-        qinarea = (struct qin64*) get_zeroed_page (GFP_DMA);
-        if (!qinarea) {
-                rc =-ENOMEM;
-                goto out;
-        }
-        qoutarea = (struct qout64*) get_zeroed_page (GFP_DMA);
-        if (!qoutarea) {
-                rc = -ENOMEM;
-                free_page ((unsigned long) qinarea);
-                goto out;
-        }
-        memset (qinarea,0,PAGE_SIZE);
-        memset (qoutarea,0,PAGE_SIZE);
-
-        qinarea->qopcode = DCSS_QACTV; /* do a query for active
-                                          segments */
-        qinarea->qoutptr = (unsigned long) qoutarea;
-        qinarea->qoutlen = sizeof(struct qout64);
-
-        /* Move segment name into double word aligned
-           field and pad with blanks to 8 long.
-         */
-
-        for (i = j = 0 ; i < 8; i++) {
-                qinarea->qname[i] = (name[j] == '\0') ? ' ' : name[j++];
-        }
-
-        /* name already in EBCDIC */
-        /* ASCEBC ((void *)&qinarea.qname, 8); */
-
-        /* set the assembler variables */
-        rx = (unsigned long) qinarea;
-        ry = DCSS_SEGEXT; /* this is extended function */
+	int diag_cc, rc;
+	unsigned long dummy, vmrc;
 
-        /* issue diagnose x'64' */
-        __asm__ __volatile__(
-#ifdef CONFIG_ARCH_S390X
-                             "   sam31\n" // switch to 31 bit
-                             "   diag    %0,%1,0x64\n"
-                             "   sam64\n" // switch back to 64 bit
-#else
-                             "   diag    %0,%1,0x64\n"
-#endif
-                             "   ipm     %2\n"
-                             "   srl     %2,28\n"
-                             : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" );
-
-        /* parse the query output area */
-	*segstart=qoutarea->segstart;
-	*segend=qoutarea->segend;
-
-        if (rc > 1)
-                {
-                        *rwattr = 2;
-                        *shattr = 2;
-                        rc = 0;
-                        goto free;
-                }
-
-        if (qoutarea->segcnt > 6)
-                {
-                        *rwattr = 3;
-                        *shattr = 3;
-                        rc = 0;
-                        goto free;
-                }
-
-        *rwattr = 1;
-        *shattr = 1;
-
-        for (i=0; i < qoutarea->segrcnt; i++) {
-                if (qoutarea->segout[i].thisseg[3] == 2 ||
-                    qoutarea->segout[i].thisseg[3] == 3 ||
-                    qoutarea->segout[i].thisseg[3] == 6 )
-                        *rwattr = 0;
-                if (qoutarea->segout[i].thisseg[3] == 1 ||
-                    qoutarea->segout[i].thisseg[3] == 3 ||
-                    qoutarea->segout[i].thisseg[3] == 5 )
-                        *shattr = 0;
-        } /* end of for statement */
-        rc = 0;
- free:
-        free_page ((unsigned long) qoutarea);
-        free_page ((unsigned long) qinarea);
+	if ((qin == NULL) || (qout == NULL)) {
+		rc = -ENOMEM;
+		goto out_free;
+	}
+
+	/* initialize diag input parameters */
+	qin->qopcode = DCSS_QACTV;
+	qin->qoutptr = (unsigned long) qout;
+	qin->qoutlen = sizeof(struct qout64);
+	memcpy (qin->qname, seg->dcss_name, 8);
+
+	diag_cc = dcss_diag (DCSS_SEGEXT, qin, &dummy, &vmrc);
+
+	if (diag_cc > 1) {
+		rc = dcss_diag_translate_rc (vmrc);
+		goto out_free;
+	}
+
+	if (qout->segcnt > 1) {
+		rc = -ENOTSUPP;
+		goto out_free;
+	}
+
+	/* analyze diag output and update seg */
+	seg->start_addr = qout->segstart;
+	seg->end = qout->segend;
+
+	seg->vm_segtype = qout->segout[0][3];
+
+	rc = 0;
+
+ out_free:
+	if (qin) kfree(qin);
+	if (qout) kfree(qout);
+	return rc;
+}
+
+/*
+ * check if the given segment collides with guest storage.
+ * returns 1 if this is the case, 0 if no collision was found
+ */
+static int
+segment_overlaps_storage(struct dcss_segment *seg)
+{
+	int i;
+
+	for (i=0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
+		if (memory_chunk[i].type != 0)
+			continue;
+		if ((memory_chunk[i].addr >> 20) > (seg->end >> 20))
+			continue;
+		if (((memory_chunk[i].addr + memory_chunk[i].size - 1) >> 20)
+				< (seg->start_addr >> 20))
+			continue;
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * check if segment collides with other segments that are currently loaded
+ * returns 1 if this is the case, 0 if no collision was found
+ */
+static int
+segment_overlaps_others (struct dcss_segment *seg)
+{
+	struct list_head *l;
+	struct dcss_segment *tmp;
+
+	BUG_ON (!spin_is_locked(&dcss_lock));
+	list_for_each(l, &dcss_list) {
+		tmp = list_entry(l, struct dcss_segment, list);
+		if ((tmp->start_addr >> 20) > (seg->end >> 20))
+			continue;
+		if ((tmp->end >> 20) < (seg->start_addr >> 20))
+			continue;
+		if (seg == tmp)
+			continue;
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * get info about a segment
+ * possible return values:
+ * -ENOSYS  : we are not running on VM
+ * -EIO     : could not perform query diagnose
+ * -ENOENT  : no such segment
+ * -ENOTSUPP: multi-part segment cannot be used with linux
+ * -ENOSPC  : segment cannot be used (overlaps with storage)
+ * -ENOMEM  : out of memory
+ * 0 .. 6   : type of segment as defined in include/asm-s390/extmem.h
+ */
+int
+segment_info (char* name)
+{
+	int rc;
+	struct dcss_segment seg;
+
+	if (!MACHINE_IS_VM)
+		return -ENOSYS;
+
+	dcss_mkname(name, seg.dcss_name);
+	rc = query_segment_info (&seg);
+	if (rc < 0)
+		return rc;
+	return seg.vm_segtype;
+}
+
+/*
+ * real segment loading function, called from segment_load
+ */
+static int
+__segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end)
+{
+	struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment),
+			GFP_DMA);
+	int dcss_command, rc, diag_cc;
+
+	if (seg == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	dcss_mkname (name, seg->dcss_name);
+	rc = query_segment_info (seg);
+	if (rc < 0)
+		goto out_free;
+	if (segment_overlaps_storage(seg)) {
+		PRINT_WARN ("segment_load: not loading segment %s - overlaps"
+				" storage\n",name);
+		rc = -ENOSPC;
+		goto out_free;
+	}
+	if (segment_overlaps_others(seg)) {
+		PRINT_WARN ("segment_load: not loading segment %s - overlaps"
+				" other segments\n",name);
+		rc = -EBUSY;
+		goto out_free;
+	}
+	if (do_nonshared)
+		dcss_command = DCSS_LOADNSR;
+	else
+		dcss_command = DCSS_LOADNOLY;
+
+	diag_cc = dcss_diag(dcss_command, seg->dcss_name,
+			&seg->start_addr, &seg->end);
+	if (diag_cc > 1) {
+		PRINT_WARN ("segment_load: could not load segment %s - "
+				"diag returned error (%ld)\n",name,seg->end);
+		rc = dcss_diag_translate_rc (seg->end);
+		dcss_diag(DCSS_PURGESEG, seg->dcss_name,
+				&seg->start_addr, &seg->end);
+		goto out_free;
+	}
+	seg->do_nonshared = do_nonshared;
+	atomic_set(&seg->ref_count, 1);
+	list_add(&seg->list, &dcss_list);
+	rc = seg->vm_segtype;
+	*addr = seg->start_addr;
+	*end  = seg->end;
+	if (do_nonshared)
+		PRINT_INFO ("segment_load: loaded segment %s range %p .. %p "
+				"type %s in non-shared mode\n", name,
+				(void*)seg->start_addr, (void*)seg->end,
+				segtype_string[seg->vm_segtype]);
+	else
+		PRINT_INFO ("segment_load: loaded segment %s range %p .. %p "
+				"type %s in shared mode\n", name,
+				(void*)seg->start_addr, (void*)seg->end,
+				segtype_string[seg->vm_segtype]);
+	goto out;
+ out_free:
+	kfree (seg);
  out:
-        return rc;
+	return rc;
 }
 
 /*
- * Load a DCSS segment via the diag 0x64.
+ * this function loads a DCSS segment
+ * name         : name of the DCSS
+ * do_nonshared : 0 indicates that the dcss should be shared with other linux images
+ *                1 indicates that the dcss should be exclusive for this linux image
+ * addr         : will be filled with start address of the segment
+ * end          : will be filled with end address of the segment
+ * return values:
+ * -ENOSYS  : we are not running on VM
+ * -EIO     : could not perform query or load diagnose
+ * -ENOENT  : no such segment
+ * -ENOTSUPP: multi-part segment cannot be used with linux
+ * -ENOSPC  : segment cannot be used (overlaps with storage)
+ * -EBUSY   : segment can temporarily not be used (overlaps with dcss)
+ * -EPERM   : segment is currently loaded with incompatible permissions
+ * -ENOMEM  : out of memory
+ * 0 .. 6   : type of segment as defined in include/asm-s390/extmem.h
  */
-int segment_load(char *name, int segtype, unsigned long *addr,
-                 unsigned long *end)
+int
+segment_load (char *name, int do_nonshared, unsigned long *addr,
+		unsigned long *end)
 {
-        char dcss_name[8];
-        struct list_head *l;
-        struct dcss_segment *seg, *tmp;
-	unsigned long dummy;
-	unsigned long segstart, segend;
-        int rc = 0,i;
-        int rwattr, shattr;
-
-        if (!MACHINE_IS_VM)
-                return -ENOSYS;
-        dcss_mkname(name, dcss_name);
-	/* search for the dcss in list of currently loaded segments */
-        spin_lock(&dcss_lock);
-        seg = NULL;
-        list_for_each(l, &dcss_list) {
-                tmp = list_entry(l, struct dcss_segment, list);
-                if (memcmp(tmp->dcss_name, dcss_name, 8) == 0) {
-                        seg = tmp;
-                        break;
-                }
-        }
-
-        if (seg == NULL) {
-                /* find out the attributes of this
-                   shared segment */
-                dcss_diag_query(dcss_name, &rwattr, &shattr, &segstart, &segend);
-		/* does segment collide with main memory? */
-		for (i=0; i < MEMORY_CHUNKS; i++) {
-			if (memory_chunk[i].type != 0)
-				continue;
-			if (memory_chunk[i].addr > segend)
-				continue;
-			if (memory_chunk[i].addr + memory_chunk[i].size <= segstart)
-				continue;
-			spin_unlock(&dcss_lock);
-			return -ENOENT;
-		}
-		/* or does it collide with other (loaded) segments? */
-        	list_for_each(l, &dcss_list) {
-                	tmp = list_entry(l, struct dcss_segment, list);
-	                if ((segstart <= tmp->end && segstart >= tmp->start_addr) ||
-				(segend <= tmp->end && segend >= tmp->start_addr) ||
-				(segstart <= tmp->start_addr && segend >= tmp->end)) {
-				PRINT_ERR("Segment Overlap!\n");
-			        spin_unlock(&dcss_lock);
-				return -ENOENT;
-	                }
-        	}
-
-                /* do case statement on segtype */
-                /* if asking for shared ro,
-                   shared rw works */
-                /* if asking for exclusive ro,
-                   exclusive rw works */
-
-                switch(segtype) {
-                case SEGMENT_SHARED_RO:
-                        if (shattr > 1 || rwattr > 1) {
-                                spin_unlock(&dcss_lock);
-                                return -ENOENT;
-                        } else {
-                                if (shattr == 0 && rwattr == 0)
-                                        rc = SEGMENT_EXCLUSIVE_RO;
-                                if (shattr == 0 && rwattr == 1)
-                                        rc = SEGMENT_EXCLUSIVE_RW;
-                                if (shattr == 1 && rwattr == 0)
-                                        rc = SEGMENT_SHARED_RO;
-                                if (shattr == 1 && rwattr == 1)
-                                        rc = SEGMENT_SHARED_RW;
-                        }
-                        break;
-                case SEGMENT_SHARED_RW:
-                        if (shattr > 1 || rwattr != 1) {
-                                spin_unlock(&dcss_lock);
-                                return -ENOENT;
-                        } else {
-                                if (shattr == 0)
-                                        rc = SEGMENT_EXCLUSIVE_RW;
-                                if (shattr == 1)
-                                        rc = SEGMENT_SHARED_RW;
-                        }
-                        break;
-
-                case SEGMENT_EXCLUSIVE_RO:
-                        if (shattr > 0 || rwattr > 1) {
-                                spin_unlock(&dcss_lock);
-                                return -ENOENT;
-                        } else {
-                                if (rwattr == 0)
-                                        rc = SEGMENT_EXCLUSIVE_RO;
-                                if (rwattr == 1)
-                                        rc = SEGMENT_EXCLUSIVE_RW;
-                        }
-                        break;
-
-                case SEGMENT_EXCLUSIVE_RW:
-/*                        if (shattr != 0 || rwattr != 1) {
-                                spin_unlock(&dcss_lock);
-                                return -ENOENT;
-                        } else {
-*/
-                                rc = SEGMENT_EXCLUSIVE_RW;
-//                        }
-                        break;
-
-                default:
-                        spin_unlock(&dcss_lock);
-                        return -ENOENT;
-                } /* end switch */
-
-                seg = kmalloc(sizeof(struct dcss_segment), GFP_DMA);
-                if (seg != NULL) {
-                        memcpy(seg->dcss_name, dcss_name, 8);
-			if (rc == SEGMENT_EXCLUSIVE_RW) {
-				if (dcss_diag(DCSS_LOADNSR, seg->dcss_name,
-						&seg->start_addr, &seg->end) == 0) {
-					if (seg->end < max_low_pfn*PAGE_SIZE ) {
-						atomic_set(&seg->ref_count, 1);
-						list_add(&seg->list, &dcss_list);
-						*addr = seg->start_addr;
-						*end = seg->end;
-						seg->dcss_attr = rc;
-						if (shattr == 1 && rwattr == 1)
-							seg->shared_attr = SEGMENT_SHARED_RW;
-						else if (shattr == 1 && rwattr == 0)
-							seg->shared_attr = SEGMENT_SHARED_RO;
-						else
-							seg->shared_attr = SEGMENT_EXCLUSIVE_RW;
-					} else {
-						dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
-						kfree (seg);
-						rc = -ENOENT;
-					}
-				} else {
-					kfree(seg);
-					rc = -ENOENT;
-			        }
-				goto out;
-                        }
-			if (dcss_diag(DCSS_LOADNOLY, seg->dcss_name,
-                                      &seg->start_addr, &seg->end) == 0) {
-				if (seg->end < max_low_pfn*PAGE_SIZE ) {
-		                        atomic_set(&seg->ref_count, 1);
-					list_add(&seg->list, &dcss_list);
-					*addr = seg->start_addr;
-					*end = seg->end;
-					seg->dcss_attr = rc;
-					seg->shared_attr = rc;
-				} else {
-					dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
-					kfree (seg);
-					rc = -ENOENT;
-				}
-                        } else {
-                                kfree(seg);
-                                rc = -ENOENT;
-                        }
-                } else rc = -ENOMEM;
-        } else {
-		/* found */
-		if ((segtype == SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr != SEGMENT_EXCLUSIVE_RW)) {
-			PRINT_ERR("Segment already loaded in other mode than EXCLUSIVE_RW!\n");
-			rc = -EPERM;
-			goto out;
-			/* reload segment in exclusive mode */
-/*			dcss_diag(DCSS_LOADNSR, seg->dcss_name,
-				  &seg->start_addr, &seg->end);
-			seg->dcss_attr = SEGMENT_EXCLUSIVE_RW;*/
-		}
-		if ((segtype != SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr == SEGMENT_EXCLUSIVE_RW)) {
-			PRINT_ERR("Segment already loaded in EXCLUSIVE_RW mode!\n");
-			rc = -EPERM;
-			goto out;
+	struct dcss_segment *seg;
+	int rc;
+
+	if (!MACHINE_IS_VM)
+		return -ENOSYS;
+
+	spin_lock (&dcss_lock);
+	seg = segment_by_name (name);
+	if (seg == NULL)
+		rc = __segment_load (name, do_nonshared, addr, end);
+	else {
+		if (do_nonshared == seg->do_nonshared) {
+			atomic_inc(&seg->ref_count);
+			*addr = seg->start_addr;
+			*end  = seg->end;
+			rc    = seg->vm_segtype;
+		} else {
+			*addr = *end = 0;
+			rc    = -EPERM;
 		}
-                atomic_inc(&seg->ref_count);
-                *addr = seg->start_addr;
-                *end = seg->end;
-                rc = seg->dcss_attr;
-        }
-out:
-        spin_unlock(&dcss_lock);
-        return rc;
+	}
+	spin_unlock (&dcss_lock);
+	return rc;
 }
 
 /*
@@ -422,84 +400,65 @@
  * it from the address space if nobody is using it
  * any longer.
  */
-void segment_unload(char *name)
+void
+segment_unload(char *name)
 {
-        char dcss_name[8];
-        unsigned long dummy;
-        struct list_head *l,*l_tmp;
-        struct dcss_segment *seg;
-
-        if (!MACHINE_IS_VM)
-                return;
-        dcss_mkname(name, dcss_name);
-        spin_lock(&dcss_lock);
-        list_for_each_safe(l, l_tmp, &dcss_list) {
-                seg = list_entry(l, struct dcss_segment, list);
-                if (memcmp(seg->dcss_name, dcss_name, 8) == 0) {
-                        if (atomic_dec_return(&seg->ref_count) == 0) {
-                                /* Last user of the segment is
-                                   gone. */
-                                list_del(&seg->list);
-                                dcss_diag(DCSS_PURGESEG, seg->dcss_name,
-                                          &dummy, &dummy);
-				kfree(seg);
-                        }
-                        break;
-                }
-        }
-        spin_unlock(&dcss_lock);
+	unsigned long dummy;
+	struct dcss_segment *seg;
+
+	if (!MACHINE_IS_VM)
+		return;
+
+	spin_lock(&dcss_lock);
+	seg = segment_by_name (name);
+	if (seg == NULL) {
+		PRINT_ERR ("could not find segment %s in segment_unload, "
+				"please report to linux390@de.ibm.com\n",name);
+		goto out_unlock;
+	}
+	if (atomic_dec_return(&seg->ref_count) == 0) {
+		list_del(&seg->list);
+		dcss_diag(DCSS_PURGESEG, seg->dcss_name,
+			  &dummy, &dummy);
+		kfree(seg);
+	}
+out_unlock:
+	spin_unlock(&dcss_lock);
 }
 
 /*
- * Replace an existing DCSS segment, so that machines
- * that load it anew will see the new version.
+ * save segment content permanently
  */
-void segment_replace(char *name)
+void segment_save(char *name)
 {
-        char dcss_name[8];
-        struct list_head *l;
-        struct dcss_segment *seg;
-        int mybeg = 0;
-        int myend = 0;
-        char mybuff1[80];
-        char mybuff2[80];
-
-        if (!MACHINE_IS_VM)
-                return;
-        dcss_mkname(name, dcss_name);
-
-        memset (mybuff1, 0, sizeof(mybuff1));
-        memset (mybuff2, 0, sizeof(mybuff2));
-
-        spin_lock(&dcss_lock);
-        list_for_each(l, &dcss_list) {
-                seg = list_entry(l, struct dcss_segment, list);
-                if (memcmp(seg->dcss_name, dcss_name, 8) == 0) {
-                        mybeg = seg->start_addr >> 12;
-                        myend = (seg->end) >> 12;
-                        if (seg->shared_attr == SEGMENT_EXCLUSIVE_RW)
-                                sprintf(mybuff1, "DEFSEG %s %X-%X EW",
-                                        name, mybeg, myend);
-                        if (seg->shared_attr == SEGMENT_EXCLUSIVE_RO)
-                                sprintf(mybuff1, "DEFSEG %s %X-%X RO",
-                                        name, mybeg, myend);
-                        if (seg->shared_attr == SEGMENT_SHARED_RW)
-                                sprintf(mybuff1, "DEFSEG %s %X-%X SW",
-                                        name, mybeg, myend);
-                        if (seg->shared_attr == SEGMENT_SHARED_RO)
-                                sprintf(mybuff1, "DEFSEG %s %X-%X SR",
-                                        name, mybeg, myend);
-                        spin_unlock(&dcss_lock);
-                        sprintf(mybuff2, "SAVESEG %s", name);
-                        cpcmd(mybuff1, NULL, 80);
-                        cpcmd(mybuff2, NULL, 80);
-                        break;
-                }
-
-        }
-        if (myend == 0) spin_unlock(&dcss_lock);
+	struct dcss_segment *seg;
+	int startpfn = 0;
+	int endpfn = 0;
+	char cmd1[80];
+	char cmd2[80];
+
+	if (!MACHINE_IS_VM)
+		return;
+
+	spin_lock(&dcss_lock);
+	seg = segment_by_name (name);
+
+	if (seg == NULL) {
+		PRINT_ERR ("could not find segment %s in segment_save, please report to linux390@de.ibm.com\n",name);
+		return;
+	}
+
+	startpfn = seg->start_addr >> 12;
+	endpfn = (seg->end) >> 12;
+	sprintf(cmd1, "DEFSEG %s %X-%X %s", name, startpfn, endpfn,
+			segtype_string[seg->vm_segtype]);
+	sprintf(cmd2, "SAVESEG %s", name);
+	cpcmd(cmd1, NULL, 80);
+	cpcmd(cmd2, NULL, 80);
+	spin_unlock(&dcss_lock);
 }
 
 EXPORT_SYMBOL(segment_load);
 EXPORT_SYMBOL(segment_unload);
-EXPORT_SYMBOL(segment_replace);
+EXPORT_SYMBOL(segment_save);
+EXPORT_SYMBOL(segment_info);
diff -Nru a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S
--- a/arch/sh/kernel/entry.S	2004-10-28 22:25:57 -07:00
+++ b/arch/sh/kernel/entry.S	2004-10-28 22:25:57 -07:00
@@ -1140,5 +1140,10 @@
 	.long sys_mq_timedreceive       /* 280 */
 	.long sys_mq_notify
 	.long sys_mq_getsetattr
+	.long sys_ni_syscall	/* Reserved for kexec */
+	.long sys_waitid
+	.long sys_add_key		/* 285 */
+	.long sys_request_key
+	.long sys_keyctl
 
 /* End of entry.S */
diff -Nru a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
--- a/arch/sh/kernel/signal.c	2004-10-28 22:25:59 -07:00
+++ b/arch/sh/kernel/signal.c	2004-10-28 22:25:59 -07:00
@@ -493,14 +493,12 @@
 
 /*
  * OK, we're invoking a handler
- */	
+ */
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
+	      sigset_t *oldset, struct pt_regs *regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Are we from a system call? */
 	if (regs->tra >= 0) {
 		/* If so, check system call restarting.. */
@@ -570,6 +568,7 @@
 {
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -588,10 +587,10 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &ka, &info, oldset, regs);
 		return 1;
 	}
 
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	2004-10-28 22:25:57 -07:00
+++ b/arch/sparc64/kernel/systbls.S	2004-10-28 22:25:57 -07:00
@@ -76,7 +76,7 @@
 	.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
 	.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/	.word sys_setaltroot, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
 
 #endif /* CONFIG_COMPAT */
 
@@ -142,7 +142,7 @@
 	.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/	.word sys_setaltroot, sys_add_key, sys_request_key, sys_keyctl
+/*280*/	.word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig
--- a/arch/um/Kconfig	2004-10-28 22:25:58 -07:00
+++ b/arch/um/Kconfig	2004-10-28 22:25:58 -07:00
@@ -1,3 +1,8 @@
+# UML uses the generic IRQ sugsystem
+config GENERIC_HARDIRQS
+	bool
+	default y
+
 config USERMODE
 	bool
 	default y
@@ -100,7 +105,8 @@
         say Y or M here; otherwise say N.
 
 config HPPFS
-	tristate "HoneyPot ProcFS"
+	tristate "HoneyPot ProcFS (EXPERIMENTAL)"
+	depends on BROKEN
 	help
 	hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
 	entries to be overridden, removed, or fabricated from the host.
@@ -113,8 +119,12 @@
 	You only need this if you are setting up a UML honeypot.  Otherwise,
 	it is safe to say 'N' here.
 
+	If you are actively using it, please ask for it to be fixed. In this
+	moment, it does not work on 2.6 (it works somehow on 2.4).
+
 config MCONSOLE
 	bool "Management console"
+	default y
 	help
         The user mode linux management console is a low-level interface to
         the kernel, somewhat like the i386 SysRq interface.  Since there is
@@ -131,19 +141,40 @@
 
 config HOST_2G_2G
 	bool "2G/2G host address space split"
+	default n
+	help
+	This is needed when the host on which you run has a 2G/2G memory
+	split, instead of the customary 3G/1G.
+
+	Note that to enable such a host
+	configuration, which makes sense only in some cases, you need special
+	host patches.
+
+	So, if you do not know what to do here, say 'N'.
 
 config SMP
-	bool "Symmetric multi-processing support"
+	bool "Symmetric multi-processing support (EXPERIMENTAL)"
 	default n
+	depends on MODE_TT && EXPERIMENTAL
 	help
-        This option enables UML SMP support.  UML implements virtual SMP by
-        allowing as many processes to run simultaneously on the host as
-        there are virtual processors configured.  Obviously, if the host is
-        a uniprocessor, those processes will timeshare, but, inside UML,
-        will appear to be running simultaneously.  If the host is a
-        multiprocessor, then UML processes may run simultaneously, depending
-        on the host scheduler.
-        It is safe to leave this unchanged.
+	This option enables UML SMP support.
+	It is NOT related to having a real SMP box. Not directly, at least.
+
+	UML implements virtual SMP by allowing as many processes to run
+	simultaneously on the host as there are virtual processors configured.
+
+	Obviously, if the host is a uniprocessor, those processes will
+	timeshare, but, inside UML, will appear to be running simultaneously.
+	If the host is a multiprocessor, then UML processes may run
+	simultaneously, depending on the host scheduler.
+
+	This, however, is supported only in TT mode. So, if you use the SKAS
+	patch on your host, switching to TT mode and enabling SMP usually gives
+	you worse performances.
+	Also, since the support for SMP has been under-developed, there could
+	be some bugs being exposed by enabling SMP.
+
+	If you don't know what to do, say N.
 
 config NR_CPUS
 	int "Maximum number of CPUs (2-32)"
@@ -246,5 +277,9 @@
 if BROKEN
 	source "drivers/mtd/Kconfig"
 endif
+
+config INPUT
+	bool
+	default n
 
 source "arch/um/Kconfig.debug"
diff -Nru a/arch/um/Kconfig_block b/arch/um/Kconfig_block
--- a/arch/um/Kconfig_block	2004-10-28 22:25:58 -07:00
+++ b/arch/um/Kconfig_block	2004-10-28 22:25:58 -07:00
@@ -52,6 +52,33 @@
 	bool "Initial RAM disk (initrd) support"
 	depends on BLK_DEV_RAM=y
 
+#Copied directly from drivers/block/Kconfig
+config INITRAMFS_SOURCE
+	string "Source directory of cpio_list"
+	default ""
+	help
+	  This can be set to either a directory containing files, etc to be
+	  included in the initramfs archive, or a file containing newline
+	  separated entries.
+
+	  If it is a file, it should be in the following format:
+	    # a comment
+	    file <name> <location> <mode> <uid> <gid>
+	    dir <name> <mode> <uid> <gid>
+	    nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>
+
+	  Where:
+	    <name>      name of the file/dir/nod in the archive
+	    <location>  location of the file in the current filesystem
+	    <mode>      mode/permissions of the file
+	    <uid>       user id (0=root)
+	    <gid>       group id (0=root)
+	    <dev_type>  device type (b=block, c=character)
+	    <maj>       major number of nod
+	    <min>       minor number of nod
+
+	  If you are not sure, leave it blank.
+
 config MMAPPER
 	tristate "Example IO memory driver"
 	depends on BROKEN
diff -Nru a/arch/um/defconfig b/arch/um/defconfig
--- a/arch/um/defconfig	2004-10-28 22:25:58 -07:00
+++ b/arch/um/defconfig	2004-10-28 22:25:58 -07:00
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc2-mm1
-# Thu Sep 16 23:44:48 2004
+# Linux kernel version: 2.6.9-bk4
+# Thu Oct 21 01:09:54 2004
 #
 CONFIG_USERMODE=y
 CONFIG_MMU=y
@@ -15,15 +15,13 @@
 CONFIG_MODE_SKAS=y
 CONFIG_NET=y
 CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=y
+CONFIG_BINFMT_MISC=m
 CONFIG_HOSTFS=y
-CONFIG_HPPFS=y
 CONFIG_MCONSOLE=y
 # CONFIG_HOST_2G_2G is not set
 # CONFIG_SMP is not set
 CONFIG_NEST_LEVEL=0
 CONFIG_KERNEL_HALF_GIGS=1
-# CONFIG_HIGHMEM is not set
 CONFIG_KERNEL_STACK_ORDER=2
 CONFIG_UML_REAL_TIME_CLOCK=y
 
@@ -40,7 +38,7 @@
 CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
@@ -48,11 +46,12 @@
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -66,7 +65,12 @@
 #
 # 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
 
 #
 # Generic Driver Options
@@ -86,6 +90,7 @@
 CONFIG_PTY_CHAN=y
 CONFIG_TTY_CHAN=y
 CONFIG_XTERM_CHAN=y
+# CONFIG_NOCONFIG_CHAN is not set
 CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
 CONFIG_CON_CHAN="xterm"
 CONFIG_SSL_CHAN="pty"
@@ -93,22 +98,21 @@
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_WATCHDOG is not set
-CONFIG_UML_SOUND=y
-CONFIG_SOUND=y
-CONFIG_HOSTAUDIO=y
+CONFIG_UML_SOUND=m
+CONFIG_SOUND=m
+CONFIG_HOSTAUDIO=m
 
 #
 # Block Devices
 #
 CONFIG_BLK_DEV_UBD=y
-# CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_UBD_SYNC=y
 CONFIG_BLK_DEV_COW_COMMON=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_MMAPPER is not set
 CONFIG_NETDEVICES=y
 
 #
@@ -120,7 +124,6 @@
 CONFIG_UML_NET_SLIP=y
 CONFIG_UML_NET_DAEMON=y
 CONFIG_UML_NET_MCAST=y
-# CONFIG_UML_NET_PCAP is not set
 CONFIG_UML_NET_SLIRP=y
 
 #
@@ -178,18 +181,15 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_KGDBOE is not set
 # CONFIG_NETPOLL is not set
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_DUMMY=y
+CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
+CONFIG_TUN=m
 
 #
 # Ethernet (10 or 100Mbit)
@@ -217,7 +217,7 @@
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-CONFIG_PPP=y
+CONFIG_PPP=m
 # CONFIG_PPP_MULTILINK is not set
 # CONFIG_PPP_FILTER is not set
 # CONFIG_PPP_ASYNC is not set
@@ -225,7 +225,7 @@
 # CONFIG_PPP_DEFLATE is not set
 # CONFIG_PPP_BSDCOMP is not set
 # CONFIG_PPPOE is not set
-CONFIG_SLIP=y
+CONFIG_SLIP=m
 # CONFIG_SLIP_COMPRESSED is not set
 # CONFIG_SLIP_SMART is not set
 # CONFIG_SLIP_MODE_SLIP6 is not set
@@ -237,47 +237,38 @@
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_REISER4_FS=y
-CONFIG_REISER4_LARGE_KEY=y
-# CONFIG_REISER4_CHECK is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_XFS_FS is not set
-CONFIG_MINIX_FS=y
+# CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
 CONFIG_QUOTACTL=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
-
-#
-# Caches
-#
-# CONFIG_CACHEFS is not set
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
 
 #
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
 # CONFIG_ZISOFS is not set
 # CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
 #
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -286,11 +277,10 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -304,10 +294,6 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_JFFS_FS=y
-CONFIG_JFFS_FS_VERBOSE=0
-# CONFIG_JFFS_PROC_FS is not set
-# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -396,75 +382,10 @@
 # CONFIG_LIBCRC32C is not set
 
 #
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_CONCAT is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-CONFIG_MTD_BLKMTD=y
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -Nru a/arch/um/drivers/line.c b/arch/um/drivers/line.c
--- a/arch/um/drivers/line.c	2004-10-28 22:25:59 -07:00
+++ b/arch/um/drivers/line.c	2004-10-28 22:25:59 -07:00
@@ -110,7 +110,6 @@
 int line_write(struct line *lines, struct tty_struct *tty, const char *buf, int len)
 {
 	struct line *line;
-	char *new;
 	unsigned long flags;
 	int n, err, i, ret = 0;
 
@@ -143,7 +142,6 @@
 	}
  out_up:
 	up(&line->sem);
- out_free:
 	return(ret);
 }
 
@@ -203,13 +201,17 @@
 
 	if(line->driver->read_irq == current_irq)
 		free_irq_later(line->driver->read_irq, line);
-	else
+	else {
+		free_irq_by_irq_and_dev(line->driver->read_irq, line);
 		free_irq(line->driver->read_irq, line);
+	}
 
 	if(line->driver->write_irq == current_irq)
 		free_irq_later(line->driver->write_irq, line);
-	else
+	else {
+		free_irq_by_irq_and_dev(line->driver->write_irq, line);
 		free_irq(line->driver->write_irq, line);
+	}
 
 	line->have_irq = 0;
 }
diff -Nru a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
--- a/arch/um/drivers/mconsole_kern.c	2004-10-28 22:25:56 -07:00
+++ b/arch/um/drivers/mconsole_kern.c	2004-10-28 22:25:56 -07:00
@@ -19,6 +19,7 @@
 #include "linux/fs.h"
 #include "linux/namei.h"
 #include "linux/proc_fs.h"
+#include "linux/syscalls.h"
 #include "asm/irq.h"
 #include "asm/uaccess.h"
 #include "user_util.h"
@@ -120,77 +121,50 @@
 
 void mconsole_proc(struct mc_request *req)
 {
-	struct nameidata nd;
-	struct file_system_type *proc;
-	struct super_block *super;
-	struct file *file;
-	int n, err;
-	char *ptr = req->request.data, *buf;
+	char path[64];
+	char *buf;
+	int len;
+	int fd;
+	char *ptr = req->request.data;
 
 	ptr += strlen("proc");
 	while(isspace(*ptr)) ptr++;
+	snprintf(path, sizeof(path), "/proc/%s", ptr);
 
-	proc = get_fs_type("proc");
-	if(proc == NULL){
-		mconsole_reply(req, "procfs not registered", 1, 0);
-		goto out;
-	}
-
-	super = (*proc->get_sb)(proc, 0, NULL, NULL);
-	put_filesystem(proc);
-	if(super == NULL){
-		mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
-		goto out;
-	}
-	up_write(&super->s_umount);
-
-	nd.dentry = super->s_root;
-	nd.mnt = NULL;
-	nd.flags = O_RDONLY + 1;
-	nd.last_type = LAST_ROOT;
-
-	err = link_path_walk(ptr, &nd);
-	if(err){
-		mconsole_reply(req, "Failed to look up file", 1, 0);
-		goto out_kill;
-	}
-
-	file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
-	if(IS_ERR(file)){
+	fd = sys_open(path, 0, 0);
+	if (fd < 0) {
 		mconsole_reply(req, "Failed to open file", 1, 0);
-		goto out_kill;
+		printk("open %s: %d\n",path,fd);
+		goto out;
 	}
 
 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if(buf == NULL){
 		mconsole_reply(req, "Failed to allocate buffer", 1, 0);
-		goto out_fput;
+		goto out_close;
 	}
 
-	if((file->f_op != NULL) && (file->f_op->read != NULL)){
-		do {
-			n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
-						&file->f_pos);
-			if(n >= 0){
-				buf[n] = '\0';
-				mconsole_reply(req, buf, 0, (n > 0));
-			}
-			else {
-				mconsole_reply(req, "Read of file failed",
-					       1, 0);
-				goto out_free;
-			}
-		} while(n > 0);
+	for (;;) {
+		len = sys_read(fd, buf, PAGE_SIZE-1);
+		if (len < 0) {
+			mconsole_reply(req, "Read of file failed", 1, 0);
+			goto out_free;
+		} else if (len == PAGE_SIZE-1) {
+			buf[len] = '\0';
+			mconsole_reply(req, buf, 0, 1);
+		} else {
+			buf[len] = '\0';
+			mconsole_reply(req, buf, 0, 0);
+			break;
+		}
 	}
-	else mconsole_reply(req, "", 0, 0);
 
  out_free:
 	kfree(buf);
- out_fput:
-	fput(file);
- out_kill:
-	deactivate_super(super);
- out: ;
+ out_close:
+	sys_close(fd);
+ out:
+	/* nothing */;
 }
 
 #define UML_MCONSOLE_HELPTEXT \
diff -Nru a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
--- a/arch/um/drivers/net_kern.c	2004-10-28 22:25:58 -07:00
+++ b/arch/um/drivers/net_kern.c	2004-10-28 22:25:58 -07:00
@@ -148,6 +148,7 @@
 	netif_stop_queue(dev);
 	spin_lock(&lp->lock);
 
+	free_irq_by_irq_and_dev(dev->irq, dev);
 	free_irq(dev->irq, dev);
 	if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
 	lp->fd = -1;
diff -Nru a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
--- a/arch/um/drivers/port_kern.c	2004-10-28 22:25:56 -07:00
+++ b/arch/um/drivers/port_kern.c	2004-10-28 22:25:56 -07:00
@@ -242,6 +242,7 @@
 		 * connection.  Then we loop here throwing out failed 
 		 * connections until a good one is found.
 		 */
+		free_irq_by_irq_and_dev(TELNETD_IRQ, conn);
 		free_irq(TELNETD_IRQ, conn);
 
 		if(conn->fd >= 0) break;
diff -Nru a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
--- a/arch/um/drivers/xterm_kern.c	2004-10-28 22:25:58 -07:00
+++ b/arch/um/drivers/xterm_kern.c	2004-10-28 22:25:58 -07:00
@@ -63,6 +63,7 @@
 	}
 	down(&data->sem);
 
+	free_irq_by_irq_and_dev(XTERM_IRQ, data);
 	free_irq(XTERM_IRQ, data);
 
 	ret = data->new_fd;
diff -Nru a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
--- a/arch/um/include/irq_user.h	2004-10-28 22:25:58 -07:00
+++ b/arch/um/include/irq_user.h	2004-10-28 22:25:58 -07:00
@@ -10,7 +10,7 @@
 
 extern void sigio_handler(int sig, union uml_pt_regs *regs);
 extern int activate_fd(int irq, int fd, int type, void *dev_id);
-extern void free_irq_by_irq_and_dev(int irq, void *dev_id);
+extern void free_irq_by_irq_and_dev(unsigned int irq, void *dev_id);
 extern void free_irq_by_fd(int fd);
 extern void reactivate_fd(int fd, int irqnum);
 extern void deactivate_fd(int fd, int irqnum);
diff -Nru a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
--- a/arch/um/kernel/dyn.lds.S	2004-10-28 22:25:58 -07:00
+++ b/arch/um/kernel/dyn.lds.S	2004-10-28 22:25:58 -07:00
@@ -59,6 +59,8 @@
   .text           : {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
+    *(.fixup)
     *(.stub .text.* .gnu.linkonce.t.*)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
diff -Nru a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
--- a/arch/um/kernel/irq.c	2004-10-28 22:25:59 -07:00
+++ b/arch/um/kernel/irq.c	2004-10-28 22:25:59 -07:00
@@ -32,58 +32,6 @@
 #include "irq_user.h"
 #include "irq_kern.h"
 
-static void register_irq_proc (unsigned int irq);
-
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
-	[0 ... NR_IRQS-1] = {
-		.handler = &no_irq_type,
-		.lock = SPIN_LOCK_UNLOCKED
-	}
-};
-
-/*
- * Generic no controller code
- */
-
-static void enable_none(unsigned int irq) { }
-static unsigned int startup_none(unsigned int irq) { return 0; }
-static void disable_none(unsigned int irq) { }
-static void ack_none(unsigned int irq)
-{
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves, it doesn't deserve
- * a generic callback i think.
- */
-#ifdef CONFIG_X86
-	printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
-#ifdef CONFIG_X86_LOCAL_APIC
-	/*
-	 * Currently unexpected vectors happen only on SMP and APIC.
-	 * We _must_ ack these because every local APIC has only N
-	 * irq slots per priority level, and a 'hanging, unacked' IRQ
-	 * holds up an irq slot - in excessive cases (when multiple
-	 * unexpected vectors occur) that might lock up the APIC
-	 * completely.
-	 */
-	ack_APIC_irq();
-#endif
-#endif
-}
-
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define shutdown_none	disable_none
-#define end_none	enable_none
-
-struct hw_interrupt_type no_irq_type = {
-	"none",
-	startup_none,
-	shutdown_none,
-	enable_none,
-	disable_none,
-	ack_none,
-	end_none
-};
 
 /*
  * Generic, controller-independent functions:
@@ -126,10 +74,6 @@
 skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
-		seq_printf(p, "NMI: ");
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", nmi_count(j));
 		seq_putc(p, '\n');
 	}
 
@@ -137,295 +81,18 @@
 }
 
 /*
- * This should really return information about whether
- * we should do bottom half handling etc. Right now we
- * end up _always_ checking the bottom half, which is a
- * waste of time and is not what some drivers would
- * prefer.
- */
-int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, 
-		     struct irqaction * action)
-{
-	int status = 1;	/* Force the "do bottom halves" bit */
-	int ret, retval = 0;
-
-	if (!(action->flags & SA_INTERRUPT))
-		local_irq_enable();
-
-	do {
-		ret = action->handler(irq, action->dev_id, regs);
-		if (ret == IRQ_HANDLED)
-			status |= action->flags;
-		retval |= ret;
-		action = action->next;
-	} while (action);
-	if (status & SA_SAMPLE_RANDOM)
-		add_interrupt_randomness(irq);
-
-	local_irq_disable();
-
-	return retval;
-}
-
-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock. 
- */
- 
-/**
- *	disable_irq_nosync - disable an irq without waiting
- *	@irq: Interrupt to disable
- *
- *	Disable the selected interrupt line. Disables of an interrupt
- *	stack. Unlike disable_irq(), this function does not ensure existing
- *	instances of the IRQ handler have completed before returning.
- *
- *	This function may be called from IRQ context.
- */
- 
-inline void disable_irq_nosync(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	if (!desc->depth++) {
-		desc->status |= IRQ_DISABLED;
-		desc->handler->disable(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-#ifdef CONFIG_SMP
-inline void synchronize_irq(unsigned int irq)
-{
-	/* is there anything to synchronize with? */
-	if (!irq_desc[irq].action)
-		return;
- 
-	while (irq_desc[irq].status & IRQ_INPROGRESS)
-		cpu_relax();
-}
-#endif
-
-/**
- *	disable_irq - disable an irq and wait for completion
- *	@irq: Interrupt to disable
- *
- *	Disable the selected interrupt line. Disables of an interrupt
- *	stack. That is for two disables you need two enables. This
- *	function waits for any pending IRQ handlers for this interrupt
- *	to complete before returning. If you use this function while
- *	holding a resource the IRQ handler may need you will deadlock.
- *
- *	This function may be called - with care - from IRQ context.
- */
- 
-void disable_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	synchronize_irq(irq);
-}
-
-/**
- *	enable_irq - enable interrupt handling on an irq
- *	@irq: Interrupt to enable
- *
- *	Re-enables the processing of interrupts on this IRQ line
- *	providing no disable_irq calls are now in effect.
- *
- *	This function may be called from IRQ context.
- */
- 
-void enable_irq(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	switch (desc->depth) {
-	case 1: {
-		unsigned int status = desc->status & ~IRQ_DISABLED;
-		desc->status = status;
-		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-			desc->status = status | IRQ_REPLAY;
-			hw_resend_irq(desc->handler,irq);
-		}
-		desc->handler->enable(irq);
-		/* fall-through */
-	}
-	default:
-		desc->depth--;
-		break;
-	case 0:
-		printk(KERN_ERR "enable_irq() unbalanced from %p\n",
-		       __builtin_return_address(0));
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/*
  * do_IRQ handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
 unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
-{	
-	/* 
-	 * 0 return value means that this irq is already being
-	 * handled by some other CPU. (or is disabled)
-	 */
-	irq_desc_t *desc = irq_desc + irq;
-	struct irqaction * action;
-	unsigned int status;
-
-	irq_enter();
-	kstat_this_cpu.irqs[irq]++;
-	spin_lock(&desc->lock);
-	desc->handler->ack(irq);
-	/*
-	   REPLAY is when Linux resends an IRQ that was dropped earlier
-	   WAITING is used by probe to mark irqs that are being tested
-	   */
-	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-	status |= IRQ_PENDING; /* we _want_ to handle it */
-
-	/*
-	 * If the IRQ is disabled for whatever reason, we cannot
-	 * use the action we have.
-	 */
-	action = NULL;
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		action = desc->action;
-		status &= ~IRQ_PENDING; /* we commit to handling */
-		status |= IRQ_INPROGRESS; /* we are handling it */
-	}
-	desc->status = status;
-
-	/*
-	 * If there is no IRQ handler or it was disabled, exit early.
-	   Since we set PENDING, if another processor is handling
-	   a different instance of this same irq, the other processor
-	   will take care of it.
-	 */
-	if (!action)
-		goto out;
-
-	/*
-	 * Edge triggered interrupts need to remember
-	 * pending events.
-	 * This applies to any hw interrupts that allow a second
-	 * instance of the same irq to arrive while we are in do_IRQ
-	 * or in the handler. But the code here only handles the _second_
-	 * instance of the irq, not the third or fourth. So it is mostly
-	 * useful for irq hardware that does not mask cleanly in an
-	 * SMP environment.
-	 */
-	for (;;) {
-		spin_unlock(&desc->lock);
-		handle_IRQ_event(irq, (struct pt_regs *) regs, action);
-		spin_lock(&desc->lock);
-		
-		if (!(desc->status & IRQ_PENDING))
-			break;
-		desc->status &= ~IRQ_PENDING;
-	}
-	desc->status &= ~IRQ_INPROGRESS;
-out:
-	/*
-	 * The ->end() handler has to deal with interrupts which got
-	 * disabled while the handler was running.
-	 */
-	desc->handler->end(irq);
-	spin_unlock(&desc->lock);
-
-	irq_exit();
-
-	return 1;
-}
-
-/**
- *	request_irq - allocate an interrupt line
- *	@irq: Interrupt line to allocate
- *	@handler: Function to be called when the IRQ occurs
- *	@irqflags: Interrupt type flags
- *	@devname: An ascii name for the claiming device
- *	@dev_id: A cookie passed back to the handler function
- *
- *	This call allocates interrupt resources and enables the
- *	interrupt line and IRQ handling. From the point this
- *	call is made your handler function may be invoked. Since
- *	your handler function must clear any interrupt the board 
- *	raises, you must take care both to initialise your hardware
- *	and to set up the interrupt handler in the right order.
- *
- *	Dev_id must be globally unique. Normally the address of the
- *	device data structure is used as the cookie. Since the handler
- *	receives this value it makes sense to use it.
- *
- *	If your interrupt is shared you must pass a non NULL dev_id
- *	as this is required when freeing the interrupt.
- *
- *	Flags:
- *
- *	SA_SHIRQ		Interrupt is shared
- *
- *	SA_INTERRUPT		Disable local interrupts while processing
- *
- *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
- *
- */
- 
-int request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, 
-		const char * devname,
-		void *dev_id)
 {
-	int retval;
-	struct irqaction * action;
-
-#if 1
-	/*
-	 * Sanity-check: shared interrupts should REALLY pass in
-	 * a real dev-ID, otherwise we'll have trouble later trying
-	 * to figure out which interrupt is which (messes up the
-	 * interrupt freeing logic etc).
-	 */
-	if (irqflags & SA_SHIRQ) {
-		if (!dev_id)
-			printk(KERN_ERR "Bad boy: %s (at 0x%x) called us "
-			       "without a dev_id!\n", devname, (&irq)[-1]);
-	}
-#endif
-
-	if (irq >= NR_IRQS)
-		return -EINVAL;
-	if (!handler)
-		return -EINVAL;
-
-	action = (struct irqaction *)
-			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-	if (!action)
-		return -ENOMEM;
-
-	action->handler = handler;
-	action->flags = irqflags;
-	cpus_clear(action->mask);
-	action->name = devname;
-	action->next = NULL;
-	action->dev_id = dev_id;
-
-	retval = setup_irq(irq, action);
-	if (retval)
-		kfree(action);
-	return retval;
+       irq_enter();
+       __do_IRQ(irq, (struct pt_regs *) regs);
+       irq_exit();
+       return 1;
 }
 
-EXPORT_SYMBOL(request_irq);
-
 int um_request_irq(unsigned int irq, int fd, int type,
 		   irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		   unsigned long irqflags, const char * devname,
@@ -444,222 +111,6 @@
 EXPORT_SYMBOL(um_request_irq);
 EXPORT_SYMBOL(reactivate_fd);
 
-/* this was setup_x86_irq but it seems pretty generic */
-int setup_irq(unsigned int irq, struct irqaction * new)
-{
-	int shared = 0;
-	unsigned long flags;
-	struct irqaction *old, **p;
-	irq_desc_t *desc = irq_desc + irq;
-
-	/*
-	 * Some drivers like serial.c use request_irq() heavily,
-	 * so we have to be careful not to interfere with a
-	 * running system.
-	 */
-	if (new->flags & SA_SAMPLE_RANDOM) {
-		/*
-		 * This function might sleep, we want to call it first,
-		 * outside of the atomic block.
-		 * Yes, this might clear the entropy pool if the wrong
-		 * driver is attempted to be loaded, without actually
-		 * installing a new handler, but is this really a problem,
-		 * only the sysadmin is able to do this.
-		 */
-		rand_initialize_irq(irq);
-	}
-
-	/*
-	 * The following block of code has to be executed atomically
-	 */
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	old = *p;
-	if (old != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & new->flags & SA_SHIRQ)) {
-			spin_unlock_irqrestore(&desc->lock,flags);
-			return -EBUSY;
-		}
-
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
-	}
-
-	*p = new;
-
-	if (!shared) {
-		desc->depth = 0;
-		desc->status &= ~IRQ_DISABLED;
-		desc->handler->startup(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock,flags);
-
-	register_irq_proc(irq);
-	return 0;
-}
-
-/**
- *	free_irq - free an interrupt
- *	@irq: Interrupt line to free
- *	@dev_id: Device identity to free
- *
- *	Remove an interrupt handler. The handler is removed and if the
- *	interrupt line is no longer in use by any driver it is disabled.
- *	On a shared IRQ the caller must ensure the interrupt is disabled
- *	on the card it drives before calling this function. The function
- *	does not return until any executing interrupts for this IRQ
- *	have completed.
- *
- *	This function may be called from interrupt context. 
- *
- *	Bugs: Attempting to free an irq in a handler for the same irq hangs
- *	      the machine.
- */
- 
-void free_irq(unsigned int irq, void *dev_id)
-{
-	irq_desc_t *desc;
-	struct irqaction **p;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS)
-		return;
-
-	desc = irq_desc + irq;
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	for (;;) {
-		struct irqaction * action = *p;
-		if (action) {
-			struct irqaction **pp = p;
-			p = &action->next;
-			if (action->dev_id != dev_id)
-				continue;
-
-			/* Found it - now remove it from the list of entries */
-			*pp = action->next;
-			if (!desc->action) {
-				desc->status |= IRQ_DISABLED;
-				desc->handler->shutdown(irq);
-			}
-			free_irq_by_irq_and_dev(irq, dev_id);
-			spin_unlock_irqrestore(&desc->lock,flags);
-
-			/* Wait to make sure it's not being used on another CPU */
-			synchronize_irq(irq);
-			kfree(action);
-			return;
-		}
-		printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
-		spin_unlock_irqrestore(&desc->lock,flags);
-		return;
-	}
-}
-
-EXPORT_SYMBOL(free_irq);
-
-/* These are initialized by sysctl_init, which is called from init/main.c */
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NR_IRQS];
-static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
-
-/* These are read and written as longs, so a read won't see a partial write
- * even during a race.
- */
-static cpumask_t irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
-
-static int irq_affinity_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int irq_affinity_write_proc (struct file *file, const char *buffer,
-					unsigned long count, void *data)
-{
-	int irq = (long) data, full_count = count, err;
-	cpumask_t new_value;
-
-	if (!irq_desc[irq].handler->set_affinity)
-		return -EIO;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if(err)
-		return(err);
-
-#ifdef CONFIG_SMP
-	/*
-	 * 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.
-	 */
-	{ cpumask_t tmp;
-	  cpus_and(tmp, new_value, cpu_online_map);
-	  if (cpus_empty(tmp))
-		  return -EINVAL;
-	}
-#endif
-
-	irq_affinity[irq] = new_value;
-	irq_desc[irq].handler->set_affinity(irq, new_value);
-
-	return full_count;
-}
-
-#define MAX_NAMELEN 10
-
-static void register_irq_proc (unsigned int irq)
-{
-	struct proc_dir_entry *entry;
-	char name [MAX_NAMELEN];
-
-	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
-	    irq_dir[irq])
-		return;
-
-	memset(name, 0, MAX_NAMELEN);
-	sprintf(name, "%d", irq);
-
-	/* create /proc/irq/1234 */
-	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-
-	/* create /proc/irq/1234/smp_affinity */
-	entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-
-	entry->nlink = 1;
-	entry->data = (void *)(long)irq;
-	entry->read_proc = irq_affinity_read_proc;
-	entry->write_proc = irq_affinity_write_proc;
-
-	smp_affinity_entry[irq] = entry;
-}
-
-void __init init_irq_proc (void)
-{
-	int i;
-
-	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", 0);
-
-	/* create /proc/irq/prof_cpu_mask */
-	create_prof_cpu_mask(root_irq_dir);
-
-	/*
-	 * Create entries for all existing IRQs.
-	 */
-	for (i = 0; i < NR_IRQS; i++)
-		register_irq_proc(i);
-}
-
 static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED;
 
 unsigned long irq_lock(void)
@@ -675,90 +126,27 @@
 	spin_unlock_irqrestore(&irq_spinlock, flags);
 }
 
-unsigned long probe_irq_on(void)
-{
-	return(0);
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off(unsigned long val)
-{
-	return(0);
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-static unsigned int startup_SIGIO_irq(unsigned int irq)
-{
-	return(0);
-}
-
-static void shutdown_SIGIO_irq(unsigned int irq)
-{
-}
-
-static void enable_SIGIO_irq(unsigned int irq)
-{
-}
-
-static void disable_SIGIO_irq(unsigned int irq)
-{
-}
-
-static void mask_and_ack_SIGIO(unsigned int irq)
-{
-}
-
-static void end_SIGIO_irq(unsigned int irq)
-{
-}
-
-static unsigned int startup_SIGVTALRM_irq(unsigned int irq)
-{
-	return(0);
-}
-
-static void shutdown_SIGVTALRM_irq(unsigned int irq)
-{
-}
-
-static void enable_SIGVTALRM_irq(unsigned int irq)
-{
-}
-
-static void disable_SIGVTALRM_irq(unsigned int irq)
-{
-}
-
-static void mask_and_ack_SIGVTALRM(unsigned int irq)
-{
-}
-
-static void end_SIGVTALRM_irq(unsigned int irq)
+/*  presently hw_interrupt_type must define (startup || enable) &&
+ *  disable && end */
+static void dummy(unsigned int irq)
 {
 }
 
 static struct hw_interrupt_type SIGIO_irq_type = {
-	"SIGIO",
-	startup_SIGIO_irq,
-	shutdown_SIGIO_irq,
-	enable_SIGIO_irq,
-	disable_SIGIO_irq,
-	mask_and_ack_SIGIO,
-	end_SIGIO_irq,
-	NULL
+	.typename = "SIGIO",
+	.disable = dummy,
+	.enable = dummy,
+	.ack = dummy,
+	.end = dummy
 };
 
 static struct hw_interrupt_type SIGVTALRM_irq_type = {
-	"SIGVTALRM",
-	startup_SIGVTALRM_irq,
-	shutdown_SIGVTALRM_irq,
-	enable_SIGVTALRM_irq,
-	disable_SIGVTALRM_irq,
-	mask_and_ack_SIGVTALRM,
-	end_SIGVTALRM_irq,
-	NULL
+	.typename = "SIGVTALRM",
+	.shutdown = dummy, /* never called */
+	.disable = dummy,
+	.enable = dummy,
+	.ack = dummy,
+	.end = dummy
 };
 
 void __init init_IRQ(void)
diff -Nru a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
--- a/arch/um/kernel/irq_user.c	2004-10-28 22:25:57 -07:00
+++ b/arch/um/kernel/irq_user.c	2004-10-28 22:25:57 -07:00
@@ -263,7 +263,7 @@
 	return((irq->irq == data->irq) && (irq->id == data->dev));
 }
 
-void free_irq_by_irq_and_dev(int irq, void *dev)
+void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
 {
 	struct irq_and_dev data = ((struct irq_and_dev) { .irq  = irq,
 							  .dev  = dev });
diff -Nru a/arch/um/kernel/main.c b/arch/um/kernel/main.c
--- a/arch/um/kernel/main.c	2004-10-28 22:25:59 -07:00
+++ b/arch/um/kernel/main.c	2004-10-28 22:25:59 -07:00
@@ -22,6 +22,8 @@
 #include "mode.h"
 #include "choose-mode.h"
 #include "uml-config.h"
+#include "irq_user.h"
+#include "time_user.h"
 
 /* Set in set_stklim, which is called from main and __wrap_malloc.
  * __wrap_malloc only calls it if main hasn't started.
diff -Nru a/arch/um/kernel/process.c b/arch/um/kernel/process.c
--- a/arch/um/kernel/process.c	2004-10-28 22:25:59 -07:00
+++ b/arch/um/kernel/process.c	2004-10-28 22:25:59 -07:00
@@ -202,6 +202,11 @@
 		"    To make it working, you need a kernel patch for your host, too.\n"
 		"    See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n");
 
+/* Ugly hack for now... --cw */
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
 static void __init check_sysemu(void)
 {
 	void *stack;
@@ -211,7 +216,9 @@
 		return;
 
 	printk("Checking syscall emulation patch for ptrace...");
+#ifdef CONFIG_MODE_SKAS
 	sysemu_supported = 0;
+#endif /* CONFIG_MODE_SKAS */
 	pid = start_ptraced_child(&stack);
 	if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
 		struct user_regs_struct regs;
@@ -233,17 +240,23 @@
 
 		stop_ptraced_child(pid, stack, 0);
 
+#ifdef CONFIG_MODE_SKAS
 		sysemu_supported = 1;
+#endif /* CONFIG_MODE_SKAS */
 		printk("found\n");
 	}
 	else
 	{
 		stop_ptraced_child(pid, stack, 1);
+#ifdef CONFIG_MODE_SKAS
 		sysemu_supported = 0;
+#endif /* CONFIG_MODE_SKAS */
 		printk("missing\n");
 	}
 
+#ifdef CONFIG_MODE_SKAS
 	set_using_sysemu(!force_sysemu_disabled);
+#endif
 }
 
 void __init check_ptrace(void)
diff -Nru a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
--- a/arch/um/kernel/process_kern.c	2004-10-28 22:25:58 -07:00
+++ b/arch/um/kernel/process_kern.c	2004-10-28 22:25:58 -07:00
@@ -206,7 +206,6 @@
 		 * although we are an idle CPU, we do not want to
 		 * get into the scheduler unnecessarily.
 		 */
-		irq_stat[smp_processor_id()].idle_timestamp = jiffies;
 		if(need_resched())
 			schedule();
 		
diff -Nru a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
--- a/arch/um/kernel/sysrq.c	2004-10-28 22:25:57 -07:00
+++ b/arch/um/kernel/sysrq.c	2004-10-28 22:25:57 -07:00
@@ -6,6 +6,7 @@
 #include "linux/sched.h"
 #include "linux/kernel.h"
 #include "linux/module.h"
+#include "linux/kallsyms.h"
 #include "asm/page.h"
 #include "asm/processor.h"
 #include "sysrq.h"
@@ -19,18 +20,17 @@
         if (!stack)
                 stack = (unsigned long*) &stack;
 
-        printk("Call Trace: ");
+        printk("Call Trace:\n");
         i = 1;
         while (((long) stack & (THREAD_SIZE-1)) != 0) {
                 addr = *stack++;
 		if (__kernel_text_address(addr)) {
-			if (i && ((i % 6) == 0))
-				printk("\n   ");
 			printk("[<%08lx>] ", addr);
+			print_symbol("%s", addr);
+			printk("\n");
 			i++;
                 }
         }
-        printk("\n");
 }
 
 /*
@@ -49,13 +49,3 @@
 	show_trace(sp);
 }
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
--- a/arch/um/kernel/tt/process_kern.c	2004-10-28 22:25:59 -07:00
+++ b/arch/um/kernel/tt/process_kern.c	2004-10-28 22:25:59 -07:00
@@ -305,7 +305,6 @@
 
 	change_sig(SIGUSR1, 0);
 	err = 0;
- out:
 	return(err);
 }
 
diff -Nru a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
--- a/arch/um/kernel/uml.lds.S	2004-10-28 22:25:58 -07:00
+++ b/arch/um/kernel/uml.lds.S	2004-10-28 22:25:58 -07:00
@@ -35,6 +35,8 @@
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
+    *(.fixup)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
     *(.gnu.linkonce.t*)
diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
--- a/arch/x86_64/kernel/Makefile	2004-10-28 22:25:59 -07:00
+++ b/arch/x86_64/kernel/Makefile	2004-10-28 22:25:59 -07:00
@@ -5,9 +5,9 @@
 extra-y 	:= head.o head64.o init_task.o vmlinux.lds
 EXTRA_AFLAGS	:= -traditional
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
-		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
+		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
 		x8664_ksyms.o i387.o syscall.o vsyscall.o \
-		setup64.o bootflag.o e820.o reboot.o warmreboot.o
+		setup64.o bootflag.o e820.o reboot.o warmreboot.o quirks.o
 obj-y += mce.o
 
 obj-$(CONFIG_MTRR)		+= ../../i386/kernel/cpu/mtrr/
@@ -17,7 +17,8 @@
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o  nmi.o
-obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o
+obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o \
+		genapic.o genapic_cluster.o genapic_flat.o
 obj-$(CONFIG_PM)		+= suspend.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend_asm.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
@@ -37,3 +38,4 @@
 swiotlb-$(CONFIG_SWIOTLB)      += ../../ia64/lib/swiotlb.o
 microcode-$(subst m,y,$(CONFIG_MICROCODE))  += ../../i386/kernel/microcode.o
 intel_cacheinfo-y		+= ../../i386/kernel/cpu/intel_cacheinfo.o
+quirks-y			+= ../../i386/kernel/quirks.o
diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
--- a/arch/x86_64/kernel/apic.c	2004-10-28 22:25:57 -07:00
+++ b/arch/x86_64/kernel/apic.c	2004-10-28 22:25:57 -07:00
@@ -32,6 +32,7 @@
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
+#include <asm/mach_apic.h>
 
 int apic_verbosity;
 
@@ -300,8 +301,7 @@
 	 * Double-check whether this APIC is really registered.
 	 * This is meaningless in clustered apic mode, so we skip it.
 	 */
-	if (!clustered_apic_mode &&
-		!physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map))
+	if (!apic_id_registered())
 		BUG();
 
 	/*
@@ -309,23 +309,7 @@
 	 * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
 	 * document number 292116).  So here it goes...
 	 */
-
-	if (!clustered_apic_mode) {
-		/*
-		 * In clustered apic mode, the firmware does this for us 
-		 * Put the APIC into flat delivery mode.
-		 * Must be "all ones" explicitly for 82489DX.
-		 */
-		apic_write_around(APIC_DFR, 0xffffffff);
-
-		/*
-		 * Set up the logical destination ID.
-		 */
-		value = apic_read(APIC_LDR);
-		value &= ~APIC_LDR_MASK;
-		value |= (1<<(smp_processor_id()+24));
-		apic_write_around(APIC_LDR, value);
-	}
+	init_apic_ldr();
 
 	/*
 	 * Set Task Priority to 'accept all'. We never change this
diff -Nru a/arch/x86_64/kernel/genapic.c b/arch/x86_64/kernel/genapic.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/x86_64/kernel/genapic.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Generic APIC sub-arch probe layer.
+ *
+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+ * James Cleverdon.
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/smp.h>
+#include <asm/ipi.h>
+
+/* which logical CPU number maps to which CPU (physical APIC ID) */
+u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+EXPORT_SYMBOL(x86_cpu_to_apicid);
+u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+
+extern struct genapic apic_cluster;
+extern struct genapic apic_flat;
+
+struct genapic *genapic = &apic_flat;
+
+
+/*
+ * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
+ */
+void __init clustered_apic_check(void)
+{
+	long i;
+	u8 clusters, max_cluster;
+	u8 id;
+	u8 cluster_cnt[NUM_APIC_CLUSTERS];
+
+	memset(cluster_cnt, 0, sizeof(cluster_cnt));
+
+	for (i = 0; i < NR_CPUS; i++) {
+		id = bios_cpu_apicid[i];
+		if (id != BAD_APICID)
+			cluster_cnt[APIC_CLUSTERID(id)]++;
+	}
+
+	clusters = 0;
+	max_cluster = 0;
+	for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
+		if (cluster_cnt[i] > 0) {
+			++clusters;
+			if (cluster_cnt[i] > max_cluster)
+				max_cluster = cluster_cnt[i];
+		}
+	}
+
+	/*
+	 * If we have clusters <= 1 and CPUs <= 8 in cluster 0, then flat mode,
+	 * else if max_cluster <= 4 and cluster_cnt[15] == 0, clustered logical
+	 * else physical mode.
+	 * (We don't use lowest priority delivery + HW APIC IRQ steering, so
+	 * can ignore the clustered logical case and go straight to physical.)
+	 */
+	if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster)
+		genapic = &apic_flat;
+	else
+		genapic = &apic_cluster;
+
+	printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
+}
+
+/* Same for both flat and clustered. */
+
+void send_IPI_self(int vector)
+{
+	__send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
+}
diff -Nru a/arch/x86_64/kernel/genapic_cluster.c b/arch/x86_64/kernel/genapic_cluster.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/x86_64/kernel/genapic_cluster.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Clustered APIC subarch code.  Up to 255 CPUs, physical delivery.
+ * (A more realistic maximum is around 230 CPUs.)
+ *
+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+ * James Cleverdon.
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <asm/smp.h>
+#include <asm/ipi.h>
+
+
+/*
+ * Set up the logical destination ID.
+ *
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116).  So here it goes...
+ */
+static void cluster_init_apic_ldr(void)
+{
+	unsigned long val, id;
+	long i, count;
+	u8 lid;
+	u8 my_id = hard_smp_processor_id();
+	u8 my_cluster = APIC_CLUSTER(my_id);
+
+	/* Create logical APIC IDs by counting CPUs already in cluster. */
+	for (count = 0, i = NR_CPUS; --i >= 0; ) {
+		lid = x86_cpu_to_log_apicid[i];
+		if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster)
+			++count;
+	}
+	/*
+	 * We only have a 4 wide bitmap in cluster mode.  There's no way
+	 * to get above 60 CPUs and still give each one it's own bit.
+	 * But, we're using physical IRQ delivery, so we don't care.
+	 * Use bit 3 for the 4th through Nth CPU in each cluster.
+	 */
+	if (count >= XAPIC_DEST_CPUS_SHIFT)
+		count = 3;
+	id = my_cluster | (1UL << count);
+	x86_cpu_to_log_apicid[smp_processor_id()] = id;
+	apic_write_around(APIC_DFR, APIC_DFR_CLUSTER);
+	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
+	val |= SET_APIC_LOGICAL_ID(id);
+	apic_write_around(APIC_LDR, val);
+}
+
+static int cluster_cpu_present_to_apicid(int mps_cpu)
+{
+	if ((unsigned)mps_cpu < NR_CPUS)
+		return (int)bios_cpu_apicid[mps_cpu];
+	else
+		return BAD_APICID;
+}
+
+/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
+
+static cpumask_t cluster_target_cpus(void)
+{
+	return cpumask_of_cpu(0);
+}
+
+static void cluster_send_IPI_mask(cpumask_t mask, int vector)
+{
+	send_IPI_mask_sequence(mask, vector);
+}
+
+static void cluster_send_IPI_allbutself(int vector)
+{
+	cpumask_t mask = cpu_online_map;
+	cpu_clear(smp_processor_id(), mask);
+
+	if (!cpus_empty(mask))
+		cluster_send_IPI_mask(mask, vector);
+}
+
+static void cluster_send_IPI_all(int vector)
+{
+	cluster_send_IPI_mask(cpu_online_map, vector);
+}
+
+static int cluster_apic_id_registered(void)
+{
+	return 1;
+}
+
+static unsigned int cluster_cpu_mask_to_apicid(cpumask_t cpumask)
+{
+	int cpu;
+
+	/*
+	 * We're using fixed IRQ delivery, can only return one phys APIC ID.
+	 * May as well be the first.
+	 */
+	cpu = first_cpu(cpumask);
+	if ((unsigned)cpu < NR_CPUS)
+		return x86_cpu_to_apicid[cpu];
+	else
+		return BAD_APICID;
+}
+
+
+struct genapic apic_cluster = {
+	.name = "clustered",
+	.int_delivery_mode = dest_Fixed,
+	.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
+	.int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
+	.target_cpus = cluster_target_cpus,
+	.apic_id_registered = cluster_apic_id_registered,
+	.init_apic_ldr = cluster_init_apic_ldr,
+	.send_IPI_all = cluster_send_IPI_all,
+	.send_IPI_allbutself = cluster_send_IPI_allbutself,
+	.send_IPI_mask = cluster_send_IPI_mask,
+	.cpu_mask_to_apicid = cluster_cpu_mask_to_apicid,
+};
diff -Nru a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/x86_64/kernel/genapic_flat.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Flat APIC subarch code.  Maximum 8 CPUs, logical delivery.
+ *
+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+ * James Cleverdon.
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <asm/smp.h>
+#include <asm/ipi.h>
+
+
+static cpumask_t flat_target_cpus(void)
+{
+	return cpu_online_map;
+}
+
+/*
+ * Set up the logical destination ID.
+ *
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC.  See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116).  So here it goes...
+ */
+static void flat_init_apic_ldr(void)
+{
+	unsigned long val;
+	unsigned long num, id;
+
+	num = smp_processor_id();
+	id = 1UL << num;
+	x86_cpu_to_log_apicid[num] = id;
+	apic_write_around(APIC_DFR, APIC_DFR_FLAT);
+	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
+	val |= SET_APIC_LOGICAL_ID(id);
+	apic_write_around(APIC_LDR, val);
+}
+
+static void flat_send_IPI_allbutself(int vector)
+{
+	/*
+	 * if there are no other CPUs in the system then
+	 * we get an APIC send error if we try to broadcast.
+	 * thus we have to avoid sending IPIs in this case.
+	 */
+	if (num_online_cpus() > 1)
+		__send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
+}
+
+static void flat_send_IPI_all(int vector)
+{
+	__send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
+}
+
+static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
+{
+	unsigned long mask = cpus_addr(cpumask)[0];
+	unsigned long cfg;
+	unsigned long flags;
+
+	local_save_flags(flags);
+	local_irq_disable();
+
+	/*
+	 * Wait for idle.
+	 */
+	apic_wait_icr_idle();
+
+	/*
+	 * prepare target chip field
+	 */
+	cfg = __prepare_ICR2(mask);
+	apic_write_around(APIC_ICR2, cfg);
+
+	/*
+	 * program the ICR
+	 */
+	cfg = __prepare_ICR(0, vector, APIC_DEST_LOGICAL);
+
+	/*
+	 * Send the IPI. The write to APIC_ICR fires this off.
+	 */
+	apic_write_around(APIC_ICR, cfg);
+	local_irq_restore(flags);
+}
+
+static int flat_apic_id_registered(void)
+{
+	return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
+}
+
+static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask)
+{
+	return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
+}
+
+
+struct genapic apic_flat =  {
+	.name = "flat",
+	.int_delivery_mode = dest_LowestPrio,
+	.int_dest_mode = (APIC_DEST_LOGICAL != 0),
+	.int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
+	.target_cpus = flat_target_cpus,
+	.apic_id_registered = flat_apic_id_registered,
+	.init_apic_ldr = flat_init_apic_ldr,
+	.send_IPI_all = flat_send_IPI_all,
+	.send_IPI_allbutself = flat_send_IPI_allbutself,
+	.send_IPI_mask = flat_send_IPI_mask,
+	.cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
+};
diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
--- a/arch/x86_64/kernel/io_apic.c	2004-10-28 22:25:58 -07:00
+++ b/arch/x86_64/kernel/io_apic.c	2004-10-28 22:25:58 -07:00
@@ -36,6 +36,7 @@
 #include <asm/smp.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
+#include <asm/mach_apic.h>
 
 #define __apicdebuginit  __init
 
@@ -726,8 +727,8 @@
 		 */
 		memset(&entry,0,sizeof(entry));
 
-		entry.delivery_mode = dest_LowestPrio;
-		entry.dest_mode = INT_DELIVERY_MODE;
+		entry.delivery_mode = INT_DELIVERY_MODE;
+		entry.dest_mode = INT_DEST_MODE;
 		entry.mask = 0;				/* enable IRQ */
 		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 
@@ -795,10 +796,10 @@
 	 * We use logical delivery to get the timer IRQ
 	 * to the first CPU.
 	 */
-	entry.dest_mode = INT_DELIVERY_MODE;
+	entry.dest_mode = INT_DEST_MODE;
 	entry.mask = 0;					/* unmask IRQ now */
 	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
-	entry.delivery_mode = dest_LowestPrio;
+	entry.delivery_mode = INT_DELIVERY_MODE;
 	entry.polarity = 0;
 	entry.trigger = 0;
 	entry.vector = vector;
@@ -1146,7 +1147,6 @@
 static void __init setup_ioapic_ids_from_mpc (void)
 {
 	union IO_APIC_reg_00 reg_00;
-	physid_mask_t phys_id_present_map = phys_cpu_present_map;
 	int apic;
 	int i;
 	unsigned char old_id;
@@ -1172,28 +1172,7 @@
 			mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
 		}
 
-		/*
-		 * Sanity check, is the ID really free? Every APIC in a
-		 * system must have a unique ID or we get lots of nice
-		 * 'stuck on smp_invalidate_needed IPI wait' messages.
-	 	 */
-		if (physid_isset(mp_ioapics[apic].mpc_apicid, phys_id_present_map)) {
-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
-				apic, mp_ioapics[apic].mpc_apicid);
-			for (i = 0; i < 0xf; i++)
-				if (!physid_isset(i, phys_id_present_map))
-					break;
-			if (i >= 0xf)
-				panic("Max APIC ID exceeded!\n");
-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
-				i);
-			physid_set(i, phys_id_present_map);
-			mp_ioapics[apic].mpc_apicid = i;
-		} else {
-			printk(KERN_INFO 
-			       "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
-			physid_set(mp_ioapics[apic].mpc_apicid, phys_id_present_map);
-		}
+		printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
 
 
 		/*
@@ -1348,9 +1327,9 @@
 	dest = cpu_mask_to_apicid(mask);
 
 	/*
-	 * Only the first 8 bits are valid.
+	 * Only the high 8 bits are valid.
 	 */
-	dest = dest << 24;
+	dest = SET_APIC_LOGICAL_ID(dest);
 
 	spin_lock_irqsave(&ioapic_lock, flags);
 	__DO_ACTION(1, = dest, )
@@ -1832,7 +1811,7 @@
 
 #ifdef CONFIG_ACPI_BOOT
 
-#define IO_APIC_MAX_ID		15
+#define IO_APIC_MAX_ID		0xFE
 
 int __init io_apic_get_unique_id (int ioapic, int apic_id)
 {
@@ -1949,8 +1928,8 @@
 
 	memset(&entry,0,sizeof(entry));
 
-	entry.delivery_mode = dest_LowestPrio;
-	entry.dest_mode = INT_DELIVERY_MODE;
+	entry.delivery_mode = INT_DELIVERY_MODE;
+	entry.dest_mode = INT_DEST_MODE;
 	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 	entry.trigger = edge_level;
 	entry.polarity = active_high_low;
@@ -1983,24 +1962,6 @@
 }
 
 #endif /*CONFIG_ACPI_BOOT*/
-
-#ifndef CONFIG_SMP
-void send_IPI_self(int vector)
-{
-	unsigned int cfg;
-
-       /*
-        * Wait for idle.
-        */
-	apic_wait_icr_idle();
-	cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL;
-
-	/*
-	 * Send the IPI. The write to APIC_ICR fires this off.
-	 */
-	apic_write_around(APIC_ICR, cfg);
-}
-#endif
 
 
 /*
diff -Nru a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
--- a/arch/x86_64/kernel/mce.c	2004-10-28 22:25:57 -07:00
+++ b/arch/x86_64/kernel/mce.c	2004-10-28 22:25:57 -07:00
@@ -361,8 +361,7 @@
 
 	memset(mcelog.entry, 0, next * sizeof(struct mce));
 	mcelog.next = 0;
-	smp_wmb(); 
-	
+
 	synchronize_kernel();	
 
 	/* Collect entries that were still getting written before the synchronize. */
diff -Nru a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
--- a/arch/x86_64/kernel/mpparse.c	2004-10-28 22:25:57 -07:00
+++ b/arch/x86_64/kernel/mpparse.c	2004-10-28 22:25:57 -07:00
@@ -330,6 +330,7 @@
 			}
 		}
 	}
+	clustered_apic_check();
 	if (!num_processors)
 		printk(KERN_ERR "SMP mptable: no processors registered!\n");
 	return num_processors;
diff -Nru a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
--- a/arch/x86_64/kernel/smp.c	2004-10-28 22:25:59 -07:00
+++ b/arch/x86_64/kernel/smp.c	2004-10-28 22:25:59 -07:00
@@ -24,105 +24,7 @@
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
-
-/*
- * the following functions deal with sending IPIs between CPUs.
- *
- * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
- */
-
-static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector)
-{
-	unsigned int icr =  APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL;
-	if (vector == KDB_VECTOR) 
-		icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI; 		
-	return icr;
-}
-
-static inline int __prepare_ICR2 (unsigned int mask)
-{
-	return SET_APIC_DEST_FIELD(mask);
-}
-
-static inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
-{
-	/*
-	 * Subtle. In the case of the 'never do double writes' workaround
-	 * we have to lock out interrupts to be safe.  As we don't care
-	 * of the value read we use an atomic rmw access to avoid costly
-	 * cli/sti.  Otherwise we use an even cheaper single atomic write
-	 * to the APIC.
-	 */
-	unsigned int cfg;
-
-	/*
-	 * Wait for idle.
-	 */
-	apic_wait_icr_idle();
-
-	/*
-	 * No need to touch the target chip field
-	 */
-	cfg = __prepare_ICR(shortcut, vector);
-
-	/*
-	 * Send the IPI. The write to APIC_ICR fires this off.
-	 */
-	apic_write_around(APIC_ICR, cfg);
-}
-
-static inline void send_IPI_allbutself(int vector)
-{
-	/*
-	 * if there are no other CPUs in the system then
-	 * we get an APIC send error if we try to broadcast.
-	 * thus we have to avoid sending IPIs in this case.
-	 */
-	if (num_online_cpus() > 1)
-		__send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
-}
-
-static inline void send_IPI_all(int vector)
-{
-	__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
-}
-
-void send_IPI_self(int vector)
-{
-	__send_IPI_shortcut(APIC_DEST_SELF, vector);
-}
-
-static inline void send_IPI_mask(cpumask_t cpumask, int vector)
-{
-	unsigned long mask = cpus_addr(cpumask)[0];
-	unsigned long cfg;
-	unsigned long flags;
-
-	local_save_flags(flags);
-	local_irq_disable();
-
-	/*
-	 * Wait for idle.
-	 */
-	apic_wait_icr_idle();
-
-	/*
-	 * prepare target chip field
-	 */
-	cfg = __prepare_ICR2(mask);
-	apic_write_around(APIC_ICR2, cfg);
-
-	/*
-	 * program the ICR 
-	 */
-	cfg = __prepare_ICR(0, vector);
-	
-	/*
-	 * Send the IPI. The write to APIC_ICR fires this off.
-	 */
-	apic_write_around(APIC_ICR, cfg);
-	local_irq_restore(flags);
-}
+#include <asm/mach_apic.h>
 
 /*
  *	Smarter SMP flushing macros. 
diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
--- a/arch/x86_64/kernel/smpboot.c	2004-10-28 22:25:59 -07:00
+++ b/arch/x86_64/kernel/smpboot.c	2004-10-28 22:25:59 -07:00
@@ -56,15 +56,12 @@
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
-char phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
+/* Package ID of each logical CPU */
+u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
 
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map;
 
-/* which logical CPU number maps to which CPU (physical APIC ID) */
-volatile char x86_cpu_to_apicid[NR_CPUS];
-EXPORT_SYMBOL(x86_cpu_to_apicid);
-
 static cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
 static cpumask_t smp_commenced_mask;
@@ -658,6 +655,8 @@
 		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
 		clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
 		cpucount--;
+		x86_cpu_to_apicid[cpu] = BAD_APICID;
+		x86_cpu_to_log_apicid[cpu] = BAD_APICID;
 	}
 }
 
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c	2004-10-28 22:25:58 -07:00
+++ b/arch/x86_64/kernel/time.c	2004-10-28 22:25:58 -07:00
@@ -776,31 +776,9 @@
 fs_initcall(late_hpet_init);
 #endif
 
-static int hpet_init(void)
+static int hpet_timer_stop_set_go(unsigned long tick)
 {
-	unsigned int cfg, id;
-
-	if (!vxtime.hpet_address)
-		return -1;
-	set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
-	__set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
-
-/*
- * Read the period, compute tick and quotient.
- */
-
-	id = hpet_readl(HPET_ID);
-
-	if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) ||
-	    !(id & HPET_ID_LEGSUP))
-		return -1;
-
-	hpet_period = hpet_readl(HPET_PERIOD);
-	if (hpet_period < 100000 || hpet_period > 100000000)
-		return -1;
-
-	hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
-		hpet_period;
+	unsigned int cfg;
 
 /*
  * Stop the timers and reset the main counter.
@@ -832,6 +810,40 @@
 	return 0;
 }
 
+static int hpet_init(void)
+{
+	unsigned int id;
+
+	if (!vxtime.hpet_address)
+		return -1;
+	set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
+	__set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
+
+/*
+ * Read the period, compute tick and quotient.
+ */
+
+	id = hpet_readl(HPET_ID);
+
+	if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) ||
+	    !(id & HPET_ID_LEGSUP))
+		return -1;
+
+	hpet_period = hpet_readl(HPET_PERIOD);
+	if (hpet_period < 100000 || hpet_period > 100000000)
+		return -1;
+
+	hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
+		hpet_period;
+
+	return hpet_timer_stop_set_go(hpet_tick);
+}
+
+static int hpet_reenable(void)
+{
+	return hpet_timer_stop_set_go(hpet_tick);
+}
+
 void __init pit_init(void)
 {
 	unsigned long flags;
@@ -941,7 +953,7 @@
 
 static long clock_cmos_diff;
 
-static int time_suspend(struct sys_device *dev, u32 state)
+static int timer_suspend(struct sys_device *dev, u32 state)
 {
 	/*
 	 * Estimate time zone so that set_time can update the clock
@@ -951,10 +963,15 @@
 	return 0;
 }
 
-static int time_resume(struct sys_device *dev)
+static int timer_resume(struct sys_device *dev)
 {
 	unsigned long flags;
-	unsigned long sec = get_cmos_time() + clock_cmos_diff;
+	unsigned long sec;
+
+	if (vxtime.hpet_address)
+		hpet_reenable();
+
+	sec = get_cmos_time() + clock_cmos_diff;
 	write_seqlock_irqsave(&xtime_lock,flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
@@ -962,24 +979,24 @@
 	return 0;
 }
 
-static struct sysdev_class pit_sysclass = {
-	.resume = time_resume,
-	.suspend = time_suspend,
-	set_kset_name("pit"),
+static struct sysdev_class timer_sysclass = {
+	.resume = timer_resume,
+	.suspend = timer_suspend,
+	set_kset_name("timer"),
 };
 
 
 /* XXX this driverfs stuff should probably go elsewhere later -john */
-static struct sys_device device_i8253 = {
+static struct sys_device device_timer = {
 	.id	= 0,
-	.cls	= &pit_sysclass,
+	.cls	= &timer_sysclass,
 };
 
 static int time_init_device(void)
 {
-	int error = sysdev_class_register(&pit_sysclass);
+	int error = sysdev_class_register(&timer_sysclass);
 	if (!error)
-		error = sysdev_register(&device_i8253);
+		error = sysdev_register(&device_timer);
 	return error;
 }
 
diff -Nru a/crypto/sha256.c b/crypto/sha256.c
--- a/crypto/sha256.c	2004-10-28 22:25:57 -07:00
+++ b/crypto/sha256.c	2004-10-28 22:25:57 -07:00
@@ -63,15 +63,7 @@
 
 static inline void LOAD_OP(int I, u32 *W, const u8 *input)
 {
-	u32 t1 = input[(4 * I)] & 0xff;
-
-	t1 <<= 8;
-	t1 |= input[(4 * I) + 1] & 0xff;
-	t1 <<= 8;
-	t1 |= input[(4 * I) + 2] & 0xff;
-	t1 <<= 8;
-	t1 |= input[(4 * I) + 3] & 0xff;
-	W[I] = t1;
+	W[I] = __be32_to_cpu( ((u32*)(input))[I] );
 }
 
 static inline void BLEND_OP(int I, u32 *W)
diff -Nru a/crypto/sha512.c b/crypto/sha512.c
--- a/crypto/sha512.c	2004-10-28 22:25:59 -07:00
+++ b/crypto/sha512.c	2004-10-28 22:25:59 -07:00
@@ -30,6 +30,7 @@
 	u64 state[8];
 	u32 count[4];
 	u8 buf[128];
+	u64 W[80];
 };
 
 static inline u64 Ch(u64 x, u64 y, u64 z)
@@ -104,34 +105,18 @@
 
 static inline void LOAD_OP(int I, u64 *W, const u8 *input)
 {
-        u64 t1  = input[(8*I)  ] & 0xff;
-        t1 <<= 8;
-        t1 |= input[(8*I)+1] & 0xff;
-        t1 <<= 8;
-        t1 |= input[(8*I)+2] & 0xff;
-        t1 <<= 8;
-        t1 |= input[(8*I)+3] & 0xff;
-        t1 <<= 8;
-        t1 |= input[(8*I)+4] & 0xff;
-        t1 <<= 8;
-        t1 |= input[(8*I)+5] & 0xff;
-        t1 <<= 8;
-        t1 |= input[(8*I)+6] & 0xff;
-        t1 <<= 8;
-        t1 |= input[(8*I)+7] & 0xff;
-        W[I] = t1;
+	W[I] = __be64_to_cpu( ((u64*)(input))[I] );
 }
 
 static inline void BLEND_OP(int I, u64 *W)
 {
-        W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
 }
 
 static void
-sha512_transform(u64 *state, const u8 *input)
+sha512_transform(u64 *state, u64 *W, const u8 *input)
 {
 	u64 a, b, c, d, e, f, g, h, t1, t2;
-	u64 W[80];
 
 	int i;
 
@@ -172,7 +157,6 @@
 
 	/* erase our data */
 	a = b = c = d = e = f = g = h = t1 = t2 = 0;
-	memset(W, 0, 80 * sizeof(u64));
 }
 
 static void
@@ -230,10 +214,10 @@
 	/* Transform as many times as possible. */
 	if (len >= part_len) {
 		memcpy(&sctx->buf[index], data, part_len);
-		sha512_transform(sctx->state, sctx->buf);
+		sha512_transform(sctx->state, sctx->W, sctx->buf);
 
 		for (i = part_len; i + 127 < len; i+=128)
-			sha512_transform(sctx->state, &data[i]);
+			sha512_transform(sctx->state, sctx->W, &data[i]);
 
 		index = 0;
 	} else {
@@ -242,6 +226,9 @@
 
 	/* Buffer remaining input */
 	memcpy(&sctx->buf[index], &data[i], len - i);
+
+	/* erase our data */
+	memset(sctx->W, 0, sizeof(sctx->W));
 }
 
 static void
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	2004-10-28 22:25:59 -07:00
+++ b/drivers/Makefile	2004-10-28 22:25:59 -07:00
@@ -17,8 +17,9 @@
 # default.
 obj-y				+= char/
 
-# i810fb depends on char/agp/
+# i810fb and intelfb depend on char/agp/
 obj-$(CONFIG_FB_I810)           += video/i810/
+obj-$(CONFIG_FB_INTEL)          += video/intelfb/
 
 # we also need input/serio early so serio bus is initialized by the time
 # serial drivers start registering their serio ports
diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
--- a/drivers/acpi/thermal.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/acpi/thermal.c	2004-10-28 22:25:59 -07:00
@@ -76,7 +76,7 @@
 MODULE_LICENSE("GPL");
 
 static int tzp;
-MODULE_PARM(tzp, "i");
+module_param(tzp, int, 0);
 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
 
 
diff -Nru a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h
--- a/drivers/atm/fore200e.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/atm/fore200e.h	2004-10-28 22:25:58 -07:00
@@ -645,7 +645,7 @@
 
 typedef struct fw_header {
     u32 magic;           /* magic number                               */
-    u32 version;         /* firware version id                         */
+    u32 version;         /* firmware version id                        */
     u32 load_offset;     /* fw load offset in board memory             */
     u32 start_offset;    /* fw execution start address in board memory */
 } fw_header_t;
diff -Nru a/drivers/atm/horizon.c b/drivers/atm/horizon.c
--- a/drivers/atm/horizon.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/atm/horizon.c	2004-10-28 22:25:56 -07:00
@@ -354,8 +354,7 @@
 
 /********** globals **********/
 
-static hrz_dev * hrz_devs = NULL;
-static struct timer_list housekeeping;
+static void do_housekeeping (unsigned long arg);
 
 static unsigned short debug = 0;
 static unsigned short vpi_bits = 0;
@@ -1386,7 +1385,7 @@
 
 static irqreturn_t interrupt_handler(int irq, void *dev_id,
 					struct pt_regs *pt_regs) {
-  hrz_dev * dev = hrz_devs;
+  hrz_dev * dev = (hrz_dev *) dev_id;
   u32 int_source;
   unsigned int irq_ok;
   (void) pt_regs;
@@ -1397,16 +1396,6 @@
     PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq);
     return IRQ_NONE;
   }
-  // Did one of our cards generate the interrupt?
-  while (dev) {
-    if (dev == dev_id)
-      break;
-    dev = dev->prev;
-  }
-  if (!dev) {
-    PRINTD (DBG_IRQ, "irq not for me: %d", irq);
-    return IRQ_NONE;
-  }
   if (irq != dev->irq) {
     PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq);
     return IRQ_NONE;
@@ -1462,28 +1451,18 @@
 
 /********** housekeeping **********/
 
-static void set_timer (struct timer_list * timer, unsigned int delay) {
-  timer->expires = jiffies + delay;
-  add_timer (timer);
-  return;
-}
-
 static void do_housekeeping (unsigned long arg) {
   // just stats at the moment
-  hrz_dev * dev = hrz_devs;
-  (void) arg;
-  // data is set to zero at module unload
-  if (housekeeping.data) {
-    while (dev) {
-      // collect device-specific (not driver/atm-linux) stats here
-      dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF);
-      dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF);
-      dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF);
-      dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF);
-      dev = dev->prev;
-    }
-    set_timer (&housekeeping, HZ/10);
-  }
+  hrz_dev * dev = (hrz_dev *) arg;
+
+  // collect device-specific (not driver/atm-linux) stats here
+  dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF);
+  dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF);
+  dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF);
+  dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF);
+
+  mod_timer (&dev->housekeeping, jiffies + HZ/10);
+
   return;
 }
 
@@ -2719,157 +2698,176 @@
   .owner	= THIS_MODULE,
 };
 
-static int __init hrz_probe (void) {
-  struct pci_dev * pci_dev;
-  int devs;
-  
-  PRINTD (DBG_FLOW, "hrz_probe");
-  
-  devs = 0;
-  pci_dev = NULL;
-  while ((pci_dev = pci_find_device
-	  (PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, pci_dev)
-	  )) {
-    hrz_dev * dev;
-    
-    // adapter slot free, read resources from PCI configuration space
-    u32 iobase = pci_resource_start (pci_dev, 0);
-    u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1));
-    u8 irq = pci_dev->irq;
-    
-    /* XXX DEV_LABEL is a guess */
-    if (!request_region (iobase, HRZ_IO_EXTENT, DEV_LABEL))
-  	  continue;
-
-    if (pci_enable_device (pci_dev))
-      continue;
-    
-    dev = kmalloc (sizeof(hrz_dev), GFP_KERNEL);
-    if (!dev) {
-      // perhaps we should be nice: deregister all adapters and abort?
-      PRINTD (DBG_ERR, "out of memory");
-      continue;
-    }
-    
-    memset (dev, 0, sizeof(hrz_dev));
-    
-    // grab IRQ and install handler - move this someplace more sensible
-    if (request_irq (irq,
-		     interrupt_handler,
-		     SA_SHIRQ, /* irqflags guess */
-		     DEV_LABEL, /* name guess */
-		     dev)) {
-      PRINTD (DBG_WARN, "request IRQ failed!");
-      // free_irq is at "endif"
-    } else {
-      
-      PRINTD (DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
-	      iobase, irq, membase);
-      
-      dev->atm_dev = atm_dev_register (DEV_LABEL, &hrz_ops, -1, NULL);
-      if (!(dev->atm_dev)) {
-	PRINTD (DBG_ERR, "failed to register Madge ATM adapter");
-      } else {
+static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+{
+	hrz_dev * dev;
+	int err = 0;
+
+	// adapter slot free, read resources from PCI configuration space
+	u32 iobase = pci_resource_start (pci_dev, 0);
+	u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1));
+	u8 irq = pci_dev->irq;
 	unsigned char lat;
-	
-	PRINTD (DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p",
-		dev->atm_dev->number, dev, dev->atm_dev);
+
+	PRINTD (DBG_FLOW, "hrz_probe");
+
+	/* XXX DEV_LABEL is a guess */
+	if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL))
+		return -EINVAL;
+
+	if (pci_enable_device(pci_dev)) {
+		err = -EINVAL;
+		goto out_release;
+	}
+
+	dev = kmalloc(sizeof(hrz_dev), GFP_KERNEL);
+	if (!dev) {
+		// perhaps we should be nice: deregister all adapters and abort?
+		PRINTD(DBG_ERR, "out of memory");
+		err = -ENOMEM;
+		goto out_disable;
+	}
+
+	memset(dev, 0, sizeof(hrz_dev));
+
+	pci_set_drvdata(pci_dev, dev);
+
+	// grab IRQ and install handler - move this someplace more sensible
+	if (request_irq(irq,
+			interrupt_handler,
+			SA_SHIRQ, /* irqflags guess */
+			DEV_LABEL, /* name guess */
+			dev)) {
+		PRINTD(DBG_WARN, "request IRQ failed!");
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
+	       iobase, irq, membase);
+
+	dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL);
+	if (!(dev->atm_dev)) {
+		PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
+		err = -EINVAL;
+		goto out_free_irq;
+	}
+
+	PRINTD(DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p",
+	       dev->atm_dev->number, dev, dev->atm_dev);
 	dev->atm_dev->dev_data = (void *) dev;
 	dev->pci_dev = pci_dev; 
-	
+
 	// enable bus master accesses
-	pci_set_master (pci_dev);
-	
+	pci_set_master(pci_dev);
+
 	// frobnicate latency (upwards, usually)
-	pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &lat);
+	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat);
 	if (pci_lat) {
-	  PRINTD (DBG_INFO, "%s PCI latency timer from %hu to %hu",
-		  "changing", lat, pci_lat);
-	  pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, pci_lat);
+		PRINTD(DBG_INFO, "%s PCI latency timer from %hu to %hu",
+		       "changing", lat, pci_lat);
+		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, pci_lat);
 	} else if (lat < MIN_PCI_LATENCY) {
-	  PRINTK (KERN_INFO, "%s PCI latency timer from %hu to %hu",
-		  "increasing", lat, MIN_PCI_LATENCY);
-	  pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY);
+		PRINTK(KERN_INFO, "%s PCI latency timer from %hu to %hu",
+		       "increasing", lat, MIN_PCI_LATENCY);
+		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY);
 	}
-	
+
 	dev->iobase = iobase;
 	dev->irq = irq; 
 	dev->membase = membase; 
-	
+
 	dev->rx_q_entry = dev->rx_q_reset = &memmap->rx_q_entries[0];
 	dev->rx_q_wrap  = &memmap->rx_q_entries[RX_CHANS-1];
-	
+
 	// these next three are performance hacks
 	dev->last_vc = -1;
 	dev->tx_last = -1;
 	dev->tx_idle = 0;
-	
+
 	dev->tx_regions = 0;
 	dev->tx_bytes = 0;
 	dev->tx_skb = NULL;
 	dev->tx_iovec = NULL;
-	
+
 	dev->tx_cell_count = 0;
 	dev->rx_cell_count = 0;
 	dev->hec_error_count = 0;
 	dev->unassigned_cell_count = 0;
-	
+
 	dev->noof_spare_buffers = 0;
-	
+
 	{
-	  unsigned int i;
-	  for (i = 0; i < TX_CHANS; ++i)
-	    dev->tx_channel_record[i] = -1;
+		unsigned int i;
+		for (i = 0; i < TX_CHANS; ++i)
+			dev->tx_channel_record[i] = -1;
 	}
-	
+
 	dev->flags = 0;
-	
+
 	// Allocate cell rates and remember ASIC version
 	// Fibre: ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53
 	// Copper: (WRONG) we want 6 into the above, close to 25Mb/s
 	// Copper: (plagarise!) 25600000/8/270*260/53 - n/53
-	
-	if (hrz_init (dev)) {
-	  // to be really pedantic, this should be ATM_OC3c_PCR
-	  dev->tx_avail = ATM_OC3_PCR;
-	  dev->rx_avail = ATM_OC3_PCR;
-	  set_bit (ultra, &dev->flags); // NOT "|= ultra" !
+
+	if (hrz_init(dev)) {
+		// to be really pedantic, this should be ATM_OC3c_PCR
+		dev->tx_avail = ATM_OC3_PCR;
+		dev->rx_avail = ATM_OC3_PCR;
+		set_bit(ultra, &dev->flags); // NOT "|= ultra" !
 	} else {
-	  dev->tx_avail = ((25600000/8)*26)/(27*53);
-	  dev->rx_avail = ((25600000/8)*26)/(27*53);
-	  PRINTD (DBG_WARN, "Buggy ASIC: no TX bus-mastering.");
+		dev->tx_avail = ((25600000/8)*26)/(27*53);
+		dev->rx_avail = ((25600000/8)*26)/(27*53);
+		PRINTD(DBG_WARN, "Buggy ASIC: no TX bus-mastering.");
 	}
-	
+
 	// rate changes spinlock
-	spin_lock_init (&dev->rate_lock);
-	
+	spin_lock_init(&dev->rate_lock);
+
 	// on-board memory access spinlock; we want atomic reads and
 	// writes to adapter memory (handles IRQ and SMP)
-	spin_lock_init (&dev->mem_lock);
-	
-	init_waitqueue_head (&dev->tx_queue);
-	
+	spin_lock_init(&dev->mem_lock);
+
+	init_waitqueue_head(&dev->tx_queue);
+
 	// vpi in 0..4, vci in 6..10
 	dev->atm_dev->ci_range.vpi_bits = vpi_bits;
 	dev->atm_dev->ci_range.vci_bits = 10-vpi_bits;
-	
-	// update count and linked list
-	++devs;
-	dev->prev = hrz_devs;
-	hrz_devs = dev;
-	// success
-	continue;
-	
-	/* not currently reached */
-	atm_dev_deregister (dev->atm_dev);
-      } /* atm_dev_register */
-      free_irq (irq, dev);
-	
-    } /* request_irq */
-    kfree (dev);
-    release_region(iobase, HRZ_IO_EXTENT);
-  } /* kmalloc and while */
-  return devs;
+
+	init_timer(&dev->housekeeping);
+	dev->housekeeping.function = do_housekeeping;
+	dev->housekeeping.data = (unsigned long) dev;
+	mod_timer(&dev->housekeeping, jiffies);
+
+out:
+	return err;
+
+out_free_irq:
+	free_irq(dev->irq, dev);
+out_free:
+	kfree(dev);
+out_disable:
+	pci_disable_device(pci_dev);
+out_release:
+	release_region(iobase, HRZ_IO_EXTENT);
+	goto out;
+}
+
+static void __devexit hrz_remove_one(struct pci_dev *pci_dev)
+{
+	hrz_dev *dev;
+
+	dev = pci_get_drvdata(pci_dev);
+
+	PRINTD(DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev);
+	del_timer_sync(&dev->housekeeping);
+	hrz_reset(dev);
+	atm_dev_deregister(dev->atm_dev);
+	free_irq(dev->irq, dev);
+	release_region(dev->iobase, HRZ_IO_EXTENT);
+	kfree(dev);
+
+	pci_disable_device(pci_dev);
 }
 
 static void __init hrz_check_args (void) {
@@ -2909,11 +2907,22 @@
 MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames");
 MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles");
 
+static struct pci_device_id hrz_pci_tbl[] = {
+	{ PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, PCI_ANY_ID, PCI_ANY_ID,
+	  0, 0, 0 },
+	{ 0, }
+};
+
+static struct pci_driver hrz_driver = {
+	.name =		"horizon",
+	.probe =	hrz_probe,
+	.remove =	__devexit_p(hrz_remove_one),
+	.id_table =	hrz_pci_tbl,
+};
+
 /********** module entry **********/
 
 static int __init hrz_module_init (void) {
-  int devs;
-  
   // sanity check - cast is needed since printk does not support %Zu
   if (sizeof(struct MEMMAP) != 128*1024/4) {
     PRINTK (KERN_ERR, "Fix struct MEMMAP (is %lu fakewords).",
@@ -2927,44 +2936,15 @@
   hrz_check_args();
   
   // get the juice
-  devs = hrz_probe();
-  
-  if (devs) {
-    init_timer (&housekeeping);
-    housekeeping.function = do_housekeeping;
-    // paranoia
-    housekeeping.data = 1;
-    set_timer (&housekeeping, 0);
-  } else {
-    PRINTK (KERN_ERR, "no (usable) adapters found");
-  }
-  
-  return devs ? 0 : -ENODEV;
+  return pci_module_init(&hrz_driver);
 }
 
 /********** module exit **********/
 
 static void __exit hrz_module_exit (void) {
-  hrz_dev * dev;
   PRINTD (DBG_FLOW, "cleanup_module");
   
-  // paranoia
-  housekeeping.data = 0;
-  del_timer (&housekeeping);
-  
-  while (hrz_devs) {
-    dev = hrz_devs;
-    hrz_devs = dev->prev;
-    
-    PRINTD (DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev);
-    hrz_reset (dev);
-    atm_dev_deregister (dev->atm_dev);
-    free_irq (dev->irq, dev);
-    release_region (dev->iobase, HRZ_IO_EXTENT);
-    kfree (dev);
-  }
-  
-  return;
+  return pci_unregister_driver(&hrz_driver);
 }
 
 module_init(hrz_module_init);
diff -Nru a/drivers/atm/horizon.h b/drivers/atm/horizon.h
--- a/drivers/atm/horizon.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/atm/horizon.h	2004-10-28 22:25:59 -07:00
@@ -457,7 +457,7 @@
   unsigned long    unassigned_cell_count;
 
   struct pci_dev * pci_dev;
-  struct hrz_dev * prev;
+  struct timer_list housekeeping;
 };
 
 typedef struct hrz_dev hrz_dev;
diff -Nru a/drivers/base/Kconfig b/drivers/base/Kconfig
--- a/drivers/base/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/drivers/base/Kconfig	2004-10-28 22:25:57 -07:00
@@ -14,7 +14,7 @@
 	default y
 	help
 	  Say yes to avoid building firmware. Firmware is usually shipped
-	  with the driver, and only when updating the firware a rebuild
+	  with the driver, and only when updating the firmware a rebuild
 	  should be made.
 	  If unsure say Y here.
 
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/base/bus.c	2004-10-28 22:25:57 -07:00
@@ -515,7 +515,7 @@
 
 	if (bus) {
 		pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
-		error = kobject_set_name(&drv->kobj, drv->name);
+		error = kobject_set_name(&drv->kobj, "%s", drv->name);
 		if (error) {
 			put_bus(bus);
 			return error;
@@ -666,7 +666,7 @@
 {
 	int retval;
 
-	retval = kobject_set_name(&bus->subsys.kset.kobj, bus->name);
+	retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
 	if (retval)
 		goto out;
 
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/base/class.c	2004-10-28 22:25:59 -07:00
@@ -139,7 +139,7 @@
 
 	INIT_LIST_HEAD(&cls->children);
 	INIT_LIST_HEAD(&cls->interfaces);
-	error = kobject_set_name(&cls->subsys.kset.kobj, cls->name);
+	error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
 	if (error)
 		return error;
 
@@ -368,7 +368,7 @@
 		 class_dev->class_id);
 
 	/* first, register with generic layer. */
-	kobject_set_name(&class_dev->kobj, class_dev->class_id);
+	kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
 	if (parent)
 		class_dev->kobj.parent = &parent->subsys.kset.kobj;
 
diff -Nru a/drivers/base/core.c b/drivers/base/core.c
--- a/drivers/base/core.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/base/core.c	2004-10-28 22:25:56 -07:00
@@ -221,7 +221,7 @@
 	pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
 
 	/* first, register with generic layer. */
-	kobject_set_name(&dev->kobj, dev->bus_id);
+	kobject_set_name(&dev->kobj, "%s", dev->bus_id);
 	if (parent)
 		dev->kobj.parent = &parent->kobj;
 
diff -Nru a/drivers/base/cpu.c b/drivers/base/cpu.c
--- a/drivers/base/cpu.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/base/cpu.c	2004-10-28 22:25:57 -07:00
@@ -32,6 +32,8 @@
 	switch (buf[0]) {
 	case '0':
 		ret = cpu_down(cpu->sysdev.id);
+		if (!ret)
+			kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
 		break;
 	case '1':
 		ret = cpu_up(cpu->sysdev.id);
diff -Nru a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
--- a/drivers/base/firmware_class.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/base/firmware_class.c	2004-10-28 22:25:59 -07:00
@@ -583,4 +583,3 @@
 EXPORT_SYMBOL(request_firmware);
 EXPORT_SYMBOL(request_firmware_nowait);
 EXPORT_SYMBOL(register_firmware);
-EXPORT_SYMBOL(firmware_class);
diff -Nru a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
--- a/drivers/block/cfq-iosched.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/block/cfq-iosched.c	2004-10-28 22:25:58 -07:00
@@ -1482,7 +1482,6 @@
 static void cfq_put_cfqd(struct cfq_data *cfqd)
 {
 	request_queue_t *q = cfqd->queue;
-	elevator_t *e = q->elevator;
 	struct cfq_queue *cfqq;
 
 	if (!atomic_dec_and_test(&cfqd->ref))
@@ -1500,7 +1499,6 @@
 
 	blk_put_queue(q);
 
-	e->elevator_data = NULL;
 	mempool_destroy(cfqd->crq_pool);
 	kfree(cfqd->crq_hash);
 	kfree(cfqd->cfq_hash);
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/block/elevator.c	2004-10-28 22:25:59 -07:00
@@ -113,14 +113,28 @@
 	return e;
 }
 
+static void elevator_put(struct elevator_type *e)
+{
+	module_put(e->elevator_owner);
+}
+
+static struct elevator_type *elevator_get(const char *name)
+{
+	struct elevator_type *e = elevator_find(name);
+
+	if (!e)
+		return NULL;
+	if (!try_module_get(e->elevator_owner))
+		return NULL;
+
+	return e;
+}
+
 static int elevator_attach(request_queue_t *q, struct elevator_type *e,
 			   struct elevator_queue *eq)
 {
 	int ret = 0;
 
-	if (!try_module_get(e->elevator_owner))
-		return -EINVAL;
-
 	memset(eq, 0, sizeof(*eq));
 	eq->ops = &e->ops;
 	eq->elevator_type = e;
@@ -156,7 +170,8 @@
 #else
 #error "You must build at least 1 IO scheduler into the kernel"
 #endif
-	printk("elevator: using %s as default io scheduler\n", chosen_elevator);
+	printk(KERN_INFO "elevator: using %s as default io scheduler\n",
+							chosen_elevator);
 }
 
 static int __init elevator_setup(char *str)
@@ -178,17 +193,21 @@
 	if (!name)
 		name = chosen_elevator;
 
-	e = elevator_find(name);
+	e = elevator_get(name);
 	if (!e)
 		return -EINVAL;
 
 	eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL);
-	if (!eq)
+	if (!eq) {
+		elevator_put(e->elevator_type);
 		return -ENOMEM;
+	}
 
 	ret = elevator_attach(q, e, eq);
-	if (ret)
+	if (ret) {
 		kfree(eq);
+		elevator_put(e->elevator_type);
+	}
 
 	return ret;
 }
@@ -198,7 +217,7 @@
 	if (e->ops->elevator_exit_fn)
 		e->ops->elevator_exit_fn(e);
 
-	module_put(e->elevator_type->elevator_owner);
+	elevator_put(e->elevator_type);
 	e->elevator_type = NULL;
 	kfree(e);
 }
@@ -271,15 +290,24 @@
 		blk_plug_device(q);
 
 	rq->q = q;
-	q->elevator->ops->elevator_add_req_fn(q, rq, where);
 
-	if (blk_queue_plugged(q)) {
-		int nrq = q->rq.count[READ] + q->rq.count[WRITE] - q->in_flight;
+	if (!test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
+		q->elevator->ops->elevator_add_req_fn(q, rq, where);
 
-		if (nrq == q->unplug_thresh)
-			__generic_unplug_device(q);
-	}
+		if (blk_queue_plugged(q)) {
+			int nrq = q->rq.count[READ] + q->rq.count[WRITE]
+				  - q->in_flight;
 
+			if (nrq == q->unplug_thresh)
+				__generic_unplug_device(q);
+		}
+	} else
+		/*
+		 * if drain is set, store the request "locally". when the drain
+		 * is finished, the requests will be handed ordered to the io
+		 * scheduler
+		 */
+		list_add_tail(&rq->queuelist, &q->drain_list);
 }
 
 void elv_add_request(request_queue_t *q, struct request *rq, int where,
@@ -333,7 +361,8 @@
 			end_that_request_chunk(rq, 0, nr_bytes);
 			end_that_request_last(rq);
 		} else {
-			printk("%s: bad return=%d\n", __FUNCTION__, ret);
+			printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__,
+								ret);
 			break;
 		}
 	}
@@ -486,7 +515,7 @@
 	list_add_tail(&e->list, &elv_list);
 	spin_unlock_irq(&elv_list_lock);
 
-	printk("io scheduler %s registered\n", e->elevator_name);
+	printk(KERN_INFO "io scheduler %s registered\n", e->elevator_name);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(elv_register);
@@ -503,19 +532,25 @@
  * switch to new_e io scheduler. be careful not to introduce deadlocks -
  * we don't free the old io scheduler, before we have allocated what we
  * need for the new one. this way we have a chance of going back to the old
- * one, if the new one fails init for some reason
+ * one, if the new one fails init for some reason. we also do an intermediate
+ * switch to noop to ensure safety with stack-allocated requests, since they
+ * don't originate from the block layer allocator. noop is safe here, because
+ * it never needs to touch the elevator itself for completion events. DRAIN
+ * flags will make sure we don't touch it for additions either.
  */
 static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
 {
 	elevator_t *e = kmalloc(sizeof(elevator_t), GFP_KERNEL);
+	struct elevator_type *noop_elevator = NULL;
 	elevator_t *old_elevator;
 
-	if (!e) {
-		printk("elevator: out of memory\n");
-		return;
-	}
+	if (!e)
+		goto error;
 
-	blk_wait_queue_drained(q);
+	/*
+	 * first step, drain requests from the block freelist
+	 */
+	blk_wait_queue_drained(q, 0);
 
 	/*
 	 * unregister old elevator data
@@ -524,6 +559,18 @@
 	old_elevator = q->elevator;
 
 	/*
+ 	 * next step, switch to noop since it uses no private rq structures
+	 * and doesn't allocate any memory for anything. then wait for any
+	 * non-fs requests in-flight
+ 	 */
+	noop_elevator = elevator_get("noop");
+	spin_lock_irq(q->queue_lock);
+	elevator_attach(q, noop_elevator, e);
+	spin_unlock_irq(q->queue_lock);
+
+	blk_wait_queue_drained(q, 1);
+
+	/*
 	 * attach and start new elevator
 	 */
 	if (elevator_attach(q, new_e, e))
@@ -537,6 +584,7 @@
 	 */
 	elevator_exit(old_elevator);
 	blk_finish_queue_drain(q);
+	elevator_put(noop_elevator);
 	return;
 
 fail_register:
@@ -549,7 +597,11 @@
 	q->elevator = old_elevator;
 	elv_register_queue(q);
 	blk_finish_queue_drain(q);
-	printk("elevator: switch to %s failed\n", new_e->elevator_name);
+error:
+	if (noop_elevator)
+		elevator_put(noop_elevator);
+	elevator_put(new_e);
+	printk(KERN_ERR "elevator: switch to %s failed\n",new_e->elevator_name);
 }
 
 ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count)
@@ -563,11 +615,14 @@
 	if (elevator_name[strlen(elevator_name) - 1] == '\n')
 		elevator_name[strlen(elevator_name) - 1] = '\0';
 
-	e = elevator_find(elevator_name);
+	e = elevator_get(elevator_name);
 	if (!e) {
-		printk("elevator: type %s not found\n", elevator_name);
+		printk(KERN_ERR "elevator: type %s not found\n", elevator_name);
 		return -EINVAL;
 	}
+
+	if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name))
+		return count;
 
 	elevator_switch(q, e);
 	return count;
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/block/floppy.c	2004-10-28 22:25:57 -07:00
@@ -4286,6 +4286,13 @@
 	}
 
 	use_virtual_dma = can_use_virtual_dma & 1;
+#if defined(CONFIG_PPC64)
+	if (check_legacy_ioport(FDC1)) {
+		del_timer(&fd_timeout);
+		err = -ENODEV;
+		goto out_unreg_region;
+	}
+#endif
 	fdc_state[0].address = FDC1;
 	if (fdc_state[0].address == -1) {
 		del_timer(&fd_timeout);
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/block/ll_rw_blk.c	2004-10-28 22:25:57 -07:00
@@ -261,6 +261,8 @@
 	blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
 
 	blk_queue_activity_fn(q, NULL, NULL);
+
+	INIT_LIST_HEAD(&q->drain_list);
 }
 
 EXPORT_SYMBOL(blk_queue_make_request);
@@ -2481,20 +2483,42 @@
 void blk_finish_queue_drain(request_queue_t *q)
 {
 	struct request_list *rl = &q->rq;
+	struct request *rq;
 
+	spin_lock_irq(q->queue_lock);
 	clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
+
+	while (!list_empty(&q->drain_list)) {
+		rq = list_entry_rq(q->drain_list.next);
+
+		list_del_init(&rq->queuelist);
+		__elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
+	}
+
+	spin_unlock_irq(q->queue_lock);
+
 	wake_up(&rl->wait[0]);
 	wake_up(&rl->wait[1]);
 	wake_up(&rl->drain);
 }
 
+static int wait_drain(request_queue_t *q, struct request_list *rl, int dispatch)
+{
+	int wait = rl->count[READ] + rl->count[WRITE];
+
+	if (dispatch)
+		wait += !list_empty(&q->queue_head);
+
+	return wait;
+}
+
 /*
  * We rely on the fact that only requests allocated through blk_alloc_request()
  * have io scheduler private data structures associated with them. Any other
  * type of request (allocated on stack or through kmalloc()) should not go
  * to the io scheduler core, but be attached to the queue head instead.
  */
-void blk_wait_queue_drained(request_queue_t *q)
+void blk_wait_queue_drained(request_queue_t *q, int wait_dispatch)
 {
 	struct request_list *rl = &q->rq;
 	DEFINE_WAIT(wait);
@@ -2502,10 +2526,10 @@
 	spin_lock_irq(q->queue_lock);
 	set_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
 
-	while (rl->count[READ] || rl->count[WRITE]) {
+	while (wait_drain(q, rl, wait_dispatch)) {
 		prepare_to_wait(&rl->drain, &wait, TASK_UNINTERRUPTIBLE);
 
-		if (rl->count[READ] || rl->count[WRITE]) {
+		if (wait_drain(q, rl, wait_dispatch)) {
 			__generic_unplug_device(q);
 			spin_unlock_irq(q->queue_lock);
 			io_schedule();
@@ -2685,22 +2709,36 @@
 {
 	struct bio *bio, *prevbio = NULL;
 	int nr_phys_segs, nr_hw_segs;
+	unsigned int phys_size, hw_size;
+	request_queue_t *q = rq->q;
 
 	if (!rq->bio)
 		return;
 
-	nr_phys_segs = nr_hw_segs = 0;
+	phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0;
 	rq_for_each_bio(bio, rq) {
 		/* Force bio hw/phys segs to be recalculated. */
 		bio->bi_flags &= ~(1 << BIO_SEG_VALID);
 
-		nr_phys_segs += bio_phys_segments(rq->q, bio);
-		nr_hw_segs += bio_hw_segments(rq->q, bio);
+		nr_phys_segs += bio_phys_segments(q, bio);
+		nr_hw_segs += bio_hw_segments(q, bio);
 		if (prevbio) {
-			if (blk_phys_contig_segment(rq->q, prevbio, bio))
+			int pseg = phys_size + prevbio->bi_size + bio->bi_size;
+			int hseg = hw_size + prevbio->bi_size + bio->bi_size;
+
+			if (blk_phys_contig_segment(q, prevbio, bio) &&
+			    pseg <= q->max_segment_size) {
 				nr_phys_segs--;
-			if (blk_hw_contig_segment(rq->q, prevbio, bio))
+				phys_size += prevbio->bi_size + bio->bi_size;
+			} else
+				phys_size = 0;
+
+			if (blk_hw_contig_segment(q, prevbio, bio) &&
+			    hseg <= q->max_segment_size) {
 				nr_hw_segs--;
+				hw_size += prevbio->bi_size + bio->bi_size;
+			} else
+				hw_size = 0;
 		}
 		prevbio = bio;
 	}
diff -Nru a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
--- a/drivers/block/paride/paride.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/block/paride/paride.c	2004-10-28 22:25:57 -07:00
@@ -140,7 +140,7 @@
 #endif
 }
 
-void pi_unclaim(PIA * pi)
+static void pi_unclaim(PIA * pi)
 {
 	pi->claimed = 0;
 #ifdef CONFIG_PARPORT
@@ -148,8 +148,6 @@
 		parport_release((struct pardevice *) (pi->pardev));
 #endif
 }
-
-EXPORT_SYMBOL(pi_unclaim);
 
 void pi_connect(PIA * pi)
 {
diff -Nru a/drivers/block/paride/paride.h b/drivers/block/paride/paride.h
--- a/drivers/block/paride/paride.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/block/paride/paride.h	2004-10-28 22:25:57 -07:00
@@ -88,8 +88,6 @@
 
 extern void pi_read_block(PIA *pi, char * buf, int count);
 
-extern void pi_unclaim(PIA *pi);
-
 extern void pi_connect(PIA *pi);
 
 extern void pi_disconnect(PIA *pi);
diff -Nru a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
--- a/drivers/block/pktcdvd.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/block/pktcdvd.c	2004-10-28 22:25:56 -07:00
@@ -621,7 +621,7 @@
 
 		BUG_ON(len < 0);
 		memcpy(vto, vfrom, len);
-		kunmap_atomic(src_bvl->bv_page, KM_USER0);
+		kunmap_atomic(vfrom, KM_USER0);
 
 		seg++;
 		offs = 0;
@@ -649,7 +649,7 @@
 			void *vfrom = kmap_atomic(pages[f], KM_USER0) + offsets[f];
 			void *vto = page_address(pkt->pages[p]) + offs;
 			memcpy(vto, vfrom, CD_FRAMESIZE);
-			kunmap_atomic(pages[f], KM_USER0);
+			kunmap_atomic(vfrom, KM_USER0);
 			pages[f] = pkt->pages[p];
 			offsets[f] = offs;
 		} else {
diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
--- a/drivers/bluetooth/hci_usb.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/bluetooth/hci_usb.c	2004-10-28 22:25:59 -07:00
@@ -106,8 +106,9 @@
 	/* ISSC Bluetooth Adapter v3.1 */
 	{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
 
-	/* Digianswer device */
+	/* Digianswer devices */
 	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
+	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE },
 
 	/* RTX Telecom based adapter with buggy SCO support */
 	{ USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC },
@@ -795,6 +796,11 @@
 	kfree(husb);
 }
 
+static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt)
+{
+	BT_DBG("%s evt %d", hdev->name, evt);
+}
+
 int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
@@ -861,9 +867,9 @@
 	husb->intr_in_ep  = intr_in_ep;
 
 	if (id->driver_info & HCI_DIGIANSWER)
-		husb->ctrl_req = HCI_DIGI_REQ;
+		husb->ctrl_req = USB_TYPE_VENDOR;
 	else
-		husb->ctrl_req = HCI_CTRL_REQ;
+		husb->ctrl_req = USB_TYPE_CLASS;
 
 	/* Find isochronous endpoints that we can use */
 	size = 0; 
@@ -911,7 +917,9 @@
 				BT_ERR("Can't claim isoc interface");
 			else if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) {
 				BT_ERR("Can't set isoc interface settings");
+				husb->isoc_iface = isoc_iface;
 				usb_driver_release_interface(&hci_usb_driver, isoc_iface);
+				husb->isoc_iface = NULL;
 			} else {
 				husb->isoc_iface  = isoc_iface;
 				husb->isoc_in_ep  = isoc_in_ep;
@@ -947,6 +955,7 @@
 	hdev->flush    = hci_usb_flush;
 	hdev->send     = hci_usb_send_frame;
 	hdev->destruct = hci_usb_destruct;
+	hdev->notify   = hci_usb_notify;
 
 	hdev->owner = THIS_MODULE;
 
diff -Nru a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
--- a/drivers/bluetooth/hci_usb.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/bluetooth/hci_usb.h	2004-10-28 22:25:59 -07:00
@@ -28,9 +28,6 @@
 #define HCI_DEV_SUBCLASS	0x01	/* RF subclass */
 #define HCI_DEV_PROTOCOL	0x01	/* Bluetooth programming protocol */
 
-#define HCI_CTRL_REQ		0x20
-#define HCI_DIGI_REQ		0x40
-
 #define HCI_IGNORE		0x01
 #define HCI_RESET		0x02
 #define HCI_DIGIANSWER		0x04
diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
--- a/drivers/cdrom/cdrom.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/cdrom/cdrom.c	2004-10-28 22:25:57 -07:00
@@ -296,12 +296,12 @@
 static int check_media_type;
 /* automatically restart mrw format */
 static int mrw_format_restart = 1;
-MODULE_PARM(debug, "i");
-MODULE_PARM(autoclose, "i");
-MODULE_PARM(autoeject, "i");
-MODULE_PARM(lockdoor, "i");
-MODULE_PARM(check_media_type, "i");
-MODULE_PARM(mrw_format_restart, "i");
+module_param(debug, bool, 0);
+module_param(autoclose, bool, 0);
+module_param(autoeject, bool, 0);
+module_param(lockdoor, bool, 0);
+module_param(check_media_type, bool, 0);
+module_param(mrw_format_restart, bool, 0);
 
 static spinlock_t cdrom_lock = SPIN_LOCK_UNLOCKED;
 
@@ -546,6 +546,8 @@
 		return ret;
 
 	mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
+	if (be16_to_cpu(mfd->feature_code) != CDF_MRW)
+		return 1;
 	*write = mfd->write;
 
 	if ((ret = cdrom_mrw_probe_pc(cdi))) {
@@ -868,13 +870,11 @@
 	cgc.cmd[8] = sizeof(buffer);		/* Allocation Length */
 	cgc.quiet = 1;
 
-	if ((ret = cdi->ops->generic_packet(cdi, &cgc))) {
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
 		mmc3_profile = 0xffff;
-	} else {
+	else
 		mmc3_profile = (buffer[6] << 8) | buffer[7];
-		printk(KERN_INFO "cdrom: %s: mmc-3 profile capable, current profile: %Xh\n",
-		       cdi->name, mmc3_profile);
-	}
+
 	cdi->mmc3_profile = mmc3_profile;
 }
 
diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
--- a/drivers/char/Kconfig	2004-10-28 22:25:56 -07:00
+++ b/drivers/char/Kconfig	2004-10-28 22:25:56 -07:00
@@ -835,7 +835,7 @@
 
 config SONYPI
 	tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && X86 && PCI && !64BIT
+	depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT
 	---help---
 	  This driver enables access to the Sony Programmable I/O Control
 	  Device which can be found in many (all ?) Sony Vaio laptops.
diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c
--- a/drivers/char/cyclades.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/char/cyclades.c	2004-10-28 22:25:57 -07:00
@@ -5551,7 +5551,7 @@
     }
     for (j = 1; j <= ints[0]; j++){
         if ( i < NR_ISA_ADDRS ){
-            cy_isa_addresses[i++] = (unsigned char *)(ints[j]);
+            cy_isa_addresses[i++] = ints[j];
         }
     }
 #endif /* CONFIG_ISA */
diff -Nru a/drivers/char/hvsi.c b/drivers/char/hvsi.c
--- a/drivers/char/hvsi.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/char/hvsi.c	2004-10-28 22:25:58 -07:00
@@ -29,11 +29,6 @@
  * the OS cannot change the speed of the port through this protocol.
  */
 
-/* TODO:
- * test FSP reset
- * add udbg support for xmon/kdb
- */
-
 #undef DEBUG
 
 #include <linux/console.h>
@@ -54,6 +49,7 @@
 #include <asm/prom.h>
 #include <asm/uaccess.h>
 #include <asm/vio.h>
+#include <asm/param.h>
 
 #define HVSI_MAJOR	229
 #define HVSI_MINOR	128
@@ -74,6 +70,7 @@
 
 struct hvsi_struct {
 	struct work_struct writer;
+	struct work_struct handshaker;
 	wait_queue_head_t emptyq; /* woken when outbuf is emptied */
 	wait_queue_head_t stateq; /* woken when HVSI state changes */
 	spinlock_t lock;
@@ -109,6 +106,7 @@
 	HVSI_WAIT_FOR_VER_QUERY,
 	HVSI_OPEN,
 	HVSI_WAIT_FOR_MCTRL_RESPONSE,
+	HVSI_FSP_DIED,
 };
 #define HVSI_CONSOLE 0x1
 
@@ -172,6 +170,13 @@
 	} u;
 } __attribute__((packed));
 
+
+
+static inline int is_console(struct hvsi_struct *hp)
+{
+	return hp->flags & HVSI_CONSOLE;
+}
+
 static inline int is_open(struct hvsi_struct *hp)
 {
 	/* if we're waiting for an mctrl then we're already open */
@@ -188,6 +193,7 @@
 		"HVSI_WAIT_FOR_VER_QUERY",
 		"HVSI_OPEN",
 		"HVSI_WAIT_FOR_MCTRL_RESPONSE",
+		"HVSI_FSP_DIED",
 	};
 	const char *name = state_names[hp->state];
 
@@ -296,14 +302,9 @@
 	return 0;
 }
 
-/*
- * we can't call tty_hangup() directly here because we need to call that
- * outside of our lock
- */
-static struct tty_struct *hvsi_recv_control(struct hvsi_struct *hp,
-		uint8_t *packet)
+static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
+	struct tty_struct **to_hangup, struct hvsi_struct **to_handshake)
 {
-	struct tty_struct *to_hangup = NULL;
 	struct hvsi_control *header = (struct hvsi_control *)packet;
 
 	switch (header->verb) {
@@ -313,15 +314,14 @@
 				pr_debug("hvsi%i: CD dropped\n", hp->index);
 				hp->mctrl &= TIOCM_CD;
 				if (!(hp->tty->flags & CLOCAL))
-					to_hangup = hp->tty;
+					*to_hangup = hp->tty;
 			}
 			break;
 		case VSV_CLOSE_PROTOCOL:
-			printk(KERN_DEBUG
-				"hvsi%i: service processor closed connection!\n", hp->index);
-			__set_state(hp, HVSI_CLOSED);
-			to_hangup = hp->tty;
-			hp->tty = NULL;
+			pr_debug("hvsi%i: service processor came back\n", hp->index);
+			if (hp->state != HVSI_CLOSED) {
+				*to_handshake = hp;
+			}
 			break;
 		default:
 			printk(KERN_WARNING "hvsi%i: unknown HVSI control packet: ",
@@ -329,8 +329,6 @@
 			dump_packet(packet);
 			break;
 	}
-
-	return to_hangup;
 }
 
 static void hvsi_recv_response(struct hvsi_struct *hp, uint8_t *packet)
@@ -388,8 +386,8 @@
 
 	switch (hp->state) {
 		case HVSI_WAIT_FOR_VER_QUERY:
-			__set_state(hp, HVSI_OPEN);
 			hvsi_version_respond(hp, query->seqno);
+			__set_state(hp, HVSI_OPEN);
 			break;
 		default:
 			printk(KERN_ERR "hvsi%i: unexpected query: ", hp->index);
@@ -467,17 +465,20 @@
  * incoming data).
  */
 static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
-		struct tty_struct **hangup)
+		struct tty_struct **hangup, struct hvsi_struct **handshake)
 {
 	uint8_t *packet = hp->inbuf;
 	int chunklen;
 
 	*flip = NULL;
 	*hangup = NULL;
+	*handshake = NULL;
 
 	chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
-	if (chunklen == 0)
+	if (chunklen == 0) {
+		pr_debug("%s: 0-length read\n", __FUNCTION__);
 		return 0;
+	}
 
 	pr_debug("%s: got %i bytes\n", __FUNCTION__, chunklen);
 	dbg_dump_hex(hp->inbuf_end, chunklen);
@@ -509,7 +510,7 @@
 				*flip = hvsi_recv_data(hp, packet);
 				break;
 			case VS_CONTROL_PACKET_HEADER:
-				*hangup = hvsi_recv_control(hp, packet);
+				hvsi_recv_control(hp, packet, hangup, handshake);
 				break;
 			case VS_QUERY_RESPONSE_PACKET_HEADER:
 				hvsi_recv_response(hp, packet);
@@ -526,8 +527,8 @@
 
 		packet += len_packet(packet);
 
-		if (*hangup) {
-			pr_debug("%s: hangup\n", __FUNCTION__);
+		if (*hangup || *handshake) {
+			pr_debug("%s: hangup or handshake\n", __FUNCTION__);
 			/*
 			 * we need to send the hangup now before receiving any more data.
 			 * If we get "data, hangup, data", we can't deliver the second
@@ -560,16 +561,15 @@
 	struct hvsi_struct *hp = (struct hvsi_struct *)arg;
 	struct tty_struct *flip;
 	struct tty_struct *hangup;
+	struct hvsi_struct *handshake;
 	unsigned long flags;
-	irqreturn_t handled = IRQ_NONE;
 	int again = 1;
 
 	pr_debug("%s\n", __FUNCTION__);
 
 	while (again) {
 		spin_lock_irqsave(&hp->lock, flags);
-		again = hvsi_load_chunk(hp, &flip, &hangup);
-		handled = IRQ_HANDLED;
+		again = hvsi_load_chunk(hp, &flip, &hangup, &handshake);
 		spin_unlock_irqrestore(&hp->lock, flags);
 
 		/*
@@ -587,6 +587,11 @@
 		if (hangup) {
 			tty_hangup(hangup);
 		}
+
+		if (handshake) {
+			pr_debug("hvsi%i: attempting re-handshake\n", handshake->index);
+			schedule_work(&handshake->handshaker);
+		}
 	}
 
 	spin_lock_irqsave(&hp->lock, flags);
@@ -603,7 +608,7 @@
 		tty_flip_buffer_push(flip);
 	}
 
-	return handled;
+	return IRQ_HANDLED;
 }
 
 /* for boot console, before the irq handler is running */
@@ -757,6 +762,23 @@
 	return 0;
 }
 
+static void hvsi_handshaker(void *arg)
+{
+	struct hvsi_struct *hp = (struct hvsi_struct *)arg;
+
+	if (hvsi_handshake(hp) >= 0)
+		return;
+
+	printk(KERN_ERR "hvsi%i: re-handshaking failed\n", hp->index);
+	if (is_console(hp)) {
+		/*
+		 * ttys will re-attempt the handshake via hvsi_open, but
+		 * the console will not.
+		 */
+		printk(KERN_ERR "hvsi%i: lost console!\n", hp->index);
+	}
+}
+
 static int hvsi_put_chars(struct hvsi_struct *hp, const char *buf, int count)
 {
 	struct hvsi_data packet __ALIGNED__;
@@ -808,6 +830,10 @@
 	tty->driver_data = hp;
 	tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */
 
+	mb();
+	if (hp->state == HVSI_FSP_DIED)
+		return -EIO;
+
 	spin_lock_irqsave(&hp->lock, flags);
 	hp->tty = tty;
 	hp->count++;
@@ -815,7 +841,7 @@
 	h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
 	spin_unlock_irqrestore(&hp->lock, flags);
 
-	if (hp->flags & HVSI_CONSOLE)
+	if (is_console(hp))
 		return 0; /* this has already been handshaked as the console */
 
 	ret = hvsi_handshake(hp);
@@ -889,7 +915,7 @@
 		hp->inbuf_end = hp->inbuf; /* discard remaining partial packets */
 
 		/* only close down connection if it is not the console */
-		if (!(hp->flags & HVSI_CONSOLE)) {
+		if (!is_console(hp)) {
 			h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE); /* no more irqs */
 			__set_state(hp, HVSI_CLOSED);
 			/*
@@ -927,11 +953,17 @@
 static void hvsi_hangup(struct tty_struct *tty)
 {
 	struct hvsi_struct *hp = tty->driver_data;
+	unsigned long flags;
 
 	pr_debug("%s\n", __FUNCTION__);
 
+	spin_lock_irqsave(&hp->lock, flags);
+
 	hp->count = 0;
+	hp->n_outbuf = 0;
 	hp->tty = NULL;
+
+	spin_unlock_irqrestore(&hp->lock, flags);
 }
 
 /* called with hp->lock held */
@@ -943,12 +975,13 @@
 		return;
 
 	n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf);
-	if (n != 0) {
-		/*
-		 * either all data was sent or there was an error, and we throw away
-		 * data on error.
-		 */
+	if (n > 0) {
+		/* success */
+		pr_debug("%s: wrote %i chars\n", __FUNCTION__, n);
 		hp->n_outbuf = 0;
+	} else if (n == -EIO) {
+		__set_state(hp, HVSI_FSP_DIED);
+		printk(KERN_ERR "hvsi%i: service processor died\n", hp->index);
 	}
 }
 
@@ -966,6 +999,19 @@
 
 	spin_lock_irqsave(&hp->lock, flags);
 
+	pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf);
+
+	if (!is_open(hp)) {
+		/*
+		 * We could have a non-open connection if the service processor died
+		 * while we were busily scheduling ourselves. In that case, it could
+		 * be minutes before the service processor comes back, so only try
+		 * again once a second.
+		 */
+		schedule_delayed_work(&hp->writer, HZ);
+		goto out;
+	}
+
 	hvsi_push(hp);
 	if (hp->n_outbuf > 0)
 		schedule_delayed_work(&hp->writer, 10);
@@ -982,6 +1028,7 @@
 		wake_up_interruptible(&hp->tty->write_wait);
 	}
 
+out:
 	spin_unlock_irqrestore(&hp->lock, flags);
 }
 
@@ -1010,6 +1057,8 @@
 
 	spin_lock_irqsave(&hp->lock, flags);
 
+	pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf);
+
 	if (!is_open(hp)) {
 		/* we're either closing or not yet open; don't accept data */
 		pr_debug("%s: not open\n", __FUNCTION__);
@@ -1279,6 +1328,7 @@
 
 		hp = &hvsi_ports[hvsi_count];
 		INIT_WORK(&hp->writer, hvsi_write_worker, hp);
+		INIT_WORK(&hp->handshaker, hvsi_handshaker, hp);
 		init_waitqueue_head(&hp->emptyq);
 		init_waitqueue_head(&hp->stateq);
 		hp->lock = SPIN_LOCK_UNLOCKED;
diff -Nru a/drivers/char/hw_random.c b/drivers/char/hw_random.c
--- a/drivers/char/hw_random.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/char/hw_random.c	2004-10-28 22:25:57 -07:00
@@ -581,7 +581,7 @@
 	DPRINTK ("ENTER\n");
 
 	/* Probe for Intel, AMD RNGs */
-	while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
+	for_each_pci_dev(pdev) {
 		ent = pci_match_device (rng_pci_tbl, pdev);
 		if (ent) {
 			rng_ops = &rng_vendor_ops[ent->driver_data];
diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c
--- a/drivers/char/lp.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/char/lp.c	2004-10-28 22:25:56 -07:00
@@ -749,8 +749,8 @@
 static char *parport[LP_NO] = { NULL,  };
 static int reset = 0;
 
-MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "s");
-MODULE_PARM(reset, "i");
+module_param_array(parport, charp, NULL, 0);
+module_param(reset, bool, 0);
 
 #ifndef MODULE
 static int __init lp_setup (char *str)
diff -Nru a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
--- a/drivers/char/mmtimer.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/char/mmtimer.c	2004-10-28 22:25:58 -07:00
@@ -103,13 +103,13 @@
 		break;
 
 	case MMTIMER_GETRES: /* resolution of the clock in 10^-15 s */
-		if(copy_to_user((unsigned long *)arg, &mmtimer_femtoperiod,
-				sizeof(unsigned long)))
+		if(copy_to_user((unsigned long __user *)arg,
+				&mmtimer_femtoperiod, sizeof(unsigned long)))
 			return -EFAULT;
 		break;
 
 	case MMTIMER_GETFREQ: /* frequency in Hz */
-		if(copy_to_user((unsigned long *)arg,
+		if(copy_to_user((unsigned long __user *)arg,
 				&sn_rtc_cycles_per_second,
 				sizeof(unsigned long)))
 			return -EFAULT;
@@ -125,8 +125,8 @@
 		break;
 
 	case MMTIMER_GETCOUNTER:
-		if(copy_to_user((unsigned long *)arg, RTC_COUNTER_ADDR,
-				sizeof(unsigned long)))
+		if(copy_to_user((unsigned long __user *)arg,
+				RTC_COUNTER_ADDR, sizeof(unsigned long)))
 			return -EFAULT;
 		break;
 	default:
diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
--- a/drivers/char/pcmcia/synclink_cs.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/char/pcmcia/synclink_cs.c	2004-10-28 22:25:57 -07:00
@@ -4557,9 +4557,7 @@
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->dev      = info->netdev;
-	skb->mac.raw  = skb->data;
-	skb->protocol = hdlc_type_trans(skb, skb->dev);
+	skb->protocol = hdlc_type_trans(skb, info->netdev);
 
 	stats->rx_packets++;
 	stats->rx_bytes += size;
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/char/random.c	2004-10-28 22:25:56 -07:00
@@ -818,12 +818,10 @@
 	 * jiffies.
 	 */
 	time = get_cycles();
-	if (time != 0) {
-		if (sizeof(time) > 4)
-			num ^= (u32)(time >> 32);
-	} else {
+	if (time)
+		num ^= (u32)((time >> 31) >> 1);
+	else
 		time = jiffies;
-	}
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
diff -Nru a/drivers/char/selection.c b/drivers/char/selection.c
--- a/drivers/char/selection.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/char/selection.c	2004-10-28 22:25:59 -07:00
@@ -304,6 +304,3 @@
 	tty_ldisc_deref(ld);
 	return 0;
 }
-
-EXPORT_SYMBOL(set_selection);
-EXPORT_SYMBOL(paste_selection);
diff -Nru a/drivers/char/sonypi.c b/drivers/char/sonypi.c
--- a/drivers/char/sonypi.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/char/sonypi.c	2004-10-28 22:25:58 -07:00
@@ -1,7 +1,7 @@
 /*
  * Sony Programmable I/O Control Device driver for VAIO
  *
- * Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
+ * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
  *
  * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
  *
@@ -19,12 +19,12 @@
  * 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.
@@ -44,84 +44,89 @@
 #include <linux/wait.h>
 #include <linux/acpi.h>
 #include <linux/dmi.h>
-#include <linux/sysdev.h>
+#include <linux/err.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
-static int verbose; /* = 0 */
-
 #include "sonypi.h"
 #include <linux/sonypi.h>
 
-static struct sonypi_device sonypi_device;
+MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
+MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SONYPI_DRIVER_VERSION);
+
 static int minor = -1;
-static int fnkeyinit; /* = 0 */
-static int camera; /* = 0 */
-static int compat; /* = 0 */
-static int useinput = 1;
+module_param(minor, int, 0);
+MODULE_PARM_DESC(minor,
+		 "minor number of the misc device, default is -1 (automatic)");
+
+static int verbose;		/* = 0 */
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
+
+static int fnkeyinit;		/* = 0 */
+module_param(fnkeyinit, int, 0444);
+MODULE_PARM_DESC(fnkeyinit,
+		 "set this if your Fn keys do not generate any event");
+
+static int camera;		/* = 0 */
+module_param(camera, int, 0444);
+MODULE_PARM_DESC(camera,
+		 "set this if you have a MotionEye camera (PictureBook series)");
+
+static int compat;		/* = 0 */
+module_param(compat, int, 0444);
+MODULE_PARM_DESC(compat,
+		 "set this if you want to enable backward compatibility mode");
+
 static unsigned long mask = 0xffffffff;
+module_param(mask, ulong, 0644);
+MODULE_PARM_DESC(mask,
+		 "set this to the mask of event you want to enable (see doc)");
 
-/* Inits the queue */
-static inline void sonypi_initq(void) {
-        sonypi_device.queue.head = sonypi_device.queue.tail = 0;
-	sonypi_device.queue.len = 0;
-	sonypi_device.queue.s_lock = SPIN_LOCK_UNLOCKED;
-	init_waitqueue_head(&sonypi_device.queue.proc_list);
-}
-
-/* Pulls an event from the queue */
-static inline unsigned char sonypi_pullq(void) {
-        unsigned char result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
-	if (!sonypi_device.queue.len) {
-		spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
-		return 0;
-	}
-	result = sonypi_device.queue.buf[sonypi_device.queue.head];
-        sonypi_device.queue.head++;
-	sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
-	sonypi_device.queue.len--;
-	spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
-        return result;
-}
-
-/* Pushes an event into the queue */
-static inline void sonypi_pushq(unsigned char event) {
-	unsigned long flags;
-
-	spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
-	if (sonypi_device.queue.len == SONYPI_BUF_SIZE) {
-		/* remove the first element */
-        	sonypi_device.queue.head++;
-		sonypi_device.queue.head &= (SONYPI_BUF_SIZE - 1);
-		sonypi_device.queue.len--;
-	}
-	sonypi_device.queue.buf[sonypi_device.queue.tail] = event;
-	sonypi_device.queue.tail++;
-	sonypi_device.queue.tail &= (SONYPI_BUF_SIZE - 1);
-	sonypi_device.queue.len++;
-
-	kill_fasync(&sonypi_device.queue.fasync, SIGIO, POLL_IN);
-	wake_up_interruptible(&sonypi_device.queue.proc_list);
-	spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
-}
-
-/* Tests if the queue is empty */
-static inline int sonypi_emptyq(void) {
-        int result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&sonypi_device.queue.s_lock, flags);
-        result = (sonypi_device.queue.len == 0);
-	spin_unlock_irqrestore(&sonypi_device.queue.s_lock, flags);
-        return result;
+static int useinput = 1;
+module_param(useinput, int, 0444);
+MODULE_PARM_DESC(useinput,
+		 "set this if you would like sonypi to feed events to the input subsystem");
+
+static struct sonypi_device sonypi_device;
+
+static int sonypi_ec_write(u8 addr, u8 value)
+{
+#ifdef CONFIG_ACPI_EC
+	if (SONYPI_ACPI_ACTIVE)
+		return ec_write(addr, value);
+#endif
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
+	outb_p(0x81, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+	outb_p(value, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+	return 0;
 }
 
-static int ec_read16(u8 addr, u16 *value) {
+static int sonypi_ec_read(u8 addr, u8 *value)
+{
+#ifdef CONFIG_ACPI_EC
+	if (SONYPI_ACPI_ACTIVE)
+		return ec_read(addr, value);
+#endif
+	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
+	outb_p(0x80, SONYPI_CST_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+	outb_p(addr, SONYPI_DATA_IOPORT);
+	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
+	*value = inb_p(SONYPI_DATA_IOPORT);
+	return 0;
+}
+
+static int ec_read16(u8 addr, u16 *value)
+{
 	u8 val_lb, val_hb;
 	if (sonypi_ec_read(addr, &val_lb))
 		return -1;
@@ -132,21 +137,22 @@
 }
 
 /* Initializes the device - this comes from the AML code in the ACPI bios */
-static void sonypi_type1_srs(void) {
+static void sonypi_type1_srs(void)
+{
 	u32 v;
 
 	pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
-	v = (v & 0xFFFF0000) | ((u32)sonypi_device.ioport1);
+	v = (v & 0xFFFF0000) | ((u32) sonypi_device.ioport1);
 	pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
 
 	pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
-	v = (v & 0xFFF0FFFF) | 
-	    (((u32)sonypi_device.ioport1 ^ sonypi_device.ioport2) << 16);
+	v = (v & 0xFFF0FFFF) |
+	    (((u32) sonypi_device.ioport1 ^ sonypi_device.ioport2) << 16);
 	pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
 
 	v = inl(SONYPI_IRQ_PORT);
-	v &= ~(((u32)0x3) << SONYPI_IRQ_SHIFT);
-	v |= (((u32)sonypi_device.bits) << SONYPI_IRQ_SHIFT);
+	v &= ~(((u32) 0x3) << SONYPI_IRQ_SHIFT);
+	v |= (((u32) sonypi_device.bits) << SONYPI_IRQ_SHIFT);
 	outl(v, SONYPI_IRQ_PORT);
 
 	pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
@@ -154,18 +160,20 @@
 	pci_write_config_dword(sonypi_device.dev, SONYPI_G10A, v);
 }
 
-static void sonypi_type2_srs(void) {
+static void sonypi_type2_srs(void)
+{
 	if (sonypi_ec_write(SONYPI_SHIB, (sonypi_device.ioport1 & 0xFF00) >> 8))
 		printk(KERN_WARNING "ec_write failed\n");
-	if (sonypi_ec_write(SONYPI_SLOB,  sonypi_device.ioport1 & 0x00FF))
+	if (sonypi_ec_write(SONYPI_SLOB, sonypi_device.ioport1 & 0x00FF))
 		printk(KERN_WARNING "ec_write failed\n");
-	if (sonypi_ec_write(SONYPI_SIRQ,  sonypi_device.bits))
+	if (sonypi_ec_write(SONYPI_SIRQ, sonypi_device.bits))
 		printk(KERN_WARNING "ec_write failed\n");
 	udelay(10);
 }
 
 /* Disables the device - this comes from the AML code in the ACPI bios */
-static void sonypi_type1_dis(void) {
+static void sonypi_type1_dis(void)
+{
 	u32 v;
 
 	pci_read_config_dword(sonypi_device.dev, SONYPI_G10A, &v);
@@ -177,7 +185,8 @@
 	outl(v, SONYPI_IRQ_PORT);
 }
 
-static void sonypi_type2_dis(void) {
+static void sonypi_type2_dis(void)
+{
 	if (sonypi_ec_write(SONYPI_SHIB, 0))
 		printk(KERN_WARNING "ec_write failed\n");
 	if (sonypi_ec_write(SONYPI_SLOB, 0))
@@ -186,7 +195,8 @@
 		printk(KERN_WARNING "ec_write failed\n");
 }
 
-static u8 sonypi_call1(u8 dev) {
+static u8 sonypi_call1(u8 dev)
+{
 	u8 v1, v2;
 
 	wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
@@ -196,7 +206,8 @@
 	return v2;
 }
 
-static u8 sonypi_call2(u8 dev, u8 fn) {
+static u8 sonypi_call2(u8 dev, u8 fn)
+{
 	u8 v1;
 
 	wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
@@ -207,7 +218,8 @@
 	return v1;
 }
 
-static u8 sonypi_call3(u8 dev, u8 fn, u8 v) {
+static u8 sonypi_call3(u8 dev, u8 fn, u8 v)
+{
 	u8 v1;
 
 	wait_on_command(0, inb_p(sonypi_device.ioport2) & 2, ITERATIONS_LONG);
@@ -220,7 +232,8 @@
 	return v1;
 }
 
-static u8 sonypi_read(u8 fn) {
+static u8 sonypi_read(u8 fn)
+{
 	u8 v1, v2;
 	int n = 100;
 
@@ -234,13 +247,14 @@
 }
 
 /* Set brightness, hue etc */
-static void sonypi_set(u8 fn, u8 v) {
-	
+static void sonypi_set(u8 fn, u8 v)
+{
 	wait_on_command(0, sonypi_call3(0x90, fn, v), ITERATIONS_SHORT);
 }
 
 /* Tests if the camera is ready */
-static int sonypi_camera_ready(void) {
+static int sonypi_camera_ready(void)
+{
 	u8 v;
 
 	v = sonypi_call2(0x8f, SONYPI_CAMERA_STATUS);
@@ -248,19 +262,20 @@
 }
 
 /* Turns the camera off */
-static void sonypi_camera_off(void) {
-
+static void sonypi_camera_off(void)
+{
 	sonypi_set(SONYPI_CAMERA_PICTURE, SONYPI_CAMERA_MUTE_MASK);
 
 	if (!sonypi_device.camera_power)
 		return;
 
-	sonypi_call2(0x91, 0); 
+	sonypi_call2(0x91, 0);
 	sonypi_device.camera_power = 0;
 }
 
 /* Turns the camera on */
-static void sonypi_camera_on(void) {
+static void sonypi_camera_on(void)
+{
 	int i, j;
 
 	if (sonypi_device.camera_power)
@@ -283,7 +298,7 @@
 		if (i)
 			break;
 	}
-	
+
 	if (j == 0) {
 		printk(KERN_WARNING "sonypi: failed to power on camera\n");
 		return;
@@ -294,19 +309,42 @@
 }
 
 /* sets the bluetooth subsystem power state */
-static void sonypi_setbluetoothpower(u8 state) {
-
+static void sonypi_setbluetoothpower(u8 state)
+{
 	state = !!state;
-	if (sonypi_device.bluetooth_power == state) 
+
+	if (sonypi_device.bluetooth_power == state)
 		return;
-	
+
 	sonypi_call2(0x96, state);
 	sonypi_call1(0x82);
 	sonypi_device.bluetooth_power = state;
 }
 
+static void input_keyrelease(void *data)
+{
+	struct input_dev *input_dev;
+	int key;
+
+	while (1) {
+		if (kfifo_get(sonypi_device.input_fifo,
+			      (unsigned char *)&input_dev,
+			      sizeof(input_dev)) != sizeof(input_dev))
+			return;
+		if (kfifo_get(sonypi_device.input_fifo,
+			      (unsigned char *)&key,
+			      sizeof(key)) != sizeof(key))
+			return;
+
+		msleep(10);
+		input_report_key(input_dev, key, 0);
+		input_sync(input_dev);
+	}
+}
+
 /* Interrupt handler: some event is available */
-static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs) {
+static irqreturn_t sonypi_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
 	u8 v1, v2, event = 0;
 	int i, j;
 
@@ -316,9 +354,10 @@
 	for (i = 0; sonypi_eventtypes[i].model; i++) {
 		if (sonypi_device.model != sonypi_eventtypes[i].model)
 			continue;
-		if ((v2 & sonypi_eventtypes[i].data) != sonypi_eventtypes[i].data)
+		if ((v2 & sonypi_eventtypes[i].data) !=
+		    sonypi_eventtypes[i].data)
 			continue;
-		if (! (mask & sonypi_eventtypes[i].mask))
+		if (!(mask & sonypi_eventtypes[i].mask))
 			continue;
 		for (j = 0; sonypi_eventtypes[i].events[j].event; j++) {
 			if (v1 == sonypi_eventtypes[i].events[j].data) {
@@ -329,40 +368,75 @@
 	}
 
 	if (verbose)
-		printk(KERN_WARNING 
-		       "sonypi: unknown event port1=0x%02x,port2=0x%02x\n",v1,v2);
+		printk(KERN_WARNING
+		       "sonypi: unknown event port1=0x%02x,port2=0x%02x\n",
+		       v1, v2);
 	/* We need to return IRQ_HANDLED here because there *are*
-	 * events belonging to the sonypi device we don't know about, 
+	 * events belonging to the sonypi device we don't know about,
 	 * but we still don't want those to pollute the logs... */
 	return IRQ_HANDLED;
 
 found:
 	if (verbose > 1)
-		printk(KERN_INFO 
+		printk(KERN_INFO
 		       "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2);
 
-#ifdef SONYPI_USE_INPUT
 	if (useinput) {
-		struct input_dev *jog_dev = &sonypi_device.jog_dev;
-		if (event == SONYPI_EVENT_JOGDIAL_PRESSED)
-			input_report_key(jog_dev, BTN_MIDDLE, 1);
-		else if (event == SONYPI_EVENT_ANYBUTTON_RELEASED)
-			input_report_key(jog_dev, BTN_MIDDLE, 0);
-		else if ((event == SONYPI_EVENT_JOGDIAL_UP) ||
-			 (event == SONYPI_EVENT_JOGDIAL_UP_PRESSED))
-			input_report_rel(jog_dev, REL_WHEEL, 1);
-		else if ((event == SONYPI_EVENT_JOGDIAL_DOWN) ||
-			 (event == SONYPI_EVENT_JOGDIAL_DOWN_PRESSED))
-			input_report_rel(jog_dev, REL_WHEEL, -1);
-		input_sync(jog_dev);
-	}
-#endif /* SONYPI_USE_INPUT */
-	sonypi_pushq(event);
+		struct input_dev *input_jog_dev = &sonypi_device.input_jog_dev;
+		struct input_dev *input_key_dev = &sonypi_device.input_key_dev;
+		switch (event) {
+		case SONYPI_EVENT_JOGDIAL_UP:
+		case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
+			input_report_rel(input_jog_dev, REL_WHEEL, 1);
+			break;
+		case SONYPI_EVENT_JOGDIAL_DOWN:
+		case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
+			input_report_rel(input_jog_dev, REL_WHEEL, -1);
+			break;
+		case SONYPI_EVENT_JOGDIAL_PRESSED: {
+			int key = BTN_MIDDLE;
+			input_report_key(input_jog_dev, key, 1);
+			kfifo_put(sonypi_device.input_fifo,
+				  (unsigned char *)&input_jog_dev,
+				  sizeof(input_jog_dev));
+			kfifo_put(sonypi_device.input_fifo,
+				  (unsigned char *)&key, sizeof(key));
+			break;
+		}
+		case SONYPI_EVENT_FNKEY_RELEASED:
+			/* Nothing, not all VAIOs generate this event */
+			break;
+		}
+		input_sync(input_jog_dev);
+
+		for (i = 0; sonypi_inputkeys[i].sonypiev; i++) {
+			int key;
+
+			if (event != sonypi_inputkeys[i].sonypiev)
+				continue;
+
+			key = sonypi_inputkeys[i].inputev;
+			input_report_key(input_key_dev, key, 1);
+			kfifo_put(sonypi_device.input_fifo,
+				  (unsigned char *)&input_key_dev,
+				  sizeof(input_key_dev));
+			kfifo_put(sonypi_device.input_fifo,
+				  (unsigned char *)&key, sizeof(key));
+		}
+		input_sync(input_key_dev);
+		schedule_work(&sonypi_device.input_work);
+	}
+
+	kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
+	kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
+	wake_up_interruptible(&sonypi_device.fifo_proc_list);
+
 	return IRQ_HANDLED;
 }
 
 /* External camera command (exported to the motion eye v4l driver) */
-u8 sonypi_camera_command(int command, u8 value) {
+u8 sonypi_camera_command(int command, u8 value)
+{
 	u8 ret = 0;
 
 	if (!camera)
@@ -370,83 +444,87 @@
 
 	down(&sonypi_device.lock);
 
-	switch(command) {
-		case SONYPI_COMMAND_GETCAMERA:
-			ret = sonypi_camera_ready();
-			break;
-		case SONYPI_COMMAND_SETCAMERA:
-			if (value)
-				sonypi_camera_on();
-			else
-				sonypi_camera_off();
-			break;
-		case SONYPI_COMMAND_GETCAMERABRIGHTNESS:
-			ret = sonypi_read(SONYPI_CAMERA_BRIGHTNESS);
-			break;
-		case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
-			sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
-			break;
-		case SONYPI_COMMAND_GETCAMERACONTRAST:
-			ret = sonypi_read(SONYPI_CAMERA_CONTRAST);
-			break;
-		case SONYPI_COMMAND_SETCAMERACONTRAST:
-			sonypi_set(SONYPI_CAMERA_CONTRAST, value);
-			break;
-		case SONYPI_COMMAND_GETCAMERAHUE:
-			ret = sonypi_read(SONYPI_CAMERA_HUE);
-			break;
-		case SONYPI_COMMAND_SETCAMERAHUE:
-			sonypi_set(SONYPI_CAMERA_HUE, value);
-			break;
-		case SONYPI_COMMAND_GETCAMERACOLOR:
-			ret = sonypi_read(SONYPI_CAMERA_COLOR);
-			break;
-		case SONYPI_COMMAND_SETCAMERACOLOR:
-			sonypi_set(SONYPI_CAMERA_COLOR, value);
-			break;
-		case SONYPI_COMMAND_GETCAMERASHARPNESS:
-			ret = sonypi_read(SONYPI_CAMERA_SHARPNESS);
-			break;
-		case SONYPI_COMMAND_SETCAMERASHARPNESS:
-			sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
-			break;
-		case SONYPI_COMMAND_GETCAMERAPICTURE:
-			ret = sonypi_read(SONYPI_CAMERA_PICTURE);
-			break;
-		case SONYPI_COMMAND_SETCAMERAPICTURE:
-			sonypi_set(SONYPI_CAMERA_PICTURE, value);
-			break;
-		case SONYPI_COMMAND_GETCAMERAAGC:
-			ret = sonypi_read(SONYPI_CAMERA_AGC);
-			break;
-		case SONYPI_COMMAND_SETCAMERAAGC:
-			sonypi_set(SONYPI_CAMERA_AGC, value);
-			break;
-		case SONYPI_COMMAND_GETCAMERADIRECTION:
-			ret = sonypi_read(SONYPI_CAMERA_STATUS);
-			ret &= SONYPI_DIRECTION_BACKWARDS;
-			break;
-		case SONYPI_COMMAND_GETCAMERAROMVERSION:
-			ret = sonypi_read(SONYPI_CAMERA_ROMVERSION);
-			break;
-		case SONYPI_COMMAND_GETCAMERAREVISION:
-			ret = sonypi_read(SONYPI_CAMERA_REVISION);
-			break;
+	switch (command) {
+	case SONYPI_COMMAND_GETCAMERA:
+		ret = sonypi_camera_ready();
+		break;
+	case SONYPI_COMMAND_SETCAMERA:
+		if (value)
+			sonypi_camera_on();
+		else
+			sonypi_camera_off();
+		break;
+	case SONYPI_COMMAND_GETCAMERABRIGHTNESS:
+		ret = sonypi_read(SONYPI_CAMERA_BRIGHTNESS);
+		break;
+	case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
+		sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
+		break;
+	case SONYPI_COMMAND_GETCAMERACONTRAST:
+		ret = sonypi_read(SONYPI_CAMERA_CONTRAST);
+		break;
+	case SONYPI_COMMAND_SETCAMERACONTRAST:
+		sonypi_set(SONYPI_CAMERA_CONTRAST, value);
+		break;
+	case SONYPI_COMMAND_GETCAMERAHUE:
+		ret = sonypi_read(SONYPI_CAMERA_HUE);
+		break;
+	case SONYPI_COMMAND_SETCAMERAHUE:
+		sonypi_set(SONYPI_CAMERA_HUE, value);
+		break;
+	case SONYPI_COMMAND_GETCAMERACOLOR:
+		ret = sonypi_read(SONYPI_CAMERA_COLOR);
+		break;
+	case SONYPI_COMMAND_SETCAMERACOLOR:
+		sonypi_set(SONYPI_CAMERA_COLOR, value);
+		break;
+	case SONYPI_COMMAND_GETCAMERASHARPNESS:
+		ret = sonypi_read(SONYPI_CAMERA_SHARPNESS);
+		break;
+	case SONYPI_COMMAND_SETCAMERASHARPNESS:
+		sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
+		break;
+	case SONYPI_COMMAND_GETCAMERAPICTURE:
+		ret = sonypi_read(SONYPI_CAMERA_PICTURE);
+		break;
+	case SONYPI_COMMAND_SETCAMERAPICTURE:
+		sonypi_set(SONYPI_CAMERA_PICTURE, value);
+		break;
+	case SONYPI_COMMAND_GETCAMERAAGC:
+		ret = sonypi_read(SONYPI_CAMERA_AGC);
+		break;
+	case SONYPI_COMMAND_SETCAMERAAGC:
+		sonypi_set(SONYPI_CAMERA_AGC, value);
+		break;
+	case SONYPI_COMMAND_GETCAMERADIRECTION:
+		ret = sonypi_read(SONYPI_CAMERA_STATUS);
+		ret &= SONYPI_DIRECTION_BACKWARDS;
+		break;
+	case SONYPI_COMMAND_GETCAMERAROMVERSION:
+		ret = sonypi_read(SONYPI_CAMERA_ROMVERSION);
+		break;
+	case SONYPI_COMMAND_GETCAMERAREVISION:
+		ret = sonypi_read(SONYPI_CAMERA_REVISION);
+		break;
 	}
 	up(&sonypi_device.lock);
 	return ret;
 }
 
-static int sonypi_misc_fasync(int fd, struct file *filp, int on) {
+EXPORT_SYMBOL(sonypi_camera_command);
+
+static int sonypi_misc_fasync(int fd, struct file *filp, int on)
+{
 	int retval;
 
-	retval = fasync_helper(fd, filp, on, &sonypi_device.queue.fasync);
+	retval = fasync_helper(fd, filp, on, &sonypi_device.fifo_async);
 	if (retval < 0)
 		return retval;
 	return 0;
 }
 
-static int sonypi_misc_release(struct inode * inode, struct file * file) {
+static int sonypi_misc_release(struct inode *inode, struct file *file)
+{
 	sonypi_misc_fasync(-1, file, 0);
 	down(&sonypi_device.lock);
 	sonypi_device.open_count--;
@@ -454,59 +532,56 @@
 	return 0;
 }
 
-static int sonypi_misc_open(struct inode * inode, struct file * file) {
+static int sonypi_misc_open(struct inode *inode, struct file *file)
+{
 	down(&sonypi_device.lock);
 	/* Flush input queue on first open */
 	if (!sonypi_device.open_count)
-		sonypi_initq();
+		kfifo_reset(sonypi_device.fifo);
 	sonypi_device.open_count++;
 	up(&sonypi_device.lock);
 	return 0;
 }
 
-static ssize_t sonypi_misc_read(struct file * file, char __user * buf,
-			size_t count, loff_t *pos)
+static ssize_t sonypi_misc_read(struct file *file, char __user *buf,
+				size_t count, loff_t *pos)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	ssize_t i = count;
+	ssize_t ret;
 	unsigned char c;
 
-	if (sonypi_emptyq()) {
-		if (file->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-		add_wait_queue(&sonypi_device.queue.proc_list, &wait);
-repeat:
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (sonypi_emptyq() && !signal_pending(current)) {
-			schedule();
-			goto repeat;
-		}
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&sonypi_device.queue.proc_list, &wait);
-	}
-	while (i > 0 && !sonypi_emptyq()) {
-		c = sonypi_pullq();
-		put_user(c, buf++);
-		i--;
-        }
-	if (count - i) {
-		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-		return count-i;
+	if ((kfifo_len(sonypi_device.fifo) == 0) &&
+	    (file->f_flags & O_NONBLOCK))
+		return -EAGAIN;
+
+	ret = wait_event_interruptible(sonypi_device.fifo_proc_list,
+				       kfifo_len(sonypi_device.fifo) != 0);
+	if (ret)
+		return ret;
+
+	while (ret < count &&
+	       (kfifo_get(sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) {
+		if (put_user(c, buf++))
+			return -EFAULT;
+		ret++;
 	}
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
+
+	if (ret > 0)
+		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+
+	return ret;
 }
 
-static unsigned int sonypi_misc_poll(struct file *file, poll_table * wait) {
-	poll_wait(file, &sonypi_device.queue.proc_list, wait);
-	if (!sonypi_emptyq())
+static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &sonypi_device.fifo_proc_list, wait);
+	if (kfifo_len(sonypi_device.fifo))
 		return POLLIN | POLLRDNORM;
 	return 0;
 }
 
-static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, 
-			     unsigned int cmd, unsigned long arg) {
+static int sonypi_misc_ioctl(struct inode *ip, struct file *fp,
+			     unsigned int cmd, unsigned long arg)
+{
 	int ret = 0;
 	void __user *argp = (void __user *)arg;
 	u8 val8;
@@ -601,99 +676,119 @@
 };
 
 struct miscdevice sonypi_misc_device = {
-	-1, "sonypi", &sonypi_misc_fops
+	.minor		= -1,
+	.name		= "sonypi",
+	.fops		= &sonypi_misc_fops,
 };
 
-#ifdef CONFIG_PM
-static int old_camera_power;
-
-static int sonypi_suspend(struct sys_device *dev, u32 state) {
-	sonypi_call2(0x81, 0); /* make sure we don't get any more events */
-	if (camera) {
-		old_camera_power = sonypi_device.camera_power;
-		sonypi_camera_off();
-	}
+static void sonypi_enable(unsigned int camera_on)
+{
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
-		sonypi_type2_dis();
+		sonypi_type2_srs();
 	else
-		sonypi_type1_dis();
-	/* disable ACPI mode */
-	if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
-		outb(0xf1, 0xb2);
-	return 0;
-}
+		sonypi_type1_srs();
+
+	sonypi_call1(0x82);
+	sonypi_call2(0x81, 0xff);
+	sonypi_call1(compat ? 0x92 : 0x82);
 
-static int sonypi_resume(struct sys_device *dev) {
 	/* Enable ACPI mode to get Fn key events */
 	if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
 		outb(0xf0, 0xb2);
+
+	if (camera && camera_on)
+		sonypi_camera_on();
+}
+
+static int sonypi_disable(void)
+{
+	sonypi_call2(0x81, 0);	/* make sure we don't get any more events */
+	if (camera)
+		sonypi_camera_off();
+
+	/* disable ACPI mode */
+	if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
+		outb(0xf1, 0xb2);
+
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
-		sonypi_type2_srs();
-	else
-		sonypi_type1_srs();
-	sonypi_call1(0x82);
-	sonypi_call2(0x81, 0xff);
-	if (compat)
-		sonypi_call1(0x92); 
+		sonypi_type2_dis();
 	else
-		sonypi_call1(0x82);
-	if (camera && old_camera_power)
-		sonypi_camera_on();
+		sonypi_type1_dis();
 	return 0;
 }
 
-/* Old PM scheme */
-static int sonypi_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) {
+#ifdef CONFIG_PM
+static int old_camera_power;
 
-	switch (rqst) {
-		case PM_SUSPEND:
-			sonypi_suspend(NULL, 0);
-			break;
-		case PM_RESUME:
-			sonypi_resume(NULL);
-			break;
+static int sonypi_suspend(struct device *dev, u32 state, u32 level)
+{
+	if (level == SUSPEND_DISABLE) {
+		old_camera_power = sonypi_device.camera_power;
+		sonypi_disable();
 	}
 	return 0;
 }
 
-/* New PM scheme (device model) */
-static struct sysdev_class sonypi_sysclass = {
-	set_kset_name("sonypi"),
-	.suspend = sonypi_suspend,
-	.resume = sonypi_resume,
-};
+static int sonypi_resume(struct device *dev, u32 level)
+{
+	if (level == RESUME_ENABLE)
+		sonypi_enable(old_camera_power);
+	return 0;
+}
+#endif
 
-static struct sys_device sonypi_sysdev = {
-	.id = 0,
-	.cls = &sonypi_sysclass,
-};
+static void sonypi_shutdown(struct device *dev)
+{
+	sonypi_disable();
+}
+
+static struct device_driver sonypi_driver = {
+	.name		= "sonypi",
+	.bus		= &platform_bus_type,
+#ifdef CONFIG_PM
+	.suspend	= sonypi_suspend,
+	.resume		= sonypi_resume,
 #endif
+	.shutdown	= sonypi_shutdown,
+};
 
-static int __devinit sonypi_probe(struct pci_dev *pcidev) {
+static int __devinit sonypi_probe(void)
+{
 	int i, ret;
 	struct sonypi_ioport_list *ioport_list;
 	struct sonypi_irq_list *irq_list;
+	struct pci_dev *pcidev;
+
+	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
 
 	sonypi_device.dev = pcidev;
-	if (pcidev)
-		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
-	else
-		sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
-	sonypi_initq();
+	sonypi_device.model = pcidev ?
+		SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2;
+
+	sonypi_device.fifo_lock = SPIN_LOCK_UNLOCKED;
+	sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
+					 &sonypi_device.fifo_lock);
+	if (IS_ERR(sonypi_device.fifo)) {
+		printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
+		ret = PTR_ERR(sonypi_device.fifo);
+		goto out_fifo;
+	}
+
+	init_waitqueue_head(&sonypi_device.fifo_proc_list);
 	init_MUTEX(&sonypi_device.lock);
-	sonypi_device.bluetooth_power = 0;
-	
+	sonypi_device.bluetooth_power = -1;
+
 	if (pcidev && pci_enable_device(pcidev)) {
 		printk(KERN_ERR "sonypi: pci_enable_device failed\n");
 		ret = -EIO;
-		goto out1;
+		goto out_pcienable;
 	}
 
-	sonypi_misc_device.minor = (minor == -1) ? 
-		MISC_DYNAMIC_MINOR : minor;
+	sonypi_misc_device.minor = (minor == -1) ? MISC_DYNAMIC_MINOR : minor;
 	if ((ret = misc_register(&sonypi_misc_device))) {
 		printk(KERN_ERR "sonypi: misc_register failed\n");
-		goto out1;
+		goto out_miscreg;
 	}
 
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) {
@@ -701,8 +796,7 @@
 		sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE;
 		sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET;
 		irq_list = sonypi_type2_irq_list;
-	}
-	else {
+	} else {
 		ioport_list = sonypi_type1_ioport_list;
 		sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE;
 		sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET;
@@ -710,8 +804,8 @@
 	}
 
 	for (i = 0; ioport_list[i].port1; i++) {
-		if (request_region(ioport_list[i].port1, 
-				   sonypi_device.region_size, 
+		if (request_region(ioport_list[i].port1,
+				   sonypi_device.region_size,
 				   "Sony Programable I/O Device")) {
 			/* get the ioport */
 			sonypi_device.ioport1 = ioport_list[i].port1;
@@ -722,7 +816,7 @@
 	if (!sonypi_device.ioport1) {
 		printk(KERN_ERR "sonypi: request_region failed\n");
 		ret = -ENODEV;
-		goto out2;
+		goto out_reqreg;
 	}
 
 	for (i = 0; irq_list[i].irq; i++) {
@@ -730,59 +824,85 @@
 		sonypi_device.irq = irq_list[i].irq;
 		sonypi_device.bits = irq_list[i].bits;
 
-		/* Enable sonypi IRQ settings */
-		if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
-			sonypi_type2_srs();
-		else
-			sonypi_type1_srs();
-
-		sonypi_call1(0x82);
-		sonypi_call2(0x81, 0xff);
-		if (compat)
-			sonypi_call1(0x92); 
-		else
-			sonypi_call1(0x82);
-
-		/* Now try requesting the irq from the system */
-		if (!request_irq(sonypi_device.irq, sonypi_irq, 
+		if (!request_irq(sonypi_device.irq, sonypi_irq,
 				 SA_SHIRQ, "sonypi", sonypi_irq))
 			break;
-
-		/* If request_irq failed, disable sonypi IRQ settings */
-		if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
-			sonypi_type2_dis();
-		else
-			sonypi_type1_dis();
 	}
 
 	if (!irq_list[i].irq) {
 		printk(KERN_ERR "sonypi: request_irq failed\n");
 		ret = -ENODEV;
-		goto out3;
+		goto out_reqirq;
 	}
 
-#ifdef CONFIG_PM
-	sonypi_device.pm = pm_register(PM_PCI_DEV, 0, sonypi_pm_callback);
-
-	if (sysdev_class_register(&sonypi_sysclass) != 0) {
-		printk(KERN_ERR "sonypi: sysdev_class_register failed\n");
-		ret = -ENODEV;
-		goto out4;
-	}
-	if (sysdev_register(&sonypi_sysdev) != 0) {
-		printk(KERN_ERR "sonypi: sysdev_register failed\n");
-		ret = -ENODEV;
-		goto out5;
+	if (useinput) {
+		/* Initialize the Input Drivers: jogdial */
+		int i;
+		sonypi_device.input_jog_dev.evbit[0] =
+			BIT(EV_KEY) | BIT(EV_REL);
+		sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] =
+			BIT(BTN_MIDDLE);
+		sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL);
+		sonypi_device.input_jog_dev.name =
+			kmalloc(sizeof(SONYPI_JOG_INPUTNAME), GFP_KERNEL);
+		if (!sonypi_device.input_jog_dev.name) {
+			printk(KERN_ERR "sonypi: kmalloc failed\n");
+			ret = -ENOMEM;
+			goto out_inkmallocinput1;
+		}
+		sprintf(sonypi_device.input_jog_dev.name, SONYPI_JOG_INPUTNAME);
+		sonypi_device.input_jog_dev.id.bustype = BUS_ISA;
+		sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY;
+
+		input_register_device(&sonypi_device.input_jog_dev);
+		printk(KERN_INFO "%s input method installed.\n",
+		       sonypi_device.input_jog_dev.name);
+
+		/* Initialize the Input Drivers: special keys */
+		sonypi_device.input_key_dev.evbit[0] = BIT(EV_KEY);
+		for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
+			if (sonypi_inputkeys[i].inputev)
+				set_bit(sonypi_inputkeys[i].inputev,
+					sonypi_device.input_key_dev.keybit);
+		sonypi_device.input_key_dev.name =
+			kmalloc(sizeof(SONYPI_KEY_INPUTNAME), GFP_KERNEL);
+		if (!sonypi_device.input_key_dev.name) {
+			printk(KERN_ERR "sonypi: kmalloc failed\n");
+			ret = -ENOMEM;
+			goto out_inkmallocinput2;
+		}
+		sprintf(sonypi_device.input_key_dev.name, SONYPI_KEY_INPUTNAME);
+		sonypi_device.input_key_dev.id.bustype = BUS_ISA;
+		sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY;
+
+		input_register_device(&sonypi_device.input_key_dev);
+		printk(KERN_INFO "%s input method installed.\n",
+		       sonypi_device.input_key_dev.name);
+
+		sonypi_device.input_fifo_lock = SPIN_LOCK_UNLOCKED;
+		sonypi_device.input_fifo =
+			kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
+				    &sonypi_device.input_fifo_lock);
+		if (IS_ERR(sonypi_device.input_fifo)) {
+			printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
+			ret = PTR_ERR(sonypi_device.input_fifo);
+			goto out_infifo;
+		}
+
+		INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL);
+	}
+
+	sonypi_device.pdev = platform_device_register_simple("sonypi", -1,
+							     NULL, 0);
+	if (IS_ERR(sonypi_device.pdev)) {
+		ret = PTR_ERR(sonypi_device.pdev);
+		goto out_platformdev;
 	}
-#endif
 
-	/* Enable ACPI mode to get Fn key events */
-	if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
-		outb(0xf0, 0xb2);
+	sonypi_enable(0);
 
-	printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver v%d.%d.\n",
-	       SONYPI_DRIVER_MAJORVERSION,
-	       SONYPI_DRIVER_MINORVERSION);
+	printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver"
+	       "v%s.\n", SONYPI_DRIVER_VERSION);
 	printk(KERN_INFO "sonypi: detected %s model, "
 	       "verbose = %d, fnkeyinit = %s, camera = %s, "
 	       "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
@@ -796,76 +916,60 @@
 	       useinput ? "on" : "off",
 	       SONYPI_ACPI_ACTIVE ? "on" : "off");
 	printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
-	       sonypi_device.irq, 
+	       sonypi_device.irq,
 	       sonypi_device.ioport1, sonypi_device.ioport2);
 
 	if (minor == -1)
 		printk(KERN_INFO "sonypi: device allocated minor is %d\n",
 		       sonypi_misc_device.minor);
 
-#ifdef SONYPI_USE_INPUT
-	if (useinput) {
-		/* Initialize the Input Drivers: */
-		sonypi_device.jog_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-		sonypi_device.jog_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_MIDDLE);
-		sonypi_device.jog_dev.relbit[0] = BIT(REL_WHEEL);
-		sonypi_device.jog_dev.name = (char *) kmalloc(
-			sizeof(SONYPI_INPUTNAME), GFP_KERNEL);
-		sprintf(sonypi_device.jog_dev.name, SONYPI_INPUTNAME);
-		sonypi_device.jog_dev.id.bustype = BUS_ISA;
-		sonypi_device.jog_dev.id.vendor = PCI_VENDOR_ID_SONY;
-	  
-		input_register_device(&sonypi_device.jog_dev);
-		printk(KERN_INFO "%s installed.\n", sonypi_device.jog_dev.name);
-	}
-#endif /* SONYPI_USE_INPUT */
-
 	return 0;
 
-#ifdef CONFIG_PM
-out5:
-	sysdev_class_unregister(&sonypi_sysclass);
-out4:
+out_platformdev:
+	kfifo_free(sonypi_device.input_fifo);
+out_infifo:
+	input_unregister_device(&sonypi_device.input_key_dev);
+	kfree(sonypi_device.input_key_dev.name);
+out_inkmallocinput2:
+	input_unregister_device(&sonypi_device.input_jog_dev);
+	kfree(sonypi_device.input_jog_dev.name);
+out_inkmallocinput1:
 	free_irq(sonypi_device.irq, sonypi_irq);
-#endif
-out3:
+out_reqirq:
 	release_region(sonypi_device.ioport1, sonypi_device.region_size);
-out2:
+out_reqreg:
 	misc_deregister(&sonypi_misc_device);
-out1:
+out_miscreg:
+	if (pcidev)
+		pci_disable_device(pcidev);
+out_pcienable:
+	kfifo_free(sonypi_device.fifo);
+out_fifo:
+	pci_dev_put(sonypi_device.dev);
 	return ret;
 }
 
-static void __devexit sonypi_remove(void) {
-
-#ifdef CONFIG_PM
-	pm_unregister(sonypi_device.pm);
+static void __devexit sonypi_remove(void)
+{
+	sonypi_disable();
 
-	sysdev_unregister(&sonypi_sysdev);
-	sysdev_class_unregister(&sonypi_sysclass);
-#endif
+	platform_device_unregister(sonypi_device.pdev);
 
-	sonypi_call2(0x81, 0); /* make sure we don't get any more events */
-	
-#ifdef SONYPI_USE_INPUT
 	if (useinput) {
-		input_unregister_device(&sonypi_device.jog_dev);
-		kfree(sonypi_device.jog_dev.name);
+		input_unregister_device(&sonypi_device.input_key_dev);
+		kfree(sonypi_device.input_key_dev.name);
+		input_unregister_device(&sonypi_device.input_jog_dev);
+		kfree(sonypi_device.input_jog_dev.name);
+		kfifo_free(sonypi_device.input_fifo);
 	}
-#endif /* SONYPI_USE_INPUT */
 
-	if (camera)
-		sonypi_camera_off();
-	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
-		sonypi_type2_dis();
-	else
-		sonypi_type1_dis();
-	/* disable ACPI mode */
-	if (!SONYPI_ACPI_ACTIVE && fnkeyinit)
-		outb(0xf1, 0xb2);
 	free_irq(sonypi_device.irq, sonypi_irq);
 	release_region(sonypi_device.ioport1, sonypi_device.region_size);
 	misc_deregister(&sonypi_misc_device);
+	if (sonypi_device.dev)
+		pci_disable_device(sonypi_device.dev);
+	kfifo_free(sonypi_device.fifo);
+	pci_dev_put(sonypi_device.dev);
 	printk(KERN_INFO "sonypi: removed.\n");
 }
 
@@ -887,78 +991,29 @@
 	{ }
 };
 
-static int __init sonypi_init_module(void)
+static int __init sonypi_init(void)
 {
-	struct pci_dev *pcidev = NULL;
-	if (dmi_check_system(sonypi_dmi_table)) {
-		pcidev = pci_find_device(PCI_VENDOR_ID_INTEL, 
-					 PCI_DEVICE_ID_INTEL_82371AB_3, 
-					 NULL);
-		return sonypi_probe(pcidev);
-	}
-	else
+	int ret;
+
+	if (!dmi_check_system(sonypi_dmi_table))
 		return -ENODEV;
+
+	ret = driver_register(&sonypi_driver);
+	if (ret)
+		return ret;
+
+	ret = sonypi_probe();
+	if (ret)
+		driver_unregister(&sonypi_driver);
+
+	return ret;
 }
 
-static void __exit sonypi_cleanup_module(void) {
+static void __exit sonypi_exit(void)
+{
+	driver_unregister(&sonypi_driver);
 	sonypi_remove();
 }
 
-#ifndef MODULE
-static int __init sonypi_setup(char *str)  {
-	int ints[8];
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	if (ints[0] <= 0) 
-		goto out;
-	minor = ints[1];
-	if (ints[0] == 1)
-		goto out;
-	verbose = ints[2];
-	if (ints[0] == 2)
-		goto out;
-	fnkeyinit = ints[3];
-	if (ints[0] == 3)
-		goto out;
-	camera = ints[4];
-	if (ints[0] == 4)
-		goto out;
-	compat = ints[5];
-	if (ints[0] == 5)
-		goto out;
-	mask = ints[6];
-	if (ints[0] == 6)
-		goto out;
-	useinput = ints[7];
-out:
-	return 1;
-}
-
-__setup("sonypi=", sonypi_setup);
-#endif /* !MODULE */
-	
-/* Module entry points */
-module_init(sonypi_init_module);
-module_exit(sonypi_cleanup_module);
-
-MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
-MODULE_DESCRIPTION("Sony Programmable I/O Control Device driver");
-MODULE_LICENSE("GPL");
-
-
-MODULE_PARM(minor,"i");
-MODULE_PARM_DESC(minor, "minor number of the misc device, default is -1 (automatic)");
-MODULE_PARM(verbose,"i");
-MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
-MODULE_PARM(fnkeyinit,"i");
-MODULE_PARM_DESC(fnkeyinit, "set this if your Fn keys do not generate any event");
-MODULE_PARM(camera,"i");
-MODULE_PARM_DESC(camera, "set this if you have a MotionEye camera (PictureBook series)");
-MODULE_PARM(compat,"i");
-MODULE_PARM_DESC(compat, "set this if you want to enable backward compatibility mode");
-MODULE_PARM(mask, "i");
-MODULE_PARM_DESC(mask, "set this to the mask of event you want to enable (see doc)");
-MODULE_PARM(useinput, "i");
-MODULE_PARM_DESC(useinput, "if you have a jogdial, set this if you would like it to use the modern Linux Input Driver system");
-
-EXPORT_SYMBOL(sonypi_camera_command);
+module_init(sonypi_init);
+module_exit(sonypi_exit);
diff -Nru a/drivers/char/sonypi.h b/drivers/char/sonypi.h
--- a/drivers/char/sonypi.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/char/sonypi.h	2004-10-28 22:25:58 -07:00
@@ -1,7 +1,7 @@
-/* 
+/*
  * Sony Programmable I/O Control Device driver for VAIO
  *
- * Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
+ * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
  *
  * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
  *
@@ -14,30 +14,29 @@
  * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
  *
  * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
- * 
+ *
  * 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.
  *
  */
 
-#ifndef _SONYPI_PRIV_H_ 
+#ifndef _SONYPI_PRIV_H_
 #define _SONYPI_PRIV_H_
 
 #ifdef __KERNEL__
 
-#define SONYPI_DRIVER_MAJORVERSION	 1
-#define SONYPI_DRIVER_MINORVERSION	23
+#define SONYPI_DRIVER_VERSION	 "1.24"
 
 #define SONYPI_DEVICE_MODEL_TYPE1	1
 #define SONYPI_DEVICE_MODEL_TYPE2	2
@@ -46,9 +45,9 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/input.h>
-#include <linux/pm.h>
 #include <linux/acpi.h>
-#include "linux/sonypi.h"
+#include <linux/kfifo.h>
+#include <linux/sonypi.h>
 
 /* type1 models use those */
 #define SONYPI_IRQ_PORT			0x8034
@@ -223,6 +222,7 @@
 	{ 0x1a, SONYPI_EVENT_FNKEY_F10 },
 	{ 0x1b, SONYPI_EVENT_FNKEY_F11 },
 	{ 0x1c, SONYPI_EVENT_FNKEY_F12 },
+	{ 0x1f, SONYPI_EVENT_FNKEY_RELEASED },
 	{ 0x21, SONYPI_EVENT_FNKEY_1 },
 	{ 0x22, SONYPI_EVENT_FNKEY_2 },
 	{ 0x31, SONYPI_EVENT_FNKEY_D },
@@ -340,30 +340,53 @@
 };
 
 #define SONYPI_BUF_SIZE	128
-struct sonypi_queue {
-	unsigned long head;
-	unsigned long tail;
-	unsigned long len;
-	spinlock_t s_lock;
-	wait_queue_head_t proc_list;
-	struct fasync_struct *fasync;
-	unsigned char buf[SONYPI_BUF_SIZE];
-};
-
-/* We enable input subsystem event forwarding if the input 
- * subsystem is compiled in, but only if sonypi is not into the
- * kernel and input as a module... */
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-#if ! (defined(CONFIG_SONYPI) && defined(CONFIG_INPUT_MODULE))
-#define SONYPI_USE_INPUT
-#endif
-#endif
 
-/* The name of the Jog Dial for the input device drivers */
-#define SONYPI_INPUTNAME	"Sony VAIO Jog Dial"
+/* The name of the devices for the input device drivers */
+#define SONYPI_JOG_INPUTNAME	"Sony Vaio Jogdial"
+#define SONYPI_KEY_INPUTNAME	"Sony Vaio Keys"
+
+/* Correspondance table between sonypi events and input layer events */
+struct {
+	int sonypiev;
+	int inputev;
+} sonypi_inputkeys[] = {
+	{ SONYPI_EVENT_CAPTURE_PRESSED,	 	KEY_CAMERA },
+	{ SONYPI_EVENT_FNKEY_ONLY, 		KEY_FN },
+	{ SONYPI_EVENT_FNKEY_ESC, 		KEY_FN_ESC },
+	{ SONYPI_EVENT_FNKEY_F1, 		KEY_FN_F1 },
+	{ SONYPI_EVENT_FNKEY_F2, 		KEY_FN_F2 },
+	{ SONYPI_EVENT_FNKEY_F3, 		KEY_FN_F3 },
+	{ SONYPI_EVENT_FNKEY_F4, 		KEY_FN_F4 },
+	{ SONYPI_EVENT_FNKEY_F5, 		KEY_FN_F5 },
+	{ SONYPI_EVENT_FNKEY_F6, 		KEY_FN_F6 },
+	{ SONYPI_EVENT_FNKEY_F7, 		KEY_FN_F7 },
+	{ SONYPI_EVENT_FNKEY_F8, 		KEY_FN_F8 },
+	{ SONYPI_EVENT_FNKEY_F9,		KEY_FN_F9 },
+	{ SONYPI_EVENT_FNKEY_F10,		KEY_FN_F10 },
+	{ SONYPI_EVENT_FNKEY_F11, 		KEY_FN_F11 },
+	{ SONYPI_EVENT_FNKEY_F12,		KEY_FN_F12 },
+	{ SONYPI_EVENT_FNKEY_1, 		KEY_FN_1 },
+	{ SONYPI_EVENT_FNKEY_2, 		KEY_FN_2 },
+	{ SONYPI_EVENT_FNKEY_D,			KEY_FN_D },
+	{ SONYPI_EVENT_FNKEY_E,			KEY_FN_E },
+	{ SONYPI_EVENT_FNKEY_F,			KEY_FN_F },
+	{ SONYPI_EVENT_FNKEY_S,			KEY_FN_S },
+	{ SONYPI_EVENT_FNKEY_B,			KEY_FN_B },
+	{ SONYPI_EVENT_BLUETOOTH_PRESSED, 	KEY_BLUE },
+	{ SONYPI_EVENT_BLUETOOTH_ON, 		KEY_BLUE },
+	{ SONYPI_EVENT_PKEY_P1, 		KEY_PROG1 },
+	{ SONYPI_EVENT_PKEY_P2, 		KEY_PROG2 },
+	{ SONYPI_EVENT_PKEY_P3, 		KEY_PROG3 },
+	{ SONYPI_EVENT_BACK_PRESSED, 		KEY_BACK },
+	{ SONYPI_EVENT_HELP_PRESSED, 		KEY_HELP },
+	{ SONYPI_EVENT_ZOOM_PRESSED, 		KEY_ZOOM },
+	{ SONYPI_EVENT_THUMBPHRASE_PRESSED, 	BTN_THUMB },
+	{ 0, 0 },
+};
 
 struct sonypi_device {
 	struct pci_dev *dev;
+	struct platform_device *pdev;
 	u16 irq;
 	u16 bits;
 	u16 ioport1;
@@ -373,15 +396,17 @@
 	int camera_power;
 	int bluetooth_power;
 	struct semaphore lock;
-	struct sonypi_queue queue;
+	struct kfifo *fifo;
+	spinlock_t fifo_lock;
+	wait_queue_head_t fifo_proc_list;
+	struct fasync_struct *fifo_async;
 	int open_count;
 	int model;
-#ifdef SONYPI_USE_INPUT
-	struct input_dev jog_dev;
-#endif
-#ifdef CONFIG_PM
-	struct pm_dev *pm;
-#endif
+	struct input_dev input_jog_dev;
+	struct input_dev input_key_dev;
+	struct work_struct input_work;
+	struct kfifo *input_fifo;
+	spinlock_t input_fifo_lock;
 };
 
 #define ITERATIONS_LONG		10000
@@ -399,37 +424,8 @@
 #define SONYPI_ACPI_ACTIVE (!acpi_disabled)
 #else
 #define SONYPI_ACPI_ACTIVE 0
-#endif /* CONFIG_ACPI */
-
-static inline int sonypi_ec_write(u8 addr, u8 value) {
-#ifdef CONFIG_ACPI_EC
-	if (SONYPI_ACPI_ACTIVE)
-		return ec_write(addr, value);
-#endif
-	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
-	outb_p(0x81, SONYPI_CST_IOPORT);
-	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
-	outb_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
-	outb_p(value, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
-	return 0;
-}
-
-static inline int sonypi_ec_read(u8 addr, u8 *value) {
-#ifdef CONFIG_ACPI_EC
-	if (SONYPI_ACPI_ACTIVE)
-		return ec_read(addr, value);
-#endif
-	wait_on_command(1, inb_p(SONYPI_CST_IOPORT) & 3, ITERATIONS_LONG);
-	outb_p(0x80, SONYPI_CST_IOPORT);
-	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
-	outb_p(addr, SONYPI_DATA_IOPORT);
-	wait_on_command(0, inb_p(SONYPI_CST_IOPORT) & 2, ITERATIONS_LONG);
-	*value = inb_p(SONYPI_DATA_IOPORT);
-	return 0;
-}
+#endif				/* CONFIG_ACPI */
 
-#endif /* __KERNEL__ */
+#endif				/* __KERNEL__ */
 
-#endif /* _SONYPI_PRIV_H_ */
+#endif				/* _SONYPI_PRIV_H_ */
diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c
--- a/drivers/char/synclink.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/char/synclink.c	2004-10-28 22:25:57 -07:00
@@ -8089,9 +8089,7 @@
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->dev      = info->netdev;
-	skb->mac.raw  = skb->data;
-	skb->protocol = hdlc_type_trans(skb, skb->dev);
+	skb->protocol = hdlc_type_trans(skb, info->netdev);
 
 	stats->rx_packets++;
 	stats->rx_bytes += size;
diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
--- a/drivers/char/synclinkmp.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/char/synclinkmp.c	2004-10-28 22:25:57 -07:00
@@ -1954,9 +1954,7 @@
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->dev      = info->netdev;
-	skb->mac.raw  = skb->data;
-	skb->protocol = hdlc_type_trans(skb, skb->dev);
+	skb->protocol = hdlc_type_trans(skb, info->netdev);
 
 	stats->rx_packets++;
 	stats->rx_bytes += size;
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/char/tty_io.c	2004-10-28 22:25:58 -07:00
@@ -168,8 +168,7 @@
 
 static inline void free_tty_struct(struct tty_struct *tty)
 {
-	if (tty->write_buf)
-		kfree(tty->write_buf);
+	kfree(tty->write_buf);
 	kfree(tty);
 }
 
@@ -1060,6 +1059,7 @@
 			up(&tty->atomic_write);
 			return -ENOMEM;
 		}
+		kfree(tty->write_buf);
 		tty->write_cnt = chunk;
 		tty->write_buf = buf;
 	}
@@ -2148,11 +2148,11 @@
 
 static int send_break(struct tty_struct *tty, int duration)
 {
-	set_current_state(TASK_INTERRUPTIBLE);
-
 	tty->driver->break_ctl(tty, -1);
-	if (!signal_pending(current))
+	if (!signal_pending(current)) {
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(duration);
+	}
 	tty->driver->break_ctl(tty, 0);
 	if (signal_pending(current))
 		return -EINTR;
diff -Nru a/drivers/char/viocons.c b/drivers/char/viocons.c
--- a/drivers/char/viocons.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/char/viocons.c	2004-10-28 22:25:56 -07:00
@@ -83,15 +83,6 @@
 	u8 data[VIOCHAR_MAX_DATA];
 };
 
-/*
- * This is a place where we handle the distribution of memory
- * for copy_from_user() calls.  The buffer_available array is to
- * help us determine which buffer to use.
- */
-#define VIOCHAR_NUM_CFU_BUFFERS	7
-static struct viocharlpevent viocons_cfu_buffer[VIOCHAR_NUM_CFU_BUFFERS];
-static atomic_t viocons_cfu_buffer_available[VIOCHAR_NUM_CFU_BUFFERS];
-
 #define VIOCHAR_WINDOW		10
 #define VIOCHAR_HIGHWATERMARK	3
 
@@ -207,50 +198,6 @@
 }
 
 /*
- * This function should ONLY be called once from viocons_init2
- */
-static void viocons_init_cfu_buffer(void)
-{
-	int i;
-
-	for (i = 1; i < VIOCHAR_NUM_CFU_BUFFERS; i++)
-		atomic_set(&viocons_cfu_buffer_available[i], 1);
-}
-
-static struct viocharlpevent *viocons_get_cfu_buffer(void)
-{
-	int i;
-
-	/*
-	 * Grab the first available buffer.  It doesn't matter if we
-	 * are interrupted during this array traversal as long as we
-	 * get an available space.
-	 */
-	for (i = 0; i < VIOCHAR_NUM_CFU_BUFFERS; i++)
-		if (atomic_dec_if_positive(&viocons_cfu_buffer_available[i])
-				== 0 )
-			return &viocons_cfu_buffer[i];
-	hvlog("\n\rviocons: viocons_get_cfu_buffer : no free buffers found");
-	return NULL;
-}
-
-static void viocons_free_cfu_buffer(struct viocharlpevent *buffer)
-{
-	int i;
-
-	i = buffer - &viocons_cfu_buffer[0];
-	if (i >= (sizeof(viocons_cfu_buffer) / sizeof(viocons_cfu_buffer[0]))) {
-		hvlog("\n\rviocons: viocons_free_cfu_buffer : buffer pointer not found in list.");
-		return;
-	}
-	if (atomic_read(&viocons_cfu_buffer_available[i]) != 0) {
-		hvlog("\n\rviocons: WARNING : returning unallocated cfu buffer.");
-		return;
-	}
-	atomic_set(&viocons_cfu_buffer_available[i], 1);
-}
-
-/*
  * Add data to our pending-send buffers.  
  *
  * NOTE: Don't use printk in here because it gets nastily recursive.
@@ -438,15 +385,14 @@
  * NOTE: Don't use printk in here because it gets nastily recursive.  hvlog
  * can be used to log to the hypervisor buffer
  */
-static int internal_write(struct port_info *pi, const char *buf,
-			  size_t len, struct viocharlpevent *viochar)
+static int internal_write(struct port_info *pi, const char *buf, size_t len)
 {
 	HvLpEvent_Rc hvrc;
 	size_t bleft;
 	size_t curlen;
 	const char *curbuf;
 	unsigned long flags;
-	int copy_needed = (viochar == NULL);
+	struct viocharlpevent *viochar;
 
 	/*
 	 * Write to the hvlog of inbound data are now done prior to
@@ -462,25 +408,13 @@
 
 	spin_lock_irqsave(&consolelock, flags);
 
-	/*
-	 * If the internal_write() was passed a pointer to a
-	 * viocharlpevent then we don't need to allocate a new one
-	 * (this is the case where we are internal_writing user space
-	 * data).  If we aren't writing user space data then we need
-	 * to get an event from viopath.
-	 */
-	if (copy_needed) {
-		/* This one is fetched from the viopath data structure */
-		viochar = (struct viocharlpevent *)
-			vio_get_event_buffer(viomajorsubtype_chario);
-		/* Make sure we got a buffer */
-		if (viochar == NULL) {
-			spin_unlock_irqrestore(&consolelock, flags);
-			hvlog("\n\rviocons: Can't get viochar buffer in internal_write().");
-			return -EAGAIN;
-		}
-		initDataEvent(viochar, pi->lp);
+	viochar = vio_get_event_buffer(viomajorsubtype_chario);
+	if (viochar == NULL) {
+		spin_unlock_irqrestore(&consolelock, flags);
+		hvlog("\n\rviocons: Can't get vio buffer in internal_write().");
+		return -EAGAIN;
 	}
+	initDataEvent(viochar, pi->lp);
 
 	curbuf = buf;
 	bleft = len;
@@ -493,25 +427,16 @@
 			curlen = bleft;
 
 		viochar->event.xCorrelationToken = pi->seq++;
-
-		if (copy_needed) {
-			memcpy(viochar->data, curbuf, curlen);
-			viochar->len = curlen;
-		}
-
+		memcpy(viochar->data, curbuf, curlen);
+		viochar->len = curlen;
 		viochar->event.xSizeMinus1 =
 		    offsetof(struct viocharlpevent, data) + curlen;
 
 		hvrc = HvCallEvent_signalLpEvent(&viochar->event);
 		if (hvrc) {
-			spin_unlock_irqrestore(&consolelock, flags);
-			if (copy_needed)
-				vio_free_event_buffer(viomajorsubtype_chario, viochar);
-
 			hvlog("viocons: error sending event! %d\n", (int)hvrc);
-			return len - bleft;
+			goto out;
 		}
-
 		curbuf += curlen;
 		bleft -= curlen;
 	}
@@ -519,14 +444,9 @@
 	/* If we didn't send it all, buffer as much of it as we can. */
 	if (bleft > 0)
 		bleft -= buffer_add(pi, curbuf, bleft);
-	/*
-	 * Since we grabbed it from the viopath data structure, return
-	 * it to the data structure.
-	 */
-	if (copy_needed)
-		vio_free_event_buffer(viomajorsubtype_chario, viochar);
+out:
+	vio_free_event_buffer(viomajorsubtype_chario, viochar);
 	spin_unlock_irqrestore(&consolelock, flags);
-
 	return len - bleft;
 }
 
@@ -603,18 +523,8 @@
 
 	hvlogOutput(s, count);
 
-	if (!viopath_isactive(pi->lp)) {
-		/*
-		 * This is a VERY noisy trace message in the case where the
-		 * path manager is not active or in the case where this
-		 * function is called prior to viocons initialization.  It is
-		 * being commented out for the sake of a clear trace buffer.
-		 */
-#if 0
-		 hvlog("\n\rviocons_write: path not active to lp %d", pi->lp);
-#endif
+	if (!viopath_isactive(pi->lp))
 		return;
-	}
 
 	/* 
 	 * Any newline character found will cause a
@@ -627,17 +537,16 @@
 			 * Newline found. Print everything up to and 
 			 * including the newline
 			 */
-			internal_write(pi, &s[begin], index - begin + 1,
-					NULL);
+			internal_write(pi, &s[begin], index - begin + 1);
 			begin = index + 1;
 			/* Emit a carriage return as well */
-			internal_write(pi, &cr, 1, NULL);
+			internal_write(pi, &cr, 1);
 		}
 	}
 
 	/* If any characters left to write, write them now */
 	if ((index - begin) > 0)
-		internal_write(pi, &s[begin], index - begin, NULL);
+		internal_write(pi, &s[begin], index - begin);
 }
 
 /*
@@ -721,11 +630,9 @@
 /*
  * TTY Write method
  */
-static int viotty_write(struct tty_struct *tty,
-			const unsigned char *buf, int count)
+static int viotty_write(struct tty_struct *tty, const unsigned char *buf,
+		int count)
 {
-	int ret;
-	int total = 0;
 	struct port_info *pi;
 
 	pi = get_port_data(tty);
@@ -746,16 +653,10 @@
 	 * viotty_write call and, since the viopath isn't active to this
 	 * partition, return count.
 	 */
-	if (!viopath_isactive(pi->lp)) {
-		/* Noisy trace.  Commented unless needed. */
-#if 0
-		 hvlog("\n\rviotty_write: viopath NOT active for lp %d.",pi->lp);
-#endif
+	if (!viopath_isactive(pi->lp))
 		return count;
-	}
 
-	total = internal_write(pi, buf, count, NULL);
-	return total;
+	return internal_write(pi, buf, count);
 }
 
 /*
@@ -774,7 +675,7 @@
 		hvlogOutput(&ch, 1);
 
 	if (viopath_isactive(pi->lp))
-		internal_write(pi, &ch, 1, NULL);
+		internal_write(pi, &ch, 1);
 }
 
 /*
@@ -1269,8 +1170,6 @@
 		put_tty_driver(viotty_driver);
 		viotty_driver = NULL;
 	}
-
-	viocons_init_cfu_buffer();
 
 	unregister_console(&viocons_early);
 	register_console(&viocons);
diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c
--- a/drivers/char/vt.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/char/vt.c	2004-10-28 22:25:59 -07:00
@@ -2153,8 +2153,6 @@
 	if (!printable || test_and_set_bit(0, &printing))
 		return;
 
-	pm_access(pm_con);
-
 	if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
 		currcons = kmsg_redirect - 1;
 
@@ -2353,7 +2351,6 @@
 {
 	int	retval;
 
-	pm_access(pm_con);
 	retval = do_con_write(tty, buf, count);
 	con_flush_chars(tty);
 
@@ -2364,7 +2361,6 @@
 {
 	if (in_interrupt())
 		return;	/* n_r3964 calls put_char() from interrupt context */
-	pm_access(pm_con);
 	do_con_write(tty, &ch, 1);
 }
 
@@ -2433,8 +2429,6 @@
 	if (in_interrupt())	/* from flush_to_ldisc */
 		return;
 
-	pm_access(pm_con);
-	
 	/* if we race with con_close(), vt may be null */
 	acquire_console_sem();
 	vt = tty->driver_data;
@@ -3255,7 +3249,6 @@
 EXPORT_SYMBOL(default_red);
 EXPORT_SYMBOL(default_grn);
 EXPORT_SYMBOL(default_blu);
-EXPORT_SYMBOL(vc_cons_allocated);
 EXPORT_SYMBOL(update_region);
 EXPORT_SYMBOL(redraw_screen);
 EXPORT_SYMBOL(vc_resize);
diff -Nru a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
--- a/drivers/firmware/efivars.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/firmware/efivars.c	2004-10-28 22:25:59 -07:00
@@ -640,7 +640,7 @@
 	*(short_name + strlen(short_name)) = '-';
 	efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
 
-	kobject_set_name(&new_efivar->kobj, short_name);
+	kobject_set_name(&new_efivar->kobj, "%s", short_name);
 	kobj_set_kset_s(new_efivar, vars_subsys);
 	kobject_register(&new_efivar->kobj);
 
diff -Nru a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
--- a/drivers/firmware/pcdp.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/firmware/pcdp.c	2004-10-28 22:25:57 -07:00
@@ -98,8 +98,8 @@
 
 	if (uart_irq_supported(rev, uart)) {
 		port.irq = acpi_register_gsi(uart->gsi,
-			uart_active_high_low(rev, uart),
-			uart_edge_level(rev, uart));
+			uart_edge_level(rev, uart),
+			uart_active_high_low(rev, uart));
 		port.flags |= UPF_AUTO_IRQ;  /* some FW reported wrong GSI */
 		if (uart_pci(rev, uart))
 			port.flags |= UPF_SHARE_IRQ;
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/drivers/i2c/busses/Kconfig	2004-10-28 22:25:59 -07:00
@@ -339,7 +339,7 @@
 
 config SCx200_ACB
 	tristate "NatSemi SCx200 ACCESS.bus"
-	depends on I2C
+	depends on I2C && PCI
 	help
 	  Enable the use of the ACCESS.bus controllers of a SCx200 processor.
 
diff -Nru a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
--- a/drivers/ide/arm/icside.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/arm/icside.c	2004-10-28 22:25:58 -07:00
@@ -212,33 +212,18 @@
 	ide_hwif_t *hwif = drive->hwif;
 	struct icside_state *state = hwif->hwif_data;
 	struct scatterlist *sg = hwif->sg_table;
-	int nents;
 
-	if (rq->flags & REQ_DRIVE_TASKFILE) {
-		ide_task_t *args = rq->special;
+	ide_map_sg(drive, rq);
 
-		if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-			hwif->sg_dma_direction = DMA_TO_DEVICE;
-		else
-			hwif->sg_dma_direction = DMA_FROM_DEVICE;
-
-		sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
-		nents = 1;
-	} else {
-		nents = blk_rq_map_sg(drive->queue, rq, sg);
-
-		if (rq_data_dir(rq) == READ)
-			hwif->sg_dma_direction = DMA_FROM_DEVICE;
-		else
-			hwif->sg_dma_direction = DMA_TO_DEVICE;
-	}
-
-	nents = dma_map_sg(state->dev, sg, nents, hwif->sg_dma_direction);
+	if (rq_data_dir(rq) == READ)
+		hwif->sg_dma_direction = DMA_FROM_DEVICE;
+	else
+		hwif->sg_dma_direction = DMA_TO_DEVICE;
 
-	hwif->sg_nents = nents;
+	hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents,
+				    hwif->sg_dma_direction);
 }
 
-
 /*
  * Configure the IOMD to give the appropriate timings for the transfer
  * mode being requested.  We take the advice of the ATA standards, and
@@ -498,14 +483,6 @@
 			ICS_ARCIN_V6_INTRSTAT_1)) & 1;
 }
 
-static int icside_dma_verbose(ide_drive_t *drive)
-{
-	printk(", %s (peak %dMB/s)",
-		ide_xfer_verbose(drive->current_speed),
-		2000 / drive->drive_data);
-	return 1;
-}
-
 static int icside_dma_timeout(ide_drive_t *drive)
 {
 	printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
@@ -554,7 +531,6 @@
 	hwif->dma_start		= icside_dma_start;
 	hwif->ide_dma_end	= icside_dma_end;
 	hwif->ide_dma_test_irq	= icside_dma_test_irq;
-	hwif->ide_dma_verbose	= icside_dma_verbose;
 	hwif->ide_dma_timeout	= icside_dma_timeout;
 	hwif->ide_dma_lostirq	= icside_dma_lostirq;
 
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/ide-cd.c	2004-10-28 22:25:58 -07:00
@@ -3039,10 +3039,9 @@
 
 	printk(", %dkB Cache", be16_to_cpu(cap.buffer_size));
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (drive->using_dma)
-		(void) HWIF(drive)->ide_dma_verbose(drive);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+		ide_dma_verbose(drive);
+
 	printk("\n");
 
 	return nslots;
@@ -3433,7 +3432,7 @@
 /* options */
 char *ignore = NULL;
 
-MODULE_PARM(ignore, "s");
+module_param(ignore, charp, 0400);
 MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
 
 static int ide_cdrom_attach (ide_drive_t *drive)
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/ide-disk.c	2004-10-28 22:25:57 -07:00
@@ -815,6 +815,7 @@
 	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;
 	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;
 	args.command_type			= IDE_DRIVE_TASK_IN;
+	args.data_phase				= TASKFILE_IN;
 	args.handler				= &task_in_intr;
 	(void) smart_enable(drive);
 	return ide_raw_taskfile(drive, &args, buf);
@@ -1244,7 +1245,7 @@
 	printk(", CHS=%d/%d/%d", 
 	       drive->bios_cyl, drive->bios_head, drive->bios_sect);
 	if (drive->using_dma)
-		(void) HWIF(drive)->ide_dma_verbose(drive);
+		ide_dma_verbose(drive);
 	printk("\n");
 
 	drive->mult_count = 0;
diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
--- a/drivers/ide/ide-dma.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/ide-dma.c	2004-10-28 22:25:58 -07:00
@@ -207,67 +207,23 @@
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct scatterlist *sg = hwif->sg_table;
-	int nents;
 
-	nents = blk_rq_map_sg(drive->queue, rq, hwif->sg_table);
-		
+	if ((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256)
+		BUG();
+
+	ide_map_sg(drive, rq);
+
 	if (rq_data_dir(rq) == READ)
 		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
 	else
 		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
 
-	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
+	return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
 }
 
 EXPORT_SYMBOL_GPL(ide_build_sglist);
 
 /**
- *	ide_raw_build_sglist	-	map IDE scatter gather for DMA
- *	@drive: the drive to build the DMA table for
- *	@rq: the request holding the sg list
- *
- *	Perform the PCI mapping magic necessary to access the source or
- *	target buffers of a taskfile request via PCI DMA. The lower layers 
- *	of the  kernel provide the necessary cache management so that we can
- *	operate in a portable fashion
- */
-
-int ide_raw_build_sglist(ide_drive_t *drive, struct request *rq)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	struct scatterlist *sg = hwif->sg_table;
-	int nents = 0;
-	ide_task_t *args = rq->special;
-	u8 *virt_addr = rq->buffer;
-	int sector_count = rq->nr_sectors;
-
-	if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-	else
-		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-
-#if 1
-	if (sector_count > 256)
-		BUG();
-
-	if (sector_count > 128) {
-#else
-	while (sector_count > 128) {
-#endif
-		sg_init_one(&sg[nents], virt_addr, 128 * SECTOR_SIZE);
-		nents++;
-		virt_addr = virt_addr + (128 * SECTOR_SIZE);
-		sector_count -= 128;
-	}
-	sg_init_one(&sg[nents], virt_addr, sector_count * SECTOR_SIZE);
-	nents++;
-
-	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
-}
-
-EXPORT_SYMBOL_GPL(ide_raw_build_sglist);
-
-/**
  *	ide_build_dmatable	-	build IDE DMA table
  *
  *	ide_build_dmatable() prepares a dma request. We map the command
@@ -288,10 +244,7 @@
 	int i;
 	struct scatterlist *sg;
 
-	if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
-		hwif->sg_nents = i = ide_raw_build_sglist(drive, rq);
-	else
-		hwif->sg_nents = i = ide_build_sglist(drive, rq);
+	hwif->sg_nents = i = ide_build_sglist(drive, rq);
 
 	if (!i)
 		return 0;
@@ -728,17 +681,46 @@
 
 EXPORT_SYMBOL(__ide_dma_good_drive);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-int __ide_dma_verbose (ide_drive_t *drive)
+int ide_use_dma(ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_hwif_t *hwif = drive->hwif;
+
+	/* consult the list of known "bad" drives */
+	if (__ide_dma_bad_drive(drive))
+		return 0;
+
+	/* capable of UltraDMA modes */
+	if (id->field_valid & 4) {
+		if (hwif->ultra_mask & id->dma_ultra)
+			return 1;
+	}
+
+	/* capable of regular DMA modes */
+	if (id->field_valid & 2) {
+		if (hwif->mwdma_mask & id->dma_mword)
+			return 1;
+		if (hwif->swdma_mask & id->dma_1word)
+			return 1;
+	}
+
+	/* consult the list of known "good" drives */
+	if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
+		return 1;
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_use_dma);
+
+void ide_dma_verbose(ide_drive_t *drive)
 {
 	struct hd_driveid *id	= drive->id;
 	ide_hwif_t *hwif	= HWIF(drive);
 
 	if (id->field_valid & 4) {
-		if ((id->dma_ultra >> 8) && (id->dma_mword >> 8)) {
-			printk(", BUG DMA OFF");
-			return hwif->ide_dma_off_quietly(drive);
-		}
+		if ((id->dma_ultra >> 8) && (id->dma_mword >> 8))
+			goto bug_dma_off;
 		if (id->dma_ultra & ((id->dma_ultra >> 8) & hwif->ultra_mask)) {
 			if (((id->dma_ultra >> 11) & 0x1F) &&
 			    eighty_ninty_three(drive)) {
@@ -768,19 +750,22 @@
 			printk(", (U)DMA");	/* Can be BIOS-enabled! */
 		}
 	} else if (id->field_valid & 2) {
-		if ((id->dma_mword >> 8) && (id->dma_1word >> 8)) {
-			printk(", BUG DMA OFF");
-			return hwif->ide_dma_off_quietly(drive);
-		}
+		if ((id->dma_mword >> 8) && (id->dma_1word >> 8))
+			goto bug_dma_off;
 		printk(", DMA");
 	} else if (id->field_valid & 1) {
 		printk(", BUG");
 	}
-	return 1;
+	return;
+bug_dma_off:
+	printk(", BUG DMA OFF");
+	hwif->ide_dma_off_quietly(drive);
+	return;
 }
 
-EXPORT_SYMBOL(__ide_dma_verbose);
+EXPORT_SYMBOL(ide_dma_verbose);
 
+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 int __ide_dma_lostirq (ide_drive_t *drive)
 {
 	printk("%s: DMA interrupt recovery\n", drive->name);
@@ -955,8 +940,6 @@
 		hwif->ide_dma_end = &__ide_dma_end;
 	if (!hwif->ide_dma_test_irq)
 		hwif->ide_dma_test_irq = &__ide_dma_test_irq;
-	if (!hwif->ide_dma_verbose)
-		hwif->ide_dma_verbose = &__ide_dma_verbose;
 	if (!hwif->ide_dma_timeout)
 		hwif->ide_dma_timeout = &__ide_dma_timeout;
 	if (!hwif->ide_dma_lostirq)
diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/ide-io.c	2004-10-28 22:25:59 -07:00
@@ -680,6 +680,9 @@
 	ide_hwif_t *hwif = drive->hwif;
 	struct scatterlist *sg = hwif->sg_table;
 
+	if (hwif->sg_mapped)	/* needed by ide-scsi */
+		return;
+
 	if ((rq->flags & REQ_DRIVE_TASKFILE) == 0) {
 		hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
 	} else {
@@ -1219,12 +1222,15 @@
 	HWGROUP(drive)->rq = NULL;
 
 	rq->errors = 0;
+
+	if (!rq->bio)
+		goto out;
+
 	rq->sector = rq->bio->bi_sector;
 	rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
 	rq->hard_cur_sectors = rq->current_nr_sectors;
-	if (rq->bio)
-		rq->buffer = NULL;
-
+	rq->buffer = NULL;
+out:
 	return ret;
 }
 
diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
--- a/drivers/ide/ide-iops.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/ide-iops.c	2004-10-28 22:25:57 -07:00
@@ -221,24 +221,18 @@
 		HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG);
 }
 
-EXPORT_SYMBOL(SELECT_INTERRUPT);
-
 void SELECT_MASK (ide_drive_t *drive, int mask)
 {
 	if (HWIF(drive)->maskproc)
 		HWIF(drive)->maskproc(drive, mask);
 }
 
-EXPORT_SYMBOL(SELECT_MASK);
-
 void QUIRK_LIST (ide_drive_t *drive)
 {
 	if (HWIF(drive)->quirkproc)
 		drive->quirk_list = HWIF(drive)->quirkproc(drive);
 }
 
-EXPORT_SYMBOL(QUIRK_LIST);
-
 /*
  * Some localbus EIDE interfaces require a special access sequence
  * when using 32-bit I/O instructions to transfer data.  We call this
@@ -253,8 +247,6 @@
 	(void) HWIF(drive)->INB(port);
 }
 
-EXPORT_SYMBOL(ata_vlb_sync);
-
 /*
  * This is used for most PIO data transfers *from* the IDE interface
  */
@@ -277,8 +269,6 @@
 	}
 }
 
-EXPORT_SYMBOL(ata_input_data);
-
 /*
  * This is used for most PIO data transfers *to* the IDE interface
  */
@@ -300,8 +290,6 @@
 		hwif->OUTSW(IDE_DATA_REG, buffer, wcount<<1);
 	}
 }
-
-EXPORT_SYMBOL(ata_output_data);
 
 /*
  * The following routines are mainly used by the ATAPI drivers.
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/ide-probe.c	2004-10-28 22:25:58 -07:00
@@ -730,6 +730,8 @@
 			    /* And beware of confused Maxtor drives that go "M0000000000"
 			      "The SN# is garbage in the ID block..." [Eric] */
 			    strncmp(drive->id->serial_no, "M0000000000000000000", 20) &&
+			    /* Same goes for another set of Maxtor drives that say "D3000000" */
+			    strncmp(drive->id->serial_no, "D3000000", 8) &&
 			    strncmp(hwif->drives[0].id->serial_no, drive->id->serial_no, 20) == 0) {
 				printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
 				drive->present = 0;
diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
--- a/drivers/ide/ide-proc.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/ide-proc.c	2004-10-28 22:25:58 -07:00
@@ -8,37 +8,6 @@
 /*
  * This is the /proc/ide/ filesystem implementation.
  *
- * The major reason this exists is to provide sufficient access
- * to driver and config data, such that user-mode programs can
- * be developed to handle chipset tuning for most PCI interfaces.
- * This should provide better utilities, and less kernel bloat.
- *
- * The entire pci config space for a PCI interface chipset can be
- * retrieved by just reading it.  e.g.    "cat /proc/ide3/config"
- *
- * To modify registers *safely*, do something like:
- *   echo "P40:88" >/proc/ide/ide3/config
- * That expression writes 0x88 to pci config register 0x40
- * on the chip which controls ide3.  Multiple tuples can be issued,
- * and the writes will be completed as an atomic set:
- *   echo "P40:88 P41:35 P42:00 P43:00" >/proc/ide/ide3/config
- *
- * All numbers must be specified using pairs of ascii hex digits.
- * It is important to note that these writes will be performed
- * after waiting for the IDE controller (both interfaces)
- * to be completely idle, to ensure no corruption of I/O in progress.
- *
- * Non-PCI registers can also be written, using "R" in place of "P"
- * in the above examples.  The size of the port transfer is determined
- * by the number of pairs of hex digits given for the data.  If a two
- * digit value is given, the write will be a byte operation; if four
- * digits are used, the write will be performed as a 16-bit operation;
- * and if eight digits are specified, a 32-bit "dword" write will be
- * performed.  Odd numbers of digits are not permitted.
- *
- * If there is an error *anywhere* in the string of registers/data
- * then *none* of the writes will be performed.
- *
  * Drive/Driver settings can be retrieved by reading the drive's
  * "settings" files.  e.g.    "cat /proc/ide0/hda/settings"
  * To write a new value "val" into a specific setting "name", use:
@@ -51,10 +20,6 @@
  * returned data as 256 16-bit words.  The "hdparm" utility will
  * be updated someday soon to use this mechanism.
  *
- * Feel free to develop and distribute fancy GUI configuration
- * utilities for your favorite PCI chipsets.  I'll be working on
- * one for the Promise 20246 someday soon.  -ml
- *
  */
 
 #include <linux/config.h>
@@ -74,227 +39,6 @@
 
 #include <asm/io.h>
 
-static int proc_ide_write_config(struct file *file, const char __user *buffer,
-				 unsigned long count, void *data)
-{
-	ide_hwif_t	*hwif = (ide_hwif_t *)data;
-	ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup);
-	ide_hwgroup_t *mategroup = NULL;
-	unsigned long timeout;
-	unsigned long flags;
-	const char *start = NULL, *msg = NULL;
-	struct entry { u32 val; u16 reg; u8 size; u8 pci; } *prog, *q, *r;
-	int want_pci = 0;
-	char *buf, *s;
-	int err;
-
-	if (hwif->mate && hwif->mate->hwgroup)
-		mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
-
-	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-		return -EACCES;
-
-	if (count >= PAGE_SIZE)
-		return -EINVAL;
-
-	s = buf = (char *)__get_free_page(GFP_USER);
-	if (!buf)
-		return -ENOMEM;
-
-	err = -ENOMEM;
-	q = prog = (struct entry *)__get_free_page(GFP_USER);
-	if (!prog)
-		goto out;
-
-	err = -EFAULT;
-	if (copy_from_user(buf, buffer, count))
-		goto out1;
-
-	buf[count] = '\0';
-
-	while (isspace(*s))
-		s++;
-
-	while (*s) {
-		char *p;
-		int digits;
-
-		start = s;
-
-		if ((char *)(q + 1) > (char *)prog + PAGE_SIZE) {
-			msg = "too many entries";
-			goto parse_error;
-		}
-
-		switch (*s++) {
-			case 'R':	q->pci = 0;
-					break;
-			case 'P':	q->pci = 1;
-					want_pci = 1;
-					break;
-			default:	msg = "expected 'R' or 'P'";
-					goto parse_error;
-		}
-
-		q->reg = simple_strtoul(s, &p, 16);
-		digits = p - s;
-		if (!digits || digits > 4 || (q->pci && q->reg > 0xff)) {
-			msg = "bad/missing register number";
-			goto parse_error;
-		}
-		if (*p++ != ':') {
-			msg = "missing ':'";
-			goto parse_error;
-		}
-		q->val = simple_strtoul(p, &s, 16);
-		digits = s - p;
-		if (digits != 2 && digits != 4 && digits != 8) {
-			msg = "bad data, 2/4/8 digits required";
-			goto parse_error;
-		}
-		q->size = digits / 2;
-
-		if (q->pci) {
-#ifdef CONFIG_BLK_DEV_IDEPCI
-			if (q->reg & (q->size - 1)) {
-				msg = "misaligned access";
-				goto parse_error;
-			}
-#else
-			msg = "not a PCI device";
-			goto parse_error;
-#endif	/* CONFIG_BLK_DEV_IDEPCI */
-		}
-
-		q++;
-
-		if (*s && !isspace(*s++)) {
-			msg = "expected whitespace after data";
-			goto parse_error;
-		}
-		while (isspace(*s))
-			s++;
-	}
-
-	/*
-	 * What follows below is fucking insane, even for IDE people.
-	 * For now I've dealt with the obvious problems on the parsing
-	 * side, but IMNSHO we should simply remove the write access
-	 * to /proc/ide/.../config, killing that FPOS completely.
-	 */
-
-	err = -EBUSY;
-	timeout = jiffies + (3 * HZ);
-	spin_lock_irqsave(&ide_lock, flags);
-	while (mygroup->busy ||
-	       (mategroup && mategroup->busy)) {
-		spin_unlock_irqrestore(&ide_lock, flags);
-		if (time_after(jiffies, timeout)) {
-			printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name);
-			goto out1;
-		}
-		spin_lock_irqsave(&ide_lock, flags);
-	}
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	if (want_pci && (!hwif->pci_dev || hwif->pci_dev->vendor)) {
-		spin_unlock_irqrestore(&ide_lock, flags);
-		printk("proc_ide: PCI registers not accessible for %s\n",
-			hwif->name);
-		err = -EINVAL;
-		goto out1;
-	}
-#endif	/* CONFIG_BLK_DEV_IDEPCI */
-
-	for (r = prog; r < q; r++) {
-		unsigned int reg = r->reg, val = r->val;
-		if (r->pci) {
-#ifdef CONFIG_BLK_DEV_IDEPCI
-			int rc = 0;
-			struct pci_dev *dev = hwif->pci_dev;
-			switch (q->size) {
-				case 1:	msg = "byte";
-					rc = pci_write_config_byte(dev, reg, val);
-					break;
-				case 2:	msg = "word";
-					rc = pci_write_config_word(dev, reg, val);
-					break;
-				case 4:	msg = "dword";
-					rc = pci_write_config_dword(dev, reg, val);
-					break;
-			}
-			if (rc) {
-				spin_unlock_irqrestore(&ide_lock, flags);
-				printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n",
-					msg, dev->bus->number, dev->devfn, reg, val);
-				printk("proc_ide_write_config: error %d\n", rc);
-				err = -EIO;
-				goto out1;
-			}
-#endif	/* CONFIG_BLK_DEV_IDEPCI */
-		} else {	/* not pci */
-			switch (r->size) {
-				case 1:	hwif->OUTB(val, reg);
-					break;
-				case 2:	hwif->OUTW(val, reg);
-					break;
-				case 4:	hwif->OUTL(val, reg);
-					break;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&ide_lock, flags);
-	err = count;
-out1:
-	free_page((unsigned long)prog);
-out:
-	free_page((unsigned long)buf);
-	return err;
-
-parse_error:
-	printk("parse error\n");
-	printk("proc_ide: error: %s: '%s'\n", msg, start);
-	err = -EINVAL;
-	goto out1;
-}
-
-static int proc_ide_read_config
-	(char *page, char **start, off_t off, int count, int *eof, void *data)
-{
-	char		*out = page;
-	int		len;
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-	ide_hwif_t	*hwif = (ide_hwif_t *)data;
-	struct pci_dev	*dev = hwif->pci_dev;
-	if ((hwif->pci_dev && hwif->pci_dev->vendor) && dev && dev->bus) {
-		int reg = 0;
-
-		out += sprintf(out, "pci bus %02x device %02x vendor %04x "
-				"device %04x channel %d\n",
-			dev->bus->number, dev->devfn,
-			hwif->pci_dev->vendor, hwif->pci_dev->device,
-			hwif->channel);
-		do {
-			u8 val;
-			int rc = pci_read_config_byte(dev, reg, &val);
-			if (rc) {
-				printk("proc_ide_read_config: error %d reading"
-					" bus %02x dev %02x reg 0x%02x\n",
-					rc, dev->bus->number, dev->devfn, reg);
-				out += sprintf(out, "??%c",
-					(++reg & 0xf) ? ' ' : '\n');
-			} else
-				out += sprintf(out, "%02x%c",
-					val, (++reg & 0xf) ? ' ' : '\n');
-		} while (reg < 0x100);
-	} else
-#endif	/* CONFIG_BLK_DEV_IDEPCI */
-		out += sprintf(out, "(none)\n");
-	len = out - page;
-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-}
-
 static int proc_ide_read_imodel
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -687,7 +431,6 @@
 
 static ide_proc_entry_t hwif_entries[] = {
 	{ "channel",	S_IFREG|S_IRUGO,	proc_ide_read_channel,	NULL },
-	{ "config",	S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config,	proc_ide_write_config },
 	{ "mate",	S_IFREG|S_IRUGO,	proc_ide_read_mate,	NULL },
 	{ "model",	S_IFREG|S_IRUGO,	proc_ide_read_imodel,	NULL },
 	{ NULL,	0, NULL, NULL }
diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/ide/ide-taskfile.c	2004-10-28 22:25:56 -07:00
@@ -63,17 +63,14 @@
 	}
 }
 
-
-void taskfile_input_data (ide_drive_t *drive, void *buffer, u32 wcount)
+static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
 {
 	HWIF(drive)->ata_input_data(drive, buffer, wcount);
 	if (drive->bswap)
 		ata_bswap_data(buffer, wcount);
 }
 
-EXPORT_SYMBOL(taskfile_input_data);
-
-void taskfile_output_data (ide_drive_t *drive, void *buffer, u32 wcount)
+static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
 {
 	if (drive->bswap) {
 		ata_bswap_data(buffer, wcount);
@@ -84,8 +81,6 @@
 	}
 }
 
-EXPORT_SYMBOL(taskfile_output_data);
-
 int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
 {
 	ide_task_t args;
@@ -101,8 +96,6 @@
 	return ide_raw_taskfile(drive, &args, buf);
 }
 
-EXPORT_SYMBOL(taskfile_lib_get_identify);
-
 ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
@@ -304,7 +297,7 @@
 	else
 		taskfile_input_data(drive, buf, SECTOR_WORDS);
 
-	kunmap_atomic(page, KM_BIO_SRC_IRQ);
+	kunmap_atomic(buf, KM_BIO_SRC_IRQ);
 #ifdef CONFIG_HIGHMEM
 	local_irq_restore(flags);
 #endif
@@ -470,7 +463,7 @@
 }
 EXPORT_SYMBOL(pre_task_out_intr);
 
-int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
+static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
 {
 	struct request rq;
 
@@ -507,8 +500,6 @@
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
-EXPORT_SYMBOL(ide_diag_taskfile);
-
 int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
 {
 	return ide_diag_taskfile(drive, args, 0, buf);
@@ -516,10 +507,6 @@
 
 EXPORT_SYMBOL(ide_raw_taskfile);
 
-#define MAX_DMA		(256*SECTOR_WORDS)
-
-ide_startstop_t flagged_taskfile(ide_drive_t *, ide_task_t *);
-
 int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
 {
 	ide_task_request_t	*req_task;
@@ -670,8 +657,6 @@
 	return err;
 }
 
-EXPORT_SYMBOL(ide_taskfile_ioctl);
-
 int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
 {
 	struct request rq;
@@ -689,8 +674,6 @@
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
-EXPORT_SYMBOL(ide_wait_cmd);
-
 /*
  * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
  */
@@ -748,9 +731,7 @@
 	return err;
 }
 
-EXPORT_SYMBOL(ide_cmd_ioctl);
-
-int ide_wait_cmd_task (ide_drive_t *drive, u8 *buf)
+static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
 {
 	struct request rq;
 
@@ -760,8 +741,6 @@
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
-EXPORT_SYMBOL(ide_wait_cmd_task);
-
 /*
  * FIXME : this needs to map into at taskfile. <andre@linux-ide.org>
  */
@@ -780,8 +759,6 @@
 	return err;
 }
 
-EXPORT_SYMBOL(ide_task_ioctl);
-
 /*
  * NOTICE: This is additions from IBM to provide a discrete interface,
  * for selective taskregister access operations.  Nice JOB Klaus!!!
@@ -902,5 +879,3 @@
 
 	return ide_started;
 }
-
-EXPORT_SYMBOL(flagged_taskfile);
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/ide.c	2004-10-28 22:25:57 -07:00
@@ -694,7 +694,6 @@
 	hwif->ide_dma_test_irq		= tmp_hwif->ide_dma_test_irq;
 	hwif->ide_dma_host_on		= tmp_hwif->ide_dma_host_on;
 	hwif->ide_dma_host_off		= tmp_hwif->ide_dma_host_off;
-	hwif->ide_dma_verbose		= tmp_hwif->ide_dma_verbose;
 	hwif->ide_dma_lostirq		= tmp_hwif->ide_dma_lostirq;
 	hwif->ide_dma_timeout		= tmp_hwif->ide_dma_timeout;
 
diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
--- a/drivers/ide/pci/aec62xx.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/aec62xx.c	2004-10-28 22:25:59 -07:00
@@ -18,52 +18,7 @@
 
 #include "aec62xx.h"
 
-#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 aec62xx_proc = 0;
-
-#define AEC_MAX_DEVS		5
-
-static struct pci_dev *aec_devs[AEC_MAX_DEVS];
-static int n_aec_devs;
-
-static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	char *chipset_nums[] = {"error", "error", "error", "error",
-				"error", "error", "850UF",   "860",
-				 "860R",   "865",  "865R", "error"  };
-	int len;
-	int i;
-
-	for (i = 0; i < n_aec_devs; i++) {
-		struct pci_dev *dev	= aec_devs[i];
-		unsigned long iobase = pci_resource_start(dev, 4);
-		u8 c0 = 0, c1 = 0, art	= 0;
-
-		c0 = inb(iobase + 0x02);
-		c1 = inb(iobase + 0x0a);
-
-		p += sprintf(p, "\nController: %d\n", i);
-		p += sprintf(p, "Chipset: AEC%s\n", chipset_nums[dev->device]);
-
-		p += sprintf(p, "--------------- Primary Channel "
-				"---------------- Secondary Channel "
-				"-------------\n");
-		(void) pci_read_config_byte(dev, 0x4a, &art);
-		p += sprintf(p, "                %sabled ",
-			(art&0x02)?" en":"dis");
-		p += sprintf(p, "                        %sabled\n",
-			(art&0x04)?" en":"dis");
-		p += sprintf(p, "--------------- drive0 --------- drive1 "
-				"-------- drive0 ---------- drive1 ------\n");
-		p += sprintf(p, "DMA enabled:    %s              %s ",
-			(c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ");
-		p += sprintf(p, "            %s               %s\n",
-			(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
-
+#if 0
 		if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
 			(void) pci_read_config_byte(dev, 0x54, &art);
 			p += sprintf(p, "DMA Mode:       %s(%s)",
@@ -79,59 +34,7 @@
 				(c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
 				(art&0x80)?"2":(art&0x40)?"1":"0");
 		} else {
-			/*
-			 * case PCI_DEVICE_ID_ARTOP_ATP860:
-			 * case PCI_DEVICE_ID_ARTOP_ATP860R:
-			 * case PCI_DEVICE_ID_ARTOP_ATP865:
-			 * case PCI_DEVICE_ID_ARTOP_ATP865R:
-			 */
-			(void) pci_read_config_byte(dev, 0x44, &art);
-			p += sprintf(p, "DMA Mode:       %s(%s)",
-				(c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
-				((art&0x07)==0x07)?"6":
-				((art&0x06)==0x06)?"5":
-				((art&0x05)==0x05)?"4":
-				((art&0x04)==0x04)?"3":
-				((art&0x03)==0x03)?"2":
-				((art&0x02)==0x02)?"1":
-				((art&0x01)==0x01)?"0":"?");
-			p += sprintf(p, "          %s(%s)",
-				(c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
-				((art&0x70)==0x70)?"6":
-				((art&0x60)==0x60)?"5":
-				((art&0x50)==0x50)?"4":
-				((art&0x40)==0x40)?"3":
-				((art&0x30)==0x30)?"2":
-				((art&0x20)==0x20)?"1":
-				((art&0x10)==0x10)?"0":"?");
-			(void) pci_read_config_byte(dev, 0x45, &art);
-			p += sprintf(p, "         %s(%s)",
-				(c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
-				((art&0x07)==0x07)?"6":
-				((art&0x06)==0x06)?"5":
-				((art&0x05)==0x05)?"4":
-				((art&0x04)==0x04)?"3":
-				((art&0x03)==0x03)?"2":
-				((art&0x02)==0x02)?"1":
-				((art&0x01)==0x01)?"0":"?");
-			p += sprintf(p, "           %s(%s)\n",
-				(c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
-				((art&0x70)==0x70)?"6":
-				((art&0x60)==0x60)?"5":
-				((art&0x50)==0x50)?"4":
-				((art&0x40)==0x40)?"3":
-				((art&0x30)==0x30)?"2":
-				((art&0x20)==0x20)?"1":
-				((art&0x10)==0x10)?"0":"?");
-		}
-	}
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif	/* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */
+#endif
 
 /*
  * TO DO: active tuning and correction of cards without a bios.
@@ -286,36 +189,16 @@
 	struct hd_driveid *id	= drive->id;
 
 	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 */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!config_chipset_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 (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		aec62xx_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -374,15 +257,6 @@
 		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
 		printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
 	}
-
-#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
-	aec_devs[n_aec_devs++] = dev;
-
-	if (!aec62xx_proc) {
-		aec62xx_proc = 1;
-		ide_pci_create_host_proc("aec62xx", aec62xx_get_info);
-	}
-#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */
 
 	if (bus_speed <= 33)
 		pci_set_drvdata(dev, (void *) aec6xxx_33_base);
diff -Nru a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h
--- a/drivers/ide/pci/aec62xx.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/pci/aec62xx.h	2004-10-28 22:25:58 -07:00
@@ -5,8 +5,6 @@
 #include <linux/pci.h>
 #include <linux/ide.h>
 
-#define DISPLAY_AEC62XX_TIMINGS
-
 struct chipset_bus_clock_list_entry {
 	byte		xfer_speed;
 	byte		chipset_settings;
diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
--- a/drivers/ide/pci/amd74xx.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/amd74xx.c	2004-10-28 22:25:59 -07:00
@@ -416,8 +416,8 @@
 {
 	int i;
 
-	if (!hwif->irq)
-		hwif->irq = hwif->channel ? 15 : 14;
+	if (hwif->irq == 0) /* 0 is bogus but will do for now */
+		hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel);
 
 	hwif->autodma = 0;
 
diff -Nru a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
--- a/drivers/ide/pci/atiixp.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/pci/atiixp.c	2004-10-28 22:25:58 -07:00
@@ -47,102 +47,6 @@
 
 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
@@ -357,36 +261,16 @@
 	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;
+
+		if (ide_use_dma(drive)) {
+			if (atiixp_config_drive_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} 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);
@@ -397,27 +281,6 @@
 }
 
 /**
- *	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
  *
@@ -459,7 +322,6 @@
 static ide_pci_device_t atiixp_pci_info[] __devinitdata = {
 	{	/* 0 */
 		.name		= "ATIIXP",
-		.init_chipset	= init_chipset_atiixp,
 		.init_hwif	= init_hwif_atiixp,
 		.channels	= 2,
 		.autodma	= AUTODMA,
diff -Nru a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
--- a/drivers/ide/pci/cmd64x.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/cmd64x.c	2004-10-28 22:25:59 -07:00
@@ -441,36 +441,16 @@
 	struct hd_driveid *id	= drive->id;
 
 	if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (__ide_dma_bad_drive(drive))
-			goto fast_ata_pio;
-		if ((id->field_valid & 4) && cmd64x_ratemask(drive)) {
-			if (id->dma_ultra & hwif->ultra_mask) {
-				/* Force if Capable UltraDMA */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!config_chipset_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 (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		config_chipset_for_pio(drive, 1);
 		return hwif->ide_dma_off_quietly(drive);
 	}
diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
--- a/drivers/ide/pci/cs5520.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/ide/pci/cs5520.c	2004-10-28 22:25:56 -07:00
@@ -51,57 +51,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#define DISPLAY_CS5520_TIMINGS
-
-#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 cs5520_proc = 0;
-static struct pci_dev *bmide_dev;
-
-static int cs5520_get_info(char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	unsigned long bmiba = pci_resource_start(bmide_dev, 2);
-	int len;
-	u8 c0 = 0, c1 = 0;
-	u16 reg16;
-	u32 reg32;
-
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-	c0 = inb(bmiba + 0x02);
-	c1 = inb(bmiba + 0x0a);
-	
-	p += sprintf(p, "\nCyrix CS55x0 IDE\n");
-	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, "\n\nTimings: \n");
-	
-	pci_read_config_word(bmide_dev, 0x62, &reg16);
-	p += sprintf(p, "8bit CAT/CRT   : %04x\n", reg16);
-	pci_read_config_dword(bmide_dev, 0x64, &reg32);
-	p += sprintf(p, "16bit Primary  : %08x\n", reg32);
-	pci_read_config_dword(bmide_dev, 0x68, &reg32);
-	p += sprintf(p, "16bit Secondary: %08x\n", reg32);
-	
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-
-#endif
-
 struct pio_clocks
 {
 	int address;
@@ -144,12 +93,14 @@
 	printk("PIO clocking = %d\n", pio);
 	
 	/* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
-	
-	/* 8bit command timing for channel */
+
+	/* 8bit CAT/CRT - 8bit command timing for channel */
 	pci_write_config_byte(pdev, 0x62 + controller, 
 		(cs5520_pio_clocks[pio].recovery << 4) |
 		(cs5520_pio_clocks[pio].assert));
-		
+
+	/* 0x64 - 16bit Primary, 0x68 - 16bit Secondary */
+
 	/* FIXME: should these use address ? */
 	/* Data read timing */
 	pci_write_config_byte(pdev, 0x64 + 4*controller + (drive->dn&1),
@@ -188,19 +139,6 @@
 	/* Then tell the core to use DMA operations */
 	return hwif->ide_dma_on(drive);
 }
-	
-	
-static unsigned int __devinit init_chipset_cs5520(struct pci_dev *dev, const char *name)
-{
-#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!cs5520_proc) {
-		cs5520_proc = 1;
-		bmide_dev = dev;
-		ide_pci_create_host_proc("cs5520", cs5520_get_info);
-	}
-#endif /* DISPLAY_CS5520_TIMINGS && CONFIG_PROC_FS */
-	return 0;
-}
 
 /*
  *	We provide a callback for our nonstandard DMA location
@@ -255,7 +193,6 @@
 #define DECLARE_CS_DEV(name_str)				\
 	{							\
 		.name		= name_str,			\
-		.init_chipset	= init_chipset_cs5520,		\
 		.init_setup_dma = cs5520_init_setup_dma,	\
 		.init_hwif	= init_hwif_cs5520,		\
 		.channels	= 2,				\
@@ -294,7 +231,6 @@
 		printk(KERN_WARNING "cs5520: No suitable DMA available.\n");
 		return -ENODEV;
 	}
-	init_chipset_cs5520(dev, d->name);
 
 	index.all = 0xf0f0;
 
diff -Nru a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
--- a/drivers/ide/pci/cs5530.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/pci/cs5530.c	2004-10-28 22:25:57 -07:00
@@ -31,56 +31,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#define DISPLAY_CS5530_TIMINGS
-
-#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 cs5530_proc = 0;
-
-static struct pci_dev *bmide_dev;
-
-static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	unsigned long bibma = pci_resource_start(bmide_dev, 4);
-	u8  c0 = 0, c1 = 0;
-
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-
-	c0 = inb_p((u16)bibma + 0x02);
-	c1 = inb_p((u16)bibma + 0x0a);
-
-	p += sprintf(p, "\n                                "
-			"Cyrix 5530 Chipset.\n");
-	p += sprintf(p, "--------------- Primary Channel "
-			"---------------- Secondary Channel "
-			"-------------\n");
-	p += sprintf(p, "                %sabled "
-			"                        %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
-	p += sprintf(p, "--------------- drive0 --------- drive1 "
-			"-------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s "
-			"            %s               %s\n",
-			(c0&0x20) ? "yes" : "no ",
-			(c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ",
-			(c1&0x40) ? "yes" : "no " );
-
-	p += sprintf(p, "UDMA\n");
-	p += sprintf(p, "DMA\n");
-	p += sprintf(p, "PIO\n");
-
-	return p-buffer;
-}
-#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
-
 /**
  *	cs5530_xfer_set_mode	-	set a new transfer mode at the drive
  *	@drive: drive to tune
@@ -271,14 +221,6 @@
 {
 	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
 	unsigned long flags;
-
-#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!cs5530_proc) {
-		cs5530_proc = 1;
-		bmide_dev = dev;
-		ide_pci_create_host_proc("cs5530", cs5530_get_info);
-	}
-#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */
 
 	dev = NULL;
 	while ((dev = pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
--- a/drivers/ide/pci/hpt34x.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/pci/hpt34x.c	2004-10-28 22:25:57 -07:00
@@ -130,40 +130,20 @@
 	drive->init_speed = 0;
 
 	if (id && (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 */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && dma)
-					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 (!config_chipset_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 (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
-		}
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
 #ifndef CONFIG_HPT34X_AUTODMA
-		return hwif->ide_dma_off_quietly(drive);
+				return hwif->ide_dma_off_quietly(drive);
 #else
-		return hwif->ide_dma_on(drive);
+				return hwif->ide_dma_on(drive);
 #endif
+		}
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		hpt34x_tune_drive(drive, 255);
 		return hwif->ide_dma_off_quietly(drive);
 	}
diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
--- a/drivers/ide/pci/hpt366.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/hpt366.c	2004-10-28 22:25:59 -07:00
@@ -72,49 +72,6 @@
 
 #include "hpt366.h"
 
-#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-static unsigned int hpt_revision(struct pci_dev *dev);
-static unsigned int hpt_minimum_revision(struct pci_dev *dev, int revision);
-
-#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
-
-static u8 hpt366_proc = 0;
-static struct pci_dev *hpt_devs[HPT366_MAX_DEVS];
-static int n_hpt_devs;
-
-static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p	= buffer;
-	char *chipset_nums[] = {"366", "366",  "368",
-				"370", "370A", "372",
-				"302", "371",  "374" };
-	int i, len;
-
-	p += sprintf(p, "\n                             "
-		"HighPoint HPT366/368/370/372/374\n");
-	for (i = 0; i < n_hpt_devs; i++) {
-		struct pci_dev *dev = hpt_devs[i];
-		unsigned long iobase = dev->resource[4].start;
-		u32 class_rev = hpt_revision(dev);
-		u8 c0, c1;
-
-		p += sprintf(p, "\nController: %d\n", i);
-		p += sprintf(p, "Chipset: HPT%s\n", chipset_nums[class_rev]);
-		p += sprintf(p, "--------------- Primary Channel "
-				"--------------- Secondary Channel "
-				"--------------\n");
-
-		/* get the bus master status registers */
-		c0 = inb(iobase + 0x2);
-		c1 = inb(iobase + 0xa);
-		p += sprintf(p, "Enabled:        %s"
-				"                             %s\n",
-			(c0 & 0x80) ? "no" : "yes",
-			(c1 & 0x80) ? "no" : "yes");
 #if 0
 		if (hpt_minimum_revision(dev, 3)) {
 			u8 cbl;
@@ -128,16 +85,6 @@
 				(cbl & 0x01) ? 33 : 66);
 			p += sprintf(p, "\n");
 		}
-#endif
-		p += sprintf(p, "--------------- drive0 --------- drive1 "
-				"------- drive0 ---------- drive1 -------\n");
-		p += sprintf(p, "DMA capable:    %s              %s" 
-				"            %s               %s\n",
-			(c0 & 0x20) ? "yes" : "no ", 
-			(c0 & 0x40) ? "yes" : "no ",
-			(c1 & 0x20) ? "yes" : "no ", 
-			(c1 & 0x40) ? "yes" : "no ");
-
 		{
 			u8 c2, c3;
 			/* older revs don't have these registers mapped 
@@ -159,15 +106,7 @@
 					(c3 & 0x80) ? "PIO " : "off ");
 		}
 	}
-	p += sprintf(p, "\n");
-
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */
+#endif
 
 static u32 hpt_revision (struct pci_dev *dev)
 {
@@ -521,35 +460,16 @@
 	drive->init_speed = 0;
 
 	if (id && (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 */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					goto try_dma_modes;
-			}
-		} else if (id->field_valid & 2) {
-try_dma_modes:
-			if (id->dma_mword & hwif->mwdma_mask) {
-				/* Force if Capable regular DMA modes */
-				if (!config_chipset_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 (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		hpt3xx_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -1105,15 +1025,6 @@
 	}
 	if (ret)
 		return ret;
-	
-#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
-	hpt_devs[n_hpt_devs++] = dev;
-
-	if (!hpt366_proc) {
-		hpt366_proc = 1;
-		ide_pci_create_host_proc("hpt366", hpt366_get_info);
-	}
-#endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */
 
 	return dev->irq;
 }
diff -Nru a/drivers/ide/pci/hpt366.h b/drivers/ide/pci/hpt366.h
--- a/drivers/ide/pci/hpt366.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/pci/hpt366.h	2004-10-28 22:25:58 -07:00
@@ -5,8 +5,6 @@
 #include <linux/pci.h>
 #include <linux/ide.h>
 
-#define DISPLAY_HPT366_TIMINGS
-
 /* various tuning parameters */
 #define HPT_RESET_STATE_ENGINE
 #undef HPT_DELAY_INTERRUPT
diff -Nru a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c
--- a/drivers/ide/pci/it8172.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/it8172.c	2004-10-28 22:25:59 -07:00
@@ -201,36 +201,16 @@
 	drive->init_speed = 0;
 
 	if (id && (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 */
-				int dma = it8172_config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!it8172_config_chipset_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 (!it8172_config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (it8172_config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		it8172_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
--- a/drivers/ide/pci/pdc202xx_new.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/pdc202xx_new.c	2004-10-28 22:25:59 -07:00
@@ -41,61 +41,6 @@
 
 #define PDC202_DEBUG_CABLE	0
 
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 pdcnew_proc = 0;
-#define PDC202_MAX_DEVS		5
-static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS];
-static int n_pdc202_devs;
-
-static char * pdcnew_info(char *buf, struct pci_dev *dev)
-{
-	char *p = buf;
-
-	p += sprintf(p, "\n                                ");
-	switch(dev->device) {
-		case PCI_DEVICE_ID_PROMISE_20277:
-			p += sprintf(p, "SBFastTrak 133 Lite"); break;
-		case PCI_DEVICE_ID_PROMISE_20276:
-			p += sprintf(p, "MBFastTrak 133 Lite"); break;
-		case PCI_DEVICE_ID_PROMISE_20275:
-			p += sprintf(p, "MBUltra133"); break;
-		case PCI_DEVICE_ID_PROMISE_20271:
-			p += sprintf(p, "FastTrak TX2000"); break;
-		case PCI_DEVICE_ID_PROMISE_20270:
-			p += sprintf(p, "FastTrak LP/TX2/TX4"); break;
-		case PCI_DEVICE_ID_PROMISE_20269:
-			p += sprintf(p, "Ultra133 TX2"); break;
-		case PCI_DEVICE_ID_PROMISE_20268:
-			p += sprintf(p, "Ultra100 TX2"); break;
-		default:
-			p += sprintf(p, "Ultra series"); break;
-			break;
-	}
-	p += sprintf(p, " Chipset.\n");
-	return (char *)p;
-}
-
-static int pdcnew_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	int i, len;
-
-	for (i = 0; i < n_pdc202_devs; i++) {
-		struct pci_dev *dev	= pdc202_devs[i];
-		p = pdcnew_info(buffer, dev);
-	}
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-
 static u8 pdcnew_ratemask (ide_drive_t *drive)
 {
 	u8 mode;
@@ -244,37 +189,16 @@
 	drive->init_speed = 0;
 
 	if (id && (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 */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!config_chipset_for_dma(drive))
-					goto no_dma_set;
-			}
-		} else if (__ide_dma_good_drive(drive) &&
-			    (id->eide_dma_time < 150)) {
-				goto no_dma_set;
-			/* Consult the list of known "good" drives */
-			if (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -416,15 +340,6 @@
 #ifdef CONFIG_PPC_PMAC
 	apple_kiwi_init(dev);
 #endif
-
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-	pdc202_devs[n_pdc202_devs++] = dev;
-
-	if (!pdcnew_proc) {
-		pdcnew_proc = 1;
-		ide_pci_create_host_proc("pdcnew", pdcnew_get_info);
-	}
-#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
 
 	return dev->irq;
 }
diff -Nru a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h
--- a/drivers/ide/pci/pdc202xx_new.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/ide/pci/pdc202xx_new.h	2004-10-28 22:25:56 -07:00
@@ -43,8 +43,6 @@
 		set_2regs(0x13,(c));			\
 	} while(0)
 
-#define DISPLAY_PDC202XX_TIMINGS
-
 static void init_setup_pdcnew(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_pdc20270(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d);
diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
--- a/drivers/ide/pci/pdc202xx_old.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/pdc202xx_old.c	2004-10-28 22:25:59 -07:00
@@ -50,68 +50,14 @@
 
 #define PDC202_DEBUG_CABLE	0
 
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 pdc202xx_proc = 0;
-#define PDC202_MAX_DEVS		5
-static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS];
-static int n_pdc202_devs;
-
-static char * pdc202xx_info (char *buf, struct pci_dev *dev)
-{
-	char *p = buf;
-
+#if 0
 	unsigned long bibma  = pci_resource_start(dev, 4);
-	u32 reg60h = 0, reg64h = 0, reg68h = 0, reg6ch = 0;
-	u16 reg50h = 0, pmask = (1<<10), smask = (1<<11);
 	u8 hi = 0, lo = 0;
 
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
-	u8 c0	= inb_p((u16)bibma + 0x02);
-	u8 c1	= inb_p((u16)bibma + 0x0a);
-
-	u8 sc11	= inb_p((u16)bibma + 0x11);
-	u8 sc1a	= inb_p((u16)bibma + 0x1a);
-	u8 sc1b	= inb_p((u16)bibma + 0x1b);
 	u8 sc1c	= inb_p((u16)bibma + 0x1c); 
-	u8 sc1d	= inb_p((u16)bibma + 0x1d);
 	u8 sc1e	= inb_p((u16)bibma + 0x1e);
 	u8 sc1f	= inb_p((u16)bibma + 0x1f);
 
-	pci_read_config_word(dev, 0x50, &reg50h);
-	pci_read_config_dword(dev, 0x60, &reg60h);
-	pci_read_config_dword(dev, 0x64, &reg64h);
-	pci_read_config_dword(dev, 0x68, &reg68h);
-	pci_read_config_dword(dev, 0x6c, &reg6ch);
-
-	p += sprintf(p, "\n                                ");
-	switch(dev->device) {
-		case PCI_DEVICE_ID_PROMISE_20267:
-			p += sprintf(p, "Ultra100"); break;
-		case PCI_DEVICE_ID_PROMISE_20265:
-			p += sprintf(p, "Ultra100 on M/B"); break;
-		case PCI_DEVICE_ID_PROMISE_20263:
-			p += sprintf(p, "FastTrak 66"); break;
-		case PCI_DEVICE_ID_PROMISE_20262:
-			p += sprintf(p, "Ultra66"); break;
-		case PCI_DEVICE_ID_PROMISE_20246:
-			p += sprintf(p, "Ultra33");
-			reg50h |= 0x0c00;
-			break;
-		default:
-			p += sprintf(p, "Ultra Series"); break;
-	}
-	p += sprintf(p, " Chipset.\n");
-
-	p += sprintf(p, "------------------------------- General Status "
-			"---------------------------------\n");
-	p += sprintf(p, "Burst Mode                           : %sabled\n",
-		(sc1f & 0x01) ? "en" : "dis");
 	p += sprintf(p, "Host Mode                            : %s\n",
 		(sc1f & 0x08) ? "Tri-Stated" : "Normal");
 	p += sprintf(p, "Bus Clocking                         : %s\n",
@@ -126,70 +72,7 @@
 	SPLIT_BYTE(sc1e, hi, lo);
 	p += sprintf(p, "Status Polling Period                : %d\n", hi);
 	p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo);
-	p += sprintf(p, "--------------- Primary Channel "
-			"---------------- Secondary Channel "
-			"-------------\n");
-	p += sprintf(p, "                %s                         %s\n",
-		(c0&0x80)?"disabled":"enabled ",
-		(c1&0x80)?"disabled":"enabled ");
-	p += sprintf(p, "66 Clocking     %s                         %s\n",
-		(sc11&0x02)?"enabled ":"disabled",
-		(sc11&0x08)?"enabled ":"disabled");
-	p += sprintf(p, "           Mode %s                      Mode %s\n",
-		(sc1a & 0x01) ? "MASTER" : "PCI   ",
-		(sc1b & 0x01) ? "MASTER" : "PCI   ");
-	p += sprintf(p, "                %s                     %s\n",
-		(sc1d & 0x08) ? "Error       " :
-		((sc1d & 0x05) == 0x05) ? "Not My INTR " :
-		(sc1d & 0x04) ? "Interrupting" :
-		(sc1d & 0x02) ? "FIFO Full   " :
-		(sc1d & 0x01) ? "FIFO Empty  " : "????????????",
-		(sc1d & 0x80) ? "Error       " :
-		((sc1d & 0x50) == 0x50) ? "Not My INTR " :
-		(sc1d & 0x40) ? "Interrupting" :
-		(sc1d & 0x20) ? "FIFO Full   " :
-		(sc1d & 0x10) ? "FIFO Empty  " : "????????????");
-	p += sprintf(p, "--------------- drive0 --------- drive1 "
-			"-------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s "
-			"            %s               %s\n",
-		(c0&0x20)?"yes":"no ", (c0&0x40)?"yes":"no ",
-		(c1&0x20)?"yes":"no ", (c1&0x40)?"yes":"no ");
-	p += sprintf(p, "DMA Mode:       %s           %s "
-			"         %s            %s\n",
-		pdc202xx_ultra_verbose(reg60h, (reg50h & pmask)),
-		pdc202xx_ultra_verbose(reg64h, (reg50h & pmask)),
-		pdc202xx_ultra_verbose(reg68h, (reg50h & smask)),
-		pdc202xx_ultra_verbose(reg6ch, (reg50h & smask)));
-	p += sprintf(p, "PIO Mode:       %s            %s "
-			"          %s            %s\n",
-		pdc202xx_pio_verbose(reg60h),
-		pdc202xx_pio_verbose(reg64h),
-		pdc202xx_pio_verbose(reg68h),
-		pdc202xx_pio_verbose(reg6ch));
-#if 0
-	p += sprintf(p, "--------------- Can ATAPI DMA ---------------\n");
 #endif
-	return (char *)p;
-}
-
-static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	int i, len;
-
-	for (i = 0; i < n_pdc202_devs; i++) {
-		struct pci_dev *dev	= pdc202_devs[i];
-		p = pdc202xx_info(buffer, dev);
-	}
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 
 static u8 pdc202xx_ratemask (ide_drive_t *drive)
 {
@@ -451,37 +334,16 @@
 	drive->init_speed = 0;
 
 	if (id && (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 */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!config_chipset_for_dma(drive))
-					goto no_dma_set;
-			}
-		} else if (__ide_dma_good_drive(drive) &&
-			    (id->eide_dma_time < 150)) {
-				goto no_dma_set;
-			/* Consult the list of known "good" drives */
-			if (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -546,11 +408,13 @@
 	u8 sc1d			= hwif->INB((high_16 + 0x001d));
 
 	if (hwif->channel) {
+		/* bit7: Error, bit6: Interrupting, bit5: FIFO Full, bit4: FIFO Empty */
 		if ((sc1d & 0x50) == 0x50)
 			goto somebody_else;
 		else if ((sc1d & 0x40) == 0x40)
 			return (dma_stat & 4) == 4;
 	} else {
+		/* bit3: Error, bit2: Interrupting, bit1: FIFO Full, bit0: FIFO Empty */
 		if ((sc1d & 0x05) == 0x05)
 			goto somebody_else;
 		else if ((sc1d & 0x04) == 0x04)
@@ -668,15 +532,6 @@
 			name, dev->resource[PCI_ROM_RESOURCE].start);
 	}
 
-#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
-	pdc202_devs[n_pdc202_devs++] = dev;
-
-	if (!pdc202xx_proc) {
-		pdc202xx_proc = 1;
-		ide_pci_create_host_proc("pdc202xx", pdc202xx_get_info);
-	}
-#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */
-
 	/*
 	 * software reset -  this is required because the bios
 	 * will set UDMA timing on if the hdd supports it. The
@@ -709,7 +564,8 @@
 	struct pci_dev *dev = hwif->pci_dev;
 
 	/* PDC20265 has problems with large LBA48 requests */
-	if (dev->device == PCI_DEVICE_ID_PROMISE_20265)
+	if ((dev->device == PCI_DEVICE_ID_PROMISE_20267) ||
+	    (dev->device == PCI_DEVICE_ID_PROMISE_20265))
 		hwif->rqsize = 256;
 
 	hwif->autodma = 0;
diff -Nru a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h
--- a/drivers/ide/pci/pdc202xx_old.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/ide/pci/pdc202xx_old.h	2004-10-28 22:25:56 -07:00
@@ -23,41 +23,6 @@
 	NULL
 };
 
-static inline u8 *pdc202xx_pio_verbose (u32 drive_pci)
-{
-	if ((drive_pci & 0x000ff000) == 0x000ff000) return("NOTSET");
-	if ((drive_pci & 0x00000401) == 0x00000401) return("PIO 4");
-	if ((drive_pci & 0x00000602) == 0x00000602) return("PIO 3");
-	if ((drive_pci & 0x00000803) == 0x00000803) return("PIO 2");
-	if ((drive_pci & 0x00000C05) == 0x00000C05) return("PIO 1");
-	if ((drive_pci & 0x00001309) == 0x00001309) return("PIO 0");
-	return("PIO ?");
-}
-
-static inline u8 *pdc202xx_dma_verbose (u32 drive_pci)
-{
-	if ((drive_pci & 0x00036000) == 0x00036000) return("MWDMA 2");
-	if ((drive_pci & 0x00046000) == 0x00046000) return("MWDMA 1");
-	if ((drive_pci & 0x00056000) == 0x00056000) return("MWDMA 0");
-	if ((drive_pci & 0x00056000) == 0x00056000) return("SWDMA 2");
-	if ((drive_pci & 0x00068000) == 0x00068000) return("SWDMA 1");
-	if ((drive_pci & 0x000BC000) == 0x000BC000) return("SWDMA 0");
-	return("PIO---");
-}
-
-static inline u8 *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable)
-{
-	if ((drive_pci & 0x000ff000) == 0x000ff000)
-		return("NOTSET");
-	if ((drive_pci & 0x00012000) == 0x00012000)
-		return((slow_cable) ? "UDMA 2" : "UDMA 4");
-	if ((drive_pci & 0x00024000) == 0x00024000)
-		return((slow_cable) ? "UDMA 1" : "UDMA 3");
-	if ((drive_pci & 0x00036000) == 0x00036000)
-		return("UDMA 0");
-	return(pdc202xx_dma_verbose(drive_pci));
-}
-
 /* A Register */
 #define	SYNC_ERRDY_EN	0xC0
 
@@ -97,8 +62,6 @@
 #define	MC2		0x04	/* DMA"C" timing */
 #define	MC1		0x02	/* DMA"C" timing */
 #define	MC0		0x01	/* DMA"C" timing */
-
-#define DISPLAY_PDC202XX_TIMINGS
 
 static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d);
 static void init_setup_pdc20265(struct pci_dev *, ide_pci_device_t *);
diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
--- a/drivers/ide/pci/piix.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/ide/pci/piix.c	2004-10-28 22:25:56 -07:00
@@ -106,165 +106,6 @@
 #include "piix.h"
 
 static int no_piix_dma;
-#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 piix_proc = 0;
-#define PIIX_MAX_DEVS		5
-static struct pci_dev *piix_devs[PIIX_MAX_DEVS];
-static int n_piix_devs;
-
-/**
- *	piix_get_info		-	fill in /proc for PIIX ide
- *	@buffer: buffer to fill
- *	@addr: address of user start in buffer
- *	@offset: offset into 'file'
- *	@count: buffer count
- *
- *	Walks the PIIX devices and outputs summary data on the tuning and
- *	anything else that will help with debugging
- */
- 
-static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	int i;
-
-	for (i = 0; i < n_piix_devs; i++) {
-		struct pci_dev *dev	= piix_devs[i];
-		unsigned long bibma = pci_resource_start(dev, 4);
-	        u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
-		u8  c0 = 0, c1 = 0, reg54 = 0, reg55 = 0;
-		u8  reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
-
-		p += sprintf(p, "\nController: %d\n", i);
-		p += sprintf(p, "\n                                Intel ");
-		switch(dev->device) {
-			case PCI_DEVICE_ID_INTEL_82801EB_1:
-				p += sprintf(p, "PIIX4 SATA 150 ");
-				break;
-			case PCI_DEVICE_ID_INTEL_82801BA_8:
-			case PCI_DEVICE_ID_INTEL_82801BA_9:
-			case PCI_DEVICE_ID_INTEL_82801CA_10:
-			case PCI_DEVICE_ID_INTEL_82801CA_11:
-			case PCI_DEVICE_ID_INTEL_82801DB_10:
-			case PCI_DEVICE_ID_INTEL_82801DB_11:
-			case PCI_DEVICE_ID_INTEL_82801EB_11:
-			case PCI_DEVICE_ID_INTEL_82801E_11:
-			case PCI_DEVICE_ID_INTEL_ESB_2:
-			case PCI_DEVICE_ID_INTEL_ICH6_19:
-				p += sprintf(p, "PIIX4 Ultra 100 ");
-				break;
-			case PCI_DEVICE_ID_INTEL_82372FB_1:
-			case PCI_DEVICE_ID_INTEL_82801AA_1:
-				p += sprintf(p, "PIIX4 Ultra 66 ");
-				break;
-			case PCI_DEVICE_ID_INTEL_82451NX:
-			case PCI_DEVICE_ID_INTEL_82801AB_1:
-			case PCI_DEVICE_ID_INTEL_82443MX_1:
-			case PCI_DEVICE_ID_INTEL_82371AB:
-				p += sprintf(p, "PIIX4 Ultra 33 ");
-				break;
-			case PCI_DEVICE_ID_INTEL_82371SB_1:
-				p += sprintf(p, "PIIX3 ");
-				break;
-			case PCI_DEVICE_ID_INTEL_82371MX:
-				p += sprintf(p, "MPIIX ");
-				break;
-			case PCI_DEVICE_ID_INTEL_82371FB_1:
-			case PCI_DEVICE_ID_INTEL_82371FB_0:
-			default:
-				p += sprintf(p, "PIIX ");
-				break;
-		}
-		p += sprintf(p, "Chipset.\n");
-
-		if (dev->device == PCI_DEVICE_ID_INTEL_82371MX)
-			continue;
-
-		pci_read_config_word(dev, 0x40, &reg40);
-		pci_read_config_word(dev, 0x42, &reg42);
-		pci_read_config_byte(dev, 0x44, &reg44);
-		pci_read_config_byte(dev, 0x48, &reg48);
-		pci_read_config_byte(dev, 0x4a, &reg4a);
-		pci_read_config_byte(dev, 0x4b, &reg4b);
-		pci_read_config_byte(dev, 0x54, &reg54);
-		pci_read_config_byte(dev, 0x55, &reg55);
-
-		psitre = (reg40 & 0x4000) ? 1 : 0;
-		ssitre = (reg42 & 0x4000) ? 1 : 0;
-
-		/*
-		 * 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",
-				(reg48&0x01) ? "yes" : "no ",
-				(reg48&0x02) ? "yes" : "no ",
-				(reg48&0x04) ? "yes" : "no ",
-				(reg48&0x08) ? "yes" : "no " );
-		p += sprintf(p, "UDMA enabled:   %s                %s "
-				"              %s                 %s\n",
-				((reg54&0x11) &&
-				 (reg55&0x10) && (reg4a&0x01)) ? "5" :
-				((reg54&0x11) && (reg4a&0x02)) ? "4" :
-				((reg54&0x11) && (reg4a&0x01)) ? "3" :
-				(reg4a&0x02) ? "2" :
-				(reg4a&0x01) ? "1" :
-				(reg4a&0x00) ? "0" : "X",
-				((reg54&0x22) &&
-				 (reg55&0x20) && (reg4a&0x10)) ? "5" :
-				((reg54&0x22) && (reg4a&0x20)) ? "4" :
-				((reg54&0x22) && (reg4a&0x10)) ? "3" :
-				(reg4a&0x20) ? "2" :
-				(reg4a&0x10) ? "1" :
-				(reg4a&0x00) ? "0" : "X",
-				((reg54&0x44) &&
-				 (reg55&0x40) && (reg4b&0x03)) ? "5" :
-				((reg54&0x44) && (reg4b&0x02)) ? "4" :
-				((reg54&0x44) && (reg4b&0x01)) ? "3" :
-				(reg4b&0x02) ? "2" :
-				(reg4b&0x01) ? "1" :
-				(reg4b&0x00) ? "0" : "X",
-				((reg54&0x88) &&
-				 (reg55&0x80) && (reg4b&0x30)) ? "5" :
-				((reg54&0x88) && (reg4b&0x20)) ? "4" :
-				((reg54&0x88) && (reg4b&0x10)) ? "3" :
-				(reg4b&0x20) ? "2" :
-				(reg4b&0x10) ? "1" :
-				(reg4b&0x00) ? "0" : "X");
-
-		p += sprintf(p, "UDMA\n");
-		p += sprintf(p, "DMA\n");
-		p += sprintf(p, "PIO\n");
-
-		/*
-		 * FIXME.... Add configuration junk data....blah blah......
-		 */
-	}
-	return p-buffer;	 /* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */
 
 /**
  *	piix_ratemask		-	compute rate mask for PIIX IDE
@@ -562,25 +403,11 @@
 
 	if ((id->capability & 1) && drive->autodma) {
 
-		/* Consult the list of known "bad" drives */
-		if (__ide_dma_bad_drive(drive))
-			goto fast_ata_pio;
-
-		/**
-		 * Try to turn DMA on if:
-		 *  - UDMA or EIDE modes are supported or
-		 *  - drive is a known "good" drive
-		 *
-		 * Checks for best mode supported are down later by
-		 * piix_config_drive_for_dma() -> ide_dma_speed()
-		 */
-		if ((id->field_valid & (4 | 2)) ||
-		    (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)) {
+		if (ide_use_dma(drive)) {
 			if (piix_config_drive_for_dma(drive))
 				return hwif->ide_dma_on(drive);
 		}
 
-		/* For some reason DMA wasn't turned on, so try PIO. */
 		goto fast_ata_pio;
 
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
@@ -627,14 +454,6 @@
 			break;
 	}
 
-#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS)
-	piix_devs[n_piix_devs++] = dev;
-
-	if (!piix_proc) {
-		piix_proc = 1;
-		ide_pci_create_host_proc("piix", piix_get_info);
-	}
-#endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */
 	return 0;
 }
 
diff -Nru a/drivers/ide/pci/piix.h b/drivers/ide/pci/piix.h
--- a/drivers/ide/pci/piix.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/pci/piix.h	2004-10-28 22:25:57 -07:00
@@ -5,10 +5,6 @@
 #include <linux/pci.h>
 #include <linux/ide.h>
 
-#define PIIX_DEBUG_DRIVE_INFO		0
-
-#define DISPLAY_PIIX_TIMINGS
-
 static void init_setup_piix(struct pci_dev *, ide_pci_device_t *);
 static unsigned int __devinit init_chipset_piix(struct pci_dev *, const char *);
 static void init_hwif_piix(ide_hwif_t *);
diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
--- a/drivers/ide/pci/sc1200.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/pci/sc1200.c	2004-10-28 22:25:58 -07:00
@@ -67,55 +67,6 @@
 	return pci_clock;
 }
 
-#define DISPLAY_SC1200_TIMINGS
-
-#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static int sc1200_get_info(char *, char **, off_t, int);
-extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-extern char *ide_media_verbose(ide_drive_t *);
-static u8 sc1200_proc = 0;
-
-static struct pci_dev *bmide_dev;
-
-static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	unsigned long bibma = pci_resource_start(bmide_dev, 4);
-	int len;
-	u8  c0 = 0, c1 = 0;
-
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-
-	c0 = inb_p(bibma + 0x02);
-	c1 = inb_p(bibma + 0x0a);
-
-	p += sprintf(p, "\n                               National SCx200 Chipset.\n");
-	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
-	p += sprintf(p, "                %sabled                         %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
-	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
-			(c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
-
-	p += sprintf(p, "UDMA\n");
-	p += sprintf(p, "DMA\n");
-	p += sprintf(p, "PIO\n");
-
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
-
 extern char *ide_xfer_verbose (byte xfer_rate);
 
 /*
@@ -505,21 +456,6 @@
 }
 
 /*
- * Initialize the sc1200 bridge for reliable IDE DMA operation.
- */
-static unsigned int __init init_chipset_sc1200 (struct pci_dev *dev, const char *name)
-{
-#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!bmide_dev) {
-		sc1200_proc = 1;
-		bmide_dev = dev;
-		ide_pci_create_host_proc("sc1200", sc1200_get_info);
-	}
-#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */
-	return 0;
-}
-
-/*
  * This gets invoked by the IDE driver once for each channel,
  * and performs channel-specific pre-initialization before drive probing.
  */
@@ -545,7 +481,6 @@
 
 static ide_pci_device_t sc1200_chipset __devinitdata = {
 	.name		= "SC1200",
-	.init_chipset	= init_chipset_sc1200,
 	.init_hwif	= init_hwif_sc1200,
 	.channels	= 2,
 	.autodma	= AUTODMA,
diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
--- a/drivers/ide/pci/serverworks.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/ide/pci/serverworks.c	2004-10-28 22:25:56 -07:00
@@ -44,164 +44,6 @@
 static u8 svwks_revision = 0;
 static struct pci_dev *isa_dev;
 
-#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 svwks_proc = 0;
-#define SVWKS_MAX_DEVS		2
-static struct pci_dev *svwks_devs[SVWKS_MAX_DEVS];
-static int n_svwks_devs;
-
-static int svwks_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	int i, len;
-
-	p += sprintf(p, "\n                             "
-			"ServerWorks OSB4/CSB5/CSB6\n");
-
-	for (i = 0; i < n_svwks_devs; i++) {
-		struct pci_dev *dev = svwks_devs[i];
-		unsigned long bibma = pci_resource_start(dev, 4);
-		u32 reg40, reg44;
-		u16 reg48, reg56;
-		u8  reg54, c0=0, c1=0;
-
-		pci_read_config_dword(dev, 0x40, &reg40);
-		pci_read_config_dword(dev, 0x44, &reg44);
-		pci_read_config_word(dev, 0x48, &reg48);
-		pci_read_config_byte(dev, 0x54, &reg54);
-		pci_read_config_word(dev, 0x56, &reg56);
-
-		/*
-		 * at that point bibma+0x2 et bibma+0xa are byte registers
-		 * to investigate:
-		 */
-		c0 = inb_p(bibma + 0x02);
-		c1 = inb_p(bibma + 0x0a);
-
-		p += sprintf(p, "\n                            ServerWorks ");
-		switch(dev->device) {
-			case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2:
-			case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE:
-				p += sprintf(p, "CSB6 ");
-				break;
-			case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
-				p += sprintf(p, "CSB5 ");
-				break;
-			case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE:
-				p += sprintf(p, "OSB4 ");
-				break;
-			default:
-				p += sprintf(p, "%04x ", dev->device);
-				break;
-		}
-		p += sprintf(p, "Chipset (rev %02x)\n", svwks_revision);
-
-		p += sprintf(p, "------------------------------- "
-				"General Status "
-				"---------------------------------\n");
-		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",
-			(reg54 & 0x01) ? "yes" : "no ",
-			(reg54 & 0x02) ? "yes" : "no ",
-			(reg54 & 0x04) ? "yes" : "no ",
-			(reg54 & 0x08) ? "yes" : "no " );
-		p += sprintf(p, "UDMA enabled:   %s                %s"
-				"               %s                 %s\n",
-			((reg56&0x0005)==0x0005)?"5":
-				((reg56&0x0004)==0x0004)?"4":
-				((reg56&0x0003)==0x0003)?"3":
-				((reg56&0x0002)==0x0002)?"2":
-				((reg56&0x0001)==0x0001)?"1":
-				((reg56&0x000F))?"?":"0",
-			((reg56&0x0050)==0x0050)?"5":
-				((reg56&0x0040)==0x0040)?"4":
-				((reg56&0x0030)==0x0030)?"3":
-				((reg56&0x0020)==0x0020)?"2":
-				((reg56&0x0010)==0x0010)?"1":
-				((reg56&0x00F0))?"?":"0",
-			((reg56&0x0500)==0x0500)?"5":
-				((reg56&0x0400)==0x0400)?"4":
-				((reg56&0x0300)==0x0300)?"3":
-				((reg56&0x0200)==0x0200)?"2":
-				((reg56&0x0100)==0x0100)?"1":
-				((reg56&0x0F00))?"?":"0",
-			((reg56&0x5000)==0x5000)?"5":
-				((reg56&0x4000)==0x4000)?"4":
-				((reg56&0x3000)==0x3000)?"3":
-				((reg56&0x2000)==0x2000)?"2":
-				((reg56&0x1000)==0x1000)?"1":
-				((reg56&0xF000))?"?":"0");
-		p += sprintf(p, "DMA enabled:    %s                %s"
-				"               %s                 %s\n",
-			((reg44&0x00002000)==0x00002000)?"2":
-				((reg44&0x00002100)==0x00002100)?"1":
-				((reg44&0x00007700)==0x00007700)?"0":
-				((reg44&0x0000FF00)==0x0000FF00)?"X":"?",
-			((reg44&0x00000020)==0x00000020)?"2":
-				((reg44&0x00000021)==0x00000021)?"1":
-				((reg44&0x00000077)==0x00000077)?"0":
-				((reg44&0x000000FF)==0x000000FF)?"X":"?",
-			((reg44&0x20000000)==0x20000000)?"2":
-				((reg44&0x21000000)==0x21000000)?"1":
-				((reg44&0x77000000)==0x77000000)?"0":
-				((reg44&0xFF000000)==0xFF000000)?"X":"?",
-			((reg44&0x00200000)==0x00200000)?"2":
-				((reg44&0x00210000)==0x00210000)?"1":
-				((reg44&0x00770000)==0x00770000)?"0":
-				((reg44&0x00FF0000)==0x00FF0000)?"X":"?");
-
-		p += sprintf(p, "PIO  enabled:   %s                %s"
-				"               %s                 %s\n",
-			((reg40&0x00002000)==0x00002000)?"4":
-				((reg40&0x00002200)==0x00002200)?"3":
-				((reg40&0x00003400)==0x00003400)?"2":
-				((reg40&0x00004700)==0x00004700)?"1":
-				((reg40&0x00005D00)==0x00005D00)?"0":"?",
-			((reg40&0x00000020)==0x00000020)?"4":
-				((reg40&0x00000022)==0x00000022)?"3":
-				((reg40&0x00000034)==0x00000034)?"2":
-				((reg40&0x00000047)==0x00000047)?"1":
-				((reg40&0x0000005D)==0x0000005D)?"0":"?",
-			((reg40&0x20000000)==0x20000000)?"4":
-				((reg40&0x22000000)==0x22000000)?"3":
-				((reg40&0x34000000)==0x34000000)?"2":
-				((reg40&0x47000000)==0x47000000)?"1":
-				((reg40&0x5D000000)==0x5D000000)?"0":"?",
-			((reg40&0x00200000)==0x00200000)?"4":
-				((reg40&0x00220000)==0x00220000)?"3":
-				((reg40&0x00340000)==0x00340000)?"2":
-				((reg40&0x00470000)==0x00470000)?"1":
-				((reg40&0x005D0000)==0x005D0000)?"0":"?");
-
-	}
-	p += sprintf(p, "\n");
-
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static int check_in_drive_lists (ide_drive_t *drive, const char **list)
 {
 	while (*list)
@@ -463,38 +305,16 @@
 	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 */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					goto try_dma_modes;
-			} else
-				/* UDMA disabled by mask, try other DMA modes */
-				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 (!config_chipset_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 (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto no_dma_set;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		config_chipset_for_pio(drive);
 		//	hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
@@ -616,16 +436,6 @@
 			btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
 		pci_write_config_byte(dev, 0x5A, btr);
 	}
-
-
-#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
-	svwks_devs[n_svwks_devs++] = dev;
-
-	if (!svwks_proc) {
-		svwks_proc = 1;
-		ide_pci_create_host_proc("svwks", svwks_get_info);
-	}
-#endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */
 
 	return (dev->irq) ? dev->irq : 0;
 }
diff -Nru a/drivers/ide/pci/serverworks.h b/drivers/ide/pci/serverworks.h
--- a/drivers/ide/pci/serverworks.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/pci/serverworks.h	2004-10-28 22:25:57 -07:00
@@ -21,8 +21,6 @@
 	NULL
 };
 
-#define DISPLAY_SVWKS_TIMINGS	1
-
 static void init_setup_svwks(struct pci_dev *, ide_pci_device_t *);
 static void init_setup_csb6(struct pci_dev *, ide_pci_device_t *);
 static unsigned int init_chipset_svwks(struct pci_dev *, const char *);
diff -Nru a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
--- a/drivers/ide/pci/sgiioc4.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/pci/sgiioc4.c	2004-10-28 22:25:58 -07:00
@@ -332,17 +332,6 @@
 }
 
 static int
-sgiioc4_ide_dma_verbose(ide_drive_t * drive)
-{
-	if (drive->using_dma == 1)
-		printk(", UDMA(16)");
-	else
-		printk(", PIO");
-
-	return 1;
-}
-
-static int
 sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
 {
 	HWIF(drive)->resetproc(drive);
@@ -379,7 +368,7 @@
 }
 
 /* Creates a dma map for the scatter-gather list entries */
-static void __init
+static void __devinit
 ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
 {
 	int num_ports = sizeof (ioc4_dma_regs_t);
@@ -501,10 +490,7 @@
 	unsigned int count = 0, i = 1;
 	struct scatterlist *sg;
 
-	if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
-		hwif->sg_nents = i = ide_raw_build_sglist(drive, rq);
-	else
-		hwif->sg_nents = i = ide_build_sglist(drive, rq);
+	hwif->sg_nents = i = ide_build_sglist(drive, rq);
 
 	if (!i)
 		return 0;	/* sglist of length Zero */
@@ -593,7 +579,7 @@
 	return 0;
 }
 
-static void __init
+static void __devinit
 ide_init_sgiioc4(ide_hwif_t * hwif)
 {
 	hwif->mmio = 2;
@@ -623,13 +609,12 @@
 	hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
 	hwif->ide_dma_host_on = &sgiioc4_ide_dma_host_on;
 	hwif->ide_dma_host_off = &sgiioc4_ide_dma_host_off;
-	hwif->ide_dma_verbose = &sgiioc4_ide_dma_verbose;
 	hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
 	hwif->ide_dma_timeout = &__ide_dma_timeout;
 	hwif->INB = &sgiioc4_INB;
 }
 
-static int __init
+static int __devinit
 sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
 {
 	unsigned long base, ctl, dma_base, irqport;
@@ -692,7 +677,7 @@
 	return 0;
 }
 
-static unsigned int __init
+static unsigned int __devinit
 pci_init_sgiioc4(struct pci_dev *dev, ide_pci_device_t * d)
 {
 	unsigned int class_rev;
@@ -745,13 +730,13 @@
 };
 MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl);
 
-static struct pci_driver driver = {
+static struct pci_driver __devinitdata driver = {
 	.name = "SGI-IOC4_IDE",
 	.id_table = sgiioc4_pci_tbl,
 	.probe = sgiioc4_init_one,
 };
 
-static int
+static int __devinit
 sgiioc4_ide_init(void)
 {
 	return ide_pci_register_driver(&driver);
diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
--- a/drivers/ide/pci/siimage.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/pci/siimage.c	2004-10-28 22:25:57 -07:00
@@ -420,37 +420,16 @@
 	struct hd_driveid *id	= drive->id;
 
 	if ((id->capability & 1) != 0 && drive->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (__ide_dma_bad_drive(drive))
-			goto fast_ata_pio;
-
-		if ((id->field_valid & 4) && siimage_ratemask(drive)) {
-			if (id->dma_ultra & hwif->ultra_mask) {
-				/* Force if Capable UltraDMA */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!config_chipset_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 (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		config_chipset_for_pio(drive, 1);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -554,12 +533,6 @@
 	return 0;
 }
 
-static int siimage_mmio_ide_dma_verbose (ide_drive_t *drive)
-{
-	int temp = __ide_dma_verbose(drive);
-	return temp;
-}
-
 /**
  *	siimage_busproc		-	bus isolation ioctl
  *	@drive: drive to isolate/restore
@@ -1077,7 +1050,6 @@
 
 	if (hwif->mmio) {
 		hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
-		hwif->ide_dma_verbose = &siimage_mmio_ide_dma_verbose;
 	} else {
 		hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq;
 	}
diff -Nru a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
--- a/drivers/ide/pci/sis5513.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ide/pci/sis5513.c	2004-10-28 22:25:58 -07:00
@@ -671,36 +671,16 @@
 	drive->init_speed = 0;
 
 	if (id && (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 */
-				int dma = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!config_chipset_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 (!config_chipset_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (config_chipset_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		sis5513_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
diff -Nru a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
--- a/drivers/ide/pci/slc90e66.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/ide/pci/slc90e66.c	2004-10-28 22:25:59 -07:00
@@ -21,103 +21,6 @@
 
 #include <asm/io.h>
 
-#define DISPLAY_SLC90E66_TIMINGS
-
-#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 slc90e66_proc = 0;
-static struct pci_dev *bmide_dev;
-
-static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	int len;
-	unsigned long bibma = pci_resource_start(bmide_dev, 4);
-	u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0;
-	u8  c0 = 0, c1 = 0;
-	u8  reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0;
-
-	pci_read_config_word(bmide_dev, 0x40, &reg40);
-	pci_read_config_word(bmide_dev, 0x42, &reg42);
-	pci_read_config_byte(bmide_dev, 0x44, &reg44);
-	pci_read_config_byte(bmide_dev, 0x47, &reg47);
-	pci_read_config_byte(bmide_dev, 0x48, &reg48);
-	pci_read_config_byte(bmide_dev, 0x4a, &reg4a);
-	pci_read_config_byte(bmide_dev, 0x4b, &reg4b);
-
-	psitre = (reg40 & 0x4000) ? 1 : 0;
-	ssitre = (reg42 & 0x4000) ? 1 : 0;
-
-        /*
-         * at that point bibma+0x2 et bibma+0xa are byte registers
-         * to investigate:
-         */
-	c0 = inb_p(bibma + 0x02);
-	c1 = inb_p(bibma + 0x0a);
-
-	p += sprintf(p, "                                SLC90E66 Chipset.\n");
-	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",
-			(reg48&0x01) ? "yes" : "no ",
-			(reg48&0x02) ? "yes" : "no ",
-			(reg48&0x04) ? "yes" : "no ",
-			(reg48&0x08) ? "yes" : "no " );
-	p += sprintf(p, "UDMA enabled:   %s                %s "
-			"              %s                 %s\n",
-			((reg4a&0x04)==0x04) ? "4" :
-			((reg4a&0x03)==0x03) ? "3" :
-			(reg4a&0x02) ? "2" :
-			(reg4a&0x01) ? "1" :
-			(reg4a&0x00) ? "0" : "X",
-			((reg4a&0x40)==0x40) ? "4" :
-			((reg4a&0x30)==0x30) ? "3" :
-			(reg4a&0x20) ? "2" :
-			(reg4a&0x10) ? "1" :
-			(reg4a&0x00) ? "0" : "X",
-			((reg4b&0x04)==0x04) ? "4" :
-			((reg4b&0x03)==0x03) ? "3" :
-			(reg4b&0x02) ? "2" :
-			(reg4b&0x01) ? "1" :
-			(reg4b&0x00) ? "0" : "X",
-			((reg4b&0x40)==0x40) ? "4" :
-			((reg4b&0x30)==0x30) ? "3" :
-			(reg4b&0x20) ? "2" :
-			(reg4b&0x10) ? "1" :
-			(reg4b&0x00) ? "0" : "X");
-
-	p += sprintf(p, "UDMA\n");
-	p += sprintf(p, "DMA\n");
-	p += sprintf(p, "PIO\n");
-
-/*
- *	FIXME.... Add configuration junk data....blah blah......
- */
-
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static u8 slc90e66_ratemask (ide_drive_t *drive)
 {
 	u8 mode	= 2;
@@ -236,6 +139,7 @@
 	if (speed >= XFER_UDMA_0) {
 		if (!(reg48 & u_flag))
 			pci_write_config_word(dev, 0x48, reg48|u_flag);
+		/* FIXME: (reg4a & a_speed) ? */
 		if ((reg4a & u_speed) != u_speed) {
 			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
 			pci_read_config_word(dev, 0x4a, &reg4a);
@@ -274,37 +178,16 @@
 	drive->init_speed = 0;
 
 	if (id && (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 */
-				int dma = slc90e66_config_drive_for_dma(drive);
-				if ((id->field_valid & 2) && !dma)
-					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 (!slc90e66_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 (!slc90e66_config_drive_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		if (ide_use_dma(drive)) {
+			if (slc90e66_config_drive_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
 		hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -313,18 +196,6 @@
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
-static unsigned int __init init_chipset_slc90e66 (struct pci_dev *dev, const char *name)
-{
-#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS)
-	if (!slc90e66_proc) {
-		slc90e66_proc = 1;
-		bmide_dev = dev;
-		ide_pci_create_host_proc("slc90e66", slc90e66_get_info);
-	}
-#endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */
-	return 0;
-}
-
 static void __init init_hwif_slc90e66 (ide_hwif_t *hwif)
 {
 	u8 reg47 = 0;
@@ -366,7 +237,6 @@
 
 static ide_pci_device_t slc90e66_chipset __devinitdata = {
 	.name		= "SLC90E66",
-	.init_chipset	= init_chipset_slc90e66,
 	.init_hwif	= init_hwif_slc90e66,
 	.channels	= 2,
 	.autodma	= AUTODMA,
diff -Nru a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
--- a/drivers/ide/pci/triflex.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/ide/pci/triflex.c	2004-10-28 22:25:57 -07:00
@@ -118,25 +118,16 @@
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct hd_driveid *id	= drive->id;
-	
-	if (id && (id->capability & 1) && drive->autodma) {
-		if (__ide_dma_bad_drive(drive))
-			goto tune_pio;
-		if (id->field_valid & 2) {
-			if ((id->dma_mword & hwif->mwdma_mask) ||
-				(id->dma_1word & hwif->swdma_mask)) {
-				if (!triflex_config_drive_for_dma(drive))
-					goto tune_pio;
-			}
-		} else 
-			goto tune_pio;
-	} else {
-tune_pio:
-		hwif->tuneproc(drive, 255);
-		return hwif->ide_dma_off_quietly(drive);
+
+	if ((id->capability & 1) && drive->autodma) {
+		if (ide_use_dma(drive)) {
+			if (triflex_config_drive_for_dma(drive))
+				return hwif->ide_dma_on(drive);
+		}
 	}
 
-	return hwif->ide_dma_on(drive);
+	hwif->tuneproc(drive, 255);
+	return hwif->ide_dma_off_quietly(drive);
 }
 
 static void __init init_hwif_triflex(ide_hwif_t *hwif)
diff -Nru a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
--- a/drivers/ide/ppc/pmac.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/ide/ppc/pmac.c	2004-10-28 22:25:56 -07:00
@@ -1560,56 +1560,6 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
 /*
- * We build & map the sglist for a given request.
- */
-static int __pmac
-pmac_ide_build_sglist(ide_drive_t *drive, struct request *rq)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	struct scatterlist *sg = hwif->sg_table;
-	int nents;
-
-	nents = blk_rq_map_sg(drive->queue, rq, sg);
-		
-	if (rq_data_dir(rq) == READ)
-		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-	else
-		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-
-	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
-}
-
-/*
- * Same as above but for a "raw" taskfile request
- */
-static int __pmac
-pmac_ide_raw_build_sglist(ide_drive_t *drive, struct request *rq)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	struct scatterlist *sg = hwif->sg_table;
-	int nents = 0;
-	ide_task_t *args = rq->special;
-	unsigned char *virt_addr = rq->buffer;
-	int sector_count = rq->nr_sectors;
-
-	if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-	else
-		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-
-	if (sector_count > 128) {
-		sg_init_one(&sg[nents], virt_addr, 128 * SECTOR_SIZE);
-		nents++;
-		virt_addr = virt_addr + (128 * SECTOR_SIZE);
-		sector_count -= 128;
-	}
-	sg_init_one(&sg[nents], virt_addr, sector_count * SECTOR_SIZE);
-	nents++;
-
-	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
-}
-
-/*
  * pmac_ide_build_dmatable builds the DBDMA command list
  * for a transfer and sets the DBDMA channel to point to it.
  */
@@ -1632,11 +1582,8 @@
 	while (readl(&dma->status) & RUN)
 		udelay(1);
 
-	/* Build sglist */
-	if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
-		hwif->sg_nents = i = pmac_ide_raw_build_sglist(drive, rq);
-	else
-		hwif->sg_nents = i = pmac_ide_build_sglist(drive, rq);
+	hwif->sg_nents = i = ide_build_sglist(drive, rq);
+
 	if (!i)
 		return 0;
 
@@ -2078,7 +2025,6 @@
 	hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
 	hwif->ide_dma_host_off = &pmac_ide_dma_host_off;
 	hwif->ide_dma_host_on = &pmac_ide_dma_host_on;
-	hwif->ide_dma_verbose = &__ide_dma_verbose;
 	hwif->ide_dma_timeout = &__ide_dma_timeout;
 	hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
 
diff -Nru a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
--- a/drivers/ieee1394/nodemgr.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/ieee1394/nodemgr.c	2004-10-28 22:25:58 -07:00
@@ -1488,8 +1488,10 @@
 			break;
 		}
 
-		if (hi->kill_me)
+		if (hi->kill_me) {
+			up(&nodemgr_serialize);
 			break;
+		}
 
 		/* Pause for 1/4 second in 1/16 second intervals,
 		 * to make sure things settle down. */
@@ -1513,8 +1515,10 @@
 				i = 0;
 
 			/* Check the kill_me again */
-			if (hi->kill_me)
+			if (hi->kill_me) {
+				up(&nodemgr_serialize);
 				goto caught_signal;
+			}
 		}
 
 		if (!nodemgr_check_irm_capability(host, reset_cycles)) {
diff -Nru a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
--- a/drivers/input/serio/i8042-io.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/input/serio/i8042-io.h	2004-10-28 22:25:56 -07:00
@@ -35,6 +35,7 @@
 # define I8042_AUX_IRQ	12
 #endif
 
+
 /*
  * Register numbers.
  */
@@ -96,7 +97,7 @@
  * On ix86 platforms touching the i8042 data register region can do really
  * bad things. Because of this the region is always reserved on ix86 boxes.
  */
-#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__)
+#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(__mips__) && !defined (CONFIG_PPC64)
 	if (!request_region(I8042_DATA_REG, 16, "i8042"))
 		return -1;
 #endif
@@ -110,12 +111,18 @@
 		i8042_noloop = 1;
 #endif
 
+#if defined(CONFIG_PPC64)
+	if (check_legacy_ioport(I8042_DATA_REG))
+		return -1;
+	if (!request_region(I8042_DATA_REG, 16, "i8042"))
+		return -1;
+#endif
 	return 0;
 }
 
 static inline void i8042_platform_exit(void)
 {
-#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__)
+#if !defined(__i386__) && !defined(__sh__) && !defined(__alpha__) && !defined(__x86_64__) && !defined(CONFIG_PPC64)
 	release_region(I8042_DATA_REG, 16);
 #endif
 }
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	2004-10-28 22:25:59 -07:00
@@ -996,7 +996,7 @@
 
 static int __init hisax_fcpcipnp_init(void)
 {
-	int retval, pci_nr_found;
+	int retval;
 
 	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
 
diff -Nru a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
--- a/drivers/macintosh/therm_adt746x.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/macintosh/therm_adt746x.c	2004-10-28 22:25:59 -07:00
@@ -23,6 +23,7 @@
 #include <linux/smp_lock.h>
 #include <linux/wait.h>
 #include <linux/suspend.h>
+
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -51,16 +52,21 @@
 static int fan_speed = -1;
 
 MODULE_AUTHOR("Colin Leroy <colin@colino.net>");
-MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and Powerbook G4 Alu");
+MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
+		   "Powerbook G4 Alu");
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(limit_adjust,"i");
-MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) by N degrees.");
+MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) "
+		 "by N degrees.");
+
 MODULE_PARM(fan_speed,"i");
-MODULE_PARM_DESC(fan_speed,"Specify fan speed (0-255) when lim < temp < lim+8 (default 128)");
+MODULE_PARM_DESC(fan_speed,"Specify fan speed (0-255) when lim < temp < lim+8 "
+		 "(default 128)");
 
 struct thermostat {
 	struct i2c_client	clt;
+	u8			temps[3];
 	u8			cached_temp[3];
 	u8			initial_limits[3];
 	u8			limits[3];
@@ -74,7 +80,9 @@
 static struct thermostat* thermostat;
 static struct task_struct *thread_therm = NULL;
 
-static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno);
+static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
+				 int busno);
+
 static void write_both_fan_speed(struct thermostat *th, int speed);
 static void write_fan_speed(struct thermostat *th, int speed, int fan);
 
@@ -140,10 +148,11 @@
 		kthread_stop(thread_therm);
 	}
 		
-	printk(KERN_INFO "adt746x: Putting max temperatures back from %d, %d, %d,"
-		" to %d, %d, %d\n",
+	printk(KERN_INFO "adt746x: Putting max temperatures back from "
+			 "%d, %d, %d to %d, %d, %d\n",
 		th->limits[0], th->limits[1], th->limits[2],
-		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2]);
+		th->initial_limits[0], th->initial_limits[1],
+		th->initial_limits[2]);
 	
 	for (i = 0; i < 3; i++)
 		write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
@@ -202,11 +211,11 @@
 	
 	if (th->last_speed[fan] != speed) {
 		if (speed == -1)
-			printk(KERN_INFO "adt746x: Setting speed to: automatic for %s fan.\n",
-				fan?"GPU":"CPU");
+			printk(KERN_INFO "adt746x: Setting speed to automatic "
+				"for %s fan.\n", fan?"GPU":"CPU");
 		else
-			printk(KERN_INFO "adt746x: Setting speed to: %d for %s fan.\n",
-				speed, fan?"GPU":"CPU");
+			printk(KERN_INFO "adt746x: Setting speed to %d "
+				"for %s fan.\n", speed, fan?"GPU":"CPU");
 	} else
 		return;
 	
@@ -217,8 +226,11 @@
 	} else {
 		/* back to automatic */
 		if(therm_type == ADT7460) {
-			manual = read_reg(th, MANUAL_MODE[fan]) & (~MANUAL_MASK);
-			write_reg(th, MANUAL_MODE[fan], manual|REM_CONTROL[fan]);
+			manual = read_reg(th,
+				MANUAL_MODE[fan]) & (~MANUAL_MASK);
+
+			write_reg(th,
+				MANUAL_MODE[fan], manual|REM_CONTROL[fan]);
 		} else {
 			manual = read_reg(th, MANUAL_MODE[fan]);
 			write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK));
@@ -228,99 +240,114 @@
 	th->last_speed[fan] = speed;			
 }
 
-static int monitor_task(void *arg)
+static void read_sensors(struct thermostat *th)
 {
-	struct thermostat* th = arg;
-	u8 temps[3];
-	u8 lims[3];
-	int i;
+	int i = 0;
+
+	for (i = 0; i < 3; i++)
+		th->temps[i]  = read_reg(th, TEMP_REG[i]);
+}
+
 #ifdef DEBUG
-	int mfan_speed;
+static void display_stats(struct thermostat *th)
+{
+	if (th->temps[0] != th->cached_temp[0]
+	||  th->temps[1] != th->cached_temp[1]
+	||  th->temps[2] != th->cached_temp[2]) {
+		printk(KERN_INFO "adt746x: Temperature infos:"
+				 " thermostats: %d,%d,%d;"
+				 " limits: %d,%d,%d;"
+				 " fan speed: %d RPM\n",
+				 th->temps[0], th->temps[1], th->temps[2],
+				 th->limits[0],  th->limits[1],  th->limits[2],
+				 read_fan_speed(th, FAN_SPEED[0]));
+	}
+	th->cached_temp[0] = th->temps[0];
+	th->cached_temp[1] = th->temps[1];
+	th->cached_temp[2] = th->temps[2];
+}
 #endif
+
+static void update_fans_speed (struct thermostat *th)
+{
+	int lastvar = 0; /* last variation, for iBook */
+	int i = 0;
+
+	/* we don't care about local sensor, so we start at sensor 1 */
+	for (i = 1; i < 3; i++) {
+		int started = 0;
+		int fan_number = (therm_type == ADT7460 && i == 2);
+		int var = th->temps[i] - th->limits[i];
+		if (var > 8) {
+			if (th->overriding[fan_number] == 0)
+				printk(KERN_INFO "adt746x: Limit exceeded by "
+					"%d, overriding specified fan speed "
+					"for %s.\n", var,
+					fan_number?"GPU":"CPU");
+
+			th->overriding[fan_number] = 1;
+			write_fan_speed(th, 255, fan_number);
+			started = 1;
+		} else if ((!th->overriding[fan_number] || var < 6) && var > 0) {
+			if (th->overriding[fan_number] == 1)
+				printk(KERN_INFO "adt746x: Limit exceeded by "
+					"%d, setting speed to specified "
+					"for %s.\n", var,
+					fan_number?"GPU":"CPU");
+
+			th->overriding[fan_number] = 0;
+			write_fan_speed(th, fan_speed, fan_number);
+			started = 1;
+		} else if (var < -1) {
+			/* don't stop iBook fan if GPU is cold and CPU is not
+			 * so cold (lastvar >= -1) */
+			if (therm_type == ADT7460 || lastvar < -1 || i == 1) {
+				if (th->last_speed[fan_number] != 0)
+					printk(KERN_INFO "adt746x: Stopping %s "
+						"fan.\n",
+						fan_number?"GPU":"CPU");
+				write_fan_speed(th, 0, fan_number);
+			}
+		}
+
+		lastvar = var;
+
+		if (started && therm_type == ADT7467)
+			return; /* we don't want to re-stop the fan
+				* if CPU is heating and GPU is not */
+	}
+}
+
+static int monitor_task(void *arg)
+{
+	struct thermostat* th = arg;
+
 	while(!kthread_should_stop()) {
 		if (current->flags & PF_FREEZE)
 			refrigerator(PF_FREEZE);
 
 		msleep_interruptible(2000);
 
-		/* Check status */
-		/* local   : chip */
-		/* remote 1: CPU ?*/
-		/* remote 2: GPU ?*/
 #ifndef DEBUG
-		if (fan_speed != -1) {
-#endif
-			for (i = 0; i < 3; i++) {
-				temps[i]  = read_reg(th, TEMP_REG[i]);
-				lims[i]   = th->limits[i];
-			}
-#ifndef DEBUG
-		}
+		if (fan_speed != -1)
+			read_sensors(th);
+#else
+		read_sensors(th);
 #endif		
-		if (fan_speed != -1) {
-			int lastvar = 0;		/* for iBook */
-			for (i = 1; i < 3; i++) {	/* we don't care about local sensor */
-				int started = 0;
-				int fan_number = (therm_type == ADT7460 && i == 2);
-				int var = temps[i] - lims[i];
-				if (var > 8) {
-					if (th->overriding[fan_number] == 0)
-						printk(KERN_INFO "adt746x: Limit exceeded by %d, overriding specified fan speed for %s.\n",
-							var, fan_number?"GPU":"CPU");
-					th->overriding[fan_number] = 1;
-					write_fan_speed(th, 255, fan_number);
-					started = 1;
-				} else if ((!th->overriding[fan_number] || var < 6) && var > 0) {
-					if (th->overriding[fan_number] == 1)
-						printk(KERN_INFO "adt746x: Limit exceeded by %d, setting speed to specified for %s.\n",
-							var, fan_number?"GPU":"CPU");					
-					th->overriding[fan_number] = 0;
-					write_fan_speed(th, fan_speed, fan_number);
-					started = 1;
-				} else if (var < -1) {
-					/* don't stop iBook fan if GPU is cold and CPU is not
-					 * so cold (lastvar >= -1) */
-					if (therm_type == ADT7460 || lastvar < -1 || i == 1) {
-						if (th->last_speed[fan_number] != 0)
-							printk(KERN_INFO "adt746x: Stopping %s fan.\n",
-								fan_number?"GPU":"CPU");
-						write_fan_speed(th, 0, fan_number);
-					}
-				}
-				
-				lastvar = var;
-				
-				if (started && therm_type == ADT7467)
-					break; /* we don't want to re-stop the fan
-						* if CPU is heating and GPU is not */
-			}
-		}
+
+		if (fan_speed != -1)
+			update_fans_speed(th);
+
 #ifdef DEBUG
-		mfan_speed = read_fan_speed(th, FAN_SPEED[0]);
-		/* only one fan in the iBook G4 */
-				
-		if (temps[0] != th->cached_temp[0]
-		||  temps[1] != th->cached_temp[1]
-		||  temps[2] != th->cached_temp[2]) {
-			printk(KERN_INFO "adt746x: Temperature infos:"
-					 " thermostats: %d,%d,%d;"
-					 " limits: %d,%d,%d;"
-					 " fan speed: %d RPM\n",
-				temps[0], temps[1], temps[2],
-				lims[0],  lims[1],  lims[2],
-				mfan_speed);
-		}
-		th->cached_temp[0] = temps[0];
-		th->cached_temp[1] = temps[1];
-		th->cached_temp[2] = temps[2];
-#endif		
+		display_stats(th);
+#endif
+
 	}
 
 	return 0;
 }
 
-static void
-set_limit(struct thermostat *th, int i)
+static void set_limit(struct thermostat *th, int i)
 {
 		/* Set CPU limit higher to avoid powerdowns */ 
 		th->limits[i] = default_limits_chip[i] + limit_adjust;
@@ -329,9 +356,9 @@
 		/* set our limits to normal */
 		th->limits[i] = default_limits_local[i] + limit_adjust;
 }
-	
-static int
-attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno)
+
+static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
+				 int busno)
 {
 	struct thermostat* th;
 	int rc;
@@ -339,9 +366,13 @@
 
 	if (thermostat)
 		return 0;
-	th = (struct thermostat *)kmalloc(sizeof(struct thermostat), GFP_KERNEL);
+
+	th = (struct thermostat *)
+		kmalloc(sizeof(struct thermostat), GFP_KERNEL);
+
 	if (!th)
 		return -ENOMEM;
+
 	memset(th, 0, sizeof(*th));
 	th->clt.addr = addr;
 	th->clt.adapter = adapter;
@@ -351,13 +382,14 @@
 
 	rc = read_reg(th, 0);
 	if (rc < 0) {
-		printk(KERN_ERR "adt746x: Thermostat failed to read config from bus %d !\n",
-			busno);
+		printk(KERN_ERR "adt746x: Thermostat failed to read config "
+				"from bus %d !\n",
+				busno);
 		kfree(th);
 		return -ENODEV;
 	}
+
 	/* force manual control to start the fan quieter */
-	
 	if (fan_speed == -1)
 		fan_speed=128;
 	
@@ -374,14 +406,16 @@
 	}
 	
 	printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
-		" to %d, %d, %d\n",
-		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2], 
-		th->limits[0], th->limits[1], th->limits[2]);
+			 " to %d, %d, %d\n",
+			 th->initial_limits[0], th->initial_limits[1],
+			 th->initial_limits[2], th->limits[0], th->limits[1],
+			 th->limits[2]);
 
 	thermostat = th;
 
 	if (i2c_attach_client(&th->clt)) {
-		printk(KERN_INFO "adt746x: Thermostat failed to attach client !\n");
+		printk(KERN_INFO "adt746x: Thermostat failed to attach "
+				 "client !\n");
 		thermostat = NULL;
 		kfree(th);
 		return -ENODEV;
@@ -392,8 +426,10 @@
 	th->last_speed[1] = -2;
 	
 	if (fan_speed != -1) {
+		/* manual mode, stop fans */
 		write_both_fan_speed(th, 0);
 	} else {
+		/* automatic mode */
 		write_both_fan_speed(th, -1);
 	}
 	
@@ -510,8 +546,9 @@
 	therm_bus = ((*prop) >> 8) & 0x0f;
 	therm_address = ((*prop) & 0xff) >> 1;
 
-	printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, limit_adjust: %d, fan_speed: %d\n",
-		therm_bus, therm_address, limit_adjust, fan_speed);
+	printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, "
+			 "limit_adjust: %d, fan_speed: %d\n",
+			 therm_bus, therm_address, limit_adjust, fan_speed);
 
 	of_dev = of_platform_device_create(np, "temperatures");
 	
@@ -548,8 +585,11 @@
 		device_remove_file(&of_dev->dev, &dev_attr_limit_adjust);
 		device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed);
 		device_remove_file(&of_dev->dev, &dev_attr_cpu_fan_speed);
+
 		if(therm_type == ADT7460)
-			device_remove_file(&of_dev->dev, &dev_attr_gpu_fan_speed);
+			device_remove_file(&of_dev->dev,
+					   &dev_attr_gpu_fan_speed);
+
 		of_device_unregister(of_dev);
 	}
 	i2c_del_driver(&thermostat_driver);
diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
--- a/drivers/macintosh/via-pmu.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/macintosh/via-pmu.c	2004-10-28 22:25:59 -07:00
@@ -153,8 +153,8 @@
 static int option_lid_wakeup = 1;
 static int sleep_in_progress;
 static int can_sleep;
-static unsigned long async_req_locks;
 #endif /* CONFIG_PMAC_PBOOK */
+static unsigned long async_req_locks;
 static unsigned int pmu_irq_stats[11];
 
 static struct proc_dir_entry *proc_pmu_root;
diff -Nru a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
--- a/drivers/md/dm-crypt.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/md/dm-crypt.c	2004-10-28 22:25:56 -07:00
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
+ * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
  *
  * This file is released under the GPL.
  */
@@ -15,6 +16,7 @@
 #include <linux/workqueue.h>
 #include <asm/atomic.h>
 #include <asm/scatterlist.h>
+#include <asm/page.h>
 
 #include "dm.h"
 
@@ -40,12 +42,22 @@
 	struct bio *bio_out;
 	unsigned int offset_in;
 	unsigned int offset_out;
-	int idx_in;
-	int idx_out;
+	unsigned int idx_in;
+	unsigned int idx_out;
 	sector_t sector;
 	int write;
 };
 
+struct crypt_config;
+
+struct crypt_iv_operations {
+	int (*ctr)(struct crypt_config *cc, struct dm_target *ti,
+	           const char *opts);
+	void (*dtr)(struct crypt_config *cc);
+	const char *(*status)(struct crypt_config *cc);
+	int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
+};
+
 /*
  * Crypt: maps a linear range of a block device
  * and encrypts / decrypts at the same time.
@@ -64,11 +76,14 @@
 	/*
 	 * crypto related data
 	 */
-	struct crypto_tfm *tfm;
+	struct crypt_iv_operations *iv_gen_ops;
+	char *iv_mode;
+	void *iv_gen_private;
 	sector_t iv_offset;
-	int (*iv_generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
-	int iv_size;
-	int key_size;
+	unsigned int iv_size;
+
+	struct crypto_tfm *tfm;
+	unsigned int key_size;
 	u8 key[0];
 };
 
@@ -93,18 +108,129 @@
 
 
 /*
- * Different IV generation algorithms
+ * Different IV generation algorithms:
+ *
+ * plain: the initial vector is the 32-bit low-endian version of the sector
+ *        number, padded with zeros if neccessary.
+ *
+ * ess_iv: "encrypted sector|salt initial vector", the sector number is
+ *         encrypted with the bulk cipher using a salt as key. The salt
+ *         should be derived from the bulk cipher's key via hashing.
+ *
+ * plumb: unimplemented, see:
+ * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454
  */
-static int crypt_iv_plain(struct crypt_config *cc, u8 *iv, sector_t sector)
+
+static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
 {
+	memset(iv, 0, cc->iv_size);
 	*(u32 *)iv = cpu_to_le32(sector & 0xffffffff);
-	if (cc->iv_size > sizeof(u32) / sizeof(u8))
-		memset(iv + (sizeof(u32) / sizeof(u8)), 0,
-		       cc->iv_size - (sizeof(u32) / sizeof(u8)));
 
 	return 0;
 }
 
+static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti,
+	                      const char *opts)
+{
+	struct crypto_tfm *essiv_tfm;
+	struct crypto_tfm *hash_tfm;
+	struct scatterlist sg;
+	unsigned int saltsize;
+	u8 *salt;
+
+	if (opts == NULL) {
+		ti->error = PFX "Digest algorithm missing for ESSIV mode";
+		return -EINVAL;
+	}
+
+	/* Hash the cipher key with the given hash algorithm */
+	hash_tfm = crypto_alloc_tfm(opts, 0);
+	if (hash_tfm == NULL) {
+		ti->error = PFX "Error initializing ESSIV hash";
+		return -EINVAL;
+	}
+
+	if (crypto_tfm_alg_type(hash_tfm) != CRYPTO_ALG_TYPE_DIGEST) {
+		ti->error = PFX "Expected digest algorithm for ESSIV hash";
+		crypto_free_tfm(hash_tfm);
+		return -EINVAL;
+	}
+
+	saltsize = crypto_tfm_alg_digestsize(hash_tfm);
+	salt = kmalloc(saltsize, GFP_KERNEL);
+	if (salt == NULL) {
+		ti->error = PFX "Error kmallocing salt storage in ESSIV";
+		crypto_free_tfm(hash_tfm);
+		return -ENOMEM;
+	}
+
+	sg.page = virt_to_page(cc->key);
+	sg.offset = offset_in_page(cc->key);
+	sg.length = cc->key_size;
+	crypto_digest_digest(hash_tfm, &sg, 1, salt);
+	crypto_free_tfm(hash_tfm);
+
+	/* Setup the essiv_tfm with the given salt */
+	essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm),
+	                             CRYPTO_TFM_MODE_ECB);
+	if (essiv_tfm == NULL) {
+		ti->error = PFX "Error allocating crypto tfm for ESSIV";
+		kfree(salt);
+		return -EINVAL;
+	}
+	if (crypto_tfm_alg_blocksize(essiv_tfm)
+	    != crypto_tfm_alg_ivsize(cc->tfm)) {
+		ti->error = PFX "Block size of ESSIV cipher does "
+			        "not match IV size of block cipher";
+		crypto_free_tfm(essiv_tfm);
+		kfree(salt);
+		return -EINVAL;
+	}
+	if (crypto_cipher_setkey(essiv_tfm, salt, saltsize) < 0) {
+		ti->error = PFX "Failed to set key for ESSIV cipher";
+		crypto_free_tfm(essiv_tfm);
+		kfree(salt);
+		return -EINVAL;
+	}
+	kfree(salt);
+
+	cc->iv_gen_private = (void *)essiv_tfm;
+	return 0;
+}
+
+static void crypt_iv_essiv_dtr(struct crypt_config *cc)
+{
+	crypto_free_tfm((struct crypto_tfm *)cc->iv_gen_private);
+	cc->iv_gen_private = NULL;
+}
+
+static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector)
+{
+	struct scatterlist sg = { NULL, };
+
+	memset(iv, 0, cc->iv_size);
+	*(u64 *)iv = cpu_to_le64(sector);
+
+	sg.page = virt_to_page(iv);
+	sg.offset = offset_in_page(iv);
+	sg.length = cc->iv_size;
+	crypto_cipher_encrypt((struct crypto_tfm *)cc->iv_gen_private,
+	                      &sg, &sg, cc->iv_size);
+
+	return 0;
+}
+
+static struct crypt_iv_operations crypt_iv_plain_ops = {
+	.generator = crypt_iv_plain_gen
+};
+
+static struct crypt_iv_operations crypt_iv_essiv_ops = {
+	.ctr       = crypt_iv_essiv_ctr,
+	.dtr       = crypt_iv_essiv_dtr,
+	.generator = crypt_iv_essiv_gen
+};
+
+
 static inline int
 crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
                           struct scatterlist *in, unsigned int length,
@@ -113,8 +239,8 @@
 	u8 iv[cc->iv_size];
 	int r;
 
-	if (cc->iv_generator) {
-		r = cc->iv_generator(cc, iv, sector);
+	if (cc->iv_gen_ops) {
+		r = cc->iv_gen_ops->generator(cc, iv, sector);
 		if (r < 0)
 			return r;
 
@@ -200,13 +326,13 @@
  */
 static struct bio *
 crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
-                   struct bio *base_bio, int *bio_vec_idx)
+                   struct bio *base_bio, unsigned int *bio_vec_idx)
 {
 	struct bio *bio;
-	int nr_iovecs = dm_div_up(size, PAGE_SIZE);
+	unsigned int nr_iovecs = dm_div_up(size, PAGE_SIZE);
 	int gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
-	int flags = current->flags;
-	int i;
+	unsigned long flags = current->flags;
+	unsigned int i;
 
 	/*
 	 * Tell VM to act less aggressively and fail earlier.
@@ -280,9 +406,8 @@
 static void crypt_free_buffer_pages(struct crypt_config *cc,
                                     struct bio *bio, unsigned int bytes)
 {
-	unsigned int start, end;
+	unsigned int i, start, end;
 	struct bio_vec *bv;
-	int i;
 
 	/*
 	 * This is ugly, but Jens Axboe thinks that using bi_idx in the
@@ -366,11 +491,11 @@
 /*
  * Decode key from its hex representation
  */
-static int crypt_decode_key(u8 *key, char *hex, int size)
+static int crypt_decode_key(u8 *key, char *hex, unsigned int size)
 {
 	char buffer[3];
 	char *endp;
-	int i;
+	unsigned int i;
 
 	buffer[2] = '\0';
 
@@ -393,9 +518,9 @@
 /*
  * Encode key into its hex representation
  */
-static void crypt_encode_key(char *hex, u8 *key, int size)
+static void crypt_encode_key(char *hex, u8 *key, unsigned int size)
 {
-	int i;
+	unsigned int i;
 
 	for(i = 0; i < size; i++) {
 		sprintf(hex, "%02x", *key);
@@ -414,9 +539,11 @@
 	struct crypto_tfm *tfm;
 	char *tmp;
 	char *cipher;
-	char *mode;
-	int crypto_flags;
-	int key_size;
+	char *chainmode;
+	char *ivmode;
+	char *ivopts;
+	unsigned int crypto_flags;
+	unsigned int key_size;
 
 	if (argc != 5) {
 		ti->error = PFX "Not enough arguments";
@@ -425,7 +552,9 @@
 
 	tmp = argv[0];
 	cipher = strsep(&tmp, "-");
-	mode = strsep(&tmp, "-");
+	chainmode = strsep(&tmp, "-");
+	ivopts = strsep(&tmp, "-");
+	ivmode = strsep(&ivopts, ":");
 
 	if (tmp)
 		DMWARN(PFX "Unexpected additional cipher options");
@@ -439,19 +568,33 @@
 		return -ENOMEM;
 	}
 
-	if (!mode || strcmp(mode, "plain") == 0)
-		cc->iv_generator = crypt_iv_plain;
-	else if (strcmp(mode, "ecb") == 0)
-		cc->iv_generator = NULL;
-	else {
-		ti->error = PFX "Invalid chaining mode";
+	cc->key_size = key_size;
+	if ((key_size == 0 && strcmp(argv[1], "-") != 0)
+	    || crypt_decode_key(cc->key, argv[1], key_size) < 0) {
+		ti->error = PFX "Error decoding key";
 		goto bad1;
 	}
 
-	if (cc->iv_generator)
+	/* Compatiblity mode for old dm-crypt cipher strings */
+	if (!chainmode || (strcmp(chainmode, "plain") == 0 && !ivmode)) {
+		chainmode = "cbc";
+		ivmode = "plain";
+	}
+
+	/* Choose crypto_flags according to chainmode */
+	if (strcmp(chainmode, "cbc") == 0)
 		crypto_flags = CRYPTO_TFM_MODE_CBC;
-	else
+	else if (strcmp(chainmode, "ecb") == 0)
 		crypto_flags = CRYPTO_TFM_MODE_ECB;
+	else {
+		ti->error = PFX "Unknown chaining mode";
+		goto bad1;
+	}
+
+	if (crypto_flags != CRYPTO_TFM_MODE_ECB && !ivmode) {
+		ti->error = PFX "This chaining mode requires an IV mechanism";
+		goto bad1;
+	}
 
 	tfm = crypto_alloc_tfm(cipher, crypto_flags);
 	if (!tfm) {
@@ -463,15 +606,39 @@
 		goto bad2;
 	}
 
+	cc->tfm = tfm;
+
+	/*
+	 * Choose ivmode. Valid modes: "plain", "essiv:<esshash>".
+	 * See comments at iv code
+	 */
+
+	if (ivmode == NULL)
+		cc->iv_gen_ops = NULL;
+	else if (strcmp(ivmode, "plain") == 0)
+		cc->iv_gen_ops = &crypt_iv_plain_ops;
+	else if (strcmp(ivmode, "essiv") == 0)
+		cc->iv_gen_ops = &crypt_iv_essiv_ops;
+	else {
+		ti->error = PFX "Invalid IV mode";
+		goto bad2;
+	}
+
+	if (cc->iv_gen_ops && cc->iv_gen_ops->ctr &&
+	    cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0)
+		goto bad2;
+
 	if (tfm->crt_cipher.cit_decrypt_iv && tfm->crt_cipher.cit_encrypt_iv)
-		/* at least a 32 bit sector number should fit in our buffer */
+		/* at least a 64 bit sector number should fit in our buffer */
 		cc->iv_size = max(crypto_tfm_alg_ivsize(tfm),
-		                  (unsigned int)(sizeof(u32) / sizeof(u8)));
+		                  (unsigned int)(sizeof(u64) / sizeof(u8)));
 	else {
 		cc->iv_size = 0;
-		if (cc->iv_generator) {
+		if (cc->iv_gen_ops) {
 			DMWARN(PFX "Selected cipher does not support IVs");
-			cc->iv_generator = NULL;
+			if (cc->iv_gen_ops->dtr)
+				cc->iv_gen_ops->dtr(cc);
+			cc->iv_gen_ops = NULL;
 		}
 	}
 
@@ -479,52 +646,59 @@
 				     mempool_free_slab, _crypt_io_pool);
 	if (!cc->io_pool) {
 		ti->error = PFX "Cannot allocate crypt io mempool";
-		goto bad2;
+		goto bad3;
 	}
 
 	cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page,
 				       mempool_free_page, NULL);
 	if (!cc->page_pool) {
 		ti->error = PFX "Cannot allocate page mempool";
-		goto bad3;
-	}
-
-	cc->tfm = tfm;
-	cc->key_size = key_size;
-	if ((key_size == 0 && strcmp(argv[1], "-") != 0)
-	    || crypt_decode_key(cc->key, argv[1], key_size) < 0) {
-		ti->error = PFX "Error decoding key";
 		goto bad4;
 	}
 
 	if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) {
 		ti->error = PFX "Error setting key";
-		goto bad4;
+		goto bad5;
 	}
 
 	if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) {
 		ti->error = PFX "Invalid iv_offset sector";
-		goto bad4;
+		goto bad5;
 	}
 
 	if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) {
 		ti->error = PFX "Invalid device sector";
-		goto bad4;
+		goto bad5;
 	}
 
 	if (dm_get_device(ti, argv[3], cc->start, ti->len,
 	                  dm_table_get_mode(ti->table), &cc->dev)) {
 		ti->error = PFX "Device lookup failed";
-		goto bad4;
+		goto bad5;
 	}
 
+	if (ivmode && cc->iv_gen_ops) {
+		if (ivopts)
+			*(ivopts - 1) = ':';
+		cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL);
+		if (!cc->iv_mode) {
+			ti->error = PFX "Error kmallocing iv_mode string";
+			goto bad5;
+		}
+		strcpy(cc->iv_mode, ivmode);
+	} else
+		cc->iv_mode = NULL;
+
 	ti->private = cc;
 	return 0;
 
-bad4:
+bad5:
 	mempool_destroy(cc->page_pool);
-bad3:
+bad4:
 	mempool_destroy(cc->io_pool);
+bad3:
+	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
+		cc->iv_gen_ops->dtr(cc);
 bad2:
 	crypto_free_tfm(tfm);
 bad1:
@@ -539,6 +713,10 @@
 	mempool_destroy(cc->page_pool);
 	mempool_destroy(cc->io_pool);
 
+	if (cc->iv_mode)
+		kfree(cc->iv_mode);
+	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
+		cc->iv_gen_ops->dtr(cc);
 	crypto_free_tfm(cc->tfm);
 	dm_put_device(ti, cc->dev);
 	kfree(cc);
@@ -577,7 +755,8 @@
 
 static inline struct bio *
 crypt_clone(struct crypt_config *cc, struct crypt_io *io, struct bio *bio,
-            sector_t sector, int *bvec_idx, struct convert_context *ctx)
+            sector_t sector, unsigned int *bvec_idx,
+            struct convert_context *ctx)
 {
 	struct bio *clone;
 
@@ -630,7 +809,7 @@
 	struct bio *clone;
 	unsigned int remaining = bio->bi_size;
 	sector_t sector = bio->bi_sector - ti->begin;
-	int bvec_idx = 0;
+	unsigned int bvec_idx = 0;
 
 	io->target = ti;
 	io->bio = bio;
@@ -692,8 +871,8 @@
 	struct crypt_config *cc = (struct crypt_config *) ti->private;
 	char buffer[32];
 	const char *cipher;
-	const char *mode = NULL;
-	int offset;
+	const char *chainmode = NULL;
+	unsigned int sz = 0;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -705,34 +884,35 @@
 
 		switch(cc->tfm->crt_cipher.cit_mode) {
 		case CRYPTO_TFM_MODE_CBC:
-			mode = "plain";
+			chainmode = "cbc";
 			break;
 		case CRYPTO_TFM_MODE_ECB:
-			mode = "ecb";
+			chainmode = "ecb";
 			break;
 		default:
 			BUG();
 		}
 
-		snprintf(result, maxlen, "%s-%s ", cipher, mode);
-		offset = strlen(result);
+		if (cc->iv_mode)
+			DMEMIT("%s-%s-%s ", cipher, chainmode, cc->iv_mode);
+		else
+			DMEMIT("%s-%s ", cipher, chainmode);
 
 		if (cc->key_size > 0) {
-			if ((maxlen - offset) < ((cc->key_size << 1) + 1))
+			if ((maxlen - sz) < ((cc->key_size << 1) + 1))
 				return -ENOMEM;
 
-			crypt_encode_key(result + offset, cc->key, cc->key_size);
-			offset += cc->key_size << 1;
+			crypt_encode_key(result + sz, cc->key, cc->key_size);
+			sz += cc->key_size << 1;
 		} else {
-			if (offset >= maxlen)
+			if (sz >= maxlen)
 				return -ENOMEM;
-			result[offset++] = '-';
+			result[sz++] = '-';
 		}
 
 		format_dev_t(buffer, cc->dev->bdev->bd_dev);
-		snprintf(result + offset, maxlen - offset, " " SECTOR_FORMAT
-		         " %s " SECTOR_FORMAT, cc->iv_offset,
-		         buffer, cc->start);
+		DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT,
+		       cc->iv_offset, buffer, cc->start);
 		break;
 	}
 	return 0;
@@ -740,7 +920,7 @@
 
 static struct target_type crypt_target = {
 	.name   = "crypt",
-	.version= {1, 0, 0},
+	.version= {1, 1, 0},
 	.module = THIS_MODULE,
 	.ctr    = crypt_ctr,
 	.dtr    = crypt_dtr,
diff -Nru a/drivers/md/dm-target.c b/drivers/md/dm-target.c
--- a/drivers/md/dm-target.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/md/dm-target.c	2004-10-28 22:25:59 -07:00
@@ -120,10 +120,9 @@
 		return -ENOMEM;
 
 	down_write(&_lock);
-	if (__find_target_type(t->name)) {
-		kfree(ti);
+	if (__find_target_type(t->name))
 		rv = -EEXIST;
-	} else
+	else
 		list_add(&ti->list, &_targets);
 
 	up_write(&_lock);
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/md/dm.c	2004-10-28 22:25:59 -07:00
@@ -805,7 +805,7 @@
 {
 	struct mapped_device *md = (struct mapped_device *) context;
 
-	atomic_inc(&md->event_nr);;
+	atomic_inc(&md->event_nr);
 	wake_up(&md->eventq);
 }
 
diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c
--- a/drivers/md/linear.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/md/linear.c	2004-10-28 22:25:57 -07:00
@@ -99,17 +99,14 @@
 	linear_conf_t *conf = mddev_to_conf(mddev);
 	int i, ret = 0;
 
-	for (i=0; i < mddev->raid_disks; i++) {
+	for (i=0; i < mddev->raid_disks && ret == 0; i++) {
 		struct block_device *bdev = conf->disks[i].rdev->bdev;
 		request_queue_t *r_queue = bdev_get_queue(bdev);
 
-		if (!r_queue->issue_flush_fn) {
+		if (!r_queue->issue_flush_fn)
 			ret = -EOPNOTSUPP;
-			break;
-		}
-		ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-		if (ret)
-			break;
+		else
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
 	}
 	return ret;
 }
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/md/md.c	2004-10-28 22:25:57 -07:00
@@ -154,38 +154,6 @@
 		tmp = tmp->next;})					\
 		)
 
-int md_flush_mddev(mddev_t *mddev, sector_t *error_sector)
-{
-	struct list_head *tmp;
-	mdk_rdev_t *rdev;
-	int ret = 0;
-
-	/*
-	 * this list iteration is done without any locking in md?!
-	 */
-	ITERATE_RDEV(mddev, rdev, tmp) {
-		request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
-		int err;
-
-		if (!r_queue->issue_flush_fn)
-			err = -EOPNOTSUPP;
-		else
-			err = r_queue->issue_flush_fn(r_queue, rdev->bdev->bd_disk, error_sector);
-
-		if (!ret)
-			ret = err;
-	}
-
-	return ret;
-}
-
-static int md_flush_all(request_queue_t *q, struct gendisk *disk,
-			 sector_t *error_sector)
-{
-	mddev_t *mddev = q->queuedata;
-
-	return md_flush_mddev(mddev, error_sector);
-}
 
 static int md_fail_request (request_queue_t *q, struct bio *bio)
 {
@@ -472,30 +440,6 @@
 	return csum;
 }
 
-/* csum_partial is not consistent between different architectures.
- * Some (i386) do a 32bit csum.  Some (alpha) do 16 bit.
- * This makes it hard for user-space to know what to do.
- * So we use calc_sb_csum to set the checksum to allow working
- * with older kernels, but allow calc_sb_csum_common to
- * be used when checking if a checksum is correct, to
- * make life easier for user-space tools that might write
- * a superblock.
- */
-static unsigned int calc_sb_csum_common(mdp_super_t *super)
-{
-	unsigned int  disk_csum = super->sb_csum;
-	unsigned long long newcsum = 0;
-	unsigned int csum;
-	int i;
-	unsigned int *superc = (int*) super;
-	super->sb_csum = 0;
-
-	for (i=0; i<MD_SB_BYTES/4; i++)
-		newcsum+= superc[i];
-	csum = (newcsum& 0xffffffff) + (newcsum>>32);
-	super->sb_csum = disk_csum;
-	return csum;
-}
 
 /*
  * Handle superblock details.
@@ -579,8 +523,7 @@
 	if (sb->raid_disks <= 0)
 		goto abort;
 
-	if (calc_sb_csum(sb) != sb->sb_csum &&
-		calc_sb_csum_common(sb) != sb->sb_csum) {
+	if (csum_fold(calc_sb_csum(sb)) != csum_fold(sb->sb_csum)) {
 		printk(KERN_WARNING "md: invalid superblock checksum on %s\n",
 			b);
 		goto abort;
@@ -805,7 +748,7 @@
 {
 	unsigned int disk_csum, csum;
 	unsigned long long newcsum;
-	int size = 256 + sb->max_dev*2;
+	int size = 256 + le32_to_cpu(sb->max_dev)*2;
 	unsigned int *isuper = (unsigned int*)sb;
 	int i;
 
@@ -820,7 +763,7 @@
 
 	csum = (newcsum & 0xffffffff) + (newcsum >> 32);
 	sb->sb_csum = disk_csum;
-	return csum;
+	return cpu_to_le32(csum);
 }
 
 static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
@@ -842,7 +785,7 @@
 	case 0:
 		sb_offset = rdev->bdev->bd_inode->i_size >> 9;
 		sb_offset -= 8*2;
-		sb_offset &= ~(4*2);
+		sb_offset &= ~(4*2-1);
 		/* convert from sectors to K */
 		sb_offset /= 2;
 		break;
@@ -875,6 +818,11 @@
 			bdevname(rdev->bdev,b));
 		return -EINVAL;
 	}
+	if (le64_to_cpu(sb->data_size) < 10) {
+		printk("md: data_size too small on %s\n",
+		       bdevname(rdev->bdev,b));
+		return -EINVAL;
+	}
 	rdev->preferred_minor = 0xffff;
 	rdev->data_offset = le64_to_cpu(sb->data_offset);
 
@@ -919,7 +867,6 @@
 
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 1;
-		mddev->minor_version = 0;
 		mddev->patch_version = 0;
 		mddev->persistent = 1;
 		mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
@@ -928,7 +875,7 @@
 		mddev->level = le32_to_cpu(sb->level);
 		mddev->layout = le32_to_cpu(sb->layout);
 		mddev->raid_disks = le32_to_cpu(sb->raid_disks);
-		mddev->size = (u32)le64_to_cpu(sb->size);
+		mddev->size = le64_to_cpu(sb->size)/2;
 		mddev->events = le64_to_cpu(sb->events);
 		
 		mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
@@ -996,7 +943,7 @@
 		if (rdev2->desc_nr > max_dev)
 			max_dev = rdev2->desc_nr;
 	
-	sb->max_dev = max_dev;
+	sb->max_dev = cpu_to_le32(max_dev);
 	for (i=0; i<max_dev;i++)
 		sb->dev_roles[max_dev] = cpu_to_le16(0xfffe);
 	
@@ -1491,17 +1438,6 @@
 	}
 
 
-	/*
-	 * Check if we can support this RAID array
-	 */
-	if (mddev->major_version != MD_MAJOR_VERSION ||
-			mddev->minor_version > MD_MINOR_VERSION) {
-		printk(KERN_ALERT 
-			"md: %s: unsupported raid array version %d.%d.%d\n",
-			mdname(mddev), mddev->major_version,
-			mddev->minor_version, mddev->patch_version);
-		goto abort;
-	}
 
 	if ((mddev->recovery_cp != MaxSector) &&
 	    ((mddev->level == 1) ||
@@ -1511,8 +1447,6 @@
 		       mdname(mddev));
 
 	return 0;
-abort:
-	return 1;
 }
 
 int mdp_major = 0;
@@ -1714,7 +1648,6 @@
 	 */
 	mddev->queue->queuedata = mddev;
 	mddev->queue->make_request_fn = mddev->pers->make_request;
-	mddev->queue->issue_flush_fn = md_flush_all;
 
 	mddev->changed = 1;
 	return 0;
@@ -1846,7 +1779,7 @@
 
 	err = do_md_run (mddev);
 	if (err) {
-		printk(KERN_WARNING "md :do_md_run() returned %d\n", err);
+		printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
 		do_md_stop (mddev, 0);
 	}
 }
@@ -2036,7 +1969,7 @@
 
 	info.major_version = mddev->major_version;
 	info.minor_version = mddev->minor_version;
-	info.patch_version = 1;
+	info.patch_version = MD_PATCHLEVEL_VERSION;
 	info.ctime         = mddev->ctime;
 	info.level         = mddev->level;
 	info.size          = mddev->size;
@@ -2436,7 +2369,7 @@
 		/* The "size" is the amount of each device that is used.
 		 * This can only make sense for arrays with redundancy.
 		 * linear and raid0 always use whatever space is available
-		 * We can only consider changing the size of no resync
+		 * We can only consider changing the size if no resync
 		 * or reconstruction is happening, and if the new size
 		 * is acceptable. It must fit before the sb_offset or,
 		 * if that is <data_offset, it must fit before the
@@ -3331,33 +3264,54 @@
 	 * 1 == like 2, but have yielded to allow conflicting resync to
 	 *		commense
 	 * other == active in resync - this many blocks
+	 *
+	 * Before starting a resync we must have set curr_resync to
+	 * 2, and then checked that every "conflicting" array has curr_resync
+	 * less than ours.  When we find one that is the same or higher
+	 * we wait on resync_wait.  To avoid deadlock, we reduce curr_resync
+	 * to 1 if we choose to yield (based arbitrarily on address of mddev structure).
+	 * This will mean we have to start checking from the beginning again.
+	 *
 	 */
+
 	do {
 		mddev->curr_resync = 2;
 
+	try_again:
+		if (signal_pending(current)) {
+			flush_signals(current);
+			goto skip;
+		}
 		ITERATE_MDDEV(mddev2,tmp) {
+			printk(".");
 			if (mddev2 == mddev)
 				continue;
 			if (mddev2->curr_resync && 
 			    match_mddev_units(mddev,mddev2)) {
-				printk(KERN_INFO "md: delaying resync of %s"
-					" until %s has finished resync (they"
-				       	" share one or more physical units)\n",
-				       mdname(mddev), mdname(mddev2));
-				if (mddev < mddev2) {/* arbitrarily yield */
+				DEFINE_WAIT(wq);
+				if (mddev < mddev2 && mddev->curr_resync == 2) {
+					/* arbitrarily yield */
 					mddev->curr_resync = 1;
 					wake_up(&resync_wait);
 				}
-				if (wait_event_interruptible(resync_wait,
-							     mddev2->curr_resync < mddev->curr_resync)) {
-					flush_signals(current);
+				if (mddev > mddev2 && mddev->curr_resync == 1)
+					/* no need to wait here, we can wait the next
+					 * time 'round when curr_resync == 2
+					 */
+					continue;
+				prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE);
+				if (!signal_pending(current)
+				    && mddev2->curr_resync >= mddev->curr_resync) {
+					printk(KERN_INFO "md: delaying resync of %s"
+					       " until %s has finished resync (they"
+					       " share one or more physical units)\n",
+					       mdname(mddev), mdname(mddev2));
 					mddev_put(mddev2);
-					goto skip;
+					schedule();
+					finish_wait(&resync_wait, &wq);
+					goto try_again;
 				}
-			}
-			if (mddev->curr_resync == 1) {
-				mddev_put(mddev2);
-				break;
+				finish_wait(&resync_wait, &wq);
 			}
 		}
 	} while (mddev->curr_resync < 2);
@@ -3500,6 +3454,7 @@
 	md_enter_safemode(mddev);
  skip:
 	mddev->curr_resync = 0;
+	wake_up(&resync_wait);
 	set_bit(MD_RECOVERY_DONE, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
 }
@@ -3567,14 +3522,11 @@
 			mddev->recovery = 0;
 			/* flag recovery needed just to double check */
 			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-			wake_up(&resync_wait);
 			goto unlock;
 		}
-		if (mddev->recovery) {
+		if (mddev->recovery)
 			/* probably just the RECOVERY_NEEDED flag */
 			mddev->recovery = 0;
-			wake_up(&resync_wait);
-		}
 
 		/* no recovery is running.
 		 * remove any failed drives, then
diff -Nru a/drivers/md/multipath.c b/drivers/md/multipath.c
--- a/drivers/md/multipath.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/md/multipath.c	2004-10-28 22:25:58 -07:00
@@ -36,8 +36,6 @@
 
 
 static mdk_personality_t multipath_personality;
-static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED;
-struct multipath_bh *multipath_retry_list = NULL, **multipath_retry_tail;
 
 
 static void *mp_pool_alloc(int gfp_flags, void *data)
@@ -63,16 +61,16 @@
 	 * now we use the first available disk.
 	 */
 
-	spin_lock_irq(&conf->device_lock);
+	rcu_read_lock();
 	for (i = 0; i < disks; i++) {
 		mdk_rdev_t *rdev = conf->multipaths[i].rdev;
 		if (rdev && rdev->in_sync) {
 			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irq(&conf->device_lock);
+			rcu_read_unlock();
 			return i;
 		}
 	}
-	spin_unlock_irq(&conf->device_lock);
+	rcu_read_unlock();
 
 	printk(KERN_ERR "multipath_map(): no more operational IO paths?\n");
 	return (-1);
@@ -82,14 +80,11 @@
 {
 	unsigned long flags;
 	mddev_t *mddev = mp_bh->mddev;
+	multipath_conf_t *conf = mddev_to_conf(mddev);
 
-	spin_lock_irqsave(&retry_list_lock, flags);
-	if (multipath_retry_list == NULL)
-		multipath_retry_tail = &multipath_retry_list;
-	*multipath_retry_tail = mp_bh;
-	multipath_retry_tail = &mp_bh->next_mp;
-	mp_bh->next_mp = NULL;
-	spin_unlock_irqrestore(&retry_list_lock, flags);
+	spin_lock_irqsave(&conf->device_lock, flags);
+	list_add(&mp_bh->retry_list, &conf->retry_list);
+	spin_unlock_irqrestore(&conf->device_lock, flags);
 	md_wakeup_thread(mddev->thread);
 }
 
@@ -140,26 +135,26 @@
 {
 	multipath_conf_t *conf = mddev_to_conf(mddev);
 	int i;
-	unsigned long flags;
 
-	spin_lock_irqsave(&conf->device_lock, flags);
+	rcu_read_lock();
 	for (i=0; i<mddev->raid_disks; i++) {
 		mdk_rdev_t *rdev = conf->multipaths[i].rdev;
-		if (rdev && !rdev->faulty) {
+		if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
 			request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
 
 			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irqrestore(&conf->device_lock, flags);
+			rcu_read_unlock();
 
 			if (r_queue->unplug_fn)
 				r_queue->unplug_fn(r_queue);
 
-			spin_lock_irqsave(&conf->device_lock, flags);
-			atomic_dec(&rdev->nr_pending);
+			rdev_dec_pending(rdev, mddev);
+			rcu_read_lock();
 		}
 	}
-	spin_unlock_irqrestore(&conf->device_lock, flags);
+	rcu_read_unlock();
 }
+
 static void multipath_unplug(request_queue_t *q)
 {
 	unplug_slaves(q->queuedata);
@@ -195,6 +190,7 @@
 	multipath = conf->multipaths + mp_bh->path;
 
 	mp_bh->bio = *bio;
+	mp_bh->bio.bi_sector += multipath->rdev->data_offset;
 	mp_bh->bio.bi_bdev = multipath->rdev->bdev;
 	mp_bh->bio.bi_rw |= (1 << BIO_RW_FAILFAST);
 	mp_bh->bio.bi_end_io = multipath_end_request;
@@ -224,22 +220,26 @@
 	multipath_conf_t *conf = mddev_to_conf(mddev);
 	int i, ret = 0;
 
-	for (i=0; i<mddev->raid_disks; i++) {
+	rcu_read_lock();
+	for (i=0; i<mddev->raid_disks && ret == 0; i++) {
 		mdk_rdev_t *rdev = conf->multipaths[i].rdev;
 		if (rdev && !rdev->faulty) {
 			struct block_device *bdev = rdev->bdev;
 			request_queue_t *r_queue = bdev_get_queue(bdev);
 
-			if (!r_queue->issue_flush_fn) {
+			if (!r_queue->issue_flush_fn)
 				ret = -EOPNOTSUPP;
-				break;
+			else {
+				atomic_inc(&rdev->nr_pending);
+				rcu_read_unlock();
+				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
+							      error_sector);
+				rdev_dec_pending(rdev, mddev);
+				rcu_read_lock();
 			}
-
-			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-			if (ret)
-				break;
 		}
 	}
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -310,10 +310,9 @@
 	struct multipath_info *p;
 
 	print_multipath_conf(conf);
-	spin_lock_irq(&conf->device_lock);
+
 	for (path=0; path<mddev->raid_disks; path++) 
 		if ((p=conf->multipaths+path)->rdev == NULL) {
-			p->rdev = rdev;
 			blk_queue_stack_limits(mddev->queue,
 					       rdev->bdev->bd_disk->queue);
 
@@ -330,9 +329,9 @@
 			conf->working_disks++;
 			rdev->raid_disk = path;
 			rdev->in_sync = 1;
+			p->rdev = rdev;
 			found = 1;
 		}
-	spin_unlock_irq(&conf->device_lock);
 
 	print_multipath_conf(conf);
 	return found;
@@ -341,26 +340,29 @@
 static int multipath_remove_disk(mddev_t *mddev, int number)
 {
 	multipath_conf_t *conf = mddev->private;
-	int err = 1;
+	int err = 0;
+	mdk_rdev_t *rdev;
 	struct multipath_info *p = conf->multipaths + number;
 
 	print_multipath_conf(conf);
-	spin_lock_irq(&conf->device_lock);
 
-	if (p->rdev) {
-		if (p->rdev->in_sync ||
-		    atomic_read(&p->rdev->nr_pending)) {
+	rdev = p->rdev;
+	if (rdev) {
+		if (rdev->in_sync ||
+		    atomic_read(&rdev->nr_pending)) {
 			printk(KERN_ERR "hot-remove-disk, slot %d is identified"				" but is still operational!\n", number);
 			err = -EBUSY;
 			goto abort;
 		}
 		p->rdev = NULL;
-		err = 0;
+		synchronize_kernel();
+		if (atomic_read(&rdev->nr_pending)) {
+			/* lost the race, try later */
+			err = -EBUSY;
+			p->rdev = rdev;
+		}
 	}
-	if (err)
-		MD_BUG();
 abort:
-	spin_unlock_irq(&conf->device_lock);
 
 	print_multipath_conf(conf);
 	return err;
@@ -382,18 +384,18 @@
 	struct bio *bio;
 	unsigned long flags;
 	multipath_conf_t *conf = mddev_to_conf(mddev);
+	struct list_head *head = &conf->retry_list;
 
 	md_check_recovery(mddev);
 	for (;;) {
 		char b[BDEVNAME_SIZE];
-		spin_lock_irqsave(&retry_list_lock, flags);
-		mp_bh = multipath_retry_list;
-		if (!mp_bh)
+		spin_lock_irqsave(&conf->device_lock, flags);
+		if (list_empty(head))
 			break;
-		multipath_retry_list = mp_bh->next_mp;
-		spin_unlock_irqrestore(&retry_list_lock, flags);
+		mp_bh = list_entry(head->prev, struct multipath_bh, retry_list);
+		list_del(head->prev);
+		spin_unlock_irqrestore(&conf->device_lock, flags);
 
-		mddev = mp_bh->mddev;
 		bio = &mp_bh->bio;
 		bio->bi_sector = mp_bh->master_bio->bi_sector;
 		
@@ -409,6 +411,7 @@
 				bdevname(bio->bi_bdev,b),
 				(unsigned long long)bio->bi_sector);
 			*bio = *(mp_bh->master_bio);
+			bio->bi_sector += conf->multipaths[mp_bh->path].rdev->data_offset;
 			bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
 			bio->bi_rw |= (1 << BIO_RW_FAILFAST);
 			bio->bi_end_io = multipath_end_request;
@@ -416,7 +419,7 @@
 			generic_make_request(bio);
 		}
 	}
-	spin_unlock_irqrestore(&retry_list_lock, flags);
+	spin_unlock_irqrestore(&conf->device_lock, flags);
 }
 
 static int multipath_run (mddev_t *mddev)
@@ -489,6 +492,7 @@
 	mddev->sb_dirty = 1;
 	conf->mddev = mddev;
 	conf->device_lock = SPIN_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&conf->retry_list);
 
 	if (!conf->working_disks) {
 		printk(KERN_ERR "multipath: no operational IO paths for %s\n",
diff -Nru a/drivers/md/raid0.c b/drivers/md/raid0.c
--- a/drivers/md/raid0.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/md/raid0.c	2004-10-28 22:25:58 -07:00
@@ -48,18 +48,14 @@
 	mdk_rdev_t **devlist = conf->strip_zone[0].dev;
 	int i, ret = 0;
 
-	for (i=0; i<mddev->raid_disks; i++) {
+	for (i=0; i<mddev->raid_disks && ret == 0; i++) {
 		struct block_device *bdev = devlist[i]->bdev;
 		request_queue_t *r_queue = bdev_get_queue(bdev);
 
-		if (!r_queue->issue_flush_fn) {
+		if (!r_queue->issue_flush_fn)
 			ret = -EOPNOTSUPP;
-			break;
-		}
-
-		ret =r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-		if (ret)
-			break;
+		else
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
 	}
 	return ret;
 }
diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c
--- a/drivers/md/raid1.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/md/raid1.c	2004-10-28 22:25:58 -07:00
@@ -30,8 +30,6 @@
 #define	NR_RAID1_BIOS 256
 
 static mdk_personality_t raid1_personality;
-static spinlock_t retry_list_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(retry_list_head);
 
 static void unplug_slaves(mddev_t *mddev);
 
@@ -188,10 +186,11 @@
 {
 	unsigned long flags;
 	mddev_t *mddev = r1_bio->mddev;
+	conf_t *conf = mddev_to_conf(mddev);
 
-	spin_lock_irqsave(&retry_list_lock, flags);
-	list_add(&r1_bio->retry_list, &retry_list_head);
-	spin_unlock_irqrestore(&retry_list_lock, flags);
+	spin_lock_irqsave(&conf->device_lock, flags);
+	list_add(&r1_bio->retry_list, &conf->retry_list);
+	spin_unlock_irqrestore(&conf->device_lock, flags);
 
 	md_wakeup_thread(mddev->thread);
 }
@@ -340,7 +339,7 @@
 	const int sectors = r1_bio->sectors;
 	sector_t new_distance, current_distance;
 
-	spin_lock_irq(&conf->device_lock);
+	rcu_read_lock();
 	/*
 	 * Check if it if we can balance. We can balance on the whole
 	 * device if no resync is going on, or below the resync window.
@@ -417,7 +416,7 @@
 		conf->last_used = new_disk;
 		atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending);
 	}
-	spin_unlock_irq(&conf->device_lock);
+	rcu_read_unlock();
 
 	return new_disk;
 }
@@ -426,26 +425,26 @@
 {
 	conf_t *conf = mddev_to_conf(mddev);
 	int i;
-	unsigned long flags;
 
-	spin_lock_irqsave(&conf->device_lock, flags);
+	rcu_read_lock();
 	for (i=0; i<mddev->raid_disks; i++) {
 		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
-		if (rdev && atomic_read(&rdev->nr_pending)) {
+		if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
 			request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
 
 			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irqrestore(&conf->device_lock, flags);
+			rcu_read_unlock();
 
 			if (r_queue->unplug_fn)
 				r_queue->unplug_fn(r_queue);
 
-			spin_lock_irqsave(&conf->device_lock, flags);
-			atomic_dec(&rdev->nr_pending);
+			rdev_dec_pending(rdev, mddev);
+			rcu_read_lock();
 		}
 	}
-	spin_unlock_irqrestore(&conf->device_lock, flags);
+	rcu_read_unlock();
 }
+
 static void raid1_unplug(request_queue_t *q)
 {
 	unplug_slaves(q->queuedata);
@@ -456,24 +455,28 @@
 {
 	mddev_t *mddev = q->queuedata;
 	conf_t *conf = mddev_to_conf(mddev);
-	unsigned long flags;
 	int i, ret = 0;
 
-	spin_lock_irqsave(&conf->device_lock, flags);
-	for (i=0; i<mddev->raid_disks; i++) {
+	rcu_read_lock();
+	for (i=0; i<mddev->raid_disks && ret == 0; i++) {
 		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
 		if (rdev && !rdev->faulty) {
 			struct block_device *bdev = rdev->bdev;
 			request_queue_t *r_queue = bdev_get_queue(bdev);
 
-			if (r_queue->issue_flush_fn) {
-				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-				if (ret)
-					break;
+			if (!r_queue->issue_flush_fn)
+				ret = -EOPNOTSUPP;
+			else {
+				atomic_inc(&rdev->nr_pending);
+				rcu_read_unlock();
+				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
+							      error_sector);
+				rdev_dec_pending(rdev, mddev);
+				rcu_read_lock();
 			}
 		}
 	}
-	spin_unlock_irqrestore(&conf->device_lock, flags);
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -580,7 +583,7 @@
 	 * bios[x] to bio
 	 */
 	disks = conf->raid_disks;
-	spin_lock_irq(&conf->device_lock);
+	rcu_read_lock();
 	for (i = 0;  i < disks; i++) {
 		if (conf->mirrors[i].rdev &&
 		    !conf->mirrors[i].rdev->faulty) {
@@ -589,7 +592,7 @@
 		} else
 			r1_bio->bios[i] = NULL;
 	}
-	spin_unlock_irq(&conf->device_lock);
+	rcu_read_unlock();
 
 	atomic_set(&r1_bio->remaining, 1);
 	md_write_start(mddev);
@@ -711,7 +714,6 @@
 	conf_t *conf = mddev->private;
 	mirror_info_t *tmp;
 
-	spin_lock_irq(&conf->device_lock);
 	/*
 	 * Find all failed disks within the RAID1 configuration 
 	 * and mark them readable
@@ -726,7 +728,6 @@
 			tmp->rdev->in_sync = 1;
 		}
 	}
-	spin_unlock_irq(&conf->device_lock);
 
 	print_conf(conf);
 	return 0;
@@ -740,10 +741,8 @@
 	int mirror;
 	mirror_info_t *p;
 
-	spin_lock_irq(&conf->device_lock);
 	for (mirror=0; mirror < mddev->raid_disks; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
-			p->rdev = rdev;
 
 			blk_queue_stack_limits(mddev->queue,
 					       rdev->bdev->bd_disk->queue);
@@ -758,9 +757,9 @@
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
 			found = 1;
+			p->rdev = rdev;
 			break;
 		}
-	spin_unlock_irq(&conf->device_lock);
 
 	print_conf(conf);
 	return found;
@@ -769,24 +768,27 @@
 static int raid1_remove_disk(mddev_t *mddev, int number)
 {
 	conf_t *conf = mddev->private;
-	int err = 1;
+	int err = 0;
+	mdk_rdev_t *rdev;
 	mirror_info_t *p = conf->mirrors+ number;
 
 	print_conf(conf);
-	spin_lock_irq(&conf->device_lock);
-	if (p->rdev) {
-		if (p->rdev->in_sync ||
-		    atomic_read(&p->rdev->nr_pending)) {
+	rdev = p->rdev;
+	if (rdev) {
+		if (rdev->in_sync ||
+		    atomic_read(&rdev->nr_pending)) {
 			err = -EBUSY;
 			goto abort;
 		}
 		p->rdev = NULL;
-		err = 0;
+		synchronize_kernel();
+		if (atomic_read(&rdev->nr_pending)) {
+			/* lost the race, try later */
+			err = -EBUSY;
+			p->rdev = rdev;
+		}
 	}
-	if (err)
-		MD_BUG();
 abort:
-	spin_unlock_irq(&conf->device_lock);
 
 	print_conf(conf);
 	return err;
@@ -904,11 +906,11 @@
 
 static void raid1d(mddev_t *mddev)
 {
-	struct list_head *head = &retry_list_head;
 	r1bio_t *r1_bio;
 	struct bio *bio;
 	unsigned long flags;
 	conf_t *conf = mddev_to_conf(mddev);
+	struct list_head *head = &conf->retry_list;
 	int unplug=0;
 	mdk_rdev_t *rdev;
 
@@ -917,12 +919,12 @@
 	
 	for (;;) {
 		char b[BDEVNAME_SIZE];
-		spin_lock_irqsave(&retry_list_lock, flags);
+		spin_lock_irqsave(&conf->device_lock, flags);
 		if (list_empty(head))
 			break;
 		r1_bio = list_entry(head->prev, r1bio_t, retry_list);
 		list_del(head->prev);
-		spin_unlock_irqrestore(&retry_list_lock, flags);
+		spin_unlock_irqrestore(&conf->device_lock, flags);
 
 		mddev = r1_bio->mddev;
 		conf = mddev_to_conf(mddev);
@@ -941,6 +943,8 @@
 			} else {
 				r1_bio->bios[r1_bio->read_disk] = NULL;
 				r1_bio->read_disk = disk;
+				bio_put(bio);
+				bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
 				r1_bio->bios[r1_bio->read_disk] = bio;
 				rdev = conf->mirrors[disk].rdev;
 				if (printk_ratelimit())
@@ -948,15 +952,17 @@
 					       " another mirror\n",
 					       bdevname(rdev->bdev,b),
 					       (unsigned long long)r1_bio->sector);
-				bio->bi_bdev = rdev->bdev;
 				bio->bi_sector = r1_bio->sector + rdev->data_offset;
+				bio->bi_bdev = rdev->bdev;
+				bio->bi_end_io = raid1_end_read_request;
 				bio->bi_rw = READ;
+				bio->bi_private = r1_bio;
 				unplug = 1;
 				generic_make_request(bio);
 			}
 		}
 	}
-	spin_unlock_irqrestore(&retry_list_lock, flags);
+	spin_unlock_irqrestore(&conf->device_lock, flags);
 	if (unplug)
 		unplug_slaves(mddev);
 }
@@ -1023,7 +1029,7 @@
 	 */
 	disk = conf->last_used;
 	/* make sure disk is operational */
-	spin_lock_irq(&conf->device_lock);
+
 	while (conf->mirrors[disk].rdev == NULL ||
 	       !conf->mirrors[disk].rdev->in_sync) {
 		if (disk <= 0)
@@ -1034,7 +1040,7 @@
 	}
 	conf->last_used = disk;
 	atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
-	spin_unlock_irq(&conf->device_lock);
+
 
 	mirror = conf->mirrors + disk;
 
@@ -1087,7 +1093,7 @@
 		int rv = max_sector - sector_nr;
 		md_done_sync(mddev, rv, 1);
 		put_buf(r1_bio);
-		atomic_dec(&conf->mirrors[disk].rdev->nr_pending);
+		rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
 		return rv;
 	}
 
@@ -1205,6 +1211,7 @@
 	conf->raid_disks = mddev->raid_disks;
 	conf->mddev = mddev;
 	conf->device_lock = SPIN_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&conf->retry_list);
 	if (conf->working_disks == 1)
 		mddev->recovery_cp = MaxSector;
 
diff -Nru a/drivers/md/raid10.c b/drivers/md/raid10.c
--- a/drivers/md/raid10.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/md/raid10.c	2004-10-28 22:25:59 -07:00
@@ -36,7 +36,7 @@
  * device of the previous section.
  * Thus there are (near_copies*far_copies) of each chunk, and each is on a different
  * drive.
- * near_copies and far_copies must be at least one, and there product is at most
+ * near_copies and far_copies must be at least one, and their product is at most
  * raid_disks.
  */
 
@@ -498,7 +498,7 @@
 	sector_t new_distance, current_distance;
 
 	raid10_find_phys(conf, r10_bio);
-	spin_lock_irq(&conf->device_lock);
+	rcu_read_lock();
 	/*
 	 * Check if we can balance. We can balance on the whole
 	 * device if no resync is going on, or below the resync window.
@@ -570,7 +570,7 @@
 
 	if (disk >= 0 && conf->mirrors[disk].rdev)
 		atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
-	spin_unlock_irq(&conf->device_lock);
+	rcu_read_unlock();
 
 	return disk;
 }
@@ -579,26 +579,26 @@
 {
 	conf_t *conf = mddev_to_conf(mddev);
 	int i;
-	unsigned long flags;
 
-	spin_lock_irqsave(&conf->device_lock, flags);
+	rcu_read_lock();
 	for (i=0; i<mddev->raid_disks; i++) {
 		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
-		if (rdev && atomic_read(&rdev->nr_pending)) {
+		if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
 			request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
 
 			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irqrestore(&conf->device_lock, flags);
+			rcu_read_unlock();
 
 			if (r_queue->unplug_fn)
 				r_queue->unplug_fn(r_queue);
 
-			spin_lock_irqsave(&conf->device_lock, flags);
-			atomic_dec(&rdev->nr_pending);
+			rdev_dec_pending(rdev, mddev);
+			rcu_read_lock();
 		}
 	}
-	spin_unlock_irqrestore(&conf->device_lock, flags);
+	rcu_read_unlock();
 }
+
 static void raid10_unplug(request_queue_t *q)
 {
 	unplug_slaves(q->queuedata);
@@ -609,24 +609,28 @@
 {
 	mddev_t *mddev = q->queuedata;
 	conf_t *conf = mddev_to_conf(mddev);
-	unsigned long flags;
 	int i, ret = 0;
 
-	spin_lock_irqsave(&conf->device_lock, flags);
-	for (i=0; i<mddev->raid_disks; i++) {
+	rcu_read_lock();
+	for (i=0; i<mddev->raid_disks && ret == 0; i++) {
 		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
 		if (rdev && !rdev->faulty) {
 			struct block_device *bdev = rdev->bdev;
 			request_queue_t *r_queue = bdev_get_queue(bdev);
 
-			if (r_queue->issue_flush_fn) {
-				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-				if (ret)
-					break;
+			if (!r_queue->issue_flush_fn)
+				ret = -EOPNOTSUPP;
+			else {
+				atomic_inc(&rdev->nr_pending);
+				rcu_read_unlock();
+				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
+							      error_sector);
+				rdev_dec_pending(rdev, mddev);
+				rcu_read_lock();
 			}
 		}
 	}
-	spin_unlock_irqrestore(&conf->device_lock, flags);
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -757,7 +761,7 @@
 	 * bios[x] to bio
 	 */
 	raid10_find_phys(conf, r10_bio);
-	spin_lock_irq(&conf->device_lock);
+	rcu_read_lock();
 	for (i = 0;  i < conf->copies; i++) {
 		int d = r10_bio->devs[i].devnum;
 		if (conf->mirrors[d].rdev &&
@@ -767,7 +771,7 @@
 		} else
 			r10_bio->devs[i].bio = NULL;
 	}
-	spin_unlock_irq(&conf->device_lock);
+	rcu_read_unlock();
 
 	atomic_set(&r10_bio->remaining, 1);
 	md_write_start(mddev);
@@ -900,7 +904,6 @@
 	conf_t *conf = mddev->private;
 	mirror_info_t *tmp;
 
-	spin_lock_irq(&conf->device_lock);
 	/*
 	 * Find all non-in_sync disks within the RAID10 configuration
 	 * and mark them in_sync
@@ -915,7 +918,6 @@
 			tmp->rdev->in_sync = 1;
 		}
 	}
-	spin_unlock_irq(&conf->device_lock);
 
 	print_conf(conf);
 	return 0;
@@ -934,10 +936,9 @@
 		 * very different from resync
 		 */
 		return 0;
-	spin_lock_irq(&conf->device_lock);
+
 	for (mirror=0; mirror < mddev->raid_disks; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
-			p->rdev = rdev;
 
 			blk_queue_stack_limits(mddev->queue,
 					       rdev->bdev->bd_disk->queue);
@@ -952,9 +953,9 @@
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
 			found = 1;
+			p->rdev = rdev;
 			break;
 		}
-	spin_unlock_irq(&conf->device_lock);
 
 	print_conf(conf);
 	return found;
@@ -963,24 +964,27 @@
 static int raid10_remove_disk(mddev_t *mddev, int number)
 {
 	conf_t *conf = mddev->private;
-	int err = 1;
+	int err = 0;
+	mdk_rdev_t *rdev;
 	mirror_info_t *p = conf->mirrors+ number;
 
 	print_conf(conf);
-	spin_lock_irq(&conf->device_lock);
-	if (p->rdev) {
-		if (p->rdev->in_sync ||
-		    atomic_read(&p->rdev->nr_pending)) {
+	rdev = p->rdev;
+	if (rdev) {
+		if (rdev->in_sync ||
+		    atomic_read(&rdev->nr_pending)) {
 			err = -EBUSY;
 			goto abort;
 		}
 		p->rdev = NULL;
-		err = 0;
+		synchronize_kernel();
+		if (atomic_read(&rdev->nr_pending)) {
+			/* lost the race, try later */
+			err = -EBUSY;
+			p->rdev = rdev;
+		}
 	}
-	if (err)
-		MD_BUG();
 abort:
-	spin_unlock_irq(&conf->device_lock);
 
 	print_conf(conf);
 	return err;
@@ -1145,6 +1149,7 @@
 		atomic_inc(&r10_bio->remaining);
 		md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9);
 
+		tbio->bi_sector += conf->mirrors[d].rdev->data_offset;
 		generic_make_request(tbio);
 	}
 
@@ -1233,8 +1238,8 @@
 			int mirror;
 			bio = r10_bio->devs[r10_bio->read_slot].bio;
 			r10_bio->devs[r10_bio->read_slot].bio = NULL;
+			bio_put(bio);
 			mirror = read_balance(conf, r10_bio);
-			r10_bio->devs[r10_bio->read_slot].bio = bio;
 			if (mirror == -1) {
 				printk(KERN_ALERT "raid10: %s: unrecoverable I/O"
 				       " read error for block %llu\n",
@@ -1248,15 +1253,14 @@
 					       " another mirror\n",
 					       bdevname(rdev->bdev,b),
 					       (unsigned long long)r10_bio->sector);
-				bio->bi_bdev = rdev->bdev;
+				bio = bio_clone(r10_bio->master_bio, GFP_NOIO);
+				r10_bio->devs[r10_bio->read_slot].bio = bio;
 				bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr
 					+ rdev->data_offset;
-				bio->bi_next = NULL;
-				bio->bi_flags &= (1<<BIO_CLONED);
-				bio->bi_flags |= 1 << BIO_UPTODATE;
-				bio->bi_idx = 0;
-				bio->bi_size = r10_bio->sectors << 9;
+				bio->bi_bdev = rdev->bdev;
 				bio->bi_rw = READ;
+				bio->bi_private = r10_bio;
+				bio->bi_end_io = raid10_end_read_request;
 				unplug = 1;
 				generic_make_request(bio);
 			}
@@ -1468,7 +1472,7 @@
 		set_bit(R10BIO_IsSync, &r10_bio->state);
 		raid10_find_phys(conf, r10_bio);
 		r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1;
-		spin_lock_irq(&conf->device_lock);
+
 		for (i=0; i<conf->copies; i++) {
 			int d = r10_bio->devs[i].devnum;
 			bio = r10_bio->devs[i].bio;
@@ -1488,14 +1492,15 @@
 			bio->bi_bdev = conf->mirrors[d].rdev->bdev;
 			count++;
 		}
-		spin_unlock_irq(&conf->device_lock);
+
 		if (count < 2) {
 			for (i=0; i<conf->copies; i++) {
 				int d = r10_bio->devs[i].devnum;
 				if (r10_bio->devs[i].bio->bi_end_io)
-					atomic_dec(&conf->mirrors[d].rdev->nr_pending);
+					rdev_dec_pending(conf->mirrors[d].rdev, mddev);
 			}
 			put_buf(r10_bio);
+			biolist = NULL;
 			goto giveup;
 		}
 	}
@@ -1557,7 +1562,7 @@
 		}
 	}
 
-	return nr_sectors;
+	return sectors_skipped + nr_sectors;
  giveup:
 	/* There is nowhere to write, so all non-sync
 	 * drives must be failed, so try the next chunk...
diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c
--- a/drivers/md/raid5.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/md/raid5.c	2004-10-28 22:25:57 -07:00
@@ -1247,13 +1247,13 @@
 		else
 			bi->bi_end_io = raid5_end_read_request;
  
-		spin_lock_irq(&conf->device_lock);
+		rcu_read_lock();
 		rdev = conf->disks[i].rdev;
 		if (rdev && rdev->faulty)
 			rdev = NULL;
 		if (rdev)
 			atomic_inc(&rdev->nr_pending);
-		spin_unlock_irq(&conf->device_lock);
+		rcu_read_unlock();
  
 		if (rdev) {
 			if (test_bit(R5_Syncio, &sh->dev[i].flags))
@@ -1302,25 +1302,24 @@
 {
 	raid5_conf_t *conf = mddev_to_conf(mddev);
 	int i;
-	unsigned long flags;
 
-	spin_lock_irqsave(&conf->device_lock, flags);
+	rcu_read_lock();
 	for (i=0; i<mddev->raid_disks; i++) {
 		mdk_rdev_t *rdev = conf->disks[i].rdev;
-		if (rdev && atomic_read(&rdev->nr_pending)) {
+		if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
 			request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
 
 			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irqrestore(&conf->device_lock, flags);
+			rcu_read_unlock();
 
-			if (r_queue && r_queue->unplug_fn)
+			if (r_queue->unplug_fn)
 				r_queue->unplug_fn(r_queue);
 
-			spin_lock_irqsave(&conf->device_lock, flags);
-			atomic_dec(&rdev->nr_pending);
+			rdev_dec_pending(rdev, mddev);
+			rcu_read_lock();
 		}
 	}
-	spin_unlock_irqrestore(&conf->device_lock, flags);
+	rcu_read_unlock();
 }
 
 static void raid5_unplug_device(request_queue_t *q)
@@ -1347,29 +1346,26 @@
 	raid5_conf_t *conf = mddev_to_conf(mddev);
 	int i, ret = 0;
 
-	for (i=0; i<mddev->raid_disks; i++) {
+	rcu_read_lock();
+	for (i=0; i<mddev->raid_disks && ret == 0; i++) {
 		mdk_rdev_t *rdev = conf->disks[i].rdev;
 		if (rdev && !rdev->faulty) {
 			struct block_device *bdev = rdev->bdev;
-			request_queue_t *r_queue;
+			request_queue_t *r_queue = bdev_get_queue(bdev);
 
-			if (!bdev)
-				continue;
-
-			r_queue = bdev_get_queue(bdev);
-			if (!r_queue)
-				continue;
-
-			if (!r_queue->issue_flush_fn) {
+			if (!r_queue->issue_flush_fn)
 				ret = -EOPNOTSUPP;
-				break;
+			else {
+				atomic_inc(&rdev->nr_pending);
+				rcu_read_unlock();
+				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
+							      error_sector);
+				rdev_dec_pending(rdev, mddev);
+				rcu_read_lock();
 			}
-
-			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-			if (ret)
-				break;
 		}
 	}
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -1799,7 +1795,6 @@
 	raid5_conf_t *conf = mddev->private;
 	struct disk_info *tmp;
 
-	spin_lock_irq(&conf->device_lock);
 	for (i = 0; i < conf->raid_disks; i++) {
 		tmp = conf->disks + i;
 		if (tmp->rdev
@@ -1811,7 +1806,6 @@
 			tmp->rdev->in_sync = 1;
 		}
 	}
-	spin_unlock_irq(&conf->device_lock);
 	print_raid5_conf(conf);
 	return 0;
 }
@@ -1819,25 +1813,28 @@
 static int raid5_remove_disk(mddev_t *mddev, int number)
 {
 	raid5_conf_t *conf = mddev->private;
-	int err = 1;
+	int err = 0;
+	mdk_rdev_t *rdev;
 	struct disk_info *p = conf->disks + number;
 
 	print_raid5_conf(conf);
-	spin_lock_irq(&conf->device_lock);
-
-	if (p->rdev) {
-		if (p->rdev->in_sync || 
-		    atomic_read(&p->rdev->nr_pending)) {
+	rdev = p->rdev;
+	if (rdev) {
+		if (rdev->in_sync ||
+		    atomic_read(&rdev->nr_pending)) {
 			err = -EBUSY;
 			goto abort;
 		}
 		p->rdev = NULL;
-		err = 0;
+		synchronize_kernel();
+		if (atomic_read(&rdev->nr_pending)) {
+			/* lost the race, try later */
+			err = -EBUSY;
+			p->rdev = rdev;
+		}
 	}
-	if (err)
-		MD_BUG();
 abort:
-	spin_unlock_irq(&conf->device_lock);
+
 	print_raid5_conf(conf);
 	return err;
 }
@@ -1849,19 +1846,17 @@
 	int disk;
 	struct disk_info *p;
 
-	spin_lock_irq(&conf->device_lock);
 	/*
 	 * find the disk ...
 	 */
 	for (disk=0; disk < mddev->raid_disks; disk++)
 		if ((p=conf->disks + disk)->rdev == NULL) {
-			p->rdev = rdev;
 			rdev->in_sync = 0;
 			rdev->raid_disk = disk;
 			found = 1;
+			p->rdev = rdev;
 			break;
 		}
-	spin_unlock_irq(&conf->device_lock);
 	print_raid5_conf(conf);
 	return found;
 }
diff -Nru a/drivers/md/raid6main.c b/drivers/md/raid6main.c
--- a/drivers/md/raid6main.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/md/raid6main.c	2004-10-28 22:25:56 -07:00
@@ -1409,13 +1409,13 @@
 		else
 			bi->bi_end_io = raid6_end_read_request;
 
-		spin_lock_irq(&conf->device_lock);
+		rcu_read_lock();
 		rdev = conf->disks[i].rdev;
 		if (rdev && rdev->faulty)
 			rdev = NULL;
 		if (rdev)
 			atomic_inc(&rdev->nr_pending);
-		spin_unlock_irq(&conf->device_lock);
+		rcu_read_unlock();
 
 		if (rdev) {
 			if (test_bit(R5_Syncio, &sh->dev[i].flags))
@@ -1464,25 +1464,24 @@
 {
 	raid6_conf_t *conf = mddev_to_conf(mddev);
 	int i;
-	unsigned long flags;
 
-	spin_lock_irqsave(&conf->device_lock, flags);
+	rcu_read_lock();
 	for (i=0; i<mddev->raid_disks; i++) {
 		mdk_rdev_t *rdev = conf->disks[i].rdev;
-		if (rdev && atomic_read(&rdev->nr_pending)) {
+		if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
 			request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
 
 			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irqrestore(&conf->device_lock, flags);
+			rcu_read_unlock();
 
-			if (r_queue && r_queue->unplug_fn)
+			if (r_queue->unplug_fn)
 				r_queue->unplug_fn(r_queue);
 
-			spin_lock_irqsave(&conf->device_lock, flags);
-			atomic_dec(&rdev->nr_pending);
+			rdev_dec_pending(rdev, mddev);
+			rcu_read_lock();
 		}
 	}
-	spin_unlock_irqrestore(&conf->device_lock, flags);
+	rcu_read_unlock();
 }
 
 static void raid6_unplug_device(request_queue_t *q)
@@ -1509,29 +1508,26 @@
 	raid6_conf_t *conf = mddev_to_conf(mddev);
 	int i, ret = 0;
 
-	for (i=0; i<mddev->raid_disks; i++) {
+	rcu_read_lock();
+	for (i=0; i<mddev->raid_disks && ret == 0; i++) {
 		mdk_rdev_t *rdev = conf->disks[i].rdev;
 		if (rdev && !rdev->faulty) {
 			struct block_device *bdev = rdev->bdev;
-			request_queue_t *r_queue;
+			request_queue_t *r_queue = bdev_get_queue(bdev);
 
-			if (!bdev)
-				continue;
-
-			r_queue = bdev_get_queue(bdev);
-			if (!r_queue)
-				continue;
-
-			if (!r_queue->issue_flush_fn) {
+			if (!r_queue->issue_flush_fn)
 				ret = -EOPNOTSUPP;
-				break;
+			else {
+				atomic_inc(&rdev->nr_pending);
+				rcu_read_unlock();
+				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
+							      error_sector);
+				rdev_dec_pending(rdev, mddev);
+				rcu_read_lock();
 			}
-
-			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
-			if (ret)
-				break;
 		}
 	}
+	rcu_read_unlock();
 	return ret;
 }
 
@@ -1968,7 +1964,6 @@
 	raid6_conf_t *conf = mddev->private;
 	struct disk_info *tmp;
 
-	spin_lock_irq(&conf->device_lock);
 	for (i = 0; i < conf->raid_disks; i++) {
 		tmp = conf->disks + i;
 		if (tmp->rdev
@@ -1980,7 +1975,6 @@
 			tmp->rdev->in_sync = 1;
 		}
 	}
-	spin_unlock_irq(&conf->device_lock);
 	print_raid6_conf(conf);
 	return 0;
 }
@@ -1988,25 +1982,29 @@
 static int raid6_remove_disk(mddev_t *mddev, int number)
 {
 	raid6_conf_t *conf = mddev->private;
-	int err = 1;
+	int err = 0;
+	mdk_rdev_t *rdev;
 	struct disk_info *p = conf->disks + number;
 
 	print_raid6_conf(conf);
-	spin_lock_irq(&conf->device_lock);
-
-	if (p->rdev) {
-		if (p->rdev->in_sync ||
-		    atomic_read(&p->rdev->nr_pending)) {
+	rdev = p->rdev;
+	if (rdev) {
+		if (rdev->in_sync ||
+		    atomic_read(&rdev->nr_pending)) {
 			err = -EBUSY;
 			goto abort;
 		}
 		p->rdev = NULL;
-		err = 0;
+		synchronize_kernel();
+		if (atomic_read(&rdev->nr_pending)) {
+			/* lost the race, try later */
+			err = -EBUSY;
+			p->rdev = rdev;
+		}
 	}
-	if (err)
-		MD_BUG();
+
 abort:
-	spin_unlock_irq(&conf->device_lock);
+
 	print_raid6_conf(conf);
 	return err;
 }
@@ -2018,19 +2016,17 @@
 	int disk;
 	struct disk_info *p;
 
-	spin_lock_irq(&conf->device_lock);
 	/*
 	 * find the disk ...
 	 */
 	for (disk=0; disk < mddev->raid_disks; disk++)
 		if ((p=conf->disks + disk)->rdev == NULL) {
-			p->rdev = rdev;
 			rdev->in_sync = 0;
 			rdev->raid_disk = disk;
 			found = 1;
+			p->rdev = rdev;
 			break;
 		}
-	spin_unlock_irq(&conf->device_lock);
 	print_raid6_conf(conf);
 	return found;
 }
diff -Nru a/drivers/media/Kconfig b/drivers/media/Kconfig
--- a/drivers/media/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/Kconfig	2004-10-28 22:25:59 -07:00
@@ -34,27 +34,15 @@
 
 config VIDEO_TUNER
 	tristate
-	default y if VIDEO_BT848=y || VIDEO_SAA7134=y || VIDEO_MXB=y || VIDEO_CX88=y
-	default m if VIDEO_BT848=m || VIDEO_SAA7134=m || VIDEO_MXB=m || VIDEO_CX88=m
-	depends on VIDEO_DEV
 
 config VIDEO_BUF
 	tristate
-	default y if VIDEO_BT848=y || VIDEO_SAA7134=y || VIDEO_SAA7146=y || VIDEO_CX88=y
-	default m if VIDEO_BT848=m || VIDEO_SAA7134=m || VIDEO_SAA7146=m || VIDEO_CX88=m
-	depends on VIDEO_DEV
 
 config VIDEO_BTCX
 	tristate
-	default y if VIDEO_BT848=y || VIDEO_CX88=y
-	default m if VIDEO_BT848=m || VIDEO_CX88=m
-	depends on VIDEO_DEV
 
 config VIDEO_IR
 	tristate
-	default y if VIDEO_BT848=y || VIDEO_SAA7134=y
-	default m if VIDEO_BT848=m || VIDEO_SAA7134=m
-	depends on VIDEO_DEV
 
 endmenu
 
diff -Nru a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
--- a/drivers/media/common/ir-common.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/common/ir-common.c	2004-10-28 22:25:58 -07:00
@@ -1,4 +1,6 @@
 /*
+ * $Id: ir-common.c,v 1.4 2004/10/13 10:39:00 kraxel Exp $
+ *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
  *
@@ -100,7 +102,7 @@
 	[ 0x2a ] = KEY_RESERVED,        // timed page/channel clck
 	[ 0x2b ] = KEY_RESERVED,        // increment (USA)
 	[ 0x2c ] = KEY_RESERVED,        // decrement (USA)
-	[ 0x2d ] = KEY_RESERVED,        // 
+	[ 0x2d ] = KEY_RESERVED,        //
 	[ 0x2f ] = KEY_RESERVED,        // PIP shift
 	[ 0x31 ] = KEY_RESERVED,        // erase
 	[ 0x34 ] = KEY_RESERVED,        // wind
@@ -141,7 +143,7 @@
 		   int ir_type, IR_KEYTAB_TYPE *ir_codes)
 {
 	int i;
-	
+
 	ir->ir_type = ir_type;
 	if (ir_codes)
 		memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
@@ -171,7 +173,7 @@
 		      u32 ir_key, u32 ir_raw)
 {
 	u32 keycode = IR_KEYCODE(ir->ir_codes, ir_key);
-	
+
 	if (ir->keypressed && ir->keycode != keycode) {
 		ir->keypressed = 0;
 		ir_input_key_event(dev,ir);
diff -Nru a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
--- a/drivers/media/dvb/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/Kconfig	2004-10-28 22:25:57 -07:00
@@ -32,6 +32,7 @@
 source "drivers/media/dvb/ttusb-budget/Kconfig"
 source "drivers/media/dvb/ttusb-dec/Kconfig"
 source "drivers/media/dvb/dibusb/Kconfig"
+source "drivers/media/dvb/cinergyT2/Kconfig"
 
 comment "Supported FlexCopII (B2C2) Adapters"
 	depends on DVB_CORE && PCI
diff -Nru a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
--- a/drivers/media/dvb/Makefile	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/Makefile	2004-10-28 22:25:58 -07:00
@@ -2,4 +2,4 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dibusb/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dibusb/ cinergyT2/
diff -Nru a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
--- a/drivers/media/dvb/bt8xx/bt878.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/bt8xx/bt878.c	2004-10-28 22:25:58 -07:00
@@ -511,7 +511,7 @@
 		printk("bt878(%d): unloading\n", bt->nr);
 
 	/* turn off all capturing, DMA and IRQs */
-	btand(~13, BT878_AGPIO_DMA_CTL);
+	btand(~0x13, BT878_AGPIO_DMA_CTL);
 
 	/* first disable interrupts before unmapping the memory! */
 	btwrite(0, BT878_AINT_MASK);
@@ -554,7 +554,7 @@
       .name 	= "bt878",
       .id_table = bt878_pci_tbl,
       .probe 	= bt878_probe,
-      .remove 	= __devexit_p(bt878_remove),
+      .remove 	= bt878_remove,
 };
 
 static int bt878_pci_driver_registered = 0;
diff -Nru a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c	2004-10-28 22:25:57 -07:00
@@ -68,20 +68,21 @@
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct dvb_bt8xx_card *card = dvbdmx->priv;
+	int rc;
 
 	dprintk("dvb_bt8xx: start_feed\n");
 	
 	if (!dvbdmx->dmx.frontend)
 		return -EINVAL;
 
-	if (card->active)
-		return 0;
-		
-	card->active = 1;
-	
-//	bt878_start(card->bt, card->gpio_mode);
-
-	return 0;
+	down(&card->lock);
+	card->nfeeds++;
+	rc = card->nfeeds;
+	if (card->nfeeds == 1)
+		bt878_start(card->bt, card->gpio_mode,
+			    card->op_sync_orin, card->irq_err_ignore);
+	up(&card->lock);
+	return rc;
 }
 
 static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
@@ -94,12 +95,11 @@
 	if (!dvbdmx->dmx.frontend)
 		return -EINVAL;
 		
-	if (!card->active)
-		return 0;
-
-//	bt878_stop(card->bt);
-
-	card->active = 0;
+	down(&card->lock);
+	card->nfeeds--;
+	if (card->nfeeds == 0)
+		bt878_stop(card->bt);
+	up(&card->lock);
 
 	return 0;
 }
@@ -207,8 +207,6 @@
 
 	tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
 	
-	bt878_start(card->bt, card->gpio_mode, card->op_sync_orin, card->irq_err_ignore);
-
 	return 0;
 }
 
@@ -223,6 +221,7 @@
 		return -ENOMEM;
 
 	memset(card, 0, sizeof(*card));
+	init_MUTEX(&card->lock);
 	card->bttv_nr = sub->core->nr;
 	strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
 	card->i2c_adapter = &sub->core->i2c_adap;
@@ -230,6 +229,9 @@
 	switch(sub->core->type)
 	{
 	case BTTV_PINNACLESAT:
+#ifdef BTTV_DVICO_DVBT_LITE
+	case BTTV_DVICO_DVBT_LITE:
+#endif
 		card->gpio_mode = 0x0400C060;
 		card->op_sync_orin = 0;
 		card->irq_err_ignore = 0;
@@ -287,7 +289,10 @@
 	}
 
 	if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
-		printk("dvb_bt8xx: unable to determine DMA core of card %d\n", card->bttv_nr);
+		printk("dvb_bt8xx: unable to determine DMA core of card %d,\n",
+		       card->bttv_nr);
+		printk("dvb_bt8xx: if you have the ALSA bt87x audio driver "
+		       "installed, try removing it.\n");
 
 		kfree(card);
 		return -EFAULT;
@@ -321,7 +326,6 @@
 		dvb_dmx_release(&card->demux);
 		dvb_unregister_adapter(card->dvb_adapter);
 		
-		list_del(&card->list);
 		kfree(card);
 
 	return 0;
diff -Nru a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h	2004-10-28 22:25:59 -07:00
@@ -28,8 +28,8 @@
 #include "bttv.h"
 
 struct dvb_bt8xx_card {
-	struct list_head list;
-	u8 active;
+	struct semaphore lock;
+	int nfeeds;
 	char card_name[32];
 	struct dvb_adapter *dvb_adapter;
 	struct bt878 *bt;
diff -Nru a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/dvb/cinergyT2/Kconfig	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,59 @@
+config DVB_CINERGYT2
+	tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver"
+	depends on DVB_CORE && USB
+	help
+	  Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
+
+	  Say Y if you own such a device and want to use it.
+
+
+config DVB_CINERGYT2_TUNING
+	bool "sophisticated fine-tuning for CinergyT2 cards"
+	depends on DVB_CINERGYT2
+	help
+	  Here you can fine-tune some parameters of the CinergyT2 driver.
+
+	  Normally you don't need to touch this, but in exotic setups you
+	  may fine-tune your setup and adjust e.g. DMA buffer sizes for
+	  a particular application.
+
+
+config DVB_CINERGYT2_STREAM_URB_COUNT
+	int "Number of queued USB Request Blocks for Highspeed Stream Transfers"
+	depends on DVB_CINERGYT2_TUNING
+        default "32"
+	help
+	  USB Request Blocks for Highspeed Stream transfers are queued in a
+	  for the Host Controller. Usually the default value is a safe choice.
+
+	  You may increase this number if you are using this device in a 
+	  Server Environment with many high-traffic USB Highspeed devices 
+	  sharing the same USB bus.
+
+
+config DVB_CINERGYT2_STREAM_BUF_SIZE
+	int "Size of URB Stream Buffers for Highspeed Transfers"
+	depends on DVB_CINERGYT2_TUNING
+        default "512"
+	help
+	  Should be a multiple of native buffer size of 512 bytes.
+	  Default value is a safe choice.
+
+	  You may increase this number if you are using this device in a 
+	  Server Environment with many high-traffic USB Highspeed devices 
+	  sharing the same USB bus.
+
+
+config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
+	bool "Register the onboard IR Remote Control Receiver as Input Device"
+	depends on DVB_CINERGYT2_TUNING
+        default "yes"
+	help
+	  Enable this option if you want to use the onboard Infrared Remote 
+	  Control Receiver as Linux-Input device.
+
+	  Right now only the keycode table for the default Remote Control
+	  delivered with the device is supported, please see the driver
+	  source code to find out how to add support for other controls.
+
+
diff -Nru a/drivers/media/dvb/cinergyT2/Makefile b/drivers/media/dvb/cinergyT2/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/dvb/cinergyT2/Makefile	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_CINERGYT2) += cinergyT2.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
diff -Nru a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,811 @@
+/*
+ * TerraTec Cinergy T²/qanu USB2 DVB-T adapter.
+ *
+ * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
+ *		    Holger Waechtler <holger@qanu.de>
+ *
+ *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
+ *
+ * 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.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/pci.h>
+#include <linux/input.h>
+#include <linux/dvb/frontend.h>
+
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+
+#ifdef CONFIG_DVB_CINERGYT2_TUNING
+	#define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
+	#define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
+	#ifdef CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
+		#define ENABLE_RC (1)
+	#endif
+#else
+	#define STREAM_URB_COUNT (32)
+	#define STREAM_BUF_SIZE (512)
+	#define ENABLE_RC (1)
+#endif
+
+#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"
+
+static int debug;
+module_param_named(debug, debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(level, args...) \
+            do { if ((debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0)
+
+enum cinergyt2_ep1_cmd {
+	CINERGYT2_EP1_PID_TABLE_RESET		= 0x01,
+	CINERGYT2_EP1_PID_SETUP			= 0x02,
+	CINERGYT2_EP1_CONTROL_STREAM_TRANSFER 	= 0x03,
+	CINERGYT2_EP1_SET_TUNER_PARAMETERS 	= 0x04,
+	CINERGYT2_EP1_GET_TUNER_STATUS		= 0x05,
+	CINERGYT2_EP1_START_SCAN		= 0x06,
+	CINERGYT2_EP1_CONTINUE_SCAN		= 0x07,
+	CINERGYT2_EP1_GET_RC_EVENTS		= 0x08,
+	CINERGYT2_EP1_SLEEP_MODE		= 0x09
+};
+
+static struct dvb_frontend_info cinergyt2_fe_info = {
+	.name = DRIVER_NAME,
+	.type = FE_OFDM,
+	.frequency_min = 174000000,
+	.frequency_max = 862000000,
+	.frequency_stepsize = 166667,
+	.notifier_delay = 0,
+	.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+		FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+		FE_CAN_FEC_AUTO |
+		FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS
+};
+
+struct cinergyt2 {
+	struct dvb_demux demux;
+	struct usb_device *udev;
+	struct semaphore sem;
+	struct dvb_adapter *adapter;
+	struct dvb_device *fedev;
+	struct dmxdev dmxdev;
+	struct dvb_net dvbnet;
+
+	int streaming;
+
+	void *streambuf;
+	dma_addr_t streambuf_dmahandle;
+	struct urb *stream_urb[STREAM_URB_COUNT];
+
+#ifdef ENABLE_RC
+	struct input_dev rc_input_dev;
+	struct work_struct rc_query_work;
+	int rc_input_event;
+#endif
+};
+
+enum {
+	CINERGYT2_RC_EVENT_TYPE_NONE = 0x00,
+	CINERGYT2_RC_EVENT_TYPE_NEC  = 0x01,
+	CINERGYT2_RC_EVENT_TYPE_RC5  = 0x02
+};
+
+struct cinergyt2_rc_event {
+	char type;
+	uint32_t value;
+} __attribute__((packed));
+
+static const uint32_t rc_keys [] = {
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xfe01eb04,	KEY_POWER,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xfd02eb04,	KEY_1,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xfc03eb04,	KEY_2,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xfb04eb04,	KEY_3,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xfa05eb04,	KEY_4,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf906eb04,	KEY_5,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf807eb04,	KEY_6,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf708eb04,	KEY_7,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf609eb04,	KEY_8,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf50aeb04,	KEY_9,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf30ceb04,	KEY_0,
+	CINERGYT2_RC_EVENT_TYPE_NEC,	0xf40beb04,	KEY_VIDEO,
+	CINERGYT2_RC_EVENT_TYPE_NEC,	0xf20deb04,	KEY_REFRESH,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf10eeb04,	KEY_SELECT,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xf00feb04,	KEY_EPG,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xef10eb04,	KEY_UP,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xeb14eb04,	KEY_DOWN,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xee11eb04,	KEY_LEFT,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xec13eb04,	KEY_RIGHT,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xed12eb04,	KEY_OK,	
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xea15eb04,	KEY_TEXT,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe916eb04,	KEY_INFO,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe817eb04,	KEY_RED,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe718eb04,	KEY_GREEN,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe619eb04,	KEY_YELLOW,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe51aeb04,	KEY_BLUE,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe31ceb04,	KEY_VOLUMEUP,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe11eeb04,	KEY_VOLUMEDOWN,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe21deb04,	KEY_MUTE,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe41beb04,	KEY_CHANNELUP,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xe01feb04,	KEY_CHANNELDOWN,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xbf40eb04,	KEY_PAUSE,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xb34ceb04,	KEY_PLAY,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xa758eb04,	KEY_RECORD,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xab54eb04,	KEY_PREVIOUS,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xb748eb04,	KEY_STOP,
+	CINERGYT2_RC_EVENT_TYPE_NEC, 	0xa35ceb04,	KEY_NEXT
+};
+
+static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs);
+
+static int cinergyt2_submit_stream_urb (struct cinergyt2 *cinergyt2, struct urb *urb)
+{
+	int err;
+
+	usb_fill_bulk_urb(urb,
+			  cinergyt2->udev,
+			  usb_rcvbulkpipe(cinergyt2->udev, 0x2),
+			  urb->transfer_buffer,
+			  STREAM_BUF_SIZE,
+			  cinergyt2_stream_irq,
+			  cinergyt2);
+
+	if ((err = usb_submit_urb(urb, GFP_ATOMIC)))
+		dprintk(1, "urb submission failed (err = %i)!\n", err);
+
+	return err;
+}
+
+static void cinergyt2_stream_irq (struct urb *urb, struct pt_regs *regs)
+{
+	struct cinergyt2 *cinergyt2 = urb->context;
+
+	if (urb->actual_length > 0)
+		dvb_dmx_swfilter(&cinergyt2->demux,
+				 urb->transfer_buffer, urb->actual_length);
+
+	if (cinergyt2->streaming)
+		cinergyt2_submit_stream_urb(cinergyt2, urb);
+}
+
+static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2)
+{
+	int i;
+
+	for (i=0; i<STREAM_URB_COUNT; i++)
+		if (cinergyt2->stream_urb[i])
+			usb_free_urb(cinergyt2->stream_urb[i]);
+
+	pci_free_consistent(NULL, STREAM_URB_COUNT*STREAM_BUF_SIZE,
+			    cinergyt2->streambuf, cinergyt2->streambuf_dmahandle);
+}
+
+static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2)
+{
+	int i;
+
+	cinergyt2->streambuf = pci_alloc_consistent(NULL, 
+					      STREAM_URB_COUNT*STREAM_BUF_SIZE,
+					      &cinergyt2->streambuf_dmahandle);
+	if (!cinergyt2->streambuf) {
+		dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n");
+		return -ENOMEM;
+	}
+
+	memset(cinergyt2->streambuf, 0, STREAM_URB_COUNT*STREAM_BUF_SIZE);
+
+	for (i=0; i<STREAM_URB_COUNT; i++) {
+		struct urb *urb;	
+
+		if (!(urb = usb_alloc_urb(0, GFP_ATOMIC))) {
+			dprintk(1, "failed to alloc consistent stream urbs, bailing out!\n");
+			cinergyt2_free_stream_urbs(cinergyt2);
+			return -ENOMEM;
+		}
+
+		urb->transfer_buffer = cinergyt2->streambuf + i * STREAM_BUF_SIZE;
+		urb->transfer_buffer_length = STREAM_BUF_SIZE;
+
+		cinergyt2->stream_urb[i] = urb;
+	}
+
+	return 0;
+}
+
+static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2)
+{
+	int i;
+
+	for (i=0; i<STREAM_URB_COUNT; i++)
+		if (cinergyt2->stream_urb[i])
+			usb_unlink_urb(cinergyt2->stream_urb[i]);
+}
+
+static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2)
+{
+	int i, err;
+
+	for (i=0; i<STREAM_URB_COUNT; i++) {
+		if ((err = cinergyt2_submit_stream_urb(cinergyt2, cinergyt2->stream_urb[i]))) {
+			cinergyt2_stop_stream_xfer(cinergyt2);
+			dprintk(1, "failed urb submission (%i: err = %i)!\n", i, err);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int cinergyt2_command (struct cinergyt2 *cinergyt2,
+		    char *send_buf, int send_buf_len,
+		    char *rec_buf, int rec_buf_len)
+{
+	int ret;
+	int actual_len;
+	char dummy;
+
+	if (down_interruptible(&cinergyt2->sem))
+		return -EBUSY;
+
+	ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1),
+			   send_buf, send_buf_len, &actual_len, HZ);
+
+	if (ret)
+		dprintk(1, "usb_bulk_msg() (send) failed, err %i\n", ret);
+	
+	if (!rec_buf)
+		rec_buf = &dummy;
+	
+	ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1),
+			   rec_buf, rec_buf_len, &actual_len, HZ);
+
+	if (ret)
+		dprintk(1, "usb_bulk_msg() (read) failed, err %i\n", ret);
+
+	up(&cinergyt2->sem);
+
+	return ret ? ret : actual_len;
+}
+
+static void cinergyt2_control_stream_transfer (struct cinergyt2 *cinergyt2, int enable)
+{
+	char buf [] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
+  	cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
+}
+
+static void cinergyt2_control_sleep_mode (struct cinergyt2 *cinergyt2, int sleep)
+{
+	char buf [] = { CINERGYT2_EP1_SLEEP_MODE, sleep ? 1 : 0 };
+  	cinergyt2_command(cinergyt2, buf, sizeof(buf), NULL, 0);
+}
+
+static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *demux = dvbdmxfeed->demux;
+	struct cinergyt2 *cinergyt2 = demux->priv;
+
+	
+	if (cinergyt2->streaming == 0) {
+	       	if (cinergyt2_start_stream_xfer (cinergyt2) == 0)
+		       cinergyt2_control_stream_transfer (cinergyt2, 1);
+	}
+
+	cinergyt2->streaming++;
+
+	return 0;
+}
+
+static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *demux = dvbdmxfeed->demux;
+	struct cinergyt2 *cinergyt2 = demux->priv;	
+
+	if (--cinergyt2->streaming == 0) {
+		cinergyt2_control_stream_transfer(cinergyt2, 0);
+		cinergyt2_stop_stream_xfer(cinergyt2);
+	}
+
+	return 0;
+}
+
+/**
+ *  convert linux-dvb frontend parameter set into TPS.
+ *  See ETSI ETS-300744, section 4.6.2, table 9 for details.
+ *
+ *  This function is probably reusable and may better get placed in a support
+ *  library.
+ *
+ *  We replace errornous fields by default TPS fields (the ones with value 0).
+ */
+
+static uint16_t compute_tps (struct dvb_frontend_parameters *param)
+{
+	uint16_t tps = 0;
+	struct dvb_ofdm_parameters *op = &param->u.ofdm;
+
+	switch (op->code_rate_HP) {
+		case FEC_2_3:
+			tps |= (1 << 7);
+			break;
+		case FEC_3_4:
+			tps |= (2 << 7);
+			break;
+		case FEC_5_6:
+			tps |= (3 << 7);
+			break;
+		case FEC_7_8:
+			tps |= (4 << 7);
+			break;
+		case FEC_1_2:
+		case FEC_AUTO:
+		default:
+			/* tps |= (0 << 7) */;
+	}
+
+	switch (op->code_rate_LP) {
+		case FEC_2_3:
+			tps |= (1 << 4);
+			break;
+		case FEC_3_4:
+			tps |= (2 << 4);
+			break;
+		case FEC_5_6:
+			tps |= (3 << 4);
+			break;
+		case FEC_7_8:
+			tps |= (4 << 4);
+			break;
+		case FEC_1_2:
+		case FEC_AUTO:
+		default:
+			/* tps |= (0 << 4) */;
+	}
+
+	switch (op->constellation) {
+		case QAM_16:
+			tps |= (1 << 13);
+			break;
+		case QAM_64:
+			tps |= (2 << 13);
+			break;
+		case QPSK:
+		default:
+			/* tps |= (0 << 13) */;
+	}
+
+	switch (op->transmission_mode) {
+		case TRANSMISSION_MODE_8K:
+			tps |= (1 << 0);
+			break;
+		case TRANSMISSION_MODE_2K:
+		default:
+			/* tps |= (0 << 0) */;
+	}
+
+	switch (op->guard_interval) {
+		case GUARD_INTERVAL_1_16:
+			tps |= (1 << 2);
+			break;
+		case GUARD_INTERVAL_1_8:
+			tps |= (2 << 2);
+			break;
+		case GUARD_INTERVAL_1_4:
+			tps |= (3 << 2);
+			break;
+		case GUARD_INTERVAL_1_32:
+		default:
+			/* tps |= (0 << 2) */;
+	}
+
+	switch (op->hierarchy_information) {
+		case HIERARCHY_1:
+			tps |= (1 << 10);
+			break;
+		case HIERARCHY_2:
+			tps |= (2 << 10);
+			break;
+		case HIERARCHY_4:
+			tps |= (3 << 10);
+			break;
+		case HIERARCHY_NONE:
+		default:
+			/* tps |= (0 << 10) */;
+	}
+
+	return tps;
+}
+
+struct dvbt_set_parameters_msg {
+	uint8_t cmd;
+	uint32_t freq;
+	uint8_t bandwidth;
+	uint16_t tps;
+	uint8_t flags;
+} __attribute__((packed));
+
+struct dvbt_get_parameters_msg {
+	uint32_t freq;
+	uint8_t bandwidth;
+	uint16_t tps;
+	uint8_t flags;
+	uint16_t gain;
+	uint8_t snr;
+	uint32_t viterbi_error_rate;
+	uint32_t rs_error_rate;
+	uint32_t uncorrected_block_count;
+	uint8_t lock_bits;
+	uint8_t prev_lock_bits;
+} __attribute__((packed));
+
+static int cinergyt2_fe_open (struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	cinergyt2_control_sleep_mode((struct cinergyt2 *) dvbdev->priv, 0);
+	return dvb_generic_open(inode, file);
+}
+
+static int cinergyt2_fe_release (struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	cinergyt2_control_sleep_mode((struct cinergyt2 *) dvbdev->priv, 1);
+	return dvb_generic_release (inode, file);
+}
+
+static int cinergyt2_fe_ioctl (struct inode *inode, struct file *file,
+			unsigned int cmd, void *arg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct cinergyt2 *cinergyt2 = dvbdev->priv;
+	int ret = 0;
+
+	switch (cmd) {
+	case FE_GET_INFO:
+		memcpy (arg, &cinergyt2_fe_info, sizeof(struct dvb_frontend_info));
+		break;
+
+	case FE_READ_STATUS:
+	{
+		struct dvbt_get_parameters_msg msg;
+		char cmd = CINERGYT2_EP1_GET_TUNER_STATUS;
+		fe_status_t *status = arg;
+
+		*status = 0;
+
+		cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg));
+		
+		if (msg.lock_bits & (1 << 6))
+			*status |= FE_HAS_LOCK;
+		if (msg.lock_bits & (1 << 5))
+			*status |= FE_HAS_SYNC;
+		if (msg.lock_bits & (1 << 4))
+			*status |= FE_HAS_CARRIER;
+		if (msg.lock_bits & (1 << 1))
+			*status |= FE_HAS_VITERBI;
+
+		break;
+	}
+
+	case FE_READ_BER:
+	{
+		struct dvbt_get_parameters_msg msg;
+		char cmd = CINERGYT2_EP1_GET_TUNER_STATUS;
+		u32 *ber = (u32 *) arg;
+
+		cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg));
+
+		*ber = le32_to_cpu(msg.viterbi_error_rate);
+
+		break;
+	}
+
+	case FE_READ_SIGNAL_STRENGTH:
+	{
+		struct dvbt_get_parameters_msg msg;
+		char cmd = CINERGYT2_EP1_GET_TUNER_STATUS;
+		u16 *signal = (u16 *) arg;
+
+		cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg));
+
+		*signal = ~(le16_to_cpu(msg.gain));
+
+		break;
+	}
+
+	case FE_READ_SNR:
+	{
+		struct dvbt_get_parameters_msg msg;
+		char cmd = CINERGYT2_EP1_GET_TUNER_STATUS;
+		u16 *snr = (u16 *) arg;
+
+		cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg));
+
+		*snr = (msg.snr << 8) | msg.snr;
+
+		break;
+	}
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+	{
+		struct dvbt_get_parameters_msg msg;
+		char cmd = CINERGYT2_EP1_GET_TUNER_STATUS;
+		u32 *ubc = (u32 *) arg;
+
+		cinergyt2_command(cinergyt2, &cmd, 1, (char *) &msg, sizeof(msg));
+
+		*ubc = le32_to_cpu(msg.uncorrected_block_count);
+
+		break;
+	}
+	
+	case FE_SET_FRONTEND:
+	{
+		struct dvb_frontend_parameters *p = (void*) arg;
+		struct dvb_ofdm_parameters *op = &p->u.ofdm;
+		struct dvbt_set_parameters_msg msg;
+
+		msg.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
+		msg.tps = cpu_to_le16(compute_tps(p));
+		msg.freq = cpu_to_le32(p->frequency / 1000);
+		msg.bandwidth = 8 - op->bandwidth - BANDWIDTH_8_MHZ;
+
+		cinergyt2_command(cinergyt2, (char *) &msg, sizeof(msg), NULL, 0);
+
+		break;
+	}
+
+	case FE_GET_FRONTEND:
+		/**
+		 *  trivial to implement (see struct dvbt_get_parameters_msg).
+		 *  equivalent to FE_READ ioctls, but needs 
+		 *  TPS -> linux-dvb parameter set conversion. Feel free
+		 *  to implement this and send us a patch if you need this
+		 *  functionality.
+		 */
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static 
+struct file_operations cinergyt2_fe_fops = {
+	.owner          = THIS_MODULE,
+	.ioctl          = dvb_generic_ioctl,
+	/**
+	 * do we really need this? If so, let's implement it via 
+	 * schedule_delayed_work() similiar to the IR code.
+	 */
+	/*.poll           = cinergyt2_fe_poll, */
+	.open           = cinergyt2_fe_open,
+	.release        = cinergyt2_fe_release
+};
+
+static struct dvb_device cinergyt2_fe_template = {
+	.users = ~0,
+	.writers = 1,
+	.readers = (~0)-1,
+	.fops = &cinergyt2_fe_fops,
+	.kernel_ioctl = cinergyt2_fe_ioctl
+};
+
+#ifdef ENABLE_RC
+static void cinergyt2_query_rc (void *data)
+{
+	struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data;
+	char buf [1] = { CINERGYT2_EP1_GET_RC_EVENTS };
+	struct cinergyt2_rc_event rc_events[12];
+	int n, len;
+
+	len = cinergyt2_command(cinergyt2, buf, sizeof(buf), 
+			     (char *) rc_events, sizeof(rc_events));
+
+	for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
+		int i;
+
+		if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
+		    rc_events[n].value == ~0)
+		{
+			/**
+			 * keyrepeat bit. If we would handle this properly
+			 * we would need to emit down events as long the
+			 * keyrepeat goes, a up event if no further 
+			 * repeat bits occur. Would need a timer to implement
+			 * and no other driver does this, so we simply
+			 * emit the last key up/down sequence again.
+			 */
+		} else {
+			cinergyt2->rc_input_event = KEY_MAX;
+			for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) {
+				if (rc_keys[i+0] == rc_events[n].type &&
+				    rc_keys[i+1] == rc_events[n].value)
+				{
+					cinergyt2->rc_input_event = rc_keys[i+2];
+					break;
+				}
+			}
+		}
+
+		if (cinergyt2->rc_input_event != KEY_MAX) {
+			input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1);
+			input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0);
+			input_sync(&cinergyt2->rc_input_dev);
+	    	}
+	}
+
+	schedule_delayed_work(&cinergyt2->rc_query_work, (HZ/5));
+}
+#endif
+
+static int cinergyt2_probe (struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct cinergyt2 *cinergyt2;
+	int i, err;
+
+	if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
+		dprintk(1, "out of memory?!?\n");
+		return -ENOMEM;
+	}
+
+	memset (cinergyt2, 0, sizeof (struct cinergyt2));
+	usb_set_intfdata (intf, (void *) cinergyt2);
+
+	init_MUTEX(&cinergyt2->sem);
+
+	cinergyt2->udev = interface_to_usbdev(intf);
+	
+	if (cinergyt2_alloc_stream_urbs (cinergyt2) < 0) {
+		dprintk(1, "unable to allocate stream urbs\n");
+		kfree(cinergyt2);
+		return -ENOMEM;
+	}
+
+	dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE);
+
+	cinergyt2->demux.priv = cinergyt2;
+	cinergyt2->demux.filternum = 256;
+	cinergyt2->demux.feednum = 256;
+	cinergyt2->demux.start_feed = cinergyt2_start_feed;
+	cinergyt2->demux.stop_feed = cinergyt2_stop_feed;
+	cinergyt2->demux.dmx.capabilities = DMX_TS_FILTERING |
+					 DMX_SECTION_FILTERING |
+					 DMX_MEMORY_BASED_FILTERING;
+
+	if ((err = dvb_dmx_init(&cinergyt2->demux)) < 0) {
+		dprintk(1, "dvb_dmx_init() failed (err = %d)\n", err);
+		goto bailout;
+	}
+
+	cinergyt2->dmxdev.filternum = cinergyt2->demux.filternum;
+	cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx;
+	cinergyt2->dmxdev.capabilities = 0;
+
+	if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, cinergyt2->adapter)) < 0) {
+		dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err);
+		goto bailout;
+	}
+
+	if (dvb_net_init(cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx))
+		dprintk(1, "dvb_net_init() failed!\n");
+
+	dvb_register_device(cinergyt2->adapter, &cinergyt2->fedev,
+			    &cinergyt2_fe_template, cinergyt2,
+			    DVB_DEVICE_FRONTEND);
+
+#ifdef ENABLE_RC
+	init_input_dev(&cinergyt2->rc_input_dev);			
+
+	cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY);
+	cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char);
+	cinergyt2->rc_input_dev.keycodemax = KEY_MAX;
+	cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
+	cinergyt2->rc_input_dev.id.bustype = BUS_USB;
+	cinergyt2->rc_input_dev.id.vendor = 0x0001;
+	cinergyt2->rc_input_dev.id.product = 0x0001;
+	cinergyt2->rc_input_dev.id.version = 0x0100;
+
+	for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3)
+		set_bit(rc_keys[i+2], cinergyt2->rc_input_dev.keybit);
+
+	input_register_device(&cinergyt2->rc_input_dev);
+
+	cinergyt2->rc_input_event = KEY_MAX;
+	
+	INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
+	schedule_delayed_work(&cinergyt2->rc_query_work, HZ);
+#endif
+
+	return 0;
+
+bailout:
+	dvb_dmxdev_release(&cinergyt2->dmxdev);
+	dvb_dmx_release(&cinergyt2->demux);
+	dvb_unregister_adapter (cinergyt2->adapter);
+	cinergyt2_free_stream_urbs (cinergyt2);
+	kfree(cinergyt2);
+	return -ENOMEM;
+}
+
+static void cinergyt2_disconnect (struct usb_interface *intf)
+{
+	struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
+
+#ifdef ENABLE_RC
+	cancel_delayed_work(&cinergyt2->rc_query_work);
+	flush_scheduled_work();
+	input_unregister_device(&cinergyt2->rc_input_dev);
+#endif
+
+	cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
+	dvb_net_release(&cinergyt2->dvbnet);
+	dvb_dmxdev_release(&cinergyt2->dmxdev);
+	dvb_dmx_release(&cinergyt2->demux);
+
+	dvb_unregister_device(cinergyt2->fedev);
+	dvb_unregister_adapter(cinergyt2->adapter);
+
+	cinergyt2_free_stream_urbs(cinergyt2);
+	kfree(cinergyt2);
+}
+
+static const struct usb_device_id cinergyt2_table [] __devinitdata = {
+	{ USB_DEVICE(0x0ccd, 0x0038) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(usb, cinergyt2_table);
+
+static struct usb_driver cinergyt2_driver = {
+	.owner 		= THIS_MODULE,
+	.name 		= "cinergyt2",
+	.probe 		= cinergyt2_probe,
+	.disconnect 	= cinergyt2_disconnect,
+	.id_table 	= cinergyt2_table
+};
+
+static int __init cinergyt2_init (void)
+{
+	int err;
+
+	if ((err = usb_register(&cinergyt2_driver)) < 0) {
+		dprintk(1, "usb_register() failed! (err %i)\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit cinergyt2_exit (void)
+{
+	usb_deregister(&cinergyt2_driver);
+}
+
+module_init (cinergyt2_init);
+module_exit (cinergyt2_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
+
diff -Nru a/drivers/media/dvb/dibusb/Kconfig b/drivers/media/dvb/dibusb/Kconfig
--- a/drivers/media/dvb/dibusb/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/dibusb/Kconfig	2004-10-28 22:25:57 -07:00
@@ -1,5 +1,5 @@
 config DVB_DIBUSB
-	tristate "Twinhan/KWorld/Hama/Artec USB DVB-T devices"
+	tristate "DiBcom/Twinhan/KWorld/Hama/Artec/Compro USB DVB-T devices"
 	depends on DVB_CORE && USB
 	select FW_LOADER
 	help
@@ -8,11 +8,13 @@
 
 	  Devices supported by this driver:
 
-	    Twinhan VisionPlus VisionDTV USB-Ter (VP7041)
+	    TwinhanDTV USB-Ter (VP7041)
+		TwinhanDTV Magic Box (VP7041e)
 	    KWorld V-Stream XPERT DTV - DVB-T USB
 	    Hama DVB-T USB-Box
 	    DiBcom reference device (non-public)
 	    Ultima Electronic/Artec T1 USB TVBOX
+	    Compro Videomate DVB-U2000 - DVB-T USB
 
 	  The VP7041 seems to be identical to "CTS Portable" (Chinese
 	  Television System).
@@ -20,7 +22,7 @@
 	  These devices can be understood as budget ones, they "only" deliver
 	  the MPEG data.
 
-	  Currently all known copies of the DiBcom reference design have the DiBcom 3000MB
+	  Currently all known copies of the DiBcom reference design have the DiBcom 3000-MB 
 	  frontend onboard. Please enable and load this one manually in order to use this
 	  device.
 
diff -Nru a/drivers/media/dvb/dibusb/dvb-dibusb.c b/drivers/media/dvb/dibusb/dvb-dibusb.c
--- a/drivers/media/dvb/dibusb/dvb-dibusb.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/dibusb/dvb-dibusb.c	2004-10-28 22:25:57 -07:00
@@ -20,9 +20,7 @@
  *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
  *  sources, on which this driver (and the dib3000mb frontend) are based.
  *
- *  TODO
- *   - probing for i2c addresses, it is possible, that they have been changed
- *     by the vendor
+ * 
  *
  * see Documentation/dvb/README.dibusb for more information
  */
@@ -57,7 +55,7 @@
 
 static int debug;
 module_param(debug, int, 0x644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore (|-able)).");
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err (|-able)).");
 #else
 #define dprintk_new(args...)
 #define debug_dump(b,l)
@@ -66,31 +64,14 @@
 #define deb_info(args...) dprintk_new(0x01,args)
 #define deb_xfer(args...) dprintk_new(0x02,args)
 #define deb_alot(args...) dprintk_new(0x04,args)
+#define deb_ts(args...)   dprintk_new(0x08,args)
+#define deb_err(args...)   dprintk_new(0x10,args)
 
 /* Version information */
 #define DRIVER_VERSION "0.0"
-#define DRIVER_DESC "DiBcom based USB Budget DVB-T device"
+#define DRIVER_DESC "Driver for DiBcom based USB Budget DVB-T device"
 #define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
 
-/* USB Driver stuff */
-
-/* table of devices that work with this driver */
-static struct usb_device_id dibusb_table [] = {
-	{ USB_DEVICE(USB_TWINHAN_VENDOR_ID, USB_VP7041_PRODUCT_PREFW_ID) },
-	{ USB_DEVICE(USB_TWINHAN_VENDOR_ID, USB_VP7041_PRODUCT_ID) },
-	{ USB_DEVICE(USB_IMC_NETWORKS_VENDOR_ID, USB_VP7041_PRODUCT_PREFW_ID) },
-	{ USB_DEVICE(USB_IMC_NETWORKS_VENDOR_ID, USB_VP7041_PRODUCT_ID) },
-	{ USB_DEVICE(USB_KWORLD_VENDOR_ID, USB_VSTREAM_PRODUCT_PREFW_ID) },
-	{ USB_DEVICE(USB_KWORLD_VENDOR_ID, USB_VSTREAM_PRODUCT_ID) },
-	{ USB_DEVICE(USB_DIBCOM_VENDOR_ID, USB_DIBCOM_PRODUCT_PREFW_ID) },
-	{ USB_DEVICE(USB_DIBCOM_VENDOR_ID, USB_DIBCOM_PRODUCT_ID) },
-	{ USB_DEVICE(USB_ULTIMA_ELECTRONIC_ID, USB_ULTIMA_ELEC_PROD_PREFW_ID) },
-	{ USB_DEVICE(USB_ULTIMA_ELECTRONIC_ID, USB_ULTIMA_ELEC_PROD_ID) },
-	{ }					/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, dibusb_table);
-
 static int dibusb_readwrite_usb(struct usb_dibusb *dib,
 		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
@@ -99,12 +80,14 @@
 	if (wbuf == NULL || wlen == 0)
 		return -EINVAL;
 
-/*	if (dib->disconnecting)
-		return -EINVAL;*/
-
 	if ((ret = down_interruptible(&dib->usb_sem)))
 		return ret;
 
+	if (dib->streaming && wbuf[0] == DIBUSB_REQ_I2C_WRITE)
+		deb_err("BUG: writing to i2c, while TS-streaming destroys the stream. What"
+			" did you do ? Please enable debugging and send the syslog to the author. (%x reg: %x %x)",
+			wbuf[0],wbuf[2],wbuf[3]);
+			
 	debug_dump(wbuf,wlen);
 
 	ret = usb_bulk_msg(dib->udev,COMMAND_PIPE,
@@ -189,6 +172,8 @@
 		(DIB3000MB_FIFO_ACTIVATE >> 8) & 0xff,
 		(DIB3000MB_FIFO_ACTIVATE) & 0xff
 	};
+	dib->streaming = 1;
+	deb_ts("start streaming\n");
 	return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
 }
 
@@ -200,11 +185,14 @@
 		(DIB3000MB_FIFO_INHIBIT >> 8) & 0xff,
 		(DIB3000MB_FIFO_INHIBIT) & 0xff
 	};
+	dib->streaming = 0;
+	deb_ts("stop streaming\n");
 	return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
 }
 
 static int dibusb_set_pid(struct dibusb_pid *dpid)
 {
+	struct usb_dibusb *dib = dpid->dib;
 	u16 pid = dpid->pid | (dpid->active ? DIB3000MB_ACTIVATE_FILTERING : 0);
 	u8 b[4] = {
 		(dpid->reg >> 8) & 0xff,
@@ -212,25 +200,50 @@
 		(pid >> 8) & 0xff,
 		(pid) & 0xff
 	};
+	int ret;
+	
+	/* firmware bug, i2c write during mpeg transfer */
+	if (dib->feedcount) {
+		deb_info("stop streaming\n");
+		ret = dibusb_stop_xfer(dib);
+	}
+	
+	if (dpid->active) 
+		dib->feedcount++;
+	else
+		dib->feedcount--;
 
-	return dibusb_i2c_msg(dpid->dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
+	ret = dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
+
+	if (ret == 0 && dib->feedcount) {
+		deb_info("start streaming\n");
+		ret = dibusb_start_xfer(dib);
+	}
+	return ret;
 }
 
 static void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
 {
 	struct usb_dibusb *dib = urb->context;
 
-	if (!dib->streaming)
-		return;
+	deb_xfer("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status);
 
-	if (urb->status == 0) {
-		deb_info("URB return len: %d\n",urb->actual_length);
+	if (dib->feedcount > 0 && urb->status == 0) {
+		deb_xfer("URB return len: %d\n",urb->actual_length);
 		if (urb->actual_length % 188)
-			deb_info("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188);
+			deb_xfer("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188);
+
+		/* Francois recommends to drop not full-filled packets, even if they may 
+		 * contain valid TS packets
+		 */
+		if (urb->actual_length == DIBUSB_TS_DEFAULT_SIZE && dib->dvb_is_ready)
 		dvb_dmx_swfilter_packets(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length/188);
-	}
+		else
+			deb_ts("URB dropped because of the " 
+					"actual_length or !dvb_is_ready (%d).\n",dib->dvb_is_ready);
+	} else 
+		deb_ts("URB dropped because of feedcount or status.\n");
 
-	if (dib->streaming)
 		usb_submit_urb(urb,GFP_KERNEL);
 }
 
@@ -240,9 +253,8 @@
 //	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
 	struct dibusb_pid *dpid;
-	int ret = 0;
 
-	deb_info("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
+	deb_ts("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
 
 	if ((dpid = dibusb_get_free_pid(dib)) == NULL) {
 		err("no free pid in list.");
@@ -253,32 +265,14 @@
 
 	dibusb_set_pid(dpid);
 
-	if (0 == dib->feed_count++) {
-		usb_fill_bulk_urb( dib->buf_urb, dib->udev, DATA_PIPE,
-			dib->buffer, 8192, dibusb_urb_complete, dib);
-		dib->buf_urb->transfer_flags = 0;
-
-
-		if ((ret = usb_submit_urb(dib->buf_urb,GFP_KERNEL))) {
-			dibusb_stop_xfer(dib);
-			err("could not submit buffer urb.");
-			return ret;
-		}
-
-		if ((ret = dibusb_start_xfer(dib)))
-			return ret;
-
-		dib->streaming = 1;
-	}
 	return 0;
 }
 
 static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-	struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
 	struct dibusb_pid *dpid = (struct dibusb_pid *) dvbdmxfeed->priv;
 
-	deb_info("stopfeed pid: 0x%04x, feedtype: %d",dvbdmxfeed->pid, dvbdmxfeed->type);
+	deb_ts("stopfeed pid: 0x%04x, feedtype: %d\n",dvbdmxfeed->pid, dvbdmxfeed->type);
 
 	if (dpid == NULL)
 		err("channel in dmxfeed->priv was NULL");
@@ -288,11 +282,6 @@
 		dibusb_set_pid(dpid);
 	}
 
-	if (--dib->feed_count == 0) {
-		dib->streaming = 0;
-		usb_unlink_urb(dib->buf_urb);
-		dibusb_stop_xfer(dib);
-	}
 	return 0;
 }
 
@@ -302,7 +291,7 @@
 
 /*
  * do not use this, just a workaround for a bug,
- * which will never occur :).
+ * which will hopefully never occur :).
  */
 static int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
 {
@@ -312,7 +301,8 @@
 
 /*
  * TODO: a tasklet should run with a delay of 1/10 second
- * and fill an appropriate event device ?
+ * and feed an appropriate event device ?
+ * NEC protocol is used for remote controlls
  */
 static int dibusb_read_remote_control(struct usb_dibusb *dib)
 {
@@ -321,6 +311,18 @@
 	if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5)))
 		return ret;
 
+
+	
+	switch (rb[0]) {
+		case DIBUSB_RC_NEC_KEY_PRESSED:
+
+			break;
+		case DIBUSB_RC_NEC_EMPTY:
+		case DIBUSB_RC_NEC_KEY_REPEATED:
+		default:
+			break;
+	}
+	
 	return 0;
 }
 
@@ -474,11 +476,13 @@
 err:
 	return ret;
 success:
+	dib->dvb_is_ready = 1;
 	return 0;
 }
 
 static int dibusb_dvb_exit(struct usb_dibusb *dib)
 {
+	dib->dvb_is_ready = 0;
 	deb_info("unregistering DVB part\n");
 	dvb_net_release(&dib->dvb_net);
 	dib->demux.dmx.close(&dib->demux.dmx);
@@ -492,8 +496,16 @@
 
 static int dibusb_exit(struct usb_dibusb *dib)
 {
-	usb_free_urb(dib->buf_urb);
-	pci_free_consistent(NULL,8192,dib->buffer,dib->dma_handle);
+	int i;
+	for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) 
+		if (dib->buf_urb[i] != NULL) {
+			deb_info("killing URB no. %d.\n",i);
+			usb_kill_urb(dib->buf_urb[i]); // TODO kernel version ifdef for unlink_urb
+			
+			deb_info("freeing URB no. %d.\n",i);
+			usb_free_urb(dib->buf_urb[i]);
+		}
+	pci_free_consistent(NULL,DIBUSB_TS_BUFFER_SIZE,dib->buffer,dib->dma_handle);
 	return 0;
 }
 
@@ -513,12 +525,28 @@
 
 	/* dibusb_reset_cpu(dib); */
 
-	dib->buffer = pci_alloc_consistent(NULL,8192, &dib->dma_handle);
-	memset(dib->buffer,0,8192);
-	if (!(dib->buf_urb = usb_alloc_urb(0,GFP_KERNEL))) {
+	if ((dib->buffer = pci_alloc_consistent(NULL,DIBUSB_TS_BUFFER_SIZE, &dib->dma_handle)) == NULL) {
+		return -ENOMEM;
+	}
+	memset(dib->buffer,0,DIBUSB_TS_BUFFER_SIZE);
+	for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) {
+		if (!(dib->buf_urb[i] = usb_alloc_urb(0,GFP_KERNEL))) {
 		dibusb_exit(dib);
 		return -ENOMEM;
 	}
+		deb_info("submitting URB no. %d\n",i);
+
+		usb_fill_bulk_urb( dib->buf_urb[i], dib->udev, DATA_PIPE,
+				&dib->buffer[i*DIBUSB_TS_URB_BUFFER_SIZE], DIBUSB_TS_URB_BUFFER_SIZE, 
+				dibusb_urb_complete, dib);
+		dib->buf_urb[i]->transfer_flags = 0;
+
+		if ((ret = usb_submit_urb(dib->buf_urb[i],GFP_KERNEL))) {
+			err("could not submit buffer urb no. %d\n",i);
+			dibusb_exit(dib);
+			return ret;
+		}
+	}
 
 	for (i=0; i < DIBUSB_MAX_PIDS; i++) {
 		dib->pid_list[i].reg = i+DIB3000MB_REG_FIRST_PID;
@@ -527,8 +555,9 @@
 		dib->pid_list[i].dib = dib;
 	}
 
+	dib->feedcount = 0;
 	dib->streaming = 0;
-	dib->feed_count = 0;
+	dib->dvb_is_ready = 0;
 
 	if ((ret = dibusb_dvb_init(dib))) {
 		dibusb_exit(dib);
@@ -591,19 +620,23 @@
 			if (ret != b[0]) {
 				err("error while transferring firmware "
 					"(transferred size: %d, block size: %d)",
-					ret,b[1]);
+					ret,b[0]);
 				ret = -EINVAL;
 				break;
 			}
 			i += 5 + b[0];
 		}
+		/* length in ret */
+		if (ret > 0)
+			ret = 0;
 		/* restart the CPU */
 		reset = 0;
-		if ((ret = dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1)) != 1)
+		if (ret || dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1) != 1) {
 			err("could not restart the USB controller CPU.");
+			ret = -EINVAL;
+		}
 
 		kfree(p);
-		ret = 0;
 	} else {
 		ret = -ENOMEM;
 	}
diff -Nru a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h
--- a/drivers/media/dvb/dibusb/dvb-dibusb.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/dibusb/dvb-dibusb.h	2004-10-28 22:25:57 -07:00
@@ -7,6 +7,7 @@
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
  *
+ * 
  *
  * for more information see dvb-dibusb.c .
  */
@@ -14,24 +15,102 @@
 #ifndef __DVB_DIBUSB_H__
 #define __DVB_DIBUSB_H__
 
+#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT	0x10
+
 /* Vendor IDs */
-#define USB_TWINHAN_VENDOR_ID			0x1822
-#define USB_IMC_NETWORKS_VENDOR_ID		0x13d3
-#define USB_KWORLD_VENDOR_ID			0xeb1a
-#define USB_DIBCOM_VENDOR_ID			0x10b8
-#define USB_ULTIMA_ELECTRONIC_ID		0x05d8
+#define USB_VID_TWINHAN_ID					0x1822
+#define USB_VID_IMC_NETWORKS_ID				0x13d3
+#define USB_VID_EMPIA_ID					0xeb1a
+#define USB_VID_DIBCOM_ID					0x10b8
+#define USB_VID_ULTIMA_ELECTRONIC_ID		0x05d8
+#define USB_VID_COMPRO_ID					0x185b
+#define USB_VID_HYPER_PALTEK				0x1025
 
 /* Product IDs before loading the firmware */
-#define USB_VP7041_PRODUCT_PREFW_ID		0x3201
-#define USB_VSTREAM_PRODUCT_PREFW_ID	0x17de
-#define USB_DIBCOM_PRODUCT_PREFW_ID		0x0bb8
-#define USB_ULTIMA_ELEC_PROD_PREFW_ID	0x8105
+#define USB_PID_TWINHAN_VP7041_COLD_ID		0x3201
+#define USB_PID_KWORLD_VSTREAM_COLD_ID		0x17de
+#define USB_PID_DIBCOM_MOD3000_COLD_ID		0x0bb8
+#define USB_PID_ULTIMA_TVBOX_COLD_ID		0x8105
+#define USB_PID_COMPRO_DVBU2000_COLD_ID		0xd000
+#define USB_PID_UNK_HYPER_PALTEK_COLD_ID	0x005e
 
 /* product ID afterwards */
-#define USB_VP7041_PRODUCT_ID			0x3202
-#define USB_VSTREAM_PRODUCT_ID			0x17df
-#define USB_DIBCOM_PRODUCT_ID			0x0bb9
-#define USB_ULTIMA_ELEC_PROD_ID			0x8106
+#define USB_PID_TWINHAN_VP7041_WARM_ID		0x3202
+#define USB_PID_KWORLD_VSTREAM_WARM_ID		0x17df
+#define USB_PID_DIBCOM_MOD3000_WARM_ID		0x0bb9
+#define USB_PID_ULTIMA_TVBOX_WARM_ID		0x8106
+#define USB_PID_COMPRO_DVBU2000_WARM_ID		0xd001
+#define USB_PID_UNK_HYPER_PALTEK_WARM_ID	0x005f
+
+/* static array of valid firmware names, the best one first */
+static const char * valid_firmware_filenames[] = {
+	"dvb-dibusb-5.0.0.11.fw",
+};
+
+struct dibusb_device {
+	u16 cold_product_id;
+	u16 warm_product_id;
+	u8 demod_addr;
+	const char *name;
+};
+
+#define DIBUSB_SUPPORTED_DEVICES	6
+
+/* USB Driver stuff */
+static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = {
+	{	.cold_product_id = USB_PID_TWINHAN_VP7041_COLD_ID, 
+		.warm_product_id = USB_PID_TWINHAN_VP7041_WARM_ID,
+		.name = "TwinhanDTV USB-Ter/Magic Box / HAMA USB DVB-T device", 
+		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+	},
+	{	.cold_product_id = USB_PID_KWORLD_VSTREAM_COLD_ID,
+		.warm_product_id = USB_PID_KWORLD_VSTREAM_WARM_ID,
+		.name = "KWorld V-Stream XPERT DTV - DVB-T USB",
+		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+	},
+	{	.cold_product_id = USB_PID_DIBCOM_MOD3000_COLD_ID,
+		.warm_product_id = USB_PID_DIBCOM_MOD3000_WARM_ID,
+		.name = "DiBcom USB DVB-T reference design (MOD300)",
+		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+	},
+	{	.cold_product_id = USB_PID_ULTIMA_TVBOX_COLD_ID,
+		.warm_product_id = USB_PID_ULTIMA_TVBOX_WARM_ID,
+		.name = "Ultima Electronic/Artec T1 USB TVBOX",
+		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+	},
+	{	.cold_product_id = USB_PID_COMPRO_DVBU2000_COLD_ID,
+		.warm_product_id = USB_PID_COMPRO_DVBU2000_WARM_ID,
+		.name = "Compro Videomate DVB-U2000 - DVB-T USB",
+		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+	},
+	{	.cold_product_id = USB_PID_UNK_HYPER_PALTEK_COLD_ID,
+		.warm_product_id = USB_PID_UNK_HYPER_PALTEK_WARM_ID,
+		.name = "Unkown USB DVB-T device ???? please report the name to linux-dvb or to the author",
+		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+	}
+};
+
+/* USB Driver stuff */
+/* table of devices that work with this driver */
+static struct usb_device_id dibusb_table [] = {
+	{ USB_DEVICE(USB_VID_TWINHAN_ID, 	USB_PID_TWINHAN_VP7041_COLD_ID) },
+	{ USB_DEVICE(USB_VID_TWINHAN_ID, 	USB_PID_TWINHAN_VP7041_WARM_ID) },
+	{ USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_COLD_ID) },
+	{ USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_WARM_ID) },
+	{ USB_DEVICE(USB_VID_EMPIA_ID,		USB_PID_KWORLD_VSTREAM_COLD_ID) },
+	{ USB_DEVICE(USB_VID_EMPIA_ID,		USB_PID_KWORLD_VSTREAM_WARM_ID) },
+	{ USB_DEVICE(USB_VID_DIBCOM_ID,		USB_PID_DIBCOM_MOD3000_COLD_ID) },
+	{ USB_DEVICE(USB_VID_DIBCOM_ID,		USB_PID_DIBCOM_MOD3000_WARM_ID) },
+	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_COLD_ID) },
+	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_WARM_ID) },
+	{ USB_DEVICE(USB_VID_COMPRO_ID,		USB_PID_COMPRO_DVBU2000_COLD_ID) },
+	{ USB_DEVICE(USB_VID_COMPRO_ID,		USB_PID_COMPRO_DVBU2000_WARM_ID) },
+	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_COLD_ID) },
+	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_WARM_ID) },
+	{ }                 /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, dibusb_table);
 
 /* CS register start/stop the usb controller cpu */
 #define DIBUSB_CPU_CSREG				0x7F92
@@ -53,15 +132,20 @@
 	struct usb_dibusb *dib;
 };
 
+#define DIBUSB_TS_NUM_URBS			3
+#define DIBUSB_TS_URB_BUFFER_SIZE	4096
+#define DIBUSB_TS_BUFFER_SIZE		(DIBUSB_TS_NUM_URBS * DIBUSB_TS_URB_BUFFER_SIZE)
+#define DIBUSB_TS_DEFAULT_SIZE		(188*21)
+
 struct usb_dibusb {
 	/* usb */
 	struct usb_device * udev;
 
 	struct dibusb_device * dibdev;
 
+	int feedcount;
 	int streaming;
-	int feed_count;
-	struct urb *buf_urb;
+	struct urb * buf_urb[DIBUSB_TS_NUM_URBS];
 	u8 *buffer;
 	dma_addr_t dma_handle;
 
@@ -77,52 +161,13 @@
 	struct semaphore i2c_sem;
 
 	/* dvb */
+	int dvb_is_ready;
 	struct dvb_adapter *adapter;
 	struct dmxdev dmxdev;
 	struct dvb_demux demux;
 	struct dvb_net dvb_net;
 };
 
-
-struct dibusb_device {
-	u16 cold_product_id;
-	u16 warm_product_id;
-	u8 demod_addr;
-	const char *name;
-};
-
-/* static array of valid firmware names, the best one first */
-static const char * valid_firmware_filenames[] = {
-	"dvb-dibusb-5.0.0.11.fw",
-};
-
-#define DIBUSB_SUPPORTED_DEVICES	4
-
-/* USB Driver stuff */
-static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = {
-	{	.cold_product_id = USB_VP7041_PRODUCT_PREFW_ID,
-		.warm_product_id = USB_VP7041_PRODUCT_ID,
-		.name = "Twinhan VisionDTV USB-Ter/HAMA USB DVB-T device",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{	.cold_product_id = USB_VSTREAM_PRODUCT_PREFW_ID,
-		.warm_product_id = USB_VSTREAM_PRODUCT_ID,
-		.name = "KWorld V-Stream XPERT DTV - DVB-T USB",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{	.cold_product_id = USB_DIBCOM_PRODUCT_PREFW_ID,
-		.warm_product_id = USB_DIBCOM_PRODUCT_ID,
-		.name = "DiBcom USB reference design",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{
- 		.cold_product_id = USB_ULTIMA_ELEC_PROD_PREFW_ID,
-		.warm_product_id = USB_ULTIMA_ELEC_PROD_ID,
-		.name = "Ultima Electronic/Artec T1 USB TVBOX",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-};
-
 #define COMMAND_PIPE	usb_sndbulkpipe(dib->udev, 0x01)
 #define RESULT_PIPE		usb_rcvbulkpipe(dib->udev, 0x81)
 #define DATA_PIPE		usb_rcvbulkpipe(dib->udev, 0x82)
@@ -141,6 +186,10 @@
 
 /* prefix for reading the current RC key */
 #define DIBUSB_REQ_POLL_REMOTE			0x04
+
+#define DIBUSB_RC_NEC_EMPTY				0x00
+#define DIBUSB_RC_NEC_KEY_PRESSED		0x01
+#define DIBUSB_RC_NEC_KEY_REPEATED		0x02
 
 /* 0x05 0xXX */
 #define DIBUSB_REQ_SET_STREAMING_MODE	0x05
diff -Nru a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c	2004-10-28 22:25:57 -07:00
@@ -1500,6 +1500,7 @@
 };
 
 static struct dvb_device dvbdev_ca = {
+        .priv	= NULL,
 	.users	= 1,
 	.readers= 1,
 	.writers= 1,
diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
--- a/drivers/media/dvb/dvb-core/dvb_net.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/dvb-core/dvb_net.c	2004-10-28 22:25:57 -07:00
@@ -37,10 +37,18 @@
 #include <linux/uio.h>
 #include <asm/uaccess.h>
 #include <linux/crc32.h>
+#include <linux/version.h>
 
 #include "dvb_demux.h"
 #include "dvb_net.h"
 
+static int dvb_net_debug;
+module_param(dvb_net_debug, int, 0444);
+MODULE_PARM_DESC(dvb_net_debug, "enable debug messages");
+
+#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0)
+
+
 static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
 {
 	unsigned int j;
@@ -50,13 +58,6 @@
 }
 
 
-#if 1
-#define dprintk(x...) printk(x)
-#else
-#define dprintk(x...)
-#endif
-
-
 #define DVB_NET_MULTICAST_MAX 10
 
 #define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
@@ -917,14 +918,6 @@
 }
 
 
-static int dvb_net_set_config(struct net_device *dev, struct ifmap *map)
-{
-	if (netif_running(dev))
-		return -EBUSY;
-	return 0;
-}
-
-
 static void wq_restart_net_feed (void *data)
 {
 	struct net_device *dev = data;
@@ -983,7 +976,6 @@
 	dev->hard_start_xmit	= dvb_net_tx;
 	dev->get_stats		= dvb_net_get_stats;
 	dev->set_multicast_list = dvb_net_set_multicast_list;
-	dev->set_config         = dvb_net_set_config;
 	dev->set_mac_address    = dvb_net_set_mac;
 	dev->mtu		= 4096;
 	dev->mc_count           = 0;
diff -Nru a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
--- a/drivers/media/dvb/frontends/dib3000mb.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/frontends/dib3000mb.c	2004-10-28 22:25:57 -07:00
@@ -17,6 +17,8 @@
  *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
  *  sources, on which this driver (and the dvb-dibusb) are based.
  *
+ * 
+ * 
  * see Documentation/dvb/README.dibusb for more information
  *
  */
@@ -36,19 +38,21 @@
 /* debug */
 
 #ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk_new(level,args...) \
+#define dprintk(level,args...) \
 	do { if ((debug & level)) { printk(args); } } while (0)
 
 static int debug;
 module_param(debug, int, 0x644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore (|-able)).");
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=setfe,16=getfe (|-able)).");
 #else
-#define dprintk_new(args...)
+#define dprintk(args...) do { } while (0);
 #endif
 
-#define deb_info(args...) dprintk_new(0x01,args)
-#define deb_xfer(args...) dprintk_new(0x02,args)
-#define deb_alot(args...) dprintk_new(0x04,args)
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_xfer(args...) dprintk(0x02,args)
+#define deb_alot(args...) dprintk(0x04,args)
+#define deb_setf(args...) dprintk(0x08,args)
+#define deb_getf(args...) dprintk(0x10,args)
 
 /* Version information */
 #define DRIVER_VERSION "0.1"
@@ -63,7 +67,7 @@
 };
 
 static struct dvb_frontend_info dib3000mb_info = {
-	.name			= "DiBcom 3000-MB DVB-T frontend",
+	.name			= "DiBcom 3000-MB DVB-T",
 	.type 			= FE_OFDM,
 	.frequency_min 		= 44250000,
 	.frequency_max 		= 867250000,
@@ -72,8 +76,8 @@
 			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
 			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | 
 			FE_CAN_HIERARCHY_AUTO,
 };
 
@@ -149,7 +153,7 @@
 	u32 dds_val, threshold = 0x800000;
 
 	if (!rd(DIB3000MB_REG_TPS_LOCK))
-		return -EINVAL;
+		return 0;
 
 	dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);
 	if (dds_val & threshold)
@@ -172,56 +176,56 @@
 					||
 		((inv_test2 == 0) && (inv_test1==1 || inv_test1==2));
 
-	deb_info("inversion %d %d, %d\n",inv_test2,inv_test1, fep->inversion);
+	deb_getf("inversion %d %d, %d\n",inv_test2,inv_test1, fep->inversion);
 
 	switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {
 		case DIB3000MB_QAM_QPSK:
-			deb_info("QPSK ");
+			deb_getf("QPSK ");
 			ofdm->constellation = QPSK;
 			break;
 		case DIB3000MB_QAM_QAM16:
-			deb_info("QAM16 ");
+			deb_getf("QAM16 ");
 			ofdm->constellation = QAM_16;
 			break;
 		case DIB3000MB_QAM_QAM64:
-			deb_info("QAM64 ");
+			deb_getf("QAM64 ");
 			ofdm->constellation = QAM_64;
 			break;
 		default:
 			err("Unexpected constellation returned by TPS (%d)",tps_val);
 			break;
  	}
-	deb_info("TPS: %d\n",tps_val);
+	deb_getf("TPS: %d\n",tps_val);
 
 	if (rd(DIB3000MB_REG_TPS_HRCH)) {
-		deb_info("HRCH ON\n");
+		deb_getf("HRCH ON\n");
 		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);
 		cr = &ofdm->code_rate_LP;
 		ofdm->code_rate_HP = FEC_NONE;
 
 		switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {
 			case DIB3000MB_VIT_ALPHA_OFF:
-				deb_info("HIERARCHY_NONE ");
+				deb_getf("HIERARCHY_NONE ");
 				ofdm->hierarchy_information = HIERARCHY_NONE;
 				break;
 			case DIB3000MB_VIT_ALPHA_1:
-				deb_info("HIERARCHY_1 ");
+				deb_getf("HIERARCHY_1 ");
 				ofdm->hierarchy_information = HIERARCHY_1;
 				break;
 			case DIB3000MB_VIT_ALPHA_2:
-				deb_info("HIERARCHY_2 ");
+				deb_getf("HIERARCHY_2 ");
 				ofdm->hierarchy_information = HIERARCHY_2;
 				break;
 			case DIB3000MB_VIT_ALPHA_4:
-				deb_info("HIERARCHY_4 ");
+				deb_getf("HIERARCHY_4 ");
 				ofdm->hierarchy_information = HIERARCHY_4;
 				break;
 			default:
 				err("Unexpected ALPHA value returned by TPS (%d)",tps_val);
 		}
-		deb_info("TPS: %d\n",tps_val);
+		deb_getf("TPS: %d\n",tps_val);
 	} else {
-		deb_info("HRCH OFF\n");
+		deb_getf("HRCH OFF\n");
 		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);
 		cr = &ofdm->code_rate_HP;
 		ofdm->code_rate_LP = FEC_NONE;
@@ -230,67 +234,67 @@
 
 	switch (tps_val) {
 		case DIB3000MB_FEC_1_2:
-			deb_info("FEC_1_2 ");
+			deb_getf("FEC_1_2 ");
 			*cr = FEC_1_2;
 			break;
 		case DIB3000MB_FEC_2_3:
-			deb_info("FEC_2_3 ");
+			deb_getf("FEC_2_3 ");
 			*cr = FEC_2_3;
 			break;
 		case DIB3000MB_FEC_3_4:
-			deb_info("FEC_3_4 ");
+			deb_getf("FEC_3_4 ");
 			*cr = FEC_3_4;
 			break;
 		case DIB3000MB_FEC_5_6:
-			deb_info("FEC_5_6 ");
+			deb_getf("FEC_5_6 ");
 			*cr = FEC_4_5;
 			break;
 		case DIB3000MB_FEC_7_8:
-			deb_info("FEC_7_8 ");
+			deb_getf("FEC_7_8 ");
 			*cr = FEC_7_8;
 			break;
 		default:
 			err("Unexpected FEC returned by TPS (%d)",tps_val);
 			break;
 	}
-	deb_info("TPS: %d\n",tps_val);
+	deb_getf("TPS: %d\n",tps_val);
 
 	switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {
 		case DIB3000MB_GUARD_TIME_1_32:
-			deb_info("GUARD_INTERVAL_1_32 ");
+			deb_getf("GUARD_INTERVAL_1_32 ");
 			ofdm->guard_interval = GUARD_INTERVAL_1_32;
 			break;
 		case DIB3000MB_GUARD_TIME_1_16:
-			deb_info("GUARD_INTERVAL_1_16 ");
+			deb_getf("GUARD_INTERVAL_1_16 ");
 			ofdm->guard_interval = GUARD_INTERVAL_1_16;
 			break;
 		case DIB3000MB_GUARD_TIME_1_8:
-			deb_info("GUARD_INTERVAL_1_8 ");
+			deb_getf("GUARD_INTERVAL_1_8 ");
 			ofdm->guard_interval = GUARD_INTERVAL_1_8;
 			break;
 		case DIB3000MB_GUARD_TIME_1_4:
-			deb_info("GUARD_INTERVAL_1_4 ");
+			deb_getf("GUARD_INTERVAL_1_4 ");
 			ofdm->guard_interval = GUARD_INTERVAL_1_4;
 			break;
 		default:
 			err("Unexpected Guard Time returned by TPS (%d)",tps_val);
 			break;
 	}
-	deb_info("TPS: %d\n",tps_val);
+	deb_getf("TPS: %d\n",tps_val);
 
 	switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {
 		case DIB3000MB_FFT_2K:
-			deb_info("TRANSMISSION_MODE_2K ");
+			deb_getf("TRANSMISSION_MODE_2K ");
 			ofdm->transmission_mode = TRANSMISSION_MODE_2K;
 			break;
 		case DIB3000MB_FFT_8K:
-			deb_info("TRANSMISSION_MODE_8K ");
+			deb_getf("TRANSMISSION_MODE_8K ");
 			ofdm->transmission_mode = TRANSMISSION_MODE_8K;
 			break;
 		default:
 			err("unexpected transmission mode return by TPS (%d)",tps_val);
 	}
-	deb_info("TPS: %d\n",tps_val);
+	deb_getf("TPS: %d\n",tps_val);
 	return 0;
 }
 
@@ -307,18 +311,18 @@
 	if (irq & 0x02) {
 		if (rd(DIB3000MB_REG_LOCK2_VALUE) & 0x01) {
 			if (dib3000mb_get_frontend(state,&fep) == 0) {
-				deb_info("reading tuning data from frontend succeeded.\n");
+				deb_setf("reading tuning data from frontend succeeded.\n");
 				return dib3000mb_set_frontend(state,&fep,0) == 0;
 			} else {
-				deb_info("reading tuning data failed -> tuning failed.\n");
+				deb_setf("reading tuning data failed -> tuning failed.\n");
 				return 0;
 			}
 		} else {
-			deb_info("AS IRQ was pending, but LOCK2 was not & 0x01.\n");
+			deb_setf("AS IRQ was pending, but LOCK2 was not & 0x01.\n");
 			return 0;
 		}
 	} else if (irq & 0x01) {
-		deb_info("Autosearch failed.\n");
+		deb_setf("Autosearch failed.\n");
 		return 0;
 	}
 
@@ -329,7 +333,7 @@
 		struct dvb_frontend_parameters *fep, int tuner)
 {
 	struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
-	fe_code_rate_t fe_cr;
+	fe_code_rate_t fe_cr = FEC_NONE;
 	int search_state,seq;
 
 	if (tuner) {
@@ -342,82 +346,105 @@
 		wr(DIB3000MB_REG_TUNER,
 				DIB3000MB_DEACTIVATE_TUNER_XFER( DIB3000MB_TUNER_ADDR_DEFAULT ) );
 
+		deb_setf("bandwidth: ");
 		switch (ofdm->bandwidth) {
 			case BANDWIDTH_8_MHZ:
-			case BANDWIDTH_AUTO:
+				deb_setf("8 MHz\n");
 				wr_foreach(dib3000mb_reg_timing_freq,dib3000mb_timing_freq[2]);
 				wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_8mhz);
 				break;
 			case BANDWIDTH_7_MHZ:
+				deb_setf("7 MHz\n");
 				wr_foreach(dib3000mb_reg_timing_freq,dib3000mb_timing_freq[1]);
 				wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_7mhz);
 				break;
 			case BANDWIDTH_6_MHZ:
+				deb_setf("6 MHz\n");
 				wr_foreach(dib3000mb_reg_timing_freq,dib3000mb_timing_freq[0]);
 				wr_foreach(dib3000mb_reg_bandwidth,dib3000mb_bandwidth_6mhz);
 				break;
+			case BANDWIDTH_AUTO:
+				return -EOPNOTSUPP;
 			default:
 				err("unkown bandwidth value.");
 				return -EINVAL;
-				break;
 		}
 	}
 	wr(DIB3000MB_REG_LOCK1_MASK,DIB3000MB_LOCK1_SEARCH_4);
 
+	deb_setf("transmission mode: ");
 	switch (ofdm->transmission_mode) {
 		case TRANSMISSION_MODE_2K:
+			deb_setf("2k\n");
 			wr(DIB3000MB_REG_FFT,DIB3000MB_FFT_2K);
 			break;
 		case TRANSMISSION_MODE_8K:
+			deb_setf("8k\n");
 			wr(DIB3000MB_REG_FFT,DIB3000MB_FFT_8K);
 			break;
 		case TRANSMISSION_MODE_AUTO:
+			deb_setf("auto\n");
 			wr(DIB3000MB_REG_FFT,DIB3000MB_FFT_AUTO);
 			break;
 		default:
 			return -EINVAL;
 	}
 
+	deb_setf("guard: ");
 	switch (ofdm->guard_interval) {
 		case GUARD_INTERVAL_1_32:
+			deb_setf("1_32\n");
 			wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_32);
 			break;
 		case GUARD_INTERVAL_1_16:
+			deb_setf("1_16\n");
 			wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_16);
 			break;
 		case GUARD_INTERVAL_1_8:
+			deb_setf("1_8\n");
 			wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_8);
 			break;
 		case GUARD_INTERVAL_1_4:
+			deb_setf("1_4\n");
 			wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_1_4);
 			break;
 		case GUARD_INTERVAL_AUTO:
+			deb_setf("auto\n");
 			wr(DIB3000MB_REG_GUARD_TIME,DIB3000MB_GUARD_TIME_AUTO);
 			break;
 		default:
 			return -EINVAL;
 	}
 
+	deb_setf("invsersion: ");
 	switch (fep->inversion) {
+		case INVERSION_AUTO:
+			deb_setf("auto\n");
+			break;
 		case INVERSION_OFF:
+			deb_setf("on\n");
 			wr(DIB3000MB_REG_DDS_INV,DIB3000MB_DDS_INV_OFF);
 			break;
-		case INVERSION_AUTO:
 		case INVERSION_ON:
+			deb_setf("on\n");
 			wr(DIB3000MB_REG_DDS_INV,DIB3000MB_DDS_INV_ON);
 			break;
 		default:
 			return -EINVAL;
 	}
 
+	deb_setf("constellation: ");
 	switch (ofdm->constellation) {
 		case QPSK:
+			deb_setf("qpsk\n");
 			wr(DIB3000MB_REG_QAM,DIB3000MB_QAM_QPSK);
 			break;
 		case QAM_16:
+			deb_setf("qam16\n");
 			wr(DIB3000MB_REG_QAM,DIB3000MB_QAM_QAM16);
 			break;
 		case QAM_64:
+			deb_setf("qam64\n");
 			wr(DIB3000MB_REG_QAM,DIB3000MB_QAM_QAM64);
 			break;
 		case QAM_AUTO:
@@ -425,53 +452,69 @@
 		default:
 			return -EINVAL;
 	}
-
+	deb_setf("hierachy: ");	
 	switch (ofdm->hierarchy_information) {
 		case HIERARCHY_NONE:
+			deb_setf("none ");
+			/* fall through alpha is 1, even when HIERARCHY is NONE */ 
 		case HIERARCHY_1:
+			deb_setf("alpha=1\n");	
 			wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_1);
 			break;
 		case HIERARCHY_2:
+			deb_setf("alpha=2\n");	
 			wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_2);
 			break;
 		case HIERARCHY_4:
+			deb_setf("alpha=4\n");	
 			wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_4);
 			break;
 		case HIERARCHY_AUTO:
+			deb_setf("alpha=auto\n");	
 			wr(DIB3000MB_REG_VIT_ALPHA,DIB3000MB_VIT_ALPHA_AUTO);
 			break;
 		default:
 			return -EINVAL;
 	}
 
+	deb_setf("hierarchy: ");
 	if (ofdm->hierarchy_information == HIERARCHY_NONE) {
+		deb_setf("none\n");
 		wr(DIB3000MB_REG_VIT_HRCH,DIB3000MB_VIT_HRCH_OFF);
 		wr(DIB3000MB_REG_VIT_HP,DIB3000MB_VIT_HP);
 		fe_cr = ofdm->code_rate_HP;
-	} else {
+	} else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {
+		deb_setf("on\n");
 		wr(DIB3000MB_REG_VIT_HRCH,DIB3000MB_VIT_HRCH_ON);
 		wr(DIB3000MB_REG_VIT_HP,DIB3000MB_VIT_LP);
 		fe_cr = ofdm->code_rate_LP;
 	}
-
+	deb_setf("fec: ");
 	switch (fe_cr) {
 		case FEC_1_2:
+			deb_setf("1_2\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_1_2);
 			break;
 		case FEC_2_3:
+			deb_setf("2_3\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_2_3);
 			break;
 		case FEC_3_4:
+			deb_setf("3_4\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_3_4);
 			break;
 		case FEC_5_6:
+			deb_setf("5_6\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_5_6);
 			break;
 		case FEC_7_8:
+			deb_setf("7_8\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE,DIB3000MB_FEC_7_8);
 			break;
 		case FEC_NONE:
+			deb_setf("none ");
 		case FEC_AUTO:
+			deb_setf("auto\n");
 			break;
 		default:
 			return -EINVAL;
@@ -482,7 +525,7 @@
 		[ofdm->guard_interval == GUARD_INTERVAL_AUTO]
 		[fep->inversion == INVERSION_AUTO];
 
-	deb_info("seq? %d\n",seq);
+	deb_setf("seq? %d\n",seq);
 
 	wr(DIB3000MB_REG_SEQ,seq);
 
@@ -522,7 +565,7 @@
 		fe_cr == FEC_AUTO ||
 		fep->inversion == INVERSION_AUTO) {
 
-		deb_info("autosearch enabled.\n");
+		deb_setf("autosearch enabled.\n");	
 
 		wr(DIB3000MB_REG_ISI,DIB3000MB_ISI_INHIBIT);
 
@@ -530,7 +573,7 @@
 		wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_OFF);
 
 		while ((search_state = dib3000mb_fe_read_search_status(state)) < 0);
-
+		deb_info("search_state after autosearch %d\n",search_state);
 		return search_state ? 0 : -EINVAL;
 	} else {
 		wr(DIB3000MB_REG_RESTART,DIB3000MB_RESTART_CTRL);
@@ -622,14 +665,25 @@
 static int dib3000mb_read_status(struct dib3000mb_state *state,fe_status_t *stat)
 {
 	*stat = 0;
-	*stat |= rd(DIB3000MB_REG_AGC_LOCK) ? FE_HAS_SIGNAL : 0;
-	*stat |= rd(DIB3000MB_REG_CARRIER_LOCK) ? FE_HAS_CARRIER : 0;
-	*stat |= rd(DIB3000MB_REG_VIT_LCK) ? FE_HAS_VITERBI : 0;
-	*stat |= rd(DIB3000MB_REG_TS_SYNC_LOCK) ? FE_HAS_SYNC : 0;
-	*stat |= *stat ? FE_HAS_LOCK : 0;
+
+	if (rd(DIB3000MB_REG_AGC_LOCK))
+		*stat |= FE_HAS_SIGNAL;
+	if (rd(DIB3000MB_REG_CARRIER_LOCK))
+		*stat |= FE_HAS_CARRIER;
+	if (rd(DIB3000MB_REG_VIT_LCK))
+		*stat |= FE_HAS_VITERBI;
+	if (rd(DIB3000MB_REG_TS_SYNC_LOCK))
+		*stat |= (FE_HAS_SYNC | FE_HAS_LOCK);
 
 	deb_info("actual status is %2x\n",*stat);
 
+	deb_getf("tps %x %x %x %x %x\n",
+			rd(DIB3000MB_REG_TPS_1),
+			rd(DIB3000MB_REG_TPS_2),
+			rd(DIB3000MB_REG_TPS_3),
+			rd(DIB3000MB_REG_TPS_4),
+			rd(DIB3000MB_REG_TPS_5));
+	
 	deb_info("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",
 			rd(DIB3000MB_REG_TPS_LOCK),
 			rd(DIB3000MB_REG_TPS_QAM),
@@ -647,15 +701,75 @@
 
 static int dib3000mb_read_ber(struct dib3000mb_state *state,u32 *ber)
 {
-	*ber =
-		(((rd(DIB3000MB_REG_BER_MSB) << 16) & 0x1f) | rd(DIB3000MB_REG_BER_LSB) ) /
-		 100000000;
+	*ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB) );
+	return 0;
+}
+/*
+ * Amaury:
+ * signal strength is measured with dBm (power compared to mW)
+ * the standard range is -90dBm(low power) to -10 dBm (strong power),
+ * but the calibration is done for -100 dBm to 0dBm
+ */
+
+#define DIB3000MB_AGC_REF_dBm		-14
+#define DIB3000MB_GAIN_SLOPE_dBm	100
+#define DIB3000MB_GAIN_DELTA_dBm	-2
+static int dib3000mb_read_signal_strength(struct dib3000mb_state *state, u16 *strength)
+{
+/* TODO log10 
+	u16 sigpow = rd(DIB3000MB_REG_SIGNAL_POWER), 
+		n_agc_power = rd(DIB3000MB_REG_AGC_POWER),
+		rf_power = rd(DIB3000MB_REG_RF_POWER);
+	double rf_power_dBm, ad_power_dBm, minar_power_dBm;
+	
+	if (n_agc_power == 0 )
+		n_agc_power = 1 ;
+
+	ad_power_dBm    = 10 * log10 ( (float)n_agc_power / (float)(1<<16) );
+	minor_power_dBm = ad_power_dBm - DIB3000MB_AGC_REF_dBm;
+	rf_power_dBm = (-DIB3000MB_GAIN_SLOPE_dBm * (float)rf_power / (float)(1<<16) + 
+			DIB3000MB_GAIN_DELTA_dBm) + minor_power_dBm;
+	// relative rf_power 
+	*strength = (u16) ((rf_power_dBm + 100) / 100 * 0xffff);
+*/
+	*strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;
 	return 0;
 }
 
-static int dib3000mb_signal_strength(struct dib3000mb_state *state, u16 *strength)
+/*
+ * Amaury: 
+ * snr is the signal quality measured in dB.
+ * snr = 10*log10(signal power / noise power)
+ * the best quality is near 35dB (cable transmission & good modulator)
+ * the minimum without errors depend of transmission parameters
+ * some indicative values are given in en300744 Annex A
+ * ex : 16QAM 2/3 (Gaussian)  = 11.1 dB
+ *
+ * If SNR is above 20dB, BER should be always 0.
+ * choose 0dB as the minimum
+ */
+static int dib3000mb_read_snr(struct dib3000mb_state *state,u16 *snr)
+{
+	short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);
+	int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |
+		rd(DIB3000MB_REG_NOISE_POWER_LSB);
+/*
+	float snr_dBm=0;
+
+	if (sigpow > 0 && icipow > 0)
+		snr_dBm = 10.0 * log10( (float) (sigpow<<8) / (float)icipow )  ;
+	else if (sigpow > 0)
+		snr_dBm = 35;
+	
+	*snr = (u16) ((snr_dBm / 35) * 0xffff);
+*/
+	*snr = (sigpow<<8) / (icipow > 0 ? icipow : 1);
+	return 0;
+}
+
+static int dib3000mb_read_unc_blocks(struct dib3000mb_state *state,u32 *unc)
 {
-//	*stength = DIB3000MB_REG_SIGNAL_POWER
+	*unc = rd(DIB3000MB_REG_UNC);
 	return 0;
 }
 
@@ -665,63 +779,81 @@
 	return 0;
 }
 
+static int dib3000mb_fe_get_tune_settings(struct dib3000mb_state *state, 
+		struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 800;
+	tune->step_size = 166667;
+	tune->max_drift = 166667*2;
+					
+	return 0;
+}
+
 static int dib3000mb_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
 {
 	struct dib3000mb_state *state = fe->data;
-	int ret = 0;
 	switch (cmd) {
 		case FE_GET_INFO:
 			deb_info("FE_GET_INFO\n");
 			memcpy(arg, &dib3000mb_info, sizeof(struct dvb_frontend_info));
+			return 0;
 			break;
 
 		case FE_READ_STATUS:
 			deb_info("FE_READ_STATUS\n");
-			ret = dib3000mb_read_status(state,(fe_status_t *)arg);
+			return dib3000mb_read_status(state,(fe_status_t *)arg);
 			break;
 
 		case FE_READ_BER:
 			deb_info("FE_READ_BER\n");
-			ret = dib3000mb_read_ber(state,(u32 *)arg);
+			return dib3000mb_read_ber(state,(u32 *)arg);
 			break;
 
 		case FE_READ_SIGNAL_STRENGTH:
 			deb_info("FE_READ_SIG_STRENGTH\n");
-			ret = dib3000mb_signal_strength(state,(u16 *) arg);
+			return dib3000mb_read_signal_strength(state,(u16 *) arg);
 			break;
 
 		case FE_READ_SNR:
 			deb_info("FE_READ_SNR\n");
+			return dib3000mb_read_snr(state,(u16 *) arg);
 			break;
 
 		case FE_READ_UNCORRECTED_BLOCKS:
 			deb_info("FE_READ_UNCORRECTED_BLOCKS\n");
+			return dib3000mb_read_unc_blocks(state,(u32 *) arg);
 			break;
 
 		case FE_SET_FRONTEND:
 			deb_info("FE_SET_FRONTEND\n");
-			ret = dib3000mb_set_frontend(state,(struct dvb_frontend_parameters *) arg,1);
+			return dib3000mb_set_frontend(state,(struct dvb_frontend_parameters *) arg,1);
 			break;
 
 		case FE_GET_FRONTEND:
 			deb_info("FE_GET_FRONTEND\n");
-			ret = dib3000mb_get_frontend(state,(struct dvb_frontend_parameters *) arg);
+			return dib3000mb_get_frontend(state,(struct dvb_frontend_parameters *) arg);
 			break;
 
 		case FE_SLEEP:
 			deb_info("FE_SLEEP\n");
-			ret = dib3000mb_sleep(state);
+			return dib3000mb_sleep(state);
 			break;
 
 		case FE_INIT:
 			deb_info("FE_INIT\n");
-			ret = dib3000mb_fe_init(state,0);
+			return dib3000mb_fe_init(state,0);
 			break;
 
+		case FE_GET_TUNE_SETTINGS:
+			deb_info("GET_TUNE_SETTINGS");
+			return dib3000mb_fe_get_tune_settings(state, (struct
+						dvb_frontend_tune_settings *) arg);
+
+			break;
 		case FE_SET_TONE:
 		case FE_SET_VOLTAGE:
 		default:
-			ret = -EOPNOTSUPP;
+			return -EOPNOTSUPP;
 			break;
 	}
 	return 0;
@@ -753,16 +885,20 @@
 	i2c_set_clientdata(client,state);
 
 	state->manufactor_id = dib3000mb_read_reg(client, DIB3000MB_REG_MANUFACTOR_ID);
+	if (state->manufactor_id != 0x01b3) {
+		ret = -ENODEV;
+		goto probe_err;
+	}
+	
 	state->device_id = dib3000mb_read_reg(client,DIB3000MB_REG_DEVICE_ID);
-	if (state->manufactor_id == 0x01b3 && state->device_id == 0x3000)
-		info("found a DiBCom (0x%04x) 3000-MB DVB-T frontend (ver: %x).",
-				state->manufactor_id, state->device_id);
-	else {
-		err("did not found a DiBCom 3000-MB.");
+	if (state->device_id != 0x3000) {
 		ret = -ENODEV;
 		goto probe_err;
 	}
 
+	info("found a DiBCom (0x%04x) 3000-MB DVB-T frontend (ver: %x).",
+			state->manufactor_id, state->device_id);
+	
 	if ((ret = i2c_attach_client(client)))
 		goto i2c_attach_err;
 
diff -Nru a/drivers/media/dvb/frontends/dib3000mb.h b/drivers/media/dvb/frontends/dib3000mb.h
--- a/drivers/media/dvb/frontends/dib3000mb.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/frontends/dib3000mb.h	2004-10-28 22:25:58 -07:00
@@ -7,6 +7,7 @@
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
  *
+ * 
  *
  * for more information see dib3000mb.c .
  */
@@ -320,7 +321,7 @@
 #define DIB3000MB_REG_UNK_108			(   108)
 #define DIB3000MB_UNK_108					(0x0080)
 
-/* fft ??? */
+/* fft */
 #define DIB3000MB_REG_UNK_121			(   121)
 #define DIB3000MB_UNK_121_2K				(     7)
 #define DIB3000MB_UNK_121_DEFAULT			(     5)
@@ -351,12 +352,11 @@
 #define DIB3000MB_REG_VIT_CODE_RATE		(   129)
 
 /* forward error correction code rates */
-#define DIB3000MB_FEC_1_2					(     0)
-#define DIB3000MB_FEC_2_3					(     1)
-#define DIB3000MB_FEC_3_4					(     2)
-#define DIB3000MB_FEC_4_5					(     3)
-#define DIB3000MB_FEC_5_6					(     4)
-#define DIB3000MB_FEC_7_8					(     5)
+#define DIB3000MB_FEC_1_2					(     1)
+#define DIB3000MB_FEC_2_3					(     2)
+#define DIB3000MB_FEC_3_4					(     3)
+#define DIB3000MB_FEC_5_6					(     5)
+#define DIB3000MB_FEC_7_8					(     7)
 
 /* vit select hp */
 #define DIB3000MB_REG_VIT_HP			(   130)
@@ -627,8 +627,8 @@
 /* packet error rate (uncorrected TS packets) (16) */
 #define DIB3000MB_REG_PACKET_ERROR_RATE	(   417)
 
-/* packet error count (16) */
-#define DIB3000MB_REG_PACKET_ERROR_COUNT	(   420)
+/* uncorrected packet count (16) */
+#define DIB3000MB_REG_UNC				(   420)
 
 /* viterbi locked (1) */
 #define DIB3000MB_REG_VIT_LCK			(   421)
diff -Nru a/drivers/media/dvb/frontends/grundig_29504-401.c b/drivers/media/dvb/frontends/grundig_29504-401.c
--- a/drivers/media/dvb/frontends/grundig_29504-401.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/frontends/grundig_29504-401.c	2004-10-28 22:25:57 -07:00
@@ -4,7 +4,7 @@
 
     Copyright (C) 2001 Holger Waechtler <holger@convergence.de>
                        for Convergence Integrated Media GmbH
-                       Marko Kohtala <marko.kohtala@nokia.com>
+                       Marko Kohtala <marko.kohtala@luukku.com>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -Nru a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
--- a/drivers/media/dvb/frontends/mt352.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/media/dvb/frontends/mt352.c	2004-10-28 22:25:56 -07:00
@@ -8,10 +8,12 @@
  *       Wolfram Joost <dbox2@frokaschwei.de>
  *
  *  Support for Samsung TDTC9251DH01C(M) tuner
- *
  *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
  *                     Amauri  Celani  <acelani@essegi.net>
  *
+ *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
+ *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
  *  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
@@ -45,22 +47,23 @@
 	} while (0)
 
 static int debug;
-static int force_card = -1;
-static int card_type = -1;
+#define MAX_CARDS	4
+static int force_card[MAX_CARDS] = { -1, -1, -1, -1 };
+static int force_card_count = 0;
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-//FIXME: Should be an array.
-module_param(force_card, int, 0444);
-MODULE_PARM_DESC(force_card, "Force card type.\n\t(0 == AVDVBT771, 1 == TUA6034, "
-		 "2 == TDTC9251DH01C).\n\tDefault is that AVDVBT771 is attempted "
-		 "to be autodetected,\n\tif you do not have this card, you must "
-		 "specify the card type here.");
-
+module_param_array(force_card, int, &force_card_count, 0444);
+MODULE_PARM_DESC(force_card, "Forces the type of each attached mt352 frontend.\n\t"
+		 "If your card is not autodetected, then you must specify its type here.\n\t"
+		 "Valid card types are: 0 == AVDVBT771, 1 == TUA6034, 2 == TDTC9251DH01C,\n\t"
+		 "3 == DVICO FusionHDTV DVB-T1, 4 == DVICO FusionHDTV DVB-T Lite.");
 
 struct mt352_state {
 	struct i2c_adapter *i2c;
 	struct dvb_adapter *dvb;
+	struct dvb_frontend_info fe_info;
+	int card_type;
 };
 
 #define mt352_write(ibuf, ilen)						\
@@ -75,60 +78,60 @@
 	}								\
 } while (0)
 
-// FIXME:
 static struct _tuner_info tuner_info [] = {
-	//AVERMEDIA 771 board
 	{
+	  .fe_name = "AverMedia DVB-T 771",
 	  .fe_frequency_min = 174000000,
 	  .fe_frequency_max = 862000000,
-	  .fe_frequency_stepsize = 83333,
-	  .coderate_hp_shift = 7,
-	  .coderate_lp_shift = 4,
-	  .constellation_shift = 13,
-	  .tx_mode_shift = 0,
-	  .guard_interval_shift = 2,
-	  .hierarchy_shift = 10,
-	  .read_reg_flag = I2C_M_NOSTART,
+	  .fe_frequency_stepsize = 166667,
+	  .pll_i2c_addr = 0xc2,
 	  .mt352_init = mt352_init_AVERMEDIA771,
 	  .mt352_charge_pump = mt352_cp_AVERMEDIA771,
 	  .mt352_band_select = mt352_bs_AVERMEDIA771
 	},
-	//TUA6034 tuner
 	{
+	  .fe_name = "Zarlink MT352 + TUA6034 DVB-T",
 	  .fe_frequency_min = 174000000,
 	  .fe_frequency_max = 862000000,
 	  .fe_frequency_stepsize = 166667,
-	  .coderate_hp_shift = 9,
-	  .coderate_lp_shift = 6,
-	  .constellation_shift = 14,
-	  .tx_mode_shift = 1,
-	  .guard_interval_shift = 3,
-	  .hierarchy_shift = 12,
-	  .read_reg_flag = I2C_M_NOSTART,
+	  .pll_i2c_addr = 0xc2,
 	  .mt352_init = mt352_init_TUA6034,
 	  .mt352_charge_pump = mt352_cp_TUA6034,
 	  .mt352_band_select = mt352_bs_TUA6034
 	},
-	//TDTC9251DH01C tuner
 	{
+	  .fe_name = "Zarlink MT352 + Samsung TDTC9251DH01C DVB-T",
 	  .fe_frequency_min = 474000000,
 	  .fe_frequency_max = 858000000,
 	  .fe_frequency_stepsize = 166667,
-	  .coderate_hp_shift = 9,
-	  .coderate_lp_shift = 6,
-	  .constellation_shift = 4,
-	  .tx_mode_shift = 1,
-	  .guard_interval_shift = 3,
-	  .hierarchy_shift = 12,
-	  .read_reg_flag = 0,
+	  .pll_i2c_addr = 0xc2,
 	  .mt352_init = mt352_init_TDTC9251DH01C,
 	  .mt352_charge_pump = mt352_cp_TDTC9251DH01C,
 	  .mt352_band_select = mt352_bs_TDTC9251DH01C
+	},
+	{
+	  .fe_name = "DVICO FusionHDTV DVB-T1",
+	  .fe_frequency_min = 174000000,
+	  .fe_frequency_max = 862000000,
+	  .fe_frequency_stepsize = 166667,
+	  .pll_i2c_addr = 0xc2,
+	  .mt352_init = mt352_init_DVICODVBT1,
+	  .mt352_charge_pump = mt352_cp_DVICODVBT1,
+	  .mt352_band_select = mt352_bs_DVICODVBT1,
+	},
+	{
+	  .fe_name = "DVICO FusionHDTV DVB-T Lite",
+	  .fe_frequency_min = 174000000,
+	  .fe_frequency_max = 862000000,
+	  .fe_frequency_stepsize = 166667,
+	  .pll_i2c_addr = 0xc0,
+	  .mt352_init = mt352_init_DVICODVBTLITE,
+	  .mt352_charge_pump = mt352_cp_DVICODVBTLITE,
+	  .mt352_band_select = mt352_bs_DVICODVBTLITE,
 	}
 };
 
-
-static struct dvb_frontend_info mt352_info = {
+static struct dvb_frontend_info mt352_info_template = {
 	.name			= "DVB-T Zarlink MT352 demodulator driver",
 	.type			= FE_OFDM,
 /*
@@ -150,63 +153,95 @@
 		FE_CAN_MUTE_TS
 };
 
+static u8 mt352_reset [] = { RESET, 0x80 };
+static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+static u8 mt352_capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
 static int mt352_init_TUA6034(struct i2c_adapter *i2c)
 {
-	static u8 mt352_reset [] = { RESET, 0x80 };
 	static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x2d };
-	static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
 	static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x19, 0xa0 };
-	static u8 mt352_acq_ctl [] = { ACQ_CTL, 0x50 };
 
 	mt352_write(mt352_clock_config, sizeof(mt352_clock_config));
 	udelay(2000);
 	mt352_write(mt352_reset, sizeof(mt352_reset));
 	mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-	mt352_write(mt352_acq_ctl, sizeof(mt352_acq_ctl));
 
 	mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
 
 	return 0;
 }
 
 static int mt352_init_AVERMEDIA771(struct i2c_adapter *i2c)
 {
-	static u8 mt352_reset [] = { RESET, 0x80 };
 	static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x2d };
-	static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
 	static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x10, 0x23, 0x00, 0xFF, 0xFF,
 				       0x00, 0xFF, 0x00, 0x40, 0x40 };
-	static u8 mt352_acq_ctl [] = { ACQ_CTL, 0x50 };
 	static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
+	static u8 mt352_capt_range_cfg[] = { CAPT_RANGE, 0x32 };
 
 	mt352_write(mt352_clock_config, sizeof(mt352_clock_config));
 	udelay(2000);
 	mt352_write(mt352_reset, sizeof(mt352_reset));
 	mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-	mt352_write(mt352_acq_ctl, sizeof(mt352_acq_ctl));
 
 	mt352_write(mt352_agc_cfg,sizeof(mt352_agc_cfg));
 	udelay(2000);
 	mt352_write(mt352_av771_extra,sizeof(mt352_av771_extra));
+	mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
 
 	return 0;
 }
 
 static int mt352_init_TDTC9251DH01C(struct i2c_adapter *i2c)
 {
-	static u8 mt352_reset [] = { RESET, 0x80 };
 	static u8 mt352_clock_config [] = { CLOCK_CTL, 0x10, 0x2d };
-	static u8 mt352_adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
 	static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x28, 0xa1 };
-	static u8 mt352_acq_ctl [] = { ACQ_CTL, 0x50 };
 
 	mt352_write(mt352_clock_config, sizeof(mt352_clock_config));
 	udelay(2000);
 	mt352_write(mt352_reset, sizeof(mt352_reset));
 	mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-	mt352_write(mt352_acq_ctl, sizeof(mt352_acq_ctl));
 
 	mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+	return 0;
+}
+
+static int mt352_init_DVICODVBT1(struct i2c_adapter *i2c)
+{
+	static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
+	static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
+	static u8 mt352_gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+
+	mt352_write(mt352_clock_config, sizeof(mt352_clock_config));
+	udelay(200);
+	mt352_write(mt352_reset, sizeof(mt352_reset));
+	mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+
+	mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
+	mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+	return 0;
+}
+
+static int mt352_init_DVICODVBTLITE(struct i2c_adapter *i2c)
+{
+	static u8 mt352_clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+	static u8 mt352_agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+	static u8 mt352_gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+
+	mt352_write(mt352_clock_config, sizeof(mt352_clock_config));
+	udelay(200);
+	mt352_write(mt352_reset, sizeof(mt352_reset));
+	mt352_write(mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+
+	mt352_write(mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
+	mt352_write(mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
 
 	return 0;
 }
@@ -215,9 +250,9 @@
 {
 	unsigned char cp = 0;
 
-	if (freq < 542)
+	if (freq < 542000000)
 		cp = 0xbe;
-	else if (freq < 830)
+	else if (freq < 830000000)
 		cp = 0xf6;
 	else
 		cp = 0xfe;
@@ -229,21 +264,21 @@
 {
 	unsigned char cp = 0;
 
-	if (freq < 150)
+	if (freq < 150000000)
 		cp = 0xB4;
-	else if (freq < 173)
+	else if (freq < 173000000)
 		cp = 0xBC;
-	else if (freq < 250)
+	else if (freq < 250000000)
 		cp = 0xB4;
-	else if (freq < 400)
+	else if (freq < 400000000)
 		cp = 0xBC;
-	else if (freq < 420)
+	else if (freq < 420000000)
 		cp = 0xF4;
-	else if (freq < 470)
+	else if (freq < 470000000)
 		cp = 0xFC;
-	else if (freq < 600)
+	else if (freq < 600000000)
 		cp = 0xBC;
-	else if (freq < 730)
+	else if (freq < 730000000)
 		cp = 0xF4;
 	else
 		cp = 0xFC;
@@ -256,11 +291,39 @@
 	return(0xcc);
 }
 
+static unsigned char mt352_cp_DVICODVBT1(u32 freq)
+{
+	unsigned char cp = 0;
+
+	if (freq < 542000000)
+		cp = 0xbc;
+	else if (freq < 830000000)
+		cp = 0xf4;
+	else
+		cp = 0xfc;
+
+	return cp;
+}
+
+static unsigned char mt352_cp_DVICODVBTLITE(u32 freq)
+{
+	unsigned char cp = 0;
+
+	if (freq < 542000000)
+		cp = 0xb4;
+	else if (freq < 771000000)
+		cp = 0xbc;
+	else 
+		cp = 0xf4;
+
+	return cp;
+}
+
 static unsigned char mt352_bs_TUA6034(u32 freq)
 {
 	unsigned char bs = 0;
 
-	if (freq < 250)
+	if (freq < 250000000)
 		bs = 0x01;
 	else
 		bs = 0x08;
@@ -272,21 +335,21 @@
 {
 	unsigned char bs = 0;
 
-	if (freq < 150)
+	if (freq < 150000000)
 		bs = 0x01;
-	else if (freq < 173)
+	else if (freq < 173000000)
 		bs = 0x01;
-	else if (freq < 250)
+	else if (freq < 250000000)
 		bs = 0x02;
-	else if (freq < 400)
+	else if (freq < 400000000)
 		bs = 0x02;
-	else if (freq < 420)
+	else if (freq < 420000000)
 		bs = 0x02;
-	else if (freq < 470)
+	else if (freq < 470000000)
 		bs = 0x02;
-	else if (freq < 600)
+	else if (freq < 600000000)
 		bs = 0x08;
-	else if (freq < 730)
+	else if (freq < 730000000)
 		bs = 0x08;
 	else
 		bs = 0x08;
@@ -298,54 +361,79 @@
 {
 	unsigned char bs = 0;
 
-	if ((freq >= 48) && (freq <= 154))      /* low band */
+	if (freq >= 48000000 && freq <= 154000000)      /* low band */
 		bs = 0x09;
 
-	if ((freq >= 161) && (freq <= 439))     /* medium band */
+	if (freq >= 161000000 && freq <= 439000000)     /* medium band */
 		bs = 0x0a;
 
-	if ((freq >= 447) && (freq <= 863))     /* high band */
+	if (freq >= 447000000 && freq <= 863000000)     /* high band */
 		bs = 0x08;
 
 	return bs;
 }
 
+static unsigned char mt352_bs_DVICODVBT1(u32 freq)
+{
+	unsigned char bs = 0;
+
+	if (freq == 0)			/* power down PLL */
+		bs = 0x03;
+	else if (freq < 157500000)	/* low band */
+		bs = 0x01;
+	else if (freq < 443250000)	/* mid band */
+		bs = 0x02;
+	else				/* high band */
+		bs = 0x04;
+
+	return bs;
+}
 
-static int mt352_detect_avermedia_771(struct i2c_adapter *i2c)
+static unsigned char mt352_bs_DVICODVBTLITE(u32 freq)
 {
-	int i;
-	u8 reg;
-	u8 id[4];
-	const u8 pciid[4] = { 0x07, 0x71, 0x14, 0x61 };
-	struct i2c_msg msg[2] =
+	unsigned char bs = 0;
+
+	if (freq == 0)			/* power down PLL */
+		bs = 0x03;
+	else if (freq < 443250000)	/* mid band */
+		bs = 0x02;
+	else				/* high band */
+		bs = 0x08;
+
+	return bs;
+}
+
+static u32 mt352_read_eeprom_dword(struct i2c_adapter *i2c, int dword_base)
 	{
+	int i;
+	u32 dword = 0;
+	u8 reg, val;
+	struct i2c_msg msg[2] = {
 		{
 			.addr = 0x50,
-			.flags = I2C_M_NOSTART,
+			.flags = 0,
 			.buf = &reg,
 			.len = 1
 		},
 		{
 			.addr = 0x50,
 			.flags = I2C_M_RD,
+			.buf = &val,
 			.len = 1
 		}
 	};
 
-	for (i = 0; i < 4; i++)
-	{
-		reg = i + 0xFC;
-		msg[1].buf = id + i;
+	for (i = 0; i < 4; i++) {
+		reg = dword_base + i;
 		if (i2c_transfer(i2c,msg,2) != 2)
-		{
 			return 0;
-		}
+		dword = (dword << 8) | val;
 	}
 
-	return *((u32 *) id) == *((u32 *) pciid);
+	return dword;
 }
 
-static int mt352_init(struct i2c_adapter *i2c)
+static int mt352_init(struct i2c_adapter *i2c, int card_type)
 {
 	/**
 	 *  all register write sequence have the register address of the
@@ -366,7 +454,7 @@
 
 static int mt352_sleep(struct i2c_adapter *i2c)
 {
-	static u8 mt352_softdown[] = { 0x89, 0x20, 0x08 };
+	static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
 
 	mt352_write(mt352_softdown, sizeof(mt352_softdown));
 
@@ -374,26 +462,27 @@
 }
 
 static int mt352_set_parameters(struct i2c_adapter *i2c,
-				struct dvb_frontend_parameters *param)
+				struct dvb_frontend_parameters *param,
+				int card_type)
 {
 	unsigned char buf[14];
 	unsigned int tps = 0;
 	struct dvb_ofdm_parameters *op = &param->u.ofdm;
-	u32 freq = param->frequency / 1000000;
 	uint16_t tmp;
+	int i;
 
 	switch (op->code_rate_HP) {
 		case FEC_2_3:
-			tps |= (1 << CODERATE_HP_SHIFT);
+			tps |= (1 << 7);
 			break;
 		case FEC_3_4:
-			tps |= (2 << CODERATE_HP_SHIFT);
+			tps |= (2 << 7);
 			break;
 		case FEC_5_6:
-			tps |= (3 << CODERATE_HP_SHIFT);
+			tps |= (3 << 7);
 			break;
 		case FEC_7_8:
-			tps |= (4 << CODERATE_HP_SHIFT);
+			tps |= (4 << 7);
 			break;
 		case FEC_1_2:
 		case FEC_AUTO:
@@ -404,20 +493,24 @@
 
 	switch (op->code_rate_LP) {
 		case FEC_2_3:
-			tps |= (1 <<  CODERATE_LP_SHIFT);
+			tps |= (1 << 4);
 			break;
 		case FEC_3_4:
-			tps |= (2 <<  CODERATE_LP_SHIFT);
+			tps |= (2 << 4);
 			break;
 		case FEC_5_6:
-			tps |= (3 <<  CODERATE_LP_SHIFT);
+			tps |= (3 << 4);
 			break;
 		case FEC_7_8:
-			tps |= (4 <<  CODERATE_LP_SHIFT);
+			tps |= (4 << 4);
 			break;
 		case FEC_1_2:
 		case FEC_AUTO:
 			break;
+		case FEC_NONE:
+			if (op->hierarchy_information == HIERARCHY_AUTO ||
+			    op->hierarchy_information == HIERARCHY_NONE)
+				break;
 		default:
 			return -EINVAL;
 	}
@@ -427,10 +520,10 @@
 			break;
 		case QAM_AUTO:
 		case QAM_16:
-			tps |= (1 << CONSTELLATION_SHIFT);
+			tps |= (1 << 13);
 			break;
 		case QAM_64:
-			tps |= (2 << CONSTELLATION_SHIFT);
+			tps |= (2 << 13);
 			break;
 		default:
 			return -EINVAL;
@@ -441,7 +534,7 @@
 		case TRANSMISSION_MODE_AUTO:
 			break;
 		case TRANSMISSION_MODE_8K:
-			tps |= (1 << TX_MODE_SHIFT);
+			tps |= (1 << 0);
 			break;
 		default:
 			return -EINVAL;
@@ -452,13 +545,13 @@
 		case GUARD_INTERVAL_AUTO:
 			break;
 		case GUARD_INTERVAL_1_16:
-			tps |= (1 << GUARD_INTERVAL_SHIFT);
+			tps |= (1 << 2);
 			break;
 		case GUARD_INTERVAL_1_8:
-			tps |= (2 << GUARD_INTERVAL_SHIFT);
+			tps |= (2 << 2);
 			break;
 		case GUARD_INTERVAL_1_4:
-			tps |= (3 << GUARD_INTERVAL_SHIFT);
+			tps |= (3 << 2);
 			break;
 		default:
 			return -EINVAL;
@@ -469,13 +562,13 @@
 		case HIERARCHY_NONE:
 			break;
 		case HIERARCHY_1:
-			tps |= (1 << HIERARCHY_SHIFT);
+			tps |= (1 << 10);
 			break;
 		case HIERARCHY_2:
-			tps |= (2 << HIERARCHY_SHIFT);
+			tps |= (2 << 10);
 			break;
 		case HIERARCHY_4:
-			tps |= (3 << HIERARCHY_SHIFT);
+			tps |= (3 << 10);
 			break;
 		default:
 			return -EINVAL;
@@ -507,7 +600,7 @@
 	buf[6] = 0x31;  /* INPUT_FREQ_(1|0), 20.48MHz clock, 36.166667MHz IF */
 	buf[7] = 0x05;  /* see MT352 Design Manual page 32 for details */
 
-	buf[8] = I2C_TUNER_ADDR;
+	buf[8] = PLL_I2C_ADDR;
 
 	/**
 	 *  All the following settings are tuner module dependent,
@@ -516,17 +609,24 @@
 
 	/* here we assume 1/6MHz == 166.66kHz stepsize */
 	#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
-	tmp = ((param->frequency*3)/500000) + IF_FREQUENCYx6;
+	tmp = (((param->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
 	buf[9] = msb(tmp);      /* CHAN_START_(1|0) */
 	buf[10] = lsb(tmp);
 
-	buf[11] = MT352_CHARGE_PUMP(freq);
-	buf[12] = MT352_BAND_SELECT(freq);
+	buf[11] = MT352_CHARGE_PUMP(param->frequency);
+	buf[12] = MT352_BAND_SELECT(param->frequency);
 
 	buf[13] = 0x01; /* TUNER_GO!! */
 
+	/* Only send the tuning request if the tuner doesn't have the requested
+	 * parameters already set.  Enhances tuning time and prevents stream
+	 * breakup when retuning the same transponder. */
+	for (i = 1; i < 13; i++)
+		if (buf[i] != mt352_read_register(i2c, i + 0x50)) {
 	mt352_write(buf, sizeof(buf));
+			break;
+		}
 
 	return 0;
 }
@@ -537,7 +637,7 @@
 	u8 b0 [] = { reg };
 	u8 b1 [] = { 0 };
 	struct i2c_msg msg [] = { { .addr = I2C_MT352_ADDR,
-				    .flags =  READ_REG_FLAG,
+				    .flags = 0,
 				    .buf = b0, .len = 1 },
 				  { .addr = I2C_MT352_ADDR,
 				    .flags = I2C_M_RD,
@@ -672,6 +772,7 @@
 {
 	struct mt352_state *state = fe->data;
 	struct i2c_adapter *i2c = state->i2c;
+	int card_type = state->card_type;
 	u8 r,snr;
 	fe_status_t *status;
 	u16 signal;
@@ -679,7 +780,7 @@
 
 	switch (cmd) {
 	case FE_GET_INFO:
-		memcpy (arg, &mt352_info, sizeof(struct dvb_frontend_info));
+		memcpy(arg, &state->fe_info, sizeof(struct dvb_frontend_info));
 		break;
 
 	case FE_READ_STATUS:
@@ -727,7 +828,8 @@
 
 	case FE_SET_FRONTEND:
 		return mt352_set_parameters (i2c,
-				 (struct dvb_frontend_parameters *) arg);
+				 (struct dvb_frontend_parameters *) arg,
+				 card_type);
 
 	case FE_GET_FRONTEND:
 		return mt352_get_parameters (i2c,
@@ -744,7 +846,13 @@
 		return mt352_sleep(i2c);
 
 	case FE_INIT:
-		return mt352_init(i2c);
+		/* Only send the initialisation command if the demodulator
+		 * isn't already enabled.  Greatly enhances tuning time. */
+		if ((mt352_read_register(i2c, CLOCK_CTL) & 0x10) == 0 ||
+		    (mt352_read_register(i2c, CONFIG) & 0x20) == 0)
+			return mt352_init(i2c, card_type);
+		else
+			return 0;
 
 	default:
 		return -EOPNOTSUPP;
@@ -757,56 +865,83 @@
 
 static int mt352_attach_adapter(struct i2c_adapter *i2c)
 {
+	static int num_cards_probed;
 	struct mt352_state *state;
 	struct i2c_client *client;
-	static u8 mt352_reset_attach [] = { 0x50, 0xC0 };
+	static u8 mt352_reset_attach [] = { RESET, 0xC0 };
 	int ret;
+	int card_type, forced_card = -1;
 
 	dprintk("Trying to attach to adapter 0x%x:%s.\n",
 		i2c->id, i2c->name);
 
-	/* set the proper MT352 frequency range */
-	mt352_info.frequency_min =  FE_FREQ_MIN;
-	mt352_info.frequency_max =  FE_FREQ_MAX;
-	mt352_info.frequency_stepsize =  FE_FREQ_STEPSIZE;
+	if (mt352_read_register(i2c, CHIP_ID) != ID_MT352)
+		return -ENODEV;
 
 	if ( !(state = kmalloc(sizeof(struct mt352_state), GFP_KERNEL)) )
 		return -ENOMEM;
 
 	memset(state, 0, sizeof(struct mt352_state));
 	state->i2c = i2c;
+	state->card_type = -1;
+	memcpy(&state->fe_info, &mt352_info_template, sizeof(struct dvb_frontend_info));
 
-	if (mt352_detect_avermedia_771(i2c)) {
-		card_type = CARD_AVDVBT771;
-	} else if (force_card < 0) {
-		dprintk("Avermedia 771 not detected, maybe you should try the "
-			"'force_card' module parameter?.\n");
-		kfree(state);
-		return -ENODEV;
+	/* Attempt autodetection of card type based on PCI ID information
+	 * stored in any on-board EEPROM. */
+	switch (mt352_read_eeprom_dword(i2c, 0xFC)) {	/* BT878A chipset */
+	case 0x07711461:
+		state->card_type = CARD_AVDVBT771;
+		break;
+	case 0xdb1018ac:
+		state->card_type = CARD_DVICODVBTLITE;
+		break;
+	default:
+		break;
 	}
 
-	if (force_card > 0) {
-		if (card_type >= 0 && force_card != card_type)
-			printk(KERN_WARNING "dvbfe_mt352: Warning, overriding"
-					    " detected card.\n");
-		card_type = force_card;
+	switch (mt352_read_eeprom_dword(i2c, 0x04)) {	/* CX2388x chipset */
+	case 0xac1800db:
+		state->card_type = CARD_DVICODVBT1;
+		break;
+	default:
+		break;
 	}
 
-	if (mt352_read_register(i2c, CHIP_ID) != ID_MT352) {
+	if (num_cards_probed < force_card_count)
+		forced_card = force_card[num_cards_probed++];
+
+	if (state->card_type == -1 && forced_card < 0) {
+		dprintk("Card type not automatically detected.  You "
+			"must use the 'force_card' module parameter.\n");
 		kfree(state);
 		return -ENODEV;
 	}
 
-	if (card_type == CARD_AVDVBT771)
-		printk(KERN_INFO FRONTEND_NAME ": Setup for Avermedia 771.\n");
-	else if (card_type == CARD_TUA6034)
-		printk(KERN_INFO FRONTEND_NAME ": Setup for TUA6034.\n");
-	else if (card_type == CARD_TDTC9251DH01C)
-		printk(KERN_INFO FRONTEND_NAME ": Setup for TDTC9251DH01C.\n");
+	if (forced_card >= 0) {
+		if (state->card_type >= 0 && forced_card != state->card_type)
+			printk(KERN_WARNING FRONTEND_NAME ": Warning, overriding"
+					    " detected card type.\n");
+		state->card_type = forced_card;
+	}
+
+	card_type = state->card_type;
+	printk(KERN_INFO FRONTEND_NAME ": Setup for %s\n", FE_NAME);
+
+	/* set the frontend name and card-specific frequency info */
+	strlcpy(state->fe_info.name, FE_NAME, sizeof(state->fe_info.name));
+	state->fe_info.frequency_min = FE_FREQ_MIN;
+	state->fe_info.frequency_max = FE_FREQ_MAX;
+	state->fe_info.frequency_stepsize = FE_FREQ_STEPSIZE;
 
 	/* Do a "hard" reset */
 	mt352_write(mt352_reset_attach, sizeof(mt352_reset_attach));
 
+	/* Try to intiialise the device */
+	if (mt352_init(i2c, card_type) != 0) {
+		kfree(state);
+		return -ENODEV;
+	}
+
 	if ( !(client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)) ) {
 		kfree(state);
 		return -ENOMEM;
@@ -823,16 +958,6 @@
 		return ret;
 	}
 
-	BUG_ON(!state->dvb);
-
-	if ((ret = dvb_register_frontend(mt352_ioctl, state->dvb, state,
-					     &mt352_info, THIS_MODULE))) {
-		i2c_detach_client(client);
-		kfree(client);
-		kfree(state);
-		return ret;
-	}
-
 	return 0;
 }
 
@@ -840,9 +965,9 @@
 {
 	struct mt352_state *state = i2c_get_clientdata(client);
 
+	if (state->dvb)
 	dvb_unregister_frontend (mt352_ioctl, state->dvb);
 	i2c_detach_client(client);
-	BUG_ON(state->dvb);
 	kfree(client);
 	kfree(state);
 	return 0;
@@ -851,13 +976,23 @@
 static int mt352_command (struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	struct mt352_state *state = i2c_get_clientdata(client);
+	int ret;
 
 	switch (cmd) {
 	case FE_REGISTER:
+		if (!state->dvb) {
+			if ((ret = dvb_register_frontend(mt352_ioctl, arg,
+							 state, &state->fe_info,
+							 THIS_MODULE)))
+				return ret;
 		state->dvb = arg;
+		}
 		break;
 	case FE_UNREGISTER:
+		if (state->dvb == arg) {
+			dvb_unregister_frontend(mt352_ioctl, state->dvb);
 		state->dvb = NULL;
+		}
 		break;
 	default:
 		return -EOPNOTSUPP;
diff -Nru a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
--- a/drivers/media/dvb/frontends/mt352.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/dvb/frontends/mt352.h	2004-10-28 22:25:59 -07:00
@@ -4,11 +4,16 @@
  *  Written by Holger Waechtler <holger@qanu.de>
  *	 and Daniel Mack <daniel@qanu.de>
  *
- *  Support for Samsung TDTC9251DH01C(M) tuner
+ *  AVerMedia AVerTV DVB-T 771 support by
+ *       Wolfram Joost <dbox2@frokaschwei.de>
  *
+ *  Support for Samsung TDTC9251DH01C(M) tuner
  *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
  *                     Amauri  Celani  <acelani@essegi.net>
  *
+ *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
+ *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
  *  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
@@ -29,12 +34,13 @@
 #define _MT352_
 
 #define I2C_MT352_ADDR  0x0f
-#define I2C_TUNER_ADDR  0xc2
 #define ID_MT352        0x13
 
 #define CARD_AVDVBT771	    0x00
 #define CARD_TUA6034	    0x01
 #define CARD_TDTC9251DH01C  0x02
+#define CARD_DVICODVBT1	    0x03
+#define CARD_DVICODVBTLITE  0x04
 
 #define msb(x) (((x) >> 8) & 0xff)
 #define lsb(x) ((x) & 0xff)
@@ -123,6 +129,9 @@
 };
 
 struct _tuner_info {
+	char *fe_name;
+#define FE_NAME tuner_info[card_type].fe_name
+
 	__u32 fe_frequency_min;
 #define FE_FREQ_MIN tuner_info[card_type].fe_frequency_min
 
@@ -132,26 +141,8 @@
 	__u32 fe_frequency_stepsize; //verificare se u32 e' corretto
 #define FE_FREQ_STEPSIZE  tuner_info[card_type].fe_frequency_stepsize
 
-	__u32 coderate_hp_shift; //verificare se u32 giusto
-#define CODERATE_HP_SHIFT tuner_info[card_type].coderate_hp_shift
-
-	__u32 coderate_lp_shift;
-#define CODERATE_LP_SHIFT tuner_info[card_type].coderate_lp_shift
-
-	int constellation_shift;
-#define CONSTELLATION_SHIFT tuner_info[card_type].constellation_shift
-
-	int tx_mode_shift;
-#define TX_MODE_SHIFT tuner_info[card_type].tx_mode_shift
-
-	int guard_interval_shift;
-#define GUARD_INTERVAL_SHIFT tuner_info[card_type].guard_interval_shift
-
-	int hierarchy_shift;
-#define HIERARCHY_SHIFT tuner_info[card_type].hierarchy_shift
-
-	int read_reg_flag;
-#define READ_REG_FLAG tuner_info[card_type].read_reg_flag
+	u8 pll_i2c_addr;
+#define PLL_I2C_ADDR tuner_info[card_type].pll_i2c_addr
 
 	int (* mt352_init) (struct i2c_adapter *i2c);
 #define MT352_INIT tuner_info[card_type].mt352_init
@@ -166,12 +157,18 @@
 static int mt352_init_TUA6034(struct i2c_adapter *i2c);
 static int mt352_init_AVERMEDIA771(struct i2c_adapter *i2c);
 static int mt352_init_TDTC9251DH01C(struct i2c_adapter *i2c);
+static int mt352_init_DVICODVBT1(struct i2c_adapter *i2c);
+static int mt352_init_DVICODVBTLITE(struct i2c_adapter *i2c);
 static unsigned char mt352_cp_TUA6034(u32 freq);
 static unsigned char mt352_cp_AVERMEDIA771(u32 freq);
 static unsigned char mt352_cp_TDTC9251DH01C(u32 freq);
+static unsigned char mt352_cp_DVICODVBT1(u32 freq);
+static unsigned char mt352_cp_DVICODVBTLITE(u32 freq);
 static unsigned char mt352_bs_TUA6034(u32 freq);
 static unsigned char mt352_bs_AVERMEDIA771(u32 freq);
 static unsigned char mt352_bs_TDTC9251DH01C(u32 freq);
-static int mt352_detect_avermedia_771(struct i2c_adapter *i2c);
+static unsigned char mt352_bs_DVICODVBT1(u32 freq);
+static unsigned char mt352_bs_DVICODVBTLITE(u32 freq);
+static u8 mt352_read_register(struct i2c_adapter *i2c, u8 reg);
 
 #endif                          /* _MT352_ */
diff -Nru a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
--- a/drivers/media/dvb/frontends/stv0299.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/dvb/frontends/stv0299.c	2004-10-28 22:25:59 -07:00
@@ -885,6 +885,43 @@
 }
 
 
+static int stv0299_send_legacy_dish_cmd(struct i2c_adapter *i2c, u32 cmd, 
+                                        int tuner_type)
+{
+	u8 last = 1;
+	int i;
+
+	/* reset voltage at the end
+	if((0x50 & stv0299_readreg (i2c, 0x0c)) == 0x50)
+		cmd |= 0x80;
+	else
+		cmd &= 0x7F;
+	*/
+
+	cmd = cmd << 1;
+	dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+
+	stv0299_set_voltage(i2c,SEC_VOLTAGE_18,tuner_type);
+	msleep(32);
+
+	for (i=0; i<9; i++) {
+		if((cmd & 0x01) != last) {
+			stv0299_set_voltage(i2c,
+					    last ? SEC_VOLTAGE_13 :
+					    	   SEC_VOLTAGE_18,
+					    tuner_type);
+			last = (last) ? 0 : 1;
+		}
+
+		cmd = cmd >> 1;
+
+		if (i != 8)
+			msleep(8);
+	}
+
+	return 0;
+}
+
 static int stv0299_set_symbolrate (struct i2c_adapter *i2c, u32 srate, int tuner_type)
 {
 	u64 big = srate;
@@ -1229,6 +1266,10 @@
 		return stv0299_set_voltage (i2c, (fe_sec_voltage_t) arg,
 					    state->tuner_type);
 
+	case FE_DISHNETWORK_SEND_LEGACY_CMD:
+		return stv0299_send_legacy_dish_cmd (i2c, (u32) arg,
+						     state->tuner_type);
+
 	case FE_GET_TUNE_SETTINGS:
 	{
 		struct dvb_frontend_tune_settings* fesettings = (struct dvb_frontend_tune_settings*) arg;
@@ -1276,12 +1317,12 @@
         u8 stat [] = { 0 };
 	u8 tda6100_buf [] = { 0, 0 };
 	int ret;
-	struct i2c_msg msg1 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
+	struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
 			   { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
-	struct i2c_msg msg2 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
+	struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
 			   { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
-	struct i2c_msg msg3 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
-			   { .addr = 0x60, .buf = tda6100_buf, .len = 2 }};
+	struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+			   { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }};
 
 	stv0299_writereg (i2c, 0x01, 0x15);
 	stv0299_writereg (i2c, 0x02, 0x30);
diff -Nru a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
--- a/drivers/media/dvb/ttpci/av7110.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/ttpci/av7110.c	2004-10-28 22:25:58 -07:00
@@ -67,7 +67,8 @@
 #include "av7110_ca.h"
 #include "av7110_ipack.h"
 
-static int av7110_debug;
+int av7110_debug;
+
 static int vidmode=CVBS_RGB_OUT;
 static int pids_off;
 static int adac=DVB_ADAC_TI;
@@ -110,7 +111,7 @@
 	av7110->has_analog_tuner = 0;
 	av7110->current_input = 0;
 	if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
-		printk ("av7110(%d): Crystal audio DAC detected\n",
+		printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
 			av7110->dvb_adapter->num);
 		av7110->adac_type = DVB_ADAC_CRYSTAL;
 		i2c_writereg(av7110, 0x20, 0x01, 0xd2);
@@ -125,13 +126,13 @@
 		/* done. */
 	}
 	else if (dev->pci->subsystem_vendor == 0x110a) {
-		printk("av7110(%d): DVB-C w/o analog module detected\n",
+		printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
 			av7110->dvb_adapter->num);
 		av7110->adac_type = DVB_ADAC_NONE;
 	}
 	else {
 		av7110->adac_type = adac;
-		printk("av7110(%d): adac type set to %d\n",
+		printk("dvb-ttpci: adac type set to %d @ card %d\n",
 			av7110->dvb_adapter->num, av7110->adac_type);
 	}
 
@@ -150,7 +151,7 @@
 
 static void recover_arm(struct av7110 *av7110)
 {
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n",av7110);
 
 	av7110_bootarm(av7110);
 	msleep(100);
@@ -160,7 +161,7 @@
 
 static void arm_error(struct av7110 *av7110)
 {
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n",av7110);
 
         av7110->arm_errors++;
         av7110->arm_ready=0;
@@ -173,7 +174,7 @@
         u16 newloops = 0;
 	int timeout;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n",av7110);
 	
         lock_kernel ();
         daemonize ("arm_mon");
@@ -199,7 +200,7 @@
                 up(&av7110->dcomlock);
 
                 if (newloops==av7110->arm_loops) {
-                        printk(KERN_ERR "av7110%d: ARM crashed!\n",
+			printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
 				av7110->dvb_adapter->num);
 
 			arm_error(av7110);
@@ -231,7 +232,7 @@
 {
 	static struct av7110 *last;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n",av7110);
 
 	if (!av7110)
 		av7110 = last;
@@ -248,13 +249,13 @@
 
 void av7110_register_irc_handler(void (*func)(u32)) 
 {
-	DEB_EE(("registering %p\n", func));
+	dprintk(4, "registering %p\n", func);
         irc_handler = func;
 }
 
 void av7110_unregister_irc_handler(void (*func)(u32)) 
 {
-	DEB_EE(("unregistering %p\n", func));
+	dprintk(4, "unregistering %p\n", func);
         irc_handler = NULL;
 }
 
@@ -268,7 +269,7 @@
 
 void IR_handle(struct av7110 *av7110, u32 ircom)
 {
-	DEB_S(("av7110: ircommand = %08x\n", ircom));
+	dprintk(4, "ircommand = %08x\n", ircom);
         irtask.data = (unsigned long) ircom;
         tasklet_schedule(&irtask);
 }
@@ -283,8 +284,6 @@
                      enum dmx_success success,
                      struct av7110 *av7110)
 {
-	DEB_INT(("av7110: %p\n",av7110));
-
         if (!dvbdmxfilter->feed->demux->dmx.frontend)
                 return 0;
         if (dvbdmxfilter->feed->demux->dmx.frontend->source==DMX_MEMORY_FE)
@@ -344,7 +343,7 @@
         int type=av7110->debitype;
         int handle=(type>>8)&0x1f;
 	
-//	DEB_EE(("av7110: %p\n",av7110));
+//	dprintk(4, "%p\n",av7110);
 
         print_time("debi");
         saa7146_write(av7110->dev, IER, 
@@ -476,10 +475,8 @@
         u32 rxbuf, txbuf;
         int len;
         
-        //printk("GPIO0 irq\n");        
-
         if (av7110->debitype !=-1)
-		printk("GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
+		printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
 		       jiffies, saa7146_read(av7110->dev, PSR),
 		       saa7146_read(av7110->dev, SSR));
        
@@ -497,10 +494,10 @@
         txbuf=irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
 	len = (av7110->debilen + 3) & ~3;
 
-//        DEB_D(("GPIO0 irq %d %d\n", av7110->debitype, av7110->debilen));
+//	dprintk(8, "GPIO0 irq %d %d\n", av7110->debitype, av7110->debilen);
         print_time("gpio");
 
-//       DEB_D(("GPIO0 irq %02x\n", av7110->debitype&0xff));        
+//	dprintk(8, "GPIO0 irq %02x\n", av7110->debitype&0xff);
         switch (av7110->debitype&0xff) {
 
         case DATA_TS_PLAY:
@@ -519,10 +516,10 @@
                 iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
 
 		av7110->video_size.h = h_ar & 0xfff;
-		DEB_D(("GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
+		dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
 				av7110->video_size.w,
 				av7110->video_size.h,
-				av7110->video_size.aspect_ratio));
+				av7110->video_size.aspect_ratio);
 
 		event.type = VIDEO_EVENT_SIZE_CHANGED;
 		event.u.size.w = av7110->video_size.w;
@@ -610,7 +607,7 @@
                         iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
                         break;
                 } 
-                DEB_D(("GPIO0 PES_PLAY len=%04x\n", len));        
+		dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
                 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
                 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
 		saa7146_wait_for_debi_done(av7110->dev);
@@ -688,7 +685,7 @@
                 break;
 
         default:
-                printk("gpioirq unknown type=%d len=%d\n", 
+		printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
                        av7110->debitype, av7110->debilen);
                 break;
         }      
@@ -705,7 +702,7 @@
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (cmd == OSD_SEND_CMD)
 		return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
@@ -736,7 +733,7 @@
 static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
 			  u16 subpid, u16 pcrpid)
         {
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (vpid == 0x1fff || apid == 0x1fff ||
 	    ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
@@ -754,7 +751,7 @@
 void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
 		u16 subpid, u16 pcrpid)
 {
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
         
 	if (down_interruptible(&av7110->pid_mutex))
 		return;
@@ -793,7 +790,7 @@
 //	u16 mode=0x0320;
 	u16 mode=0xb96a;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (dvbdmxfilter->type == DMX_TYPE_SEC) {
 		if (hw_sections) {
@@ -817,7 +814,7 @@
 
 	ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
 	if (ret < 0) {
-		printk("StartHWFilter error\n");
+		dprintk(1, "StartHWFilter error\n");
 		return ret;
         }
 
@@ -835,13 +832,11 @@
 	int ret;
 	u16 handle;
         
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	handle = dvbdmxfilter->hw_handle;
 	if (handle > 32) {
-		DEB_S(("dvb: StopHWFilter tried to stop invalid filter %d.\n",
-		       handle));
-		DEB_S(("dvb: filter type = %d\n", dvbdmxfilter->type));
+		dprintk(1, "StopHWFilter tried to stop invalid filter %d, filter type = %d\n", handle, dvbdmxfilter->type);
 		return 0;
                 }
 
@@ -852,10 +847,10 @@
 	buf[2] = handle;
 	ret = av7110_fw_request(av7110, buf, 3, answ, 2);
 	if (ret)
-		printk("StopHWFilter error\n");
+		dprintk(1, "StopHWFilter error\n");
 
 	if (answ[1] != handle) {
-		DEB_S(("dvb: filter %d shutdown error :%d\n", handle, answ[1]));
+		dprintk(2, "filter %d shutdown error :%d\n", handle, answ[1]);
 		ret = -1;
         }
         return ret;
@@ -869,7 +864,7 @@
 	u16 *pid = dvbdmx->pids, npids[5];
 	int i;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
 	npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
 	i = dvbdmxfeed->pes_type;
@@ -902,7 +897,7 @@
 	u16 *pid = dvbdmx->pids, npids[5];
 	int i;
                 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
                 
 	if (dvbdmxfeed->pes_type <= 1) {
 		av7110_av_stop(av7110, dvbdmxfeed->pes_type ?  RP_VIDEO : RP_AUDIO);
@@ -935,7 +930,7 @@
 	struct dvb_demux *demux = feed->demux;
 	struct av7110 *av7110 = (struct av7110 *) demux->priv;
                 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
                 
 	if (!demux->dmx.frontend)
 		return -EINVAL;
@@ -993,7 +988,7 @@
 	struct dvb_demux *demux = feed->demux;
 	struct av7110 *av7110 = (struct av7110 *) demux->priv;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (feed->type == DMX_TYPE_TS) {
 		if (feed->ts_type & TS_DECODER) {
@@ -1035,7 +1030,7 @@
 	int mode;
 	int i;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
 	mode = av7110->playing;
 	av7110->playing = 0;
@@ -1068,7 +1063,7 @@
 		BUG();
 	av7110 = (struct av7110 *) dvbdemux->priv;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (num != 0)
 		return -EINVAL;
@@ -1078,14 +1073,14 @@
 		printk(KERN_ERR "%s: av7110_fw_request error\n", __FUNCTION__);
 		return -EIO;
 }
-	DEB_EE(("av7110: fwstc = %04hx %04hx %04hx %04hx\n",
-		fwstc[0], fwstc[1], fwstc[2], fwstc[3]));
+	dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
+		fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
 
 	*stc =	(((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
 		(((uint64_t)  fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
 	*base = 1;
         
-	DEB_EE(("av7110: stc = %lu\n", (unsigned long)*stc));
+	dprintk(4, "stc = %lu\n", (unsigned long)*stc);
 
 	return 0;
 }
@@ -1099,7 +1094,7 @@
 {
 	struct av7110 *av7110 = fe->before_after_data;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	switch (cmd) {
 	case FE_SET_TONE:
@@ -1138,7 +1133,7 @@
 {
 	struct av7110 *av7110 = data;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
         av7110->fe_synced = (s & FE_HAS_LOCK) ? 1 : 0;
 
@@ -1168,7 +1163,7 @@
         int ret, i;
         struct dvb_demux *dvbdemux=&av7110->demux;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
         if (av7110->registered)
                 return -1;
@@ -1243,7 +1238,7 @@
 {
         struct dvb_demux *dvbdemux=&av7110->demux;
 
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
         if (!av7110->registered)
                 return;
@@ -1397,7 +1392,7 @@
 	/* check if the firmware is available */
 	av7110->bin_fw = (unsigned char*) vmalloc(fw->size);
 	if (NULL == av7110->bin_fw) {
-		DEB_D(("out of memory\n"));
+		dprintk(1, "out of memory\n");
 		release_firmware(fw);
 		return -ENOMEM;
 	}
@@ -1440,14 +1435,14 @@
 	struct av7110 *av7110 = NULL;
 	int ret = 0;
 
-	DEB_EE(("dev: %p\n", dev));
+	dprintk(4, "dev: %p\n", dev);
 
 	/* prepare the av7110 device struct */
 	if (!(av7110 = kmalloc (sizeof (struct av7110), GFP_KERNEL))) {
-		printk ("%s: out of memory!\n", __FUNCTION__);
+		dprintk(1, "out of memory\n");
 		return -ENOMEM;
 	}
-	DEB_EE(("av7110: %p\n", av7110));
+
 	memset(av7110, 0, sizeof(struct av7110));
 	
 	av7110->card_name = (char*)pci_ext->ext_priv;
@@ -1547,11 +1542,11 @@
 	}
 
 	if (FW_VERSION(av7110->arm_app)<0x2501)
-		printk ("av7110: Warning, firmware version 0x%04x is too old. "
+		printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
 			"System might be unstable!\n", FW_VERSION(av7110->arm_app));
 
 	if (kernel_thread(arm_thread, (void *) av7110, 0) < 0) {
-		printk(KERN_ERR "av7110(%d): faile to start arm_mon kernel thread\n",
+		printk("dvb-ttpci: failed to start arm_mon kernel thread @ card %d\n",
 		       av7110->dvb_adapter->num);
 		goto err2;
 	}
@@ -1572,7 +1567,7 @@
 	if (ret)
 		goto err3;
 
-	printk(KERN_INFO "av7110: found av7110-%d.\n",av7110_num);
+	printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
 	av7110->device_initialized = 1;
 	av7110_num++;
         return 0;
@@ -1604,7 +1599,7 @@
 static int av7110_detach (struct saa7146_dev* saa)
 {
 	struct av7110 *av7110 = (struct av7110*)saa->ext_priv;
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 	
 	if( 0 == av7110->device_initialized ) {
 		return 0;
@@ -1652,8 +1647,6 @@
 static void av7110_irq(struct saa7146_dev* dev, u32 *isr) 
 {
 	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
-
-//	DEB_INT(("dev: %p, av7110: %p\n",dev,av7110));
 
 	if (*isr & MASK_19)
 		tasklet_schedule (&av7110->debi_tasklet);
diff -Nru a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
--- a/drivers/media/dvb/ttpci/av7110.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/media/dvb/ttpci/av7110.h	2004-10-28 22:25:56 -07:00
@@ -27,6 +27,11 @@
 
 #include <media/saa7146_vv.h>
 
+extern int av7110_debug;
+
+#define dprintk(level,args...) \
+	    do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __FUNCTION__); printk(args); } } while (0)
+
 #define MAXFILT 32
 
 enum {AV_PES_STREAM, PS_STREAM, TS_STREAM, PES_STREAM};
diff -Nru a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
--- a/drivers/media/dvb/ttpci/av7110_av.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/ttpci/av7110_av.c	2004-10-28 22:25:57 -07:00
@@ -98,8 +98,6 @@
 {
 	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv;
 
-//	DEB_EE(("struct dvb_filter_pes2ts:%p\n", p2t));
-
 	if (!(dvbdmxfeed->ts_type & TS_PACKET))
 		return 0;
 	if (buf[3] == 0xe0)	 // video PES do not have a length in TS
@@ -115,8 +113,6 @@
 {
 	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
 
-//	DEB_EE(("dvb_demux_feed:%p\n", dvbdmxfeed));
-
 	dvbdmxfeed->cb.ts(data, 188, NULL, 0,
 			  &dvbdmxfeed->feed.ts, DMX_OK);
 	return 0;
@@ -127,7 +123,7 @@
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 
-	DEB_EE(("av7110: %p, dvb_demux_feed:%p\n", av7110, dvbdmxfeed));
+	dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed);
 
 	if (av7110->playing || (av7110->rec_mode & av))
 		return -EBUSY;
@@ -169,7 +165,7 @@
 
 int av7110_av_start_play(struct av7110 *av7110, int av)
 {
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (av7110->rec_mode)
 		return -EBUSY;
@@ -202,7 +198,7 @@
 
 void av7110_av_stop(struct av7110 *av7110, int av)
 {
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (!(av7110->playing & av) && !(av7110->rec_mode & av))
 		return;
@@ -243,8 +239,6 @@
 	u32 sync;
 	u16 blen;
 
-	DEB_EE(("dvb_ring_buffer_t: %p\n", buf));
-
 	if (!dlen) {
 		wake_up(&buf->queue);
 		return -1;
@@ -275,8 +269,8 @@
 
 	dvb_ringbuffer_read(buf, dest, (size_t) blen, 0);
 
-	DEB_S(("pread=0x%08lx, pwrite=0x%08lx\n",
-	       (unsigned long) buf->pread, (unsigned long) buf->pwrite));
+	dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
+	       (unsigned long) buf->pread, (unsigned long) buf->pwrite);
 	wake_up(&buf->queue);
 	return blen;
 }
@@ -286,7 +280,7 @@
 {
 	int err, vol, val, balance = 0;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	av7110->mixer.volume_left = volleft;
 	av7110->mixer.volume_right = volright;
@@ -325,7 +319,7 @@
 
 void av7110_set_vidmode(struct av7110 *av7110, int mode)
 {
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
 
@@ -353,7 +347,7 @@
 	int sw;
 	u8 *p;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (av7110->sinfo)
 		return;
@@ -366,7 +360,7 @@
 		vsize = ((p[1] &0x0F) << 8) | (p[2]);
 		sw = (p[3] & 0x0F);
 		av7110_set_vidmode(av7110, sw2mode[sw]);
-		DEB_S(("dvb: playback %dx%d fr=%d\n", hsize, vsize, sw));
+		dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw);
 		av7110->sinfo = 1;
 		break;
 	}
@@ -403,7 +397,7 @@
 static void play_video_cb(u8 *buf, int count, void *priv)
 {
 	struct av7110 *av7110 = (struct av7110 *) priv;
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if ((buf[3] & 0xe0) == 0xe0) {
 		get_video_format(av7110, buf, count);
@@ -415,7 +409,7 @@
 static void play_audio_cb(u8 *buf, int count, void *priv)
 {
 	struct av7110 *av7110 = (struct av7110 *) priv;
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	aux_ring_buffer_write(&av7110->aout, buf, count);
 }
@@ -427,7 +421,7 @@
 			unsigned long count, int nonblock, int type)
 {
 	unsigned long todo = count, n;
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (!av7110->kbuf[type])
 		return -ENOBUFS;
@@ -460,7 +454,7 @@
 			unsigned long count, int nonblock, int type)
 {
 	unsigned long todo = count, n;
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (!av7110->kbuf[type])
 		return -ENOBUFS;
@@ -490,7 +484,7 @@
 			 unsigned long count, int nonblock, int type)
 {
 	unsigned long todo = count, n;
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (!av7110->kbuf[type])
 		return -ENOBUFS;
@@ -769,7 +763,7 @@
 	struct av7110 *av7110 = (struct av7110 *) demux->priv;
 	struct ipack *ipack = &av7110->ipack[feed->pes_type];
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	switch (feed->pes_type) {
 	case 0:
@@ -810,8 +804,6 @@
 	struct dvb_video_events *events = &av7110->video_events;
 	int wp;
 
-	DEB_D(("\n"));
-
 	spin_lock_bh(&events->lock);
 
 	wp = (events->eventw + 1) % MAX_VIDEO_EVENT;
@@ -834,8 +826,6 @@
 {
 	struct dvb_video_events *events = &av7110->video_events;
 
-	DEB_D(("\n"));
-
 	if (events->overflow) {
 		events->overflow = 0;
 		return -EOVERFLOW;
@@ -874,7 +864,7 @@
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 	unsigned int mask = 0;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
 		poll_wait(file, &av7110->avout.queue, wait);
@@ -901,7 +891,7 @@
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 		return -EPERM;
@@ -918,7 +908,7 @@
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 	unsigned int mask = 0;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	poll_wait(file, &av7110->aout.queue, wait);
 
@@ -937,7 +927,7 @@
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) {
 		printk(KERN_ERR "not audio source memory\n");
@@ -954,7 +944,7 @@
 {
 	int i, n;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (!(av7110->playing & RP_VIDEO)) {
 		if (av7110_av_start_play(av7110, RP_VIDEO) < 0)
@@ -984,7 +974,7 @@
 	unsigned long arg = (unsigned long) parg;
 	int ret = 0;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 		if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT &&
@@ -1180,7 +1170,7 @@
 	unsigned long arg = (unsigned long) parg;
 	int ret = 0;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (((file->f_flags & O_ACCMODE) == O_RDONLY) &&
 	    (cmd != AUDIO_GET_STATUS))
@@ -1296,7 +1286,7 @@
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 	int err;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if ((err = dvb_generic_open(inode, file)) < 0)
 		return err;
@@ -1320,7 +1310,7 @@
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 		av7110_av_stop(av7110, RP_VIDEO);
@@ -1335,7 +1325,7 @@
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 	int err=dvb_generic_open(inode, file);
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	if (err < 0)
 		return err;
@@ -1349,7 +1339,7 @@
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(2, "av7110:%p, \n", av7110);
 
 	av7110_av_stop(av7110, RP_AUDIO);
 	return dvb_generic_release(inode, file);
diff -Nru a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
--- a/drivers/media/dvb/ttpci/av7110_ca.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/ttpci/av7110_ca.c	2004-10-28 22:25:58 -07:00
@@ -44,7 +44,7 @@
 
 void CI_handle(struct av7110 *av7110, u8 *data, u16 len)
 {
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(8, "av7110:%p\n",av7110);
 
 	if (len < 3)
 		return;
@@ -207,7 +207,7 @@
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 	int err = dvb_generic_open(inode, file);
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(8, "av7110:%p\n",av7110);
 
 	if (err < 0)
 		return err;
@@ -223,13 +223,16 @@
 	struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer;
 	unsigned int mask = 0;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(8, "av7110:%p\n",av7110);
 
 	poll_wait(file, &rbuf->queue, wait);
+	poll_wait(file, &wbuf->queue, wait);
+
 	if (!dvb_ringbuffer_empty(rbuf))
-		mask |= POLLIN;
-	if (dvb_ringbuffer_avail(wbuf) > 1024)
-		mask |= POLLOUT;
+		mask |= (POLLIN | POLLRDNORM);
+
+	if (dvb_ringbuffer_free(wbuf) > 1024)
+		mask |= (POLLOUT | POLLWRNORM);
 
 	return mask;
 }
@@ -241,7 +244,7 @@
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 	unsigned long arg = (unsigned long) parg;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(8, "av7110:%p\n",av7110);
 
 	switch (cmd) {
 	case CA_RESET:
@@ -318,7 +321,7 @@
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(8, "av7110:%p\n",av7110);
 	return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos);
 }
 
@@ -328,7 +331,7 @@
 	struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
 	struct av7110 *av7110 = (struct av7110 *) dvbdev->priv;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(8, "av7110:%p\n",av7110);
 	return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
 }
 
diff -Nru a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
--- a/drivers/media/dvb/ttpci/av7110_hw.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/ttpci/av7110_hw.c	2004-10-28 22:25:58 -07:00
@@ -110,7 +110,7 @@
 	IER_ENABLE(av7110->dev, MASK_03);
 
 	av7110->arm_ready = 1;
-	printk("av7110: ARM RESET\n");
+	dprintk(1, "reset ARM\n");
 }
 
 
@@ -118,7 +118,7 @@
 {
 	int k;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	for (k = 0; k < 100; k++) {
 		if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
@@ -134,7 +134,7 @@
 	int blocks, rest;
 	u32 base, bootblock = BOOT_BLOCK;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	blocks = len / BOOT_MAX_SIZE;
 	rest = len % BOOT_MAX_SIZE;
@@ -143,7 +143,7 @@
 	for (i = 0; i < blocks; i++) {
 		if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0)
 			return -1;
-		DEB_D(("Writing DRAM block %d\n", i));
+		dprintk(4, "writing DRAM block %d\n", i);
 		mwdebi(av7110, DEBISWAB, bootblock,
 		       ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
 		bootblock ^= 0x1400;
@@ -206,7 +206,7 @@
 	u32 ret;
 	int i;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
 
@@ -222,17 +222,17 @@
 	/* test DEBI */
 	iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
 	if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
-		printk(KERN_ERR "dvb: debi test in av7110_bootarm() failed: "
-		       "%08x != %08x (check your BIOS hotplug settings)\n",
+		printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
+		       "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
 		       ret, 0x10325476);
 		return -1;
 	}
 	for (i = 0; i < 8192; i += 4)
 		iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
-	DEB_D(("av7110_bootarm: debi test OK\n"));
+	dprintk(2, "debi test OK\n");
 
 	/* boot */
-	DEB_D(("av7110_bootarm: load boot code\n"));
+	dprintk(1, "load boot code\n");
 	saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
 	//saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
 	//saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
@@ -241,25 +241,25 @@
 	iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
 
 	if (saa7146_wait_for_debi_done(av7110->dev)) {
-		printk(KERN_ERR "dvb: av7110_bootarm(): "
+		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
 		       "saa7146_wait_for_debi_done() timed out\n");
 		return -1;
 	}
 	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
 	mdelay(1);
 
-	DEB_D(("av7110_bootarm: load dram code\n"));
+	dprintk(1, "load dram code\n");
 	if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0)
 		return -1;
 
 	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
 	mdelay(1);
 
-	DEB_D(("av7110_bootarm: load dpram code\n"));
+	dprintk(1, "load dpram code\n");
 	mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
 
 	if (saa7146_wait_for_debi_done(av7110->dev)) {
-		printk(KERN_ERR "dvb: av7110_bootarm(): "
+		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
 		       "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
 		return -1;
 	}
@@ -289,10 +289,10 @@
 	u32 stat;
 #endif
 
-//	DEB_EE(("av7110: %p\n", av7110));
+//	dprintk(4, "%p\n", av7110);
 
 	if (!av7110->arm_ready) {
-		DEB_D(("arm not ready.\n"));
+		dprintk(1, "arm not ready.\n");
 		return -1;
 	}
 
@@ -300,7 +300,7 @@
 	while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
 		msleep(1);
 		if (time_after(jiffies, start + ARM_WAIT_FREE)) {
-			printk(KERN_ERR "%s: timeout waiting for COMMAND idle\n", __FUNCTION__);
+			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
 			return -1;
 		}
 	}
@@ -310,7 +310,7 @@
 	while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 )) {
 		msleep(1);
 		if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
-			printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
+			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __FUNCTION__);
 			return -1;
 		}
 	}
@@ -320,7 +320,7 @@
 	while (rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull) {
 		msleep(1);
 		if (time_after(jiffies, start + ARM_WAIT_OSD)) {
-			printk(KERN_ERR "%s: timeout waiting for !OSDQFull\n", __FUNCTION__);
+			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for !OSDQFull\n", __FUNCTION__);
 			return -1;
 		}
 	}
@@ -339,7 +339,7 @@
 	while (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 )) {
 		msleep(1);
 		if (time_after(jiffies, start + ARM_WAIT_FREE)) {
-			printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n",
+			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND to complete\n",
 			       __FUNCTION__);
 			return -1;
 		}
@@ -347,11 +347,11 @@
 
 	stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
 	if (stat & GPMQOver) {
-		printk(KERN_ERR "%s: GPMQOver\n", __FUNCTION__);
+		printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __FUNCTION__);
 		return -1;
 	}
 	else if (stat & OSDQOver) {
-		printk(KERN_ERR "%s: OSDQOver\n", __FUNCTION__);
+		printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __FUNCTION__);
 		return -1;
 	}
 #endif
@@ -363,10 +363,10 @@
 {
 	int ret;
 
-//	DEB_EE(("av7110: %p\n", av7110));
+//	dprintk(4, "%p\n", av7110);
 
 	if (!av7110->arm_ready) {
-		DEB_D(("arm not ready.\n"));
+		dprintk(1, "arm not ready.\n");
 		return -1;
 	}
 	if (down_interruptible(&av7110->dcomlock))
@@ -375,7 +375,7 @@
 	ret = __av7110_send_fw_cmd(av7110, buf, length);
 	up(&av7110->dcomlock);
 	if (ret)
-		printk("av7110_send_fw_cmd error\n");
+		printk("dvb-ttpci: %s(): av7110_send_fw_cmd error\n", __FUNCTION__);
 	return ret;
 }
 
@@ -385,7 +385,7 @@
 	u16 buf[num + 2];
 	int i, ret;
 
-//	DEB_EE(("av7110: %p\n",av7110));
+//	dprintk(4, "%p\n", av7110);
 
 	buf[0] = ((type << 8) | com);
 	buf[1] = num;
@@ -399,7 +399,7 @@
 
 	ret = av7110_send_fw_cmd(av7110, buf, num + 2);
 	if (ret)
-		printk("av7110_fw_cmd error\n");
+		printk("dvb-ttpci: av7110_fw_cmd error\n");
 	return ret;
 }
 
@@ -409,7 +409,7 @@
 	u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
 		16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	for(i = 0; i < len && i < 32; i++)
 	{
@@ -421,7 +421,7 @@
 
 	ret = av7110_send_fw_cmd(av7110, cmd, 18);
 	if (ret)
-		printk("av7110_send_ci_cmd error\n");
+		printk("dvb-ttpci: av7110_send_ci_cmd error\n");
 	return ret;
 }
 
@@ -435,10 +435,10 @@
 	u32 stat;
 #endif
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (!av7110->arm_ready) {
-		DEB_D(("arm not ready.\n"));
+		dprintk(1, "arm not ready.\n");
 		return -1;
 	}
 
@@ -447,7 +447,7 @@
 
 	if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
 		up(&av7110->dcomlock);
-		printk("av7110_fw_request error\n");
+		printk("dvb-ttpci: av7110_fw_request error\n");
 		return err;
 	}
 
@@ -457,7 +457,7 @@
 		msleep(1);
 #endif
 		if (time_after(jiffies, start + ARM_WAIT_FREE)) {
-			printk("%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
+			printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__);
 			up(&av7110->dcomlock);
 			return -1;
 		}
@@ -501,7 +501,7 @@
 	int ret;
 	ret = av7110_fw_request(av7110, &tag, 0, buf, length);
 	if (ret)
-		printk("av7110_fw_query error\n");
+		printk("dvb-ttpci: av7110_fw_query error\n");
 	return ret;
 }
 
@@ -516,10 +516,10 @@
 	u16 buf[20];
 	u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (av7110_fw_query(av7110, tag, buf, 16)) {
-		printk("DVB: AV7110-%d: ERROR: Failed to boot firmware\n",
+		printk("dvb-ttpci: failed to boot firmware @ card %d\n",
 		       av7110->dvb_adapter->num);
 		return -EIO;
 	}
@@ -530,17 +530,17 @@
 	av7110->arm_app = (buf[6] << 16) + buf[7];
 	av7110->avtype = (buf[8] << 16) + buf[9];
 
-	printk("DVB: AV711%d(%d) - firm %08x, rtsl %08x, vid %08x, app %08x\n",
-	       av7110->avtype, av7110->dvb_adapter->num, av7110->arm_fw,
+	printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
+	       av7110->dvb_adapter->num, av7110->arm_fw,
 	       av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
 
 	/* print firmware capabilities */
 	if (FW_CI_LL_SUPPORT(av7110->arm_app))
-		printk("DVB: AV711%d(%d) - firmware supports CI link layer interface\n",
-		       av7110->avtype, av7110->dvb_adapter->num);
+		printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
+		       av7110->dvb_adapter->num);
 	else
-		printk("DVB: AV711%d(%d) - no firmware support for CI link layer interface\n",
-		       av7110->avtype, av7110->dvb_adapter->num);
+		printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
+		       av7110->dvb_adapter->num);
 
 	return 0;
 }
@@ -552,7 +552,7 @@
 	u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
 			16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (len > 10)
 		len = 10;
@@ -569,7 +569,7 @@
 		buf[i + 4] = msg[i];
 
 	if (av7110_send_fw_cmd(av7110, buf, 18))
-		printk("av7110_diseqc_send error\n");
+		printk("dvb-ttpci: av7110_diseqc_send error\n");
 
 	return 0;
 }
@@ -628,7 +628,7 @@
 	while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
 		msleep(1);
 		if (time_after(jiffies, start + ARM_WAIT_OSD)) {
-			printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n",
+			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
 			       __FUNCTION__);
 			up(&av7110->dcomlock);
 			return -1;
@@ -652,7 +652,7 @@
 	while (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2)) {
 		msleep(1);
 		if (time_after(jiffies, start + ARM_WAIT_OSD)) {
-			printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n",
+			printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
 			       __FUNCTION__);
 			up(&av7110->dcomlock);
 			return -1;
@@ -663,7 +663,7 @@
 	while (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2)) {
 		msleep(1);
 		if (time_after(jiffies, start + ARM_WAIT_SHAKE)) {
-			printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n",
+			printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
 			       __FUNCTION__);
 			up(&av7110->dcomlock);
 			return -1;
@@ -678,7 +678,7 @@
 	ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
 	up(&av7110->dcomlock);
 	if (ret)
-		printk("WriteText error\n");
+		printk("dvb-ttpci: WriteText error\n");
 	return ret;
 }
 
@@ -741,7 +741,7 @@
 	u8 c;
 	int ret;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	ret = wait_event_interruptible_timeout(av7110->bmpq, av7110->bmp_state != BMP_LOADING, HZ);
 	if (ret == -ERESTARTSYS || ret == 0) {
@@ -794,7 +794,7 @@
 {
 	int ret;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	BUG_ON (av7110->bmp_state == BMP_NONE);
 
@@ -812,7 +812,7 @@
 
 static inline int ReleaseBitmap(struct av7110 *av7110)
 {
-	DEB_EE(("av7110: %p\n",av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if (av7110->bmp_state != BMP_LOADED)
 		return -1;
diff -Nru a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
--- a/drivers/media/dvb/ttpci/av7110_ir.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/ttpci/av7110_ir.c	2004-10-28 22:25:57 -07:00
@@ -4,18 +4,13 @@
 #include <linux/moduleparam.h>
 #include <linux/input.h>
 #include <linux/proc_fs.h>
-#include <linux/bitops.h>
+#include <asm/bitops.h>
 
 #include "av7110.h"
 
 #define UP_TIMEOUT (HZ/4)
 
-static int av7110_ir_debug;
-
-module_param_named(debug_ir, av7110_ir_debug, int, 0644);
-MODULE_PARM_DESC(av7110_ir_debug, "Turn on/off IR debugging (default:off).");
-
-#define dprintk(x...)  do { if (av7110_ir_debug) printk (x); } while (0)
+/* enable ir debugging by or'ing av7110_debug with 16 */
 
 static struct input_dev input_dev;
 
@@ -78,7 +73,7 @@
 
 	keycode = key_map[data];
 	
-	dprintk ("#########%08x######### addr %i data 0x%02x (keycode %i)\n",
+	dprintk(16, "#########%08x######### addr %i data 0x%02x (keycode %i)\n",
 		 ircom, addr, data, keycode);
 
 	/* check device address (if selected) */
diff -Nru a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
--- a/drivers/media/dvb/ttpci/av7110_v4l.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c	2004-10-28 22:25:58 -07:00
@@ -45,8 +45,8 @@
 	struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg };
 
 	if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
-		printk("av7110(%d): %s(%u = %u) failed\n",
-		       av7110->dvb_adapter->num, __FUNCTION__, reg, val);
+		dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
+		       av7110->dvb_adapter->num, reg, val);
 		return -EIO;
 	}
 	return 0;
@@ -62,8 +62,8 @@
 	};
 
 	if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
-		printk("av7110(%d): %s(%u) failed\n",
-		       av7110->dvb_adapter->num, __FUNCTION__, reg);
+		dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
+		       av7110->dvb_adapter->num, reg);
 		return -EIO;
 	}
 	*val = (msg2[0] << 8) | msg2[1];
@@ -99,7 +99,7 @@
 	u8 buf[] = { 0x00, reg, data };
 	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
 
-	DEB_EE(("av7710: dev: %p\n", dev));
+	dprintk(4, "dev: %p\n", dev);
 
 	if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
 		return -1;
@@ -110,7 +110,7 @@
 {
 	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
 
-	DEB_EE(("av7710: dev: %p\n", dev));
+	dprintk(4, "dev: %p\n", dev);
 
 	if (1 != saa7146_i2c_transfer(dev, &msg, 1, 1))
 		return -1;
@@ -128,7 +128,7 @@
 	u8 config;
 	u8 buf[4];
 
-	DEB_EE(("av7710: freq: 0x%08x\n", freq));
+	dprintk(4, "freq: 0x%08x\n", freq);
 
 	/* magic number: 614. tuning with the frequency given by v4l2
 	   is always off by 614*62.5 = 38375 kHz...*/
@@ -171,13 +171,13 @@
 	u8 band = 0;
 	int source, sync, err;
 
-	DEB_EE(("av7110: %p\n", av7110));
+	dprintk(4, "%p\n", av7110);
 
 	if ((vv->video_status & STATUS_OVERLAY) != 0) {
 		vv->ov_suspend = vv->video_fh;
 		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
 		if (err != 0) {
-			DEB_D(("warning: suspending video failed\n"));
+			dprintk(2, "suspending video failed\n");
 			vv->ov_suspend = NULL;
 		}
 	}
@@ -188,7 +188,7 @@
 		source = SAA7146_HPS_SOURCE_PORT_B;
 		sync = SAA7146_HPS_SYNC_PORT_B;
 		memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
-		printk("av7110: switching to analog TV\n");
+		dprintk(1, "switching to analog TV\n");
 		msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
 		msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
 		msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
@@ -201,7 +201,7 @@
 		source = SAA7146_HPS_SOURCE_PORT_A;
 		sync = SAA7146_HPS_SYNC_PORT_A;
 		memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
-		printk("av7110: switching DVB mode\n");
+		dprintk(1, "switching DVB mode\n");
 		msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
 		msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
 		msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
@@ -212,10 +212,11 @@
 
 	/* hmm, this does not do anything!? */
 	if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
-		printk("ADSwitch error\n");
+		dprintk(1, "ADSwitch error\n");
 
 	if (ves1820_writereg(dev, 0x0f, band))
-		printk("setting band in demodulator failed.\n");
+		dprintk(1, "setting band in demodulator failed.\n");
+
 	saa7146_set_hps_source_and_sync(dev, source, sync);
 
 	if (vv->ov_suspend != NULL) {
@@ -230,7 +231,7 @@
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
-	DEB_EE(("saa7146_dev: %p\n", dev));
+	dprintk(4, "saa7146_dev: %p\n", dev);
 
 	switch (cmd) {
 	case VIDIOC_G_TUNER:
@@ -239,7 +240,7 @@
 		u16 stereo_det;
 		s8 stereo;
 
-		DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index));
+		dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
 
 		if (!av7110->has_analog_tuner || t->index != 0)
 			return -EINVAL;
@@ -258,10 +259,10 @@
 
 		// FIXME: standard / stereo detection is still broken
 		msp_readreg(av7110, MSP_RD_DEM, 0x007e, &stereo_det);
-printk("VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
+		dprintk(1, "VIDIOC_G_TUNER: msp3400 TV standard detection: 0x%04x\n", stereo_det);
 
 		msp_readreg(av7110, MSP_RD_DSP, 0x0018, &stereo_det);
-		printk("VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
+		dprintk(1, "VIDIOC_G_TUNER: msp3400 stereo detection: 0x%04x\n", stereo_det);
 		stereo = (s8)(stereo_det >> 8);
 		if (stereo > 0x10) {
 			/* stereo */
@@ -282,29 +283,29 @@
 	{
 		struct v4l2_tuner *t = arg;
 		u16 fm_matrix, src;
-		DEB_EE(("VIDIOC_S_TUNER: %d\n", t->index));
+		dprintk(2, "VIDIOC_S_TUNER: %d\n", t->index);
 
 		if (!av7110->has_analog_tuner || av7110->current_input != 1)
 			return -EINVAL;
 
 		switch (t->audmode) {
 		case V4L2_TUNER_MODE_STEREO:
-			DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n"));
+			dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n");
 			fm_matrix = 0x3001; // stereo
 			src = 0x0020;
 			break;
 		case V4L2_TUNER_MODE_LANG1:
-			DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n"));
+			dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n");
 			fm_matrix = 0x3000; // mono
 			src = 0x0000;
 			break;
 		case V4L2_TUNER_MODE_LANG2:
-			DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n"));
+			dprintk(2, "VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n");
 			fm_matrix = 0x3000; // mono
 			src = 0x0010;
 			break;
 		default: /* case V4L2_TUNER_MODE_MONO: {*/
-			DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n"));
+			dprintk(2, "VIDIOC_S_TUNER: TDA9840_SET_MONO\n");
 			fm_matrix = 0x3000; // mono
 			src = 0x0030;
 			break;
@@ -319,7 +320,7 @@
 	{
 		struct v4l2_frequency *f = arg;
 
-		DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency));
+		dprintk(2, "VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency);
 
 		if (!av7110->has_analog_tuner || av7110->current_input != 1)
 			return -EINVAL;
@@ -333,7 +334,7 @@
 	{
 		struct v4l2_frequency *f = arg;
 
-		DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency));
+		dprintk(2, "VIDIOC_S_FREQUENCY: freq:0x%08x.\n", f->frequency);
 
 		if (!av7110->has_analog_tuner || av7110->current_input != 1)
 			return -EINVAL;
@@ -358,7 +359,7 @@
 	{
 		struct v4l2_input *i = arg;
 
-		DEB_EE(("VIDIOC_ENUMINPUT: %d\n", i->index));
+		dprintk(2, "VIDIOC_ENUMINPUT: %d\n", i->index);
 
 		if (av7110->has_analog_tuner ) {
 			if (i->index < 0 || i->index >= 2)
@@ -376,14 +377,14 @@
 	{
 		int *input = (int *)arg;
 		*input = av7110->current_input;
-		DEB_EE(("VIDIOC_G_INPUT: %d\n", *input));
+		dprintk(2, "VIDIOC_G_INPUT: %d\n", *input);
 		return 0;
 	}
 	case VIDIOC_S_INPUT:
 	{
 		int input = *(int *)arg;
 
-		DEB_EE(("VIDIOC_S_INPUT: %d\n", input));
+		dprintk(2, "VIDIOC_S_INPUT: %d\n", input);
 
 		if (!av7110->has_analog_tuner )
 			return 0;
@@ -399,7 +400,7 @@
 	{
 		struct v4l2_audio *a = arg;
 
-		DEB_EE(("VIDIOC_G_AUDIO: %d\n", a->index));
+		dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
 		if (a->index != 0)
 			return -EINVAL;
 		memcpy(a, &msp3400_v4l2_audio, sizeof(struct v4l2_audio));
@@ -408,7 +409,7 @@
 	case VIDIOC_S_AUDIO:
 	{
 		struct v4l2_audio *a = arg;
-		DEB_EE(("VIDIOC_S_AUDIO: %d\n", a->index));
+		dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
 		break;
 	}
 	default:
@@ -506,13 +507,13 @@
 	    || i2c_writereg(av7110, 0x80, 0x0, 0) != 1)
 		return -ENODEV;
 
-	printk("av7110(%d): DVB-C analog module detected, initializing MSP3400\n",
+	printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
 		av7110->dvb_adapter->num);
 	av7110->adac_type = DVB_ADAC_MSP;
 	msleep(100); // the probing above resets the msp...
 	msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
 	msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
-	printk("av7110(%d): MSP3400 version 0x%04x 0x%04x\n",
+	dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n",
 		av7110->dvb_adapter->num, version1, version2);
 	msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
 	msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
@@ -531,8 +532,7 @@
 		/* init the saa7113 */
 		while (*i != 0xff) {
 			if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
-				printk("av7110(%d): saa7113 initialization failed",
-						av7110->dvb_adapter->num);
+				dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter->num);
 				break;
 			}
 			i += 2;
diff -Nru a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
--- a/drivers/media/dvb/ttpci/budget-av.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/dvb/ttpci/budget-av.c	2004-10-28 22:25:59 -07:00
@@ -127,19 +127,18 @@
 	const u8 *data = saa7113_tab;
 
         if (i2c_writereg (&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
-                DEB_D(("saa7113: not found on KNC card\n"));
+                dprintk(1, "saa7113 not found on KNC card\n");
                 return -ENODEV;
         }
 
-        INFO(("saa7113: detected and initializing\n"));
+        dprintk(1, "saa7113 detected and initializing\n");
 
 	while (*data != 0xff) {
                 i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data+1));
                 data += 2;
         }
 
-	DEB_D(("saa7113: status=%02x\n",
-	      i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f)));
+	dprintk(1, "saa7113  status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
 
 	return 0;
 }
@@ -171,7 +170,7 @@
 	struct budget_av *budget_av = (struct budget_av*) dev->ext_priv;
 	int err;
 
-	DEB_EE(("dev: %p\n",dev));
+	dprintk(2, "dev: %p\n", dev);
 
 	if ( 1 == budget_av->has_saa7113 ) {
 	saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
@@ -198,7 +197,7 @@
 	u8 *mac;
 	int err;
 
-	DEB_EE(("dev: %p\n",dev));
+	dprintk(2, "dev: %p\n", dev);
 
 	if (bi->type != BUDGET_KNC1 && bi->type != BUDGET_CIN1200) {
 		return -ENODEV;
@@ -299,7 +298,7 @@
 	{
 		struct v4l2_input *i = arg;
 		
-		DEB_EE(("VIDIOC_ENUMINPUT %d.\n",i->index));
+		dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
 		if( i->index < 0 || i->index >= KNC1_INPUTS) {
 			return -EINVAL;
 		}
@@ -312,19 +311,16 @@
 
 		*input = budget_av->cur_input;
 
-		DEB_EE(("VIDIOC_G_INPUT %d.\n",*input));
+		dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
 		return 0;		
 	}	
 	case VIDIOC_S_INPUT:
 	{
 		int input = *(int *)arg;
-		DEB_EE(("VIDIOC_S_INPUT %d.\n", input));
+		dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
 		return saa7113_setinput (budget_av, input);
 	}
 	default:
-/*
-		DEB2(printk("does not handle this ioctl.\n"));
-*/
 		return -ENOIOCTLCMD;
 	}
 	return 0;
@@ -384,21 +380,13 @@
 	.irq_func	= ttpci_budget_irq10_handler,
 };	
 
-
 static int __init budget_av_init(void) 
 {
-	DEB_EE((".\n"));
-
-	if (saa7146_register_extension(&budget_extension))
-		return -ENODEV;
-	
-	return 0;
+	return saa7146_register_extension(&budget_extension);
 }
 
-
 static void __exit budget_av_exit(void)
 {
-	DEB_EE((".\n"));
 	saa7146_unregister_extension(&budget_extension); 
 }
 
diff -Nru a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
--- a/drivers/media/dvb/ttpci/budget-ci.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/ttpci/budget-ci.c	2004-10-28 22:25:57 -07:00
@@ -500,7 +500,7 @@
 {
         struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv;
 
-        DEB_EE(("dev: %p, budget_ci: %p\n", dev, budget_ci));
+	dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
 
         if (*isr & MASK_06)
                 tasklet_schedule (&budget_ci->msp430_irq_tasklet);
@@ -523,7 +523,7 @@
 	if (!(budget_ci = kmalloc (sizeof(struct budget_ci), GFP_KERNEL)))
 		return -ENOMEM;
 
-	DEB_EE(("budget_ci: %p\n", budget_ci));
+	dprintk(2, "budget_ci: %p\n", budget_ci);
 
 	spin_lock_init(&budget_ci->debilock);
 	budget_ci->budget.ci_present = 0;
@@ -606,10 +606,8 @@
 	return saa7146_register_extension(&budget_extension);
 }
 
-
 static void __exit budget_ci_exit(void)
 {
-	DEB_EE((".\n"));
 	saa7146_unregister_extension(&budget_extension); 
 }
 
diff -Nru a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
--- a/drivers/media/dvb/ttpci/budget-core.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/ttpci/budget-core.c	2004-10-28 22:25:57 -07:00
@@ -50,7 +50,7 @@
 
 static int stop_ts_capture(struct budget *budget)
 {
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
         if (--budget->feeding)
                 return budget->feeding;
@@ -65,7 +65,7 @@
 {
         struct saa7146_dev *dev=budget->dev;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
         if (budget->feeding) 
                 return ++budget->feeding;
@@ -171,7 +171,7 @@
         struct budget *budget = (struct budget*) demux->priv;
 	int status;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
         if (!demux->dmx.frontend)
                 return -EINVAL;
@@ -188,7 +188,7 @@
         struct budget *budget = (struct budget *) demux->priv;
 	int status;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
    	spin_lock(&budget->feedlock);
 	status = stop_ts_capture (budget);
@@ -202,7 +202,7 @@
         struct dvb_demux *dvbdemux=&budget->demux;
         int ret;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
         dvbdemux->priv = (void *) budget;
 
@@ -251,7 +251,7 @@
 {
         struct dvb_demux *dvbdemux=&budget->demux;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
 	dvb_net_release(&budget->dvb_net);
 
@@ -294,7 +294,7 @@
 
 	memset(budget, 0, sizeof(struct budget));
 
-	DEB_EE(("dev: %p, budget: %p\n", dev, budget));
+	dprintk(2, "dev: %p, budget: %p\n", dev, budget);
 
 	budget->card = bi;
 	budget->dev = (struct saa7146_dev *) dev;
@@ -377,7 +377,7 @@
 {
 	struct saa7146_dev *dev = budget->dev;
 
-	DEB_EE(("budget: %p\n", budget));
+	dprintk(2, "budget: %p\n", budget);
 
 	budget_unregister (budget);
 
@@ -398,7 +398,7 @@
 {
 	struct budget *budget = (struct budget*)dev->ext_priv;
 
-	DEB_EE(("dev: %p, budget: %p\n",dev,budget));
+	dprintk(8, "dev: %p, budget: %p\n",dev,budget);
 
 	if (*isr & MASK_10)
 		tasklet_schedule (&budget->vpe_tasklet);
diff -Nru a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
--- a/drivers/media/dvb/ttpci/budget-patch.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/dvb/ttpci/budget-patch.c	2004-10-28 22:25:57 -07:00
@@ -30,9 +30,9 @@
  * the project's page is at http://www.linuxtv.org/dvb/
  */
 
-#include "budget.h"
 #include "av7110.h"
 #include "av7110_hw.h"
+#include "budget.h"
 
 #define budget_patch budget
 
@@ -51,7 +51,7 @@
 {
         struct saa7146_dev *dev=budget->dev;
 
-        DEB_EE(("budget: %p\n", budget));
+        dprintk(2, "budget: %p\n", budget);
 
         if (count <= 0 || count > 4)
                 return -1;
@@ -71,7 +71,7 @@
 {
         int i;
 
-        DEB_EE(("budget: %p\n", budget));
+        dprintk(2, "budget: %p\n", budget);
 
         for (i = 2; i < length; i++)
                 budget_wdebi(budget, DEBINOSWAP, COMMAND + 2*i, (u32) buf[i], 2);
@@ -90,7 +90,7 @@
 {
         u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0};
         
-        DEB_EE(("budget: %p\n", budget));
+        dprintk(2, "budget: %p\n", budget);
         budget_av7110_send_fw_cmd(budget, buf, 2);
 }
 
@@ -101,7 +101,7 @@
         u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) | SendDiSEqC),
                 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
-        DEB_EE(("budget: %p\n", budget));
+        dprintk(2, "budget: %p\n", budget);
 
         if (len>10)
                 len=10;
@@ -126,7 +126,7 @@
 {
         struct budget_patch *budget = fe->before_after_data;
 
-        DEB_EE(("budget: %p\n", budget));
+        dprintk(2, "budget: %p\n", budget);
 
         switch (cmd) {
         case FE_SET_TONE:
@@ -171,7 +171,7 @@
         if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
                 return -ENOMEM;
 
-        DEB_EE(("budget: %p\n",budget));
+        dprintk(2, "budget: %p\n", budget);
 
         if ((err = ttpci_budget_init (budget, dev, info))) {
                 kfree (budget);
@@ -251,10 +251,8 @@
 	return saa7146_register_extension(&budget_extension);
 }
 
-
 static void __exit budget_patch_exit(void)
 {
-        DEB_EE((".\n"));
         saa7146_unregister_extension(&budget_extension); 
 }
 
diff -Nru a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
--- a/drivers/media/dvb/ttpci/budget.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/ttpci/budget.c	2004-10-28 22:25:58 -07:00
@@ -39,7 +39,7 @@
 static void Set22K (struct budget *budget, int state)
 {
 	struct saa7146_dev *dev=budget->dev;
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 	saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
 }
 
@@ -51,7 +51,7 @@
 static void DiseqcSendBit (struct budget *budget, int data)
 {
 	struct saa7146_dev *dev=budget->dev;
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
 	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
 	udelay(data ? 500 : 1000);
@@ -64,7 +64,7 @@
 {
 	int i, par=1, d;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
 	for (i=7; i>=0; i--) {
 		d = (data>>i)&1;
@@ -81,7 +81,7 @@
 	struct saa7146_dev *dev=budget->dev;
 	int i;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
 	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
 	mdelay(16);
@@ -110,7 +110,7 @@
 {
        struct budget *budget = fe->before_after_data;
 
-       DEB_EE(("budget: %p\n",budget));
+       dprintk(2, "budget: %p\n", budget);
 
        switch (cmd) {
        case FE_SET_TONE:
@@ -155,7 +155,7 @@
 {
 	struct saa7146_dev *dev=budget->dev;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
 	switch (voltage) {
 		case SEC_VOLTAGE_13:
@@ -176,7 +176,7 @@
 {
 	struct budget *budget = fe->before_after_data;
 
-	DEB_EE(("budget: %p\n",budget));
+	dprintk(2, "budget: %p\n", budget);
 
 	switch (cmd) {
 		case FE_SET_VOLTAGE:
@@ -199,7 +199,7 @@
 		return -ENOMEM;
 	}
 
-	DEB_EE(("dev:%p, info:%p, budget:%p\n",dev,info,budget));
+	dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
 
 	dev->ext_priv = budget;
 
@@ -289,7 +289,6 @@
 
 static void __exit budget_exit(void)
 {
-	DEB_EE((".\n"));
 	saa7146_unregister_extension(&budget_extension); 
 }
 
diff -Nru a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
--- a/drivers/media/dvb/ttpci/budget.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/dvb/ttpci/budget.h	2004-10-28 22:25:58 -07:00
@@ -13,6 +13,13 @@
 
 extern int budget_debug;
 
+#ifdef dprintk
+#undef dprintk
+#endif
+
+#define dprintk(level,args...) \
+            do { if ((budget_debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0)
+
 struct budget_info {
 	char *name;
 	int type;
diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2004-10-28 22:25:59 -07:00
@@ -1293,6 +1293,7 @@
 				ttusb_dec_set_model(dec, TTUSB_DEC3000S);
 				break;
 			case 0x00070009:
+			case 0x00070013:
 				ttusb_dec_set_model(dec, TTUSB_DEC2000T);
 				break;
 			case 0x00070011:
diff -Nru a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
--- a/drivers/media/video/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/Kconfig	2004-10-28 22:25:59 -07:00
@@ -9,8 +9,13 @@
 
 config VIDEO_BT848
 	tristate "BT848 Video For Linux"
-	depends on VIDEO_DEV && PCI && I2C && FW_LOADER
+	depends on VIDEO_DEV && PCI && I2C
 	select I2C_ALGOBIT
+	select FW_LOADER
+	select VIDEO_BTCX
+	select VIDEO_BUF
+	select VIDEO_IR
+	select VIDEO_TUNER
 	---help---
 	  Support for BT848 based frame grabber/overlay boards. This includes
 	  the Miro, Hauppauge and STB boards. Please read the material in
@@ -230,6 +235,9 @@
 config VIDEO_SAA7134
 	tristate "Philips SAA7134 support"
 	depends on VIDEO_DEV && PCI && I2C
+	select VIDEO_BUF
+	select VIDEO_IR
+	select VIDEO_TUNER
 	---help---
 	  This is a video4linux driver for Philips SAA7130/7134 based
 	  TV cards.
@@ -241,6 +249,7 @@
 	tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
 	depends on VIDEO_DEV && PCI
 	select VIDEO_SAA7146_VV
+	select VIDEO_TUNER
 	---help---
 	  This is a video4linux driver for the 'Multimedia eXtension Board'
 	  TV card by Siemens-Nixdorf.
@@ -287,7 +296,11 @@
 
 config VIDEO_CX88
 	tristate "Conexant 2388x (bt878 successor) support"
-	depends on VIDEO_DEV && PCI && I2C_ALGOBIT && EXPERIMENTAL
+	depends on VIDEO_DEV && PCI && EXPERIMENTAL
+	select I2C_ALGOBIT
+	select VIDEO_BTCX
+	select VIDEO_BUF
+	select VIDEO_TUNER
 	---help---
 	  This is a video4linux driver for Conexant 2388x based
 	  TV cards.
diff -Nru a/drivers/media/video/bt848.h b/drivers/media/video/bt848.h
--- a/drivers/media/video/bt848.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/video/bt848.h	2004-10-28 22:25:57 -07:00
@@ -1,4 +1,4 @@
-/* 
+/*
     bt848.h - Bt848 register offsets
 
     Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
@@ -22,10 +22,10 @@
 #define _BT848_H_
 
 #ifndef PCI_VENDOR_ID_BROOKTREE
-#define PCI_VENDOR_ID_BROOKTREE 0x109e 
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
 #endif
 #ifndef PCI_DEVICE_ID_BT848
-#define PCI_DEVICE_ID_BT848     0x350	
+#define PCI_DEVICE_ID_BT848     0x350
 #endif
 #ifndef PCI_DEVICE_ID_BT849
 #define PCI_DEVICE_ID_BT849     0x351
@@ -50,7 +50,7 @@
 #define BT848_DSTATUS_LOF      (1<<1)
 #define BT848_DSTATUS_COF      (1<<0)
 
-#define BT848_IFORM            0x004  
+#define BT848_IFORM            0x004
 #define BT848_IFORM_HACTIVE    (1<<7)
 #define BT848_IFORM_MUXSEL     (3<<5)
 #define BT848_IFORM_MUX0       (2<<5)
@@ -71,7 +71,7 @@
 #define BT848_IFORM_AUTO       0
 #define BT848_IFORM_NORM       7
 
-#define BT848_TDEC             0x008  
+#define BT848_TDEC             0x008
 #define BT848_TDEC_DEC_FIELD   (1<<7)
 #define BT848_TDEC_FLDALIGN    (1<<6)
 #define BT848_TDEC_DEC_RAT     (0x1f)
diff -Nru a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
--- a/drivers/media/video/btcx-risc.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/media/video/btcx-risc.c	2004-10-28 22:25:56 -07:00
@@ -1,5 +1,5 @@
 /*
-    $Id: btcx-risc.c,v 1.2 2004/09/15 16:15:24 kraxel Exp $
+    $Id: btcx-risc.c,v 1.3 2004/10/13 10:39:00 kraxel Exp $
 
     btcx-risc.c
 
@@ -189,7 +189,7 @@
 {
 	unsigned int clip,skip;
 	int end,maxline;
-	
+
 	skip=0;
 	maxline = 9999;
 	for (clip = 0; clip < nclips; clip++) {
@@ -199,7 +199,7 @@
 			continue;
 		if (clips[clip].c.left > (signed)width)
 			break;
-		
+
 		/* vertical range */
 		if (line > clips[clip].c.top+clips[clip].c.height-1)
 			continue;
diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
--- a/drivers/media/video/bttv-cards.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/bttv-cards.c	2004-10-28 22:25:58 -07:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-cards.c,v 1.28 2004/10/06 13:45:14 kraxel Exp $
+    $Id: bttv-cards.c,v 1.29 2004/10/13 10:39:00 kraxel Exp $
 
     bttv-cards.c
 
@@ -143,7 +143,7 @@
 int __init bttv_parse(char *str, int max, int *vals)
 {
 	int i,number,res = 2;
-	
+
 	for (i = 0; res == 2 && i < max; i++) {
 		res = get_option(&str,&number);
 		if (res)
@@ -192,7 +192,7 @@
 	{ 0x3000121a, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
 	{ 0x263710b4, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
 	{ 0x3060121a, BTTV_STB2,	  "3Dfx VoodooTV 100/ STB OEM" },
-	
+
 	{ 0x3000144f, BTTV_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
 	{ 0x3002144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
 	{ 0x3005144f, BTTV_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
@@ -210,7 +210,7 @@
 	{ 0x1118153b, BTTV_TERRATVALUE,   "Terratec TValue (Temic PAL B/G)" },
 	{ 0x1119153b, BTTV_TERRATVALUE,   "Terratec TValue (Philips PAL I)" },
 	{ 0x111a153b, BTTV_TERRATVALUE,   "Terratec TValue (Temic PAL I)" },
- 
+
 	{ 0x1123153b, BTTV_TERRATVRADIO,  "Terratec TV Radio+" },
 	{ 0x1127153b, BTTV_TERRATV,       "Terratec TV+ (V1.05)"    },
 	// clashes with FlyVideo
@@ -246,7 +246,7 @@
 	{ 0xa1550000, BTTV_IVC200,        "IVC-200"  },
 	{ 0xa1550001, BTTV_IVC200,        "IVC-200"  },
 	{ 0xa1550002, BTTV_IVC200,        "IVC-200"  },
-	{ 0xa1550003, BTTV_IVC200,        "IVC-200"  },	
+	{ 0xa1550003, BTTV_IVC200,        "IVC-200"  },
 	{ 0xa1550100, BTTV_IVC200,        "IVC-200G" },
 	{ 0xa1550101, BTTV_IVC200,        "IVC-200G" },
 	{ 0xa1550102, BTTV_IVC200,        "IVC-200G" },
@@ -267,10 +267,10 @@
 	{ 0xa182ff0d, BTTV_IVC120,        "IVC-120G" },
 	{ 0xa182ff0e, BTTV_IVC120,        "IVC-120G" },
 	{ 0xa182ff0f, BTTV_IVC120,        "IVC-120G" },
-	
+
 	{ 0x41424344, BTTV_GRANDTEC,      "GrandTec Multi Capture" },
 	{ 0x01020304, BTTV_XGUARD,        "Grandtec Grand X-Guard" },
-	
+
 	{ 0x18501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
 	{ 0xa0501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
 	{ 0x18511851, BTTV_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
@@ -302,7 +302,7 @@
 
 	// likely broken, vendor id doesn't match the other magic views ...
 	//{ 0xa0fca04f, BTTV_MAGICTVIEW063, "Guillemot Maxi TV Video 3" },
-	
+
 	// DVB cards (using pci function .1 for mpeg data xfer)
 	{ 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
 	{ 0x07611461, BTTV_AVDVBT_761,    "AverMedia AverTV DVB-T" },
@@ -311,7 +311,7 @@
 	{ 0xfc00270f, BTTV_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
 	{ 0x07711461, BTTV_AVDVBT_771,    "AVermedia DVB-T 771" },
 	{ 0xdb1018ac, BTTV_DVICO_DVBT_LITE,    "DVICO FusionHDTV DVB-T Lite" },
-	
+
 	{ 0, -1, NULL }
 };
 
@@ -702,7 +702,7 @@
 		10000 : ext. Video audio input
 		20000 : TV Mono
 		a0000 : TV Mono/2
-	       1a0000 : TV Stereo	
+	       1a0000 : TV Stereo
 		30000 : Radio
 		40000 : Mute
        */
@@ -1117,7 +1117,7 @@
 	.pll            = PLL_28,
 	.tuner_type     = 5,
 },{
-	/* This is the ultimate cheapo capture card 
+	/* This is the ultimate cheapo capture card
 	 * just a BT848A on a small PCB!
 	 * Steve Hosgood <steve@equiinet.com> */
 	.name           = "GrandTec 'Grand Video Capture' (Bt848)",
@@ -1188,7 +1188,7 @@
 	.tuner_type     = -1,
 },{
 	/* Miguel Angel Alvarez <maacruz@navegalia.com>
-	   new Easy TV BT878 version (model CPH061) 
+	   new Easy TV BT878 version (model CPH061)
 	   special thanks to Informatica Mieres for providing the card */
 	.name           = "Askey CPH061/ BESTBUY Easy TV (bt878)",
 	.video_inputs	= 3,
@@ -1392,7 +1392,7 @@
 },{
         .name           = "Powercolor MTV878/ MTV878R/ MTV878F",
         .video_inputs   = 3,
-        .audio_inputs   = 2, 
+        .audio_inputs   = 2,
 	.tuner		= 0,
         .svhs           = 2,
         .gpiomask       = 0x1C800F,  // Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset
@@ -1570,7 +1570,7 @@
         .no_tda9875     = 1,
         .no_tda7432     = 1,
 },{
-	
+
 	/* ---- card 0x58 ---------------------------------- */
 	.name           = "Osprey 200/250",   /* 0x1(A|B)-00C4-C1 */
 	.video_inputs   = 2,
@@ -1663,11 +1663,11 @@
 	.tuner_type     = -1,
 	.no_msp34xx     = 1,
 	.no_tda9875     = 1,
-	.no_tda7432     = 1,   
+	.no_tda7432     = 1,
 	.gpiomask       = 0x01,
 	.audiomux       = { 0, 0, 0, 0, 1 },
 	.muxsel         = { 3, 0, 1, 2},
-	.needs_tvaudio  = 0, 
+	.needs_tvaudio  = 0,
 	.pll            = PLL_28,
 	.no_gpioirq     = 1,
 },{
@@ -1679,7 +1679,7 @@
         .gpiomask       = 2,
 	// TV, Comp1, Composite over SVID con, SVID
         .muxsel         = { 2, 3, 1, 1},
-        .audiomux       = { 2, 2, 0, 0, 0 }, 
+        .audiomux       = { 2, 2, 0, 0, 0 },
         .pll            = PLL_28,
 	.has_radio      = 1,
         .tuner_type     = TUNER_PHILIPS_PAL,
@@ -1764,7 +1764,7 @@
 	/* Notes:
 	   - card lacks subsystem ID
 	   - stereo variant w/ daughter board with tda9874a @0xb0
-	   - Audio Routing: 
+	   - Audio Routing:
 		always from tda9874 independent of GPIO (?)
 		external line in: unknown
 	   - Other chips: em78p156elp @ 0x96 (probably IR remote control)
@@ -1848,7 +1848,7 @@
 	.audio_inputs   = 0,
 	.tuner          = -1, /* card has no tuner */
 	.svhs           = 3,
-	.gpiomask       = 0x00, 
+	.gpiomask       = 0x00,
 	.muxsel         = { 2, 3, 1, 0},
 	.audiomux       = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
 	.needs_tvaudio  = 1,
@@ -1921,7 +1921,7 @@
 	.no_tda9875     = 1,
 	.no_tda7432     = 1,
 	.gpiomask       = 0x00,
-	.muxsel         = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 
+	.muxsel         = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
 			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
 	.muxsel_hook    = ivc120_muxsel,
 	.pll            = PLL_28,
@@ -2206,7 +2206,7 @@
 		for (type = -1, i = 0; cards[i].id != 0; i++)
 			if (cards[i].id  == btv->cardid)
 				type = i;
-		
+
 		if (type != -1) {
 			/* found it */
 			printk(KERN_INFO "bttv%d: detected: %s [card=%d], "
@@ -2223,12 +2223,12 @@
 			printk(KERN_DEBUG "please mail id, board name and "
 			       "the correct card= insmod option to kraxel@bytesex.org\n");
 		}
-	} 
+	}
 
 	/* let the user override the autodetected type */
 	if (card[btv->c.nr] < bttv_num_tvcards)
 		btv->c.type=card[btv->c.nr];
-	
+
 	/* print which card config we are using */
 	printk(KERN_INFO "bttv%d: using: %s [card=%d,%s]\n",btv->c.nr,
 	       bttv_tvcards[btv->c.type].name, btv->c.type,
@@ -2268,7 +2268,7 @@
 void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
 {
 	int type = -1;
-	
+
 	if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13))
 		type = BTTV_MODTEC_205;
 	else if (0 == strncmp(eeprom_data+20,"Picolo",7))
@@ -2284,7 +2284,7 @@
 }
 
 static void flyvideo_gpio(struct bttv *btv)
-{ 
+{
 	int gpio,has_remote,has_radio,is_capture_only,is_lr90,has_tda9820_tda9821;
 	int tuner=-1,ttype;
 
@@ -2298,10 +2298,10 @@
 	//       CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
 	//       GPIO14-12: n.c.
 	// LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
-	
+
 	// lowest 3 bytes are remote control codes (no handshake needed)
         // xxxFFF: No remote control chip soldered
-        // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered 
+        // xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
 	// Note: Some bits are Audio_Mask !
 
 	ttype=(gpio&0x0f0000)>>16;
@@ -2329,18 +2329,18 @@
 	is_lr90             = !(gpio & 0x002000); // else LR26/LR50 (LR38/LR51 f. capture only)
         //		        gpio & 0x001000 // output bit for audio routing
 
-	if(is_capture_only) 
-		tuner=4; // No tuner present 
+	if(is_capture_only)
+		tuner=4; // No tuner present
 
-	printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n", 
-	       btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio); 
+	printk(KERN_INFO "bttv%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+	       btv->c.nr, has_radio? "yes":"no ", has_remote? "yes":"no ", tuner, gpio);
 	printk(KERN_INFO "bttv%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
-		btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ", 
+		btv->c.nr, is_lr90?"yes":"no ", has_tda9820_tda9821?"yes":"no ",
 		is_capture_only?"yes":"no ");
 
 	if(tuner!= -1) // only set if known tuner autodetected, else let insmod option through
 		btv->tuner_type = tuner;
-	btv->has_radio = has_radio;  
+	btv->has_radio = has_radio;
 
 	// LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
         // LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
@@ -2439,13 +2439,13 @@
 {
 	gpio_inout(0xffffff,0xFFFF37);
 	gpio_write(0x200020);
-	
+
 	/* flash strobe inverter ?! */
 	gpio_write(0x200024);
-	
+
 	/* switch sync drive off */
 	gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
-	
+
 	/* set BT848 muxel to 2 */
 	btaor((2)<<5, ~(2<<5), BT848_IFORM);
 }
@@ -2534,7 +2534,7 @@
 	 */
 	if (btv->id != 878)
 		return;
-	
+
 	if (bttv_debug)
 		printk("bttv%d: BT878A ARESET\n",btv->c.nr);
 	btwrite((1<<7), 0x058);
@@ -2581,7 +2581,7 @@
 	case BTTV_MIRO:
 	case BTTV_MIROPRO:
 	case BTTV_PINNACLE:
-	case BTTV_PINNACLEPRO: 
+	case BTTV_PINNACLEPRO:
 		/* miro/pinnacle */
 		miro_pinnacle_gpio(btv);
 		break;
@@ -2705,7 +2705,7 @@
 
 	/* tuner configuration (from card list / autodetect / insmod option) */
  	if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
-		if(UNSET == btv->tuner_type) 
+		if(UNSET == btv->tuner_type)
                 	btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
 	if (UNSET != tuner[btv->c.nr])
 		btv->tuner_type = tuner[btv->c.nr];
@@ -2753,7 +2753,7 @@
 	    bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0)
 		request_module("tda9875");
 
-	if (!bttv_tvcards[btv->c.type].no_tda7432 && 
+	if (!bttv_tvcards[btv->c.type].no_tda7432 &&
 	    bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0)
 		request_module("tda7432");
 
@@ -2777,12 +2777,12 @@
 /* ----------------------------------------------------------------------- */
 /* some hauppauge specific stuff                                           */
 
-static struct HAUPPAUGE_TUNER 
+static struct HAUPPAUGE_TUNER
 {
         int  id;
         char *name;
-} 
-hauppauge_tuner[] __devinitdata = 
+}
+hauppauge_tuner[] __devinitdata =
 {
         { TUNER_ABSENT,        "" },
         { TUNER_ABSENT,        "External" },
@@ -2832,7 +2832,7 @@
 	{ TUNER_ABSENT,        "Philips TD1536D_FH_44"},
 	{ TUNER_LG_NTSC_FM,    "LG TPI8NSR01F"},
 	{ TUNER_LG_PAL_FM,     "LG TPI8PSB01D"},
-	{ TUNER_LG_PAL,        "LG TPI8PSB11D"},	
+	{ TUNER_LG_PAL,        "LG TPI8PSB11D"},
 	{ TUNER_LG_PAL_I_FM,   "LG TAPC-I001D"},
 	{ TUNER_LG_PAL_I,      "LG TAPC-I701D"}
 };
@@ -2872,12 +2872,12 @@
 	model = eeprom_data[12] << 8 | eeprom_data[11];
 	tuner = eeprom_data[9];
 	radio = eeprom_data[blk2-1] & 0x01;
-	
+
         if (tuner < ARRAY_SIZE(hauppauge_tuner))
                 btv->tuner_type = hauppauge_tuner[tuner].id;
 	if (radio)
 		btv->has_radio = 1;
-	
+
 	if (bttv_verbose)
 		printk(KERN_INFO "bttv%d: Hauppauge eeprom: model=%d, "
 		       "tuner=%s (%d), radio=%s\n",
@@ -2914,7 +2914,7 @@
 		btv->has_matchbox = 0;
 	}
 	return 0;
-}	
+}
 
 
 /* ----------------------------------------------------------------------- */
@@ -2941,7 +2941,7 @@
 	gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG);
 	gpio_write(0);
 	udelay(PVR_GPIO_DELAY);
-	
+
 	gpio_write(BTTV_ALT_NCONFIG);
 	udelay(PVR_GPIO_DELAY);
 
@@ -2951,7 +2951,7 @@
 			gpio_bits(BTTV_ALT_DCLK,0);
 			if (bits & 0x01)
 				gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA);
-			else 
+			else
 				gpio_bits(BTTV_ALT_DATA,0);
 			gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
 			bits >>= 1;
@@ -2959,7 +2959,7 @@
 	}
 	gpio_bits(BTTV_ALT_DCLK,0);
 	udelay(PVR_GPIO_DELAY);
-	
+
 	/* begin Altera init loop (Not necessary,but doesn't hurt) */
 	for (i = 0 ; i < 30 ; i++) {
 		gpio_bits(BTTV_ALT_DCLK,0);
@@ -2971,7 +2971,7 @@
 
 #if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
 /* old 2.4.x way -- via soundcore's mod_firmware_load */
-   
+
 static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf";
 MODULE_PARM(firm_altera,"s");
 MODULE_PARM_DESC(firm_altera,"WinTV/PVR firmware "
@@ -2991,7 +2991,7 @@
 		       btv->c.nr, firm_altera);
 		return -1;
 	}
-	
+
 	printk(KERN_INFO "bttv%d: uploading altera firmware [%s] ...\n",
 	       btv->c.nr, firm_altera);
 	result = pvr_altera_load(btv, micro, microlen);
@@ -3019,7 +3019,7 @@
 	       btv->c.nr, (rc < 0) ? "failed" : "ok");
         release_firmware(fw_entry);
 	return rc;
-}	
+}
 #endif
 
 /* ----------------------------------------------------------------------- */
@@ -3030,7 +3030,7 @@
        int i = 0;
        unsigned char *ee = eeprom_data;
        unsigned long serial = 0;
-    
+
        if (btv->c.type == 0) {
                /* this might be an antique... check for MMAC label in eeprom */
                if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) {
@@ -3046,7 +3046,7 @@
        } else {
 	       unsigned short type;
                int offset = 4*16;
-        
+
                for(; offset < 8*16; offset += 16) {
                        unsigned short checksum = 0;
                        /* verify the checksum */
@@ -3057,13 +3057,13 @@
                                break;
                        }
                }
-        
+
                if (offset >= 8*16)
 		       return;
 
 	       /* found a valid descriptor */
 	       type = (ee[offset+4]<<8) | (ee[offset+5]);
-	       
+
 	       switch(type) {
 
 	       /* 848 based */
@@ -3073,7 +3073,7 @@
 	       case 0x0005:
 		       btv->c.type = BTTV_OSPREY101_848;
 		       break;
-		       
+
                /* 878 based */
 	       case 0x0012:
 	       case 0x0013:
@@ -3121,10 +3121,10 @@
 		       | (ee[offset+8] <<  8)
 		       | (ee[offset+9]);
        }
-       
+
        printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n",
 	      btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial);
-}	
+}
 
 /* ----------------------------------------------------------------------- */
 /* AVermedia specific stuff, from  bktr_card.c                             */
@@ -3166,7 +3166,7 @@
 	if (tuner_make == 1)
 		if(tuner_format <=9)
 			tuner = tuner_1_table[tuner_format];
-	
+
 	printk(KERN_INFO "bttv%d: Avermedia eeprom[0x%02x%02x]: tuner=",
 		btv->c.nr,eeprom_data[0x41],eeprom_data[0x42]);
 	if(tuner) {
@@ -3256,8 +3256,8 @@
 
 /* ----------------------------------------------------------------------- */
 /*  Imagenation L-Model PXC200 Framegrabber */
-/*  This is basically the same procedure as 
- *  used by Alessandro Rubini in his pxc200 
+/*  This is basically the same procedure as
+ *  used by Alessandro Rubini in his pxc200
  *  driver, but using BTTV functions */
 
 static void __devinit init_PXC200(struct bttv *btv)
@@ -3268,13 +3268,13 @@
 	unsigned int i;
 	int tmp;
 	u32 val;
-	
+
 	/* Initialise GPIO-connevted stuff */
 	gpio_inout(0xffffff, (1<<13));
 	gpio_write(0);
 	udelay(3);
 	gpio_write(1<<13);
-	/* GPIO inputs are pulled up, so no need to drive 
+	/* GPIO inputs are pulled up, so no need to drive
 	 * reset pin any longer */
 	gpio_bits(0xffffff, 0);
 	if (bttv_gpio)
@@ -3289,16 +3289,16 @@
 	*/
 
 	btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
-	
+
 	/*	Initialise MAX517 DAC */
 	printk(KERN_INFO "Setting DAC reference voltage level ...\n");
 	bttv_I2CWrite(btv,0x5E,0,0x80,1);
-	
+
 	/*	Initialise 12C508 PIC */
-	/*	The I2CWrite and I2CRead commmands are actually to the 
+	/*	The I2CWrite and I2CRead commmands are actually to the
 	 *	same chips - but the R/W bit is included in the address
 	 *	argument so the numbers are different */
-	
+
 
 	printk(KERN_INFO "Initialising 12C508 PIC chip ...\n");
 
@@ -3306,7 +3306,7 @@
 	val = btread(BT848_GPIO_DMA_CTL);
 	val |= BT848_GPIO_DMA_CTL_GPCLKMODE;
 	btwrite(val, BT848_GPIO_DMA_CTL);
-	
+
 	/* Then, push to 0 the reset pin long enough to reset the *
 	 * device same as above for the reset line, but not the same
 	 * value sent to the GPIO-connected stuff
@@ -3418,7 +3418,7 @@
 	unsigned long timeout;
 	int value = 0;
 	int i;
-	
+
 	/* better safe than sorry */
 	gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
 
@@ -3430,10 +3430,10 @@
 
 	if (bttv_gpio)
 		bttv_gpio_tracking(btv,"tea5757 read");
-	
+
 	bus_low(btv,btv->mbox_we);
 	bus_low(btv,btv->mbox_clk);
-	
+
 	udelay(10);
 	timeout= jiffies + HZ;
 
@@ -3465,7 +3465,7 @@
 {
 	int i;
 	int reg = value;
-	
+
 	gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
 
 	if (btv->mbox_ior) {
@@ -3520,7 +3520,7 @@
 		v->flags |= VIDEO_AUDIO_VOLUME;
 		return;
 	}
-	
+
 	/* 32 levels logarithmic */
 	vol = 32 - ((v->volume>>11));
 	/* units */
@@ -3547,7 +3547,7 @@
 	data |=  WINVIEW_PT2254_STROBE;
 	data &= ~WINVIEW_PT2254_DATA;
 	gpio_write(data);
-	udelay(10);                     
+	udelay(10);
 	data &= ~WINVIEW_PT2254_STROBE;
 	gpio_write(data);
 }
@@ -3672,7 +3672,7 @@
 avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set)
 {
 	int val = 0;
-	
+
 	if (set) {
 		if (v->mode & VIDEO_SOUND_LANG2)   /* SAP */
 			val = 0x01;
@@ -3807,7 +3807,7 @@
 
 /*
  * Dariusz Kowalewski <darekk@automex.pl>
- * sound control for FlyVideo 2000S (with tda9874 decoder) 
+ * sound control for FlyVideo 2000S (with tda9874 decoder)
  * based on pvbt878p9b_audio() - this is not tested, please fix!!!
  */
 static void
@@ -3990,13 +3990,13 @@
  * ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>]
  *
  * The IVC120G security card has 4 i2c controlled TDA8540 matrix
- * swichers to provide 16 channels to MUX0. The TDA8540's have 
- * 4 indepedant outputs and as such the IVC120G also has the 
- * optional "Monitor Out" bus. This allows the card to be looking 
+ * swichers to provide 16 channels to MUX0. The TDA8540's have
+ * 4 indepedant outputs and as such the IVC120G also has the
+ * optional "Monitor Out" bus. This allows the card to be looking
  * at one input while the monitor is looking at another.
  *
  * Since I've couldn't be bothered figuring out how to add an
- * independant muxsel for the monitor bus, I've just set it to 
+ * independant muxsel for the monitor bus, I've just set it to
  * whatever the card is looking at.
  *
  *  OUT0 of the TDA8540's is connected to MUX0         (0x03)
@@ -4021,12 +4021,12 @@
 static void ivc120_muxsel(struct bttv *btv, unsigned int input)
 {
 	// Simple maths
-	int key = input % 4;    
+	int key = input % 4;
 	int matrix = input / 4;
-	
+
 	dprintk("bttv%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
 		btv->c.nr, input, matrix, key);
-	
+
 	// Handles the input selection on the TDA8540's
 	bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
 		      ((matrix == 3) ? (key | key << 2) : 0x00), 1);
@@ -4036,17 +4036,17 @@
 		      ((matrix == 1) ? (key | key << 2) : 0x00), 1);
 	bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
 		      ((matrix == 2) ? (key | key << 2) : 0x00), 1);
-	
+
 	// Handles the output enables on the TDA8540's
 	bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
 		      ((matrix == 3) ? 0x03 : 0x00), 1);  // 13 - 16
 	bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
 		      ((matrix == 0) ? 0x03 : 0x00), 1);  // 1-4
 	bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
-		      ((matrix == 1) ? 0x03 : 0x00), 1);  // 5-8 
+		      ((matrix == 1) ? 0x03 : 0x00), 1);  // 5-8
 	bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
 		      ((matrix == 2) ? 0x03 : 0x00), 1);  // 9-12
-	
+
 	// Selects MUX0 for input on the 878
 	btaor((0)<<5, ~(3<<5), BT848_IFORM);
 }
@@ -4153,7 +4153,7 @@
 
 #if 0
 	/* print which chipset we have */
-	while ((dev = pci_get_class(PCI_CLASS_BRIDGE_HOST << 8,dev)))
+	while ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8,dev)))
 		printk(KERN_INFO "bttv: Host bridge is %s\n",pci_name(dev));
 #endif
 
@@ -4172,8 +4172,8 @@
 	if (UNSET != latency)
 		printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency);
 
-	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
-				     PCI_DEVICE_ID_INTEL_82441, dev))) {
+	while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_82441, dev))) {
                 unsigned char b;
 		pci_read_config_byte(dev, 0x53, &b);
 		if (bttv_debug)
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/bttv-driver.c	2004-10-28 22:25:59 -07:00
@@ -1,26 +1,26 @@
 
 /*
-    $Id: bttv-driver.c,v 1.22 2004/10/12 07:33:22 kraxel Exp $
+    $Id: bttv-driver.c,v 1.23 2004/10/13 10:39:00 kraxel Exp $
 
     bttv - Bt848 frame grabber driver
-    
+
     Copyright (C) 1996,97,98 Ralph  Metzler <rjkm@thp.uni-koeln.de>
                            & Marcus Metzler <mocm@thp.uni-koeln.de>
     (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
-    
+
     some v4l2 code lines are taken from Justin's bttv2 driver which is
     (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
-    
+
     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.
@@ -195,7 +195,7 @@
 		.sheight        = 576,
 		.totalwidth     = 1135,
 		.adelay         = 0x7f,
-		.bdelay         = 0x72, 
+		.bdelay         = 0x72,
 		.iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
 		.scaledtwidth   = 1135,
 		.hdelayx1       = 186,
@@ -683,20 +683,20 @@
 /* ----------------------------------------------------------------------- */
 /* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC          */
 
-/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C 
-   PLL_X = Reference pre-divider (0=1, 1=2) 
+/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
+   PLL_X = Reference pre-divider (0=1, 1=2)
    PLL_C = Post divider (0=6, 1=4)
-   PLL_I = Integer input 
-   PLL_F = Fractional input 
-   
-   F_input = 28.636363 MHz: 
+   PLL_I = Integer input
+   PLL_F = Fractional input
+
+   F_input = 28.636363 MHz:
    PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
 */
 
 static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
 {
         unsigned char fl, fh, fi;
-        
+
         /* prevent overflows */
         fin/=4;
         fout/=4;
@@ -747,7 +747,7 @@
 		/*  Let other people run while the PLL stabilizes */
 		vprintk(".");
 		msleep(10);
-		
+
                 if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
 			btwrite(0,BT848_DSTATUS);
                 } else {
@@ -810,7 +810,7 @@
 static void bt848_hue(struct bttv *btv, int hue)
 {
 	int value;
-	
+
 	btv->hue = hue;
 
 	/* -128 to 127 */
@@ -821,9 +821,9 @@
 static void bt848_contrast(struct bttv *btv, int cont)
 {
 	int value,hibit;
-	
+
 	btv->contrast = cont;
-	
+
 	/* 0-511 */
 	value = (cont  >> 7);
 	hibit = (value >> 6) & 4;
@@ -835,7 +835,7 @@
 static void bt848_sat(struct bttv *btv, int color)
 {
 	int val_u,val_v,hibits;
-	
+
 	btv->saturation = color;
 
 	/* 0-511 for the color */
@@ -977,7 +977,7 @@
 set_input(struct bttv *btv, unsigned int input)
 {
 	unsigned long flags;
-	
+
 	btv->input = input;
 	if (irq_iswitch) {
 		spin_lock_irqsave(&btv->s_lock,flags);
@@ -1022,7 +1022,7 @@
 static void init_bt848(struct bttv *btv)
 {
 	int val;
-	
+
 	if (bttv_tvcards[btv->c.type].no_video) {
 		/* very basic init only */
 		init_irqreg(btv);
@@ -1039,7 +1039,7 @@
                 BT848_GPIO_DMA_CTL_PLTP1_16|
                 BT848_GPIO_DMA_CTL_PLTP23_16|
                 BT848_GPIO_DMA_CTL_GPINTC|
-                BT848_GPIO_DMA_CTL_GPINTI, 
+                BT848_GPIO_DMA_CTL_GPINTI,
                 BT848_GPIO_DMA_CTL);
 
 	val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
@@ -1091,7 +1091,7 @@
 {
 	struct video_audio va;
 	int i;
-	
+
 	for (i = 0; i < BTTV_CTLS; i++)
 		if (bttv_ctls[i].id == c->id)
 			break;
@@ -1361,7 +1361,7 @@
 {
 	int redo_dma_risc = 0;
 	int rc;
-	
+
 	/* check settings */
 	if (NULL == fmt)
 		return -EINVAL;
@@ -1381,7 +1381,7 @@
 		if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
 			return -EINVAL;
 	}
-	
+
 	/* alloc + fill struct bttv_buffer (if changed) */
 	if (buf->vb.width != width || buf->vb.height != height ||
 	    buf->vb.field != field ||
@@ -1417,7 +1417,7 @@
 buffer_setup(void *priv, unsigned int *count, unsigned int *size)
 {
 	struct bttv_fh *fh = priv;
-	
+
 	*size = fh->fmt->depth*fh->width*fh->height >> 3;
 	if (0 == *count)
 		*count = gbuffers;
@@ -1503,7 +1503,7 @@
 	case VIDIOCGTUNER:
 	{
 		struct video_tuner *v = arg;
-		
+
 		if (UNSET == bttv_tvcards[btv->c.type].tuner)
 			return -EINVAL;
 		if (v->tuner) /* Only tuner 0 */
@@ -1532,7 +1532,7 @@
 		up(&btv->lock);
 		return 0;
 	}
-	
+
         case VIDIOCGCHAN:
         {
                 struct video_channel *v = arg;
@@ -1574,7 +1574,6 @@
 			return 0;
 		}
 
-		bttv_call_i2c_clients(btv,cmd,v);
 		btv->tvnorm = v->norm;
 		set_input(btv,v->channel);
 		up(&btv->lock);
@@ -1615,7 +1614,7 @@
 		/* card specific hooks */
 		if (btv->audio_hook)
 			btv->audio_hook(btv,v,1);
-		
+
 		up(&btv->lock);
 		return 0;
 	}
@@ -1625,7 +1624,7 @@
 	{
 		struct v4l2_standard *e = arg;
 		unsigned int index = e->index;
-		
+
 		if (index >= BTTV_TVNORMS)
 			return -EINVAL;
 		v4l2_video_std_construct(e, bttv_tvnorms[e->index].v4l2_id,
@@ -1659,7 +1658,7 @@
 	case VIDIOC_QUERYSTD:
 	{
 		v4l2_std_id *id = arg;
-		
+
 		if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
 			*id = V4L2_STD_625_50;
 		else
@@ -1671,7 +1670,7 @@
 	{
 		struct v4l2_input *i = arg;
 		unsigned int n;
-		
+
 		n = i->index;
 		if (n >= bttv_tvcards[btv->c.type].video_inputs)
 			return -EINVAL;
@@ -1708,7 +1707,7 @@
 	case VIDIOC_S_INPUT:
 	{
 		unsigned int *i = arg;
-		
+
 		if (*i > bttv_tvcards[btv->c.type].video_inputs)
 			return -EINVAL;
 		down(&btv->lock);
@@ -1716,7 +1715,7 @@
 		up(&btv->lock);
 		return 0;
 	}
-	
+
 	case VIDIOC_G_TUNER:
 	{
 		struct v4l2_tuner *t = arg;
@@ -1812,7 +1811,7 @@
 
 	default:
 		return -ENOIOCTLCMD;
-	
+
 	}
 	return 0;
 }
@@ -1907,25 +1906,25 @@
 	default:
 		BUG();
 	}
-	
+
 	down(&fh->cap.lock);
 	if (fh->ov.clips)
 		kfree(fh->ov.clips);
 	fh->ov.clips    = clips;
 	fh->ov.nclips   = n;
-	
+
 	fh->ov.w        = win->w;
 	fh->ov.field    = win->field;
 	fh->ov.setup_ok = 1;
 	btv->init.ov.w.width   = win->w.width;
 	btv->init.ov.w.height  = win->w.height;
 	btv->init.ov.field     = win->field;
-	
+
 	/* update overlay if needed */
 	retval = 0;
 	if (check_btres(fh, RESOURCE_OVERLAY)) {
 		struct bttv_buffer *new;
-		
+
 		new = videobuf_alloc(sizeof(*new));
 		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
 		retval = bttv_switch_overlay(btv,fh,new);
@@ -1939,7 +1938,7 @@
 static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
 {
 	struct videobuf_queue* q = NULL;
-	
+
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		q = &fh->cap;
@@ -1956,7 +1955,7 @@
 static int bttv_resource(struct bttv_fh *fh)
 {
 	int res = 0;
-	
+
 	switch (fh->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		res = RESOURCE_VIDEO;
@@ -2065,7 +2064,7 @@
 			(f->fmt.pix.width * fmt->depth) >> 3;
 		f->fmt.pix.sizeimage =
 			f->fmt.pix.height * f->fmt.pix.bytesperline;
-		
+
 		return 0;
 	}
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
@@ -2083,7 +2082,7 @@
 		      struct v4l2_format *f)
 {
 	int retval;
-	
+
 	switch (f->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	{
@@ -2096,7 +2095,7 @@
 		if (0 != retval)
 			return retval;
 		fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-		
+
 		/* update our state informations */
 		down(&fh->cap.lock);
 		fh->fmt              = fmt;
@@ -2108,7 +2107,7 @@
 		btv->init.width      = f->fmt.pix.width;
 		btv->init.height     = f->fmt.pix.height;
 		up(&fh->cap.lock);
-		
+
 		return 0;
 	}
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
@@ -2218,7 +2217,7 @@
 	{
 		struct video_picture *pic = arg;
 		const struct bttv_format *fmt;
-		
+
 		fmt = format_by_palette(pic->palette);
 		if (NULL == fmt)
 			return -EINVAL;
@@ -2365,7 +2364,7 @@
 
 		if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))
 			return -EBUSY;
-		
+
 		down(&fh->cap.lock);
 		if (*on) {
 			fh->ov.tvnorm = btv->tvnorm;
@@ -2419,7 +2418,7 @@
 		if (buf->vb.state == STATE_QUEUED ||
 		    buf->vb.state == STATE_ACTIVE)
 			goto fh_unlock_and_return;
-		
+
 		field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)
 			? V4L2_FIELD_INTERLACED
 			: V4L2_FIELD_BOTTOM;
@@ -2543,7 +2542,7 @@
 			V4L2_CAP_VIDEO_OVERLAY |
 			V4L2_CAP_VBI_CAPTURE |
 			V4L2_CAP_TUNER |
-			V4L2_CAP_READWRITE | 
+			V4L2_CAP_READWRITE |
 			V4L2_CAP_STREAMING;
 		return 0;
 	}
@@ -2628,7 +2627,7 @@
 	{
 		struct v4l2_framebuffer *fb = arg;
 		const struct bttv_format *fmt;
-		
+
 		if(!capable(CAP_SYS_ADMIN) &&
 		   !capable(CAP_SYS_RAWIO))
 			return -EPERM;
@@ -2657,7 +2656,7 @@
 			btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
 		else
 			btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
-		
+
 		retval = 0;
 		fh->ovfmt = fmt;
 		btv->init.ovfmt = fmt;
@@ -2675,7 +2674,7 @@
 
 			if (check_btres(fh, RESOURCE_OVERLAY)) {
 				struct bttv_buffer *new;
-		
+
 				new = videobuf_alloc(sizeof(*new));
 				bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);
 				retval = bttv_switch_overlay(btv,fh,new);
@@ -2795,7 +2794,7 @@
 	}
 #endif
 
-	
+
 	case VIDIOC_ENUMSTD:
 	case VIDIOC_G_STD:
 	case VIDIOC_S_STD:
@@ -2908,7 +2907,7 @@
 		up(&fh->cap.lock);
 		buf = (struct bttv_buffer*)fh->cap.read_buf;
 	}
-	
+
 	poll_wait(file, &buf->vb.done, wait);
 	if (buf->vb.state == STATE_DONE ||
 	    buf->vb.state == STATE_ERROR)
@@ -2985,7 +2984,7 @@
 	/* turn off overlay */
 	if (check_btres(fh, RESOURCE_OVERLAY))
 		bttv_switch_overlay(btv,fh,NULL);
-	
+
 	/* stop video capture */
 	if (check_btres(fh, RESOURCE_VIDEO)) {
 		videobuf_streamoff(file->private_data,&fh->cap);
@@ -3140,7 +3139,7 @@
         case VIDIOCSTUNER:
 		/* nothing to do */
 		return 0;
-	
+
 	case BTTV_VERSION:
         case VIDIOCGFREQ:
         case VIDIOCSFREQ:
@@ -3206,7 +3205,7 @@
 static void bttv_print_irqbits(u32 print, u32 mark)
 {
 	unsigned int i;
-	
+
 	printk("bits:");
 	for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
 		if (print & (1 << i))
@@ -3373,7 +3372,7 @@
 	struct bttv_buffer *ovbi;
 	struct bttv_buffer *item;
 	unsigned long flags;
-	
+
 	if (bttv_verbose) {
 		printk(KERN_INFO "bttv%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
 		       btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
@@ -3383,7 +3382,7 @@
 	}
 
 	spin_lock_irqsave(&btv->s_lock,flags);
-	
+
 	/* deactivate stuff */
 	memset(&new,0,sizeof(new));
 	old  = btv->curr;
@@ -3412,7 +3411,7 @@
 		item->vb.state = STATE_ERROR;
 		wake_up(&item->vb.done);
 	}
-	
+
 	btv->errors++;
 	spin_unlock_irqrestore(&btv->s_lock,flags);
 }
@@ -3466,7 +3465,7 @@
 		spin_unlock(&btv->s_lock);
 		return;
 	}
-	
+
 	/* switch over */
 	old = btv->curr;
 	btv->curr = new;
@@ -3558,7 +3557,7 @@
 			printk("\n");
 		}
 
-		if (astat&BT848_INT_VSYNC) 
+		if (astat&BT848_INT_VSYNC)
                         btv->field_count++;
 
 		if (astat & BT848_INT_GPINT) {
@@ -3603,7 +3602,7 @@
 		count++;
 		if (count > 4) {
 			btwrite(0, BT848_INT_MASK);
-			printk(KERN_ERR 
+			printk(KERN_ERR
 			       "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr);
 			bttv_print_irqbits(stat,astat);
 			printk("]\n");
@@ -3711,9 +3710,9 @@
 {
 #if defined(__powerpc__)
         unsigned int cmd;
-	
+
         pci_read_config_dword(dev, PCI_COMMAND, &cmd);
-        cmd = (cmd | PCI_COMMAND_MEMORY ); 
+        cmd = (cmd | PCI_COMMAND_MEMORY );
         pci_write_config_dword(dev, PCI_COMMAND, cmd);
 #endif
 }
@@ -3750,14 +3749,14 @@
 	init_timer(&btv->timeout);
 	btv->timeout.function = bttv_irq_timeout;
 	btv->timeout.data     = (unsigned long)btv;
-	
+
         btv->i2c_rc = -1;
         btv->tuner_type  = UNSET;
         btv->pinnacle_id = UNSET;
 	btv->new_input   = UNSET;
 	btv->gpioirq     = 1;
 	btv->has_radio=radio[btv->c.nr];
-	
+
 	/* pci stuff (init, get irq/mmio, ... */
 	btv->c.pci = dev;
         btv->id  = dev->device;
@@ -3794,7 +3793,7 @@
         printk("irq: %d, latency: %d, mmio: 0x%lx\n",
 	       btv->c.pci->irq, lat, pci_resource_start(dev,0));
 	schedule();
-	
+
 	btv->bt848_mmio=ioremap(pci_resource_start(dev,0), 0x1000);
 	if (NULL == ioremap(pci_resource_start(dev,0), 0x1000)) {
 		printk("bttv%d: ioremap() failed\n", btv->c.nr);
@@ -3829,7 +3828,7 @@
 	btv->opt_vcr_hack   = vcr_hack;
 	btv->opt_whitecrush_upper  = whitecrush_upper;
 	btv->opt_whitecrush_lower  = whitecrush_lower;
-	
+
 	/* fill struct bttv with some useful defaults */
 	btv->init.btv         = btv;
 	btv->init.ov.w.width  = 320;
@@ -3886,7 +3885,7 @@
 
  fail2:
         free_irq(btv->c.pci->irq,btv);
-	
+
  fail1:
 	if (btv->bt848_mmio)
 		iounmap(btv->bt848_mmio);
@@ -3915,7 +3914,7 @@
 	btv->shutdown=1;
 	wake_up(&btv->gpioq);
 	bttv_sub_del_devices(&btv->c);
-	
+
         /* unregister i2c_bus + input */
 	fini_bttv_i2c(btv);
 
diff -Nru a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
--- a/drivers/media/video/bttv-gpio.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/bttv-gpio.c	2004-10-28 22:25:59 -07:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-gpio.c,v 1.3 2004/09/15 16:15:24 kraxel Exp $
+    $Id: bttv-gpio.c,v 1.4 2004/10/13 10:39:00 kraxel Exp $
 
     bttv-gpio.c  --  gpio sub drivers
 
@@ -24,7 +24,7 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-    
+
 */
 
 #include <linux/module.h>
@@ -63,6 +63,7 @@
 int bttv_sub_add_device(struct bttv_core *core, char *name)
 {
 	struct bttv_sub_device *sub;
+	int err;
 
 	sub = kmalloc(sizeof(*sub),GFP_KERNEL);
 	if (NULL == sub)
@@ -76,9 +77,13 @@
 	snprintf(sub->dev.bus_id,sizeof(sub->dev.bus_id),"%s%d",
 		 name, core->nr);
 
+	err = device_register(&sub->dev);
+	if (0 != err) {
+		kfree(sub);
+		return err;
+	}
 	printk("bttv%d: add subdevice \"%s\"\n", core->nr, sub->dev.bus_id);
 	list_add_tail(&sub->list,&core->subs);
-	device_register(&sub->dev);
 	return 0;
 }
 
@@ -129,8 +134,7 @@
 {
 	sub->drv.bus = &bttv_sub_bus_type;
 	snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted);
-	driver_register(&sub->drv);
-	return 0;
+	return driver_register(&sub->drv);
 }
 EXPORT_SYMBOL(bttv_sub_register);
 
diff -Nru a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
--- a/drivers/media/video/bttv-i2c.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/media/video/bttv-i2c.c	2004-10-28 22:25:56 -07:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-i2c.c,v 1.10 2004/10/06 17:30:51 kraxel Exp $
+    $Id: bttv-i2c.c,v 1.11 2004/10/13 10:39:00 kraxel Exp $
 
     bttv-i2c.c  --  all the i2c code is here
 
@@ -22,7 +22,7 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-    
+
 */
 
 #include <linux/module.h>
@@ -83,7 +83,7 @@
 {
 	struct bttv *btv = (struct bttv*)data;
 	int state;
-	
+
 	state = btread(BT848_I2C) & 0x02 ? 1 : 0;
 	return state;
 }
@@ -126,7 +126,7 @@
 /* ----------------------------------------------------------------------- */
 /* I2C functions - hardware i2c                                            */
 
-static int algo_control(struct i2c_adapter *adapter, 
+static int algo_control(struct i2c_adapter *adapter,
 			unsigned int cmd, unsigned long arg)
 {
 	return 0;
@@ -142,7 +142,7 @@
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int rc = 0;
-	
+
 	add_wait_queue(&btv->i2c_queue, &wait);
 	if (0 == btv->i2c_done)
 		msleep_interruptible(20);
@@ -352,7 +352,7 @@
 
 
 /* read I2C */
-int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) 
+int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
 {
         unsigned char buffer = 0;
 
@@ -397,7 +397,7 @@
 void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
 {
 	int i;
-        
+
 	if (bttv_I2CWrite(btv, addr, 0, -1, 0)<0) {
 		printk(KERN_WARNING "bttv: readee error\n");
 		return;
diff -Nru a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c
--- a/drivers/media/video/bttv-if.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/video/bttv-if.c	2004-10-28 22:25:57 -07:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-if.c,v 1.2 2004/09/15 16:15:24 kraxel Exp $
+    $Id: bttv-if.c,v 1.3 2004/10/13 10:39:00 kraxel Exp $
 
     bttv-if.c  --  old gpio interface to other kernel modules
                    don't use in new code, will go away in 2.7
@@ -24,7 +24,7 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-    
+
 */
 
 #include <linux/module.h>
@@ -82,7 +82,7 @@
 	if (card >= bttv_num) {
 		return -EINVAL;
 	}
-	
+
 	btv = &bttvs[card];
 	gpio_inout(mask,data);
 	if (bttv_gpio)
@@ -93,7 +93,7 @@
 int bttv_read_gpio(unsigned int card, unsigned long *data)
 {
 	struct bttv *btv;
-	
+
 	if (card >= bttv_num) {
 		return -EINVAL;
 	}
@@ -104,7 +104,7 @@
 		return -ENODEV;
 	}
 
-/* prior setting BT848_GPIO_REG_INP is (probably) not needed 
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
    because we set direct input on init */
 	*data = gpio_read();
 	return 0;
@@ -113,14 +113,14 @@
 int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
 {
 	struct bttv *btv;
-	
+
 	if (card >= bttv_num) {
 		return -EINVAL;
 	}
 
 	btv = &bttvs[card];
 
-/* prior setting BT848_GPIO_REG_INP is (probably) not needed 
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
    because direct input is set on init */
 	gpio_bits(mask,data);
 	if (bttv_gpio)
diff -Nru a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c
--- a/drivers/media/video/bttv-risc.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/bttv-risc.c	2004-10-28 22:25:58 -07:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-risc.c,v 1.8 2004/10/06 17:30:51 kraxel Exp $
+    $Id: bttv-risc.c,v 1.9 2004/10/13 10:39:00 kraxel Exp $
 
     bttv-risc.c  --  interfaces to other kernel modules
 
@@ -240,7 +240,7 @@
 	/* skip list for window clipping */
 	if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
 		return -ENOMEM;
-	
+
 	/* estimate risc mem: worst case is (clip+1) * lines instructions
 	   + sync + jump (all 2 dwords) */
 	instructions  = (ov->nclips + 1) *
@@ -293,7 +293,7 @@
 				ra = addr + (fmt->depth>>3)*start;
 			else
 				ra = 0;
-				
+
 			if (0 == start)
 				ri |= BT848_RISC_SOL;
 			if (ov->w.width == end)
@@ -413,7 +413,7 @@
 		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
 		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
 		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
-	
+
 	cmd = BT848_RISC_JUMP;
 	if (btv->loop_irq) {
 		cmd |= BT848_RISC_IRQ;
@@ -426,7 +426,7 @@
 		del_timer(&btv->timeout);
 	}
         btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
-	
+
 	btaor(capctl, ~0x0f, BT848_CAP_CTL);
 	if (capctl) {
 		if (btv->dma_on)
@@ -447,7 +447,7 @@
 bttv_risc_init_main(struct bttv *btv)
 {
 	int rc;
-	
+
 	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
 		return rc;
 	dprintk(KERN_DEBUG "bttv%d: risc main @ %08Lx\n",
@@ -616,7 +616,7 @@
 
 		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
 			      V4L2_FIELD_HAS_BOTH(buf->vb.field),buf->tvnorm);
-		
+
 		switch (buf->vb.field) {
 		case V4L2_FIELD_TOP:
 			bttv_risc_packed(btv,&buf->top,buf->vb.dma.sglist,
diff -Nru a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
--- a/drivers/media/video/bttv-vbi.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/bttv-vbi.c	2004-10-28 22:25:58 -07:00
@@ -1,21 +1,21 @@
 /*
-    $Id: bttv-vbi.c,v 1.5 2004/10/06 17:30:51 kraxel Exp $
+    $Id: bttv-vbi.c,v 1.6 2004/10/13 10:39:00 kraxel Exp $
 
     bttv - Bt848 frame grabber driver
     vbi interface
-    
+
     (c) 2002 Gerd Knorr <kraxel@bytesex.org>
-    
+
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     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.
@@ -83,7 +83,7 @@
 	struct bttv *btv = fh->btv;
 	struct bttv_buffer *buf = (struct bttv_buffer*)vb;
 	int rc;
-	
+
 	buf->vb.size = fh->lines * 2 * 2048;
 	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
 		return -EINVAL;
@@ -112,7 +112,7 @@
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 	struct bttv_buffer *buf = (struct bttv_buffer*)vb;
-	
+
 	dprintk("queue %p\n",vb);
 	buf->vb.state = STATE_QUEUED;
 	list_add_tail(&buf->vb.queue,&btv->vcapture);
@@ -127,7 +127,7 @@
 	struct bttv_fh *fh = priv;
 	struct bttv *btv = fh->btv;
 	struct bttv_buffer *buf = (struct bttv_buffer*)vb;
-	
+
 	dprintk("free %p\n",vb);
 	bttv_dma_free(fh->btv,buf);
 }
diff -Nru a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
--- a/drivers/media/video/bttv.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/video/bttv.h	2004-10-28 22:25:57 -07:00
@@ -1,5 +1,5 @@
 /*
- * $Id: bttv.h,v 1.9 2004/09/15 16:15:24 kraxel Exp $
+ * $Id: bttv.h,v 1.10 2004/10/13 10:39:00 kraxel Exp $
  *
  *  bttv - Bt848 frame grabber driver
  *
@@ -26,9 +26,9 @@
 #define BTTV_HAUPPAUGE     0x02
 #define BTTV_STB           0x03
 #define BTTV_INTEL         0x04
-#define BTTV_DIAMOND       0x05 
-#define BTTV_AVERMEDIA     0x06 
-#define BTTV_MATRIX_VISION 0x07 
+#define BTTV_DIAMOND       0x05
+#define BTTV_AVERMEDIA     0x06
+#define BTTV_MATRIX_VISION 0x07
 #define BTTV_FLYVIDEO      0x08
 #define BTTV_TURBOTV       0x09
 #define BTTV_HAUPPAUGE878  0x0a
@@ -245,7 +245,7 @@
 
 /* returns card type + card ID (for bt878-based ones)
    for possible values see lines below beginning with #define BTTV_UNKNOWN
-   returns negative value if error occurred 
+   returns negative value if error occurred
 */
 extern int bttv_get_cardinfo(unsigned int card, int *type,
 			     unsigned int *cardid);
@@ -268,18 +268,18 @@
 
 /* sets GPDATA register to new value:
   (data & mask) | (current_GPDATA_value & ~mask)
-  returns negative value if error occurred 
+  returns negative value if error occurred
 */
 extern int bttv_write_gpio(unsigned int card,
 			   unsigned long mask, unsigned long data);
 
-/* returns pointer to task queue which can be used as parameter to 
+/* returns pointer to task queue which can be used as parameter to
    interruptible_sleep_on
    in interrupt handler if BT848_INT_GPINT bit is set - this queue is activated
-   (wake_up_interruptible) and following call to the function bttv_read_gpio 
+   (wake_up_interruptible) and following call to the function bttv_read_gpio
    should return new value of GPDATA,
    returns NULL value if error occurred or queue is not available
-   WARNING: because there is no buffer for GPIO data, one MUST 
+   WARNING: because there is no buffer for GPIO data, one MUST
    process data ASAP
 */
 extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card);
diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
--- a/drivers/media/video/bttvp.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/video/bttvp.h	2004-10-28 22:25:57 -07:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttvp.h,v 1.10 2004/10/06 17:30:51 kraxel Exp $
+    $Id: bttvp.h,v 1.11 2004/10/13 10:39:00 kraxel Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -145,7 +145,7 @@
 struct bttv_fh {
 	struct bttv              *btv;
 	int resources;
-#ifdef VIDIOC_G_PRIORITY 
+#ifdef VIDIOC_G_PRIORITY
 	enum v4l2_priority       prio;
 #endif
 	enum v4l2_buf_type       type;
@@ -334,10 +334,10 @@
         struct semaphore lock;
 	int resources;
         struct semaphore reslock;
-#ifdef VIDIOC_G_PRIORITY 
+#ifdef VIDIOC_G_PRIORITY
 	struct v4l2_prio_state prio;
 #endif
-	
+
 	/* video state */
 	unsigned int input;
 	unsigned int audio;
diff -Nru a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
--- a/drivers/media/video/cpia.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/cpia.c	2004-10-28 22:25:58 -07:00
@@ -3781,7 +3781,7 @@
 
 	pos = (unsigned long)(cam->frame_buf);
 	while (size > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
 			up(&cam->busy_lock);
 			return -EAGAIN;
@@ -4047,22 +4047,13 @@
 	proc_cpia_create();
 #endif
 
-#ifdef CONFIG_KMOD
-#ifdef CONFIG_VIDEO_CPIA_PP_MODULE
-	request_module("cpia_pp");
-#endif
-
-#ifdef CONFIG_VIDEO_CPIA_USB_MODULE
-	request_module("cpia_usb");
-#endif
-#endif	/* CONFIG_KMOD */
-
 #ifdef CONFIG_VIDEO_CPIA_PP
 	cpia_pp_init();
 #endif
 #ifdef CONFIG_VIDEO_CPIA_USB
 	cpia_usb_init();
 #endif
+
 	return 0;
 }
 
diff -Nru a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
--- a/drivers/media/video/cx88/Makefile	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/video/cx88/Makefile	2004-10-28 22:25:57 -07:00
@@ -5,4 +5,4 @@
 obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
 obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
 
-EXTRA_CFLAGS = -I $(src)/.. -I $(srctree)/drivers/media/dvb/dvb-core
+EXTRA_CFLAGS = -I$(src)/.. -I$(srctree)/drivers/media/dvb/dvb-core
diff -Nru a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
--- a/drivers/media/video/ir-kbd-gpio.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/ir-kbd-gpio.c	2004-10-28 22:25:59 -07:00
@@ -1,5 +1,6 @@
-
 /*
+ * $Id: ir-kbd-gpio.c,v 1.10 2004/09/15 16:15:24 kraxel Exp $
+ *
  * Copyright (c) 2003 Gerd Knorr
  * Copyright (c) 2003 Pavel Machek
  *
@@ -45,7 +46,7 @@
 	[ 60 ] = KEY_KP9,
 
 	[ 48 ] = KEY_EJECTCD,     // Unmarked on my controller
-	[  0 ] = KEY_POWER, 
+	[  0 ] = KEY_POWER,
 	[ 18 ] = BTN_LEFT,        // DISPLAY/L
 	[ 50 ] = BTN_RIGHT,       // LOOP/R
 	[ 10 ] = KEY_MUTE,
@@ -74,6 +75,45 @@
 	[  1 ] = KEY_BLUE,        // unmarked
 };
 
+/* Matt Jesson <dvb@jesson.eclipse.co.uk */
+static IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
+	[ 0x28 ] = KEY_KP0,         //'0' / 'enter'
+	[ 0x22 ] = KEY_KP1,         //'1'
+	[ 0x12 ] = KEY_KP2,         //'2' / 'up arrow'
+	[ 0x32 ] = KEY_KP3,         //'3'
+	[ 0x24 ] = KEY_KP4,         //'4' / 'left arrow'
+	[ 0x14 ] = KEY_KP5,         //'5'
+	[ 0x34 ] = KEY_KP6,         //'6' / 'right arrow'
+	[ 0x26 ] = KEY_KP7,         //'7'
+	[ 0x16 ] = KEY_KP8,         //'8' / 'down arrow'
+	[ 0x36 ] = KEY_KP9,         //'9'
+
+	[ 0x20 ] = KEY_LIST,        // 'source'
+	[ 0x10 ] = KEY_TEXT,        // 'teletext'
+	[ 0x00 ] = KEY_POWER,       // 'power'
+	[ 0x04 ] = KEY_AUDIO,       // 'audio'
+	[ 0x06 ] = KEY_ZOOM,        // 'full screen'
+	[ 0x18 ] = KEY_VIDEO,       // 'display'
+	[ 0x38 ] = KEY_SEARCH,      // 'loop'
+	[ 0x08 ] = KEY_INFO,        // 'preview'
+	[ 0x2a ] = KEY_REWIND,      // 'backward <<'
+	[ 0x1a ] = KEY_FASTFORWARD, // 'forward >>'
+	[ 0x3a ] = KEY_RECORD,      // 'capture'
+	[ 0x0a ] = KEY_MUTE,        // 'mute'
+	[ 0x2c ] = KEY_RECORD,      // 'record'
+	[ 0x1c ] = KEY_PAUSE,       // 'pause'
+	[ 0x3c ] = KEY_STOP,        // 'stop'
+	[ 0x0c ] = KEY_PLAY,        // 'play'
+	[ 0x2e ] = KEY_RED,         // 'red'
+	[ 0x01 ] = KEY_BLUE,        // 'blue' / 'cancel'
+	[ 0x0e ] = KEY_YELLOW,      // 'yellow' / 'ok'
+	[ 0x21 ] = KEY_GREEN,       // 'green'
+	[ 0x11 ] = KEY_CHANNELDOWN, // 'channel -'
+	[ 0x31 ] = KEY_CHANNELUP,   // 'channel +'
+	[ 0x1e ] = KEY_VOLUMEDOWN,  // 'volume -'
+	[ 0x3e ] = KEY_VOLUMEUP,    // 'volume +'
+};
+
 static IR_KEYTAB_TYPE winfast_codes[IR_KEYTAB_SIZE] = {
 	[  5 ] = KEY_KP1,
 	[  6 ] = KEY_KP2,
@@ -130,7 +170,7 @@
 	[  6 ] = KEY_KP7,
 	[ 10 ] = KEY_KP8,
 	[ 18 ] = KEY_KP9,
-	
+
 	[  3 ] = KEY_TUNER,       // TV/FM
 	[  7 ] = KEY_SEARCH,      // scan
 	[ 28 ] = KEY_ZOOM,        // full screen
@@ -140,7 +180,7 @@
 	[ 20 ] = KEY_CHANNELDOWN,
 	[ 22 ] = KEY_CHANNELUP,
 	[ 24 ] = KEY_MUTE,
-	
+
 	[  0 ] = KEY_LIST,        // source
 	[ 19 ] = KEY_INFO,        // loop
 	[ 16 ] = KEY_LAST,        // +100
@@ -151,6 +191,47 @@
 	[ 15 ] = KEY_STOP,         // freeze
 };
 
+/* Attila Kondoros <attila.kondoros@chello.hu> */
+static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
+
+	[  1 ] = KEY_KP1,
+	[  2 ] = KEY_KP2,
+	[  3 ] = KEY_KP3,
+	[  4 ] = KEY_KP4,
+	[  5 ] = KEY_KP5,
+	[  6 ] = KEY_KP6,
+	[  7 ] = KEY_KP7,
+	[  8 ] = KEY_KP8,
+	[  9 ] = KEY_KP9,
+	[  0 ] = KEY_KP0,
+	[ 23 ] = KEY_LAST,        // +100
+	[ 10 ] = KEY_LIST,        // recall
+
+
+	[ 28 ] = KEY_TUNER,       // TV/FM
+	[ 21 ] = KEY_SEARCH,      // scan
+	[ 18 ] = KEY_POWER,       // power
+	[ 31 ] = KEY_VOLUMEDOWN,  // vol up
+	[ 27 ] = KEY_VOLUMEUP,    // vol down
+	[ 30 ] = KEY_CHANNELDOWN, // chn up
+	[ 26 ] = KEY_CHANNELUP,   // chn down
+
+	[ 17 ] = KEY_VIDEO,       // video
+	[ 15 ] = KEY_ZOOM,        // full screen
+	[ 19 ] = KEY_MUTE,        // mute/unmute
+	[ 16 ] = KEY_TEXT,        // min
+
+	[ 13 ] = KEY_STOP,        // freeze
+	[ 14 ] = KEY_RECORD,      // record
+	[ 29 ] = KEY_PLAYPAUSE,   // stop
+	[ 25 ] = KEY_PLAY,        // play
+
+	[ 22 ] = KEY_GOTO,        // osd
+	[ 20 ] = KEY_REFRESH,     // default
+	[ 12 ] = KEY_KPPLUS,      // fine tune >>>>
+	[ 24 ] = KEY_KPMINUS      // fine tune <<<<
+};
+
 /* ---------------------------------------------------------------------- */
 
 struct IR {
@@ -202,7 +283,7 @@
 			return;
 		ir->last_gpio = gpio;
 	}
-	
+
 	/* extract data */
 	data = ir_extract_bits(gpio, ir->mask_keycode);
 	dprintk(DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
@@ -284,6 +365,14 @@
 		ir->polling      = 50; // ms
 		break;
 
+	case BTTV_AVDVBT_761:
+	/* case BTTV_AVDVBT_771: */
+		ir_codes         = ir_codes_avermedia_dvbt;
+		ir->mask_keycode = 0x0f00c0;
+		ir->mask_keydown = 0x000020;
+		ir->polling      = 50; // ms
+		break;
+
 	case BTTV_PXELVWPLTVPAK:
 		ir_codes         = ir_codes_pixelview;
 		ir->mask_keycode = 0x003e00;
@@ -308,6 +397,12 @@
 		ir->mask_keycode = 0x0008e000;
 		ir->mask_keydown = 0x00200000;
 		break;
+	case BTTV_APAC_VIEWCOMP:
+		ir_codes         = ir_codes_apac_viewcomp;
+		ir->mask_keycode = 0x001f00;
+		ir->mask_keyup   = 0x008000;
+		ir->polling      = 50; // ms
+		break;
 	}
 	if (NULL == ir_codes) {
 		kfree(ir);
@@ -317,7 +412,7 @@
 	/* init hardware-specific stuff */
 	bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0);
 	ir->sub = sub;
-	
+
 	/* init input device */
 	snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
 		 sub->core->type);
diff -Nru a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
--- a/drivers/media/video/ir-kbd-i2c.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/media/video/ir-kbd-i2c.c	2004-10-28 22:25:56 -07:00
@@ -1,4 +1,6 @@
 /*
+ * $Id: ir-kbd-i2c.c,v 1.8 2004/09/15 16:15:24 kraxel Exp $
+ *
  * keyboard input driver for i2c IR remote controls
  *
  * Copyright (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
@@ -156,7 +158,7 @@
 static inline int reverse(int data, int bits)
 {
 	int i,c;
-	
+
 	for (c=0,i=0; i<bits; i++) {
 		c |= (((data & (1<<i)) ? 1:0)) << (bits-1-i);
 	}
@@ -193,7 +195,7 @@
 static int get_key_pixelview(struct IR *ir, u32 *ir_key, u32 *ir_raw)
 {
         unsigned char b;
-	
+
 	/* poll IR chip */
 	if (1 != i2c_master_recv(&ir->c,&b,1)) {
 		dprintk(1,"read error\n");
@@ -207,7 +209,7 @@
 static int get_key_pv951(struct IR *ir, u32 *ir_key, u32 *ir_raw)
 {
         unsigned char b;
-	
+
 	/* poll IR chip */
 	if (1 != i2c_master_recv(&ir->c,&b,1)) {
 		dprintk(1,"read error\n");
@@ -218,7 +220,7 @@
 	if (b==0xaa)
 		return 0;
 	dprintk(2,"key %02x\n", b);
-	
+
 	*ir_key = b;
 	*ir_raw = b;
 	return 1;
@@ -227,26 +229,26 @@
 static int get_key_knc1(struct IR *ir, u32 *ir_key, u32 *ir_raw)
 {
 	unsigned char b;
-	
+
 	/* poll IR chip */
 	if (1 != i2c_master_recv(&ir->c,&b,1)) {
 		dprintk(1,"read error\n");
 		return -EIO;
 	}
-	
+
 	/* it seems that 0xFE indicates that a button is still hold
 	   down, while 0xFF indicates that no button is hold
 	   down. 0xFE sequences are sometimes interrupted by 0xFF */
-	
+
 	dprintk(2,"key %02x\n", b);
-	
+
 	if (b == 0xFF)
 		return 0;
-	
+
 	if (b == 0xFE)
 		/* keep old data */
 		return 1;
-	
+
 	*ir_key = b;
 	*ir_raw = b;
 	return 1;
@@ -323,7 +325,7 @@
         .detach_client  = ir_detach,
 };
 
-static struct i2c_client client_template = 
+static struct i2c_client client_template =
 {
         I2C_DEVNAME("unset"),
         .driver = &driver
@@ -336,7 +338,7 @@
 	char *name;
 	int ir_type;
         struct IR *ir;
-		
+
         if (NULL == (ir = kmalloc(sizeof(struct IR),GFP_KERNEL)))
                 return -ENOMEM;
 	memset(ir,0,sizeof(*ir));
@@ -400,14 +402,14 @@
 	input_register_device(&ir->input);
 	printk(DEVNAME ": %s detected at %s [%s]\n",
 	       ir->input.name,ir->input.phys,adap->name);
-	       
+
 	/* start polling via eventd */
 	INIT_WORK(&ir->work, ir_work, ir);
 	init_timer(&ir->timer);
 	ir->timer.function = ir_timer;
 	ir->timer.data     = (unsigned long)ir;
 	schedule_work(&ir->work);
-	
+
 	return 0;
 }
 
@@ -430,16 +432,16 @@
 
 static int ir_probe(struct i2c_adapter *adap)
 {
-	
+
 	/* The external IR receiver is at i2c address 0x34 (0x35 for
 	   reads).  Future Hauppauge cards will have an internal
 	   receiver at 0x30 (0x31 for reads).  In theory, both can be
 	   fitted, and Hauppauge suggest an external overrides an
-	   internal. 
-	   
-	   That's why we probe 0x1a (~0x34) first. CB 
+	   internal.
+
+	   That's why we probe 0x1a (~0x34) first. CB
 	*/
-	
+
 	static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
 	static const int probe_saa7134[] = { 0x7a, -1};
 	const int *probe = NULL;
@@ -478,13 +480,12 @@
 MODULE_DESCRIPTION("input driver for i2c IR remote controls");
 MODULE_LICENSE("GPL");
 
-static int ir_init(void)
+static int __init ir_init(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void ir_fini(void)
+static void __exit ir_fini(void)
 {
 	i2c_del_driver(&driver);
 }
diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c
--- a/drivers/media/video/meye.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/meye.c	2004-10-28 22:25:58 -07:00
@@ -1188,7 +1188,7 @@
 	pos = (unsigned long)meye.grab_fbuffer;
 
 	while (size > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
 			up(&meye.lock);
 			return -EAGAIN;
diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
--- a/drivers/media/video/msp3400.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/msp3400.c	2004-10-28 22:25:58 -07:00
@@ -47,6 +47,8 @@
 #include <linux/videodev.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/kthread.h>
+#include <linux/suspend.h>
 #include <asm/semaphore.h>
 #include <asm/pgtable.h>
 
@@ -54,54 +56,53 @@
 #include <media/id.h>
 #include "msp3400.h"
 
+#define OPMODE_AUTO    -1
+#define OPMODE_MANUAL   0
+#define OPMODE_SIMPLE   1   /* use short programming (>= msp3410 only) */
+#define OPMODE_SIMPLER  2   /* use shorter programming (>= msp34xxG)   */
+
 /* insmod parameters */
+static int opmode   = OPMODE_AUTO;
 static int debug    = 0;    /* debug output */
 static int once     = 0;    /* no continous stereo monitoring */
 static int amsound  = 0;    /* hard-wire AM sound at 6.5 Hz (france),
-			      the autoscan seems work well only with FM... */
-static int simple   = -1;   /* use short programming (>= msp3410 only) */
+			       the autoscan seems work well only with FM... */
+static int standard = 1;    /* Override auto detect of audio standard, if needed. */
 static int dolby    = 0;
 
-#define DFP_COUNT 0x41
-static const int bl_dfp[] = {
-	0x00, 0x01, 0x02, 0x03,  0x06, 0x08, 0x09, 0x0a,
-	0x0b, 0x0d, 0x0e, 0x10
-};
+static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual
+					(msp34xxg only) 0x00a0-0x03c0 */
 
 struct msp3400c {
 	int rev1,rev2;
-	
-	int simple;
+
+	int opmode;
 	int mode;
 	int norm;
-	int stereo;
 	int nicam_on;
 	int acb;
 	int main, second;	/* sound carrier */
 	int input;
+	int source;             /* see msp34xxg_set_source */
+
+	/* v4l2 */
+	int audmode;
+	int rxsubchans;
 
 	int muted;
 	int volume, balance;
 	int bass, treble;
 
-	/* shadow register set */
-	int dfp_regs[DFP_COUNT];
-
 	/* thread */
-	pid_t                tpid;
-	struct completion    texit;
+	struct task_struct   *kthread;
 	wait_queue_head_t    wq;
-
-	int                  active:1;
 	int                  restart:1;
-	int                  rmmod:1;
-
-	int                  watch_stereo;
-	struct timer_list    wake_stereo;
+	int                  watch_stereo:1;
 };
 
 #define HAVE_NICAM(msp)   (((msp->rev2>>8) & 0xff) != 00)
 #define HAVE_SIMPLE(msp)  ((msp->rev1      & 0xff) >= 'D'-'@')
+#define HAVE_SIMPLER(msp) ((msp->rev1      & 0xff) >= 'G'-'@')
 #define HAVE_RADIO(msp)   ((msp->rev1      & 0xff) >= 'G'-'@')
 
 #define VIDEO_MODE_RADIO 16      /* norm magic for radio mode */
@@ -111,11 +112,21 @@
 #define dprintk      if (debug >= 1) printk
 #define d2printk     if (debug >= 2) printk
 
-MODULE_PARM(once,"i");
-MODULE_PARM(debug,"i");
-MODULE_PARM(simple,"i");
-MODULE_PARM(amsound,"i");
-MODULE_PARM(dolby,"i");
+/* read-only */
+module_param(opmode,           int, 0444);
+
+/* read-write */
+module_param(once,             int, 0644);
+module_param(debug,            int, 0644);
+module_param(stereo_threshold, int, 0644);
+module_param(standard,         int, 0644);
+module_param(amsound,          int, 0644);
+module_param(dolby,            int, 0644);
+
+MODULE_PARM_DESC(once, "No continuous stereo monitoring");
+MODULE_PARM_DESC(debug, "Enable debug messages");
+MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect");
+MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan");
 
 MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
 MODULE_AUTHOR("Gerd Knorr");
@@ -141,10 +152,6 @@
 /* ----------------------------------------------------------------------- */
 /* functions for talking to the MSP3400C Sound processor                   */
 
-#ifndef I2C_M_IGNORE_NAK
-# define I2C_M_IGNORE_NAK 0x1000
-#endif
-
 static int msp3400c_reset(struct i2c_client *client)
 {
 	/* reset and read revision code */
@@ -160,14 +167,14 @@
 		{ client->addr, 0,        3, write },
 		{ client->addr, I2C_M_RD, 2, read  },
 	};
-	
+
 	if ( (1 != i2c_transfer(client->adapter,&reset[0],1)) ||
 	     (1 != i2c_transfer(client->adapter,&reset[1],1)) ||
 	     (2 != i2c_transfer(client->adapter,test,2)) ) {
 		printk(KERN_ERR "msp3400: chip reset failed\n");
 		return -1;
         }
-	return 0; 
+	return 0;
 }
 
 static int
@@ -198,7 +205,7 @@
 		msp3400c_reset(client);
 		return -1;
 	}
-        return read[0] << 8 | read[1];
+	return read[0] << 8 | read[1];
 }
 
 static int
@@ -303,15 +310,15 @@
 
 static struct CARRIER_DETECT carrier_detect_main[] = {
 	/* main carrier */
-	{ MSP_CARRIER(4.5),        "4.5   NTSC"                   }, 
-	{ MSP_CARRIER(5.5),        "5.5   PAL B/G"                }, 
+	{ MSP_CARRIER(4.5),        "4.5   NTSC"                   },
+	{ MSP_CARRIER(5.5),        "5.5   PAL B/G"                },
 	{ MSP_CARRIER(6.0),        "6.0   PAL I"                  },
 	{ MSP_CARRIER(6.5),        "6.5   PAL D/K + SAT + SECAM"  }
 };
 
 static struct CARRIER_DETECT carrier_detect_55[] = {
 	/* PAL B/G */
-	{ MSP_CARRIER(5.7421875),  "5.742 PAL B/G FM-stereo"     }, 
+	{ MSP_CARRIER(5.7421875),  "5.742 PAL B/G FM-stereo"     },
 	{ MSP_CARRIER(5.85),       "5.85  PAL B/G NICAM"         }
 };
 
@@ -329,16 +336,6 @@
 
 /* ----------------------------------------------------------------------- */
 
-#define SCART_MASK    0
-#define SCART_IN1     1
-#define SCART_IN2     2
-#define SCART_IN1_DA  3
-#define SCART_IN2_DA  4
-#define SCART_IN3     5
-#define SCART_IN4     6
-#define SCART_MONO    7
-#define SCART_MUTE    8
-
 static int scarts[3][9] = {
   /* MASK    IN1     IN2     IN1_DA  IN2_DA  IN3     IN4     MONO    MUTE   */
   {  0x0320, 0x0000, 0x0200, -1,     -1,     0x0300, 0x0020, 0x0100, 0x0320 },
@@ -392,8 +389,8 @@
 		muted ? "on" : "off", volume, balance, val>>8, bal);
 	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
 	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones  */
-	/* scart - on/off only */
-	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007, val ? 0x4000 : 0);
+	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007,
+		       muted ? 0x01 : (val | 0x01));
 	msp3400c_write(client,I2C_MSP3400C_DFP, 0x0001, bal << 8);
 }
 
@@ -417,31 +414,32 @@
 {
 	struct msp3400c *msp = i2c_get_clientdata(client);
 	int i;
-	
+
 	dprintk(KERN_DEBUG "msp3400: setmode: %d\n",type);
-	msp->mode   = type;
-	msp->stereo = VIDEO_SOUND_MONO;
+	msp->mode       = type;
+	msp->audmode    = V4L2_TUNER_MODE_MONO;
+	msp->rxsubchans = V4L2_TUNER_SUB_MONO;
 
 	msp3400c_write(client,I2C_MSP3400C_DEM, 0x00bb,          /* ad_cv */
 		       msp_init_data[type].ad_cv);
-    
+
 	for (i = 5; i >= 0; i--)                                   /* fir 1 */
 		msp3400c_write(client,I2C_MSP3400C_DEM, 0x0001,
 			       msp_init_data[type].fir1[i]);
-    
+
 	msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */
 	msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0040);
 	msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0000);
 	for (i = 5; i >= 0; i--)
 		msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005,
 			       msp_init_data[type].fir2[i]);
-    
+
 	msp3400c_write(client,I2C_MSP3400C_DEM, 0x0083,     /* MODE_REG */
 		       msp_init_data[type].mode_reg);
-    
+
 	msp3400c_setcarrier(client, msp_init_data[type].cdo1,
 			    msp_init_data[type].cdo2);
-    
+
 	msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
 
 	if (dolby) {
@@ -470,51 +468,67 @@
 	}
 }
 
+static int best_audio_mode(int rxsubchans)
+{
+	if (rxsubchans & V4L2_TUNER_SUB_STEREO)
+		return V4L2_TUNER_MODE_STEREO;
+	if (rxsubchans & V4L2_TUNER_SUB_LANG1)
+		return V4L2_TUNER_MODE_LANG1;
+	if (rxsubchans & V4L2_TUNER_SUB_LANG2)
+		return V4L2_TUNER_MODE_LANG2;
+	return V4L2_TUNER_MODE_MONO;
+}
+
 /* turn on/off nicam + stereo */
-static void msp3400c_setstereo(struct i2c_client *client, int mode)
+static void msp3400c_set_audmode(struct i2c_client *client, int audmode)
 {
 	static char *strmode[16] = {
 #if __GNUC__ >= 3
-		[ 0 ... 15 ]           = "invalid",
+		[ 0 ... 15 ]               = "invalid",
 #endif
-		[ VIDEO_SOUND_MONO ]   = "mono",
-		[ VIDEO_SOUND_STEREO ] = "stereo",
-		[ VIDEO_SOUND_LANG1  ] = "lang1",
-		[ VIDEO_SOUND_LANG2  ] = "lang2",
+		[ V4L2_TUNER_MODE_MONO   ] = "mono",
+		[ V4L2_TUNER_MODE_STEREO ] = "stereo",
+		[ V4L2_TUNER_MODE_LANG1  ] = "lang1",
+		[ V4L2_TUNER_MODE_LANG2  ] = "lang2",
 	};
 	struct msp3400c *msp = i2c_get_clientdata(client);
 	int nicam=0; /* channel source: FM/AM or nicam */
 	int src=0;
 
+	BUG_ON(msp->opmode == OPMODE_SIMPLER);
+	msp->audmode = audmode;
+
 	/* switch demodulator */
 	switch (msp->mode) {
 	case MSP_MODE_FM_TERRA:
-		dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n",strmode[mode]);
+		dprintk(KERN_DEBUG "msp3400: FM setstereo: %s\n",
+			strmode[audmode]);
 		msp3400c_setcarrier(client,msp->second,msp->main);
-		switch (mode) {
-		case VIDEO_SOUND_STEREO:
+		switch (audmode) {
+		case V4L2_TUNER_MODE_STEREO:
 			msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001);
 			break;
-		case VIDEO_SOUND_MONO:
-		case VIDEO_SOUND_LANG1:
-		case VIDEO_SOUND_LANG2:
+		case V4L2_TUNER_MODE_MONO:
+		case V4L2_TUNER_MODE_LANG1:
+		case V4L2_TUNER_MODE_LANG2:
 			msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000);
 			break;
 		}
 		break;
 	case MSP_MODE_FM_SAT:
-		dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n",strmode[mode]);
-		switch (mode) {
-		case VIDEO_SOUND_MONO:
+		dprintk(KERN_DEBUG "msp3400: SAT setstereo: %s\n",
+			strmode[audmode]);
+		switch (audmode) {
+		case V4L2_TUNER_MODE_MONO:
 			msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
 			break;
-		case VIDEO_SOUND_STEREO:
+		case V4L2_TUNER_MODE_STEREO:
 			msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
 			break;
-		case VIDEO_SOUND_LANG1:
+		case V4L2_TUNER_MODE_LANG1:
 			msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
 			break;
-		case VIDEO_SOUND_LANG2:
+		case V4L2_TUNER_MODE_LANG2:
 			msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
 			break;
 		}
@@ -522,21 +536,25 @@
 	case MSP_MODE_FM_NICAM1:
 	case MSP_MODE_FM_NICAM2:
 	case MSP_MODE_AM_NICAM:
-		dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n",strmode[mode]);
+		dprintk(KERN_DEBUG "msp3400: NICAM setstereo: %s\n",
+			strmode[audmode]);
 		msp3400c_setcarrier(client,msp->second,msp->main);
 		if (msp->nicam_on)
 			nicam=0x0100;
 		break;
 	case MSP_MODE_BTSC:
-		dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n",strmode[mode]);
+		dprintk(KERN_DEBUG "msp3400: BTSC setstereo: %s\n",
+			strmode[audmode]);
 		nicam=0x0300;
 		break;
 	case MSP_MODE_EXTERN:
-		dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n",strmode[mode]);
+		dprintk(KERN_DEBUG "msp3400: extern setstereo: %s\n",
+			strmode[audmode]);
 		nicam = 0x0200;
 		break;
 	case MSP_MODE_FM_RADIO:
-		dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n",strmode[mode]);
+		dprintk(KERN_DEBUG "msp3400: FM-Radio setstereo: %s\n",
+			strmode[audmode]);
 		break;
 	default:
 		dprintk(KERN_DEBUG "msp3400: mono setstereo\n");
@@ -544,15 +562,15 @@
 	}
 
 	/* switch audio */
-	switch (mode) {
-	case VIDEO_SOUND_STEREO:
+	switch (audmode) {
+	case V4L2_TUNER_MODE_STEREO:
 		src = 0x0020 | nicam;
-#if 0 
+#if 0
 		/* spatial effect */
 		msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000);
 #endif
 		break;
-	case VIDEO_SOUND_MONO:
+	case V4L2_TUNER_MODE_MONO:
 		if (msp->mode == MSP_MODE_AM_NICAM) {
 			dprintk("msp3400: switching to AM mono\n");
 			/* AM mono decoding is handled by tuner, not MSP chip */
@@ -561,10 +579,10 @@
 			src = 0x0200;
 			break;
 		}
-	case VIDEO_SOUND_LANG1:
+	case V4L2_TUNER_MODE_LANG1:
 		src = 0x0000 | nicam;
 		break;
-	case VIDEO_SOUND_LANG2:
+	case V4L2_TUNER_MODE_LANG2:
 		src = 0x0010 | nicam;
 		break;
 	}
@@ -608,19 +626,6 @@
 	}
 }
 
-static void
-msp3400c_restore_dfp(struct i2c_client *client)
-{
-	struct msp3400c *msp = i2c_get_clientdata(client);
-	int i;
-
-	for (i = 0; i < DFP_COUNT; i++) {
-		if (-1 == msp->dfp_regs[i])
-			continue;
-		msp3400c_write(client,I2C_MSP3400C_DFP, i, msp->dfp_regs[i]);
-	}
-}
-
 /* ----------------------------------------------------------------------- */
 
 struct REGISTER_DUMP {
@@ -641,8 +646,8 @@
 {
 	struct msp3400c *msp = i2c_get_clientdata(client);
 	int val;
-	int newstereo = msp->stereo;
-	int newnicam  = msp->nicam_on;
+	int rxsubchans = msp->rxsubchans;
+	int newnicam   = msp->nicam_on;
 	int update = 0;
 
 	switch (msp->mode) {
@@ -653,11 +658,11 @@
 		dprintk(KERN_DEBUG
 			"msp34xx: stereo detect register: %d\n",val);
 		if (val > 4096) {
-			newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO;
+			rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
 		} else if (val < -4096) {
-			newstereo = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+			rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
 		} else {
-			newstereo = VIDEO_SOUND_MONO;
+			rxsubchans = V4L2_TUNER_SUB_MONO;
 		}
 		newnicam = 0;
 		break;
@@ -674,27 +679,27 @@
 			switch ((val & 0x1e) >> 1)  {
 			case 0:
 			case 8:
-				newstereo = VIDEO_SOUND_STEREO;
+				rxsubchans = V4L2_TUNER_SUB_STEREO;
 				break;
 			case 1:
 			case 9:
-				newstereo = VIDEO_SOUND_MONO
-					| VIDEO_SOUND_LANG1;
+				rxsubchans = V4L2_TUNER_SUB_MONO
+					| V4L2_TUNER_SUB_LANG1;
 				break;
 			case 2:
 			case 10:
-				newstereo = VIDEO_SOUND_MONO
-					| VIDEO_SOUND_LANG1
-					| VIDEO_SOUND_LANG2;
+				rxsubchans = V4L2_TUNER_SUB_MONO
+					| V4L2_TUNER_SUB_LANG1
+					| V4L2_TUNER_SUB_LANG2;
 				break;
 			default:
-				newstereo = VIDEO_SOUND_MONO;
+				rxsubchans = V4L2_TUNER_SUB_MONO;
 				break;
 			}
 			newnicam=1;
 		} else {
 			newnicam = 0;
-			newstereo = VIDEO_SOUND_MONO;
+			rxsubchans = V4L2_TUNER_SUB_MONO;
 		}
 		break;
 	case MSP_MODE_BTSC:
@@ -707,16 +712,16 @@
 			(val & 0x0040) ? "stereo" : "mono",
 			(val & 0x0080) ? ", nicam 2nd mono" : "",
 			(val & 0x0100) ? ", bilingual/SAP"  : "");
-		newstereo = VIDEO_SOUND_MONO;
-		if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO;
-		if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1;
+		rxsubchans = V4L2_TUNER_SUB_MONO;
+		if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO;
+		if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1;
 		break;
 	}
-	if (newstereo != msp->stereo) {
+	if (rxsubchans != msp->rxsubchans) {
 		update = 1;
-		dprintk(KERN_DEBUG "msp34xx: watch: stereo %d => %d\n",
-			msp->stereo,newstereo);
-		msp->stereo   = newstereo;
+		dprintk(KERN_DEBUG "msp34xx: watch: rxsubchans %d => %d\n",
+			msp->rxsubchans,rxsubchans);
+		msp->rxsubchans = rxsubchans;
 	}
 	if (newnicam != msp->nicam_on) {
 		update = 1;
@@ -737,22 +742,24 @@
 	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(&msp->wq, &wait);
-	if (!msp->rmmod) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (timeout < 0)
+	if (!kthread_should_stop()) {
+		if (timeout < 0) {
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
-		else
-			schedule_timeout(timeout);
+		} else {
+#if 0
+			/* hmm, that one doesn't return on wakeup ... */
+			msleep_interruptible(timeout);
+#else
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(msecs_to_jiffies(timeout));
+#endif
+		}
 	}
+	if (current->flags & PF_FREEZE)
+		refrigerator(PF_FREEZE);
 	remove_wait_queue(&msp->wq, &wait);
-	return msp->rmmod || signal_pending(current);
-}
-
-static void msp3400c_stereo_wake(unsigned long data)
-{
-	struct msp3400c *msp = (struct msp3400c*)data;   /* XXX alpha ??? */
-
-	wake_up_interruptible(&msp->wq);
+	return msp->restart;
 }
 
 /* stereo/multilang monitoring */
@@ -760,53 +767,31 @@
 {
 	struct msp3400c *msp = i2c_get_clientdata(client);
 
-	if (autodetect_stereo(client)) {
-		if (msp->stereo & VIDEO_SOUND_STEREO)
-			msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
-		else if (msp->stereo & VIDEO_SOUND_LANG1)
-			msp3400c_setstereo(client,VIDEO_SOUND_LANG1);
-		else if (msp->stereo & VIDEO_SOUND_LANG2)
-			msp3400c_setstereo(client,VIDEO_SOUND_LANG2);
-		else
-			msp3400c_setstereo(client,VIDEO_SOUND_MONO);
-	}
+	if (autodetect_stereo(client))
+		msp3400c_set_audmode(client,best_audio_mode(msp->rxsubchans));
 	if (once)
 		msp->watch_stereo = 0;
-	if (msp->watch_stereo)
-		mod_timer(&msp->wake_stereo, jiffies+5*HZ);
 }
 
 static int msp3400c_thread(void *data)
 {
 	struct i2c_client *client = data;
 	struct msp3400c *msp = i2c_get_clientdata(client);
-	
 	struct CARRIER_DETECT *cd;
 	int count, max1,max2,val1,val2, val,this;
-	
-	daemonize("msp3400");
-	allow_signal(SIGTERM);
-	printk("msp3400: daemon started\n");
 
+	printk("msp3400: kthread started\n");
 	for (;;) {
 		d2printk("msp3400: thread: sleep\n");
-		if (msp34xx_sleep(msp,-1))
-			goto done;
-
+		msp34xx_sleep(msp,-1);
 		d2printk("msp3400: thread: wakeup\n");
-		msp->active = 1;
 
-		if (msp->watch_stereo) {
-			watch_stereo(client);
-			msp->active = 0;
-			continue;
-		}
-
-		/* some time for the tuner to sync */
-		if (msp34xx_sleep(msp,HZ/5))
-			goto done;
-		
 	restart:
+		dprintk("msp3410: thread: restart scan\n");
+		msp->restart = 0;
+		if (kthread_should_stop())
+			break;
+
 		if (VIDEO_MODE_RADIO == msp->norm ||
 		    MSP_MODE_EXTERN  == msp->mode) {
 			/* no carrier scan, just unmute */
@@ -815,14 +800,18 @@
 					   msp->volume, msp->balance);
 			continue;
 		}
-		msp->restart = 0;
+
+		/* mute */
 		msp3400c_setvolume(client, msp->muted, 0, 0);
 		msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
 		val1 = val2 = 0;
 		max1 = max2 = -1;
-		del_timer(&msp->wake_stereo);
 		msp->watch_stereo = 0;
 
+		/* some time for the tuner to sync */
+		if (msp34xx_sleep(msp,200))
+			goto restart;
+
 		/* carrier detect pass #1 -- main carrier */
 		cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main);
 
@@ -835,12 +824,8 @@
 
 		for (this = 0; this < count; this++) {
 			msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
-
-			if (msp34xx_sleep(msp,HZ/10))
-				goto done;
-			if (msp->restart)
-				msp->restart = 0;
-
+			if (msp34xx_sleep(msp,100))
+				goto restart;
 			val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
 			if (val > 32767)
 				val -= 65536;
@@ -848,14 +833,16 @@
 				val1 = val, max1 = this;
 			dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name);
 		}
-	
+
 		/* carrier detect pass #2 -- second (stereo) carrier */
 		switch (max1) {
 		case 1: /* 5.5 */
-			cd = carrier_detect_55; count = CARRIER_COUNT(carrier_detect_55);
+			cd = carrier_detect_55;
+			count = CARRIER_COUNT(carrier_detect_55);
 			break;
 		case 3: /* 6.5 */
-			cd = carrier_detect_65; count = CARRIER_COUNT(carrier_detect_65);
+			cd = carrier_detect_65;
+			count = CARRIER_COUNT(carrier_detect_65);
 			break;
 		case 0: /* 4.5 */
 		case 2: /* 6.0 */
@@ -863,19 +850,15 @@
 			cd = NULL; count = 0;
 			break;
 		}
-		
+
 		if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
 			/* autodetect doesn't work well with AM ... */
 			cd = NULL; count = 0; max2 = 0;
 		}
 		for (this = 0; this < count; this++) {
 			msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
-
-			if (msp34xx_sleep(msp,HZ/10))
-				goto done;
-			if (msp->restart)
+			if (msp34xx_sleep(msp,100))
 				goto restart;
-
 			val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
 			if (val > 32767)
 				val -= 65536;
@@ -893,7 +876,7 @@
 				msp->second = carrier_detect_55[max2].cdo;
 				msp3400c_setmode(client, MSP_MODE_FM_TERRA);
 				msp->nicam_on = 0;
-				msp3400c_setstereo(client, VIDEO_SOUND_MONO);
+				msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO);
 				msp->watch_stereo = 1;
 			} else if (max2 == 1 && HAVE_NICAM(msp)) {
 				/* B/G NICAM */
@@ -920,7 +903,7 @@
 				msp->second = carrier_detect_65[max2].cdo;
 				msp3400c_setmode(client, MSP_MODE_FM_TERRA);
 				msp->nicam_on = 0;
-				msp3400c_setstereo(client, VIDEO_SOUND_MONO);
+				msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO);
 				msp->watch_stereo = 1;
 			} else if (max2 == 0 &&
 				   msp->norm == VIDEO_MODE_SECAM) {
@@ -928,7 +911,7 @@
 				msp->second = carrier_detect_65[max2].cdo;
 				msp3400c_setmode(client, MSP_MODE_AM_NICAM);
 				msp->nicam_on = 0;
-				msp3400c_setstereo(client, VIDEO_SOUND_MONO);
+				msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO);
 				msp3400c_setcarrier(client, msp->second, msp->main);
 				/* volume prescale for SCART (AM mono input) */
 				msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);
@@ -951,29 +934,26 @@
 			msp3400c_setmode(client, MSP_MODE_FM_TERRA);
 			msp->nicam_on = 0;
 			msp3400c_setcarrier(client, msp->second, msp->main);
-			msp->stereo = VIDEO_SOUND_MONO;
-			msp3400c_setstereo(client, VIDEO_SOUND_MONO);
+			msp->rxsubchans = V4L2_TUNER_SUB_MONO;
+			msp3400c_set_audmode(client, V4L2_TUNER_MODE_MONO);
 			break;
 		}
 
-		/* unmute + restore dfp registers */
+		/* unmute */
 		msp3400c_setvolume(client, msp->muted,
 				   msp->volume, msp->balance);
-		msp3400c_restore_dfp(client);
-
-		if (msp->watch_stereo)
-			mod_timer(&msp->wake_stereo, jiffies+5*HZ);
-
 		if (debug)
 			msp3400c_print_mode(msp);
-		
-		msp->active = 0;
-	}
 
-done:
-	msp->active = 0;
+		/* monitor tv audio mode */
+		while (msp->watch_stereo) {
+			if (msp34xx_sleep(msp,5000))
+				goto restart;
+			watch_stereo(client);
+		}
+	}
 	dprintk(KERN_DEBUG "msp3400: thread: exit\n");
-        complete_and_exit(&msp->texit, 0);
+	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1006,36 +986,68 @@
 	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2  SAT ADR" },
 	{     -1, 0, 0, NULL }, /* EOF */
 };
- 
+
+static inline const char *msp34xx_standard_mode_name(int mode)
+{
+	int i;
+	for (i = 0; modelist[i].name != NULL; i++)
+		if (modelist[i].retval == mode)
+			return modelist[i].name;
+	return "unknown";
+}
+
+static int msp34xx_modus(int norm)
+{
+	switch (norm) {
+	case VIDEO_MODE_PAL:
+		return 0x1003;
+	case VIDEO_MODE_NTSC:  /* BTSC */
+		return 0x2003;
+	case VIDEO_MODE_SECAM:
+		return 0x0003;
+	case VIDEO_MODE_RADIO:
+		return 0x0003;
+	case VIDEO_MODE_AUTO:
+		return 0x2003;
+	default:
+		return 0x0003;
+	}
+}
+
+static int msp34xx_standard(int norm)
+{
+	switch (norm) {
+	case VIDEO_MODE_PAL:
+		return 1;
+	case VIDEO_MODE_NTSC:  /* BTSC */
+		return 0x0020;
+	case VIDEO_MODE_SECAM:
+		return 1;
+	case VIDEO_MODE_RADIO:
+		return 0x0040;
+	default:
+		return 1;
+	}
+}
+
 static int msp3410d_thread(void *data)
 {
 	struct i2c_client *client = data;
 	struct msp3400c *msp = i2c_get_clientdata(client);
 	int mode,val,i,std;
-    
-	daemonize("msp3410 [auto]");
-	allow_signal(SIGTERM);
-	printk("msp3410: daemon started\n");
 
+	printk("msp3410: daemon started\n");
 	for (;;) {
 		d2printk(KERN_DEBUG "msp3410: thread: sleep\n");
-		if (msp34xx_sleep(msp,-1))
-			goto done;
-
+		msp34xx_sleep(msp,-1);
 		d2printk(KERN_DEBUG "msp3410: thread: wakeup\n");
-		msp->active = 1;
-
-		if (msp->watch_stereo) {
-			watch_stereo(client);
-			msp->active = 0;
-			continue;
-		}
-	
-		/* some time for the tuner to sync */
-		if (msp34xx_sleep(msp,HZ/5))
-			goto done;
 
 	restart:
+		dprintk("msp3410: thread: restart scan\n");
+		msp->restart = 0;
+		if (kthread_should_stop())
+			break;
+
 		if (msp->mode == MSP_MODE_EXTERN) {
 			/* no carrier scan needed, just unmute */
 			dprintk(KERN_DEBUG "msp3410: thread: no carrier scan\n");
@@ -1043,47 +1055,24 @@
 					   msp->volume, msp->balance);
 			continue;
 		}
-		msp->restart = 0;
-		del_timer(&msp->wake_stereo);
-		msp->watch_stereo = 0;
 
 		/* put into sane state (and mute) */
 		msp3400c_reset(client);
 
+		/* some time for the tuner to sync */
+		if (msp34xx_sleep(msp,200))
+			goto restart;
+
 		/* start autodetect */
-		switch (msp->norm) {
-		case VIDEO_MODE_PAL:
-			mode = 0x1003;
-			std  = 1;
-			break;
-		case VIDEO_MODE_NTSC:  /* BTSC */
-			mode = 0x2003;
-			std  = 0x0020;
-			break;
-		case VIDEO_MODE_SECAM: 
-			mode = 0x0003;
-			std  = 1;
-			break;
-		case VIDEO_MODE_RADIO:
-			mode = 0x0003;
-			std  = 0x0040;
-			break;
-		default:
-			mode = 0x0003;
-			std  = 1;
-			break;
-		}
+		mode = msp34xx_modus(msp->norm);
+		std  = msp34xx_standard(msp->norm);
 		msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode);
 		msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std);
+		msp->watch_stereo = 0;
 
-		if (debug) {
-			int i;
-			for (i = 0; modelist[i].name != NULL; i++)
-				if (modelist[i].retval == std)
-					break;
+		if (debug)
 			printk(KERN_DEBUG "msp3410: setting mode: %s (0x%04x)\n",
-			       modelist[i].name ? modelist[i].name : "unknown",std);
-		}
+			       msp34xx_standard_mode_name(std) ,std);
 
 		if (std != 1) {
 			/* programmed some specific mode */
@@ -1091,9 +1080,7 @@
 		} else {
 			/* triggered autodetect */
 			for (;;) {
-				if (msp34xx_sleep(msp,HZ/10))
-					goto done;
-				if (msp->restart)
+				if (msp34xx_sleep(msp,100))
 					goto restart;
 
 				/* check results */
@@ -1135,29 +1122,30 @@
 			else
 				msp->mode = MSP_MODE_FM_NICAM2;
 			/* just turn on stereo */
-			msp->stereo = VIDEO_SOUND_STEREO;
+			msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
 			msp->nicam_on = 1;
 			msp->watch_stereo = 1;
-			msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
+			msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO);
 			break;
-		case 0x0009:			
+		case 0x0009:
 			msp->mode = MSP_MODE_AM_NICAM;
-			msp->stereo = VIDEO_SOUND_MONO;
+			msp->rxsubchans = V4L2_TUNER_SUB_MONO;
 			msp->nicam_on = 1;
-			msp3400c_setstereo(client,VIDEO_SOUND_MONO);
+			msp3400c_set_audmode(client,V4L2_TUNER_MODE_MONO);
 			msp->watch_stereo = 1;
 			break;
 		case 0x0020: /* BTSC */
 			/* just turn on stereo */
-			msp->mode   = MSP_MODE_BTSC;
-			msp->stereo = VIDEO_SOUND_STEREO;
+			msp->mode = MSP_MODE_BTSC;
+			msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
 			msp->nicam_on = 0;
 			msp->watch_stereo = 1;
-			msp3400c_setstereo(client,VIDEO_SOUND_STEREO);
+			msp3400c_set_audmode(client,V4L2_TUNER_MODE_STEREO);
 			break;
 		case 0x0040: /* FM radio */
 			msp->mode   = MSP_MODE_FM_RADIO;
-			msp->stereo = VIDEO_SOUND_STEREO;
+			msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
+			msp->audmode = V4L2_TUNER_MODE_STEREO;
 			msp->nicam_on = 0;
 			msp->watch_stereo = 0;
 			/* not needed in theory if HAVE_RADIO(), but
@@ -1183,50 +1171,276 @@
 		case 0x0004:
 		case 0x0005:
 			msp->mode   = MSP_MODE_FM_TERRA;
-			msp->stereo = VIDEO_SOUND_MONO;
+			msp->rxsubchans = V4L2_TUNER_SUB_MONO;
+			msp->audmode = V4L2_TUNER_MODE_MONO;
 			msp->nicam_on = 0;
 			msp->watch_stereo = 1;
 			break;
 		}
-		
-		/* unmute + restore dfp registers */
+
+		/* unmute, restore misc registers */
 		msp3400c_setbass(client, msp->bass);
 		msp3400c_settreble(client, msp->treble);
 		msp3400c_setvolume(client, msp->muted,
 				    msp->volume, msp->balance);
-		msp3400c_restore_dfp(client);
-
-		if (msp->watch_stereo)
-			mod_timer(&msp->wake_stereo, jiffies+HZ);
+		msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb);
 
-		msp->active = 0;
+		/* monitor tv audio mode */
+		while (msp->watch_stereo) {
+			if (msp34xx_sleep(msp,5000))
+				goto restart;
+			watch_stereo(client);
+		}
 	}
-
-done:
-	msp->active = 0;
 	dprintk(KERN_DEBUG "msp3410: thread: exit\n");
-        complete_and_exit(&msp->texit, 0);
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
+/* msp34xxG + (simpler no-thread)                                          */
+/* this one uses both automatic standard detection and automatic sound     */
+/* select which are available in the newer G versions                      */
+/* struct msp: only norm, acb and source are really used in this mode      */
+
+static void msp34xxg_set_source(struct i2c_client *client, int source);
+
+/* (re-)initialize the msp34xxg, according to the current norm in msp->norm
+ * return 0 if it worked, -1 if it failed
+ */
+static int msp34xxg_init(struct i2c_client *client)
+{
+	struct msp3400c *msp = i2c_get_clientdata(client);
+	int modus;
+
+	if (msp3400c_reset(client))
+		return -1;
+
+	/* make sure that input/output is muted (paranoid mode) */
+	if (msp3400c_write(client,
+			   I2C_MSP3400C_DFP,
+			   0x13, /* ACB */
+			   0x0f20 /* mute DSP input, mute SCART 1 */))
+		return -1;
+
+	/* step-by-step initialisation, as described in the manual */
+	modus = msp34xx_modus(msp->norm);
+	modus &= ~0x03; /* STATUS_CHANGE=0 */
+	modus |= 0x01;  /* AUTOMATIC_SOUND_DETECTION=1 */
+	if (msp3400c_write(client,
+			   I2C_MSP3400C_DEM,
+			   0x30/*MODUS*/,
+			   modus))
+		return -1;
+
+	/* write the dfps that may have an influence on
+	   standard/audio autodetection right now */
+	msp34xxg_set_source(client, msp->source);
+
+	if (msp3400c_write(client, I2C_MSP3400C_DFP,
+			   0x0e, /* AM/FM Prescale */
+			   0x3000 /* default: [15:8] 75khz deviation */))
+		return -1;
+
+	if (msp3400c_write(client, I2C_MSP3400C_DFP,
+			   0x10, /* NICAM Prescale */
+			   0x5a00 /* default: 9db gain (as recommended) */))
+		return -1;
+
+	if (msp3400c_write(client,
+			   I2C_MSP3400C_DEM,
+			   0x20, /* STANDARD SELECT  */
+			   standard /* default: 0x01 for automatic standard select*/))
+		return -1;
+	return 0;
+}
+
+static int msp34xxg_thread(void *data)
+{
+	struct i2c_client *client = data;
+	struct msp3400c *msp = i2c_get_clientdata(client);
+	int val, std, i;
+
+	printk("msp34xxg: daemon started\n");
+	for (;;) {
+		d2printk(KERN_DEBUG "msp34xxg: thread: sleep\n");
+		msp34xx_sleep(msp,-1);
+		d2printk(KERN_DEBUG "msp34xxg: thread: wakeup\n");
+
+	restart:
+		dprintk("msp34xxg: thread: restart scan\n");
+		msp->restart = 0;
+		if (kthread_should_stop())
+			break;
+
+		/* setup the chip*/
+		msp34xxg_init(client);
+		std = standard;
+		if (std != 0x01)
+			goto unmute;
+
+		/* watch autodetect */
+		dprintk("msp34xxg: triggered autodetect, waiting for result\n");
+		for (i = 0; i < 10; i++) {
+			if (msp34xx_sleep(msp,100))
+				goto restart;
+
+			/* check results */
+			val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
+			if (val < 0x07ff) {
+				std = val;
+				break;
+			}
+			dprintk("msp34xxg: detection still in progress\n");
+		}
+		if (0x01 == std) {
+			dprintk("msp34xxg: detection still in progress after 10 tries. giving up.\n");
+			continue;
+		}
+
+	unmute:
+		dprintk("msp34xxg: current mode: %s (0x%04x)\n",
+			msp34xx_standard_mode_name(std), std);
+
+		/* unmute: dispatch sound to scart output, set scart volume */
+		dprintk("msp34xxg: unmute\n");
+
+		msp3400c_setbass(client, msp->bass);
+		msp3400c_settreble(client, msp->treble);
+		msp3400c_setvolume(client, msp->muted, msp->volume, msp->balance);
+
+		/* restore ACB */
+		if (msp3400c_write(client,
+				   I2C_MSP3400C_DFP,
+				   0x13, /* ACB */
+				   msp->acb))
+			return -1;
+	}
+	dprintk(KERN_DEBUG "msp34xxg: thread: exit\n");
+	return 0;
+}
+
+/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
+ * the value for source is the same as bit 15:8 of DFP registers 0x08,
+ * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
+ *
+ * this function replaces msp3400c_setstereo
+ */
+static void msp34xxg_set_source(struct i2c_client *client, int source)
+{
+	struct msp3400c *msp = i2c_get_clientdata(client);
+
+	/* fix matrix mode to stereo and let the msp choose what
+	 * to output according to 'source', as recommended
+	 */
+	int value = (source&0x07)<<8|(source==0 ? 0x00:0x20);
+	dprintk("msp34xxg: set source to %d (0x%x)\n", source, value);
+	msp3400c_write(client,
+		       I2C_MSP3400C_DFP,
+		       0x08, /* Loudspeaker Output */
+		       value);
+	msp3400c_write(client,
+		       I2C_MSP3400C_DFP,
+		       0x0a, /* SCART1 DA Output */
+		       value);
+	msp3400c_write(client,
+		       I2C_MSP3400C_DFP,
+		       0x0c, /* Quasi-peak detector */
+		       value);
+	/*
+	 * set identification threshold. Personally, I
+	 * I set it to a higher value that the default
+	 * of 0x190 to ignore noisy stereo signals.
+	 * this needs tuning. (recommended range 0x00a0-0x03c0)
+	 * 0x7f0 = forced mono mode
+	 */
+	msp3400c_write(client,
+		       I2C_MSP3400C_DEM,
+		       0x22, /* a2 threshold for stereo/bilingual */
+		       source==0 ? 0x7f0:stereo_threshold);
+	msp->source=source;
+}
+
+static void msp34xxg_detect_stereo(struct i2c_client *client)
+{
+	struct msp3400c *msp = i2c_get_clientdata(client);
+
+	int status = msp3400c_read(client,
+				   I2C_MSP3400C_DEM,
+				   0x0200 /* STATUS */);
+	int is_bilingual = status&0x100;
+	int is_stereo = status&0x40;
+
+	msp->rxsubchans = 0;
+	if (is_stereo)
+		msp->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+	else
+		msp->rxsubchans |= V4L2_TUNER_SUB_MONO;
+	if (is_bilingual) {
+		msp->rxsubchans |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2;
+		/* I'm supposed to check whether it's SAP or not
+		 * and set only LANG2/SAP in this case. Yet, the MSP
+		 * does a lot of work to hide this and handle everything
+		 * the same way. I don't want to work around it so unless
+		 * this is a problem, I'll handle SAP just like lang1/lang2.
+		 */
+	}
+	dprintk("msp34xxg: status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
+		status, is_stereo, is_bilingual, msp->rxsubchans);
+}
+
+static void msp34xxg_set_audmode(struct i2c_client *client, int audmode)
+{
+	struct msp3400c *msp = i2c_get_clientdata(client);
+	int source = 0;
+
+	switch (audmode) {
+	case V4L2_TUNER_MODE_MONO:
+		source=0; /* mono only */
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+		source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */
+		/* problem: that could also mean 2 (scart input) */
+		break;
+	case V4L2_TUNER_MODE_LANG1:
+		source=3; /* stereo or A */
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		source=4; /* stereo or B */
+		break;
+	default: /* doing nothing: a safe, sane default */
+		audmode = 0;
+		return;
+	}
+	msp->audmode = audmode;
+	msp34xxg_set_source(client, source);
+}
+
+
+/* ----------------------------------------------------------------------- */
 
 static int msp_attach(struct i2c_adapter *adap, int addr, int kind);
 static int msp_detach(struct i2c_client *client);
 static int msp_probe(struct i2c_adapter *adap);
 static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
 
+static int msp_suspend(struct device * dev, u32 state, u32 level);
+static int msp_resume(struct device * dev, u32 level);
+
 static struct i2c_driver driver = {
 	.owner          = THIS_MODULE,
-        .name           = "i2c msp3400 driver",
+	.name           = "i2c msp3400 driver",
         .id             = I2C_DRIVERID_MSP3400,
         .flags          = I2C_DF_NOTIFY,
         .attach_adapter = msp_probe,
         .detach_client  = msp_detach,
         .command        = msp_command,
+	.driver {
+		.suspend = msp_suspend,
+		.resume  = msp_resume,
+	},
 };
 
-static struct i2c_client client_template = 
+static struct i2c_client client_template =
 {
 	I2C_DEVNAME("(unset)"),
 	.flags     = I2C_CLIENT_ALLOW_USE,
@@ -1237,7 +1451,7 @@
 {
 	struct msp3400c *msp;
         struct i2c_client *c;
-	int i;
+	int (*thread_func)(void *data) = NULL;
 
         client_template.adapter = adap;
         client_template.addr = addr;
@@ -1246,7 +1460,7 @@
                 dprintk("msp3400: no chip found\n");
                 return -1;
         }
-	
+
         if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
                 return -ENOMEM;
         memcpy(c,&client_template,sizeof(struct i2c_client));
@@ -1254,16 +1468,14 @@
 		kfree(c);
 		return -ENOMEM;
 	}
-	
+
 	memset(msp,0,sizeof(struct msp3400c));
-	msp->volume = 65535;
+	msp->volume  = 58880;  /* 0db gain */
 	msp->balance = 32768;
-	msp->bass   = 32768;
-	msp->treble = 32768;
-	msp->input  = -1;
-	msp->muted  = 1;
-	for (i = 0; i < DFP_COUNT; i++)
-		msp->dfp_regs[i] = -1;
+	msp->bass    = 32768;
+	msp->treble  = 32768;
+	msp->input   = -1;
+	msp->muted   = 1;
 
 	i2c_set_clientdata(c, msp);
 	init_waitqueue_head(&msp->wq);
@@ -1274,7 +1486,7 @@
 		dprintk("msp3400: no chip found\n");
 		return -1;
 	}
-    
+
 	msp->rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e);
 	if (-1 != msp->rev1)
 		msp->rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f);
@@ -1295,36 +1507,51 @@
 		 (msp->rev2>>8)&0xff, (msp->rev1&0xff)+'@',
 		 ((msp->rev1>>8)&0xff)+'@', msp->rev2&0x1f);
 
-	if (simple == -1) {
-		/* default mode */
-		msp->simple = HAVE_SIMPLE(msp);
-	} else {
-		/* use insmod option */
-		msp->simple = simple;
+	msp->opmode = opmode;
+	if (OPMODE_AUTO == msp->opmode) {
+		if (HAVE_SIMPLER(msp))
+			msp->opmode = OPMODE_SIMPLER;
+		else if (HAVE_SIMPLE(msp))
+			msp->opmode = OPMODE_SIMPLE;
+		else
+			msp->opmode = OPMODE_MANUAL;
 	}
 
-	/* timer for stereo checking */
-	init_timer(&msp->wake_stereo);
-	msp->wake_stereo.function = msp3400c_stereo_wake;
-	msp->wake_stereo.data     = (unsigned long)msp;
-
 	/* hello world :-) */
 	printk(KERN_INFO "msp34xx: init: chip=%s",i2c_clientname(c));
 	if (HAVE_NICAM(msp))
 		printk(" +nicam");
 	if (HAVE_SIMPLE(msp))
 		printk(" +simple");
+	if (HAVE_SIMPLER(msp))
+		printk(" +simpler");
 	if (HAVE_RADIO(msp))
 		printk(" +radio");
+
+	/* version-specific initialization */
+	switch (msp->opmode) {
+	case OPMODE_MANUAL:
+		printk(" mode=manual");
+		thread_func = msp3400c_thread;
+		break;
+	case OPMODE_SIMPLE:
+		printk(" mode=simple");
+		thread_func = msp3410d_thread;
+		break;
+	case OPMODE_SIMPLER:
+		printk(" mode=simpler");
+		thread_func = msp34xxg_thread;
+		break;
+	}
 	printk("\n");
 
-	/* startup control thread */
-	init_completion(&msp->texit);
-	msp->tpid = kernel_thread(msp->simple ? msp3410d_thread : msp3400c_thread,
-				  (void *)c, 0);
-	if (msp->tpid < 0)
-		printk(KERN_WARNING "msp34xx: kernel_thread() failed\n");
-	wake_up_interruptible(&msp->wq);
+	/* startup control thread if needed */
+	if (thread_func) {
+		msp->kthread = kthread_run(thread_func, c, "msp34xx");
+		if (NULL == msp->kthread)
+			printk(KERN_WARNING "msp34xx: kernel_thread() failed\n");
+		wake_up_interruptible(&msp->wq);
+	}
 
 	/* done */
         i2c_attach_client(c);
@@ -1334,13 +1561,11 @@
 static int msp_detach(struct i2c_client *client)
 {
 	struct msp3400c *msp  = i2c_get_clientdata(client);
-	
+
 	/* shutdown control thread */
-	del_timer_sync(&msp->wake_stereo);
-	if (msp->tpid >= 0) {
-		msp->rmmod = 1;
-		wake_up_interruptible(&msp->wq);
-		wait_for_completion(&msp->texit);
+	if (msp->kthread >= 0) {
+		msp->restart = 1;
+		kthread_stop(msp->kthread);
 	}
     	msp3400c_reset(client);
 
@@ -1352,18 +1577,8 @@
 
 static int msp_probe(struct i2c_adapter *adap)
 {
-#ifdef I2C_CLASS_TV_ANALOG
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, msp_attach);
-#else
-	switch (adap->id) {
-	case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3:
-	case I2C_ALGO_BIT | I2C_HW_B_BT848:
-	//case I2C_ALGO_SAA7134:
-		return i2c_probe(adap, &addr_data, msp_attach);
-		break;
-	}
-#endif
 	return 0;
 }
 
@@ -1371,14 +1586,73 @@
 {
 	struct msp3400c *msp  = i2c_get_clientdata(client);
 
+	if (NULL == msp->kthread)
+		return;
 	msp3400c_setvolume(client,msp->muted,0,0);
-	msp->watch_stereo=0;
-	del_timer(&msp->wake_stereo);
-	if (msp->active)
-		msp->restart = 1;
+	msp->watch_stereo = 0;
+	msp->restart = 1;
 	wake_up_interruptible(&msp->wq);
 }
 
+/* ----------------------------------------------------------------------- */
+
+static int mode_v4l2_to_v4l1(int rxsubchans)
+{
+	int mode = 0;
+
+	if (rxsubchans & V4L2_TUNER_SUB_STEREO)
+		mode |= VIDEO_SOUND_STEREO;
+	if (rxsubchans & V4L2_TUNER_SUB_LANG2)
+		mode |= VIDEO_SOUND_LANG2;
+	if (rxsubchans & V4L2_TUNER_SUB_LANG1)
+		mode |= VIDEO_SOUND_LANG1;
+	if (0 == mode)
+		mode |= VIDEO_SOUND_MONO;
+	return mode;
+}
+
+static int mode_v4l1_to_v4l2(int mode)
+{
+	if (mode & VIDEO_SOUND_STEREO)
+		return V4L2_TUNER_MODE_STEREO;
+	if (mode & VIDEO_SOUND_LANG2)
+		return V4L2_TUNER_MODE_LANG2;
+	if (mode & VIDEO_SOUND_LANG1)
+		return V4L2_TUNER_MODE_LANG1;
+	return V4L2_TUNER_MODE_MONO;
+}
+
+static void msp_any_detect_stereo(struct i2c_client *client)
+{
+	struct msp3400c *msp  = i2c_get_clientdata(client);
+
+	switch (msp->opmode) {
+	case OPMODE_MANUAL:
+	case OPMODE_SIMPLE:
+		autodetect_stereo(client);
+		break;
+	case OPMODE_SIMPLER:
+		msp34xxg_detect_stereo(client);
+		break;
+	}
+}
+
+static void msp_any_set_audmode(struct i2c_client *client, int audmode)
+{
+	struct msp3400c *msp  = i2c_get_clientdata(client);
+
+	switch (msp->opmode) {
+	case OPMODE_MANUAL:
+	case OPMODE_SIMPLE:
+		msp->watch_stereo = 0;
+		msp3400c_set_audmode(client, audmode);
+		break;
+	case OPMODE_SIMPLER:
+		msp34xxg_set_audmode(client, audmode);
+		break;
+	}
+}
+
 static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	struct msp3400c *msp  = i2c_get_clientdata(client);
@@ -1410,7 +1684,6 @@
 			break;
 		case AUDIO_TUNER:
 			msp->mode   = -1;
-			msp_wake_thread(client);
 			break;
 		default:
 			if (*sarg & AUDIO_MUTE)
@@ -1418,63 +1691,38 @@
 			break;
 		}
 		if (scart) {
-			msp->stereo = VIDEO_SOUND_STEREO;
+			msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
+			msp->audmode = V4L2_TUNER_MODE_STEREO;
 			msp3400c_set_scart(client,scart,0);
 			msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
-			msp3400c_setstereo(client,msp->stereo);
+			if (msp->opmode != OPMODE_SIMPLER)
+				msp3400c_set_audmode(client, msp->audmode);
 		}
-		if (msp->active)
-			msp->restart = 1;
+		msp_wake_thread(client);
 		break;
 
 	case AUDC_SET_RADIO:
 		dprintk(KERN_DEBUG "msp34xx: AUDC_SET_RADIO\n");
 		msp->norm = VIDEO_MODE_RADIO;
-		msp->watch_stereo=0;
-		del_timer(&msp->wake_stereo);
 		dprintk(KERN_DEBUG "msp34xx: switching to radio mode\n");
-		if (msp->simple) {
-			/* the thread will do for us */
-			msp_wake_thread(client);
-		} else {
+		msp->watch_stereo = 0;
+		switch (msp->opmode) {
+		case OPMODE_MANUAL:
 			/* set msp3400 to FM radio mode */
 			msp3400c_setmode(client,MSP_MODE_FM_RADIO);
 			msp3400c_setcarrier(client, MSP_CARRIER(10.7),
 					    MSP_CARRIER(10.7));
 			msp3400c_setvolume(client, msp->muted,
 					   msp->volume, msp->balance);
+			break;
+		case OPMODE_SIMPLE:
+		case OPMODE_SIMPLER:
+			/* the thread will do for us */
+			msp_wake_thread(client);
+			break;
 		}
-		if (msp->active)
-			msp->restart = 1;
 		break;
 
-#if 1
-	/* work-in-progress:  hook to control the DFP registers */
-	case MSP_SET_DFPREG:
-	{
-		struct msp_dfpreg *r = arg;
-		unsigned int i;
-
-		if (r->reg < 0 || r->reg >= DFP_COUNT)
-			return -EINVAL;
-		for (i = 0; i < ARRAY_SIZE(bl_dfp); i++)
-			if (r->reg == bl_dfp[i])
-				return -EINVAL;
-		msp->dfp_regs[r->reg] = r->value;
-		msp3400c_write(client,I2C_MSP3400C_DFP,r->reg,r->value);
-		return 0;
-	}
-	case MSP_GET_DFPREG:
-	{
-		struct msp_dfpreg *r = arg;
-
-		if (r->reg < 0 || r->reg >= DFP_COUNT)
-			return -EINVAL;
-		r->value = msp3400c_read(client,I2C_MSP3400C_DFP,r->reg);
-		return 0;
-	}
-#endif
-
 	/* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
@@ -1495,10 +1743,8 @@
 		va->bass = msp->bass;
 		va->treble = msp->treble;
 
-		if (msp->norm != VIDEO_MODE_RADIO) {
-			autodetect_stereo(client);
-			va->mode = msp->stereo;
-		}
+		msp_any_detect_stereo(client);
+		va->mode = mode_v4l2_to_v4l1(msp->rxsubchans);
 		break;
 	}
 	case VIDIOCSAUDIO:
@@ -1517,23 +1763,22 @@
 		msp3400c_setbass(client,msp->bass);
 		msp3400c_settreble(client,msp->treble);
 
-		if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO) {
-			msp->watch_stereo=0;
-			del_timer(&msp->wake_stereo);
-			msp->stereo = va->mode & 0x0f;
-			msp3400c_setstereo(client,va->mode & 0x0f);
-		}
+		if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO)
+			msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode));
 		break;
 	}
 	case VIDIOCSCHAN:
 	{
 		struct video_channel *vc = arg;
-		
+
 		dprintk(KERN_DEBUG "msp34xx: VIDIOCSCHAN (norm=%d)\n",vc->norm);
 		msp->norm = vc->norm;
+		msp_wake_thread(client);
 		break;
 	}
+
 	case VIDIOCSFREQ:
+	case VIDIOC_S_FREQUENCY:
 	{
 		/* new channel -- kick audio carrier scan */
 		dprintk(KERN_DEBUG "msp34xx: VIDIOCSFREQ\n");
@@ -1541,10 +1786,61 @@
 		break;
 	}
 
+	/* --- v4l2 ioctls --- */
+	case VIDIOC_G_TUNER:
+	{
+		struct v4l2_tuner *vt = arg;
+
+		msp_any_detect_stereo(client);
+		vt->audmode    = msp->audmode;
+		vt->rxsubchans = msp->rxsubchans;
+		vt->capability = V4L2_TUNER_CAP_STEREO |
+			V4L2_TUNER_CAP_LANG1|
+			V4L2_TUNER_CAP_LANG2;
+		break;
+	}
+	case VIDIOC_S_TUNER:
+	{
+		struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
+
+		/* only set audmode */
+		if (vt->audmode != -1 && vt->audmode != 0)
+			msp_any_set_audmode(client, vt->audmode);
+		break;
+	}
+
+	/* msp34xx specific */
+	case MSP_SET_MATRIX:
+	{
+		struct msp_matrix *mspm = arg;
+
+		dprintk(KERN_DEBUG "msp34xx: MSP_SET_MATRIX\n");
+		msp3400c_set_scart(client, mspm->input, mspm->output);
+		break;
+	}
+
 	default:
 		/* nothing */
 		break;
 	}
+	return 0;
+}
+
+static int msp_suspend(struct device * dev, u32 state, u32 level)
+{
+	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+
+	dprintk("msp34xx: suspend\n");
+	msp3400c_reset(c);
+	return 0;
+}
+
+static int msp_resume(struct device * dev, u32 level)
+{
+	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+
+	dprintk("msp34xx: resume\n");
+	msp_wake_thread(c);
 	return 0;
 }
 
diff -Nru a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h
--- a/drivers/media/video/msp3400.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/msp3400.h	2004-10-28 22:25:59 -07:00
@@ -8,7 +8,29 @@
     int value;
 };
 
+struct msp_matrix {
+  int input;
+  int output;
+};
+
 #define MSP_SET_DFPREG     _IOW('m',15,struct msp_dfpreg)
 #define MSP_GET_DFPREG     _IOW('m',16,struct msp_dfpreg)
+
+/* ioctl for MSP_SET_MATRIX will have to be registered */
+#define MSP_SET_MATRIX     _IOW('m',17,struct msp_matrix)
+
+#define SCART_MASK    0
+#define SCART_IN1     1
+#define SCART_IN2     2
+#define SCART_IN1_DA  3
+#define SCART_IN2_DA  4
+#define SCART_IN3     5
+#define SCART_IN4     6
+#define SCART_MONO    7
+#define SCART_MUTE    8
+
+#define SCART_DSP_IN  0
+#define SCART1_OUT    1
+#define SCART2_OUT    2
 
 #endif /* MSP3400_H */
diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
--- a/drivers/media/video/tda7432.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/tda7432.c	2004-10-28 22:25:58 -07:00
@@ -1,8 +1,8 @@
 /*
  * For the STS-Thompson TDA7432 audio processor chip
- * 
+ *
  * Handles audio functions: volume, balance, tone, loudness
- * This driver will not complain if used with any 
+ * This driver will not complain if used with any
  * other i2c device with the same address.
  *
  * Muting and tone control by Jonathan Isom <jisom@ematic.com>
@@ -106,7 +106,7 @@
  * output (for front and rear).  Since most vidcap cards probably
  * don't have 4 channel output, this driver will set front & rear
  * together (no independent control).
- */ 
+ */
 
 		/* Subaddresses for TDA7432 */
 
@@ -132,13 +132,13 @@
  * 0x03 - Mute  (Using Attenuators Plays better with modules)
  * Mono probably isn't used - I'm guessing only the stereo
  * input is connected on most cards, so we'll set it to stereo.
- * 
+ *
  * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut
  * Bit 4 controls bass range: 0/1 is extended/standard bass range
- * 
+ *
  * Highest 3 bits not used
  */
- 
+
 #define TDA7432_STEREO_IN	0
 #define TDA7432_MONO_IN		2	/* Probably won't be used */
 #define TDA7432_BASS_SYM	1 << 3
@@ -161,7 +161,7 @@
 #define TDA7432_LD_ON		1 << 7
 
 
-/* Subaddress 0x02 - Tone control */ 
+/* Subaddress 0x02 - Tone control */
 
 /* Bits 0,1,2 control absolute treble gain from 0dB to 14dB
  * 0x0 is 14dB, 0x7 is 0dB
@@ -173,23 +173,23 @@
  * Bits 4,5,6 control absolute bass gain from 0dB to 14dB
  * (This is only true for normal base range, set in 0x00)
  * 0x0 << 4 is 14dB, 0x7 is 0dB
- * 
+ *
  * Bit 7 controls bass attenuation/gain (sign)
  * 1 << 7 = gain (+)
- * 0 << 7 = attenuation (-) 
+ * 0 << 7 = attenuation (-)
  *
  * Example:
  * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble
  */
 
-#define TDA7432_TREBLE_0DB		0xf 
+#define TDA7432_TREBLE_0DB		0xf
 #define TDA7432_TREBLE			7
 #define TDA7432_TREBLE_GAIN		1 << 3
 #define TDA7432_BASS_0DB		0xf
 #define TDA7432_BASS			7 << 4
 #define TDA7432_BASS_GAIN		1 << 7
 
- 
+
 /* Subaddress 0x03 - Left  Front attenuation */
 /* Subaddress 0x04 - Left  Rear  attenuation */
 /* Subaddress 0x05 - Right Front attenuation */
@@ -202,7 +202,7 @@
  * 0x1f is -37.5dB
  *
  * Bit 5 mutes that channel when set (1 = mute, 0 = unmute)
- * We'll use the mute on the input, though (above) 
+ * We'll use the mute on the input, though (above)
  * Bits 6,7 unused
  */
 
@@ -223,8 +223,8 @@
  *
  * Bits 5,6,7 unused
  */
- 
- 
+
+
 
 /* Begin code */
 
@@ -253,7 +253,7 @@
 		printk(KERN_WARNING "tda7432: I/O error, trying (read)\n");
 		return -1;
 	}
-	dprintk("tda7432: Read 0x%02x\n", buffer); 
+	dprintk("tda7432: Read 0x%02x\n", buffer);
 	return buffer;
 }
 #endif
@@ -263,8 +263,8 @@
 	struct tda7432 *t = i2c_get_clientdata(client);
 	unsigned char buf[16];
 	d2printk("tda7432: In tda7432_set\n");
-	
-	dprintk(KERN_INFO 
+
+	dprintk(KERN_INFO
 		"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
 		t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud);
 	buf[0]  = TDA7432_IN;
@@ -292,10 +292,10 @@
 
 	t->input  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
 		    TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
-		    TDA7432_BASS_NORM;   /* Normal bass range     */ 
+		    TDA7432_BASS_NORM;   /* Normal bass range     */
 	t->volume =  0x3b ;				 /* -27dB Volume            */
 	if (loudness)			 /* Turn loudness on?     */
-		t->volume |= TDA7432_LD_ON;	
+		t->volume |= TDA7432_LD_ON;
 	t->muted    = VIDEO_AUDIO_MUTE;
 	t->treble   = TDA7432_TREBLE_0DB; /* 0dB Treble            */
 	t->bass		= TDA7432_BASS_0DB; 	 /* 0dB Bass              */
@@ -328,7 +328,7 @@
         client->adapter = adap;
         client->addr = addr;
 	i2c_set_clientdata(client, t);
-	
+
 	do_tda7432_init(client);
 	printk(KERN_INFO "tda7432: init\n");
 
@@ -354,7 +354,7 @@
 
 	do_tda7432_init(client);
 	i2c_detach_client(client);
-	
+
 	kfree(t);
 	return 0;
 }
@@ -369,7 +369,7 @@
 	/* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
-	
+
 	/* Query card - scale from TDA7432 settings to V4L settings */
 	case VIDIOCGAUDIO:
 	{
@@ -385,7 +385,7 @@
 		va->mode |= VIDEO_SOUND_STEREO;
 		/* Master volume control
 		 * V4L volume is min 0, max 65535
-		 * TDA7432 Volume: 
+		 * TDA7432 Volume:
 		 * Min (-79dB) is 0x6f
 		 * Max (+20dB) is 0x07 (630)
 		 * Max (0dB) is 0x20 (829)
@@ -396,7 +396,7 @@
 		} else {       /* max 0db   */
 			va->volume = ( 0x6f - (t->volume & 0x7F) ) * 829;
 		}
-		
+
 		/* Balance depends on L,R attenuation
 		 * V4L balance is 0 to 65535, middle is 32768
 		 * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f
@@ -404,15 +404,15 @@
 		 * attenuation exists for lf, lr, rf, rr
 		 * we use only lf and rf (front channels)
 		 */
-		
+
 		if ( (t->lf) < (t->rf) )
 			/* right is attenuated, balance shifted left */
 			va->balance = (32768 - 1057*(t->rf));
 		else
 			/* left is attenuated, balance shifted right */
 			va->balance = (32768 + 1057*(t->lf));
-		
-		/* Bass/treble 4 bits each */	
+
+		/* Bass/treble 4 bits each */
 		va->bass=t->bass;
 		if(va->bass >= 0x8)
 			va->bass = ~(va->bass - 0x8) & 0xf;
@@ -421,7 +421,7 @@
 		if(va->treble >= 0x8)
 			va->treble = ~(va->treble - 0x8) & 0xf;
 		va->treble = (va->treble << 12)+(va->treble << 8)+(va->treble << 4)+(va->treble);
-								
+
 		break; /* VIDIOCGAUDIO case */
 	}
 
@@ -437,13 +437,13 @@
 			} else {    /* max 0db   */
 				t->volume = 0x6f - ((va->volume)/829);
 			}
-		
+
 		if (loudness)		/* Turn on the loudness bit */
 			t->volume |= TDA7432_LD_ON;
-		
+
 			tda7432_write(client,TDA7432_VL, t->volume);
 		}
-		
+
 		if(va->flags & VIDEO_AUDIO_BASS)
 		{
 			t->bass = va->bass >> 12;
@@ -458,15 +458,15 @@
 		}
 		if(va->flags & (VIDEO_AUDIO_TREBLE| VIDEO_AUDIO_BASS))
 			tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble );
-		
+
 		if(va->flags & VIDEO_AUDIO_BALANCE)	{
-		if (va->balance < 32768) 
+		if (va->balance < 32768)
 		{
 			/* shifted to left, attenuate right */
 			t->rr = (32768 - va->balance)/1057;
 			t->rf = t->rr;
 			t->lr = TDA7432_ATTEN_0DB;
-			t->lf = TDA7432_ATTEN_0DB;	
+			t->lf = TDA7432_ATTEN_0DB;
 		}
 		else if(va->balance > 32769)
 		{
@@ -474,22 +474,22 @@
 			t->lf = (va->balance - 32768)/1057;
 			t->lr = t->lf;
 			t->rr = TDA7432_ATTEN_0DB;
-			t->rf = TDA7432_ATTEN_0DB;		
+			t->rf = TDA7432_ATTEN_0DB;
 		}
-		else 
+		else
 		{
-			/* centered */		
+			/* centered */
 			t->rr = TDA7432_ATTEN_0DB;
 			t->rf = TDA7432_ATTEN_0DB;
 			t->lf = TDA7432_ATTEN_0DB;
 			t->lr = TDA7432_ATTEN_0DB;
 		}
 		}
-					
-	 	t->muted=(va->flags & VIDEO_AUDIO_MUTE);	
+
+	 	t->muted=(va->flags & VIDEO_AUDIO_MUTE);
 		if (t->muted)
 		{
-			/* Mute & update balance*/	
+			/* Mute & update balance*/
 			tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE);
 			tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE);
 			tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE);
@@ -500,7 +500,7 @@
 			tda7432_write(client,TDA7432_RF, t->rf);
 			tda7432_write(client,TDA7432_RR, t->rr);
 		}
-							
+
 		break;
 
 	} /* end of VIDEOCSAUDIO case */
@@ -529,7 +529,7 @@
 {
 	I2C_DEVNAME("tda7432"),
         .id         = -1,
-	.driver     = &driver, 
+	.driver     = &driver,
 };
 
 static int __init tda7432_init(void)
diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
--- a/drivers/media/video/tda9875.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/video/tda9875.c	2004-10-28 22:25:57 -07:00
@@ -1,19 +1,19 @@
 /*
  * For the TDA9875 chip
- * (The TDA9875 is used on the Diamond DTV2000 french version 
+ * (The TDA9875 is used on the Diamond DTV2000 french version
  * Other cards probably use these chips as well.)
- * This driver will not complain if used with any 
+ * This driver will not complain if used with any
  * other i2c device with the same address.
  *
  * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source and
- * Eric Sandeen 
+ * Eric Sandeen
  * This code is placed under the terms of the GNU General Public License
  * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
  * Which was based on tda8425.c by Greg Alexander (c) 1998
  *
  * OPTIONS:
  * debug   - set to 1 if you'd like to see debug messages
- * 
+ *
  *  Revision: 0.1 - original version
  */
 
@@ -64,7 +64,7 @@
  * http://www.semiconductors.philips.com
  * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator
  *
- */ 
+ */
 
 		/* subaddresses for TDA9875 */
 #define TDA9875_MUT         0x12  /*General mute  (value --> 0b11001100*/
@@ -133,7 +133,7 @@
 		printk(KERN_WARNING "tda9875: I/O error, trying (read)\n");
 		return -1;
 	}
-	dprintk("Read 0x%02x\n", buffer); 
+	dprintk("Read 0x%02x\n", buffer);
 	return buffer;
 }
 #endif
@@ -178,7 +178,7 @@
 static void do_tda9875_init(struct i2c_client *client)
 {
 	struct tda9875 *t = i2c_get_clientdata(client);
-	dprintk("In tda9875_init\n"); 
+	dprintk("In tda9875_init\n");
 	tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/
     	tda9875_write(client, TDA9875_MSR, 0x03 );    /* Monitor 0b00000XXX*/
 	tda9875_write(client, TDA9875_C1MSB, 0x00 );  /*Car1(FM) MSB XMHz*/
@@ -192,7 +192,7 @@
 	tda9875_write(client, TDA9875_FMAT, 0x00 );   /*FM Matrix reg 0x00*/
 	tda9875_write(client, TDA9875_SC1, 0x00 );    /* SCART 1 (SC1)*/
 	tda9875_write(client, TDA9875_SC2, 0x01 );    /* SCART 2 (sc2)*/
-        
+
 	tda9875_write(client, TDA9875_CH1V, 0x10 );  /* Channel volume 1 mute*/
 	tda9875_write(client, TDA9875_CH2V, 0x10 );  /* Channel volume 2 mute */
 	tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/
@@ -204,14 +204,14 @@
 	tda9875_write(client, TDA9875_MVR, 0x03 );   /* Vol Main right 10dB*/
 	tda9875_write(client, TDA9875_MBA, 0x00 );   /* Main Bass Main 0dB*/
 	tda9875_write(client, TDA9875_MTR, 0x00 );   /* Main Treble Main 0dB*/
-	tda9875_write(client, TDA9875_ACS, 0x44 );   /* Aux chan select (dac)*/	
+	tda9875_write(client, TDA9875_ACS, 0x44 );   /* Aux chan select (dac)*/
 	tda9875_write(client, TDA9875_AVL, 0x00 );   /* Vol Aux left 0dB*/
 	tda9875_write(client, TDA9875_AVR, 0x00 );   /* Vol Aux right 0dB*/
 	tda9875_write(client, TDA9875_ABA, 0x00 );   /* Aux Bass Main 0dB*/
 	tda9875_write(client, TDA9875_ATR, 0x00 );   /* Aux Aigus Main 0dB*/
-	
+
 	tda9875_write(client, TDA9875_MUT, 0xcc );   /* General mute  */
-        
+
 	t->mode=AUDIO_UNMUTE;
 	t->lvol=t->rvol =0;  	/* 0dB */
 	t->bass=0; 		        /* 0dB */
@@ -262,7 +262,7 @@
 		kfree(t);
 		return 1;
 	}
-	
+
 	do_tda9875_init(client);
 	printk(KERN_INFO "tda9875: init\n");
 
@@ -288,7 +288,7 @@
 
 	do_tda9875_init(client);
 	i2c_detach_client(client);
-	
+
 	kfree(t);
 	return 0;
 }
@@ -298,9 +298,9 @@
 {
 	struct tda9875 *t = i2c_get_clientdata(client);
 
-	dprintk("In tda9875_command...\n"); 
+	dprintk("In tda9875_command...\n");
 
-	switch (cmd) {	
+	switch (cmd) {
         /* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
@@ -335,7 +335,7 @@
 		struct video_audio *va = arg;
 		int left,right;
 
-		dprintk("VIDEOCSAUDIO...\n"); 
+		dprintk("VIDEOCSAUDIO...\n");
 		left = (min(65536 - va->balance,32768) *
 			va->volume) / 32768;
 		right = (min(va->balance,(__u16)32768) *
@@ -357,7 +357,7 @@
 		 t->bass = 15;
 		if (t->bass < -12)
 		 t->bass = -12 & 0xff;
-		
+
 		t->treble = ((va->treble/2700)-12) & 0xff;
 		if (t->treble > 12)
 		 t->treble = 12;
@@ -367,7 +367,7 @@
 
 
 //printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble);
-		
+
 
                 tda9875_set(client);
 
diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
--- a/drivers/media/video/tda9887.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/tda9887.c	2004-10-28 22:25:59 -07:00
@@ -535,6 +535,11 @@
 	tda9887_set_config(t,buf);
 	tda9887_set_insmod(t,buf);
 
+	if (t->std & V4L2_STD_SECAM_L) {
+		/* secam fixup (FIXME: move this to tvnorms array?) */
+		buf[1] &= ~cOutputPort2Inactive;
+	}
+
 	dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
 		buf[1],buf[2],buf[3]);
 	if (debug > 1)
@@ -565,11 +570,11 @@
                 return -ENOMEM;
 	memset(t,0,sizeof(*t));
 	t->client      = client_template;
-	t->std         = 0;;
+	t->std         = 0;
 	t->pinnacle_id = UNSET;
         i2c_set_clientdata(&t->client, t);
         i2c_attach_client(&t->client);
-        
+
 	return 0;
 }
 
@@ -618,7 +623,7 @@
 		t->radio = 1;
 		tda9887_configure(t);
 		break;
-		
+
 	case AUDC_CONFIG_PINNACLE:
 	{
 		int *i = arg;
@@ -712,6 +717,22 @@
 	return 0;
 }
 
+static int tda9887_suspend(struct device * dev, u32 state, u32 level)
+{
+	dprintk("tda9887: suspend\n");
+	return 0;
+}
+
+static int tda9887_resume(struct device * dev, u32 level)
+{
+	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+	struct tda9887 *t = i2c_get_clientdata(c);
+
+	dprintk("tda9887: resume\n");
+	tda9887_configure(t);
+	return 0;
+}
+
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_driver driver = {
@@ -722,6 +743,10 @@
         .attach_adapter = tda9887_probe,
         .detach_client  = tda9887_detach,
         .command        = tda9887_command,
+	.driver = {
+		.suspend = tda9887_suspend,
+		.resume  = tda9887_resume,
+	},
 };
 static struct i2c_client client_template =
 {
diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
--- a/drivers/media/video/tuner.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/tuner.c	2004-10-28 22:25:59 -07:00
@@ -1,4 +1,9 @@
+/*
+ * $Id: tuner.c,v 1.27 2004/10/20 09:43:34 kraxel Exp $
+ */
+
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -15,30 +20,34 @@
 #include <media/tuner.h>
 #include <media/audiochip.h>
 
-/* Addresses to scan */
+#define UNSET (-1U)
+
+/* standard i2c insmod options */
 static unsigned short normal_i2c[] = {I2C_CLIENT_END};
 static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
-#define UNSET (-1U)
-
-/* insmod options */
-static unsigned int debug =  0;
+/* insmod options used at init time => read/only */
 static unsigned int type  =  UNSET;
 static unsigned int addr  =  0;
+module_param(type, int, 444);
+module_param(addr, int, 444);
+
+/* insmod options used at runtime => read/write */
+static unsigned int debug         = 0;
+static unsigned int tv_antenna    = 1;
+static unsigned int radio_antenna = 0;
+static unsigned int optimize_vco  = 1;
+module_param(debug,             int, 644);
+module_param(tv_antenna,        int, 644);
+module_param(radio_antenna,     int, 644);
+module_param(optimize_vco,      int, 644);
+
 static unsigned int tv_range[2]    = { 44, 958 };
 static unsigned int radio_range[2] = { 65, 108 };
-static unsigned int tv_antenna = 1;
-static unsigned int radio_antenna = 0;
-MODULE_PARM(debug,"i");
-MODULE_PARM(type,"i");
-MODULE_PARM(addr,"i");
-MODULE_PARM(tv_range,"2i");
-MODULE_PARM(radio_range,"2i");
-MODULE_PARM(tv_antenna,"i");
-MODULE_PARM(radio_antenna,"i");
 
-#define optimize_vco 1
+module_param_array(tv_range,    int, NULL, 644);
+module_param_array(radio_range, int, NULL, 644);
 
 MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
 MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
@@ -52,10 +61,10 @@
 	unsigned int freq;            /* keep track of the current settings */
 	v4l2_std_id  std;
 	int          using_v4l2;
-	
+
 	unsigned int radio;
 	unsigned int input;
-	
+
 	// only for MT2032
 	unsigned int xogc;
 	unsigned int radio_if2;
@@ -71,11 +80,11 @@
 
 /* tv standard selection for Temic 4046 FM5
    this value takes the low bits of control byte 2
-   from datasheet Rev.01, Feb.00 
+   from datasheet Rev.01, Feb.00
      standard     BG      I       L       L2      D
      picture IF   38.9    38.9    38.9    33.95   38.9
      sound 1      33.4    32.9    32.4    40.45   32.4
-     sound 2      33.16   
+     sound 2      33.16
      NICAM        33.05   32.348  33.05           33.05
  */
 #define TEMIC_SET_PAL_I         0x05
@@ -97,7 +106,7 @@
 #define PHILIPS_SET_PAL_I	0x01 /* Bit 2 always zero !*/
 #define PHILIPS_SET_PAL_BGDK	0x09
 #define PHILIPS_SET_PAL_L2	0x0a
-#define PHILIPS_SET_PAL_L	0x0b	
+#define PHILIPS_SET_PAL_L	0x0b
 
 /* system switching for Philips FI1216MF MK2
    from datasheet "1996 Jul 09",
@@ -115,20 +124,20 @@
 
 /* ---------------------------------------------------------------------- */
 
-struct tunertype 
+struct tunertype
 {
 	char *name;
 	unsigned char Vendor;
 	unsigned char Type;
-  
+
 	unsigned short thresh1;  /*  band switch VHF_LO <=> VHF_HI  */
 	unsigned short thresh2;  /*  band switch VHF_HI <=> UHF     */
 	unsigned char VHF_L;
 	unsigned char VHF_H;
 	unsigned char UHF;
-	unsigned char config; 
-	unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL, 
-				   732  =16*45.75 NTSCi, 
+	unsigned char config;
+	unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL,
+				   732  =16*45.75 NTSCi,
 				   940  =16*58.75 NTSC-Japan
 				   704  =16*44    ATSC */
 };
@@ -171,7 +180,7 @@
         { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
 	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
 	{ "Temic PAL_BG (4006FH5)", TEMIC, PAL,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, 
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
   	{ "Alps TSCH6",Alps,NTSC,
   	  16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
 
@@ -245,14 +254,14 @@
 	{ "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
 	  16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
         { "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
-          16*160.00,16*442.00,0x01,0x02,0x04,0xc8,732 },
+          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
 
         { "Tenna TNF 8831 BGFF)", Philips, PAL,
           16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
 	{ "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC,
 	  16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732},
         { "TCL 2002N", TCL, NTSC,
-          16*172.00,16*448.00,0x01,0x02,0x08,0x88,732},
+          16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732},
 
 };
 #define TUNERS ARRAY_SIZE(tuners)
@@ -421,7 +430,7 @@
  	if(rfin >400*1000*1000)
                 buf[6]=0xe4;
         else
-                buf[6]=0xf4; // set PKEN per rev 1.2 
+                buf[6]=0xf4; // set PKEN per rev 1.2
 	buf[7]=8+xogc;
 	buf[8]=0xc3; //reserved
 	buf[9]=0x4e; //reserved
@@ -442,10 +451,10 @@
 		i2c_master_recv(c,buf,1);
 		dprintk("mt2032 Reg.E=0x%02x\n",buf[0]);
 		lock=buf[0] &0x06;
-		
+
 		if (lock==6)
 			break;
-		
+
 		dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
 		udelay(1000);
 	}
@@ -467,7 +476,7 @@
 	if(tad1 ==1) return lock;
 
 	if(tad1==2) {
-		if(sel==0) 
+		if(sel==0)
 			return lock;
 		else sel--;
 	}
@@ -520,13 +529,13 @@
 	// wait for PLLs to lock (per manual), retry LINT if not.
 	for(lint_try=0; lint_try<2; lint_try++) {
 		lock=mt2032_check_lo_lock(c);
-		
+
 		if(optimize_vco)
 			lock=mt2032_optimize_vco(c,sel,lock);
 		if(lock==6) break;
-		
-		printk("mt2032: re-init PLLs by LINT\n"); 
-		buf[0]=7; 
+
+		printk("mt2032: re-init PLLs by LINT\n");
+		buf[0]=7;
 		buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
 		i2c_master_send(c,buf,2);
 		mdelay(10);
@@ -651,46 +660,46 @@
 	unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
 	int ret;
 	unsigned char buf[6];
-	
+
 	dprintk("mt2050_set_if_freq freq=%d\n",freq);
-	
+
 	f_lo1=freq+if1;
 	f_lo1=(f_lo1/1000000)*1000000;
-	
+
 	f_lo2=f_lo1-freq-if2;
 	f_lo2=(f_lo2/50000)*50000;
-	
+
 	lo1=f_lo1/4000000;
 	lo2=f_lo2/4000000;
-	
+
 	f_lo1_modulo= f_lo1-(lo1*4000000);
 	f_lo2_modulo= f_lo2-(lo2*4000000);
-	
+
 	num1=4*f_lo1_modulo/4000000;
 	num2=4096*(f_lo2_modulo/1000)/4000;
-	
+
 	// todo spurchecks
-	
+
 	div1a=(lo1/12)-1;
 	div1b=lo1-(div1a+1)*12;
-	
+
 	div2a=(lo2/8)-1;
 	div2b=lo2-(div2a+1)*8;
-	
+
 	dprintk("lo1 lo2 = %d %d\n", lo1, lo2);
         dprintk("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",num1,num2,div1a,div1b,div2a,div2b);
-	
-	
+
+
 	buf[0]=1;
 	buf[1]= 4*div1b + num1;
 	if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
-	
+
 	buf[2]=div1a;
 	buf[3]=32*div2b + num2/256;
 	buf[4]=num2-(num2/256)*256;
 	buf[5]=div2a;
 	if(num2!=0) buf[5]=buf[5]|0x40;
-	
+
 	if(debug) {
 		int i;
 		printk("bufs is: ");
@@ -698,7 +707,7 @@
 			printk("%x ",buf[i]);
 		printk("\n");
 	}
-	
+
 	ret=i2c_master_send(c,buf,6);
         if (ret!=6)
                 printk("mt2050_set_if_freq failed with %d\n",ret);
@@ -708,7 +717,7 @@
 {
 	struct tuner *t = i2c_get_clientdata(c);
 	unsigned int if2;
-	
+
 	if (t->std & V4L2_STD_525_60) {
 		// NTSC
                 if2 = 45750*1000;
@@ -724,7 +733,7 @@
 {
 	struct tuner *t = i2c_get_clientdata(c);
 	int if2 = t->radio_if2;
-	
+
 	mt2050_set_if_freq(c, freq*62500, if2);
 	mt2050_set_antenna(c, radio_antenna);
 }
@@ -734,19 +743,19 @@
 	struct tuner *t = i2c_get_clientdata(c);
 	unsigned char buf[2];
 	int ret;
-	
+
 	buf[0]=6;
 	buf[1]=0x10;
 	ret=i2c_master_send(c,buf,2); //  power
-	
+
 	buf[0]=0x0f;
 	buf[1]=0x0f;
 	ret=i2c_master_send(c,buf,2); // m1lo
-	
+
 	buf[0]=0x0d;
 	ret=i2c_master_send(c,buf,1);
 	i2c_master_recv(c,buf,1);
-	
+
 	dprintk("mt2050: sro is %x\n",buf[0]);
 	t->tv_freq    = mt2050_set_tv_freq;
 	t->radio_freq = mt2050_set_radio_freq;
@@ -759,7 +768,7 @@
 	char *name;
         unsigned char buf[21];
 	int company_code;
-	
+
 	memset(buf,0,sizeof(buf));
 	t->tv_freq    = NULL;
 	t->radio_freq = NULL;
@@ -828,13 +837,17 @@
         unsigned char buffer[4];
 	int rc;
 
-	tun=&tuners[t->type];
-	if (freq < tun->thresh1) 
+	tun = &tuners[t->type];
+	if (freq < tun->thresh1) {
 		config = tun->VHF_L;
-	else if (freq < tun->thresh2) 
+		dprintk("tv: VHF lowrange\n");
+	} else if (freq < tun->thresh2) {
 		config = tun->VHF_H;
-	else
+		dprintk("tv: VHF high range\n");
+	} else {
 		config = tun->UHF;
+		dprintk("tv: UHF range\n");
+	}
 
 
 	/* tv norm specific stuff for multi-norm tuners */
@@ -887,7 +900,7 @@
 		/* 0x02 -> NTSC antenna input 1 */
 		/* 0x03 -> NTSC antenna input 2 */
 		config &= ~0x03;
-		if (t->std & V4L2_STD_ATSC)
+		if (!(t->std & V4L2_STD_ATSC))
 			config |= 2;
 		/* FIXME: input */
 		break;
@@ -897,7 +910,7 @@
 		tun->config |= 0x40;
 		break;
 	}
-	
+
 	/*
 	 * Philips FI1216MK2 remark from specification :
 	 * for channel selection involving band switching, and to ensure
@@ -1131,7 +1144,7 @@
 	if (this_adap > 0)
 		return -1;
 	this_adap++;
-	
+
         client_template.adapter = adap;
         client_template.addr = addr;
 
@@ -1233,7 +1246,7 @@
 			break;
 		}
                 break;
-		
+
 	/* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
@@ -1328,7 +1341,25 @@
 		/* nothing */
 		break;
 	}
-	
+
+	return 0;
+}
+
+static int tuner_suspend(struct device * dev, u32 state, u32 level)
+{
+	dprintk("tuner: suspend\n");
+	/* FIXME: power down ??? */
+	return 0;
+}
+
+static int tuner_resume(struct device * dev, u32 level)
+{
+	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+	struct tuner *t = i2c_get_clientdata(c);
+
+	dprintk("tuner: resume\n");
+	if (t->freq)
+		set_freq(c,t->freq);
 	return 0;
 }
 
@@ -1342,6 +1373,10 @@
         .attach_adapter = tuner_probe,
         .detach_client  = tuner_detach,
         .command        = tuner_command,
+	.driver = {
+		.suspend = tuner_suspend,
+		.resume  = tuner_resume,
+	},
 };
 static struct i2c_client client_template =
 {
diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
--- a/drivers/media/video/tvaudio.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/media/video/tvaudio.c	2004-10-28 22:25:57 -07:00
@@ -3,12 +3,12 @@
  *
  * Copyright (c) 2000 Gerd Knorr
  * based on code by:
- *   Eric Sandeen (eric_sandeen@bigfoot.com) 
+ *   Eric Sandeen (eric_sandeen@bigfoot.com)
  *   Steve VanDeBogart (vandebo@uclink.berkeley.edu)
  *   Greg Alexander (galexand@acm.org)
  *
  * This code is placed under the terms of the GNU General Public License
- * 
+ *
  * OPTIONS:
  *   debug - set to 1 if you'd like to see debug messages
  *
@@ -207,7 +207,7 @@
 		       i2c_clientname(&chip->c));
 		return -1;
 	}
-	dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer); 
+	dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer);
 	return buffer;
 }
 
@@ -227,14 +227,14 @@
 		return -1;
 	}
 	dprintk("%s: chip_read2: reg%d=0x%x\n",
-		i2c_clientname(&chip->c),subaddr,read[0]); 
+		i2c_clientname(&chip->c),subaddr,read[0]);
 	return read[0];
 }
 
 static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
 {
 	int i;
-	
+
 	if (0 == cmd->count)
 		return 0;
 
@@ -273,7 +273,7 @@
 	DECLARE_WAITQUEUE(wait, current);
         struct CHIPSTATE *chip = data;
 	struct CHIPDESC  *desc = chiplist + chip->type;
-	
+
 	daemonize("%s",i2c_clientname(&chip->c));
 	allow_signal(SIGTERM);
 	dprintk("%s: thread started\n", i2c_clientname(&chip->c));
@@ -292,10 +292,10 @@
 		/* don't do anything for radio or if mode != auto */
 		if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0)
 			continue;
-		
+
 		/* have a look what's going on */
 		desc->checkmode(chip);
-		
+
 		/* schedule next check */
 		mod_timer(&chip->wt, jiffies+2*HZ);
 	}
@@ -352,14 +352,14 @@
 static int tda9840_getmode(struct CHIPSTATE *chip)
 {
 	int val, mode;
-	
+
 	val = chip_read(chip);
 	mode = VIDEO_SOUND_MONO;
 	if (val & TDA9840_DS_DUAL)
 		mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
 	if (val & TDA9840_ST_STEREO)
 		mode |= VIDEO_SOUND_STEREO;
-	
+
 	dprintk ("tda9840_getmode(): raw chip read: %d, return: %d\n",
 		 val, mode);
 	return mode;
@@ -369,7 +369,7 @@
 {
 	int update = 1;
 	int t = chip->shadow.bytes[TDA9840_SW + 1] & ~0x7e;
-	
+
 	switch (mode) {
 	case VIDEO_SOUND_MONO:
 		t |= TDA9840_MONO;
@@ -419,7 +419,7 @@
  * in 1dB steps - mute is 0x27 */
 
 
-/* 0x02 - BA in TDA9855 */ 
+/* 0x02 - BA in TDA9855 */
 /* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19)
  * in .5dB steps - 0 is 0x0E */
 
@@ -433,7 +433,7 @@
 /* Unique to TDA9855: */
 /* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf)
  * in 3dB steps - mute is 0x0 */
- 
+
 /* Unique to TDA9850: */
 /* lower 4 bits control stereo noise threshold, over which stereo turns off
  * set to values of 0x00 through 0x0f for Ster1 through Ster16 */
@@ -446,7 +446,7 @@
 #define TDA9855_LOUD	1<<5 /* Loudness, 1==off */
 #define TDA9855_SUR	1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */
 			     /* Bits 0 to 3 select various combinations
-                              * of line in and line out, only the 
+                              * of line in and line out, only the
                               * interesting ones are defined */
 #define TDA9855_EXT	1<<2 /* Selects inputs LIR and LIL.  Pins 41 & 12 */
 #define TDA9855_INT	0    /* Selects inputs LOR and LOL.  (internal) */
@@ -499,7 +499,7 @@
 {
 	int mode;
 
-	mode = ((TDA985x_STP | TDA985x_SAPP) & 
+	mode = ((TDA985x_STP | TDA985x_SAPP) &
 		chip_read(chip)) >> 4;
 	/* Add mono mode regardless of SAP and stereo */
 	/* Allows forced mono */
@@ -510,7 +510,7 @@
 {
 	int update = 1;
 	int c6 = chip->shadow.bytes[TDA985x_C6+1] & 0x3f;
-	
+
 	switch (mode) {
 	case VIDEO_SOUND_MONO:
 		c6 |= TDA985x_MONO;
@@ -538,7 +538,7 @@
 #define TDA9873_AD	0x01 /* Adjust                       */
 #define TDA9873_PT	0x02 /* Port                         */
 
-/* Subaddress 0x00: Switching Data 
+/* Subaddress 0x00: Switching Data
  * B7..B0:
  *
  * B1, B0: Input source selection
@@ -552,10 +552,10 @@
 #define TDA9873_EXT_MONO    1
 
 /*    B3, B2: output signal select
- * B4    : transmission mode 
+ * B4    : transmission mode
  *  0, 0, 1   Mono
  *  1, 0, 0   Stereo
- *  1, 1, 1   Stereo (reversed channel)    
+ *  1, 1, 1   Stereo (reversed channel)
  *  0, 0, 0   Dual AB
  *  0, 0, 1   Dual AA
  *  0, 1, 0   Dual BB
@@ -587,7 +587,7 @@
 
 #define	TDA9873_STEREO_ADJ	0x06 /* 0dB gain */
 
-/* Bits C6..C4 control FM stantard  
+/* Bits C6..C4 control FM stantard
  * C6, C5, C4
  *  0,  0,  0   B/G (PAL FM)
  *  0,  0,  1   M
@@ -609,7 +609,7 @@
 #define TDA9873_IDR_FAST 1 << 7
 
 
-/* Subaddress 0x02: Port data */ 
+/* Subaddress 0x02: Port data */
 
 /* E1, E0   free programmable ports P1/P2
     0,  0   both ports low
@@ -632,11 +632,11 @@
  */
 #define TDA9873_MOUT_MONO   0
 #define TDA9873_MOUT_FMONO  0
-#define TDA9873_MOUT_DUALA  0 
-#define TDA9873_MOUT_DUALB  1 << 3 
-#define TDA9873_MOUT_ST     1 << 4 
+#define TDA9873_MOUT_DUALA  0
+#define TDA9873_MOUT_DUALB  1 << 3
+#define TDA9873_MOUT_ST     1 << 4
 #define TDA9873_MOUT_EXTM   (1 << 4 ) & (1 << 3)
-#define TDA9873_MOUT_EXTL   1 << 5 
+#define TDA9873_MOUT_EXTL   1 << 5
 #define TDA9873_MOUT_EXTR   (1 << 5 ) & (1 << 3)
 #define TDA9873_MOUT_EXTLR  (1 << 5 ) & (1 << 4)
 #define TDA9873_MOUT_MUTE   (1 << 5 ) & (1 << 4) & (1 << 3)
@@ -670,13 +670,13 @@
 		dprintk("tda9873_setmode(): external input\n");
 		return;
 	}
-	
+
 	dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
 	dprintk("tda9873_setmode(): sw_data  = %d\n", sw_data);
 
 	switch (mode) {
 	case VIDEO_SOUND_MONO:
-		sw_data |= TDA9873_TR_MONO;   
+		sw_data |= TDA9873_TR_MONO;
 		break;
 	case VIDEO_SOUND_STEREO:
 		sw_data |= TDA9873_TR_STEREO;
@@ -871,7 +871,7 @@
 		if(nsr & 0x02) /* NSR.S/MB=1 */
 			mode |= VIDEO_SOUND_STEREO;
 #endif
-		if(nsr & 0x01) /* NSR.D/SB=1 */ 
+		if(nsr & 0x01) /* NSR.D/SB=1 */
 			mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
 	} else {
 		if(dsr & 0x02) /* DSR.IDSTE=1 */
@@ -1082,7 +1082,7 @@
 static void tda8425_setmode(struct CHIPSTATE *chip, int mode)
 {
 	int s1 = chip->shadow.bytes[TDA8425_S1+1] & 0xe1;
-	
+
 	if (mode & VIDEO_SOUND_LANG1) {
 		s1 |= TDA8425_S1_ML_SOUND_A;
 		s1 |= TDA8425_S1_STEREO_PSEUDO;
@@ -1090,10 +1090,10 @@
 	} else if (mode & VIDEO_SOUND_LANG2) {
 		s1 |= TDA8425_S1_ML_SOUND_B;
 		s1 |= TDA8425_S1_STEREO_PSEUDO;
-		
+
 	} else {
 		s1 |= TDA8425_S1_ML_STEREO;
-		
+
 		if (mode & VIDEO_SOUND_MONO)
 			s1 |= TDA8425_S1_STEREO_MONO;
 		if (mode & VIDEO_SOUND_STEREO)
@@ -1152,7 +1152,7 @@
 static int ta8874z_getmode(struct CHIPSTATE *chip)
 {
 	int val, mode;
-	
+
 	val = chip_read(chip);
 	mode = VIDEO_SOUND_MONO;
 	if (val & TA8874Z_B1){
@@ -1264,7 +1264,7 @@
 		.inputmute  = TDA9873_MUTE | TDA9873_AUTOMUTE,
 		.inputmap   = {0xa0, 0xa2, 0xa0, 0xa0, 0xc0},
 		.inputmask  = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE,
-		
+
 	},
 	{
 		.name       = "tda9874h/a",
@@ -1522,7 +1522,7 @@
 		wake_up_interruptible(&chip->wq);
 		wait_for_completion(&chip->texit);
 	}
-	
+
 	i2c_detach_client(&chip->c);
 	kfree(chip);
 	return 0;
@@ -1587,7 +1587,7 @@
 	case VIDIOCSAUDIO:
 	{
 		struct video_audio *va = arg;
-		
+
 		if (desc->flags & CHIP_HAS_VOLUME) {
 			chip->left = (min(65536 - va->balance,32768) *
 				      va->volume) / 32768;
@@ -1613,7 +1613,7 @@
 	case VIDIOCSCHAN:
 	{
 		struct video_channel *vc = arg;
-		
+
 		dprintk(KERN_DEBUG "tvaudio: VIDIOCSCHAN\n");
 		chip->norm = vc->norm;
 		break;
diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
--- a/drivers/media/video/tvmixer.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/tvmixer.c	2004-10-28 22:25:59 -07:00
@@ -82,7 +82,7 @@
 
 	if (NULL == client)
 		return -ENODEV;
-	
+
         if (cmd == SOUND_MIXER_INFO) {
                 mixer_info info;
                 strlcpy(info.id, "tv card", sizeof(info.id));
@@ -148,7 +148,7 @@
 			 va.volume) / 32768;
 		ret = v4l_to_mix2(left,right);
 		break;
-		
+
 	case MIXER_WRITE(SOUND_MIXER_BASS):
 		va.bass = mix_to_v4l(val);
 		client->driver->command(client,VIDIOCSAUDIO,&va);
@@ -324,7 +324,7 @@
 	devices[i].dev   = client;
 	printk("tvmixer: %s (%s) registered with minor %d\n",
 	       client->name,client->adapter->name,minor);
-	
+
 	return 0;
 }
 
@@ -333,7 +333,7 @@
 static int __init tvmixer_init_module(void)
 {
 	int i;
-	
+
 	for (i = 0; i < DEV_MAX; i++)
 		devices[i].minor = -1;
 
@@ -343,7 +343,7 @@
 static void __exit tvmixer_cleanup_module(void)
 {
 	int i;
-	
+
 	i2c_del_driver(&driver);
 	for (i = 0; i < DEV_MAX; i++) {
 		if (devices[i].minor != -1) {
diff -Nru a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
--- a/drivers/media/video/v4l1-compat.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/v4l1-compat.c	2004-10-28 22:25:58 -07:00
@@ -116,7 +116,7 @@
 		if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)
 			value = 65535;
 		ctrl2.id = qctrl2.id;
-		ctrl2.value = 
+		ctrl2.value =
 			(value * (qctrl2.maximum - qctrl2.minimum)
 			 + 32767)
 			/ 65535;
@@ -256,7 +256,7 @@
 
 	memset(&desc2,0,sizeof(desc2));
 	memset(&fmt2,0,sizeof(fmt2));
-	
+
 	desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
 		goto done;
@@ -326,7 +326,7 @@
 			err = 0;
 		}
 
-		memcpy(cap->name, cap2->card, 
+		memcpy(cap->name, cap2->card,
 		       min(sizeof(cap->name), sizeof(cap2->card)));
 		cap->name[sizeof(cap->name) - 1] = 0;
 		if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
@@ -383,7 +383,7 @@
 		if (0 != fbuf2.fmt.bytesperline)
 			buffer->bytesperline = fbuf2.fmt.bytesperline;
 		else {
-			buffer->bytesperline = 
+			buffer->bytesperline =
 				(buffer->width * buffer->depth + 7) & 7;
 			buffer->bytesperline >>= 3;
 		}
@@ -633,7 +633,7 @@
 		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 		if (err < 0)
 			dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
-		if (fmt2->fmt.pix.pixelformat != 
+		if (fmt2->fmt.pix.pixelformat !=
 		    palette_to_pixelformat(pict->palette)) {
 			fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
 				pict->palette);
@@ -807,7 +807,7 @@
 
 		memset(&aud2,0,sizeof(aud2));
 		memset(&tun2,0,sizeof(tun2));
-		
+
 		aud2.index = aud->audio;
 		err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
 		if (err < 0) {
@@ -815,7 +815,7 @@
 			break;
 		}
 
-		set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, 
+		set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
 				aud->volume, drv);
 		set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
 				aud->bass, drv);
@@ -863,16 +863,16 @@
 		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
 		memset(&buf2,0,sizeof(buf2));
 		memset(fmt2,0,sizeof(*fmt2));
-		
+
 		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 		if (err < 0) {
 			dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
 			break;
 		}
-		if (mm->width   != fmt2->fmt.pix.width  || 
+		if (mm->width   != fmt2->fmt.pix.width  ||
 		    mm->height  != fmt2->fmt.pix.height ||
-		    palette_to_pixelformat(mm->format) != 
+		    palette_to_pixelformat(mm->format) !=
 		    fmt2->fmt.pix.pixelformat)
 		{/* New capture format...  */
 			fmt2->fmt.pix.width = mm->width;
@@ -955,11 +955,11 @@
 	case VIDIOCGVBIFMT: /* query VBI data capture format */
 	{
 		struct vbi_format      *fmt = arg;
-		
+
 		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
 		memset(fmt2, 0, sizeof(*fmt2));
 		fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		
+
 		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 		if (err < 0) {
 			dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
@@ -979,7 +979,7 @@
 	case VIDIOCSVBIFMT:
 	{
 		struct vbi_format      *fmt = arg;
-		
+
 		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
 		memset(fmt2, 0, sizeof(*fmt2));
 
@@ -987,10 +987,10 @@
 		fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
 		fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
 		fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
-		fmt2->fmt.vbi.start[0]         = fmt->start[0]; 
-		fmt2->fmt.vbi.count[0]         = fmt->count[0]; 
-		fmt2->fmt.vbi.start[1]         = fmt->start[1]; 
-		fmt2->fmt.vbi.count[1]         = fmt->count[1]; 
+		fmt2->fmt.vbi.start[0]         = fmt->start[0];
+		fmt2->fmt.vbi.count[0]         = fmt->count[0];
+		fmt2->fmt.vbi.start[1]         = fmt->start[1];
+		fmt2->fmt.vbi.count[1]         = fmt->count[1];
 		fmt2->fmt.vbi.flags            = fmt->flags;
 		err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
 		if (err < 0) {
@@ -1014,7 +1014,7 @@
 			dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
 		break;
 	}
-	
+
 	default:
 		err = -ENOIOCTLCMD;
 		break;
diff -Nru a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
--- a/drivers/media/video/v4l2-common.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/media/video/v4l2-common.c	2004-10-28 22:25:59 -07:00
@@ -36,7 +36,7 @@
 /*
  * Video4linux 1/2 integration by Justin Schoeman
  * <justin@suntiger.ee.up.ac.za>
- * 2.4 PROCFS support ported from 2.4 kernels by 
+ * 2.4 PROCFS support ported from 2.4 kernels by
  *  Iñaki García Etxebarria <garetxe@euskalnet.net>
  * Makefile fix by "W. Michael Petullo" <mike@flyn.org>
  * 2.4 devfs support ported from 2.4 kernels by
@@ -84,14 +84,14 @@
  *  Video Standard Operations (contributed by Michael Schimek)
  */
 
-/* This is the recommended method to deal with the framerate fields. More 
+/* This is the recommended method to deal with the framerate fields. More
    sophisticated drivers will access the fields directly. */
 unsigned int
 v4l2_video_std_fps(struct v4l2_standard *vs)
-{ 
+{
 	if (vs->frameperiod.numerator > 0)
-		return (((vs->frameperiod.denominator << 8) / 
-			 vs->frameperiod.numerator) + 
+		return (((vs->frameperiod.denominator << 8) /
+			 vs->frameperiod.numerator) +
 			(1 << 7)) / (1 << 8);
 	return 0;
 }
@@ -132,7 +132,7 @@
 	memset(global,0,sizeof(*global));
 	return 0;
 }
-	
+
 int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
 		     enum v4l2_priority new)
 {
diff -Nru a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
--- a/drivers/media/video/video-buf.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/media/video/video-buf.c	2004-10-28 22:25:58 -07:00
@@ -1,5 +1,5 @@
 /*
- * $Id: video-buf.c,v 1.12 2004/10/11 14:53:13 kraxel Exp $
+ * $Id: video-buf.c,v 1.13 2004/10/13 10:39:00 kraxel Exp $
  *
  * generic helper functions for video4linux capture buffers, to handle
  * memory management and PCI DMA.  Right now bttv + saa7134 use it.
@@ -9,7 +9,7 @@
  * into PAGE_SIZE chunks).  They also assume the driver does not need
  * to touch the video data (thus it is probably not useful for USB 1.1
  * as data often must be uncompressed by the drivers).
- * 
+ *
  * (c) 2001-2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
  *
  * This program is free software; you can redistribute it and/or modify
@@ -66,7 +66,7 @@
 		sglist[i].length = PAGE_SIZE;
 	}
 	return sglist;
-	
+
  err:
 	kfree(sglist);
 	return NULL;
@@ -193,7 +193,7 @@
 {
 	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
 	BUG_ON(0 == dma->nr_pages);
-	
+
 	if (dma->pages) {
 		dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages,
 						   dma->offset);
@@ -289,7 +289,7 @@
 {
 	int retval = 0;
 	DECLARE_WAITQUEUE(wait, current);
-	
+
 	MAGIC_CHECK(vb->magic,MAGIC_BUFFER);
 	add_wait_queue(&vb->done, &wait);
 	while (vb->state == STATE_ACTIVE || vb->state == STATE_QUEUED) {
@@ -355,7 +355,7 @@
 	err = videobuf_dma_pci_map(pci,&vb->dma);
 	if (0 != err)
 		return err;
-		
+
 	return 0;
 }
 
@@ -383,11 +383,11 @@
 	INIT_LIST_HEAD(&q->stream);
 }
 
-int 
+int
 videobuf_queue_is_busy(struct videobuf_queue *q)
 {
 	int i;
-	
+
 	if (q->streaming) {
 		dprintk(1,"busy: streaming active\n");
 		return 1;
@@ -636,7 +636,7 @@
 	retval = q->ops->buf_prepare(priv,buf,field);
 	if (0 != retval)
 		goto done;
-	
+
 	list_add_tail(&buf->stream,&q->stream);
 	if (q->streaming) {
 		spin_lock_irqsave(q->irqlock,flags);
@@ -644,7 +644,7 @@
 		spin_unlock_irqrestore(q->irqlock,flags);
 	}
 	retval = 0;
-	
+
  done:
 	up(&q->lock);
 	return retval;
@@ -656,7 +656,7 @@
 {
 	struct videobuf_buffer *buf;
 	int retval;
-	
+
 	down(&q->lock);
 	retval = -EBUSY;
 	if (q->reading)
@@ -697,7 +697,7 @@
 	struct list_head *list;
 	unsigned long flags;
 	int retval;
-	
+
 	down(&q->lock);
 	retval = -EBUSY;
 	if (q->reading)
@@ -756,7 +756,7 @@
 	retval = q->ops->buf_prepare(priv,q->read_buf,field);
 	if (0 != retval)
 		goto done;
-	
+
         /* start capture & wait */
 	spin_lock_irqsave(q->irqlock,flags);
 	q->ops->buf_queue(priv,q->read_buf);
@@ -890,7 +890,7 @@
 void videobuf_read_stop(void *priv, struct videobuf_queue *q)
 {
 	int i;
-	
+
 	videobuf_queue_cancel(priv,q);
 	INIT_LIST_HEAD(&q->stream);
 	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
@@ -910,7 +910,7 @@
 	unsigned int *fc, bytes;
 	int err, retval;
 	unsigned long flags;
-	
+
 	dprintk(2,"%s\n",__FUNCTION__);
 	down(&q->lock);
 	retval = -EBUSY;
@@ -950,7 +950,7 @@
 				*fc = q->read_buf->field_count >> 1;
 				dprintk(1,"vbihack: %d\n",*fc);
 			}
-			
+
 			/* copy stuff */
 			bytes = count;
 			if (bytes > q->read_buf->size - q->read_off)
diff -Nru a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
--- a/drivers/misc/ibmasm/ibmasmfs.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/misc/ibmasm/ibmasmfs.c	2004-10-28 22:25:59 -07:00
@@ -173,13 +173,8 @@
 {
 	struct dentry *dentry;
 	struct inode *inode;
-	struct qstr qname;
 
-	qname.name = name;
-	qname.len = strlen (name);
-	qname.hash = full_name_hash(name, qname.len);
-
-	dentry = d_alloc(parent, &qname);
+	dentry = d_alloc_name(parent, name);
 	if (!dentry)
 		return NULL;
 
@@ -202,12 +197,8 @@
 {
 	struct dentry *dentry;
 	struct inode *inode;
-	struct qstr qname;
 
-	qname.name = name;
-	qname.len = strlen (name);
-	qname.hash = full_name_hash(name, qname.len);
-	dentry = d_alloc(parent, &qname);
+	dentry = d_alloc_name(parent, name);
 	if (!dentry)
 		return NULL;
 
diff -Nru a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
--- a/drivers/mmc/mmc_block.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/mmc/mmc_block.c	2004-10-28 22:25:59 -07:00
@@ -200,6 +200,9 @@
 		}
 		brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
 
+		brq.data.sg = mq->sg;
+		brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
+
 		mmc_wait_for_req(card->host, &brq.mrq);
 		if (brq.cmd.error) {
 			printk(KERN_ERR "%s: error %d sending read/write command\n",
diff -Nru a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
--- a/drivers/mmc/mmc_queue.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/mmc/mmc_queue.c	2004-10-28 22:25:58 -07:00
@@ -80,7 +80,7 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (!blk_queue_plugged(q))
 			mq->req = req = elv_next_request(q);
-		spin_unlock(q->queue_lock);
+		spin_unlock_irq(q->queue_lock);
 
 		if (!req) {
 			if (mq->flags & MMC_QUEUE_EXIT)
@@ -147,19 +147,31 @@
 	mq->queue->queuedata = mq;
 	mq->req = NULL;
 
+	mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
+			 GFP_KERNEL);
+	if (!mq->sg) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
 	init_completion(&mq->thread_complete);
 	init_waitqueue_head(&mq->thread_wq);
 	init_MUTEX(&mq->thread_sem);
 
 	ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL);
-	if (ret < 0) {
-		blk_cleanup_queue(mq->queue);
-	} else {
+	if (ret >= 0) {
 		wait_for_completion(&mq->thread_complete);
 		init_completion(&mq->thread_complete);
 		ret = 0;
+		goto out;
 	}
 
+ cleanup:
+	kfree(mq->sg);
+	mq->sg = NULL;
+
+	blk_cleanup_queue(mq->queue);
+ out:
 	return ret;
 }
 EXPORT_SYMBOL(mmc_init_queue);
@@ -169,6 +181,10 @@
 	mq->flags |= MMC_QUEUE_EXIT;
 	wake_up(&mq->thread_wq);
 	wait_for_completion(&mq->thread_complete);
+
+	kfree(mq->sg);
+	mq->sg = NULL;
+
 	blk_cleanup_queue(mq->queue);
 
 	mq->card = NULL;
diff -Nru a/drivers/mmc/mmc_queue.h b/drivers/mmc/mmc_queue.h
--- a/drivers/mmc/mmc_queue.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/mmc/mmc_queue.h	2004-10-28 22:25:56 -07:00
@@ -15,6 +15,7 @@
 	int			(*issue_fn)(struct mmc_queue *, struct request *);
 	void			*data;
 	struct request_queue	*queue;
+	struct scatterlist	*sg;
 };
 
 struct mmc_io_request {
diff -Nru a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
--- a/drivers/mmc/mmci.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/mmc/mmci.c	2004-10-28 22:25:58 -07:00
@@ -501,7 +501,7 @@
 	 * We can do SGIO
 	 */
 	mmc->max_hw_segs = 16;
-	mmc->max_phys_segs = 16;
+	mmc->max_phys_segs = NR_SG;
 
 	/*
 	 * Since we only have a 16-bit data length register, we must
diff -Nru a/drivers/mmc/mmci.h b/drivers/mmc/mmci.h
--- a/drivers/mmc/mmci.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/mmc/mmci.h	2004-10-28 22:25:59 -07:00
@@ -139,7 +139,6 @@
 	struct timer_list	timer;
 	unsigned int		oldstat;
 
-	struct scatterlist	sg[NR_SG];
 	unsigned int		sg_len;
 
 	/* pio stuff */
@@ -150,14 +149,11 @@
 
 static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
 {
-	struct scatterlist *sg = host->sg;
-	struct request *req = data->req;
-
 	/*
 	 * Ideally, we want the higher levels to pass us a scatter list.
 	 */
-	host->sg_len = blk_rq_map_sg(req->q, req, sg);
-	host->sg_ptr = sg;
+	host->sg_len = data->sg_len;
+	host->sg_ptr = data->sg;
 	host->sg_off = 0;
 }
 
diff -Nru a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
--- a/drivers/mmc/pxamci.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/mmc/pxamci.c	2004-10-28 22:25:58 -07:00
@@ -44,6 +44,10 @@
 #define DBG(x...)	do { } while (0)
 #endif
 
+#define DRIVER_NAME	"pxa2xx-mci"
+
+#define NR_SG	1
+
 struct pxamci_host {
 	struct mmc_host		*mmc;
 	spinlock_t		lock;
@@ -63,9 +67,8 @@
 
 	dma_addr_t		sg_dma;
 	struct pxa_dma_desc	*sg_cpu;
+	unsigned int		dma_len;
 
-	dma_addr_t		dma_buf;
-	unsigned int		dma_size;
 	unsigned int		dma_dir;
 };
 
@@ -122,10 +125,9 @@
 static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
 {
 	unsigned int nob = data->blocks;
-	unsigned int timeout, size;
-	dma_addr_t dma;
+	unsigned int timeout;
 	u32 dcmd;
-	int i;
+	int i, len;
 
 	host->data = data;
 
@@ -152,35 +154,22 @@
 
 	dcmd |= DCMD_BURST32 | DCMD_WIDTH1;
 
-	host->dma_size = data->blocks << data->blksz_bits;
-	host->dma_buf = dma_map_single(mmc_dev(host->mmc), data->req->buffer,
-				       host->dma_size, host->dma_dir);
-
-	for (i = 0, size = host->dma_size, dma = host->dma_buf; size; i++) {
-		u32 len = size;
-
-		if (len > DCMD_LENGTH)
-			len = 0x1000;
+	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+				   host->dma_dir);
 
+	for (i = 0; i < host->dma_len; i++) {
 		if (data->flags & MMC_DATA_READ) {
 			host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
-			host->sg_cpu[i].dtadr = dma;
+			host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
 		} else {
-			host->sg_cpu[i].dsadr = dma;
+			host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]);
 			host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
 		}
-		host->sg_cpu[i].dcmd = dcmd | len;
-
-		dma += len;
-		size -= len;
-
-		if (size) {
-			host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
-						 sizeof(struct pxa_dma_desc);
-		} else {
-			host->sg_cpu[i].ddadr = DDADR_STOP;
-		}
+		host->sg_cpu[i].dcmd = dcmd | sg_dma_len(&data->sg[i]);
+		host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
+					sizeof(struct pxa_dma_desc);
 	}
+	host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP;
 	wmb();
 
 	DDADR(host->dma) = host->sg_dma;
@@ -276,8 +265,8 @@
 		return 0;
 
 	DCSR(host->dma) = 0;
-	dma_unmap_single(mmc_dev(host->mmc), host->dma_buf, host->dma_size,
-			 host->dma_dir);
+	dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+		     host->dma_dir);
 
 	if (stat & STAT_READ_TIME_OUT)
 		data->error = MMC_ERR_TIMEOUT;
@@ -429,7 +418,7 @@
 	if (!r || irq == NO_IRQ)
 		return -ENXIO;
 
-	r = request_mem_region(r->start, SZ_4K, "PXAMCI");
+	r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
 	if (!r)
 		return -EBUSY;
 
@@ -443,6 +432,17 @@
 	mmc->f_min = 312500;
 	mmc->f_max = 20000000;
 
+	/*
+	 * We can do SG-DMA, but we don't because we never know how much
+	 * data we successfully wrote to the card.
+	 */
+	mmc->max_phys_segs = NR_SG;
+
+	/*
+	 * Our hardware DMA can handle a maximum of one page per SG entry.
+	 */
+	mmc->max_seg_size = PAGE_SIZE;
+
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 	host->dma = -1;
@@ -482,13 +482,14 @@
 	pxa_gpio_mode(GPIO8_MMCCS0_MD);
 	pxa_set_cken(CKEN12_MMC, 1);
 
-	host->dma = pxa_request_dma("PXAMCI", DMA_PRIO_LOW, pxamci_dma_irq, host);
+	host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW,
+				    pxamci_dma_irq, host);
 	if (host->dma < 0) {
 		ret = -EBUSY;
 		goto out;
 	}
 
-	ret = request_irq(host->irq, pxamci_irq, 0, "PXAMCI", host);
+	ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);
 	if (ret)
 		goto out;
 
@@ -579,7 +580,7 @@
 #endif
 
 static struct device_driver pxamci_driver = {
-	.name		= "pxa2xx-mci",
+	.name		= DRIVER_NAME,
 	.bus		= &platform_bus_type,
 	.probe		= pxamci_probe,
 	.remove		= pxamci_remove,
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/3c59x.c	2004-10-28 22:25:56 -07:00
@@ -2887,7 +2887,7 @@
 }
 
 static struct ethtool_ops vortex_ethtool_ops = {
-	.get_drvinfo =		vortex_get_drvinfo,
+	.get_drvinfo		= vortex_get_drvinfo,
 };
 
 #ifdef CONFIG_PCI
diff -Nru a/drivers/net/7990.c b/drivers/net/7990.c
--- a/drivers/net/7990.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/7990.c	2004-10-28 22:25:58 -07:00
@@ -466,7 +466,7 @@
                 return -EAGAIN;
 
         res = lance_reset(dev);
-	lp->devlock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&lp->devlock);
 	netif_start_queue (dev);
 
 	return res;
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/8139too.c	2004-10-28 22:25:56 -07:00
@@ -599,10 +599,10 @@
 MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM (multicast_filter_limit, "i");
-MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM (debug, "i");
+module_param(multicast_filter_limit, int, 0);
+module_param_array(media, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
+module_param(debug, int, 0);
 MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
 MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
 MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
diff -Nru a/drivers/net/82596.c b/drivers/net/82596.c
--- a/drivers/net/82596.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/82596.c	2004-10-28 22:25:58 -07:00
@@ -1260,7 +1260,7 @@
 	lp->scb.command = 0;
 	lp->scb.cmd = I596_NULL;
 	lp->scb.rfd = I596_NULL;
-	lp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&lp->lock);
 
 	err = register_netdev(dev);
 	if (err)
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/Kconfig	2004-10-28 22:25:59 -07:00
@@ -1413,66 +1413,17 @@
 	depends on NET_PCI && PCI
 	select MII
 	---help---
-	  This driver supports Intel(R) PRO/100 family of adapters, which 
-	  includes:
-
-	  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
-	  82559                                          A56831-xxx, 
-	  A10563-xxx,
-	  A12171-xxx, 
-	  A12321-xxx, 
-	  A12320-xxx, 
-	  A12170-xxx
-	  748568-xxx
-	  748565-xxx
-	  82550       PRO/100 S Desktop Adapter          751767-xxx
-	  82559                                          748592-xxx, 
-	  A12167-xxx, 
-	  A12318-xxx, 
-	  A12317-xxx, 
-	  A12165-xxx,
-	  748569-xxx 
-	  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
-
-
+	  This driver supports Intel(R) PRO/100 family of adapters.
 	  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 123456-001 (six digits hyphen three digits). Match 
-	  this to the list of numbers above.
+	  in the format 123456-001 (six digits hyphen three digits). 
 
-	  For more information on how to identify your adapter, go to the 
-	  Adapter & Driver ID Guide at:
+	  Use the above information and the Adapter & Driver ID Guide at:
 
 	  http://support.intel.com/support/network/adapter/pro100/21397.htm
 
+          to identify the adapter.
+
 	  For the latest Intel PRO/100 network driver for Linux, see:
 
 	  http://appsr.intel.com/scripts-df/support_intel.asp
@@ -1730,7 +1681,7 @@
 	  (e.g. VT8235).
 
 	  To compile this driver as a module, choose M here. The module
-	  will be called via-rhine.
+	  will be called via-velocity.
 
 config VIA_RHINE_MMIO
 	bool "Use MMIO instead of PIO"
@@ -1742,18 +1693,6 @@
 
 	  If unsure, say Y.
 
-config VIA_VELOCITY
-	tristate "VIA Velocity support"
-	depends on NET_PCI && PCI
-	select CRC32
-	select CRC_CCITT
-	select MII
-	help
-	  If you have a VIA "Velocity" based network card say Y here.
-
-	  To compile this driver as a module, choose M here. The module
-	  will be called via-velocity.
-
 config LAN_SAA9730
 	bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
 	depends on NET_PCI && EXPERIMENTAL && MIPS
@@ -1933,29 +1872,8 @@
 	depends on PCI
 	---help---
 	  This driver supports Intel(R) PRO/1000 gigabit ethernet family of
-	  adapters, which includes:
-
-	  Controller  Adapter Name                         Board IDs
-	  ----------  ------------                         ---------
-	  82542       PRO/1000 Gigabit Server Adapter      700262-xxx,
-	  717037-xxx
-	  82543       PRO/1000 F Server Adapter            738640-xxx,
-	  A38888-xxx
-	  82543       PRO/1000 T Server Adapter            A19845-xxx,
-	  A33948-xxx
-	  82544       PRO/1000 XT Server Adapter           A51580-xxx
-	  82544       PRO/1000 XF Server Adapter           A50484-xxx
-	  82544       PRO/1000 T Desktop Adapter           A62947-xxx
-	  82540       PRO/1000 MT Desktop Adapter          A78408-xxx
-	  82541       PRO/1000 MT Desktop Adapter          C91016-xxx
-	  82545       PRO/1000 MT Server Adapter           A92165-xxx
-	  82546       PRO/1000 MT Dual Port Server Adapter A92111-xxx
-	  82545       PRO/1000 MF Server Adapter           A91622-xxx
-	  82545       PRO/1000 MF Server Adapter(LX)       A91624-xxx
-	  82546       PRO/1000 MF Dual Port Server Adapter A91620-xxx 
-
-	  For more information on how to identify your adapter, go to the
-	  Adapter & Driver ID Guide at:
+	  adapters.  For more information on how to identify your adapter, go 
+	  to the Adapter & Driver ID Guide at:
 
 	  <http://support.intel.com/support/network/adapter/pro100/21397.htm>
 
@@ -2140,6 +2058,18 @@
 	  say M here and read Documentation/kbuild/modules.txt. The module will
 	  be called sk98lin. This is recommended.
 
+config VIA_VELOCITY
+	tristate "VIA Velocity support"
+	depends on NET_PCI && PCI
+	select CRC32
+	select CRC_CCITT
+	select MII
+	help
+	  If you have a VIA "Velocity" based network card say Y here.
+
+	  To compile this driver as a module, choose M here. The module
+	  will be called via-velocity.
+
 config TIGON3
 	tristate "Broadcom Tigon3 support"
 	depends on PCI
@@ -2202,14 +2132,8 @@
 	depends on PCI
 	---help---
 	  This driver supports Intel(R) PRO/10GbE family of
-	  adapters, which includes:
-
-	  Controller  Adapter Name                           Board IDs
-	  ----------  ------------                           ---------
-	  82597EX     Intel(R) PRO/10GbE LR Server Adapter   A82505-xxx
-
-	  For more information on how to identify your adapter, go to the
-	  Adapter & Driver ID Guide at:
+	  adapters.  For more information on how to identify your adapter, go
+	  to the Adapter & Driver ID Guide at:
 
 	  <http://support.intel.com/support/network/adapter/pro100/21397.htm>
 
diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c
--- a/drivers/net/acenic.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/acenic.c	2004-10-28 22:25:58 -07:00
@@ -443,7 +443,7 @@
 MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
 
 
-static char version[] __initdata = 
+static char version[] __devinitdata = 
   "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
@@ -538,7 +538,7 @@
 	 * addresses but who gives a damn.
 	 */
 	dev->base_addr = pci_resource_start(pdev, 0);
-	ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000);
+	ap->regs = ioremap(dev->base_addr, 0x4000);
 	if (!ap->regs) {
 		printk(KERN_ERR "%s:  Unable to map I/O register, "
 		       "AceNIC %i will be disabled.\n",
@@ -631,7 +631,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i;
 
 	unregister_netdev(dev);
@@ -884,7 +884,7 @@
 /*
  * Commands are considered to be slow.
  */
-static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd)
+static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd)
 {
 	u32 idx;
 
@@ -897,10 +897,10 @@
 }
 
 
-static int __init ace_init(struct net_device *dev)
+static int __devinit ace_init(struct net_device *dev)
 {
 	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs;
 	struct ace_info *info = NULL;
 	struct pci_dev *pdev;
 	unsigned long myjif;
@@ -1318,11 +1318,10 @@
 	writel(TX_RING_BASE, &regs->WinBase);
 
 	if (ACE_IS_TIGON_I(ap)) {
-		ap->tx_ring = (struct tx_desc *)regs->Window;
-		for (i = 0; i < (TIGON_I_TX_RING_ENTRIES * 
-				 sizeof(struct tx_desc) / 4); i++) {
-			writel(0, (unsigned long)ap->tx_ring + i * 4);
-		}
+		ap->tx_ring = (struct tx_desc *) regs->Window;
+		for (i = 0; i < (TIGON_I_TX_RING_ENTRIES 
+				 * sizeof(struct tx_desc)) / sizeof(u32); i++)
+			writel(0, (void __iomem *)ap->tx_ring  + i * 4);
 
 		set_aceaddr(&info->tx_ctrl.rngptr, TX_RING_BASE);
 	} else {
@@ -1549,14 +1548,9 @@
 
 static void ace_set_rxtx_parms(struct net_device *dev, int jumbo)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
-	int board_idx;
-
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
-	board_idx = ap->board_idx;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
+	int board_idx = ap->board_idx;
 
 	if (board_idx >= 0) {
 		if (!jumbo) {
@@ -1594,7 +1588,7 @@
 {
 	struct net_device *dev = data;
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 
 	/*
 	 * We haven't received a stats update event for more than 2.5
@@ -1617,7 +1611,7 @@
 
 static void ace_tasklet(unsigned long dev)
 {
-	struct ace_private *ap = ((struct net_device *)dev)->priv;
+	struct ace_private *ap = netdev_priv((struct net_device *)dev);
 	int cur_size;
 
 	cur_size = atomic_read(&ap->cur_rx_bufs);
@@ -1675,10 +1669,9 @@
  */
 static void ace_load_std_rx_ring(struct ace_private *ap, int nr_bufs)
 {
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
-
-	regs = ap->regs;
+	
 
 	prefetchw(&ap->cur_rx_bufs);
 
@@ -1739,11 +1732,9 @@
 
 static void ace_load_mini_rx_ring(struct ace_private *ap, int nr_bufs)
 {
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
 
-	regs = ap->regs;
-
 	prefetchw(&ap->cur_mini_bufs);
 
 	idx = ap->rx_mini_skbprd;
@@ -1798,11 +1789,9 @@
  */
 static void ace_load_jumbo_rx_ring(struct ace_private *ap, int nr_bufs)
 {
-	struct ace_regs *regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	short i, idx;
 
-	regs = ap->regs;
-
 	idx = ap->rx_jumbo_skbprd;
 
 	for (i = 0; i < nr_bufs; i++) {
@@ -2082,8 +2071,7 @@
 	 * the 12.3.x Firmware - my Tigon I NICs seem to disagree!
 	 */
 	if (ACE_IS_TIGON_I(ap)) {
-		struct ace_regs *regs = ap->regs;
-		writel(idx, &regs->RxRetCsm);
+		writel(idx, &ap->regs->RxRetCsm);
 	}
 	ap->cur_rx = idx;
 
@@ -2163,16 +2151,13 @@
 
 static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
 	struct net_device *dev = (struct net_device *)dev_id;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	u32 idx;
 	u32 txcsm, rxretcsm, rxretprd;
 	u32 evtcsm, evtprd;
 
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
 	/*
 	 * In case of PCI shared interrupts or spurious interrupts,
 	 * we want to make sure it is actually our interrupt before
@@ -2325,13 +2310,10 @@
 
 static int ace_open(struct net_device *dev)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	struct cmd cmd;
 
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
 	if (!(ap->fw_running)) {
 		printk(KERN_WARNING "%s: Firmware not running!\n", dev->name);
 		return -EBUSY;
@@ -2383,8 +2365,8 @@
 
 static int ace_close(struct net_device *dev)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	struct cmd cmd;
 	unsigned long flags;
 	short i;
@@ -2396,9 +2378,7 @@
 	 */
 	netif_stop_queue(dev);
 
-	ap = netdev_priv(dev);
-	regs = ap->regs;
-
+	
 	if (ap->promisc) {
 		cmd.evt = C_SET_PROMISC_MODE;
 		cmd.code = C_C_PROMISC_DISABLE;
@@ -2433,9 +2413,11 @@
 
 		if (mapping) {
 			if (ACE_IS_TIGON_I(ap)) {
-				writel(0, &ap->tx_ring[i].addr.addrhi);
-				writel(0, &ap->tx_ring[i].addr.addrlo);
-				writel(0, &ap->tx_ring[i].flagsize);
+				struct tx_desc __iomem *tx 
+					= (struct tx_desc __iomem *) &ap->tx_ring[i];
+				writel(0, &tx->addr.addrhi);
+				writel(0, &tx->addr.addrlo);
+				writel(0, &tx->flagsize);
 			} else
 				memset(ap->tx_ring + i, 0,
 				       sizeof(struct tx_desc));
@@ -2492,11 +2474,12 @@
 #endif
 
 	if (ACE_IS_TIGON_I(ap)) {
-		writel(addr >> 32, &desc->addr.addrhi);
-		writel(addr & 0xffffffff, &desc->addr.addrlo);
-		writel(flagsize, &desc->flagsize);
+		struct tx_desc __iomem *io = (struct tx_desc __iomem *) desc;
+		writel(addr >> 32, &io->addr.addrhi);
+		writel(addr & 0xffffffff, &io->addr.addrlo);
+		writel(flagsize, &io->flagsize);
 #if ACENIC_DO_VLAN
-		writel(vlan_tag, &desc->vlanres);
+		writel(vlan_tag, &io->vlanres);
 #endif
 	} else {
 		desc->addr.addrhi = addr >> 32;
@@ -2512,9 +2495,10 @@
 static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	struct tx_desc *desc;
 	u32 idx, flagsize;
+	unsigned long maxjiff = jiffies + 3*HZ;
 
 restart:
 	idx = ap->tx_prd;
@@ -2522,10 +2506,7 @@
 	if (tx_ring_full(ap, ap->tx_ret_csm, idx))
 		goto overflow;
 
-#if MAX_SKB_FRAGS
-	if (!skb_shinfo(skb)->nr_frags)
-#endif
-	{
+	if (!skb_shinfo(skb)->nr_frags)	{
 		dma_addr_t mapping;
 		u32 vlan_tag = 0;
 
@@ -2547,9 +2528,7 @@
 			flagsize |= BD_FLG_COAL_NOW;
 
 		ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
-	}
-#if MAX_SKB_FRAGS
-	else {
+	} else {
 		dma_addr_t mapping;
 		u32 vlan_tag = 0;
 		int i, len = 0;
@@ -2604,7 +2583,6 @@
 			ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
 		}
 	}
-#endif
 
  	wmb();
  	ap->tx_prd = idx;
@@ -2624,7 +2602,7 @@
 	}
 
 	dev->trans_start = jiffies;
-	return 0;
+	return NETDEV_TX_OK;
 
 overflow:
 	/*
@@ -2643,15 +2621,22 @@
 	 * Alternative is to return with 1 not throttling queue. In this
 	 * case loop becomes longer, no more useful effects.
 	 */
-	barrier();
-	goto restart;
+	if (time_before(jiffies, maxjiff)) {
+		barrier();
+		cpu_relax();
+		goto restart;
+	}
+	
+	/* The ring is stuck full. */
+	printk(KERN_WARNING "%s: Transmit ring stuck full\n", dev->name);
+	return NETDEV_TX_BUSY;
 }
 
 
 static int ace_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 
 	if (new_mtu > ACE_JUMBO_MTU)
 		return -EINVAL;
@@ -2688,7 +2673,7 @@
 static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	u32 link;
 
 	memset(ecmd, 0, sizeof(struct ethtool_cmd));
@@ -2741,7 +2726,7 @@
 static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	u32 link, speed;
 
 	link = readl(&regs->GigLnkState);
@@ -2821,8 +2806,9 @@
  */
 static int ace_set_mac_addr(struct net_device *dev, void *p)
 {
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	struct sockaddr *addr=p;
-	struct ace_regs *regs;
 	u8 *da;
 	struct cmd cmd;
 
@@ -2833,7 +2819,6 @@
 
 	da = (u8 *)dev->dev_addr;
 
-	regs = ((struct ace_private *)netdev_priv(dev))->regs;
 	writel(da[0] << 8 | da[1], &regs->MacAddrHi);
 	writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5],
 	       &regs->MacAddrLo);
@@ -2850,7 +2835,7 @@
 static void ace_set_multicast_list(struct net_device *dev)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_regs *regs = ap->regs;
+	struct ace_regs __iomem *regs = ap->regs;
 	struct cmd cmd;
 
 	if ((dev->flags & IFF_ALLMULTI) && !(ap->mcast_all)) {
@@ -2904,8 +2889,8 @@
 static struct net_device_stats *ace_get_stats(struct net_device *dev)
 {
 	struct ace_private *ap = netdev_priv(dev);
-	struct ace_mac_stats *mac_stats =
-		(struct ace_mac_stats *)ap->regs->Stats;
+	struct ace_mac_stats __iomem *mac_stats =
+		(struct ace_mac_stats __iomem *)ap->regs->Stats;
 
 	ap->stats.rx_missed_errors = readl(&mac_stats->drop_space);
 	ap->stats.multicast = readl(&mac_stats->kept_mc);
@@ -2915,10 +2900,10 @@
 }
 
 
-static void __init ace_copy(struct ace_regs *regs, void *src,
+static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
 			    u32 dest, int size)
 {
-	unsigned long tdest;
+	void __iomem *tdest;
 	u32 *wsrc;
 	short tsize, i;
 
@@ -2928,7 +2913,7 @@
 	while (size > 0) {
 		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
 			    min_t(u32, size, ACE_WINDOW_SIZE));
-		tdest = (unsigned long)&regs->Window +
+		tdest = (void __iomem *) &regs->Window + 
 			(dest & (ACE_WINDOW_SIZE - 1));
 		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
 		/*
@@ -2948,9 +2933,9 @@
 }
 
 
-static void __init ace_clear(struct ace_regs *regs, u32 dest, int size)
+static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
 {
-	unsigned long tdest;
+	void __iomem *tdest;
 	short tsize = 0, i;
 
 	if (size <= 0)
@@ -2959,7 +2944,7 @@
 	while (size > 0) {
 		tsize = min_t(u32, ((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
 				min_t(u32, size, ACE_WINDOW_SIZE));
-		tdest = (unsigned long)&regs->Window +
+		tdest = (void __iomem *) &regs->Window + 
 			(dest & (ACE_WINDOW_SIZE - 1));
 		writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
 
@@ -2981,13 +2966,10 @@
  * This operation requires the NIC to be halted and is performed with
  * interrupts disabled and with the spinlock hold.
  */
-int __init ace_load_firmware(struct net_device *dev)
+int __devinit ace_load_firmware(struct net_device *dev)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
-
-	ap = netdev_priv(dev);
-	regs = ap->regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 
 	if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
 		printk(KERN_ERR "%s: trying to download firmware while the "
@@ -3035,7 +3017,7 @@
  * Thanks to Stevarino Webinski for helping tracking down the bugs in the
  * code i2c readout code by beta testing all my hacks.
  */
-static void __init eeprom_start(struct ace_regs *regs)
+static void __devinit eeprom_start(struct ace_regs __iomem *regs)
 {
 	u32 local;
 
@@ -3064,7 +3046,7 @@
 }
 
 
-static void __init eeprom_prep(struct ace_regs *regs, u8 magic)
+static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
 {
 	short i;
 	u32 local;
@@ -3101,7 +3083,7 @@
 }
 
 
-static int __init eeprom_check_ack(struct ace_regs *regs)
+static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
 {
 	int state;
 	u32 local;
@@ -3129,7 +3111,7 @@
 }
 
 
-static void __init eeprom_stop(struct ace_regs *regs)
+static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
 {
 	u32 local;
 
@@ -3164,11 +3146,11 @@
 /*
  * Read a whole byte from the EEPROM.
  */
-static int __init read_eeprom_byte(struct net_device *dev,
+static int __devinit read_eeprom_byte(struct net_device *dev,
 				   unsigned long offset)
 {
-	struct ace_private *ap;
-	struct ace_regs *regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 	unsigned long flags;
 	u32 local;
 	int result = 0;
@@ -3179,9 +3161,6 @@
 		result = -ENODEV;
 		goto out;
 	}
-
-	ap = netdev_priv(dev);
-	regs = ap->regs;
 
 	/*
 	 * Don't take interrupts on this CPU will bit banging
diff -Nru a/drivers/net/acenic.h b/drivers/net/acenic.h
--- a/drivers/net/acenic.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/acenic.h	2004-10-28 22:25:58 -07:00
@@ -10,11 +10,6 @@
  */
 #define USE_TX_COAL_NOW	 0
 
-#ifndef MAX_SKB_FRAGS
-#define MAX_SKB_FRAGS 0
-#endif
-
-
 /*
  * Addressing:
  *
@@ -638,7 +633,7 @@
 struct ace_private
 {
 	struct ace_info		*info;
-	struct ace_regs		*regs;		/* register base */
+	struct ace_regs	__iomem	*regs;		/* register base */
 	struct ace_skb		*skb;
 	dma_addr_t		info_dma;	/* 32/64 bit */
 
@@ -712,13 +707,7 @@
 }
 
 #define tx_free(ap) 		tx_space((ap)->tx_ret_csm, (ap)->tx_prd, ap)
-
-#if MAX_SKB_FRAGS
 #define tx_ring_full(ap, csm, prd)	(tx_space(ap, csm, prd) <= TX_RESERVED)
-#else
-#define tx_ring_full			0
-#endif
-
 
 static inline void set_aceaddr(aceaddr *aa, dma_addr_t addr)
 {
@@ -729,7 +718,7 @@
 }
 
 
-static inline void ace_set_txprd(struct ace_regs *regs,
+static inline void ace_set_txprd(struct ace_regs __iomem *regs,
 				 struct ace_private *ap, u32 value)
 {
 #ifdef INDEX_DEBUG
@@ -750,8 +739,8 @@
 
 static inline void ace_mask_irq(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
-	struct ace_regs *regs = ap->regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
 
 	if (ACE_IS_TIGON_I(ap))
 		writel(1, &regs->MaskInt);
@@ -764,8 +753,8 @@
 
 static inline void ace_unmask_irq(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
-	struct ace_regs *regs = ap->regs;
+	struct ace_private *ap = netdev_priv(dev);
+	struct ace_regs __iomem *regs = ap->regs;
  
 	if (ACE_IS_TIGON_I(ap))
 		writel(0, &regs->MaskInt);
diff -Nru a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h
--- a/drivers/net/acenic_firmware.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/acenic_firmware.h	2004-10-28 22:25:58 -07:00
@@ -23,7 +23,7 @@
 #define tigonFwRodata NULL
 #else
 /* Generated by genfw.c */
-static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
+static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = {
 0x10000003, 
 0x0, 0xd, 0xd, 0x3c1d0001, 
 0x8fbd5c54, 0x3a0f021, 0x3c100000, 0x26104000, 
diff -Nru a/drivers/net/atarilance.c b/drivers/net/atarilance.c
--- a/drivers/net/atarilance.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/atarilance.c	2004-10-28 22:25:59 -07:00
@@ -606,7 +606,7 @@
 		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );
 	}
 
-	lp->devlock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&lp->devlock);
 
 	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */
 	for( i = 0; i < 6; i++ )
diff -Nru a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
--- a/drivers/net/bonding/bond_main.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/bonding/bond_main.c	2004-10-28 22:25:59 -07:00
@@ -4700,6 +4700,7 @@
 module_init(bonding_init);
 module_exit(bonding_exit);
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
 MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others");
 MODULE_SUPPORTED_DEVICE("most ethernet devices");
diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c
--- a/drivers/net/defxx.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/defxx.c	2004-10-28 22:25:56 -07:00
@@ -19,7 +19,7 @@
  *   LVS	Lawrence V. Stefani <lstefani@yahoo.com>
  *
  * Maintainers:
- *   macro	Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ *   macro	Maciej W. Rozycki <macro@linux-mips.org>
  *
  * Credits:
  *   I'd like to thank Patricia Cross for helping me get started with
@@ -190,6 +190,7 @@
  *		Feb 2001			Skb allocation fixes
  *		Feb 2001	davej		PCI enable cleanups.
  *		04 Aug 2003	macro		Converted to the DMA API.
+ *		14 Aug 2004	macro		Fix device names reported.
  */
 
 /* Include files */
@@ -214,12 +215,14 @@
 
 #include "defxx.h"
 
-/* Version information string - should be updated prior to each new release!!! */
+/* Version information string should be updated prior to each new release!  */
+#define DRV_NAME "defxx"
+#define DRV_VERSION "v1.07"
+#define DRV_RELDATE "2004/08/14"
 
 static char version[] __devinitdata =
-	"defxx.c:v1.06 2003/08/04  Lawrence V. Stefani and others\n";
-
-#define DRV_NAME "defxx"
+	DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
+	"  Lawrence V. Stefani and others\n";
 
 #define DYNAMIC_BUFFERS 1
 
@@ -235,7 +238,7 @@
 static void		dfx_bus_init(struct net_device *dev);
 static void		dfx_bus_config_check(DFX_board_t *bp);
 
-static int		dfx_driver_init(struct net_device *dev);
+static int		dfx_driver_init(struct net_device *dev, const char *print_name);
 static int		dfx_adap_init(DFX_board_t *bp, int get_buffers);
 
 static int		dfx_open(struct net_device *dev);
@@ -404,24 +407,25 @@
  */
 static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr)
 {
+	static int version_disp;
+	char *print_name = DRV_NAME;
 	struct net_device *dev;
 	DFX_board_t	  *bp;			/* board pointer */
 	int alloc_size;				/* total buffer size used */
 	int err;
 
-#ifndef MODULE
-	static int version_disp;
-
-	if (!version_disp)	/* display version info if adapter is found */
-	{
+	if (!version_disp) {	/* display version info if adapter is found */
 		version_disp = 1;	/* set display flag to TRUE so that */
 		printk(version);	/* we only display this string ONCE */
 	}
-#endif
+
+	if (pdev != NULL)
+		print_name = pdev->slot_name;
 
 	dev = alloc_fddidev(sizeof(*bp));
 	if (!dev) {
-		printk (KERN_ERR "defxx: unable to allocate fddidev, aborting\n");
+		printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n",
+		       print_name);
 		return -ENOMEM;
 	}
 
@@ -437,9 +441,12 @@
 
 	bp = dev->priv;
 
-	if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, DRV_NAME)) {
-		printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n",
-			DRV_NAME, PFI_K_CSR_IO_LEN, ioaddr);
+	if (!request_region(ioaddr,
+			    pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN,
+			    print_name)) {
+		printk(KERN_ERR "%s: Cannot reserve I/O resource "
+		       "0x%x @ 0x%lx, aborting\n", print_name,
+		       pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, ioaddr);
 		err = -EBUSY;
 		goto err_out;
 	}
@@ -468,7 +475,7 @@
 		pci_set_master (pdev);
 	}
 
-	if (dfx_driver_init(dev) != DFX_K_SUCCESS) {
+	if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) {
 		err = -ENODEV;
 		goto err_out_region;
 	}
@@ -477,6 +484,7 @@
 	if (err)
 		goto err_out_kfree;
 
+	printk("%s: registered as %s\n", print_name, dev->name);
 	return 0;
 
 err_out_kfree:
@@ -770,6 +778,7 @@
  *       
  * Arguments:
  *   dev - pointer to device information
+ *   print_name - printable device name
  *
  * Functional Description:
  *   This function allocates additional resources such as the host memory
@@ -792,7 +801,8 @@
  *   returning from this routine.
  */
 
-static int __devinit dfx_driver_init(struct net_device *dev)
+static int __devinit dfx_driver_init(struct net_device *dev,
+				     const char *print_name)
 {
 	DFX_board_t *bp = dev->priv;
 	int			alloc_size;			/* total buffer size needed */
@@ -841,26 +851,20 @@
 
 	/*  Read the factory MAC address from the adapter then save it */
 
-	if (dfx_hw_port_ctrl_req(bp,
-							PI_PCTRL_M_MLA,
-							PI_PDATA_A_MLA_K_LO,
-							0,
-							&data) != DFX_K_SUCCESS)
-		{
-		printk("%s: Could not read adapter factory MAC address!\n", dev->name);
+	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_LO, 0,
+				 &data) != DFX_K_SUCCESS) {
+		printk("%s: Could not read adapter factory MAC address!\n",
+		       print_name);
 		return(DFX_K_FAILURE);
-		}
+	}
 	memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32));
 
-	if (dfx_hw_port_ctrl_req(bp,
-							PI_PCTRL_M_MLA,
-							PI_PDATA_A_MLA_K_HI,
-							0,
-							&data) != DFX_K_SUCCESS)
-		{
-		printk("%s: Could not read adapter factory MAC address!\n", dev->name);
+	if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
+				 &data) != DFX_K_SUCCESS) {
+		printk("%s: Could not read adapter factory MAC address!\n",
+		       print_name);
 		return(DFX_K_FAILURE);
-		}
+	}
 	memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16));
 
 	/*
@@ -872,27 +876,19 @@
 
 	memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
 	if (bp->bus_type == DFX_BUS_TYPE_EISA)
-		printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-				dev->name,
-				dev->base_addr,
-				dev->irq,
-				dev->dev_addr[0],
-				dev->dev_addr[1],
-				dev->dev_addr[2],
-				dev->dev_addr[3],
-				dev->dev_addr[4],
-				dev->dev_addr[5]);
+		printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, "
+		       "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+		       print_name, dev->base_addr, dev->irq,
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5]);
 	else
-		printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-				dev->name,
-				dev->base_addr,
-				dev->irq,
-				dev->dev_addr[0],
-				dev->dev_addr[1],
-				dev->dev_addr[2],
-				dev->dev_addr[3],
-				dev->dev_addr[4],
-				dev->dev_addr[5]);
+		printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, "
+		       "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+		       print_name, dev->base_addr, dev->irq,
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5]);
 
 	/*
 	 * Get memory for descriptor block, consumer block, and other buffers
@@ -909,11 +905,11 @@
 					(PI_ALIGN_K_DESC_BLK - 1);
 	bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size,
 						     &bp->kmalloced_dma);
-	if (top_v == NULL)
-		{
-		printk("%s: Could not allocate memory for host buffers and structures!\n", dev->name);
+	if (top_v == NULL) {
+		printk("%s: Could not allocate memory for host buffers "
+		       "and structures!\n", print_name);
 		return(DFX_K_FAILURE);
-		}
+	}
 	memset(top_v, 0, alloc_size);	/* zero out memory before continuing */
 	top_p = bp->kmalloced_dma;	/* get physical address of buffer */
 
@@ -970,14 +966,20 @@
 
 	/* Display virtual and physical addresses if debug driver */
 
-	DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",				dev->name, (long)bp->descr_block_virt,	bp->descr_block_phys);
-	DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",			dev->name, (long)bp->cmd_req_virt,		bp->cmd_req_phys);
-	DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",			dev->name, (long)bp->cmd_rsp_virt,		bp->cmd_rsp_phys);
-	DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",			dev->name, (long)bp->rcv_block_virt,	bp->rcv_block_phys);
-	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",				dev->name, (long)bp->cons_block_virt,	bp->cons_block_phys);
+	DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",
+		   print_name,
+		   (long)bp->descr_block_virt, bp->descr_block_phys);
+	DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys);
+	DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys);
+	DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys);
+	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",
+		   print_name, (long)bp->cons_block_virt, bp->cons_block_phys);
 
 	return(DFX_K_SUCCESS);
-	}
+}
 
 
 /*
@@ -2668,12 +2670,12 @@
  
 static void my_skb_align(struct sk_buff *skb, int n)
 {
-	unsigned long x=(unsigned long)skb->data;	
+	unsigned long x = (unsigned long)skb->data;
 	unsigned long v;
 	
-	v=(x+n-1)&~(n-1);	/* Where we want to be */
+	v = ALIGN(x, n);	/* Where we want to be */
 	
-	skb_reserve(skb, v-x);
+	skb_reserve(skb, v - x);
 }
 
 
@@ -3428,11 +3430,6 @@
 {
 	int rc_pci, rc_eisa;
 
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-	printk(version);
-#endif
-
 	rc_pci = pci_module_init(&dfx_driver);
 	if (rc_pci >= 0) dfx_have_pci = 1;
 	
@@ -3453,6 +3450,9 @@
 
 module_init(dfx_init);
 module_exit(dfx_cleanup);
+MODULE_AUTHOR("Lawrence V. Stefani");
+MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver "
+		   DRV_VERSION " " DRV_RELDATE);
 MODULE_LICENSE("GPL");
 
 
diff -Nru a/drivers/net/defxx.h b/drivers/net/defxx.h
--- a/drivers/net/defxx.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/defxx.h	2004-10-28 22:25:58 -07:00
@@ -16,7 +16,7 @@
  *   LVS	Lawrence V. Stefani <lstefani@yahoo.com>
  *
  * Maintainers:
- *   macro	Maciej W. Rozycki <macro@ds2.pg.gda.pl>
+ *   macro	Maciej W. Rozycki <macro@linux-mips.org>
  *
  * Modification History:
  *		Date		Name	Description
diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c
--- a/drivers/net/depca.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/depca.c	2004-10-28 22:25:58 -07:00
@@ -666,7 +666,7 @@
 		outb(nicsr, DEPCA_NICSR);
 	}
 
-	lp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&lp->lock);
 	sprintf(lp->adapter_name, "%s (%s)",
 		depca_signature[lp->adapter], device->bus_id);
 	status = -EBUSY;
diff -Nru a/drivers/net/dummy.c b/drivers/net/dummy.c
--- a/drivers/net/dummy.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/dummy.c	2004-10-28 22:25:58 -07:00
@@ -77,7 +77,7 @@
 
 static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct net_device_stats *stats = dev->priv;
+	struct net_device_stats *stats = netdev_priv(dev);
 
 	stats->tx_packets++;
 	stats->tx_bytes+=skb->len;
@@ -88,7 +88,7 @@
 
 static struct net_device_stats *dummy_get_stats(struct net_device *dev)
 {
-	return dev->priv;
+	return netdev_priv(dev);
 }
 
 static struct net_device **dummies;
diff -Nru a/drivers/net/e100.c b/drivers/net/e100.c
--- a/drivers/net/e100.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/e100.c	2004-10-28 22:25:59 -07:00
@@ -154,8 +154,8 @@
 
 
 #define DRV_NAME		"e100"
-#define DRV_EXT			"-NAPI"
-#define DRV_VERSION		"3.0.27-k2"DRV_EXT
+#define DRV_EXT		"-NAPI"
+#define DRV_VERSION		"3.2.3-k2"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2004 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -574,13 +574,21 @@
 
 static inline void e100_enable_irq(struct nic *nic)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&nic->cmd_lock, flags);
 	writeb(irq_mask_none, &nic->csr->scb.cmd_hi);
+	spin_unlock_irqrestore(&nic->cmd_lock, flags);
 	e100_write_flush(nic);
 }
 
 static inline void e100_disable_irq(struct nic *nic)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&nic->cmd_lock, flags);
 	writeb(irq_mask_all, &nic->csr->scb.cmd_hi);
+	spin_unlock_irqrestore(&nic->cmd_lock, flags);
 	e100_write_flush(nic);
 }
 
@@ -595,16 +603,6 @@
 	writel(software_reset, &nic->csr->port);
 	e100_write_flush(nic); udelay(20);
 
-	/* TCO workaround - 82559 and greater */
-	if(nic->mac >= mac_82559_D101M) {
-		/* Issue a redundant CU load base without setting
-		 * general pointer, and without waiting for scb to
-		 * clear.  This gets us into post-driver.  Finally,
-		 * wait 20 msec for reset to take effect. */
-		writeb(cuc_load_base, &nic->csr->scb.cmd_lo);
-		mdelay(20);
-	}
-
 	/* Mask off our interrupt line - it's unmasked after reset */
 	e100_disable_irq(nic);
 }
@@ -1253,8 +1251,13 @@
 	mii_check_link(&nic->mii);
 
 	/* Software generated interrupt to recover from (rare) Rx
-	 * allocation failure */
-	writeb(irq_sw_gen, &nic->csr->scb.cmd_hi);
+	* allocation failure.
+	* Unfortunately have to use a spinlock to not re-enable interrupts
+	* accidentally, due to hardware that shares a register between the
+	* interrupt mask bit and the SW Interrupt generation bit */
+	spin_lock_irq(&nic->cmd_lock);
+	writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
+	spin_unlock_irq(&nic->cmd_lock);
 	e100_write_flush(nic);
 
 	e100_update_stats(nic);
@@ -1304,6 +1307,7 @@
 	switch(err) {
 	case -ENOSPC:
 		/* We queued the skb, but now we're out of space. */
+		DPRINTK(TX_ERR, DEBUG, "No space for CB\n");
 		netif_stop_queue(netdev);
 		break;
 	case -ENOMEM:
@@ -1424,14 +1428,12 @@
 #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
 static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
 {
-	unsigned int rx_offset = 2; /* u32 align protocol headers */
-
-	if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + rx_offset)))
+	if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN)))
 		return -ENOMEM;
 
 	/* Align, init, and map the RFD. */
 	rx->skb->dev = nic->netdev;
-	skb_reserve(rx->skb, rx_offset);
+	skb_reserve(rx->skb, NET_IP_ALIGN);
 	memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd));
 	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
 		RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
@@ -1470,7 +1472,7 @@
 
 	/* If data isn't ready, nothing to indicate */
 	if(unlikely(!(rfd_status & cb_complete)))
-       		return -EAGAIN;
+		return -EAGAIN;
 
 	/* Get actual data size */
 	actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
@@ -1762,7 +1764,7 @@
 
 	if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
 	   skb->data, ETH_DATA_LEN))
-       		err = -EAGAIN;
+		err = -EAGAIN;
 
 err_loopback_none:
 	mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
@@ -1955,12 +1957,17 @@
 	struct param_range *rfds = &nic->params.rfds;
 	struct param_range *cbs = &nic->params.cbs;
 
+	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 
+		return -EINVAL;
+
 	if(netif_running(netdev))
 		e100_down(nic);
 	rfds->count = max(ring->rx_pending, rfds->min);
 	rfds->count = min(rfds->count, rfds->max);
 	cbs->count = max(ring->tx_pending, cbs->min);
 	cbs->count = min(cbs->count, cbs->max);
+	DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n",
+	        rfds->count, cbs->count);
 	if(netif_running(netdev))
 		e100_up(nic);
 
@@ -2172,6 +2179,7 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	netdev->poll_controller = e100_netpoll;
 #endif
+	strcpy(netdev->name, pci_name(pdev));
 
 	nic = netdev_priv(netdev);
 	nic->netdev = netdev;
@@ -2255,6 +2263,7 @@
 
 	pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
 
+	strcpy(netdev->name, "eth%d");
 	if((err = register_netdev(netdev))) {
 		DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
 		goto err_out_free;
@@ -2351,7 +2360,7 @@
 		printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
 		printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
 	}
-        return pci_module_init(&e100_driver);
+	return pci_module_init(&e100_driver);
 }
 
 static void __exit e100_cleanup_module(void)
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- a/drivers/net/e1000/e1000.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/e1000/e1000.h	2004-10-28 22:25:56 -07:00
@@ -64,7 +64,6 @@
 #include <linux/udp.h>
 #include <net/pkt_sched.h>
 #include <linux/list.h>
-#include <linux/rtnetlink.h>
 #include <linux/reboot.h>
 #ifdef NETIF_F_TSO
 #include <net/checksum.h>
@@ -73,7 +72,6 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
-#include <linux/moduleparam.h>
 
 #define BAR_0		0
 #define BAR_1		1
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/e1000/e1000_ethtool.c	2004-10-28 22:25:58 -07:00
@@ -249,7 +249,8 @@
 			e1000_reset(adapter);
 	}
 	else
-		return e1000_force_mac_fc(hw);
+		return ((hw->media_type == e1000_media_type_fiber) ?
+			e1000_setup_link(hw) : e1000_force_mac_fc(hw));
 	
 	return 0;
 }
@@ -592,6 +593,9 @@
 	tx_old = adapter->tx_ring;
 	rx_old = adapter->rx_ring;
 
+	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 
+		return -EINVAL;
+
 	if(netif_running(adapter->netdev))
 		e1000_down(adapter);
 
@@ -637,7 +641,6 @@
 	return err;
 }
 
-
 #define REG_PATTERN_TEST(R, M, W)                                              \
 {                                                                              \
 	uint32_t pat, value;                                                   \
@@ -1017,8 +1020,8 @@
 		struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
 		struct sk_buff *skb;
 
-		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
-				     GFP_KERNEL))) {
+		if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, 
+				GFP_KERNEL))) {
 			ret_val = 6;
 			goto err_nomem;
 		}
@@ -1442,6 +1445,8 @@
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
 	case E1000_DEV_ID_82546EB_QUAD_COPPER:
+	case E1000_DEV_ID_82545EM_FIBER:
+	case E1000_DEV_ID_82545EM_COPPER:
 		wol->supported = 0;
 		wol->wolopts   = 0;
 		return;
diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
--- a/drivers/net/e1000/e1000_hw.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/e1000/e1000_hw.c	2004-10-28 22:25:59 -07:00
@@ -65,6 +65,7 @@
 static void e1000_standby_eeprom(struct e1000_hw *hw);
 static int32_t e1000_id_led_init(struct e1000_hw * hw);
 static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
+static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);
 static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
 
 /* IGP cable length table */
@@ -1594,6 +1595,15 @@
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
         if(ret_val)
             return ret_val;
+
+        if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
+           (!hw->autoneg) &&
+           (hw->forced_speed_duplex == e1000_10_full ||
+            hw->forced_speed_duplex == e1000_10_half)) {
+            ret_val = e1000_polarity_reversal_workaround(hw);
+            if(ret_val)
+                return ret_val;
+        }
     }
     return E1000_SUCCESS;
 }
@@ -1983,6 +1993,7 @@
     uint32_t ctrl;
     uint32_t status;
     uint32_t rctl;
+    uint32_t icr;
     uint32_t signal = 0;
     int32_t ret_val;
     uint16_t phy_data;
@@ -2032,6 +2043,25 @@
              * link-up */
             e1000_check_downshift(hw);
 
+            /* If we are on 82544 or 82543 silicon and speed/duplex
+             * are forced to 10H or 10F, then we will implement the polarity
+             * reversal workaround.  We disable interrupts first, and upon
+             * returning, place the devices interrupt state to its previous
+             * value except for the link status change interrupt which will
+             * happen due to the execution of this workaround.
+             */
+
+            if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
+               (!hw->autoneg) &&
+               (hw->forced_speed_duplex == e1000_10_full ||
+                hw->forced_speed_duplex == e1000_10_half)) {
+                E1000_WRITE_REG(hw, IMC, 0xffffffff);
+                ret_val = e1000_polarity_reversal_workaround(hw);
+                icr = E1000_READ_REG(hw, ICR);
+                E1000_WRITE_REG(hw, ICS, (icr & ~E1000_ICS_LSC));
+                E1000_WRITE_REG(hw, IMS, IMS_ENABLE_MASK);
+            }
+
         } else {
             /* No link detected */
             e1000_config_dsp_after_link_change(hw, FALSE);
@@ -5191,28 +5221,88 @@
     return E1000_SUCCESS;
 }
 
-/******************************************************************************
- * Verifies the hardware needs to allow ARPs to be processed by the host
- *
- * hw - Struct containing variables accessed by shared code
- *
- * returns: - TRUE/FALSE
- *
- *****************************************************************************/
-uint32_t
-e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+static int32_t
+e1000_polarity_reversal_workaround(struct e1000_hw *hw)
 {
-    uint32_t manc;
+    int32_t ret_val;
+    uint16_t mii_status_reg;
+    uint16_t i;
 
-    if (hw->asf_firmware_present) {
-        manc = E1000_READ_REG(hw, MANC);
+    /* Polarity reversal workaround for forced 10F/10H links. */
+
+    /* Disable the transmitter on the PHY */
+
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+    if(ret_val)
+        return ret_val;
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
+    if(ret_val)
+        return ret_val;
+
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+    if(ret_val)
+        return ret_val;
+
+    /* This loop will early-out if the NO link condition has been met. */
+    for(i = PHY_FORCE_TIME; i > 0; i--) {
+        /* Read the MII Status Register and wait for Link Status bit
+         * to be clear.
+         */
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        if((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break;
+        msec_delay_irq(100);
+    }
+
+    /* Recommended delay time after link has been lost */
+    msec_delay_irq(1000);
+
+    /* Now we will re-enable th transmitter on the PHY */
+
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
+    if(ret_val)
+        return ret_val;
+    msec_delay_irq(50);
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
+    if(ret_val)
+        return ret_val;
+    msec_delay_irq(50);
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
+    if(ret_val)
+        return ret_val;
+    msec_delay_irq(50);
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
+    if(ret_val)
+        return ret_val;
 
-        if (!(manc & E1000_MANC_RCV_TCO_EN) ||
-            !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
-            return FALSE;
-        if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
-            return TRUE;
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
+    if(ret_val)
+        return ret_val;
+
+    /* This loop will early-out if the link condition has been met. */
+    for(i = PHY_FORCE_TIME; i > 0; i--) {
+        /* Read the MII Status Register and wait for Link Status bit
+         * to be set.
+         */
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
+            return ret_val;
+
+        if(mii_status_reg & MII_SR_LINK_STATUS) break;
+        msec_delay_irq(100);
     }
-    return FALSE;
+    return E1000_SUCCESS;
 }
 
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/e1000/e1000_main.c	2004-10-28 22:25:57 -07:00
@@ -48,7 +48,7 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-char e1000_driver_version[] = "5.3.19-k2"DRIVERNAPI;
+char e1000_driver_version[] = "5.5.4-k2"DRIVERNAPI;
 char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
@@ -311,7 +311,8 @@
 void
 e1000_reset(struct e1000_adapter *adapter)
 {
-	uint32_t pba, manc;
+	uint32_t pba;
+
 	/* Repartition Pba for greater than 9k mtu
 	 * To take effect CTRL.RST is required.
 	 */
@@ -354,12 +355,6 @@
 
 	e1000_reset_adaptive(&adapter->hw);
 	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
-
-	if(adapter->en_mng_pt) {
-		manc = E1000_READ_REG(&adapter->hw, MANC);
-		manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
-		E1000_WRITE_REG(&adapter->hw, MANC, manc);
-	}
 }
 
 /**
@@ -422,11 +417,6 @@
 	adapter->hw.back = adapter;
 	adapter->msg_enable = (1 << debug) - 1;
 
-	rtnl_lock();
-	/* we need to set the name early for the DPRINTK macro */
-	if(dev_alloc_name(netdev, netdev->name) < 0)
-		goto err_free_unlock;
-
 	mmio_start = pci_resource_start(pdev, BAR_0);
 	mmio_len = pci_resource_len(pdev, BAR_0);
 
@@ -466,6 +456,7 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	netdev->poll_controller = e1000_netpoll;
 #endif
+	strcpy(netdev->name, pci_name(pdev));
 
 	netdev->mem_start = mmio_start;
 	netdev->mem_end = mmio_start + mmio_len;
@@ -502,8 +493,6 @@
  	/* hard_start_xmit is safe against parallel locking */
  	netdev->features |= NETIF_F_LLTX; 
  
-	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
-
 	/* before reading the EEPROM, reset the controller to 
 	 * put the device in a known good starting state */
 	
@@ -553,7 +542,6 @@
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
 	e1000_check_options(adapter);
 
 	/* Initial Wake on LAN setting
@@ -586,12 +574,13 @@
 	/* reset the hardware with the new settings */
 	e1000_reset(adapter);
 
-	/* We're already holding the rtnl lock; call the no-lock version */
-	if((err = register_netdevice(netdev)))
+	strcpy(netdev->name, "eth%d");
+	if((err = register_netdev(netdev)))
 		goto err_register;
 
+	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
+
 	cards_found++;
-	rtnl_unlock();
 	return 0;
 
 err_register:
@@ -599,8 +588,6 @@
 err_eeprom:
 	iounmap(adapter->hw.hw_addr);
 err_ioremap:
-err_free_unlock:
-	rtnl_unlock();
 	free_netdev(netdev);
 err_alloc_etherdev:
 	pci_release_regions(pdev);
@@ -641,6 +628,8 @@
 	pci_release_regions(pdev);
 
 	free_netdev(netdev);
+
+	pci_disable_device(pdev);
 }
 
 /**
@@ -2335,8 +2324,8 @@
 		if(unlikely(adapter->vlgrp &&
 			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-						 le16_to_cpu(rx_desc->special &
-						 E1000_RXD_SPC_VLAN_MASK));
+					le16_to_cpu(rx_desc->special) &
+					E1000_RXD_SPC_VLAN_MASK);
 		} else {
 			netif_receive_skb(skb);
 		}
@@ -2344,8 +2333,8 @@
 		if(unlikely(adapter->vlgrp &&
 			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_rx(skb, adapter->vlgrp,
-					le16_to_cpu(rx_desc->special &
-					E1000_RXD_SPC_VLAN_MASK));
+					le16_to_cpu(rx_desc->special) &
+					E1000_RXD_SPC_VLAN_MASK);
 		} else {
 			netif_rx(skb);
 		}
@@ -2894,9 +2883,9 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev->priv;
-	uint32_t manc;
+	uint32_t manc, ret;
 
-	pci_enable_device(pdev);
+	ret = pci_enable_device(pdev);
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
 
diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
--- a/drivers/net/e1000/e1000_osdep.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/e1000/e1000_osdep.h	2004-10-28 22:25:57 -07:00
@@ -49,6 +49,12 @@
 				set_current_state(TASK_UNINTERRUPTIBLE); \
 				schedule_timeout((x * HZ)/1000 + 2); \
 			} } while(0)
+/* Some workarounds require millisecond delays and are run during interrupt
+ * context.  Most notably, when establishing link, the phy may need tweaking
+ * but cannot process phy register reads/writes faster than millisecond
+ * intervals...and we establish link due to a "link status change" interrupt.
+ */
+#define msec_delay_irq(x) mdelay(x)
 #endif
 
 #define PCI_COMMAND_REGISTER   PCI_COMMAND
diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
--- a/drivers/net/e1000/e1000_param.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/e1000/e1000_param.c	2004-10-28 22:25:58 -07:00
@@ -34,31 +34,21 @@
 
 #define E1000_MAX_NIC 32
 
-#define OPTION_UNSET    -1
+#define OPTION_UNSET   -1
 #define OPTION_DISABLED 0
 #define OPTION_ENABLED  1
 
-/* Module Parameters are always initialized to -1, so that the driver
- * can tell the difference between no user specified value or the
- * user asking for the default value.
- * The true default values are loaded in when e1000_check_options is called.
- *
- * This is a GCC extension to ANSI C.
- * See the item "Labeled Elements in Initializers" in the section
- * "Extensions to the C Language Family" of the GCC documentation.
- */
-
-#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
-
 /* All parameters are treated the same, as an integer array of values.
  * This macro just reduces the need to repeat the same declaration code
  * over and over (plus this helps to avoid typo bugs).
  */
 
-#define E1000_PARAM(X, S) \
-static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \
-MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \
-MODULE_PARM_DESC(X, S);
+#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
+#define E1000_PARAM(X, desc) \
+	static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
+	static int num_##X = 0; \
+	module_param_array(X, int, &num_##X, 0); \
+	MODULE_PARM_DESC(X, desc);
 
 /* Transmit Descriptor Count
  *
@@ -305,7 +295,6 @@
 		DPRINTK(PROBE, NOTICE,
 		       "Warning: no configuration for board #%i\n", bd);
 		DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
-		bd = E1000_MAX_NIC;
 	}
 
 	{ /* Transmit Descriptor Count */
@@ -322,9 +311,14 @@
 		opt.arg.r.max = mac_type < e1000_82544 ?
 			E1000_MAX_TXD : E1000_MAX_82544_TXD;
 
-		tx_ring->count = TxDescriptors[bd];
-		e1000_validate_option(&tx_ring->count, &opt, adapter);
-		E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+		if (num_TxDescriptors > bd) {
+			tx_ring->count = TxDescriptors[bd];
+			e1000_validate_option(&tx_ring->count, &opt, adapter);
+			E1000_ROUNDUP(tx_ring->count, 
+						REQ_TX_DESCRIPTOR_MULTIPLE);
+		} else {
+			tx_ring->count = opt.def;
+		}
 	}
 	{ /* Receive Descriptor Count */
 		struct e1000_option opt = {
@@ -340,9 +334,14 @@
 		opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
 			E1000_MAX_82544_RXD;
 
-		rx_ring->count = RxDescriptors[bd];
-		e1000_validate_option(&rx_ring->count, &opt, adapter);
-		E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+		if (num_RxDescriptors > bd) {
+			rx_ring->count = RxDescriptors[bd];
+			e1000_validate_option(&rx_ring->count, &opt, adapter);
+			E1000_ROUNDUP(rx_ring->count, 
+						REQ_RX_DESCRIPTOR_MULTIPLE);
+		} else {
+			rx_ring->count = opt.def;
+		}
 	}
 	{ /* Checksum Offload Enable/Disable */
 		struct e1000_option opt = {
@@ -352,9 +351,13 @@
 			.def  = OPTION_ENABLED
 		};
 
-		int rx_csum = XsumRX[bd];
-		e1000_validate_option(&rx_csum, &opt, adapter);
-		adapter->rx_csum = rx_csum;
+		if (num_XsumRX > bd) {
+			int rx_csum = XsumRX[bd];
+			e1000_validate_option(&rx_csum, &opt, adapter);
+			adapter->rx_csum = rx_csum;
+		} else {
+			adapter->rx_csum = opt.def;
+		}
 	}
 	{ /* Flow Control */
 
@@ -374,9 +377,13 @@
 					 .p = fc_list }}
 		};
 
-		int fc = FlowControl[bd];
-		e1000_validate_option(&fc, &opt, adapter);
-		adapter->hw.fc = adapter->hw.original_fc = fc;
+		if (num_FlowControl > bd) {
+			int fc = FlowControl[bd];
+			e1000_validate_option(&fc, &opt, adapter);
+			adapter->hw.fc = adapter->hw.original_fc = fc;
+		} else {
+			adapter->hw.fc = opt.def;
+		}
 	}
 	{ /* Transmit Interrupt Delay */
 		struct e1000_option opt = {
@@ -388,8 +395,13 @@
 					 .max = MAX_TXDELAY }}
 		};
 
-		adapter->tx_int_delay = TxIntDelay[bd];
-		e1000_validate_option(&adapter->tx_int_delay, &opt, adapter);
+		if (num_TxIntDelay > bd) {
+			adapter->tx_int_delay = TxIntDelay[bd];
+			e1000_validate_option(&adapter->tx_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->tx_int_delay = opt.def;
+		}
 	}
 	{ /* Transmit Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -401,8 +413,13 @@
 					 .max = MAX_TXABSDELAY }}
 		};
 
-		adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->tx_abs_int_delay, &opt, adapter);
+		if (num_TxAbsIntDelay > bd) {
+			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
+			e1000_validate_option(&adapter->tx_abs_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->tx_abs_int_delay = opt.def;
+		}
 	}
 	{ /* Receive Interrupt Delay */
 		struct e1000_option opt = {
@@ -414,8 +431,13 @@
 					 .max = MAX_RXDELAY }}
 		};
 
-		adapter->rx_int_delay = RxIntDelay[bd];
-		e1000_validate_option(&adapter->rx_int_delay, &opt, adapter);
+		if (num_RxIntDelay > bd) {
+			adapter->rx_int_delay = RxIntDelay[bd];
+			e1000_validate_option(&adapter->rx_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->rx_int_delay = opt.def;
+		}
 	}
 	{ /* Receive Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -427,8 +449,13 @@
 					 .max = MAX_RXABSDELAY }}
 		};
 
-		adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->rx_abs_int_delay, &opt, adapter);
+		if (num_RxAbsIntDelay > bd) {
+			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
+			e1000_validate_option(&adapter->rx_abs_int_delay, &opt, 
+								adapter);
+		} else {
+			adapter->rx_abs_int_delay = opt.def;
+		}
 	}
 	{ /* Interrupt Throttling Rate */
 		struct e1000_option opt = {
@@ -440,20 +467,27 @@
 					 .max = MAX_ITR }}
 		};
 
-		adapter->itr = InterruptThrottleRate[bd];
-		switch(adapter->itr) {
-		case -1:
+		if (num_InterruptThrottleRate > bd) {
+			adapter->itr = InterruptThrottleRate[bd];
+			switch(adapter->itr) {
+			case -1:
+				adapter->itr = 1;
+				break;
+			case 0:
+				DPRINTK(PROBE, INFO, "%s turned off\n", 
+					opt.name);
+				break;
+			case 1:
+				DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", 
+					opt.name);
+				break;
+			default:
+				e1000_validate_option(&adapter->itr, &opt, 
+					adapter);
+				break;
+			}
+		} else {
 			adapter->itr = 1;
-			break;
-		case 0:
-			DPRINTK(PROBE, INFO, "%s turned off\n", opt.name);
-			break;
-		case 1:
-			DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name);
-			break;
-		default:
-			e1000_validate_option(&adapter->itr, &opt, adapter);
-			break;
 		}
 	}
 
@@ -481,17 +515,17 @@
 e1000_check_fiber_options(struct e1000_adapter *adapter)
 {
 	int bd = adapter->bd_number;
-	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
-
-	if((Speed[bd] != OPTION_UNSET)) {
+	if(num_Speed > bd) {
 		DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
-	if((Duplex[bd] != OPTION_UNSET)) {
+
+	if(num_Duplex > bd) {
 		DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
-	if((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
+
+	if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
 		DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
 				 "not valid for fiber adapters, "
 				 "parameter ignored\n");
@@ -510,7 +544,6 @@
 {
 	int speed, dplx;
 	int bd = adapter->bd_number;
-	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
 
 	{ /* Speed */
 		struct e1000_opt_list speed_list[] = {{          0, "" },
@@ -527,8 +560,12 @@
 					 .p = speed_list }}
 		};
 
-		speed = Speed[bd];
-		e1000_validate_option(&speed, &opt, adapter);
+		if (num_Speed > bd) {
+			speed = Speed[bd];
+			e1000_validate_option(&speed, &opt, adapter);
+		} else {
+			speed = opt.def;
+		}
 	}
 	{ /* Duplex */
 		struct e1000_opt_list dplx_list[] = {{           0, "" },
@@ -544,11 +581,15 @@
 					 .p = dplx_list }}
 		};
 
-		dplx = Duplex[bd];
-		e1000_validate_option(&dplx, &opt, adapter);
+		if (num_Duplex > bd) {
+			dplx = Duplex[bd];
+			e1000_validate_option(&dplx, &opt, adapter);
+		} else {
+			dplx = opt.def;
+		}
 	}
 
-	if(AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) {
+	if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
 		DPRINTK(PROBE, INFO,
 		       "AutoNeg specified along with Speed or Duplex, "
 		       "parameter ignored\n");
@@ -605,7 +646,7 @@
 	switch (speed + dplx) {
 	case 0:
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
+		if((num_Speed > bd) && (speed != 0 || dplx != 0))
 			DPRINTK(PROBE, INFO,
 			       "Speed and duplex autonegotiation enabled\n");
 		break;
diff -Nru a/drivers/net/eql.c b/drivers/net/eql.c
--- a/drivers/net/eql.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/eql.c	2004-10-28 22:25:59 -07:00
@@ -164,12 +164,12 @@
 
 static void __init eql_setup(struct net_device *dev)
 {
-	equalizer_t *eql = dev->priv;
+	equalizer_t *eql = netdev_priv(dev);
 
 	SET_MODULE_OWNER(dev);
 
 	init_timer(&eql->timer);
-	eql->timer.data     	= (unsigned long) dev->priv;
+	eql->timer.data     	= (unsigned long) eql;
 	eql->timer.expires  	= jiffies + EQL_DEFAULT_RESCHED_IVAL;
 	eql->timer.function 	= eql_timer;
 
@@ -197,7 +197,7 @@
 
 static int eql_open(struct net_device *dev)
 {
-	equalizer_t *eql = dev->priv;
+	equalizer_t *eql = netdev_priv(dev);
 
 	/* XXX We should force this off automatically for the user. */
 	printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
@@ -241,7 +241,7 @@
 
 static int eql_close(struct net_device *dev)
 {
-	equalizer_t *eql = dev->priv;
+	equalizer_t *eql = netdev_priv(dev);
 
 	/*
 	 *	The timer has to be stopped first before we start hacking away
@@ -326,7 +326,7 @@
 
 static int eql_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	equalizer_t *eql = dev->priv;
+	equalizer_t *eql = netdev_priv(dev);
 	slave_t *slave;
 
 	spin_lock(&eql->queue.lock);
@@ -352,7 +352,7 @@
 
 static struct net_device_stats * eql_get_stats(struct net_device *dev)
 {
-	equalizer_t *eql = dev->priv;
+	equalizer_t *eql = netdev_priv(dev);
 	return &eql->stats;
 }
 
@@ -378,7 +378,7 @@
 
 static inline int eql_is_full(slave_queue_t *queue)
 {
-	equalizer_t *eql = queue->master_dev->priv;
+	equalizer_t *eql = netdev_priv(queue->master_dev);
 
 	if (queue->num_slaves >= eql->max_slaves)
 		return 1;
@@ -420,7 +420,7 @@
 			if (!eql_is_master(slave_dev) &&
 			    !eql_is_slave(slave_dev)) {
 				slave_t *s = kmalloc(sizeof(*s), GFP_KERNEL);
-				equalizer_t *eql = master_dev->priv;
+				equalizer_t *eql = netdev_priv(master_dev);
 				int ret;
 
 				if (!s) {
@@ -453,7 +453,7 @@
 
 static int eql_emancipate(struct net_device *master_dev, slaving_request_t __user *srqp)
 {
-	equalizer_t *eql = master_dev->priv;
+	equalizer_t *eql = netdev_priv(master_dev);
 	struct net_device *slave_dev;
 	slaving_request_t srq;
 	int ret;
@@ -485,7 +485,7 @@
 
 static int eql_g_slave_cfg(struct net_device *dev, slave_config_t __user *scp)
 {
-	equalizer_t *eql = dev->priv;
+	equalizer_t *eql = netdev_priv(dev);
 	slave_t *slave;
 	struct net_device *slave_dev;
 	slave_config_t sc;
@@ -539,7 +539,7 @@
 	if (!slave_dev)
 		return ret;
 
-	eql = dev->priv;
+	eql = netdev_priv(dev);
 	spin_lock_bh(&eql->queue.lock);
 	if (eql_is_slave(slave_dev)) {
 		slave = __eql_find_slave_dev(&eql->queue, slave_dev);
@@ -561,7 +561,7 @@
 	master_config_t mc;
 
 	if (eql_is_master(dev)) {
-		eql = dev->priv;
+		eql = netdev_priv(dev);
 		mc.max_slaves = eql->max_slaves;
 		mc.min_slaves = eql->min_slaves;
 		if (copy_to_user(mcp, &mc, sizeof (master_config_t)))
@@ -580,7 +580,7 @@
 		return -EFAULT;
 
 	if (eql_is_master(dev)) {
-		eql = dev->priv;
+		eql = netdev_priv(dev);
 		eql->max_slaves = mc.max_slaves;
 		eql->min_slaves = mc.min_slaves;
 		return 0;
diff -Nru a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
--- a/drivers/net/hamradio/hdlcdrv.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/hamradio/hdlcdrv.c	2004-10-28 22:25:59 -07:00
@@ -549,6 +549,8 @@
 
 	netif_stop_queue(dev);
 
+	netif_stop_queue(dev);
+
 	if (s->ops && s->ops->close)
 		i = s->ops->close(dev);
 	if (s->skb)
diff -Nru a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
--- a/drivers/net/hamradio/mkiss.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/hamradio/mkiss.c	2004-10-28 22:25:59 -07:00
@@ -518,7 +518,7 @@
 
 	ax->flags   &= (1 << AXF_INUSE);      /* Clear ESCAPE & ERROR flags */
 
-	ax->buflock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&ax->buflock);
 
 	netif_start_queue(dev);
 	return 0;
diff -Nru a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
--- a/drivers/net/ibmlana.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/ibmlana.c	2004-10-28 22:25:57 -07:00
@@ -885,14 +885,6 @@
 	return &priv->stat;
 }
 
-/* we don't support runtime reconfiguration, since am MCA card can
-   be unambigously identified by its POS registers. */
-
-static int ibmlana_config(struct net_device *dev, struct ifmap *map)
-{
-	return 0;
-}
-
 /* switch receiver mode. */
 
 static void ibmlana_set_multicast_list(struct net_device *dev)
@@ -984,7 +976,6 @@
 
 	dev->open = ibmlana_open;
 	dev->stop = ibmlana_close;
-	dev->set_config = ibmlana_config;
 	dev->hard_start_xmit = ibmlana_tx;
 	dev->do_ioctl = NULL;
 	dev->get_stats = ibmlana_stats;
diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/ixgb/ixgb_main.c	2004-10-28 22:25:57 -07:00
@@ -30,7 +30,7 @@
 
 char ixgb_driver_name[] = "ixgb";
 char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
-char ixgb_driver_version[] = "1.0.66";
+char ixgb_driver_version[] = "1.0.66-k2";
 char ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
@@ -1614,8 +1614,12 @@
 	}
 #else
 	for (i = 0; i < IXGB_MAX_INTR; i++)
-		if (!ixgb_clean_rx_irq(adapter) & !ixgb_clean_tx_irq(adapter))
+		if (ixgb_clean_rx_irq(adapter) == FALSE)
 			break;
+	for (i = 0; i < IXGB_MAX_INTR; i++)
+		if (ixgb_clean_tx_irq(adapter) == FALSE)
+			break;
+
 	/* if RAIDC:EN == 1 and ICR:RXDMT0 == 1, we need to
 	 * set IMS:RXDMT0 to 1 to restart the RBD timer (POLL)
 	 */
@@ -1676,7 +1680,7 @@
 	eop = tx_ring->buffer_info[i].next_to_watch;
 	eop_desc = IXGB_TX_DESC(*tx_ring, eop);
 
-	while (eop_desc->status & cpu_to_le32(IXGB_TX_DESC_STATUS_DD)) {
+	while (eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
 
 		for (cleaned = FALSE; !cleaned;) {
 			tx_desc = IXGB_TX_DESC(*tx_ring, i);
diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
--- a/drivers/net/lasi_82596.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/lasi_82596.c	2004-10-28 22:25:57 -07:00
@@ -1218,7 +1218,7 @@
 	lp->scb.command = 0;
 	lp->scb.cmd = I596_NULL;
 	lp->scb.rfd = I596_NULL;
-	lp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&lp->lock);
 	lp->dma_addr = dma_addr;
 	lp->dev = gen_dev;
 
diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c
--- a/drivers/net/mac8390.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/mac8390.c	2004-10-28 22:25:58 -07:00
@@ -42,10 +42,6 @@
 
 #include "8390.h"
 
-#if (LINUX_VERSION_CODE < 0x02030e)
-#define net_device device
-#endif
-
 #define WD_START_PG			0x00	/* First page of TX buffer */
 #define CABLETRON_RX_START_PG		0x00    /* First page of RX buffer */
 #define CABLETRON_RX_STOP_PG		0x30    /* Last page +1 of RX ring */
diff -Nru a/drivers/net/meth.c b/drivers/net/meth.c
--- a/drivers/net/meth.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/meth.c	2004-10-28 22:25:59 -07:00
@@ -368,31 +368,6 @@
 }
 
 /*
- * Configuration changes (passed on by ifconfig)
- */
-static int meth_config(struct net_device *dev, struct ifmap *map)
-{
-	if (dev->flags & IFF_UP) /* can't act on a running interface */
-		return -EBUSY;
-
-	/* Don't allow changing the I/O address */
-	if (map->base_addr != dev->base_addr) {
-		printk(KERN_WARNING "meth: Can't change I/O address\n");
-		return -EOPNOTSUPP;
-	}
-
-	/* Don't allow changing the IRQ */
-	if (map->irq != dev->irq) {
-		printk(KERN_WARNING "meth: Can't change IRQ\n");
-		return -EOPNOTSUPP;
-	}
-	DPRINTK("Configured\n");
-
-	/* ignore other fields */
-	return 0;
-}
-
-/*
  * Receive a packet: retrieve, encapsulate and pass over to upper levels
  */
 static void meth_rx(struct net_device* dev, unsigned long int_status)
@@ -813,7 +788,6 @@
 
 	dev->open            = meth_open;
 	dev->stop            = meth_release;
-	dev->set_config      = meth_config;
 	dev->hard_start_xmit = meth_tx;
 	dev->do_ioctl        = meth_ioctl;
 	dev->get_stats       = meth_stats;
diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
--- a/drivers/net/ne2k-pci.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/ne2k-pci.c	2004-10-28 22:25:57 -07:00
@@ -653,12 +653,43 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
+#ifdef CONFIG_PM
+static int ne2k_pci_suspend (struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+
+	netif_device_detach(dev);
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, state);
+
+	return 0;
+}
+
+static int ne2k_pci_resume (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev);
+	NS8390_init(dev, 1);
+	netif_device_attach(dev);
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
 
 static struct pci_driver ne2k_driver = {
 	.name		= DRV_NAME,
 	.probe		= ne2k_pci_init_one,
 	.remove		= __devexit_p(ne2k_pci_remove_one),
 	.id_table	= ne2k_pci_tbl,
+#ifdef CONFIG_PM
+	.suspend	= ne2k_pci_suspend,
+	.resume		= ne2k_pci_resume,
+#endif /* CONFIG_PM */
+
 };
 
 
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/ns83820.c	2004-10-28 22:25:59 -07:00
@@ -64,6 +64,8 @@
  *				tuning
  *			0.20 -	fix stupid RFEN thinko.  i am such a smurf.
  *
+ *	20040828	0.21 -	add hardware vlan accleration
+ *				by Neil Horman <nhorman@redhat.com>
  * Driver Overview
  * ===============
  *
@@ -92,7 +94,9 @@
 //#define dprintk		printk
 #define dprintk(x...)		do { } while (0)
 
+#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -108,6 +112,7 @@
 #include <linux/prefetch.h>
 #include <linux/ethtool.h>
 #include <linux/timer.h>
+#include <linux/if_vlan.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -115,7 +120,7 @@
 
 #define DRV_NAME "ns83820"
 
-/* Global parameters.  See MODULE_PARM near the bottom. */
+/* Global parameters.  See module_param near the bottom. */
 static int ihr = 2;
 static int reset_phy = 0;
 static int lnksts = 0;		/* CFG_LNKSTS bit polarity */
@@ -138,6 +143,9 @@
 
 /* tunables */
 #define RX_BUF_SIZE	1500	/* 8192 */
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define NS83820_VLAN_ACCEL_SUPPORT
+#endif
 
 /* Must not exceed ~65000. */
 #define NR_RX_DESC	64
@@ -262,6 +270,8 @@
 #define EXTSTS_UDPPKT	0x00200000
 #define EXTSTS_TCPPKT	0x00080000
 #define EXTSTS_IPPKT	0x00020000
+#define EXTSTS_VPKT	0x00010000
+#define EXTSTS_VTG_MASK	0x0000ffff
 
 #define SPDSTS_POLARITY	(CFG_SPDSTS1 | CFG_SPDSTS0 | CFG_DUPSTS | (lnksts ? CFG_LNKSTS : 0))
 
@@ -403,6 +413,7 @@
 #define CMDSTS_INTR	0x20000000
 #define CMDSTS_ERR	0x10000000
 #define CMDSTS_OK	0x08000000
+#define CMDSTS_RUNT	0x00200000
 #define CMDSTS_LEN_MASK	0x0000ffff
 
 #define CMDSTS_DEST_MASK	0x01800000
@@ -432,6 +443,10 @@
 
 	struct pci_dev		*pci_dev;
 
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+	struct vlan_group	*vlgrp;
+#endif
+
 	struct rx_info		rx_info;
 	struct tasklet_struct	rx_tasklet;
 
@@ -494,6 +509,33 @@
 	(((NR_TX_DESC-2 + dev->tx_done_idx - dev->tx_free_idx) % NR_TX_DESC) > MIN_TX_DESC_FREE)
 
 
+#ifdef NS83820_VLAN_ACCEL_SUPPORT 
+static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
+{
+	struct ns83820 *dev = PRIV(ndev);
+
+	spin_lock_irq(&dev->misc_lock);
+	spin_lock(&dev->tx_lock);
+
+	dev->vlgrp = grp;
+
+	spin_unlock(&dev->tx_lock);
+	spin_unlock_irq(&dev->misc_lock);
+}
+
+static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
+{
+	struct ns83820 *dev = PRIV(ndev);
+
+	spin_lock_irq(&dev->misc_lock);
+	spin_lock(&dev->tx_lock);
+	if (dev->vlgrp)
+		dev->vlgrp->vlan_devices[vid] = NULL;
+	spin_unlock(&dev->tx_lock);
+	spin_unlock_irq(&dev->misc_lock);
+}
+#endif
+
 /* Packet Receiver
  *
  * The hardware supports linked lists of receive descriptors for
@@ -836,6 +878,7 @@
 	struct ns83820 *dev = PRIV(ndev);
 	struct rx_info *info = &dev->rx_info;
 	unsigned next_rx;
+	int rx_rc, len;
 	u32 cmdsts, *desc;
 	unsigned long flags;
 	int nr = 0;
@@ -876,8 +919,24 @@
 
 		pci_unmap_single(dev->pci_dev, bufptr,
 				 RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		len = cmdsts & CMDSTS_LEN_MASK;
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+		/* NH: As was mentioned below, this chip is kinda
+		 * brain dead about vlan tag stripping.  Frames
+		 * that are 64 bytes with a vlan header appended
+		 * like arp frames, or pings, are flagged as Runts
+		 * when the tag is stripped and hardware.  This
+		 * also means that the OK bit in the descriptor 
+		 * is cleared when the frame comes in so we have
+		 * to do a specific length check here to make sure
+		 * the frame would have been ok, had we not stripped
+		 * the tag.
+		 */ 
+		if (likely((CMDSTS_OK & cmdsts) ||
+			((cmdsts & CMDSTS_RUNT) && len >= 56))) {   
+#else
 		if (likely(CMDSTS_OK & cmdsts)) {
-			int len = cmdsts & 0xffff;
+#endif
 			skb_put(skb, len);
 			if (unlikely(!skb))
 				goto netdev_mangle_me_harder_failed;
@@ -891,7 +950,18 @@
 				skb->ip_summed = CHECKSUM_NONE;
 			}
 			skb->protocol = eth_type_trans(skb, ndev);
-			if (NET_RX_DROP == netif_rx(skb)) {
+#ifdef NS83820_VLAN_ACCEL_SUPPORT 
+			if(extsts & EXTSTS_VPKT) {
+				unsigned short tag;
+				tag = ntohs(extsts & EXTSTS_VTG_MASK);
+				rx_rc = vlan_hwaccel_rx(skb,dev->vlgrp,tag);
+			} else {
+				rx_rc = netif_rx(skb);
+			}
+#else
+			rx_rc = netif_rx(skb);
+#endif
+			if (NET_RX_DROP == rx_rc) {
 netdev_mangle_me_harder_failed:
 				dev->stats.rx_dropped ++;
 			}
@@ -1099,6 +1169,17 @@
 			extsts |= EXTSTS_UDPPKT;
 	}
 
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+	if(vlan_tx_tag_present(skb)) {
+		/* fetch the vlan tag info out of the
+		 * ancilliary data if the vlan code
+		 * is using hw vlan acceleration
+		 */
+		short tag = vlan_tx_tag_get(skb);
+		extsts |= (EXTSTS_VPKT | htons(tag));
+	}
+#endif
+
 	len = skb->len;
 	if (nr_frags)
 		len -= skb->data_len;
@@ -1854,7 +1935,6 @@
 	SET_ETHTOOL_OPS(ndev, &ops);
 	ndev->tx_timeout = ns83820_tx_timeout;
 	ndev->watchdog_timeo = 5 * HZ;
-
 	pci_set_drvdata(pci_dev, ndev);
 
 	ns83820_do_reset(dev, CR_RST);
@@ -1980,11 +2060,25 @@
 	 * a ping with a VLAN header) then the card, strips the 4 byte VLAN
 	 * tag and then checks the packet size, so if RXCFG_ARP is not enabled,
 	 * it discrards it!.  These guys......
+	 * also turn on tag stripping if hardware acceleration is enabled
 	 */
-	writel(VRCR_IPEN | VRCR_VTDEN, dev->base + VRCR);
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN|VRCR_VTREN) 
+#else
+#define VRCR_INIT_VALUE (VRCR_IPEN|VRCR_VTDEN)
+#endif
+	writel(VRCR_INIT_VALUE, dev->base + VRCR);
 
-	/* Enable per-packet TCP/UDP/IP checksumming */
-	writel(VTCR_PPCHK, dev->base + VTCR);
+	/* Enable per-packet TCP/UDP/IP checksumming
+	 * and per packet vlan tag insertion if
+	 * vlan hardware acceleration is enabled
+	 */
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+#define VTCR_INIT_VALUE (VTCR_PPCHK|VTCR_VPPTI)
+#else
+#define VTCR_INIT_VALUE VTCR_PPCHK
+#endif
+	writel(VTCR_INIT_VALUE, dev->base + VTCR);
 
 	/* Ramit : Enable async and sync pause frames */
 	/* writel(0, dev->base + PCR); */
@@ -2001,6 +2095,13 @@
 	ndev->features |= NETIF_F_SG;
 	ndev->features |= NETIF_F_IP_CSUM;
 
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+	/* We also support hardware vlan acceleration */
+	ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+	ndev->vlan_rx_register = ns83820_vlan_rx_register;
+	ndev->vlan_rx_kill_vid = ns83820_vlan_rx_kill_vid;
+#endif
+
 	if (using_dac) {
 		printk(KERN_INFO "%s: using 64 bit addressing.\n",
 			ndev->name);
@@ -2109,13 +2210,13 @@
 
 MODULE_DEVICE_TABLE(pci, ns83820_pci_tbl);
 
-MODULE_PARM(lnksts, "i");
+module_param(lnksts, int, 0);
 MODULE_PARM_DESC(lnksts, "Polarity of LNKSTS bit");
 
-MODULE_PARM(ihr, "i");
+module_param(ihr, int, 0);
 MODULE_PARM_DESC(ihr, "Time in 100 us increments to delay interrupts (range 0-127)");
 
-MODULE_PARM(reset_phy, "i");
+module_param(reset_phy, int, 0);
 MODULE_PARM_DESC(reset_phy, "Set to 1 to reset the PHY on startup");
 
 module_init(ns83820_init);
diff -Nru a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
--- a/drivers/net/pci-skeleton.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/pci-skeleton.c	2004-10-28 22:25:56 -07:00
@@ -795,7 +795,7 @@
 	tp->pci_dev = pdev;
 	tp->board = ent->driver_data;
 	tp->mmio_addr = ioaddr;
-	tp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&tp->lock);
 
 	pci_set_drvdata(pdev, dev);
 
diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
--- a/drivers/net/pcnet32.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/pcnet32.c	2004-10-28 22:25:57 -07:00
@@ -359,9 +359,9 @@
     struct net_device_stats stats;
     char		tx_full;
     int			options;
-    int	shared_irq:1,			/* shared irq possible */
-	dxsuflo:1,			/* disable transmit stop on uflo */
-	mii:1;				/* mii port available */
+    unsigned int	shared_irq:1,	/* shared irq possible */
+			dxsuflo:1,	/* disable transmit stop on uflo */
+			mii:1;		/* mii port available */
     struct net_device	*next;
     struct mii_if_info	mii_if;
     struct timer_list	watchdog_timer;
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/ppp_generic.c	2004-10-28 22:25:59 -07:00
@@ -1920,7 +1920,7 @@
 #endif /* CONFIG_PPP_MULTILINK */
 	init_rwsem(&pch->chan_sem);
 	spin_lock_init(&pch->downl);
-	pch->upl = RW_LOCK_UNLOCKED;
+	rwlock_init(&pch->upl);
 	spin_lock_bh(&all_channels_lock);
 	pch->file.index = ++last_channel_index;
 	list_add(&pch->list, &new_channels);
diff -Nru a/drivers/net/s2io.c b/drivers/net/s2io.c
--- a/drivers/net/s2io.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/s2io.c	2004-10-28 22:25:58 -07:00
@@ -3983,14 +3983,14 @@
 
 MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@s2io.com>");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ring_num, "1-" __MODULE_STRING(1) "i");
-MODULE_PARM(frame_len, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(ring_len, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(fifo_num, "1-" __MODULE_STRING(1) "i");
-MODULE_PARM(fifo_len, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(rx_prio, "1-" __MODULE_STRING(1) "i");
-MODULE_PARM(tx_prio, "1-" __MODULE_STRING(1) "i");
-MODULE_PARM(latency_timer, "1-" __MODULE_STRING(1) "i");
+module_param(ring_num, uint, 0);
+module_param_array(frame_len, uint, NULL, 0);
+module_param_array(ring_len, uint, NULL, 0);
+module_param(fifo_num, uint, 0);
+module_param_array(fifo_len, uint, NULL, 0);
+module_param(rx_prio, uint, 0);
+module_param(tx_prio, uint, 0);
+module_param(latency_timer, byte, 0);
 
 /*
 *  Input Argument/s: 
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/sis900.c	2004-10-28 22:25:57 -07:00
@@ -262,13 +262,12 @@
 	u8 reg;
 	int i;
 
-	isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
+	isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
+	if (!isa_bridge)
+		isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
 	if (!isa_bridge) {
-		isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
-		if (!isa_bridge) {
-			printk("%s: Can not find ISA bridge\n", net_dev->name);
-			return 0;
-		}
+		printk("%s: Can not find ISA bridge\n", net_dev->name);
+		return 0;
 	}
 	pci_read_config_byte(isa_bridge, 0x48, &reg);
 	pci_write_config_byte(isa_bridge, 0x48, reg | 0x40);
@@ -278,6 +277,7 @@
 		((u8 *)(net_dev->dev_addr))[i] = inb(0x71); 
 	}
 	pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
+	pci_dev_put(isa_bridge);
 
 	return 1;
 }
@@ -488,9 +488,11 @@
 	}
 
 	/* save our host bridge revision */
-	dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
-	if (dev)
+	dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
+	if (dev) {
 		pci_read_config_byte(dev, PCI_CLASS_REVISION, &sis_priv->host_bridge_rev);
+		pci_dev_put(dev);
+	}
 
 	/* print some information about our NIC */
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name,
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/sk_mca.c	2004-10-28 22:25:58 -07:00
@@ -972,14 +972,6 @@
 	return &(priv->stat);
 }
 
-/* we don't support runtime reconfiguration, since an MCA card can
-   be unambigously identified by its POS registers. */
-
-static int skmca_config(struct net_device *dev, struct ifmap *map)
-{
-	return 0;
-}
-
 /* switch receiver mode.  We use the LANCE's multicast filter to prefilter
    multicast addresses. */
 
@@ -1147,7 +1139,6 @@
 	/* set methods */
 	dev->open = skmca_open;
 	dev->stop = skmca_close;
-	dev->set_config = skmca_config;
 	dev->hard_start_xmit = skmca_tx;
 	dev->do_ioctl = NULL;
 	dev->get_stats = skmca_stats;
diff -Nru a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
--- a/drivers/net/skfp/hwmtm.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/skfp/hwmtm.c	2004-10-28 22:25:58 -07:00
@@ -1901,7 +1901,8 @@
 	}
 
 	if (!smc->hw.mac_ring_is_up || frag_count > queue->tx_free) {
-		if (frame_status &= ~LAN_TX) {
+		frame_status &= ~LAN_TX;
+		if (frame_status) {
 			DB_TX("Ring is down: terminate LAN_TX",0,0,2) ;
 		}
 		else {
diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c
--- a/drivers/net/slip.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/slip.c	2004-10-28 22:25:59 -07:00
@@ -57,6 +57,7 @@
 #define SL_CHECK_TRANSMIT
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -85,8 +86,8 @@
 
 static struct net_device **slip_devs;
 
-int slip_maxdev = SL_NRUNIT;		/* Can be overridden with insmod! */
-MODULE_PARM(slip_maxdev, "i");
+static int slip_maxdev = SL_NRUNIT;
+module_param(slip_maxdev, int, 0);
 MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices");
 
 static int slip_esc(unsigned char *p, unsigned char *d, int len);
@@ -458,13 +459,11 @@
 
 static void sl_tx_timeout(struct net_device *dev)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 
 	spin_lock(&sl->lock);
 
 	if (netif_queue_stopped(dev)) {
-		struct slip *sl = (struct slip*)(dev->priv);
-
 		if (!netif_running(dev))
 			goto out;
 
@@ -494,7 +493,7 @@
 static int
 sl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 
 	spin_lock(&sl->lock);
 	if (!netif_running(dev))  {
@@ -528,7 +527,7 @@
 static int
 sl_close(struct net_device *dev)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 
 	spin_lock_bh(&sl->lock);
 	if (sl->tty) {
@@ -547,7 +546,7 @@
 
 static int sl_open(struct net_device *dev)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 
 	if (sl->tty==NULL)
 		return -ENODEV;
@@ -561,7 +560,7 @@
 
 static int sl_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 
 	if (new_mtu < 68 || new_mtu > 65534)
 		return -EINVAL;
@@ -577,7 +576,7 @@
 sl_get_stats(struct net_device *dev)
 {
 	static struct net_device_stats stats;
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 #ifdef SL_INCLUDE_CSLIP
 	struct slcompress *comp;
 #endif
@@ -612,7 +611,7 @@
 
 static int sl_init(struct net_device *dev)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 
 	/*
 	 *	Finish setting up the DEVICE info. 
@@ -630,7 +629,7 @@
 
 static void sl_uninit(struct net_device *dev)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 
 	sl_free_bufs(sl);
 }
@@ -719,7 +718,7 @@
 		if ((dev = slip_devs[i]) == NULL)
 			break;
 
-		sl = dev->priv;
+		sl = netdev_priv(dev);
 		if (sl->tty || sl->leased)
 			continue;
 		if (dev->flags&IFF_UP)
@@ -746,7 +745,7 @@
 		if (dev == NULL)
 			break;
 
-		sl = dev->priv;
+		sl = netdev_priv(dev);
 		if (sl->leased) {
 			if (sl->line != line)
 				continue;
@@ -788,7 +787,7 @@
 		i = sel;
 		dev = slip_devs[i];
 		if (score > 1) {
-			sl = dev->priv;
+			sl = netdev_priv(dev);
 			sl->flags &= (1 << SLF_INUSE);
 			return sl;
 		}
@@ -799,7 +798,7 @@
 		return NULL;
 
 	if (dev) {
-		sl = dev->priv;
+		sl = netdev_priv(dev);
 		if (test_bit(SLF_INUSE, &sl->flags)) {
 			unregister_netdevice(dev);
 			dev = NULL;
@@ -817,7 +816,7 @@
 		dev->base_addr  = i;
 	}
 
-	sl = dev->priv;
+	sl = netdev_priv(dev);
 
 	/* Initialize channel control data */
 	sl->magic       = SLIP_MAGIC;
@@ -1260,7 +1259,7 @@
 
 static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
 {
-	struct slip *sl = (struct slip*)(dev->priv);
+	struct slip *sl = netdev_priv(dev);
 	unsigned long *p = (unsigned long *)&rq->ifr_ifru;
 
 	if (sl == NULL)		/* Allocation failed ?? */
@@ -1406,7 +1405,7 @@
 			dev = slip_devs[i];
 			if (!dev)
 				continue;
-			sl = dev->priv;
+			sl = netdev_priv(dev);
 			spin_lock_bh(&sl->lock);
 			if (sl->tty) {
 				busy++;
@@ -1423,7 +1422,7 @@
 			continue;
 		slip_devs[i] = NULL;
 
-		sl = dev->priv;
+		sl = netdev_priv(dev);
 		if (sl->tty) {
 			printk(KERN_ERR "%s: tty discipline still running\n",
 			       dev->name);
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/sundance.c	2004-10-28 22:25:58 -07:00
@@ -879,7 +879,7 @@
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
 
-	np->mcastlock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&np->mcastlock);
 
 	set_rx_mode(dev);
 	writew(0, ioaddr + IntrEnable);
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/tg3.c	2004-10-28 22:25:58 -07:00
@@ -12,7 +12,7 @@
 #include <linux/config.h>
 
 #include <linux/module.h>
-
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
@@ -141,11 +141,11 @@
 MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)");
 MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM(tg3_debug, "i");
-MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
 static int tg3_debug = -1;	/* -1 == use TG3_DEF_MSG_ENABLE as value */
+module_param(tg3_debug, int, 0);
+MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
 
 static struct pci_device_id tg3_pci_tbl[] = {
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700,
@@ -225,8 +225,8 @@
 
 MODULE_DEVICE_TABLE(pci, tg3_pci_tbl);
 
-struct {
-	char string[ETH_GSTRING_LEN];
+static struct {
+	const char string[ETH_GSTRING_LEN];
 } ethtool_stats_keys[TG3_NUM_STATS] = {
 	{ "rx_octets" },
 	{ "rx_fragments" },
@@ -4505,7 +4505,7 @@
 	0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000,
 };
 
-u32 tg3TsoFwRodata[] = {
+static u32 tg3TsoFwRodata[] = {
 	0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
 	0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f,
 	0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000,
@@ -4513,7 +4513,7 @@
 	0x00000000,
 };
 
-u32 tg3TsoFwData[] = {
+static u32 tg3TsoFwData[] = {
 	0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
 	0x00000000,
@@ -4694,14 +4694,14 @@
 	0x00000000, 0x00000000, 0x00000000,
 };
 
-u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
+static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
 	0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
 	0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000,
 	0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
 	0x00000000, 0x00000000, 0x00000000,
 };
 
-u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
+static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
 	0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000,
 };
@@ -6324,7 +6324,7 @@
 					u32 offset, u32 *val);
 static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	int ret;
 	u8  *pd;
 	u32 i, offset, len, val, b_offset, b_count;
@@ -6686,7 +6686,7 @@
 static void tg3_get_ethtool_stats (struct net_device *dev,
 				   struct ethtool_stats *estats, u64 *tmp_stats)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
 }
 
diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
--- a/drivers/net/tokenring/ibmtr.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/tokenring/ibmtr.c	2004-10-28 22:25:58 -07:00
@@ -895,7 +895,7 @@
 
 	ti->sram_virt &= ~1; /* to reverse what we do in tok_close */
 	/* init the spinlock */
-	ti->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&ti->lock);
 	init_timer(&ti->tr_timer);
 	
 	i = tok_init_card(dev);
diff -Nru a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
--- a/drivers/net/tokenring/olympic.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/tokenring/olympic.c	2004-10-28 22:25:59 -07:00
@@ -1401,7 +1401,6 @@
 	u16 lan_status = 0, lan_status_diff  ; /* Initialize to stop compiler warning */
 	u8 fdx_prot_error ; 
 	u16 next_ptr;
-	int i ; 
 
 	arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; 
 	asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; 
diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
--- a/drivers/net/tulip/de2104x.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/tulip/de2104x.c	2004-10-28 22:25:59 -07:00
@@ -1208,8 +1208,7 @@
 		pci_write_config_dword(de->pdev, PCIPM, pmctl);
 
 		/* de4x5.c delays, so we do too */
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout(msecs_to_jiffies(10));
+		msleep(10);
 	}
 }
 
diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
--- a/drivers/net/tulip/de4x5.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/tulip/de4x5.c	2004-10-28 22:25:56 -07:00
@@ -1141,7 +1141,7 @@
 	lp->asBitValid = TRUE;
 	lp->timeout = -1;
 	lp->gendev = gendev;
-	lp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&lp->lock);
 	init_timer(&lp->timer);
 	de4x5_parse_params(dev);
 
@@ -1316,7 +1316,7 @@
     ** Re-initialize the DE4X5... 
     */
     status = de4x5_init(dev);
-    lp->lock = SPIN_LOCK_UNLOCKED;
+    spin_lock_init(&lp->lock);
     lp->state = OPEN;
     de4x5_dbg_open(dev);
     
@@ -5089,7 +5089,7 @@
     lp->useMII = TRUE;
 
     /* Search the MII address space for possible PHY devices */
-    for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(++i)%DE4X5_MAX_MII) {
+    for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
 	lp->phy[lp->active].addr = i;
 	if (i==0) n++;                             /* Count cycles */
 	while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */
diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
--- a/drivers/net/tulip/tulip_core.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/tulip/tulip_core.c	2004-10-28 22:25:58 -07:00
@@ -1221,6 +1221,11 @@
 	struct tulip_private *tp;
 	/* See note below on the multiport cards. */
 	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+	static struct pci_device_id early_486_chipsets[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496) },
+		{ },
+	};
 	static int last_irq;
 	static int multiport_cnt;	/* For four-port boards w/one EEPROM */
 	u8 chip_rev;
@@ -1274,17 +1279,15 @@
 	 *	without the workarounds being on.
 	 */
 
-	/* Intel Saturn. Switch to 8 long words burst, 8 long word cache aligned
-	   Aries might need this too. The Saturn errata are not pretty reading but
-	   thankfully it's an old 486 chipset.
+	/* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache
+	      aligned.  Aries might need this too. The Saturn errata are not 
+	      pretty reading but thankfully it's an old 486 chipset.
+
+	   2. The dreaded SiS496 486 chipset. Same workaround as Intel
+	      Saturn.
 	*/
 
-	if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL)) {
-		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
-		force_csr0 = 1;
-	}
-	/* The dreaded SiS496 486 chipset. Same workaround as above. */
-	if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL)) {
+	if (pci_dev_present(early_486_chipsets)) {
 		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
 		force_csr0 = 1;
 	}
diff -Nru a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
--- a/drivers/net/tulip/xircom_cb.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/tulip/xircom_cb.c	2004-10-28 22:25:59 -07:00
@@ -117,6 +117,9 @@
 static int xircom_close(struct net_device *dev);
 static void xircom_up(struct xircom_private *card);
 static struct net_device_stats *xircom_get_stats(struct net_device *dev);
+#if CONFIG_NET_POLL_CONTROLLER
+static void xircom_poll_controller(struct net_device *dev);
+#endif
 
 static void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset);
 static void investigate_write_descriptor(struct net_device *dev, struct xircom_private *card, int descnr, unsigned int bufferoffset);
@@ -256,7 +259,7 @@
 	private->dev = dev;
 	private->pdev = pdev;
 	private->io_port = pci_resource_start(pdev, 0);
-	private->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&private->lock);
 	dev->irq = pdev->irq;
 	dev->base_addr = private->io_port;
 	
@@ -269,6 +272,9 @@
 	dev->stop = &xircom_close;
 	dev->get_stats = &xircom_get_stats;
 	dev->priv = private;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &xircom_poll_controller;
+#endif
 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 	pci_set_drvdata(pdev, dev);
 
@@ -500,6 +506,14 @@
 } 
                                                  
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void xircom_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	xircom_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 
 static void initialize_card(struct xircom_private *card)
diff -Nru a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
--- a/drivers/net/tulip/xircom_tulip_cb.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/tulip/xircom_tulip_cb.c	2004-10-28 22:25:57 -07:00
@@ -584,7 +584,7 @@
 
 	tp = netdev_priv(dev);
 
-	tp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&tp->lock);
 	tp->pdev = pdev;
 	tp->chip_id = chip_idx;
 	/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */
diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
--- a/drivers/net/wan/cosa.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/wan/cosa.c	2004-10-28 22:25:56 -07:00
@@ -156,7 +156,7 @@
 	unsigned short startaddr;	/* Firmware start address */
 	unsigned short busmaster;	/* Use busmastering? */
 	int nchannels;			/* # of channels on this card */
-	int driver_status;		/* For communicating with firware */
+	int driver_status;		/* For communicating with firmware */
 	int firmware_status;		/* Downloaded, reseted, etc. */
 	long int rxbitmap, txbitmap;	/* Bitmap of channels who are willing to send/receive data */
 	long int rxtx;			/* RX or TX in progress? */
diff -Nru a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
--- a/drivers/net/wan/cycx_main.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/wan/cycx_main.c	2004-10-28 22:25:58 -07:00
@@ -225,7 +225,7 @@
 	card->hw.irq	 = irq;
 	card->hw.dpmsize = CYCX_WINDOWSIZE;
 	card->hw.fwid	 = CFID_X25_2X;
-	card->lock	 = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&card->lock);
 	init_waitqueue_head(&card->wait_stats);
 
 	rc = cycx_setup(&card->hw, conf->data, conf->data_size, conf->maddr);
diff -Nru a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
--- a/drivers/net/wan/cycx_x25.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/wan/cycx_x25.c	2004-10-28 22:25:57 -07:00
@@ -231,7 +231,7 @@
 	/* Initialize protocol-specific fields */
 	card->mbox  = card->hw.dpmbase + X25_MBOX_OFFS;
 	card->u.x.connection_keys = 0;
-	card->u.x.lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&card->u.x.lock);
 
 	/* Configure adapter. Here we set reasonable defaults, then parse
 	 * device configuration structure and set configuration options.
diff -Nru a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
--- a/drivers/net/wan/dscc4.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/wan/dscc4.c	2004-10-28 22:25:59 -07:00
@@ -518,7 +518,6 @@
 	skb = dev_alloc_skb(len);
 	dpriv->rx_skbuff[dirty] = skb;
 	if (skb) {
-		skb->dev = dev;
 		skb->protocol = hdlc_type_trans(skb, dev);
 		skb->mac.raw = skb->data;
 		rx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data,
diff -Nru a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
--- a/drivers/net/wan/farsync.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/net/wan/farsync.c	2004-10-28 22:25:58 -07:00
@@ -857,6 +857,18 @@
 	dev->trans_start = jiffies;
 }
 
+/*
+ * Mark it for our own raw sockets interface
+ */
+static unsigned short farsync_type_trans(struct sk_buff *skb,
+					 struct net_device *dev)
+{
+	skb->dev = dev;
+	skb->mac.raw = skb->data;
+	skb->pkt_type = PACKET_HOST;
+	return htons(ETH_P_CUST);
+}
+
 /*      Rx dma complete interrupt
  */
 static void
@@ -881,17 +893,10 @@
 
 	/* Push upstream */
 	dbg(DBG_RX, "Pushing the frame up the stack\n");
-	skb->mac.raw = skb->data;
-	skb->dev = dev;
-	if (port->mode == FST_RAW) {
-		/*
-		 * Mark it for our own raw sockets interface
-		 */
-		skb->protocol = htons(ETH_P_CUST);
-		skb->pkt_type = PACKET_HOST;
-	} else {
-		skb->protocol = hdlc_type_trans(skb, skb->dev);
-	}
+	if (port->mode == FST_RAW)
+		skb->protocol = farsync_type_trans(skb, dev);
+	else
+		skb->protocol = hdlc_type_trans(skb, dev);
 	rx_status = netif_rx(skb);
 	fst_process_rx_status(rx_status, port_to_dev(port)->name);
 	if (rx_status == NET_RX_DROP)
@@ -1316,17 +1321,10 @@
 
 		/* Push upstream */
 		dbg(DBG_RX, "Pushing frame up the stack\n");
-		skb->mac.raw = skb->data;
-		skb->dev = dev;
-		if (port->mode == FST_RAW) {
-			/*
-			 * Mark it for our own raw sockets interface
-			 */
-			skb->protocol = htons(ETH_P_CUST);
-			skb->pkt_type = PACKET_HOST;
-		} else {
-			skb->protocol = hdlc_type_trans(skb, skb->dev);
-		}
+		if (port->mode == FST_RAW)
+			skb->protocol = farsync_type_trans(skb, dev);
+		else
+			skb->protocol = hdlc_type_trans(skb, dev);
 		rx_status = netif_rx(skb);
 		fst_process_rx_status(rx_status, port_to_dev(port)->name);
 		if (rx_status == NET_RX_DROP) {
diff -Nru a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
--- a/drivers/net/wan/hd6457x.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/wan/hd6457x.c	2004-10-28 22:25:57 -07:00
@@ -315,8 +315,6 @@
 #endif
 	stats->rx_packets++;
 	stats->rx_bytes += skb->len;
-	skb->mac.raw = skb->data;
-	skb->dev = dev;
 	skb->dev->last_rx = jiffies;
 	skb->protocol = hdlc_type_trans(skb, dev);
 	netif_rx(skb);
diff -Nru a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
--- a/drivers/net/wan/lmc/lmc_main.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/wan/lmc/lmc_main.c	2004-10-28 22:25:57 -07:00
@@ -101,7 +101,6 @@
 static int lmc_close(struct net_device *dev);
 static struct net_device_stats *lmc_get_stats(struct net_device *dev);
 static irqreturn_t lmc_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static int lmc_set_config(struct net_device *dev, struct ifmap *map);
 static void lmc_initcsrs(lmc_softc_t * const sc, lmc_csrptr_t csr_base, size_t csr_size);
 static void lmc_softreset(lmc_softc_t * const);
 static void lmc_running_reset(struct net_device *dev);
@@ -814,7 +813,6 @@
     dev->stop = lmc_close;
     dev->get_stats = lmc_get_stats;
     dev->do_ioctl = lmc_ioctl;
-    dev->set_config = lmc_set_config;
     dev->tx_timeout = lmc_driver_timeout;
     dev->watchdog_timeo = (HZ); /* 1 second */
     
@@ -1973,13 +1971,6 @@
     LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring));
 
     lmc_trace(sc->lmc_device, "lmc_softreset out");
-}
-
-static int lmc_set_config(struct net_device *dev, struct ifmap *map) /*fold00*/
-{
-    lmc_trace(dev, "lmc_set_config in");
-    lmc_trace(dev, "lmc_set_config out");
-    return -EOPNOTSUPP;
 }
 
 void lmc_gpio_mkinput(lmc_softc_t * const sc, u_int32_t bits) /*fold00*/
diff -Nru a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
--- a/drivers/net/wan/pc300_drv.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/wan/pc300_drv.c	2004-10-28 22:25:59 -07:00
@@ -1959,7 +1959,6 @@
 			cpc_trace(dev, skb, 'R');
 		}
 		stats->rx_packets++;
-		skb->mac.raw = skb->data;
 		skb->protocol = hdlc_type_trans(skb, dev);
 		netif_rx(skb);
 	}
diff -Nru a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
--- a/drivers/net/wan/wanxl.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/wan/wanxl.c	2004-10-28 22:25:59 -07:00
@@ -224,8 +224,6 @@
 #endif
 				stats->rx_packets++;
 				stats->rx_bytes += skb->len;
-				skb->mac.raw = skb->data;
-				skb->dev = dev;
 				dev->last_rx = jiffies;
 				skb->protocol = hdlc_type_trans(skb, dev);
 				netif_rx(skb);
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/net/wireless/airo.c	2004-10-28 22:25:57 -07:00
@@ -2722,7 +2722,7 @@
 		set_bit(FLAG_MPI, &ai->flags);
 	}
         ai->dev = dev;
-	ai->aux_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&ai->aux_lock);
 	sema_init(&ai->sem, 1);
 	ai->config.len = 0;
 	ai->pci = pci;
diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
--- a/drivers/net/wireless/netwave_cs.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/net/wireless/netwave_cs.c	2004-10-28 22:25:59 -07:00
@@ -219,7 +219,6 @@
 /* Misc device stuff */
 static int netwave_open(struct net_device *dev);  /* Open the device */
 static int netwave_close(struct net_device *dev); /* Close the device */
-static int netwave_config(struct net_device *dev, struct ifmap *map);
 
 /* Packet transmission and Packet reception */
 static int netwave_start_xmit( struct sk_buff *skb, struct net_device *dev);
@@ -482,7 +481,6 @@
     /* Netwave specific entries in the device structure */
     SET_MODULE_OWNER(dev);
     dev->hard_start_xmit = &netwave_start_xmit;
-    dev->set_config = &netwave_config;
     dev->get_stats  = &netwave_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     /* wireless extensions */
@@ -1286,16 +1284,6 @@
     /* Set the IENA bit in COR */
     wait_WOC(iobase);
     outb(corConfIENA + corConfLVLREQ, iobase + NETWAVE_REG_COR);
-}
-
-/*
- * Function netwave_config (dev, map)
- *
- *    Configure device, this work is done by netwave_pcmcia_config when a
- *    card is inserted
- */
-static int netwave_config(struct net_device *dev, struct ifmap *map) {
-    return 0; 
 }
 
 /*
diff -Nru a/drivers/net/znet.c b/drivers/net/znet.c
--- a/drivers/net/znet.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/net/znet.c	2004-10-28 22:25:56 -07:00
@@ -421,7 +421,7 @@
 
 	znet->rx_dma = netinfo->dma1;
 	znet->tx_dma = netinfo->dma2;
-	znet->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&znet->lock);
 	znet->sia_base = 0xe6;	/* Magic address for the 82501 SIA */
 	znet->sia_size = 2;
 	/* maz: Despite the '593 being advertised above as using a
diff -Nru a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
--- a/drivers/oprofile/oprofilefs.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/oprofile/oprofilefs.c	2004-10-28 22:25:57 -07:00
@@ -135,11 +135,8 @@
 {
 	struct dentry * dentry;
 	struct inode * inode;
-	struct qstr qname;
-	qname.name = name;
-	qname.len = strlen(name);
-	qname.hash = full_name_hash(qname.name, qname.len);
-	dentry = d_alloc(root, &qname);
+
+	dentry = d_alloc_name(root, name);
 	if (!dentry)
 		return NULL;
 	inode = oprofilefs_get_inode(sb, S_IFREG | perm);
@@ -228,11 +225,8 @@
 {
 	struct dentry * dentry;
 	struct inode * inode;
-	struct qstr qname;
-	qname.name = name;
-	qname.len = strlen(name);
-	qname.hash = full_name_hash(qname.name, qname.len);
-	dentry = d_alloc(root, &qname);
+
+	dentry = d_alloc_name(root, name);
 	if (!dentry)
 		return NULL;
 	inode = oprofilefs_get_inode(sb, S_IFDIR | 0755);
diff -Nru a/drivers/parport/daisy.c b/drivers/parport/daisy.c
--- a/drivers/parport/daisy.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/parport/daisy.c	2004-10-28 22:25:57 -07:00
@@ -207,8 +207,7 @@
  *
  *	This function is similar to parport_register_device(), except
  *	that it locates a device by its number rather than by the port
- *	it is attached to.  See parport_find_device() and
- *	parport_find_class().
+ *	it is attached to.
  *
  *	All parameters except for @devnum are the same as for
  *	parport_register_device().  The return value is the same as
@@ -305,53 +304,6 @@
 	return res;
 }
 
-/**
- *	parport_device_coords - convert canonical device number
- *	@devnum: device number
- *	@parport: pointer to storage for parallel port number
- *	@mux: pointer to storage for multiplexor port number
- *	@daisy: pointer to storage for daisy chain address
- *
- *	This function converts a device number into its coordinates in
- *	terms of which parallel port in the system it is attached to,
- *	which multiplexor port it is attached to if there is a
- *	multiplexor on that port, and which daisy chain address it has
- *	if it is in a daisy chain.
- *
- *	The caller must allocate storage for @parport, @mux, and
- *	@daisy.
- *
- *	If there is no device with the specified device number, -ENXIO
- *	is returned.  Otherwise, the values pointed to by @parport,
- *	@mux, and @daisy are set to the coordinates of the device,
- *	with -1 for coordinates with no value.
- *
- *	This function is not actually very useful, but this interface
- *	was suggested by IEEE 1284.3.
- **/
-
-int parport_device_coords (int devnum, int *parport, int *mux, int *daisy)
-{
-	struct daisydev *dev;
-
-	spin_lock(&topology_lock);
-
-	dev = topology;
-	while (dev && dev->devnum != devnum)
-		dev = dev->next;
-
-	if (!dev) {
-		spin_unlock(&topology_lock);
-		return -ENXIO;
-	}
-
-	if (parport) *parport = dev->port->portnum;
-	if (mux) *mux = dev->port->muxport;
-	if (daisy) *daisy = dev->daisy;
-	spin_unlock(&topology_lock);
-	return 0;
-}
-
 /* Send a daisy-chain-style CPP command packet. */
 static int cpp_daisy (struct parport *port, int cmd)
 {
@@ -558,108 +510,3 @@
 	kfree (deviceid);
 	return detected;
 }
-
-/* Find a device with a particular manufacturer and model string,
-   starting from a given device number.  Like the PCI equivalent,
-   'from' itself is skipped. */
-
-/**
- *	parport_find_device - find a specific device
- *	@mfg: required manufacturer string
- *	@mdl: required model string
- *	@from: previous device number found in search, or %NULL for
- *	       new search
- *
- *	This walks through the list of parallel port devices looking
- *	for a device whose 'MFG' string matches @mfg and whose 'MDL'
- *	string matches @mdl in their IEEE 1284 Device ID.
- *
- *	When a device is found matching those requirements, its device
- *	number is returned; if there is no matching device, a negative
- *	value is returned.
- *
- *	A new search it initiated by passing %NULL as the @from
- *	argument.  If @from is not %NULL, the search continues from
- *	that device.
- **/
-
-int parport_find_device (const char *mfg, const char *mdl, int from)
-{
-	struct daisydev *d;
-	int res = -1;
-
-	/* Find where to start. */
-
-	spin_lock(&topology_lock);
-	d = topology; /* sorted by devnum */
-	while (d && d->devnum <= from)
-		d = d->next;
-
-	/* Search. */
-	while (d) {
-		struct parport_device_info *info;
-		info = &d->port->probe_info[1 + d->daisy];
-		if ((!mfg || !strcmp (mfg, info->mfr)) &&
-		    (!mdl || !strcmp (mdl, info->model)))
-			break;
-
-		d = d->next;
-	}
-
-	if (d)
-		res = d->devnum;
-
-	spin_unlock(&topology_lock);
-	return res;
-}
-
-/**
- *	parport_find_class - find a device in a specified class
- *	@cls: required class
- *	@from: previous device number found in search, or %NULL for
- *	       new search
- *
- *	This walks through the list of parallel port devices looking
- *	for a device whose 'CLS' string matches @cls in their IEEE
- *	1284 Device ID.
- *
- *	When a device is found matching those requirements, its device
- *	number is returned; if there is no matching device, a negative
- *	value is returned.
- *
- *	A new search it initiated by passing %NULL as the @from
- *	argument.  If @from is not %NULL, the search continues from
- *	that device.
- **/
-
-int parport_find_class (parport_device_class cls, int from)
-{
-	struct daisydev *d;
-	int res = -1;
-
-	spin_lock(&topology_lock);
-	d = topology; /* sorted by devnum */
-	/* Find where to start. */
-	while (d && d->devnum <= from)
-		d = d->next;
-
-	/* Search. */
-	while (d && d->port->probe_info[1 + d->daisy].class != cls)
-		d = d->next;
-
-	if (d)
-		res = d->devnum;
-
-	spin_unlock(&topology_lock);
-	return res;
-}
-
-EXPORT_SYMBOL(parport_open);
-EXPORT_SYMBOL(parport_close);
-EXPORT_SYMBOL(parport_device_num);
-EXPORT_SYMBOL(parport_device_coords);
-EXPORT_SYMBOL(parport_daisy_deselect_all);
-EXPORT_SYMBOL(parport_daisy_select);
-EXPORT_SYMBOL(parport_daisy_init);
-EXPORT_SYMBOL(parport_find_device);
-EXPORT_SYMBOL(parport_find_class);
diff -Nru a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
--- a/drivers/parport/ieee1284.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/parport/ieee1284.c	2004-10-28 22:25:56 -07:00
@@ -40,7 +40,7 @@
 
 /* Make parport_wait_peripheral wake up.
  * It will be useful to call this from an interrupt handler. */
-void parport_ieee1284_wakeup (struct parport *port)
+static void parport_ieee1284_wakeup (struct parport *port)
 {
 	up (&port->physport->ieee1284.irq);
 }
@@ -813,9 +813,7 @@
 EXPORT_SYMBOL(parport_negotiate);
 EXPORT_SYMBOL(parport_write);
 EXPORT_SYMBOL(parport_read);
-EXPORT_SYMBOL(parport_ieee1284_wakeup);
 EXPORT_SYMBOL(parport_wait_peripheral);
-EXPORT_SYMBOL(parport_poll_peripheral);
 EXPORT_SYMBOL(parport_wait_event);
 EXPORT_SYMBOL(parport_set_timeout);
 EXPORT_SYMBOL(parport_ieee1284_interrupt);
diff -Nru a/drivers/parport/probe.c b/drivers/parport/probe.c
--- a/drivers/parport/probe.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/parport/probe.c	2004-10-28 22:25:57 -07:00
@@ -213,4 +213,3 @@
 	parport_close (dev);
 	return retval;
 }
-EXPORT_SYMBOL(parport_device_id);
diff -Nru a/drivers/parport/procfs.c b/drivers/parport/procfs.c
--- a/drivers/parport/procfs.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/parport/procfs.c	2004-10-28 22:25:57 -07:00
@@ -529,8 +529,5 @@
 }
 #endif
 
-EXPORT_SYMBOL(parport_device_proc_register);
-EXPORT_SYMBOL(parport_device_proc_unregister);
-
 module_init(parport_default_proc_register)
 module_exit(parport_default_proc_unregister)
diff -Nru a/drivers/parport/share.c b/drivers/parport/share.c
--- a/drivers/parport/share.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/parport/share.c	2004-10-28 22:25:58 -07:00
@@ -1007,7 +1007,6 @@
 EXPORT_SYMBOL(parport_unregister_driver);
 EXPORT_SYMBOL(parport_register_device);
 EXPORT_SYMBOL(parport_unregister_device);
-EXPORT_SYMBOL(parport_get_port);
 EXPORT_SYMBOL(parport_put_port);
 EXPORT_SYMBOL(parport_find_number);
 EXPORT_SYMBOL(parport_find_base);
diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
--- a/drivers/pci/hotplug/pci_hotplug_core.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/pci/hotplug/pci_hotplug_core.c	2004-10-28 22:25:59 -07:00
@@ -568,7 +568,7 @@
 	if ((slot->info == NULL) || (slot->ops == NULL))
 		return -EINVAL;
 
-	kobject_set_name(&slot->kobj, slot->name);
+	kobject_set_name(&slot->kobj, "%s", slot->name);
 	kobj_set_kset_s(slot, pci_hotplug_slots_subsys);
 
 	/* this can fail if we have already registered a slot with the same name */
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/pci/quirks.c	2004-10-28 22:25:56 -07:00
@@ -18,7 +18,6 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/irq.h>
 
 #undef DEBUG
 
@@ -1211,58 +1210,12 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_ANY_ID,	  quirk_intel_ide_combined );
 #endif /* CONFIG_SCSI_SATA */
 
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
-
-void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
-{
-	u8 config, rev;
-	u32 word;
-	extern struct pci_raw_ops *raw_pci_ops;
-
-	/* BIOS may enable hardware IRQ balancing for
-	 * E7520/E7320/E7525(revision ID 0x9 and below)
-	 * based platforms.
-	 * Disable SW irqbalance/affinity on those platforms.
-	 */
-	pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev);
-	if (rev > 0x9)
-		return;
-
-	printk(KERN_INFO "Intel E7520/7320/7525 detected.");
-
-	/* enable access to config space*/
-	pci_read_config_byte(dev, 0xf4, &config);
-	config |= 0x2;
-	pci_write_config_byte(dev, 0xf4, config);
-
-	/* read xTPR register */
-	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
-
-	if (!(word & (1 << 13))) {
-		printk(KERN_INFO "Disabling irq balancing and affinity\n");
-#ifdef CONFIG_IRQBALANCE
-		irqbalance_disable("");
-#endif
-		noirqdebug_setup("");
-		no_irq_affinity = 1;
-	}
-
-	config &= ~0x2;
-	/* disable access to config space*/
-	pci_write_config_byte(dev, 0xf4, config);
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7320_MCH,	quirk_intel_irqbalance);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7525_MCH,	quirk_intel_irqbalance);
-#endif
 
 int pciehp_msi_quirk;
 
 static void __devinit quirk_pciehp_msi(struct pci_dev *pdev)
 {
 	pciehp_msi_quirk = 1;
-#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
-	quirk_intel_irqbalance(pdev);
-#endif
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_SMCH,	quirk_pciehp_msi );
 
diff -Nru a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
--- a/drivers/pcmcia/bulkmem.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/pcmcia/bulkmem.c	2004-10-28 22:25:59 -07:00
@@ -49,11 +49,11 @@
 #include "cs_internal.h"
 
 #ifdef DEBUG
-extern int pc_debug;
+extern int ds_pc_debug;
 #define cs_socket_name(skt)	((skt)->dev.class_id)
 
 #define ds_dbg(skt, lvl, fmt, arg...) do {		\
-	if (pc_debug >= lvl)				\
+	if (ds_pc_debug >= lvl)				\
 		printk(KERN_DEBUG "ds: %s: " fmt, 	\
 		       cs_socket_name(skt) , ## arg);	\
 } while (0)
diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
--- a/drivers/pcmcia/cistpl.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/pcmcia/cistpl.c	2004-10-28 22:25:57 -07:00
@@ -331,6 +331,14 @@
 		list_del(&cis->node);
 		kfree(cis);
 	}
+
+	/*
+	 * If there was a fake CIS, destroy that as well.
+	 */
+	if (s->fake_cis) {
+		kfree(s->fake_cis);
+		s->fake_cis = NULL;
+	}
 }
 
 /*======================================================================
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/pcmcia/cs.c	2004-10-28 22:25:57 -07:00
@@ -364,10 +364,6 @@
     s->irq.AssignedIRQ = s->irq.Config = 0;
     s->lock_count = 0;
     destroy_cis_cache(s);
-    if (s->fake_cis) {
-	kfree(s->fake_cis);
-	s->fake_cis = NULL;
-    }
 #ifdef CONFIG_CARDBUS
     cb_free(s);
 #endif
@@ -613,10 +609,18 @@
 		 * FIXME: need a better check here for cardbus cards.
 		 */
 		if (verify_cis_cache(skt) != 0) {
+			cs_dbg(skt, 4, "cis mismatch - different card\n");
 			socket_remove_drivers(skt);
 			destroy_cis_cache(skt);
+			/*
+			 * Workaround: give DS time to schedule removal.
+			 * Remove me once the 100ms delay is eliminated
+			 * in ds.c
+			 */
+			msleep(200);
 			send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
 		} else {
+			cs_dbg(skt, 4, "cis matches cache\n");
 			send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
 		}
 	} else {
diff -Nru a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
--- a/drivers/pcmcia/ds.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/pcmcia/ds.c	2004-10-28 22:25:59 -07:00
@@ -75,12 +75,12 @@
 MODULE_LICENSE("Dual MPL/GPL");
 
 #ifdef DEBUG
-int pc_debug;
+int ds_pc_debug;
 
-module_param(pc_debug, int, 0644);
+module_param_named(pc_debug, ds_pc_debug, int, 0644);
 
 #define ds_dbg(lvl, fmt, arg...) do {				\
-	if (pc_debug > (lvl))					\
+	if (ds_pc_debug > (lvl))					\
 		printk(KERN_DEBUG "ds: " fmt , ## arg);		\
 } while (0)
 #else
@@ -1060,7 +1060,11 @@
 	}
     }
 
-    if (cmd & IOC_OUT) __copy_to_user(uarg, (char *)&buf, size);
+    if (cmd & IOC_OUT) {
+        if (__copy_to_user(uarg, (char *)&buf, size))
+            err = -EFAULT;
+    }
+
 
     return err;
 } /* ds_ioctl */
diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
--- a/drivers/pnp/pnpbios/core.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/pnp/pnpbios/core.c	2004-10-28 22:25:56 -07:00
@@ -60,6 +60,7 @@
 #include <linux/completion.h>
 #include <linux/spinlock.h>
 #include <linux/dmi.h>
+#include <linux/delay.h>
 
 #include <asm/page.h>
 #include <asm/desc.h>
@@ -177,8 +178,7 @@
 		/*
 		 * Poll every 2 seconds
 		 */
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ*2);
+		msleep_interruptible(2000);
 		if(signal_pending(current))
 			break;
 
@@ -537,6 +537,14 @@
 		printk(KERN_INFO "PnPBIOS: Disabled\n");
 		return -ENODEV;
 	}
+
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled) {
+		pnpbios_disabled = 1;
+		printk(KERN_INFO "PnPBIOS: Disabled by ACPI\n");
+		return -ENODEV;
+	}
+#endif /* CONFIG_ACPI */
 
 	/* scan the system for pnpbios support */
 	if (!pnpbios_probe_system())
diff -Nru a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
--- a/drivers/s390/block/dcssblk.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/s390/block/dcssblk.c	2004-10-28 22:25:57 -07:00
@@ -140,6 +140,53 @@
 }
 
 /*
+ * print appropriate error message for segment_load()/segment_info()
+ * return code
+ */
+static void
+dcssblk_segment_warn(int rc, char* seg_name)
+{
+	switch (rc) {
+	case -ENOENT:
+		PRINT_WARN("cannot load/query segment %s, does not exist\n",
+			   seg_name);
+		break;
+	case -ENOSYS:
+		PRINT_WARN("cannot load/query segment %s, not running on VM\n",
+			   seg_name);
+		break;
+	case -EIO:
+		PRINT_WARN("cannot load/query segment %s, hardware error\n",
+			   seg_name);
+		break;
+	case -ENOTSUPP:
+		PRINT_WARN("cannot load/query segment %s, is a multi-part "
+			   "segment\n", seg_name);
+		break;
+	case -ENOSPC:
+		PRINT_WARN("cannot load/query segment %s, overlaps with "
+			   "storage\n", seg_name);
+		break;
+	case -EBUSY:
+		PRINT_WARN("cannot load/query segment %s, overlaps with "
+			   "already loaded dcss\n", seg_name);
+		break;
+	case -EPERM:
+		PRINT_WARN("cannot load/query segment %s, already loaded in "
+			   "incompatible mode\n", seg_name);
+		break;
+	case -ENOMEM:
+		PRINT_WARN("cannot load/query segment %s, out of memory\n",
+			   seg_name);
+		break;
+	default:
+		PRINT_WARN("cannot load/query segment %s, return value %i\n",
+			   seg_name, rc);
+		break;
+	}
+}
+
+/*
  * device attribute for switching shared/nonshared (exclusive)
  * operation (show + store)
  */
@@ -185,61 +232,38 @@
 	if (inbuf[0] == '1') {
 		// reload segment in shared mode
 		segment_unload(dev_info->segment_name);
-		rc = segment_load(dev_info->segment_name, SEGMENT_SHARED_RO,
+		rc = segment_load(dev_info->segment_name, SEGMENT_SHARED,
 					&dev_info->start, &dev_info->end);
 		if (rc < 0) {
-			PRINT_ERR("Segment %s not reloaded, rc=%d\n",
-					dev_info->segment_name, rc);
+			dcssblk_segment_warn(rc, dev_info->segment_name);
 			goto removeseg;
 		}
 		dev_info->is_shared = 1;
-		PRINT_INFO("Segment %s reloaded, shared mode.\n",
-			   dev_info->segment_name);
+		if (rc == SEG_TYPE_SR || rc == SEG_TYPE_ER || rc == SEG_TYPE_SC)
+			set_disk_ro(dev_info->gd, 1);
 	} else if (inbuf[0] == '0') {
 		// reload segment in exclusive mode
+		if (dev_info->segment_type == SEG_TYPE_SC) {
+			PRINT_ERR("Segment type SC (%s) cannot be loaded in "
+				  "non-shared mode\n", dev_info->segment_name);
+			up_write(&dcssblk_devices_sem);
+			return -EINVAL;
+		}
 		segment_unload(dev_info->segment_name);
-		rc = segment_load(dev_info->segment_name, SEGMENT_EXCLUSIVE_RW,
+		rc = segment_load(dev_info->segment_name, SEGMENT_EXCLUSIVE,
 					&dev_info->start, &dev_info->end);
 		if (rc < 0) {
-			PRINT_ERR("Segment %s not reloaded, rc=%d\n",
-					dev_info->segment_name, rc);
+			dcssblk_segment_warn(rc, dev_info->segment_name);
 			goto removeseg;
 		}
 		dev_info->is_shared = 0;
-		PRINT_INFO("Segment %s reloaded, exclusive (read-write) mode.\n",
-			   dev_info->segment_name);
+		set_disk_ro(dev_info->gd, 0);
 	} else {
 		up_write(&dcssblk_devices_sem);
 		PRINT_WARN("Invalid value, must be 0 or 1\n");
 		return -EINVAL;
 	}
-	dev_info->segment_type = rc;
 	rc = count;
-
-	switch (dev_info->segment_type) {
-		case SEGMENT_SHARED_RO:
-		case SEGMENT_EXCLUSIVE_RO:
-			set_disk_ro(dev_info->gd, 1);
-			break;
-		case SEGMENT_SHARED_RW:
-		case SEGMENT_EXCLUSIVE_RW:
-			set_disk_ro(dev_info->gd, 0);
-			break;
-	}
-	if ((inbuf[0] == '1') &&
-	   ((dev_info->segment_type == SEGMENT_EXCLUSIVE_RO) ||
-	    (dev_info->segment_type == SEGMENT_EXCLUSIVE_RW))) {
-		PRINT_WARN("Could not get shared copy of segment %s\n",
-				dev_info->segment_name);
-		rc = -EPERM;
-	}
-	if ((inbuf[0] == '0') &&
-	   ((dev_info->segment_type == SEGMENT_SHARED_RO) ||
-	    (dev_info->segment_type == SEGMENT_SHARED_RW))) {
-		PRINT_WARN("Could not get exclusive copy of segment %s\n",
-				dev_info->segment_name);
-		rc = -EPERM;
-	}
 	up_write(&dcssblk_devices_sem);
 	goto out;
 
@@ -292,7 +316,7 @@
 			// device is idle => we save immediately
 			PRINT_INFO("Saving segment %s\n",
 				   dev_info->segment_name);
-			segment_replace(dev_info->segment_name);
+			segment_save(dev_info->segment_name);
 		}  else {
 			// device is busy => we save it when it becomes
 			// idle in dcssblk_release
@@ -390,18 +414,17 @@
 	/*
 	 * load the segment
 	 */
-	rc = segment_load(local_buf, SEGMENT_SHARED_RO,
+	rc = segment_load(local_buf, SEGMENT_SHARED,
 				&dev_info->start, &dev_info->end);
 	if (rc < 0) {
-		PRINT_ERR("Segment %s not loaded, rc=%d\n", local_buf, rc);
+		dcssblk_segment_warn(rc, dev_info->segment_name);
 		goto dealloc_gendisk;
 	}
 	seg_byte_size = (dev_info->end - dev_info->start + 1);
 	set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors
-	PRINT_INFO("Loaded segment %s from %p to %p, size = %lu Byte, "
-		   "capacity = %lu sectors (512 Byte)\n", local_buf,
-		   	(void *) dev_info->start, (void *) dev_info->end,
-			seg_byte_size, seg_byte_size >> 9);
+	PRINT_INFO("Loaded segment %s, size = %lu Byte, "
+		   "capacity = %lu (512 Byte) sectors\n", local_buf,
+		   seg_byte_size, seg_byte_size >> 9);
 
 	dev_info->segment_type = rc;
 	dev_info->save_pending = 0;
@@ -451,12 +474,12 @@
 	blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
 
 	switch (dev_info->segment_type) {
-		case SEGMENT_SHARED_RO:
-		case SEGMENT_EXCLUSIVE_RO:
+		case SEG_TYPE_SR:
+		case SEG_TYPE_ER:
+		case SEG_TYPE_SC:
 			set_disk_ro(dev_info->gd,1);
 			break;
-		case SEGMENT_SHARED_RW:
-		case SEGMENT_EXCLUSIVE_RW:
+		default:
 			set_disk_ro(dev_info->gd,0);
 			break;
 	}
@@ -589,7 +612,7 @@
 	    && (dev_info->save_pending)) {
 		PRINT_INFO("Segment %s became idle and is being saved now\n",
 			    dev_info->segment_name);
-		segment_replace(dev_info->segment_name);
+		segment_save(dev_info->segment_name);
 		dev_info->save_pending = 0;
 	}
 	up_write(&dcssblk_devices_sem);
diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
--- a/drivers/s390/char/con3215.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/s390/char/con3215.c	2004-10-28 22:25:58 -07:00
@@ -987,7 +987,6 @@
 	      const unsigned char *buf, int count)
 {
 	struct raw3215_info *raw;
-	int length, ret;
 
 	if (!tty)
 		return 0;
diff -Nru a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
--- a/drivers/s390/char/monreader.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/s390/char/monreader.c	2004-10-28 22:25:57 -07:00
@@ -115,6 +115,53 @@
 	ASCEBC(ebcdic_name, 8);
 }
 
+/*
+ * print appropriate error message for segment_load()/segment_info()
+ * return code
+ */
+static void
+mon_segment_warn(int rc, char* seg_name)
+{
+	switch (rc) {
+	case -ENOENT:
+		P_WARNING("cannot load/query segment %s, does not exist\n",
+			  seg_name);
+		break;
+	case -ENOSYS:
+		P_WARNING("cannot load/query segment %s, not running on VM\n",
+			  seg_name);
+		break;
+	case -EIO:
+		P_WARNING("cannot load/query segment %s, hardware error\n",
+			  seg_name);
+		break;
+	case -ENOTSUPP:
+		P_WARNING("cannot load/query segment %s, is a multi-part "
+			  "segment\n", seg_name);
+		break;
+	case -ENOSPC:
+		P_WARNING("cannot load/query segment %s, overlaps with "
+			  "storage\n", seg_name);
+		break;
+	case -EBUSY:
+		P_WARNING("cannot load/query segment %s, overlaps with "
+			  "already loaded dcss\n", seg_name);
+		break;
+	case -EPERM:
+		P_WARNING("cannot load/query segment %s, already loaded in "
+			  "incompatible mode\n", seg_name);
+		break;
+	case -ENOMEM:
+		P_WARNING("cannot load/query segment %s, out of memory\n",
+			  seg_name);
+		break;
+	default:
+		P_WARNING("cannot load/query segment %s, return value %i\n",
+			  seg_name, rc);
+		break;
+	}
+}
+
 static inline unsigned long
 mon_mca_start(struct mon_msg *monmsg)
 {
@@ -534,10 +581,21 @@
 		return -ENODEV;
 	}
 
-	rc = segment_load(mon_dcss_name, SEGMENT_SHARED_RO,
+	rc = segment_info(mon_dcss_name);
+	if (rc < 0) {
+		mon_segment_warn(rc, mon_dcss_name);
+		return rc;
+	}
+	if (rc != SEG_TYPE_SC) {
+		P_ERROR("segment %s has unsupported type, should be SC\n",
+			mon_dcss_name);
+		return -EINVAL;
+	}
+
+	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
 			  &mon_dcss_start, &mon_dcss_end);
 	if (rc < 0) {
-		P_ERROR("Segment %s not loaded, rc = %d\n", mon_dcss_name, rc);
+		mon_segment_warn(rc, mon_dcss_name);
 		return -EINVAL;
 	}
 	dcss_mkname(mon_dcss_name, &user_data_connect[8]);
diff -Nru a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
--- a/drivers/s390/char/sclp_tty.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/s390/char/sclp_tty.c	2004-10-28 22:25:59 -07:00
@@ -397,8 +397,6 @@
 static int
 sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
-	int length, ret;
-
 	if (sclp_tty_chars_count > 0) {
 		sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
 		sclp_tty_chars_count = 0;
@@ -603,7 +601,7 @@
 
 	/* if set in ioctl write operators input to console  */
 	if (sclp_ioctls.echo)
-		sclp_tty_write(sclp_tty, 0, start, count);
+		sclp_tty_write(sclp_tty, start, count);
 
 	/* transfer input to high level driver */
 	sclp_tty_input(start, count);
diff -Nru a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
--- a/drivers/s390/char/tty3270.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/s390/char/tty3270.c	2004-10-28 22:25:57 -07:00
@@ -1603,7 +1603,6 @@
 	      const unsigned char *buf, int count)
 {
 	struct tty3270 *tp;
-	int length, ret;
 
 	tp = tty->driver_data;
 	if (!tp)
diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
--- a/drivers/s390/cio/qdio.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/s390/cio/qdio.c	2004-10-28 22:25:58 -07:00
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.86 $"
+#define VERSION_QDIO_C "$Revision: 1.88 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -808,7 +808,7 @@
 #endif /* QDIO_USE_PROCESSING_STATE */
 		/* 
 		 * not needed, as the inbound queue will be synced on the next
-		 * siga-r
+		 * siga-r, resp. tiqdio_is_inbound_q_done will do the siga-s
 		 */
 		/*SYNC_MEMORY;*/
 		f++;
@@ -899,7 +899,7 @@
 
 /* means, no more buffers to be filled */
 inline static int
-iqdio_is_inbound_q_done(struct qdio_q *q)
+tiqdio_is_inbound_q_done(struct qdio_q *q)
 {
 	int no_used;
 #ifdef CONFIG_QDIO_DEBUG
@@ -1139,7 +1139,7 @@
 		goto out;
 
 	qdio_kick_inbound_handler(q);
-	if (iqdio_is_inbound_q_done(q))
+	if (tiqdio_is_inbound_q_done(q))
 		if (!qdio_stop_polling(q)) {
 			/* 
 			 * we set the flags to get into the stuff next time,
@@ -1401,7 +1401,7 @@
 	int result=-ENOMEM;
 
 	for (i=0;i<no_input_qs;i++) {
-		q=kmalloc(sizeof(struct qdio_q),GFP_KERNEL);
+		q=kmalloc(sizeof(struct qdio_q),GFP_KERNEL|GFP_DMA);
 
 		if (!q) {
 			QDIO_PRINT_ERR("kmalloc of q failed!\n");
@@ -1410,7 +1410,7 @@
 
 		memset(q,0,sizeof(struct qdio_q));
 
-		q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL);
+		q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL|GFP_DMA);
 		if (!q->slib) {
 			QDIO_PRINT_ERR("kmalloc of slib failed!\n");
 			goto out;
@@ -1420,7 +1420,7 @@
 	}
 
 	for (i=0;i<no_output_qs;i++) {
-		q=kmalloc(sizeof(struct qdio_q),GFP_KERNEL);
+		q=kmalloc(sizeof(struct qdio_q),GFP_KERNEL|GFP_DMA);
 
 		if (!q) {
 			goto out;
@@ -1428,7 +1428,7 @@
 
 		memset(q,0,sizeof(struct qdio_q));
 
-		q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL);
+		q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL|GFP_DMA);
 		if (!q->slib) {
 			QDIO_PRINT_ERR("kmalloc of slib failed!\n");
 			goto out;
diff -Nru a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
--- a/drivers/s390/net/ctcdbug.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/s390/net/ctcdbug.h	2004-10-28 22:25:57 -07:00
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.3 $)
+ * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $)
  *
  * CTC / ESCON network driver - s390 dbf exploit.
  *
@@ -9,7 +9,7 @@
  *    Author(s): Original Code written by
  *			  Peter Tiedemann (ptiedem@de.ibm.com)
  *
- *    $Revision: 1.3 $	 $Date: 2004/07/28 12:27:54 $
+ *    $Revision: 1.4 $	 $Date: 2004/10/15 09:26:58 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@
 		debug_event(ctc_dbf_##name,level,(void*)(addr),len); \
 	} while (0)
 
-extern DEFINE_PER_CPU(char[256], ctc_dbf_txt_buf);
+DECLARE_PER_CPU(char[256], ctc_dbf_txt_buf);
 extern debug_info_t *ctc_dbf_setup;
 extern debug_info_t *ctc_dbf_data;
 extern debug_info_t *ctc_dbf_trace;
diff -Nru a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
--- a/drivers/s390/net/iucv.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/s390/net/iucv.h	2004-10-28 22:25:59 -07:00
@@ -63,7 +63,7 @@
 		debug_event(iucv_dbf_##name,level,(void*)(addr),len); \
 	} while (0)
 
-extern DEFINE_PER_CPU(char[256], iucv_dbf_txt_buf);
+DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf);
 
 #define IUCV_DBF_TEXT_(name,level,text...)				\
 	do {								\
diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
--- a/drivers/s390/net/lcs.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/s390/net/lcs.c	2004-10-28 22:25:57 -07:00
@@ -11,7 +11,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.92 $	 $Date: 2004/09/03 08:06:11 $
+ *    $Revision: 1.94 $	 $Date: 2004/10/19 09:30:54 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.92 $"
+#define VERSION_LCS_C  "$Revision: 1.94 $"
 
 static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
 static char debug_buffer[255];
@@ -549,6 +549,7 @@
 		return 0;
 	LCS_DBF_TEXT(4,trace,"haltsch");
 	LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id);
+	channel->state = CH_STATE_INIT;
 	spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
 	rc = ccw_device_halt(channel->ccwdev, (addr_t) channel);
 	spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
@@ -1357,6 +1358,7 @@
 
 	LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
 	LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
+	LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl);
 
 	/* How far in the ccw chain have we processed? */
 	if ((channel->state != CH_STATE_INIT) &&
@@ -1624,8 +1626,6 @@
 	/* start/reset card */
 	if (card->dev)
 		netif_stop_queue(card->dev);
-	card->write.state = CH_STATE_INIT;
-	card->read.state = CH_STATE_INIT;
 	rc = lcs_stop_channels(card);
 	if (rc == 0) {
 		rc = lcs_start_channels(card);
diff -Nru a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
--- a/drivers/s390/net/qeth.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/s390/net/qeth.h	2004-10-28 22:25:56 -07:00
@@ -92,7 +92,7 @@
 		debug_event(qeth_dbf_##name,level,(void*)(addr),len); \
 	} while (0)
 
-extern DEFINE_PER_CPU(char[256], qeth_dbf_txt_buf);
+DECLARE_PER_CPU(char[256], qeth_dbf_txt_buf);
 
 #define QETH_DBF_TEXT_(name,level,text...)				\
 	do {								\
@@ -740,8 +740,6 @@
 #ifdef CONFIG_QETH_VLAN
 	spinlock_t vlanlock;
 	struct vlan_group *vlangrp;
-	__u8 vlans_current[VLAN_GROUP_ARRAY_LEN/(8*sizeof(__u8))];
-        __u8 vlans_new[VLAN_GROUP_ARRAY_LEN/(8*sizeof(__u8))];
 #endif
 	struct work_struct kernel_thread_starter;
 	spinlock_t thread_mask_lock;
diff -Nru a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
--- a/drivers/s390/net/qeth_main.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/s390/net/qeth_main.c	2004-10-28 22:25:58 -07:00
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.145 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.155 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.145 $	 $Date: 2004/10/08 15:08:40 $
+ *    $Revision: 1.155 $	 $Date: 2004/10/21 13:27:46 $
  *
  * 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
@@ -78,7 +78,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.145 $"
+#define VERSION_QETH_C "$Revision: 1.155 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -2153,8 +2153,9 @@
 qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	struct qeth_card *card;
+	struct ethhdr *eth;
 
-	QETH_DBF_TEXT(trace,5,"typtrans");
+	QETH_DBF_TEXT(trace,6,"typtrans");
 
 	card = (struct qeth_card *)dev->priv;
 #ifdef CONFIG_TR
@@ -2162,7 +2163,23 @@
 	    (card->info.link_type == QETH_LINK_TYPE_LANE_TR))
 	 	return tr_type_trans(skb,dev);
 #endif /* CONFIG_TR */
-	return eth_type_trans(skb,dev);
+	skb->mac.raw = skb->data;
+	skb_pull(skb, ETH_HLEN );
+	eth = eth_hdr(skb);
+
+	if (*eth->h_dest & 1) {
+		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+	} else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+		skb->pkt_type = PACKET_OTHERHOST;
+
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+	if (*(unsigned short *) (skb->data) == 0xFFFF)
+		return htons(ETH_P_802_3);
+	return htons(ETH_P_802_2);
 }
 
 static inline void
@@ -2234,26 +2251,21 @@
 qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
 			struct qeth_hdr *hdr)
 {
-	__u32 cast_type = 0;
-	__u16 rc = 0;
+	unsigned short vlan_id = 0;
 
-	cast_type = *(__u32 *) hdr->hdr.l2.flags;
-	if (cast_type & (QETH_LAYER2_FLAG_UNICAST << 8))
-		skb->pkt_type = PACKET_HOST;
-	else if (cast_type & (QETH_LAYER2_FLAG_MULTICAST << 8))
-		skb->pkt_type = PACKET_MULTICAST;
-	else if (cast_type & (QETH_LAYER2_FLAG_BROADCAST << 8))
-		skb->pkt_type = PACKET_BROADCAST;
+	skb->pkt_type = PACKET_HOST;
+	if (card->options.checksum_type == NO_CHECKSUMMING)
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	else
-		skb->pkt_type = PACKET_HOST;
+		skb->ip_summed = CHECKSUM_NONE;
 #ifdef CONFIG_QETH_VLAN
-	if (cast_type & (QETH_LAYER2_FLAG_VLAN << 8)) {
-		rc = hdr->hdr.l2.vlan_id;
+	if (hdr->hdr.l2.flags[2] & (QETH_LAYER2_FLAG_VLAN)) {
 		skb_pull(skb, VLAN_HLEN);
+		vlan_id = hdr->hdr.l2.vlan_id;
 	}
 #endif
-	skb->protocol = qeth_type_trans(skb, card->dev);
-	return rc;
+	skb->protocol = qeth_type_trans(skb, skb->dev);
+	return vlan_id;
 }
 
 static inline void
@@ -2261,7 +2273,8 @@
 		 struct qeth_hdr *hdr)
 {
 #ifdef CONFIG_QETH_IPV6
-	if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU){
+	if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) {
+		skb->pkt_type = PACKET_HOST;
 		skb->protocol = qeth_type_trans(skb, card->dev);
 		return;
 	}
@@ -2322,6 +2335,7 @@
 #endif
 	while((skb = qeth_get_next_skb(card, buf->buffer, &element,
 				       &offset, &hdr))) {
+		skb->dev = card->dev;
 		if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
 			vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr);
 		else
@@ -2331,13 +2345,12 @@
 			dev_kfree_skb_any(skb);
 			continue;
 		}
-		skb->dev = card->dev;
 #ifdef CONFIG_QETH_VLAN
 		if (vlan_tag)
 			vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag);
 		else
 #endif
-			rxrc = netif_rx(skb);
+		rxrc = netif_rx(skb);
 		card->dev->last_rx = jiffies;
 		card->stats.rx_packets++;
 		card->stats.rx_bytes += skb->len;
@@ -3621,7 +3634,8 @@
 		*skb = new_skb;
 	}
 #ifdef CONFIG_QETH_VLAN
-	if (card->vlangrp && vlan_tx_tag_present(*skb) && (ipv == 6)){
+	if (card->vlangrp && vlan_tx_tag_present(*skb) &&
+	    ((ipv == 6) || card->options.layer2) ) {
 		/*
 		 * Move the mac addresses (6 bytes src, 6 bytes dest)
 		 * to the beginning of the new header.  We are using three
@@ -3631,14 +3645,13 @@
 		memcpy((*skb)->data, (*skb)->data + 4, 4);
 		memcpy((*skb)->data + 4, (*skb)->data + 8, 4);
 		memcpy((*skb)->data + 8, (*skb)->data + 12, 4);
-		tag = (u16 *) (*skb)->data + 12;
+		tag = (u16 *)((*skb)->data + 12);
 		/*
 		 * first two bytes  = ETH_P_8021Q (0x8100)
 		 * second two bytes = VLANID
 		 */
 		*tag = __constant_htons(ETH_P_8021Q);
-		*(tag + 1) = vlan_tx_tag_get(*skb);
-		*(tag + 1) = htons(*(tag + 1));
+		*(tag + 1) = htons(vlan_tx_tag_get(*skb));
 	}
 #endif
 	*hdr = (struct qeth_hdr *) skb_push(*skb, sizeof(struct qeth_hdr));
@@ -3734,7 +3747,7 @@
 		qeth_layer2_get_packet_type(card, hdr, skb);
 
 	hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
-#ifdef QETH_VLAN
+#ifdef CONFIG_QETH_VLAN
 	/* VSWITCH relies on the VLAN
 	 * information to be present in
 	 * the QDIO header */
@@ -4793,7 +4806,6 @@
 }
 
 #ifdef CONFIG_QETH_VLAN
-static void qeth_layer2_process_vlans(struct qeth_card *);
 static void
 qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
@@ -4806,8 +4818,6 @@
 	spin_lock_irqsave(&card->vlanlock, flags);
 	card->vlangrp = grp;
 	spin_unlock_irqrestore(&card->vlanlock, flags);
-	if (card->options.layer2)
-		qeth_layer2_process_vlans(card);
 }
 
 static inline void
@@ -4902,12 +4912,69 @@
 }
 
 static void
+qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
+			    enum qeth_ipa_cmds ipacmd)
+{
+ 	int rc;
+	struct qeth_ipa_cmd *cmd;
+	struct qeth_cmd_buffer *iob;
+
+	QETH_DBF_TEXT_(trace, 4, "L2sdv%x",ipacmd);
+	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
+	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+        cmd->data.setdelvlan.vlan_id = i;
+
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
+        if (rc) {
+                PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
+			  "Continuing\n",i, card->info.if_name, rc);
+		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd);
+		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
+		QETH_DBF_TEXT_(trace, 2, "err%d", rc);
+        }
+}
+
+static void
+qeth_layer2_process_vlans(struct qeth_card *card, int clear)
+{
+        unsigned short  i;
+
+	QETH_DBF_TEXT(trace, 3, "L2prcvln");
+
+	if (!card->vlangrp)
+		return;
+	for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+		if (card->vlangrp->vlan_devices[i] == NULL)
+			continue;
+		if (clear)
+			qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
+		else
+			qeth_layer2_send_setdelvlan(card, i, IPA_CMD_SETVLAN);
+        }
+}
+
+/*add_vid is layer 2 used only ....*/
+static void
+qeth_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
+{
+	struct qeth_card *card;
+
+	QETH_DBF_TEXT_(trace, 4, "aid:%d", vid);
+
+	card = (struct qeth_card *) dev->priv;
+	if (!card->options.layer2)
+		return;
+	qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
+}
+
+/*... kill_vid used for both modes*/
+static void
 qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
 	struct qeth_card *card;
 	unsigned long flags;
 
-	QETH_DBF_TEXT(trace,4,"vlkilvid");
+	QETH_DBF_TEXT_(trace, 4, "kid:%d", vid);
 
 	card = (struct qeth_card *) dev->priv;
 	/* free all skbs for the vlan device */
@@ -4920,7 +4987,7 @@
 		card->vlangrp->vlan_devices[vid] = NULL;
 	spin_unlock_irqrestore(&card->vlanlock, flags);
 	if (card->options.layer2)
-		qeth_layer2_process_vlans(card);
+		qeth_layer2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
  	if ( (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) ||
 	     (qeth_set_thread_start_bit(card, QETH_SET_MC_THREAD) == 0) )
 		schedule_work(&card->kernel_thread_starter);
@@ -5328,93 +5395,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_QETH_VLAN
-/* ATT: not a very readable order: bytes count from lower numbers, bits
-   count from lsb */
-static void
-qeth_layer2_set_bit(__u8 *ptr,int i)
-{
-        ptr[i/8]|=0x80>>(i%8);
-}
-
-static int
-qeth_layer2_get_bit(__u8 *ptr,int i)
-{
-        return (ptr[i/8]&(0x80>>(i%8)))?1:0;
-}
-
-static void
-qeth_layer2_takeover_vlans(struct qeth_card *card)
-{
-        int i;
-
-	QETH_DBF_TEXT(trace, 3, "L2tkvlan");
-        /* copy new to current */
-        memcpy(&card->vlans_current[0],
-               &card->vlans_new[0],
-               VLAN_GROUP_ARRAY_LEN/(8*sizeof(__u8)));
-
-        /* clear new vector */
-        memset(&card->vlans_new[0], 0,
-	       VLAN_GROUP_ARRAY_LEN/(8*sizeof(__u8)));
-
-        for (i=0; i<VLAN_GROUP_ARRAY_LEN; i++) {
-                if ( (card->vlangrp) &&
-                     (card->vlangrp->vlan_devices[i]) )
-                        qeth_layer2_set_bit(&card->vlans_new[0], i);
-        }
-}
-
-static void
-qeth_layer2_send_setdelvlan(struct qeth_card *card, __u16 i,
-			    enum qeth_ipa_cmds ipacmd)
-{
- 	int rc;
-	struct qeth_ipa_cmd *cmd;
-	struct qeth_cmd_buffer *iob;
-
-	QETH_DBF_TEXT(trace, 4, "L2sdvlan");
-	iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-        cmd->data.setdelvlan.vlan_id = i;
-
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-        if (rc) {
-                PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. "
-			  "Continuing\n",i, card->info.if_name, rc);
-		QETH_DBF_TEXT_(trace, 2, "L2VL%4x", ipacmd);
-		QETH_DBF_TEXT_(trace, 2, "L2%s", CARD_BUS_ID(card));
-		QETH_DBF_TEXT_(trace, 2, "err%d", rc);
-        }
-}
-
-static void
-qeth_layer2_register_vlans(struct qeth_card *card)
-{
-        __u16 i;
-
-	QETH_DBF_TEXT(trace, 3, "L2regvln");
-        for (i=0; i<VLAN_GROUP_ARRAY_LEN; i++) {
-                if ( (qeth_layer2_get_bit(&card->vlans_current[0], i)) &&
-                     (!qeth_layer2_get_bit(&card->vlans_new[0], i)) )
-                        qeth_layer2_send_setdelvlan(card, i, IPA_CMD_DELVLAN);
-                if ( (!qeth_layer2_get_bit(&card->vlans_current[0], i)) &&
-                     (qeth_layer2_get_bit(&card->vlans_new[0], i)) )
-                        qeth_layer2_send_setdelvlan(card, i, IPA_CMD_SETVLAN);
-        }
-}
-
-static void
-qeth_layer2_process_vlans(struct qeth_card *card)
-{
-	QETH_DBF_TEXT(trace, 2, "L2provln");
-
-	qeth_layer2_takeover_vlans(card);
-	qeth_layer2_register_vlans(card);
-}
-
-#endif
-
 static int
 qeth_layer2_register_addr_entry(struct qeth_card *card,
 				struct qeth_ipaddr *addr)
@@ -5575,6 +5555,7 @@
 #ifdef CONFIG_QETH_VLAN
 	dev->vlan_rx_register = qeth_vlan_rx_register;
 	dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
+	dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
 #endif
 	if (qeth_get_netdev_flags(card) & IFF_NOARP) {
 		dev->rebuild_header = NULL;
@@ -5596,9 +5577,8 @@
 	if ((card->options.fake_broadcast) ||
 	    (card->info.broadcast_capable))
 		dev->flags |= IFF_BROADCAST;
-
 	dev->hard_header_len =
-		qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
+			qeth_get_hlen(card->info.link_type) + card->options.add_hhlen;
 	dev->addr_len = OSA_ADDR_LEN;
 	dev->mtu = card->info.initial_mtu;
 
@@ -6187,7 +6167,10 @@
 			   card->info.if_name, rc);
 	} else {
 		PRINT_INFO("VLAN enabled \n");
-		card->dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+		card->dev->features |=
+			NETIF_F_HW_VLAN_FILTER |
+			NETIF_F_HW_VLAN_TX |
+			NETIF_F_HW_VLAN_RX;
 	}
 #endif /* QETH_VLAN */
 	return rc;
@@ -6559,6 +6542,7 @@
 		card->lan_online = 1;
 	if (card->options.layer2) {
 		card->dev->features |=
+			NETIF_F_HW_VLAN_FILTER |
 			NETIF_F_HW_VLAN_TX |
 			NETIF_F_HW_VLAN_RX;
 		card->dev->flags|=IFF_MULTICAST|IFF_BROADCAST;
@@ -6568,7 +6552,7 @@
 			return rc;
 		}
 #ifdef CONFIG_QETH_VLAN
-		qeth_layer2_process_vlans(card);
+		qeth_layer2_process_vlans(card, 0);
 #endif
 		goto out;
 	}
@@ -6737,6 +6721,10 @@
 		card->state = CARD_STATE_SOFTSETUP;
 	}
 	if (card->state == CARD_STATE_SOFTSETUP) {
+#ifdef CONFIG_QETH_VLAN
+		if (card->options.layer2)
+			qeth_layer2_process_vlans(card, 1);
+#endif
 		qeth_clear_ip_list(card, !card->use_hard_stop, recover_flag);
 		qeth_clear_ipacmd_list(card);
 		card->state = CARD_STATE_HARDSETUP;
@@ -7019,7 +7007,12 @@
 	}
 /*maybe it was set offline without ifconfig down
  * we can also use this state for recovery purposes*/
-	qeth_set_allowed_threads(card, 0xffffffff, 0);
+	if (card->options.layer2)
+		qeth_set_allowed_threads(card,
+					 QETH_RECOVER_THREAD |
+					 QETH_SET_MC_THREAD,0);
+	else
+		qeth_set_allowed_threads(card, 0xffffffff, 0);
 	if (recover_flag == CARD_STATE_RECOVER)
 		qeth_start_again(card);
 	qeth_notify_processes();
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/scsi/ide-scsi.c	2004-10-28 22:25:58 -07:00
@@ -45,6 +45,7 @@
 #include <linux/hdreg.h>
 #include <linux/slab.h>
 #include <linux/ide.h>
+#include <linux/scatterlist.h>
 
 #include <asm/io.h>
 #include <asm/bitops.h>
@@ -253,17 +254,6 @@
 		kfree(atapi_buf);
 }
 
-static inline void idescsi_free_bio (struct bio *bio)
-{
-	struct bio *bhp;
-
-	while (bio) {
-		bhp = bio;
-		bio = bio->bi_next;
-		bio_put(bhp);
-	}
-}
-
 static void hexdump(u8 *x, int len)
 {
 	int i;
@@ -421,7 +411,6 @@
 	spin_lock_irqsave(host->host_lock, flags);
 	pc->done(pc->scsi_cmd);
 	spin_unlock_irqrestore(host->host_lock, flags);
-	idescsi_free_bio(rq->bio);
 	kfree(pc);
 	kfree(rq);
 	scsi->pc = NULL;
@@ -585,6 +574,50 @@
 	return ide_started;
 }
 
+static inline int idescsi_set_direction(idescsi_pc_t *pc)
+{
+	switch (pc->c[0]) {
+		case READ_6: case READ_10: case READ_12:
+			clear_bit(PC_WRITING, &pc->flags);
+			return 0;
+		case WRITE_6: case WRITE_10: case WRITE_12:
+			set_bit(PC_WRITING, &pc->flags);
+			return 0;
+		default:
+			return 1;
+	}
+}
+
+static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc)
+{
+	ide_hwif_t *hwif = drive->hwif;
+	struct scatterlist *sg, *scsi_sg;
+	int segments;
+
+	if (!pc->request_transfer || pc->request_transfer % 1024)
+		return 1;
+
+	if (idescsi_set_direction(pc))
+		return 1;
+
+	sg = hwif->sg_table;
+	scsi_sg = pc->scsi_cmd->request_buffer;
+	segments = pc->scsi_cmd->use_sg;
+
+	if (segments > hwif->sg_max_nents)
+		return 1;
+
+	if (!segments) {
+		hwif->sg_nents = 1;
+		sg_init_one(sg, pc->scsi_cmd->request_buffer, pc->request_transfer);
+	} else {
+		hwif->sg_nents = segments;
+		memcpy(sg, scsi_sg, sizeof(*sg) * segments);
+	}
+
+	return 0;
+}
+
 /*
  *	Issue a packet command
  */
@@ -594,7 +627,6 @@
 	ide_hwif_t *hwif = drive->hwif;
 	atapi_feature_t feature;
 	atapi_bcount_t bcount;
-	struct request *rq = pc->rq;
 
 	scsi->pc=pc;							/* Set the current packet command */
 	pc->actually_transferred=0;					/* We haven't transferred any data yet */
@@ -602,8 +634,11 @@
 	bcount.all = min(pc->request_transfer, 63 * 1024);		/* Request to transfer the entire buffer at once */
 
 	feature.all = 0;
-	if (drive->using_dma && rq->bio)
+	if (drive->using_dma && !idescsi_map_sg(drive, pc)) {
+		hwif->sg_mapped = 1;
 		feature.b.dma = !hwif->dma_setup(drive);
+		hwif->sg_mapped = 0;
+	}
 
 	SELECT_DRIVE(drive);
 	if (IDE_CONTROL_REG)
@@ -775,81 +810,6 @@
 	return -EINVAL;
 }
 
-static inline struct bio *idescsi_kmalloc_bio (int count)
-{
-	struct bio *bh, *bhp, *first_bh;
-
-	if ((first_bh = bhp = bh = bio_alloc(GFP_ATOMIC, 1)) == NULL)
-		goto abort;
-	bio_init(bh);
-	bh->bi_vcnt = 1;
-	while (--count) {
-		if ((bh = bio_alloc(GFP_ATOMIC, 1)) == NULL)
-			goto abort;
-		bio_init(bh);
-		bh->bi_vcnt = 1;
-		bhp->bi_next = bh;
-		bhp = bh;
-		bh->bi_next = NULL;
-	}
-	return first_bh;
-abort:
-	idescsi_free_bio (first_bh);
-	return NULL;
-}
-
-static inline int idescsi_set_direction (idescsi_pc_t *pc)
-{
-	switch (pc->c[0]) {
-		case READ_6: case READ_10: case READ_12:
-			clear_bit (PC_WRITING, &pc->flags);
-			return 0;
-		case WRITE_6: case WRITE_10: case WRITE_12:
-			set_bit (PC_WRITING, &pc->flags);
-			return 0;
-		default:
-			return 1;
-	}
-}
-
-static inline struct bio *idescsi_dma_bio(ide_drive_t *drive, idescsi_pc_t *pc)
-{
-	struct bio *bh = NULL, *first_bh = NULL;
-	int segments = pc->scsi_cmd->use_sg;
-	struct scatterlist *sg = pc->scsi_cmd->request_buffer;
-
-	if (!drive->using_dma || !pc->request_transfer || pc->request_transfer % 1024)
-		return NULL;
-	if (idescsi_set_direction(pc))
-		return NULL;
-	if (segments) {
-		if ((first_bh = bh = idescsi_kmalloc_bio (segments)) == NULL)
-			return NULL;
-#if IDESCSI_DEBUG_LOG
-		printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10);
-#endif /* IDESCSI_DEBUG_LOG */
-		while (segments--) {
-			bh->bi_io_vec[0].bv_page = sg->page;
-			bh->bi_io_vec[0].bv_len = sg->length;
-			bh->bi_io_vec[0].bv_offset = sg->offset;
-			bh->bi_size = sg->length;
-			bh = bh->bi_next;
-			sg++;
-		}
-	} else {
-		if ((first_bh = bh = idescsi_kmalloc_bio (1)) == NULL)
-			return NULL;
-#if IDESCSI_DEBUG_LOG
-		printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10);
-#endif /* IDESCSI_DEBUG_LOG */
-		bh->bi_io_vec[0].bv_page = virt_to_page(pc->scsi_cmd->request_buffer);
-		bh->bi_io_vec[0].bv_offset = offset_in_page(pc->scsi_cmd->request_buffer);
-		bh->bi_io_vec[0].bv_len = pc->request_transfer;
-		bh->bi_size = pc->request_transfer;
-	}
-	return first_bh;
-}
-
 static inline int should_transform(ide_drive_t *drive, struct scsi_cmnd *cmd)
 {
 	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
@@ -921,7 +881,6 @@
 
 	ide_init_drive_cmd (rq);
 	rq->special = (char *) pc;
-	rq->bio = idescsi_dma_bio (drive, pc);
 	rq->flags = REQ_SPECIAL;
 	spin_unlock_irq(host->host_lock);
 	(void) ide_do_drive_cmd (drive, rq, ide_end);
@@ -975,7 +934,6 @@
 		 */
 		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);
@@ -1024,7 +982,6 @@
 	/* 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);
diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/scsi/libata-scsi.c	2004-10-28 22:25:57 -07:00
@@ -97,7 +97,7 @@
 		return 0;
 
 	default:
-		rc = -EOPNOTSUPP;
+		rc = -ENOTTY;
 		break;
 	}
 
@@ -742,13 +742,13 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd)
+static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
 {
 	if (cmd->use_sg) {
 		struct scatterlist *sg;
 
 		sg = (struct scatterlist *) cmd->request_buffer;
-		kunmap_atomic(sg->page, KM_USER0);
+		kunmap_atomic(buf - sg->offset, KM_USER0);
 	}
 }
 
@@ -778,7 +778,7 @@
 	buflen = ata_scsi_rbuf_get(cmd, &rbuf);
 	memset(rbuf, 0, buflen);
 	rc = actor(args, rbuf, buflen);
-	ata_scsi_rbuf_put(cmd);
+	ata_scsi_rbuf_put(cmd, rbuf);
 
 	if (rc)
 		ata_bad_cdb(cmd, args->done);
@@ -1264,7 +1264,7 @@
 			buflen = ata_scsi_rbuf_get(cmd, &buf);
 			buf[2] = 0x5;
 			buf[3] = (buf[3] & 0xf0) | 2;
-			ata_scsi_rbuf_put(cmd);
+			ata_scsi_rbuf_put(cmd, buf);
 		}
 		cmd->result = SAM_STAT_GOOD;
 	}
diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/scsi/megaraid.c	2004-10-28 22:25:56 -07:00
@@ -4006,7 +4006,7 @@
 	mbox->m_out.xferaddr = (u32)adapter->buf_dma_handle;
 
 	/*
-	 * Non-ROMB firware fail this command, so all channels
+	 * Non-ROMB firmware fail this command, so all channels
 	 * must be shown RAID
 	 */
 	adapter->mega_ch_class = 0xFF;
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/serial/8250.c	2004-10-28 22:25:56 -07:00
@@ -32,6 +32,7 @@
 #include <linux/serialP.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/8250.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -41,7 +42,6 @@
 #endif
 
 #include <linux/serial_core.h>
-#include "8250.h"
 
 /*
  * Configuration:
@@ -112,11 +112,17 @@
 #define SERIAL_PORT_DFNS
 #endif
 
+#ifndef ARCH_HAS_GET_LEGACY_SERIAL_PORTS
 static struct old_serial_port old_serial_port[] = {
 	SERIAL_PORT_DFNS /* defined in asm/serial.h */
 };
-
+static inline struct old_serial_port *get_legacy_serial_ports(unsigned int *count)
+{
+	*count = ARRAY_SIZE(old_serial_port);
+	return old_serial_port;
+}
 #define UART_NR	(ARRAY_SIZE(old_serial_port) + CONFIG_SERIAL_8250_NR_UARTS)
+#endif /* ARCH_HAS_DYNAMIC_LEGACY_SERIAL_PORTS */
 
 #ifdef CONFIG_SERIAL_8250_RSA
 
@@ -1958,22 +1964,27 @@
 {
 	struct uart_8250_port *up;
 	static int first = 1;
+	struct old_serial_port *old_ports;
+	int count;
 	int i;
 
 	if (!first)
 		return;
 	first = 0;
 
-	for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
-	     i++, up++) {
-		up->port.iobase   = old_serial_port[i].port;
-		up->port.irq      = irq_canonicalize(old_serial_port[i].irq);
-		up->port.uartclk  = old_serial_port[i].baud_base * 16;
-		up->port.flags    = old_serial_port[i].flags;
-		up->port.hub6     = old_serial_port[i].hub6;
-		up->port.membase  = old_serial_port[i].iomem_base;
-		up->port.iotype   = old_serial_port[i].io_type;
-		up->port.regshift = old_serial_port[i].iomem_reg_shift;
+	old_ports = get_legacy_serial_ports(&count);
+	if (old_ports == NULL)
+		return;
+
+	for (i = 0, up = serial8250_ports; i < count; i++, up++) {
+		up->port.iobase   = old_ports[i].port;
+		up->port.irq      = irq_canonicalize(old_ports[i].irq);
+		up->port.uartclk  = old_ports[i].baud_base * 16;
+		up->port.flags    = old_ports[i].flags;
+		up->port.hub6     = old_ports[i].hub6;
+		up->port.membase  = old_ports[i].iomem_base;
+		up->port.iotype   = old_ports[i].io_type;
+		up->port.regshift = old_ports[i].iomem_reg_shift;
 		up->port.ops      = &serial8250_pops;
 		if (share_irqs)
 			up->port.flags |= UPF_SHARE_IRQ;
diff -Nru a/drivers/serial/8250.h b/drivers/serial/8250.h
--- a/drivers/serial/8250.h	2004-10-28 22:25:56 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,75 +0,0 @@
-/*
- *  linux/drivers/char/8250.h
- *
- *  Driver for 8250/16550-type serial ports
- *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *
- *  Copyright (C) 2001 Russell King.
- *
- * 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.
- *
- *  $Id: 8250.h,v 1.8 2002/07/21 21:32:30 rmk Exp $
- */
-
-#include <linux/config.h>
-
-int serial8250_register_port(struct uart_port *);
-void serial8250_unregister_port(int line);
-void serial8250_get_irq_map(unsigned int *map);
-void serial8250_suspend_port(int line);
-void serial8250_resume_port(int line);
-
-struct old_serial_port {
-	unsigned int uart;
-	unsigned int baud_base;
-	unsigned int port;
-	unsigned int irq;
-	unsigned int flags;
-	unsigned char hub6;
-	unsigned char io_type;
-	unsigned char *iomem_base;
-	unsigned short iomem_reg_shift;
-};
-
-/*
- * This replaces serial_uart_config in include/linux/serial.h
- */
-struct serial8250_config {
-	const char	*name;
-	unsigned short	fifo_size;
-	unsigned short	tx_loadsz;
-	unsigned char	fcr;
-	unsigned int	flags;
-};
-
-#define UART_CAP_FIFO	(1 << 8)	/* UART has FIFO */
-#define UART_CAP_EFR	(1 << 9)	/* UART has EFR */
-#define UART_CAP_SLEEP	(1 << 10)	/* UART has IER sleep */
-#define UART_CAP_AFE	(1 << 11)	/* MCR-based hw flow control */
-
-#undef SERIAL_DEBUG_PCI
-
-#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
-#define SERIAL_INLINE
-#endif
-  
-#ifdef SERIAL_INLINE
-#define _INLINE_ inline
-#else
-#define _INLINE_
-#endif
-
-#define PROBE_RSA	(1 << 0)
-#define PROBE_ANY	(~0)
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
-#define SERIAL8250_SHARE_IRQS 1
-#else
-#define SERIAL8250_SHARE_IRQS 0
-#endif
diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
--- a/drivers/serial/8250_pci.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/serial/8250_pci.c	2004-10-28 22:25:59 -07:00
@@ -23,13 +23,13 @@
 #include <linux/delay.h>
 #include <linux/tty.h>
 #include <linux/serial_core.h>
-#include <linux/8250_pci.h>
 #include <linux/bitops.h>
+#include <linux/8250.h>
+#include <linux/8250_pci.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
 
-#include "8250.h"
 
 /*
  * Definitions for PCI support.
diff -Nru a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
--- a/drivers/serial/8250_pnp.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/serial/8250_pnp.c	2004-10-28 22:25:56 -07:00
@@ -26,11 +26,10 @@
 #include <linux/serialP.h>
 #include <linux/serial_core.h>
 #include <linux/bitops.h>
+#include <linux/8250.h>
 
 #include <asm/byteorder.h>
 #include <asm/serial.h>
-
-#include "8250.h"
 
 #define UNKNOWN_DEV 0x3000
 
diff -Nru a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
--- a/drivers/serial/au1x00_uart.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/serial/au1x00_uart.c	2004-10-28 22:25:57 -07:00
@@ -29,6 +29,7 @@
 #include <linux/serial.h>
 #include <linux/serialP.h>
 #include <linux/delay.h>
+#include <linux/8250.h>
 
 #include <asm/serial.h>
 #include <asm/io.h>
@@ -40,7 +41,6 @@
 #endif
 
 #include <linux/serial_core.h>
-#include "8250.h"
 
 /*
  * Debugging.
diff -Nru a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
--- a/drivers/serial/serial_cs.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/serial/serial_cs.c	2004-10-28 22:25:58 -07:00
@@ -44,6 +44,7 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/major.h>
+#include <linux/8250.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -54,8 +55,6 @@
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
-
-#include "8250.h"
 
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
diff -Nru a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
--- a/drivers/serial/sn_console.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/serial/sn_console.c	2004-10-28 22:25:58 -07:00
@@ -108,7 +108,6 @@
 /* Only used if USE_DYNAMIC_MINOR is set to 1 */
 static struct miscdevice misc;	/* used with misc_register for dynamic */
 
-extern u64 __iomem *master_node_bedrock_address;
 extern void early_sn_setup(void);
 
 #undef DEBUG
@@ -124,9 +123,6 @@
 static int snt_hw_puts_buffered(const char *, int);
 static int snt_poll_getc(void);
 static int snt_poll_input_pending(void);
-static int snt_sim_puts(const char *, int);
-static int snt_sim_getc(void);
-static int snt_sim_input_pending(void);
 static int snt_intr_getc(void);
 static int snt_intr_input_pending(void);
 static void sn_transmit_chars(struct sn_cons_port *, int);
@@ -140,14 +136,6 @@
 	.sal_input_pending = snt_poll_input_pending
 };
 
-/* A table for the simulator */
-static struct sn_sal_ops sim_ops = {
-	.sal_puts_raw = snt_sim_puts,
-	.sal_puts = snt_sim_puts,
-	.sal_getc = snt_sim_getc,
-	.sal_input_pending = snt_sim_input_pending
-};
-
 /* A table for interrupts enabled */
 static struct sn_sal_ops intr_ops = {
 	.sal_puts_raw = snt_hw_puts_raw,
@@ -194,53 +182,6 @@
 	return !status && input;
 }
 
-/* routines for running the console on the simulator */
-
-/**
- * snt_sim_puts - send to the console, used in simulator mode
- * @str: String to send
- * @count: length of string
- *
- */
-static int snt_sim_puts(const char *str, int count)
-{
-	int counter = count;
-
-#ifdef FLAG_DIRECT_CONSOLE_WRITES
-	/* This is an easy way to pre-pend the output to know whether the output
-	 * was done via sal or directly */
-	writeb('[', master_node_bedrock_address + (UART_TX << 3));
-	writeb('+', master_node_bedrock_address + (UART_TX << 3));
-	writeb(']', master_node_bedrock_address + (UART_TX << 3));
-	writeb(' ', master_node_bedrock_address + (UART_TX << 3));
-#endif				/* FLAG_DIRECT_CONSOLE_WRITES */
-	while (counter > 0) {
-		writeb(*str, master_node_bedrock_address + (UART_TX << 3));
-		counter--;
-		str++;
-	}
-	return count;
-}
-
-/**
- * snt_sim_getc - Get character from console in simulator mode
- *
- */
-static int snt_sim_getc(void)
-{
-	return readb(master_node_bedrock_address + (UART_RX << 3));
-}
-
-/**
- * snt_sim_input_pending - Check if there is input pending in simulator mode
- *
- */
-static int snt_sim_input_pending(void)
-{
-	return readb(master_node_bedrock_address +
-		     (UART_LSR << 3)) & UART_LSR_DR;
-}
-
 /* routines for an interrupt driven console (normal) */
 
 /**
@@ -491,11 +432,7 @@
 	printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
 
 	if (!sal_console_port.sc_ops) {
-		if (IS_RUNNING_ON_SIMULATOR())
-			sal_console_port.sc_ops = &sim_ops;
-		else
-			sal_console_port.sc_ops = &poll_ops;
-
+		sal_console_port.sc_ops = &poll_ops;
 		early_sn_setup();
 	}
 	sal_console_port.sc_ops->sal_puts_raw(printk_buf, printed_len);
@@ -781,12 +718,8 @@
 	spin_lock_irqsave(&port->sc_port.lock, flags);
 
 	/* early_printk invocation may have done this for us */
-	if (!port->sc_ops) {
-		if (IS_RUNNING_ON_SIMULATOR())
-			port->sc_ops = &sim_ops;
-		else
-			port->sc_ops = &poll_ops;
-	}
+	if (!port->sc_ops)
+		port->sc_ops = &poll_ops;
 
 	/* we can't turn on the console interrupt (as request_irq
 	 * calls kmalloc, which isn't set up yet), so we rely on a
@@ -1155,11 +1088,7 @@
 	if (!ia64_platform_is("sn2"))
 		return -1;
 
-	if (IS_RUNNING_ON_SIMULATOR())
-		sal_console_port.sc_ops = &sim_ops;
-	else
-		sal_console_port.sc_ops = &poll_ops;
-
+	sal_console_port.sc_ops = &poll_ops;
 	early_sn_setup();	/* Find SAL entry points */
 	register_console(&sal_console_early);
 
diff -Nru a/drivers/usb/Kconfig b/drivers/usb/Kconfig
--- a/drivers/usb/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/Kconfig	2004-10-28 22:25:57 -07:00
@@ -7,7 +7,7 @@
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
 config USB
 	tristate "Support for Host-side USB"
-	depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 || ARCH_LH7A404 || PXA27x
+	depends on USB_ARCH_HAS_HCD
 	---help---
 	  Universal Serial Bus (USB) is a specification for a serial bus
 	  subsystem which offers higher speeds and more features than the
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/class/audio.c	2004-10-28 22:25:59 -07:00
@@ -3119,12 +3119,18 @@
 {
 	struct usb_device *dev = state->s->usbdev;
 	struct mixerchannel *ch;
-	unsigned char buf[2];
+	unsigned char *buf;
 	__s16 v1;
 	unsigned int v2, v3;
 
 	if (!state->nrmixch || state->nrmixch > SOUND_MIXER_NRDEVICES)
 		return;
+	buf = kmalloc(sizeof(*buf) * 2, GFP_KERNEL);
+	if (!buf) {
+		printk(KERN_ERR "prepmixch: out of memory\n") ;
+		return;
+	}
+
 	ch = &state->mixch[state->nrmixch-1];
 	switch (ch->selector) {
 	case 0:  /* mixer unit request */
@@ -3236,13 +3242,16 @@
 	default:
 		goto err;
 	}
-	return;
 
+ freebuf:
+	kfree(buf);
+	return;
  err:
 	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
 	       dev->devnum, state->ctrlif, ch->unitid, ch->chnum, ch->selector);
 	if (state->nrmixch)
 		state->nrmixch--;
+	goto freebuf;
 }
 
 
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/class/usblp.c	2004-10-28 22:25:57 -07:00
@@ -222,6 +222,7 @@
 
 /* forward reference to make our lives easier */
 static struct usb_driver usblp_driver;
+static DECLARE_MUTEX(usblp_sem);	/* locks the existence of usblp's */
 
 /*
  * Functions for usblp control messages.
@@ -343,7 +344,7 @@
 	if (minor < 0)
 		return -ENODEV;
 
-	lock_kernel();
+	down (&usblp_sem);
 
 	retval = -ENODEV;
 	intf = usb_find_interface(&usblp_driver, minor);
@@ -389,7 +390,7 @@
 		}
 	}
 out:
-	unlock_kernel();
+	up (&usblp_sem);
 	return retval;
 }
 
@@ -415,13 +416,13 @@
 {
 	struct usblp *usblp = file->private_data;
 
-	down (&usblp->sem);
+	down (&usblp_sem);
 	usblp->used = 0;
 	if (usblp->present) {
 		usblp_unlink_urbs(usblp);
-		up(&usblp->sem);
 	} else 		/* finish cleanup from disconnect */
 		usblp_cleanup (usblp);
+	up (&usblp_sem);
 	return 0;
 }
 
@@ -1149,8 +1150,8 @@
 		BUG ();
 	}
 
+	down (&usblp_sem);
 	down (&usblp->sem);
-	lock_kernel();
 	usblp->present = 0;
 	usb_set_intfdata (intf, NULL);
 
@@ -1159,12 +1160,11 @@
 			usblp->writebuf, usblp->writeurb->transfer_dma);
 	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
 			usblp->readbuf, usblp->readurb->transfer_dma);
+	up (&usblp->sem);
 
 	if (!usblp->used)
 		usblp_cleanup (usblp);
-	else 	/* cleanup later, on release */
-		up (&usblp->sem);
-	unlock_kernel();
+	up (&usblp_sem);
 }
 
 static struct usb_device_id usblp_ids [] = {
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/core/hub.c	2004-10-28 22:25:58 -07:00
@@ -56,6 +56,31 @@
 module_param (blinkenlights, bool, S_IRUGO);
 MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs");
 
+/*
+ * As of 2.6.10 we introduce a new USB device initialization scheme which
+ * closely resembles the way Windows works.  Hopefully it will be compatible
+ * with a wider range of devices than the old scheme.  However some previously
+ * working devices may start giving rise to "device not accepting address"
+ * errors; if that happens the user can try the old scheme by adjusting the
+ * following module parameters.
+ *
+ * For maximum flexibility there are two boolean parameters to control the
+ * hub driver's behavior.  On the first initialization attempt, if the
+ * "old_scheme_first" parameter is set then the old scheme will be used,
+ * otherwise the new scheme is used.  If that fails and "use_both_schemes"
+ * is set, then the driver will make another attempt, using the other scheme.
+ */
+static int old_scheme_first = 0;
+module_param(old_scheme_first, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(old_scheme_first,
+		 "start with the old device initialization scheme");
+
+static int use_both_schemes = 0;
+module_param(use_both_schemes, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(use_both_schemes,
+		"try the other device initialization scheme if the "
+		"first one fails");
+
 
 #ifdef	DEBUG
 static inline char *portspeed (int portstatus)
@@ -78,9 +103,17 @@
 /* USB 2.0 spec Section 11.24.4.5 */
 static int get_hub_descriptor(struct usb_device *hdev, void *data, int size)
 {
-	return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
-		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
-		USB_DT_HUB << 8, 0, data, size, HZ * USB_CTRL_GET_TIMEOUT);
+	int i, ret;
+
+	for (i = 0; i < 3; i++) {
+		ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
+			USB_DT_HUB << 8, 0, data, size,
+			HZ * USB_CTRL_GET_TIMEOUT);
+		if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
+			return ret;
+	}
+	return -EINVAL;
 }
 
 /*
@@ -641,6 +674,7 @@
 		hub->indicator [0] = INDICATOR_CYCLE;
 
 	hub_power_on(hub);
+	hub->change_bits[0] = ~0;
 	hub_activate(hub);
 	return 0;
 
@@ -1265,7 +1299,8 @@
 #define PORT_RESET_TRIES	5
 #define SET_ADDRESS_TRIES	2
 #define GET_DESCRIPTOR_TRIES	2
-#define SET_CONFIG_TRIES	2
+#define SET_CONFIG_TRIES	(2 * (use_both_schemes + 1))
+#define USE_NEW_SCHEME(i)	((i) / 2 == old_scheme_first)
 
 #define HUB_ROOT_RESET_TIME	50	/* times are in msec */
 #define HUB_SHORT_RESET_TIME	10
@@ -1983,20 +2018,30 @@
 	return portstatus;
 }
 
+#define usb_sndaddr0pipe()	(PIPE_CONTROL << 30)
+#define usb_rcvaddr0pipe()	((PIPE_CONTROL << 30) | USB_DIR_IN)
+
 static int hub_set_address(struct usb_device *udev)
 {
 	int retval;
 
 	if (udev->devnum == 0)
 		return -EINVAL;
-	if (udev->state != USB_STATE_DEFAULT &&
-			udev->state != USB_STATE_ADDRESS)
+	if (udev->state == USB_STATE_ADDRESS)
+		return 0;
+	if (udev->state != USB_STATE_DEFAULT)
 		return -EINVAL;
-	retval = usb_control_msg(udev, (PIPE_CONTROL << 30) /* Address 0 */,
+	retval = usb_control_msg(udev, usb_sndaddr0pipe(),
 		USB_REQ_SET_ADDRESS, 0, udev->devnum, 0,
 		NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-	if (retval == 0)
+	if (retval == 0) {
+		int m = udev->epmaxpacketin[0];
+
 		usb_set_device_state(udev, USB_STATE_ADDRESS);
+		usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+		usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+		udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = m;
+	}
 	return retval;
 }
 
@@ -2010,7 +2055,8 @@
  * pointers, it's not necessary to lock the device.
  */
 static int
-hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
+hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
+		int retry_counter)
 {
 	static DECLARE_MUTEX(usb_address0_sem);
 
@@ -2049,6 +2095,7 @@
 		dev_dbg(&udev->dev, "device reset changed speed!\n");
 		goto fail;
 	}
+	oldspeed = udev->speed;
   
 	/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
 	 * it's fixed size except for full speed devices.
@@ -2058,22 +2105,22 @@
 		i = 64;
 		break;
 	case USB_SPEED_FULL:		/* 8, 16, 32, or 64 */
-		/* to determine the ep0 maxpacket size, read the first 8
-		 * bytes from the device descriptor to get bMaxPacketSize0;
-		 * then correct our initial (small) guess.
+		/* to determine the ep0 maxpacket size, try to read
+		 * the device descriptor to get bMaxPacketSize0 and
+		 * then correct our initial guess.
 		 */
-		// FALLTHROUGH
+		i = 64;
+		break;
 	case USB_SPEED_LOW:		/* fixed at 8 */
 		i = 8;
 		break;
 	default:
 		goto fail;
 	}
-	udev->epmaxpacketin [0] = i;
-	udev->epmaxpacketout[0] = i;
+	udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = i;
  
 	dev_info (&udev->dev,
-			"%s %s speed USB device using address %d\n",
+			"%s %s speed USB device using %s and address %d\n",
 			(udev->config) ? "reset" : "new",
 			({ char *speed; switch (udev->speed) {
 			case USB_SPEED_LOW:	speed = "low";	break;
@@ -2081,6 +2128,7 @@
 			case USB_SPEED_HIGH:	speed = "high";	break;
 			default: 		speed = "?";	break;
 			}; speed;}),
+			udev->bus->controller->driver->name,
 			udev->devnum);
 
 	/* Set up TT records, if needed  */
@@ -2101,11 +2149,59 @@
 	 * this area, and this is how Linux has done it for ages.
 	 * Change it cautiously.
 	 *
-	 * NOTE:  Windows gets the descriptor first, seemingly to help
-	 * work around device bugs like "can't use addresses with bit 3
-	 * set in certain configurations".  Yes, really.
-	 */
-	for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) {
+	 * NOTE:  If USE_NEW_SCHEME() is true we will start by issuing
+	 * a 64-byte GET_DESCRIPTOR request.  This is what Windows does,
+	 * so it may help with some non-standards-compliant devices.
+	 * Otherwise we start with SET_ADDRESS and then try to read the
+	 * first 8 bytes of the device descriptor to get the ep0 maxpacket
+	 * value.
+	 */
+	for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
+		if (USE_NEW_SCHEME(retry_counter)) {
+			struct usb_device_descriptor *buf;
+
+#define GET_DESCRIPTOR_BUFSIZE	64
+			buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
+			if (!buf) {
+				retval = -ENOMEM;
+				continue;
+			}
+			buf->bMaxPacketSize0 = 0;
+
+			/* Use a short timeout the first time through,
+			 * so that recalcitrant full-speed devices with
+			 * 8- or 16-byte ep0-maxpackets won't slow things
+			 * down tremendously by NAKing the unexpectedly
+			 * early status stage.
+			 */
+			j = usb_control_msg(udev, usb_rcvaddr0pipe(),
+					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+					USB_DT_DEVICE << 8, 0,
+					buf, GET_DESCRIPTOR_BUFSIZE,
+					(i ? HZ * USB_CTRL_GET_TIMEOUT : HZ));
+			udev->descriptor.bMaxPacketSize0 =
+					buf->bMaxPacketSize0;
+			kfree(buf);
+
+			retval = hub_port_reset(hdev, port, udev, delay);
+			if (retval < 0)		/* error or disconnect */
+				goto fail;
+			if (oldspeed != udev->speed) {
+				dev_dbg(&udev->dev,
+					"device reset changed speed!\n");
+				retval = -ENODEV;
+				goto fail;
+			}
+			if (udev->descriptor.bMaxPacketSize0 == 0) {
+				dev_err(&udev->dev, "device descriptor "
+						"read/%s, error %d\n",
+						"64", j);
+				retval = -EMSGSIZE;
+				continue;
+			}
+#undef GET_DESCRIPTOR_BUFSIZE
+		}
+
 		for (j = 0; j < SET_ADDRESS_TRIES; ++j) {
 			retval = hub_set_address(udev);
 			if (retval >= 0)
@@ -2124,25 +2220,31 @@
 		 *  - read ep0 maxpacket even for high and low speed,
   		 */
 		msleep(10);
+		if (USE_NEW_SCHEME(retry_counter))
+			break;
+
 		retval = usb_get_device_descriptor(udev, 8);
-		if (retval >= 8)
+		if (retval < 8) {
+			dev_err(&udev->dev, "device descriptor "
+					"read/%s, error %d\n",
+					"8", retval);
+			if (retval >= 0)
+				retval = -EMSGSIZE;
+		} else {
+			retval = 0;
 			break;
-		msleep(100);
+		}
 	}
-	if (retval != 8) {
-		dev_err(&udev->dev, "device descriptor read/%s, error %d\n",
-				"8", retval);
-		if (retval >= 0)
-			retval = -EMSGSIZE;
+	if (retval)
 		goto fail;
-	}
-	if (udev->speed == USB_SPEED_FULL
-			&& (udev->epmaxpacketin [0]
-				!= udev->descriptor.bMaxPacketSize0)) {
+
+	/* Should we verify that the value is valid? */
+	i = udev->descriptor.bMaxPacketSize0;
+	dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+	if (udev->epmaxpacketin[0] != i) {
 		usb_disable_endpoint(udev, 0 + USB_DIR_IN);
 		usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
-		udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0;
-		udev->epmaxpacketout[0] = udev->descriptor.bMaxPacketSize0;
+		udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = i;
 	}
   
 	retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
@@ -2312,7 +2414,7 @@
 		}
 
 		/* reset and get descriptor */
-		status = hub_port_init(hdev, udev, port);
+		status = hub_port_init(hdev, udev, port, i);
 		if (status < 0)
 			goto loop;
 
@@ -2732,7 +2834,7 @@
 {
 	struct usb_device *parent = udev->parent;
 	struct usb_device_descriptor descriptor = udev->descriptor;
-	int i, ret, port = -1;
+	int i, ret = 0, port = -1;
 	int udev_is_a_hub = 0;
 
 	if (udev->state == USB_STATE_NOTATTACHED ||
@@ -2768,12 +2870,16 @@
 		hub_pre_reset(udev);
 	}
 
-	/* ep0 maxpacket size may change; let the HCD know about it.
-	 * Other endpoints will be handled by re-enumeration. */
-	usb_disable_endpoint(udev, 0);
-	usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
-	ret = hub_port_init(parent, udev, port);
+		/* ep0 maxpacket size may change; let the HCD know about it.
+		 * Other endpoints will be handled by re-enumeration. */
+		usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+		usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+		ret = hub_port_init(parent, udev, port, i);
+		if (ret >= 0)
+			break;
+	}
 	if (ret < 0)
 		goto re_enumerate;
  
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/core/message.c	2004-10-28 22:25:57 -07:00
@@ -823,9 +823,19 @@
  */
 int usb_get_status(struct usb_device *dev, int type, int target, void *data)
 {
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
-		HZ * USB_CTRL_GET_TIMEOUT);
+	int ret;
+	u16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
+
+	if (!status)
+		return -ENOMEM;
+
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
+		sizeof(*status), HZ * USB_CTRL_GET_TIMEOUT);
+
+	*(u16 *)data = *status;
+	kfree(status);
+	return ret;
 }
 
 /**
diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
--- a/drivers/usb/core/urb.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/core/urb.c	2004-10-28 22:25:58 -07:00
@@ -264,11 +264,10 @@
 
 	max = usb_maxpacket (dev, pipe, is_out);
 	if (max <= 0) {
-		dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)",
-			__FUNCTION__,
-			usb_pipeendpoint (pipe), is_out ? "OUT" : "IN",
-			dev->bus->bus_name, dev->devpath,
-			max);
+		dev_dbg(&dev->dev,
+			"bogus endpoint ep%d%s in %s (bad maxpacket %d)",
+			usb_pipeendpoint (pipe), is_out ? "out" : "in",
+			__FUNCTION__, max);
 		return -EMSGSIZE;
 	}
 
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/core/usb.c	2004-10-28 22:25:58 -07:00
@@ -550,9 +550,7 @@
 		return 0;
 
 	intf = to_usb_interface(dev);
-
 	usb_drv = to_usb_driver(drv);
-	id = usb_drv->id_table;
 	
 	id = usb_match_id (intf, usb_drv->id_table);
 	if (id)
@@ -765,6 +763,7 @@
 
 	if (dev->bus->op->allocate)
 		if (dev->bus->op->allocate(dev)) {
+			usb_bus_put(bus);
 			kfree(dev);
 			return NULL;
 		}
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/gadget/ether.c	2004-10-28 22:25:59 -07:00
@@ -2320,7 +2320,7 @@
 	} else if (gadget_is_lh7a40x(gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
 	} else if (gadget_is_n9604(gadget)) {
-		device_desc.bcdDevice = __constant_cpu_to_le16 (0x020a);
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
 	} else {
 		/* can't assume CDC works.  don't want to default to
 		 * anything less functional on CDC-capable hardware,
diff -Nru a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
--- a/drivers/usb/gadget/file_storage.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/gadget/file_storage.c	2004-10-28 22:25:59 -07:00
@@ -250,7 +250,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"31 August 2004"
+#define DRIVER_VERSION		"20 October 2004"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -430,9 +430,9 @@
 
 /* Command Block Wrapper */
 struct bulk_cb_wrap {
-	u32	Signature;		// Contains 'USBC'
+	__le32	Signature;		// Contains 'USBC'
 	u32	Tag;			// Unique per command id
-	u32	DataTransferLength;	// Size of the data
+	__le32	DataTransferLength;	// Size of the data
 	u8	Flags;			// Direction in bit 7
 	u8	Lun;			// LUN (normally 0)
 	u8	Length;			// Of the CDB, <= MAX_COMMAND_SIZE
@@ -445,9 +445,9 @@
 
 /* Command Status Wrapper */
 struct bulk_cs_wrap {
-	u32	Signature;		// Should = 'USBS'
+	__le32	Signature;		// Should = 'USBS'
 	u32	Tag;			// Same as original command
-	u32	Residue;		// Amount not transferred
+	__le32	Residue;		// Amount not transferred
 	u8	Status;			// See below
 };
 
@@ -3717,30 +3717,30 @@
 
 	if (mod_data.release == 0xffff) {	// Parameter wasn't set
 		if (gadget_is_net2280(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16(0x0301);
+			mod_data.release = 0x0301;
 		else if (gadget_is_dummy(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16(0x0302);
+			mod_data.release = 0x0302;
 		else if (gadget_is_pxa(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16(0x0303);
+			mod_data.release = 0x0303;
 		else if (gadget_is_sh(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16(0x0304);
+			mod_data.release = 0x0304;
 
 		/* The sa1100 controller is not supported */
 
 		else if (gadget_is_goku(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16(0x0306);
+			mod_data.release = 0x0306;
 		else if (gadget_is_mq11xx(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16(0x0307);
+			mod_data.release = 0x0307;
 		else if (gadget_is_omap(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16(0x0308);
+			mod_data.release = 0x0308;
 		else if (gadget_is_lh7a40x(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16 (0x0309);
+			mod_data.release = 0x0309;
 		else if (gadget_is_n9604(fsg->gadget))
-			mod_data.release = __constant_cpu_to_le16 (0x030a);
+			mod_data.release = 0x0310;
 		else {
 			WARN(fsg, "controller '%s' not recognized\n",
 				fsg->gadget->name);
-			mod_data.release = __constant_cpu_to_le16(0x0399);
+			mod_data.release = 0x0399;
 		}
 	}
 
diff -Nru a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
--- a/drivers/usb/gadget/goku_udc.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/gadget/goku_udc.c	2004-10-28 22:25:57 -07:00
@@ -90,7 +90,7 @@
 static void nuke(struct goku_ep *, int status);
 
 static inline void
-command(struct goku_udc_regs *regs, int command, unsigned epnum)
+command(struct goku_udc_regs __iomem *regs, int command, unsigned epnum)
 {
 	writel(COMMAND_EP(epnum) | command, &regs->Command);
 	udelay(300);
@@ -161,8 +161,8 @@
 
 	/* ep1 and ep2 can do double buffering and/or dma */
 	if (ep->num < 3) {
-		struct goku_udc_regs	*regs = ep->dev->regs;
-		u32			tmp;
+		struct goku_udc_regs __iomem	*regs = ep->dev->regs;
+		u32				tmp;
 
 		/* double buffer except (for now) with pio in */
 		tmp = ((ep->dma || !ep->is_in)
@@ -191,7 +191,7 @@
 	return 0;
 }
 
-static void ep_reset(struct goku_udc_regs *regs, struct goku_ep *ep)
+static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep)
 {
 	struct goku_udc		*dev = ep->dev;
 
@@ -209,16 +209,16 @@
 		writel(dev->int_enable, &regs->int_enable);
 		readl(&regs->int_enable);
 		if (ep->num < 3) {
-			struct goku_udc_regs	*regs = ep->dev->regs;
-			u32			tmp;
+			struct goku_udc_regs __iomem	*r = ep->dev->regs;
+			u32				tmp;
 
-			tmp = readl(&regs->EPxSingle);
+			tmp = readl(&r->EPxSingle);
 			tmp &= ~(0x11 << ep->num);
-			writel(tmp, &regs->EPxSingle);
+			writel(tmp, &r->EPxSingle);
 
-			tmp = readl(&regs->EPxBCS);
+			tmp = readl(&r->EPxBCS);
 			tmp &= ~(0x11 << ep->num);
-			writel(tmp, &regs->EPxBCS);
+			writel(tmp, &r->EPxBCS);
 		}
 		/* reset dma in case we're still using it */
 		if (ep->dma) {
@@ -237,7 +237,7 @@
 	}
 
 	ep->ep.maxpacket = MAX_FIFO_SIZE;
-	ep->desc = 0;
+	ep->desc = NULL;
 	ep->stopped = 1;
 	ep->irqs = 0;
 	ep->dma = 0;
@@ -274,10 +274,10 @@
 	struct goku_request	*req;
 
 	if (!_ep)
-		return 0;
+		return NULL;
 	req = kmalloc(sizeof *req, gfp_flags);
 	if (!req)
-		return 0;
+		return NULL;
 
 	memset(req, 0, sizeof *req);
 	req->req.dma = DMA_ADDR_INVALID;
@@ -334,7 +334,7 @@
 
 	ep = container_of(_ep, struct goku_ep, ep);
 	if (!_ep)
-		return 0;
+		return NULL;
 	*dma = DMA_ADDR_INVALID;
 
 #if	defined(USE_KMALLOC)
@@ -413,7 +413,7 @@
 /*-------------------------------------------------------------------------*/
 
 static inline int
-write_packet(u32 *fifo, u8 *buf, struct goku_request *req, unsigned max)
+write_packet(u32 __iomem *fifo, u8 *buf, struct goku_request *req, unsigned max)
 {
 	unsigned	length, count;
 
@@ -488,10 +488,10 @@
 
 static int read_fifo(struct goku_ep *ep, struct goku_request *req)
 {
-	struct goku_udc_regs	*regs;
-	u32			size, set;
-	u8			*buf;
-	unsigned		bufferspace, is_short, dbuff;
+	struct goku_udc_regs __iomem	*regs;
+	u32				size, set;
+	u8				*buf;
+	unsigned			bufferspace, is_short, dbuff;
 
 	regs = ep->dev->regs;
 top:
@@ -581,7 +581,8 @@
 }
 
 static inline void
-pio_irq_enable(struct goku_udc *dev, struct goku_udc_regs *regs, int epnum)
+pio_irq_enable(struct goku_udc *dev,
+		struct goku_udc_regs __iomem *regs, int epnum)
 {
 	dev->int_enable |= INT_EPxDATASET (epnum);
 	writel(dev->int_enable, &regs->int_enable);
@@ -589,7 +590,8 @@
 }
 
 static inline void
-pio_irq_disable(struct goku_udc *dev, struct goku_udc_regs *regs, int epnum)
+pio_irq_disable(struct goku_udc *dev,
+		struct goku_udc_regs __iomem *regs, int epnum)
 {
 	dev->int_enable &= ~INT_EPxDATASET (epnum);
 	writel(dev->int_enable, &regs->int_enable);
@@ -613,10 +615,10 @@
 // return:  0 = q running, 1 = q stopped, negative = errno
 static int start_dma(struct goku_ep *ep, struct goku_request *req)
 {
-	struct goku_udc_regs	*regs = ep->dev->regs;
-	u32			master;
-	u32			start = req->req.dma;
-	u32			end = start + req->req.length - 1;
+	struct goku_udc_regs __iomem	*regs = ep->dev->regs;
+	u32				master;
+	u32				start = req->req.dma;
+	u32				end = start + req->req.length - 1;
 
 	master = readl(&regs->dma_master) & MST_RW_BITS;
 
@@ -668,9 +670,9 @@
 
 static void dma_advance(struct goku_udc *dev, struct goku_ep *ep)
 {
-	struct goku_request	*req;
-	struct goku_udc_regs	*regs = ep->dev->regs;
-	u32			master;
+	struct goku_request		*req;
+	struct goku_udc_regs __iomem	*regs = ep->dev->regs;
+	u32				master;
 
 	master = readl(&regs->dma_master);
 
@@ -716,9 +718,9 @@
 
 static void abort_dma(struct goku_ep *ep, int status)
 {
-	struct goku_udc_regs	*regs = ep->dev->regs;
-	struct goku_request	*req;
-	u32			curr, master;
+	struct goku_udc_regs __iomem	*regs = ep->dev->regs;
+	struct goku_request		*req;
+	u32				curr, master;
 
 	/* NAK future host requests, hoping the implicit delay lets the
 	 * dma engine finish reading (or writing) its latest packet and
@@ -848,7 +850,7 @@
 		if (unlikely(status != 0)) {
 			if (status > 0)
 				status = 0;
-			req = 0;
+			req = NULL;
 		}
 
 	} /* else pio or dma irq handler advances the queue. */
@@ -927,7 +929,7 @@
 	} else if (!list_empty(&req->queue))
 		done(ep, req, -ECONNRESET);
 	else
-		req = 0;
+		req = NULL;
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	return req ? 0 : -EOPNOTSUPP;
@@ -984,7 +986,8 @@
 		retval = -EAGAIN;
 	else if (ep->is_in && value
 			/* data in (either) packet buffer? */
-			&& (ep->dev->regs->DataSet & DATASET_AB(ep->num)))
+			&& (readl(&ep->dev->regs->DataSet)
+					& DATASET_AB(ep->num)))
 		retval = -EAGAIN;
 	else if (!value)
 		goku_clear_halt(ep);
@@ -1000,9 +1003,9 @@
 
 static int goku_fifo_status(struct usb_ep *_ep)
 {
-	struct goku_ep		*ep;
-	struct goku_udc_regs	*regs;
-	u32			size;
+	struct goku_ep			*ep;
+	struct goku_udc_regs __iomem	*regs;
+	u32				size;
 
 	if (!_ep)
 		return -ENODEV;
@@ -1022,9 +1025,9 @@
 
 static void goku_fifo_flush(struct usb_ep *_ep)
 {
-	struct goku_ep		*ep;
-	struct goku_udc_regs	*regs;
-	u32			size;
+	struct goku_ep			*ep;
+	struct goku_udc_regs __iomem	*regs;
+	u32				size;
 
 	if (!_ep)
 		return;
@@ -1141,14 +1144,14 @@
 udc_proc_read(char *buffer, char **start, off_t off, int count,
 		int *eof, void *_dev)
 {
-	char			*buf = buffer;
-	struct goku_udc		*dev = _dev;
-	struct goku_udc_regs	*regs = dev->regs;
-	char			*next = buf;
-	unsigned		size = count;
-	unsigned long		flags;
-	int			i, t, is_usb_connected;
-	u32			tmp;
+	char				*buf = buffer;
+	struct goku_udc			*dev = _dev;
+	struct goku_udc_regs __iomem	*regs = dev->regs;
+	char				*next = buf;
+	unsigned			size = count;
+	unsigned long			flags;
+	int				i, t, is_usb_connected;
+	u32				tmp;
 
 	if (off != 0)
 		return 0;
@@ -1336,17 +1339,17 @@
 		ep->dev = dev;
 		INIT_LIST_HEAD (&ep->queue);
 
-		ep_reset(0, ep);
+		ep_reset(NULL, ep);
 	}
 
-	dev->ep[0].reg_mode = 0;
+	dev->ep[0].reg_mode = NULL;
 	dev->ep[0].ep.maxpacket = MAX_EP0_SIZE;
 	list_del_init (&dev->ep[0].ep.ep_list);
 }
 
 static void udc_reset(struct goku_udc *dev)
 {
-	struct goku_udc_regs	*regs = dev->regs;
+	struct goku_udc_regs __iomem	*regs = dev->regs;
 
 	writel(0, &regs->power_detect);
 	writel(0, &regs->int_enable);
@@ -1363,8 +1366,8 @@
 
 static void ep0_start(struct goku_udc *dev)
 {
-	struct goku_udc_regs	*regs = dev->regs;
-	unsigned		i;
+	struct goku_udc_regs __iomem	*regs = dev->regs;
+	unsigned			i;
 
 	VDBG(dev, "%s\n", __FUNCTION__);
 
@@ -1441,15 +1444,15 @@
 		return -EBUSY;
 
 	/* hook up the driver */
-	driver->driver.bus = 0;
+	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
 	retval = driver->bind(&dev->gadget);
 	if (retval) {
 		DBG(dev, "bind to driver %s --> error %d\n",
 				driver->driver.name, retval);
-		dev->driver = 0;
-		dev->gadget.dev.driver = 0;
+		dev->driver = NULL;
+		dev->gadget.dev.driver = NULL;
 		return retval;
 	}
 
@@ -1471,7 +1474,7 @@
 	DBG (dev, "%s\n", __FUNCTION__);
 
 	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = 0;
+		driver = NULL;
 
 	/* disconnect gadget driver after quiesceing hw and the driver */
 	udc_reset (dev);
@@ -1498,7 +1501,7 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&dev->lock, flags);
-	dev->driver = 0;
+	dev->driver = NULL;
 	stop_activity(dev, driver);
 	spin_unlock_irqrestore(&dev->lock, flags);
 
@@ -1514,9 +1517,9 @@
 
 static void ep0_setup(struct goku_udc *dev)
 {
-	struct goku_udc_regs	*regs = dev->regs;
-	struct usb_ctrlrequest	ctrl;
-	int			tmp;
+	struct goku_udc_regs __iomem	*regs = dev->regs;
+	struct usb_ctrlrequest		ctrl;
+	int				tmp;
 
 	/* read SETUP packet and enter DATA stage */
 	ctrl.bRequestType = readl(&regs->bRequestType);
@@ -1623,11 +1626,11 @@
 
 static irqreturn_t goku_irq(int irq, void *_dev, struct pt_regs *r)
 {
-	struct goku_udc		*dev = _dev;
-	struct goku_udc_regs	*regs = dev->regs;
-	struct goku_ep		*ep;
-	u32			stat, handled = 0;
-	unsigned		i, rescans = 5;
+	struct goku_udc			*dev = _dev;
+	struct goku_udc_regs __iomem	*regs = dev->regs;
+	struct goku_ep			*ep;
+	u32				stat, handled = 0;
+	unsigned			i, rescans = 5;
 
 	spin_lock(&dev->lock);
 
@@ -1645,7 +1648,7 @@
 			stat = 0;
 			handled = 1;
 			// FIXME have a neater way to prevent re-enumeration
-			dev->driver = 0;
+			dev->driver = NULL;
 			goto done;
 		}
 		if (stat & INT_PWRDETECT) {
@@ -1825,9 +1828,9 @@
 		pci_disable_device(pdev);
 	device_unregister(&dev->gadget.dev);
 
-	pci_set_drvdata(pdev, 0);
-	dev->regs = 0;
-	the_controller = 0;
+	pci_set_drvdata(pdev, NULL);
+	dev->regs = NULL;
+	the_controller = NULL;
 
 	INFO(dev, "unbind\n");
 }
@@ -1838,9 +1841,9 @@
 
 static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	struct goku_udc		*dev = 0;
+	struct goku_udc		*dev = NULL;
 	unsigned long		resource, len;
-	void			*base = 0;
+	void __iomem		*base = NULL;
 	int			retval;
 	char			buf [8], *bufp;
 
@@ -1900,7 +1903,7 @@
 		retval = -EFAULT;
 		goto done;
 	}
-	dev->regs = (struct goku_udc_regs *) base;
+	dev->regs = (struct goku_udc_regs __iomem *) base;
 
 	pci_set_drvdata(pdev, dev);
 	INFO(dev, "%s\n", driver_desc);
diff -Nru a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
--- a/drivers/usb/gadget/goku_udc.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/gadget/goku_udc.h	2004-10-28 22:25:57 -07:00
@@ -216,9 +216,9 @@
 	struct list_head			queue;
 	const struct usb_endpoint_descriptor	*desc;
 
-	u32					*reg_fifo;
-	u32					*reg_mode;
-	u32					*reg_status;
+	u32 __iomem				*reg_fifo;
+	u32 __iomem				*reg_mode;
+	u32 __iomem				*reg_status;
 };
 
 struct goku_request {
@@ -253,7 +253,7 @@
 
 	/* pci state used to access those endpoints */
 	struct pci_dev			*pdev;
-	struct goku_udc_regs		*regs;
+	struct goku_udc_regs __iomem	*regs;
 	u32				int_enable;
 
 	/* statistics... */
diff -Nru a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
--- a/drivers/usb/gadget/inode.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/gadget/inode.c	2004-10-28 22:25:59 -07:00
@@ -1981,12 +1981,8 @@
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
-	struct qstr	qname;
 
-	qname.name = name;
-	qname.len = strlen (name);
-	qname.hash = full_name_hash (qname.name, qname.len);
-	dentry = d_alloc (sb->s_root, &qname);
+	dentry = d_alloc_name(sb->s_root, name);
 	if (!dentry)
 		return NULL;
 
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/usb/gadget/net2280.c	2004-10-28 22:25:56 -07:00
@@ -717,7 +717,7 @@
 		dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE);
 
 	/* td->dmadesc = previously set by caller */
-	td->dmaaddr = cpu_to_le32p (&req->req.dma);
+	td->dmaaddr = cpu_to_le32 (req->req.dma);
 
 	/* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
 	wmb ();
@@ -1707,8 +1707,10 @@
 				td = req->td;
 				t = scnprintf (next, size, "\t    td %08x "
 					" count %08x buf %08x desc %08x\n",
-					req->td_dma, td->dmacount,
-					td->dmaaddr, td->dmadesc);
+					(u32) req->td_dma,
+					le32_to_cpu (td->dmacount),
+					le32_to_cpu (td->dmaaddr),
+					le32_to_cpu (td->dmadesc));
 				if (t <= 0 || t > size)
 					goto done;
 				size -= t;
@@ -2845,6 +2847,7 @@
 	dev->got_irq = 1;
 
 	/* DMA setup */
+	/* NOTE:  we know only the 32 LSBs of dma addresses may be nonzero */
 	dev->requests = pci_pool_create ("requests", pdev,
 		sizeof (struct net2280_dma),
 		0 /* no alignment requirements */,
diff -Nru a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
--- a/drivers/usb/gadget/net2280.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/gadget/net2280.h	2004-10-28 22:25:59 -07:00
@@ -495,10 +495,10 @@
  * use struct net2280_dma_regs bitfields
  */
 struct net2280_dma {
-	u32		dmacount;
-	u32		dmaaddr;		/* the buffer */
-	u32		dmadesc;		/* next dma descriptor */
-	u32		_reserved;
+	__le32		dmacount;
+	__le32		dmaaddr;		/* the buffer */
+	__le32		dmadesc;		/* next dma descriptor */
+	__le32		_reserved;
 } __attribute__ ((aligned (16)));
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
--- a/drivers/usb/gadget/omap_udc.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/gadget/omap_udc.c	2004-10-28 22:25:57 -07:00
@@ -59,15 +59,14 @@
 
 #undef	USB_TRACE
 
-/* OUT-dma seems to be behaving */
+/* bulk DMA seems to be behaving for both IN and OUT */
 #define	USE_DMA
 
 /* ISO too */
 #define	USE_ISO
 
-
 #define	DRIVER_DESC	"OMAP UDC driver"
-#define	DRIVER_VERSION	"24 August 2004"
+#define	DRIVER_VERSION	"4 October 2004"
 
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 
@@ -104,7 +103,6 @@
 module_param (fifo_mode, uint, 0);
 MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)");
 
-
 #ifdef	USE_DMA
 static unsigned use_dma = 1;
 
@@ -224,18 +222,17 @@
 		list_add(&ep->iso, &udc->iso);
 
 	/* maybe assign a DMA channel to this endpoint */
-	if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-			&& !(ep->bEndpointAddress & USB_DIR_IN))
-			/* FIXME ISO can dma, but prefers first channel.
-			 * IN can dma, but lacks debugging.
-			 */
+	if (use_dma && desc->bmAttributes == USB_ENDPOINT_XFER_BULK)
+		/* FIXME ISO can dma, but prefers first channel */
 		dma_channel_claim(ep, 0);
 
 	/* PIO OUT may RX packets */
 	if (desc->bmAttributes != USB_ENDPOINT_XFER_ISOC
 			&& !ep->has_dma
-			&& !(ep->bEndpointAddress & USB_DIR_IN))
+			&& !(ep->bEndpointAddress & USB_DIR_IN)) {
 		UDC_CTRL_REG = UDC_SET_FIFO_EN;
+		ep->ackwait = 1 + ep->double_buf;
+	}
 
 	spin_unlock_irqrestore(&udc->lock, flags);
 	VDBG("%s enabled\n", _ep->name);
@@ -262,6 +259,7 @@
 	ep->has_dma = 0;
 	UDC_CTRL_REG = UDC_SET_HALT;
 	list_del_init(&ep->iso);
+	del_timer(&ep->timer);
 
 	spin_unlock_irqrestore(&ep->udc->lock, flags);
 
@@ -498,17 +496,22 @@
 		u16	ep_stat = UDC_STAT_FLG_REG;
 
 		is_last = 0;
-		if (ep_stat & FIFO_UNREADABLE)
+		if (ep_stat & FIFO_EMPTY) {
+			if (!ep->double_buf)
+				break;
+			ep->fnf = 1;
+		}
+		if (ep_stat & UDC_EP_HALTED)
 			break;
 
-		if (ep_stat & (UDC_NON_ISO_FIFO_FULL|UDC_ISO_FIFO_FULL))
+		if (ep_stat & FIFO_FULL)
 			avail = ep->ep.maxpacket;
-		else 
+		else  {
 			avail = UDC_RXFSTAT_REG;
+			ep->fnf = ep->double_buf;
+		}
 		count = read_packet(buf, req, avail);
 
-		// FIXME double buffered PIO OUT wasn't behaving...
-
 		/* partial packet reads may not be errors */
 		if (count < ep->ep.maxpacket) {
 			is_last = 1;
@@ -526,26 +529,56 @@
 
 		if (!ep->bEndpointAddress)
 			break;
-		if (!ep->double_buf) {
-			UDC_CTRL_REG = UDC_SET_FIFO_EN;
-			if (!is_last)
-				break;
-		}
-
-		if (is_last) {
+		if (is_last)
 			done(ep, req, 0);
-			if (list_empty(&ep->queue) || !ep->double_buf)
-				break;
-			req = container_of(ep->queue.next,
-					struct omap_req, queue);
-			is_last = 0;
-		}
+		break;
 	}
 	return is_last;
 }
 
 /*-------------------------------------------------------------------------*/
 
+static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
+{
+	dma_addr_t	end;
+
+	/* IN-DMA needs this on fault/cancel paths, so 15xx misreports
+	 * the last transfer's bytecount by more than a FIFO's worth.
+	 */
+	if (cpu_is_omap15xx())
+		return 0;
+
+	end = omap_readw(OMAP_DMA_CSAC(ep->lch));
+	if (end == ep->dma_counter)
+		return 0;
+
+	end |= start & (0xffff << 16);
+	if (end < start)
+		end += 0x10000;
+	return end - start;
+}
+
+#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \
+		? OMAP_DMA_CSAC(x) /* really: CPC */ \
+		: OMAP_DMA_CDAC(x))
+
+static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
+{
+	dma_addr_t	end;
+
+	end = omap_readw(DMA_DEST_LAST(ep->lch));
+	if (end == ep->dma_counter)
+		return 0;
+
+	end |= start & (0xffff << 16);
+	if (cpu_is_omap15xx())
+		end++;
+	if (end < start)
+		end += 0x10000;
+	return end - start;
+}
+
+
 /* Each USB transfer request using DMA maps to one or more DMA transfers.
  * When DMA completion isn't request completion, the UDC continues with
  * the next DMA transfer for that USB transfer.
@@ -555,26 +588,29 @@
 {
 	u16		txdma_ctrl;
 	unsigned	length = req->req.length - req->req.actual;
+	const int	sync_mode = cpu_is_omap15xx()
+				? OMAP_DMA_SYNC_FRAME
+				: OMAP_DMA_SYNC_ELEMENT;
 
 	/* measure length in either bytes or packets */
-	if (length <= (UDC_TXN_TSC + 1)) {
+	if ((cpu_is_omap16xx() && length <= (UDC_TXN_TSC + 1))
+			|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
 		txdma_ctrl = UDC_TXN_EOT | length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-				length, 1, OMAP_DMA_SYNC_ELEMENT);
+				length, 1, sync_mode);
 	} else {
-		length = max(length / ep->maxpacket,
+		length = min(length / ep->maxpacket,
 				(unsigned) UDC_TXN_TSC + 1);
  		txdma_ctrl = length;
 		omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
-				ep->ep.maxpacket, length,
-				OMAP_DMA_SYNC_ELEMENT);
+				ep->ep.maxpacket, length, sync_mode);
 		length *= ep->maxpacket;
 	}
-
 	omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
 
 	omap_start_dma(ep->lch);
+	ep->dma_counter = omap_readw(OMAP_DMA_CSAC(ep->lch));
 	UDC_DMA_IRQ_EN_REG |= UDC_TX_DONE_IE(ep->dma_channel);
 	UDC_TXDMA_REG(ep->dma_channel) = UDC_TXN_START | txdma_ctrl;
 	req->dma_bytes = length;
@@ -592,14 +628,9 @@
 				&& req->dma_bytes != 0
 				&& (req->req.actual % ep->maxpacket) == 0)
 			return;
-	} else {
-		u32	last;
-
-		// FIXME this surely isn't #bytes transferred
-		last = (omap_readw(OMAP_DMA_CSSA_U(ep->lch)) << 16)
-				| omap_readw(OMAP_DMA_CSSA_L(ep->lch));
-		req->req.actual = last - req->req.dma;
-	}
+	} else
+		req->req.actual += dma_src_len(ep, req->req.dma
+							+ req->req.actual);
 
 	/* tx completion */
 	omap_stop_dma(ep->lch);
@@ -624,6 +655,7 @@
 			OMAP_DMA_SYNC_ELEMENT);
 	omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
 		OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+	ep->dma_counter = omap_readw(DMA_DEST_LAST(ep->lch));
 
 	UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
 	UDC_DMA_IRQ_EN_REG |= UDC_RX_EOT_IE(ep->dma_channel);
@@ -638,15 +670,13 @@
 {
 	u16	count;
 
-	/* FIXME must be a better way to see how much dma
-	 * happened, even when it never got going...
-	 */
-	count = omap_readw(OMAP_DMA_CDAC(ep->lch));
-	count -= 0xffff & (req->req.dma + req->req.actual);
+	if (status == 0)
+		ep->dma_counter = (u16) (req->req.dma + req->req.actual);
+	count = dma_dest_len(ep, req->req.dma + req->req.actual);
 	count += req->req.actual;
 	if (count <= req->req.length)
 		req->req.actual = count;
-	
+
 	if (count != req->dma_bytes || status)
 		omap_stop_dma(ep->lch);
 
@@ -705,7 +735,9 @@
 
 	if (irq_src & UDC_RXN_CNT) {
 		ep = &udc->ep[UDC_DMA_RX_SRC(dman_stat)];
-		DBG("%s, RX_CNT irq?\n", ep->ep.name);
+		ep->irqs++;
+		/* omap15xx does this unasked... */
+		VDBG("%s, RX_CNT irq?\n", ep->ep.name);
 		UDC_IRQ_SRC_REG = UDC_RXN_CNT;
 	}
 }
@@ -778,7 +810,8 @@
 		omap_disable_dma_irq(ep->lch, OMAP_DMA_BLOCK_IRQ);
 
 		/* channel type P: hw synch (fifo) */
-		omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+		if (!cpu_is_omap15xx())
+			omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
 	}
 
 just_restart:
@@ -803,6 +836,10 @@
 			use_ep(ep, UDC_EP_SEL);
 			(is_in ? write_fifo : read_fifo)(ep, req);
 			deselect_ep();
+			if (!is_in) {
+				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				ep->ackwait = 1 + ep->double_buf;
+			}
 			/* IN: 6 wait states before it'll tx */
 		}
 	}
@@ -833,24 +870,21 @@
 		UDC_TXDMA_CFG_REG &= ~mask;
 
 		if (req) {
-			if (active)
-				udelay(50);
 			finish_in_dma(ep, req, -ECONNRESET);
-			if (UDC_TXDMA_CFG_REG & mask)
-				WARN("%s, SPIN abort TX dma\n", ep->ep.name);
-		}
 
-		/* host may empty the fifo (or not...) */
+			/* clear FIFO; hosts probably won't empty it */
+			use_ep(ep, UDC_EP_SEL);
+			UDC_CTRL_REG = UDC_CLR_EP;
+			deselect_ep();
+		}
 		while (UDC_TXDMA_CFG_REG & mask)
 			udelay(10);
-
 	} else {
 		UDC_RXDMA_CFG_REG &= ~mask;
 
 		/* dma empties the fifo */
-		while (active && (UDC_RXDMA_CFG_REG & mask))
+		while (UDC_RXDMA_CFG_REG & mask)
 			udelay(10);
-		omap_stop_dma(ep->lch);
 		if (req)
 			finish_out_dma(ep, req, -ECONNRESET);
 	}
@@ -997,6 +1031,10 @@
 			if ((is_in ? write_fifo : read_fifo)(ep, req) == 1)
 				req = 0;
 			deselect_ep();
+			if (!is_in) {
+				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				ep->ackwait = 1 + ep->double_buf;
+			}
 			/* IN: 6 wait states before it'll tx */
 		}
 	}
@@ -1034,7 +1072,7 @@
 	if (use_dma && ep->dma_channel && ep->queue.next == &req->queue) {
 		int channel = ep->dma_channel;
 
-		/* releasing the dma completion cancels the request,
+		/* releasing the channel cancels the request,
 		 * reclaiming the channel restarts the queue
 		 */
 		dma_channel_release(ep);
@@ -1104,8 +1142,10 @@
 			use_ep(ep, 0);
 			UDC_CTRL_REG = UDC_RESET_EP;
 			ep->ackwait = 0;
-			if (!(ep->bEndpointAddress & USB_DIR_IN))
+			if (!(ep->bEndpointAddress & USB_DIR_IN)) {
 				UDC_CTRL_REG = UDC_SET_FIFO_EN;
+				ep->ackwait = 1 + ep->double_buf;
+			}
 		}
 	}
 done:
@@ -1218,7 +1258,7 @@
 
 /*
  * Called by whatever detects VBUS sessions:  external transceiver
- * driver, or maybe GPIO0 VBUS IRQ.
+ * driver, or maybe GPIO0 VBUS IRQ.  May request 48 MHz clock.
  */
 static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
 {
@@ -1229,6 +1269,13 @@
 	spin_lock_irqsave(&udc->lock, flags);
 	VDBG("VBUS %s\n", is_active ? "on" : "off");
 	udc->vbus_active = (is_active != 0);
+	if (cpu_is_omap15xx()) {
+		/* "software" detect, ignored if !VBUS_MODE_1510 */
+		if (is_active)
+			FUNC_MUX_CTRL_0_REG |= VBUS_CTRL_1510;
+		else
+			FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
+	}
 	if (can_pullup(udc))
 		pullup_enable(udc);
 	else
@@ -1342,8 +1389,15 @@
 	/* Clear any pending requests and then scrub any rx/tx state
 	 * before starting to handle the SETUP request.
 	 */
-	if (irq_src & UDC_SETUP)
+	if (irq_src & UDC_SETUP) {
+		u16	ack = irq_src & (UDC_EP0_TX|UDC_EP0_RX);
+
 		nuke(ep0, 0);
+		if (ack) {
+			UDC_IRQ_SRC_REG = ack;
+			irq_src = UDC_SETUP;
+		}
+	}
 
 	/* IN/OUT packets mean we're in the DATA or STATUS stage.  
 	 * This driver uses only uses protocol stalls (ep0 never halts),
@@ -1508,8 +1562,10 @@
 				use_ep(ep, 0);
 				UDC_CTRL_REG = UDC_RESET_EP;
 				ep->ackwait = 0;
-				if (!(ep->bEndpointAddress & USB_DIR_IN))
+				if (!(ep->bEndpointAddress & USB_DIR_IN)) {
 					UDC_CTRL_REG = UDC_SET_FIFO_EN;
+					ep->ackwait = 1 + ep->double_buf;
+				}
 			}
 			VDBG("%s halt cleared by host\n", ep->name);
 			goto ep0out_status_stage;
@@ -1743,6 +1799,39 @@
 	return status;
 }
 
+/* workaround for seemingly-lost IRQs for RX ACKs... */
+#define PIO_OUT_TIMEOUT	(jiffies + HZ/3)
+#define HALF_FULL(f)	(!((f)&(UDC_NON_ISO_FIFO_FULL|UDC_NON_ISO_FIFO_EMPTY)))
+
+static void pio_out_timer(unsigned long _ep)
+{
+	struct omap_ep	*ep = (void *) _ep;
+	unsigned long	flags;
+	u16		stat_flg;
+
+	spin_lock_irqsave(&ep->udc->lock, flags);
+	if (!list_empty(&ep->queue) && ep->ackwait) {
+		use_ep(ep, 0);
+		stat_flg = UDC_STAT_FLG_REG;
+
+		if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
+				|| (ep->double_buf && HALF_FULL(stat_flg)))) {
+			struct omap_req	*req;
+
+			VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
+			req = container_of(ep->queue.next,
+					struct omap_req, queue);
+			UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL;
+			(void) read_fifo(ep, req);
+			UDC_EP_NUM_REG = ep->bEndpointAddress;
+			UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			ep->ackwait = 1 + ep->double_buf;
+		}
+	}
+	mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
+	spin_unlock_irqrestore(&ep->udc->lock, flags);
+}
+
 static irqreturn_t
 omap_udc_pio_irq(int irq, void *_dev, struct pt_regs *r)
 {
@@ -1766,38 +1855,56 @@
 		ep = &udc->ep[epnum];
 		ep->irqs++;
 
-		if (!list_empty(&ep->queue)) {
-			UDC_EP_NUM_REG = epnum | UDC_EP_SEL;
-			if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+		UDC_EP_NUM_REG = epnum | UDC_EP_SEL;
+		ep->fnf = 0;
+		if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+			ep->ackwait--;
+			if (!list_empty(&ep->queue)) {
 				int stat;
 				req = container_of(ep->queue.next,
 						struct omap_req, queue);
 				stat = read_fifo(ep, req);
-				// FIXME double buffered PIO OUT should work
+				if (!ep->double_buf)
+					ep->fnf = 1;
 			}
-			UDC_EP_NUM_REG = epnum;
 		}
+		/* min 6 clock delay before clearing EP_SEL ... */
+		epn_stat = UDC_EPN_STAT_REG;
+		epn_stat = UDC_EPN_STAT_REG;
+		UDC_EP_NUM_REG = epnum;
+
+		/* enabling fifo _after_ clearing ACK, contrary to docs,
+		 * reduces lossage; timer still needed though (sigh).
+		 */
+		if (ep->fnf) {
+			UDC_CTRL_REG = UDC_SET_FIFO_EN;
+			ep->ackwait = 1 + ep->double_buf;
+		}
+		mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
 	}
 
 	/* then IN transfers */
-	if (irq_src & UDC_EPN_TX) {
+	else if (irq_src & UDC_EPN_TX) {
 		epnum = epn_stat & 0x0f;
 		UDC_IRQ_SRC_REG = UDC_EPN_TX;
 		status = IRQ_HANDLED;
 		ep = &udc->ep[16 + epnum];
 		ep->irqs++;
-		ep->ackwait = 0;
 
-		if (!list_empty(&ep->queue)) {
-			UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL;
-			if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+		UDC_EP_NUM_REG = epnum | UDC_EP_DIR | UDC_EP_SEL;
+		if ((UDC_STAT_FLG_REG & UDC_ACK)) {
+			ep->ackwait = 0;
+			if (!list_empty(&ep->queue)) {
 				req = container_of(ep->queue.next,
 						struct omap_req, queue);
 				(void) write_fifo(ep, req);
 			}
-			UDC_EP_NUM_REG = epnum | UDC_EP_DIR;
-			/* 6 wait states before it'll tx */
 		}
+		/* min 6 clock delay before clearing EP_SEL ... */
+		epn_stat = UDC_EPN_STAT_REG;
+		epn_stat = UDC_EPN_STAT_REG;
+		UDC_EP_NUM_REG = epnum | UDC_EP_DIR;
+		/* then 6 clocks before it'd tx */
 	}
 
 	spin_unlock_irqrestore(&udc->lock, flags);
@@ -1939,6 +2046,9 @@
 			pullup_disable (udc);
 	}
 
+	if (machine_is_omap_innovator())
+		omap_vbus_session(&udc->gadget, 1);
+
 done:
 	return status;
 }
@@ -1954,6 +2064,9 @@
 	if (!driver || driver != udc->driver)
 		return -EINVAL;
 
+	if (machine_is_omap_innovator())
+		omap_vbus_session(&udc->gadget, 0);
+
 	if (udc->transceiver)
 		(void) otg_set_peripheral(udc->transceiver, 0);
 	else
@@ -2002,8 +2115,16 @@
 
 	stat_flg = UDC_STAT_FLG_REG;
 	seq_printf(s,
-		"\n%s %sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
-		ep->name, buf, ep->irqs, stat_flg,
+		"\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",
+		ep->name, buf,
+		ep->double_buf ? "dbuf " : "",
+		({char *s; switch(ep->ackwait){
+		case 0: s = ""; break;
+		case 1: s = "(ackw) "; break;
+		case 2: s = "(ackw2) "; break;
+		default: s = "(?) "; break;
+		} s;}),
+		ep->irqs, stat_flg,
 		(stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",
 		(stat_flg & UDC_MISS_IN) ? "miss_in " : "",
 		(stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "",
@@ -2021,10 +2142,19 @@
 	if (list_empty (&ep->queue))
 		seq_printf(s, "\t(queue empty)\n");
 	else
-		list_for_each_entry (req, &ep->queue, queue)
+		list_for_each_entry (req, &ep->queue, queue) {
+			unsigned	length = req->req.actual;
+
+			if (use_dma && buf[0]) {
+				length += ((ep->bEndpointAddress & USB_DIR_IN)
+						? dma_src_len : dma_dest_len)
+					(ep, req->req.dma + length);
+				buf[0] = 0;
+			}
 			seq_printf(s, "\treq %p len %d/%d buf %p\n",
-					&req->req, req->req.actual,
+					&req->req, length,
 					req->req.length, req->req.buf);
+		}
 }
 
 static char *trx_mode(unsigned m)
@@ -2125,7 +2255,11 @@
 		fifo_mode,
 		udc->driver ? udc->driver->driver.name : "(none)",
 		HMC,
-		udc->transceiver ? udc->transceiver->label : "");
+		udc->transceiver ? udc->transceiver->label : "(none)");
+	seq_printf(s, "ULPD control %04x req %04x status %04x\n",
+		__REG16(ULPD_CLOCK_CTRL),
+		__REG16(ULPD_SOFT_REQ),
+		__REG16(ULPD_STATUS_REQ));
 
 	/* OTG controller registers */
 	if (!cpu_is_omap15xx())
@@ -2305,10 +2439,10 @@
 		epn_rxtx |= UDC_EPN_RX_ISO;
 		dbuf = 1;
 	} else {
-		/* pio-out could potentially double-buffer,
-		 * as can (should!) DMA-IN
+		/* double-buffering "not supported" on 15xx,
+		 * and ignored for PIO-IN on 16xx
 		 */
-		if (!use_dma || (addr & USB_DIR_IN))
+		if (!use_dma || cpu_is_omap15xx())
 			dbuf = 0;
 
 		switch (maxp) {
@@ -2320,6 +2454,9 @@
 		}
 		if (dbuf && addr)
 			epn_rxtx |= UDC_EPN_RX_DB;
+		init_timer(&ep->timer);
+		ep->timer.function = pio_out_timer;
+		ep->timer.data = (unsigned long) ep;
 	}
 	if (addr)
 		epn_rxtx |= UDC_EPN_RX_VALID;
@@ -2509,23 +2646,35 @@
 		return -EBUSY;
 	}
 
-	INFO("OMAP UDC rev %d.%d, %s receptacle\n",
+	INFO("OMAP UDC rev %d.%d%s\n",
 		UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
-		config->otg ? "Mini-AB" : "B/Mini-B");
+		config->otg ? ", Mini-AB" : "");
 
 	/* use the mode given to us by board init code */
 	if (cpu_is_omap15xx()) {
 		hmc = HMC_1510;
 		type = "(unknown)";
 
-		/* FIXME may need a GPIO-0 handler to call
-		 * usb_gadget_vbus_{dis,}connect() on us...
-		 */
+		if (machine_is_omap_innovator()) {
+			/* just set up software VBUS detect, and then
+			 * later rig it so we always report VBUS.
+			 * FIXME without really sensing VBUS, we can't
+			 * know when to turn PULLUP_EN on/off; and that
+			 * means we always "need" the 48MHz clock.
+			 */
+			u32 tmp = FUNC_MUX_CTRL_0_REG;
+
+			FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
+			tmp |= VBUS_MODE_1510;
+			tmp &= ~VBUS_CTRL_1510;
+			FUNC_MUX_CTRL_0_REG = tmp;
+		}
 	} else {
 		hmc = HMC_1610;
 		switch (hmc) {
 		case 3:
 		case 11:
+		case 16:
 		case 19:
 		case 25:
 			xceiv = otg_get_transceiver();
@@ -2565,7 +2714,9 @@
 	xceiv = 0;
 	// "udc" is now valid
 	pullup_disable(udc);
+#if	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
 	udc->gadget.is_otg = (config->otg != 0);
+#endif
 
 	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
 	status = request_irq(odev->resource[1].start, omap_udc_irq,
@@ -2694,7 +2845,11 @@
 
 static int __init udc_init(void)
 {
-	INFO("%s, version: " DRIVER_VERSION "%s\n", driver_desc,
+	INFO("%s, version: " DRIVER_VERSION
+#ifdef	USE_ISO
+		" (iso)"
+#endif
+		"%s\n", driver_desc,
 		use_dma ?  " (dma)" : "");
 	return driver_register(&udc_driver);
 }
diff -Nru a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
--- a/drivers/usb/gadget/omap_udc.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/gadget/omap_udc.h	2004-10-28 22:25:57 -07:00
@@ -146,11 +146,14 @@
 	u8				bmAttributes;
 	unsigned			double_buf:1;
 	unsigned			stopped:1;
-	unsigned			ackwait:1;
+	unsigned			fnf:1;
 	unsigned			has_dma:1;
+	u8				ackwait;
 	u8				dma_channel;
+	u16				dma_counter;
 	int				lch;
 	struct omap_udc			*udc;
+	struct timer_list		timer;
 };
 
 struct omap_udc {
@@ -168,7 +171,6 @@
 	unsigned			ep0_set_config:1;
 	unsigned			ep0_reset_config:1;
 	unsigned			ep0_setup:1;
-	unsigned			hmc:6;
 
 	struct completion		*done;
 };
diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
--- a/drivers/usb/gadget/zero.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/gadget/zero.c	2004-10-28 22:25:57 -07:00
@@ -1189,7 +1189,7 @@
 	} else if (gadget_is_lh7a40x(gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
 	} else if (gadget_is_n9604(gadget)) {
-		device_desc.bcdDevice = __constant_cpu_to_le16 (0x020a);
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
 	} else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
diff -Nru a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
--- a/drivers/usb/host/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/host/Kconfig	2004-10-28 22:25:59 -07:00
@@ -1,3 +1,21 @@
+# Host-side USB depends on having a host controller
+# NOTE:  dummy_hcd is always an option, but it's ignored here ...
+# NOTE:  SL-811 option should be board-specific ...
+config USB_ARCH_HAS_HCD
+	boolean
+	default y if USB_ARCH_HAS_OHCI
+	default y if ARM				# SL-811
+	default PCI
+
+# many non-PCI hcds implement OHCI
+config USB_ARCH_HAS_OHCI
+	boolean
+	default y if SA1111
+	default y if ARCH_OMAP
+	default y if ARCH_LH7A404
+	default y if PXA27x
+	default PCI
+
 #
 # USB Host Controller Drivers
 #
@@ -6,7 +24,7 @@
 
 config USB_EHCI_HCD
 	tristate "EHCI HCD (USB 2.0) support"
-	depends on USB
+	depends on USB && PCI
 	---help---
 	  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
 	  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
@@ -51,8 +69,8 @@
 
 config USB_OHCI_HCD
 	tristate "OHCI HCD support"
-	depends on USB
-	select ISP1301_OMAP if MACH_OMAP_H2
+	depends on USB && USB_ARCH_HAS_OHCI
+	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
 	---help---
 	  The Open Host Controller Interface (OHCI) is a standard for accessing
 	  USB 1.1 host controller hardware.  It does more in hardware than Intel's
@@ -68,7 +86,7 @@
 
 config USB_UHCI_HCD
 	tristate "UHCI HCD (most Intel and VIA) support"
-	depends on USB
+	depends on USB && PCI
 	---help---
 	  The Universal Host Controller Interface is a standard by Intel for
 	  accessing the USB hardware in the PC (which is also called the USB
diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
--- a/drivers/usb/host/ehci-dbg.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/host/ehci-dbg.c	2004-10-28 22:25:59 -07:00
@@ -185,7 +185,7 @@
 }
 
 static int __attribute__((__unused__))
-dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
+dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
 {
 	return scnprintf (buf, len,
 		"%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
@@ -204,7 +204,7 @@
 }
 
 static int __attribute__((__unused__))
-dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
+dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
 {
 	return scnprintf (buf, len,
 		"%s%sintrenable %02x%s%s%s%s%s%s",
@@ -221,7 +221,8 @@
 static const char *const fls_strings [] =
     { "1024", "512", "256", "??" };
 
-static int dbg_command_buf (char *buf, unsigned len, char *label, u32 command)
+static int
+dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
 {
 	return scnprintf (buf, len,
 		"%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s",
@@ -240,7 +241,7 @@
 }
 
 static int
-dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status)
+dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
 {
 	char	*sig;
 
@@ -276,19 +277,19 @@
 {}
 
 static inline int __attribute__((__unused__))
-dbg_status_buf (char *buf, unsigned len, char *label, u32 status)
+dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
 { return 0; }
 
 static inline int __attribute__((__unused__))
-dbg_command_buf (char *buf, unsigned len, char *label, u32 command)
+dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
 { return 0; }
 
 static inline int __attribute__((__unused__))
-dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable)
+dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
 { return 0; }
 
 static inline int __attribute__((__unused__))
-dbg_port_buf (char *buf, unsigned len, char *label, int port, u32 status)
+dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
 { return 0; }
 
 #endif	/* DEBUG */
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/host/ehci-hcd.c	2004-10-28 22:25:58 -07:00
@@ -347,9 +347,18 @@
 
 #ifdef	CONFIG_PCI
 	/* EHCI 0.96 and later may have "extended capabilities" */
-	if (hcd->self.controller->bus == &pci_bus_type)
+	if (hcd->self.controller->bus == &pci_bus_type) {
+		struct pci_dev	*pdev = to_pci_dev(ehci->hcd.self.controller);
+
+		/* AMD8111 EHCI doesn't work, according to AMD errata */
+		if ((pdev->vendor == PCI_VENDOR_ID_AMD)
+				&& (pdev->device == 0x7463)) {
+			ehci_info (ehci, "ignoring AMD8111 (errata)\n");
+			return -EIO;
+		}
+
 		temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
-	else
+	} else
 		temp = 0;
 	while (temp && count--) {
 		u32		cap;
@@ -362,10 +371,6 @@
 			if (bios_handoff (ehci, temp, cap) != 0)
 				return -EOPNOTSUPP;
 			break;
-		case 0x0a:		/* appendix C */
-			ehci_dbg (ehci, "debug registers, BAR %d offset %d\n",
-				(cap >> 29) & 0x07, (cap >> 16) & 0x0fff);
-			break;
 		case 0:			/* illegal reserved capability */
 			ehci_warn (ehci, "illegal capability!\n");
 			cap = 0;
@@ -857,6 +862,30 @@
 	}
 }
 
+static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+	/* if we need to use IAA and it's busy, defer */
+	if (qh->qh_state == QH_STATE_LINKED
+			&& ehci->reclaim
+			&& HCD_IS_RUNNING (ehci->hcd.state)) {
+		struct ehci_qh		*last;
+
+		for (last = ehci->reclaim;
+				last->reclaim;
+				last = last->reclaim)
+			continue;
+		qh->qh_state = QH_STATE_UNLINK_WAIT;
+		last->reclaim = qh;
+
+	/* bypass IAA if the hc can't care */
+	} else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim)
+		end_unlink_async (ehci, NULL);
+
+	/* something else might have unlinked the qh by now */
+	if (qh->qh_state == QH_STATE_LINKED)
+		start_unlink_async (ehci, qh);
+}
+
 /* remove from hardware lists
  * completions normally happen asynchronously
  */
@@ -875,28 +904,7 @@
 		qh = (struct ehci_qh *) urb->hcpriv;
 		if (!qh)
 			break;
-
-		/* if we need to use IAA and it's busy, defer */
-		if (qh->qh_state == QH_STATE_LINKED
-				&& ehci->reclaim
-				&& HCD_IS_RUNNING (ehci->hcd.state)
-				) {
-			struct ehci_qh		*last;
-
-			for (last = ehci->reclaim;
-					last->reclaim;
-					last = last->reclaim)
-				continue;
-			qh->qh_state = QH_STATE_UNLINK_WAIT;
-			last->reclaim = qh;
-
-		/* bypass IAA if the hc can't care */
-		} else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim)
-			end_unlink_async (ehci, NULL);
-
-		/* something else might have unlinked the qh by now */
-		if (qh->qh_state == QH_STATE_LINKED)
-			start_unlink_async (ehci, qh);
+		unlink_async (ehci, qh);
 		break;
 
 	case PIPE_INTERRUPT:
@@ -949,7 +957,7 @@
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	int			epnum;
 	unsigned long		flags;
-	struct ehci_qh		*qh;
+	struct ehci_qh		*qh, *tmp;
 
 	/* ASSERT:  any requests/urbs are being unlinked */
 	/* ASSERT:  nobody can be submitting urbs for this any more */
@@ -975,6 +983,16 @@
 	if (!HCD_IS_RUNNING (ehci->hcd.state))
 		qh->qh_state = QH_STATE_IDLE;
 	switch (qh->qh_state) {
+	case QH_STATE_LINKED:
+		for (tmp = ehci->async->qh_next.qh;
+				tmp && tmp != qh;
+				tmp = tmp->qh_next.qh)
+			continue;
+		/* periodic qh self-unlinks on empty */
+		if (!tmp)
+			goto nogood;
+		unlink_async (ehci, qh);
+		/* FALL THROUGH */
 	case QH_STATE_UNLINK:		/* wait for hw to finish? */
 idle_timeout:
 		spin_unlock_irqrestore (&ehci->lock, flags);
@@ -988,6 +1006,7 @@
 		}
 		/* else FALL THROUGH */
 	default:
+nogood:
 		/* caller was supposed to have unlinked any requests;
 		 * that's not our job.  just leak this memory.
 		 */
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/host/ehci-sched.c	2004-10-28 22:25:57 -07:00
@@ -353,8 +353,8 @@
 	hcd_to_bus (&ehci->hcd)->bandwidth_allocated -= 
 		(qh->usecs + qh->c_usecs) / qh->period;
 
-	dbg ("descheduled qh %p, period = %d frame = %d count = %d, urbs = %d",
-		qh, qh->period, frame,
+	ehci_dbg (ehci, "descheduled qh%d/%p frame=%d count=%d, urbs=%d\n",
+		qh->period, qh, frame,
 		atomic_read (&qh->kref.refcount), ehci->periodic_sched);
 }
 
@@ -486,13 +486,14 @@
 		qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff);
 		qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
 	} else
-		dbg ("reused previous qh %p schedule", qh);
+		ehci_dbg (ehci, "reused qh %p schedule\n", qh);
 
 	/* stuff into the periodic schedule */
 	qh->qh_state = QH_STATE_LINKED;
-	dbg ("scheduled qh %p usecs %d/%d period %d.0 starting %d.%d (gap %d)",
-		qh, qh->usecs, qh->c_usecs,
-		qh->period, frame, uframe, qh->gap_uf);
+	ehci_dbg(ehci,
+		"scheduled qh%d/%p usecs %d/%d starting %d.%d (gap %d)\n",
+		qh->period, qh, qh->usecs, qh->c_usecs,
+		frame, uframe, qh->gap_uf);
 	do {
 		if (unlikely (ehci->pshadow [frame].ptr != 0)) {
 
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/usb/host/ohci-hcd.c	2004-10-28 22:25:56 -07:00
@@ -154,6 +154,11 @@
 module_param (power_switching, bool, 0);
 MODULE_PARM_DESC (power_switching, "true (not default) to switch port power");
 
+/* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */
+static int no_handshake = 0;
+module_param (no_handshake, bool, 0);
+MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake");
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -426,7 +431,7 @@
 
 #ifndef IR_DISABLE
 	/* SMM owns the HC?  not for long! */
-	if (ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+	if (!no_handshake && ohci_readl (&ohci->regs->control) & OHCI_CTRL_IR) {
 		ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
 
 		/* this timeout is arbitrary.  we make it long, so systems
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/host/uhci-hcd.c	2004-10-28 22:25:59 -07:00
@@ -765,8 +765,12 @@
 
 	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
 
-	/* Low-speed transfers get a different queue, and won't hog the bus */
-	if (urb->dev->speed == USB_SPEED_LOW)
+	/* Low-speed transfers get a different queue, and won't hog the bus.
+	 * Also, some devices enumerate better without FSBR; the easiest way
+	 * to do that is to put URBs on the low-speed queue while the device
+	 * is in the DEFAULT state. */
+	if (urb->dev->speed == USB_SPEED_LOW ||
+			urb->dev->state == USB_STATE_DEFAULT)
 		skelqh = uhci->skel_ls_control_qh;
 	else {
 		skelqh = uhci->skel_fs_control_qh;
diff -Nru a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
--- a/drivers/usb/input/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/input/Kconfig	2004-10-28 22:25:59 -07:00
@@ -1,7 +1,7 @@
 #
 # USB Input driver configuration
 #
-comment "USB Human Interface Devices (HID)"
+comment "USB Input Devices"
 	depends on USB
 
 config USB_HID
@@ -12,7 +12,8 @@
 	  mice, joysticks, graphic tablets, or any other HID based devices
 	  to your computer via USB. You also need to select HID Input layer
 	  support (below) if you want to use keyboards, mice, joysticks and
-	  the like.
+	  the like ... as well as Uninterruptible Power Supply (UPS) and
+	  monitor control devices.
 
 	  You can't use this driver and the HIDBP (Boot Protocol) keyboard
 	  and mouse drivers at the same time. More information is available:
@@ -24,7 +25,7 @@
 	  module will be called usbhid.
 
 comment "Input core support is needed for USB HID input layer or HIDBP support"
-	depends on USB && INPUT=n
+	depends on USB_HID && INPUT=n
 
 config USB_HIDINPUT
 	bool "HID input layer support"
@@ -32,8 +33,7 @@
 	depends on INPUT && USB_HID
 	help
 	  Say Y here if you want to use a USB keyboard, mouse or joystick,
-	  or any other HID input device. You also need "Input core support", 
-	  (CONFIG_INPUT), which you select under "Input device support", above.
+	  or any other HID input device.
 
 	  If unsure, say Y.
 
@@ -87,7 +87,6 @@
 
 	  This module supports these devices separately using a separate
 	  event interface on /dev/usb/hiddevX (char 180:96 to 180:111).
-	  This driver requires CONFIG_USB_HID.
 
 	  If unsure, say Y.
 
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/input/hid-core.c	2004-10-28 22:25:58 -07:00
@@ -925,6 +925,7 @@
 		case -ECONNRESET:	/* unlink */
 		case -ENOENT:
 		case -ESHUTDOWN:
+		case -EPERM:
 			return;
 		case -ETIMEDOUT:	/* NAK */
 			break;
@@ -1833,6 +1834,30 @@
 	return 0;
 }
 
+static int hid_suspend(struct usb_interface *intf, u32 state)
+{
+	struct hid_device *hid = usb_get_intfdata (intf);
+
+	usb_kill_urb(hid->urbin);
+	intf->dev.power.power_state = state;
+	dev_dbg(&intf->dev, "suspend\n");
+	return 0;
+}
+
+static int hid_resume(struct usb_interface *intf)
+{
+	struct hid_device *hid = usb_get_intfdata (intf);
+	int status;
+
+	intf->dev.power.power_state = PM_SUSPEND_ON;
+	if (hid->open)
+		status = usb_submit_urb(hid->urbin, GFP_NOIO);
+	else
+		status = 0;
+	dev_dbg(&intf->dev, "resume status %d\n", status);
+	return status;
+}
+
 static struct usb_device_id hid_usb_ids [] = {
 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
 	    .bInterfaceClass = USB_INTERFACE_CLASS_HID },
@@ -1846,6 +1871,8 @@
 	.name =		"usbhid",
 	.probe =	hid_probe,
 	.disconnect =	hid_disconnect,
+	.suspend =	hid_suspend,
+	.resume =	hid_resume,
 	.id_table =	hid_usb_ids,
 };
 
diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
--- a/drivers/usb/media/dabusb.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/media/dabusb.c	2004-10-28 22:25:58 -07:00
@@ -595,8 +595,7 @@
 		if (file->f_flags & O_NONBLOCK) {
 			return -EBUSY;
 		}
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout (HZ / 2);
+		msleep_interruptible(500);
 
 		if (signal_pending (current)) {
 			return -EAGAIN;
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- a/drivers/usb/media/ov511.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/media/ov511.c	2004-10-28 22:25:57 -07:00
@@ -4756,7 +4756,7 @@
 
 	pos = (unsigned long)ov->fbuf;
 	while (size > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
 			up(&ov->lock);
 			return -EAGAIN;
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- a/drivers/usb/media/se401.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/media/se401.c	2004-10-28 22:25:57 -07:00
@@ -1168,7 +1168,7 @@
 	}
 	pos = (unsigned long)se401->fbuf;
 	while (size > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
 			up(&se401->lock);
 			return -EAGAIN;
diff -Nru a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
--- a/drivers/usb/media/sn9c102_core.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/usb/media/sn9c102_core.c	2004-10-28 22:25:56 -07:00
@@ -1555,7 +1555,7 @@
 
 	pos = (unsigned long)cam->frame[i].bufmem;
 	while (size > 0) { /* size is page-aligned */
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE,
 		                     vma->vm_page_prot)) {
 			up(&cam->fileop_sem);
diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
--- a/drivers/usb/media/stv680.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/media/stv680.c	2004-10-28 22:25:58 -07:00
@@ -1277,7 +1277,7 @@
 	}
 	pos = (unsigned long) stv680->fbuf;
 	while (size > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
 			up (&stv680->lock);
 			return -EAGAIN;
diff -Nru a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
--- a/drivers/usb/media/usbvideo.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/media/usbvideo.c	2004-10-28 22:25:59 -07:00
@@ -1153,7 +1153,7 @@
 
 	pos = (unsigned long) uvd->fbuf;
 	while (size > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
 			return -EAGAIN;
 
diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/media/vicam.c	2004-10-28 22:25:57 -07:00
@@ -1045,7 +1045,7 @@
 
 	pos = (unsigned long)cam->framebuf;
 	while (size > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
 			return -EAGAIN;
 
diff -Nru a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
--- a/drivers/usb/media/w9968cf.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/media/w9968cf.c	2004-10-28 22:25:59 -07:00
@@ -2904,7 +2904,7 @@
 		return -EINVAL;
 
 	while (vsize > 0) {
-		page = page_to_pfn(vmalloc_to_page((void *)pos));
+		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page + vma->vm_pgoff,
 						PAGE_SIZE, vma->vm_page_prot))
 			return -EAGAIN;
diff -Nru a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h
--- a/drivers/usb/media/w9968cf.h	2004-10-28 22:25:56 -07:00
+++ b/drivers/usb/media/w9968cf.h	2004-10-28 22:25:56 -07:00
@@ -135,7 +135,7 @@
 
 #define W9968CF_MODULE_NAME     "V4L driver for W996[87]CF JPEG USB " \
                                 "Dual Mode Camera Chip"
-#define W9968CF_MODULE_VERSION  "1:1.32-basic"
+#define W9968CF_MODULE_VERSION  "1:1.33-basic"
 #define W9968CF_MODULE_AUTHOR   "(C) 2002-2004 Luca Risolia"
 #define W9968CF_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define W9968CF_MODULE_LICENSE  "GPL"
diff -Nru a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
--- a/drivers/usb/misc/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/misc/Kconfig	2004-10-28 22:25:59 -07:00
@@ -121,6 +121,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cytherm.
 
+config USB_PHIDGETKIT
+	tristate "USB PhidgetKit support"
+	depends on USB
+	help
+	  Say Y here if you want to connect a PhidgetKit USB device from
+	  Phidgets Inc.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called phidgetkit.
+
 config USB_PHIDGETSERVO
 	tristate "USB PhidgetServo support"
 	depends on USB
diff -Nru a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
--- a/drivers/usb/misc/Makefile	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/misc/Makefile	2004-10-28 22:25:58 -07:00
@@ -10,8 +10,9 @@
 obj-$(CONFIG_USB_LCD)		+= usblcd.o
 obj-$(CONFIG_USB_LED)		+= usbled.o
 obj-$(CONFIG_USB_LEGOTOWER)	+= legousbtower.o
+obj-$(CONFIG_USB_PHIDGETKIT)	+= phidgetkit.o
+obj-$(CONFIG_USB_PHIDGETSERVO)	+= phidgetservo.o
 obj-$(CONFIG_USB_RIO500)	+= rio500.o
 obj-$(CONFIG_USB_TEST)		+= usbtest.o
 obj-$(CONFIG_USB_TIGL)		+= tiglusb.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
-obj-$(CONFIG_USB_PHIDGETSERVO)	+= phidgetservo.o
diff -Nru a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/misc/phidgetkit.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,581 @@
+/*
+ * USB PhidgetInterfaceKit driver 1.0
+ *
+ * Copyright (C) 2004 Sean Young <sean@mess.org>
+ * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is a driver for the USB PhidgetInterfaceKit.
+ */
+
+#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/usb.h>
+
+#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
+#define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
+
+#define USB_VENDOR_ID_GLAB		0x06c2
+#define USB_DEVICE_ID_INTERFACEKIT004	0x0040
+#define USB_DEVICE_ID_INTERFACEKIT888	0x0045
+#define USB_DEVICE_ID_INTERFACEKIT047	0x0051
+#define USB_DEVICE_ID_INTERFACEKIT088	0x0053
+
+#define USB_VENDOR_ID_WISEGROUP		0x0925
+#define USB_DEVICE_ID_INTERFACEKIT884	0x8201
+
+#define MAX_INTERFACES			8
+
+struct driver_interfacekit {
+	int sensors;
+	int inputs;
+	int outputs;
+	int has_lcd;
+};
+#define ifkit(_sensors, _inputs, _outputs, _lcd)			\
+static struct driver_interfacekit ph_##_sensors##_inputs##_outputs = {	\
+	.sensors	= _sensors,					\
+	.inputs		= _inputs,					\
+	.outputs	= _outputs,					\
+	.has_lcd	= _lcd,						\
+};
+ifkit(0, 0, 4, 0);
+ifkit(8, 8, 8, 0);
+ifkit(0, 4, 7, 1);
+ifkit(8, 8, 4, 0);
+ifkit(0, 8, 8, 1);
+
+struct phidget_interfacekit {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	struct driver_interfacekit *ifkit;
+	int outputs[MAX_INTERFACES];
+	int inputs[MAX_INTERFACES];
+	int sensors[MAX_INTERFACES];
+	u8 lcd_files_on;
+
+	struct urb *irq;
+	unsigned char *data;
+	dma_addr_t data_dma;
+};
+
+static struct usb_device_id id_table[] = {
+	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004),
+		.driver_info = (kernel_ulong_t)&ph_004},
+	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888),
+		.driver_info = (kernel_ulong_t)&ph_888},
+	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047),
+		.driver_info = (kernel_ulong_t)&ph_047},
+	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
+		.driver_info = (kernel_ulong_t)&ph_088},
+	{USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884),
+		.driver_info = (kernel_ulong_t)&ph_884},
+	{}
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable)
+{
+	unsigned char *buffer;
+	int retval;
+	int n;
+
+	buffer = kmalloc(4, GFP_KERNEL);
+	if (!buffer) {
+		dev_err(&kit->udev->dev, "%s - out of memory\n",
+			__FUNCTION__);
+		return -ENOMEM;
+	}
+
+	kit->outputs[output_num] = enable;
+	memset(buffer, 0, 4);
+	for (n=0; n<8; n++) {
+		if (kit->outputs[n]) {
+			buffer[0] |= 1 << n;
+		}
+	}
+
+	dev_dbg(&kit->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]);
+
+	retval = usb_control_msg(kit->udev,
+			 usb_sndctrlpipe(kit->udev, 0),
+			 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2 * HZ);
+
+	if (retval != 4)
+		dev_err(&kit->udev->dev, "retval = %d\n", retval);
+	kfree(buffer);
+
+	return retval < 0 ? retval : 0;
+}
+
+static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row)
+{
+	unsigned char *buffer;
+        unsigned char *form_buffer;
+	int retval = -ENOMEM;
+	int i,j, len, buf_ptr;
+	
+	buffer = kmalloc(8, GFP_KERNEL);
+	form_buffer = kmalloc(30, GFP_KERNEL);
+	if ((!buffer) || (!form_buffer)) {
+		dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
+		goto exit;
+	}
+
+	len = strlen(display);
+	if (len > 20)
+		len = 20;
+
+	dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display);
+
+	form_buffer[0] = row * 0x40 + 0x80;
+	form_buffer[1] = 0x02;
+	buf_ptr = 2;
+	for (i = 0; i<len; i++)
+		form_buffer[buf_ptr++] = display[i];
+
+	for (i = 0; i < (20 - len); i++)
+		form_buffer[buf_ptr++] = 0x20;
+	form_buffer[buf_ptr++] = 0x01;
+	form_buffer[buf_ptr++] = row * 0x40 + 0x80 + strlen(display);
+
+	for (i = 0; i < buf_ptr; i += 7) {
+		if ((buf_ptr - i) > 7)
+			len = 7;
+		else
+			len = (buf_ptr - i);
+		for (j = 0; j < len; j++)
+			buffer[j] = form_buffer[i + j];
+		buffer[7] = len;
+
+		retval = usb_control_msg(kit->udev,
+				 usb_sndctrlpipe(kit->udev, 0),
+				 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
+		if (retval < 0)
+			goto exit;
+	}
+
+	retval = 0;
+exit:
+	kfree(buffer);
+	kfree(form_buffer);
+
+	return retval;
+}
+
+#define set_lcd_line(number)	\
+static ssize_t lcd_line_##number(struct device *dev, const char *buf, size_t count)	\
+{											\
+	struct usb_interface *intf = to_usb_interface(dev);				\
+	struct phidget_interfacekit *kit = usb_get_intfdata(intf);			\
+	change_string(kit, buf, number - 1);						\
+	return count;									\
+}											\
+static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
+set_lcd_line(1);
+set_lcd_line(2);
+
+static ssize_t set_backlight(struct device *dev, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct phidget_interfacekit *kit = usb_get_intfdata(intf);
+	int enabled;
+	unsigned char *buffer;
+	int retval = -ENOMEM;
+	
+	buffer = kmalloc(8, GFP_KERNEL);
+	if (!buffer) {
+		dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
+		goto exit;
+	}
+
+	if (sscanf(buf, "%d", &enabled) < 1) {
+		retval = -EINVAL;
+		goto exit;
+	}
+	memset(buffer, 0x00, 8);
+	if (enabled)
+		buffer[0] = 0x01;
+	buffer[7] = 0x11;
+
+	dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off");
+	
+	retval = usb_control_msg(kit->udev,
+			 usb_sndctrlpipe(kit->udev, 0),
+			 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
+	if (retval < 0)
+		goto exit;
+
+	retval = count;
+exit:
+	kfree(buffer);
+	return retval;
+}
+static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
+
+static void remove_lcd_files(struct phidget_interfacekit *kit)
+{
+	if (kit->lcd_files_on) {
+		dev_dbg(&kit->udev->dev, "Removing lcd files\n");
+		device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1);
+		device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2);
+		device_remove_file(&kit->intf->dev, &dev_attr_backlight);
+	}
+}
+
+static ssize_t enable_lcd_files(struct device *dev, const char *buf, size_t count)
+{
+	struct usb_interface *intf = to_usb_interface(dev);
+	struct phidget_interfacekit *kit = usb_get_intfdata(intf);
+	int enable;
+	
+	if (kit->ifkit->has_lcd == 0)
+		return -ENODEV;
+
+	if (sscanf(buf, "%d", &enable) < 1)
+		return -EINVAL;
+
+	if (enable) {
+		if (!kit->lcd_files_on) {
+			dev_dbg(&kit->udev->dev, "Adding lcd files\n");
+			device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1);
+			device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2);
+			device_create_file(&kit->intf->dev, &dev_attr_backlight);
+			kit->lcd_files_on = 1;
+		}
+	} else {
+		if (kit->lcd_files_on) {
+			remove_lcd_files(kit);
+			kit->lcd_files_on = 0;
+		}
+	}
+	
+	return count;
+}
+static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
+
+static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct phidget_interfacekit *kit = urb->context;
+	unsigned char *buffer = kit->data;
+	int status;
+	int n;
+
+	switch (urb->status) {
+	case 0:			/* success */
+		break;
+	case -ECONNRESET:	/* unlink */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	/* -EPIPE:  should clear the halt */
+	default:		/* error */
+		goto resubmit;
+	}
+
+	for (n=0; n<8; n++) {
+		kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0;
+	}
+
+	if (buffer[0] & 1) {
+		kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256;
+		kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16;
+		kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256;
+		kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16;
+	} else {
+		kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256;
+		kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16;
+		kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256;
+		kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16;
+	}
+
+resubmit:
+	status = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (status)
+		err("can't resubmit intr, %s-%s/interfacekit0, status %d",
+			kit->udev->bus->bus_name,
+			kit->udev->devpath, status);
+}
+
+#define show_set_output(value)		\
+static ssize_t set_output##value(struct device *dev, const char *buf, 	\
+							size_t count)	\
+{									\
+	struct usb_interface *intf = to_usb_interface(dev);		\
+	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+	int enabled;							\
+	int retval;							\
+									\
+	if (sscanf(buf, "%d", &enabled) < 1) {				\
+		return -EINVAL;						\
+	}								\
+									\
+	retval = change_outputs(kit, value - 1, enabled ? 1 : 0);	\
+									\
+	return retval ? retval : count;					\
+}									\
+									\
+static ssize_t show_output##value(struct device *dev, char *buf)	\
+{									\
+	struct usb_interface *intf = to_usb_interface(dev);		\
+	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+									\
+	return sprintf(buf, "%d\n", kit->outputs[value - 1 ]);		\
+}									\
+static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO,			\
+		show_output##value, set_output##value);
+show_set_output(1);
+show_set_output(2);
+show_set_output(3);
+show_set_output(4);
+show_set_output(5);
+show_set_output(6);
+show_set_output(7);
+show_set_output(8);	/* should be MAX_INTERFACES - 1 */
+
+#define show_input(value)	\
+static ssize_t show_input##value(struct device *dev, char *buf)	\
+{									\
+	struct usb_interface *intf = to_usb_interface(dev);		\
+	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+									\
+	return sprintf(buf, "%d\n", kit->inputs[value - 1]);		\
+}									\
+static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
+
+show_input(1);
+show_input(2);
+show_input(3);
+show_input(4);
+show_input(5);
+show_input(6);
+show_input(7);
+show_input(8);		/* should be MAX_INTERFACES - 1 */
+
+#define show_sensor(value)	\
+static ssize_t show_sensor##value(struct device *dev, char *buf)	\
+{									\
+	struct usb_interface *intf = to_usb_interface(dev);		\
+	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+									\
+	return sprintf(buf, "%d\n", kit->sensors[value - 1]);		\
+}									\
+static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
+
+show_sensor(1);
+show_sensor(2);
+show_sensor(3);
+show_sensor(4);
+show_sensor(5);
+show_sensor(6);
+show_sensor(7);
+show_sensor(8);		/* should be MAX_INTERFACES - 1 */
+
+static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct phidget_interfacekit *kit;
+	struct driver_interfacekit *ifkit;
+	int pipe, maxp;
+
+	ifkit = (struct driver_interfacekit *)id->driver_info;
+	if (!ifkit)
+		return -ENODEV;
+
+	interface = intf->cur_altsetting;
+	if (interface->desc.bNumEndpoints != 1)
+		return -ENODEV;
+
+	endpoint = &interface->endpoint[0].desc;
+	if (!(endpoint->bEndpointAddress & 0x80)) 
+		return -ENODEV;
+	/*
+	 * bmAttributes
+	 */
+	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+	
+	kit = kmalloc(sizeof(*kit), GFP_KERNEL);
+	if (kit  == NULL) {
+		dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__);
+		return -ENOMEM;
+	}
+	memset(kit, 0, sizeof(*kit));
+	kit->ifkit = ifkit;
+
+	kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma);
+	if (!kit->data) {
+		kfree(kit);
+		return -ENOMEM;
+	}
+
+	kit->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!kit->irq) {
+		usb_buffer_free(dev, 8, kit->data, kit->data_dma);
+		kfree(kit);
+		return -ENOMEM;
+	}
+
+	kit->udev = usb_get_dev(dev);
+	kit->intf = intf;
+	usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
+			(maxp > 8 ? 8 : maxp),
+			interfacekit_irq, kit, endpoint->bInterval);
+	kit->irq->transfer_dma = kit->data_dma;
+	kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	usb_set_intfdata(intf, kit);
+
+	if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
+		return -EIO;
+	}
+
+	if (ifkit->outputs == 8) {
+		device_create_file(&intf->dev, &dev_attr_output1);
+		device_create_file(&intf->dev, &dev_attr_output2);
+		device_create_file(&intf->dev, &dev_attr_output3);
+		device_create_file(&intf->dev, &dev_attr_output4);
+		device_create_file(&intf->dev, &dev_attr_output5);
+		device_create_file(&intf->dev, &dev_attr_output6);
+		device_create_file(&intf->dev, &dev_attr_output7);
+		device_create_file(&intf->dev, &dev_attr_output8);
+	} 
+
+	if (ifkit->inputs >= 4) {
+		device_create_file(&intf->dev, &dev_attr_input1);
+		device_create_file(&intf->dev, &dev_attr_input2);
+		device_create_file(&intf->dev, &dev_attr_input3);
+		device_create_file(&intf->dev, &dev_attr_input4);
+	}
+	if (ifkit->inputs == 8) {
+		device_create_file(&intf->dev, &dev_attr_input5);
+		device_create_file(&intf->dev, &dev_attr_input6);
+		device_create_file(&intf->dev, &dev_attr_input7);
+		device_create_file(&intf->dev, &dev_attr_input8);
+	}
+
+	if (ifkit->sensors >= 4) {
+		device_create_file(&intf->dev, &dev_attr_sensor1);
+		device_create_file(&intf->dev, &dev_attr_sensor2);
+		device_create_file(&intf->dev, &dev_attr_sensor3);
+		device_create_file(&intf->dev, &dev_attr_sensor4);
+	}
+	if (ifkit->sensors >= 7) {
+		device_create_file(&intf->dev, &dev_attr_sensor5);
+		device_create_file(&intf->dev, &dev_attr_sensor6);
+		device_create_file(&intf->dev, &dev_attr_sensor7);
+	}
+	if (ifkit->sensors == 8) {
+		device_create_file(&intf->dev, &dev_attr_sensor8);
+	}
+
+	if (ifkit->has_lcd)
+		device_create_file(&intf->dev, &dev_attr_lcd);
+
+	dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
+			ifkit->inputs, ifkit->outputs, ifkit->sensors);
+
+	return 0;
+}
+
+static void interfacekit_disconnect(struct usb_interface *interface)
+{
+	struct phidget_interfacekit *kit;
+
+	kit = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+	if (!kit)
+		return;
+
+	if (kit->ifkit->outputs == MAX_INTERFACES) {
+		device_remove_file(&interface->dev, &dev_attr_output1);
+		device_remove_file(&interface->dev, &dev_attr_output2);
+		device_remove_file(&interface->dev, &dev_attr_output3);
+		device_remove_file(&interface->dev, &dev_attr_output4);
+		device_remove_file(&interface->dev, &dev_attr_output5);
+		device_remove_file(&interface->dev, &dev_attr_output6);
+		device_remove_file(&interface->dev, &dev_attr_output7);
+		device_remove_file(&interface->dev, &dev_attr_output7);
+	}
+
+	if (kit->ifkit->inputs >= 4) {
+		device_remove_file(&interface->dev, &dev_attr_input1);
+		device_remove_file(&interface->dev, &dev_attr_input2);
+		device_remove_file(&interface->dev, &dev_attr_input3);
+		device_remove_file(&interface->dev, &dev_attr_input4);
+	}
+	if (kit->ifkit->inputs == 8) {
+		device_remove_file(&interface->dev, &dev_attr_input5);
+		device_remove_file(&interface->dev, &dev_attr_input6);
+		device_remove_file(&interface->dev, &dev_attr_input7);
+		device_remove_file(&interface->dev, &dev_attr_input8);
+	}
+
+	if (kit->ifkit->sensors >= 4) {
+		device_remove_file(&interface->dev, &dev_attr_sensor1);
+		device_remove_file(&interface->dev, &dev_attr_sensor2);
+		device_remove_file(&interface->dev, &dev_attr_sensor3);
+		device_remove_file(&interface->dev, &dev_attr_sensor4);
+	}
+	if (kit->ifkit->sensors >= 7) {
+		device_remove_file(&interface->dev, &dev_attr_sensor5);
+		device_remove_file(&interface->dev, &dev_attr_sensor6);
+		device_remove_file(&interface->dev, &dev_attr_sensor7);
+	}
+	if (kit->ifkit->sensors == 8) {
+		device_remove_file(&interface->dev, &dev_attr_sensor8);
+	}
+	if (kit->ifkit->has_lcd)
+		device_create_file(&interface->dev, &dev_attr_lcd);
+
+	dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
+		kit->ifkit->inputs, kit->ifkit->outputs, kit->ifkit->sensors);
+
+	usb_kill_urb(kit->irq);
+	usb_free_urb(kit->irq);
+	usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma);
+
+	usb_put_dev(kit->udev);
+	kfree(kit);
+}
+
+static struct usb_driver interfacekit_driver = {
+	.owner = THIS_MODULE,
+	.name = "phidgetkit",
+	.probe = interfacekit_probe,
+	.disconnect = interfacekit_disconnect,
+	.id_table = id_table
+};
+
+static int __init interfacekit_init(void)
+{
+	int retval = 0;
+
+	retval = usb_register(&interfacekit_driver);
+	if (retval)
+		err("usb_register failed. Error number %d", retval);
+
+	return retval;
+}
+
+static void __exit interfacekit_exit(void)
+{
+	usb_deregister(&interfacekit_driver);
+}
+
+module_init(interfacekit_init);
+module_exit(interfacekit_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
--- a/drivers/usb/misc/tiglusb.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/usb/misc/tiglusb.c	2004-10-28 22:25:56 -07:00
@@ -4,7 +4,7 @@
  * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
  *
  * Copyright (C) 2001-2004:
- *   Romain Lievin <roms@lpg.ticalc.org>
+ *   Romain Lievin <roms@tilp.info>
  *   Julien BLACHE <jb@technologeek.org>
  * under the terms of the GNU General Public License.
  *
@@ -14,7 +14,7 @@
  * and the website at:  http://lpg.ticalc.org/prj_usb/
  * for more info.
  *
- * History :
+ * History:
  *   1.0x, Romain & Julien: initial submit.
  *   1.03, Greg Kroah: modifications.
  *   1.04, Julien: clean-up & fixes; Romain: 2.4 backport.
@@ -22,6 +22,7 @@
  *   1.06, Romain: synched with 2.5, version/firmware changed (confusing).
  *   1.07, Romain: fixed bad use of usb_clear_halt (invalid argument);
  *          timeout argument checked in ioctl + clean-up.
+ *   1.08, Romain: added support of USB port embedded on some TI's handhelds.
  */
 
 #include <linux/module.h>
@@ -41,7 +42,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "1.07"
+#define DRIVER_VERSION "1.08"
 #define DRIVER_AUTHOR  "Romain Lievin <roms@tilp.info> & Julien Blache <jb@jblache.org>"
 #define DRIVER_DESC    "TI-GRAPH LINK USB (aka SilverLink) driver"
 #define DRIVER_LICENSE "GPL"
@@ -115,8 +116,7 @@
 			return -EBUSY;
 		}
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout (HZ / 2);
+		msleep_interruptible(500);
 
 		if (signal_pending (current)) {
 			return -EAGAIN;
@@ -178,11 +178,11 @@
 	if (!s->dev)
 		return -EIO;
 
-	buffer = kmalloc(BULK_RCV_MAX, GFP_KERNEL);
+	buffer = kmalloc (s->max_ps, GFP_KERNEL);
 	if (!buffer)
 		return -ENOMEM;
 
-	bytes_to_read = (count >= BULK_RCV_MAX) ? BULK_RCV_MAX : count;
+	bytes_to_read = (count >= s->max_ps) ? s->max_ps : count;
 
 	pipe = usb_rcvbulkpipe (s->dev, 1);
 	result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
@@ -235,11 +235,11 @@
 	if (!s->dev)
 		return -EIO;
 
-	buffer = kmalloc(BULK_SND_MAX, GFP_KERNEL);
+	buffer = kmalloc (s->max_ps, GFP_KERNEL);
 	if (!buffer)
 		return -ENOMEM;
 
-	bytes_to_write = (count >= BULK_SND_MAX) ? BULK_SND_MAX : count;
+	bytes_to_write = (count >= s->max_ps) ? s->max_ps : count;
 	if (copy_from_user (buffer, buf, bytes_to_write)) {
 		ret = -EFAULT;
 		goto out;
@@ -309,6 +309,15 @@
 		if (clear_pipes (s->dev))
 			ret = -EIO;
 		break;
+	case IOCTL_TIUSB_GET_MAXPS:
+                if (copy_to_user((int *) arg, &s->max_ps, sizeof(int)))
+                        return -EFAULT;
+                break;
+        case IOCTL_TIUSB_GET_DEVID:
+                if (copy_to_user((int *) arg, &s->dev->descriptor.idProduct,
+                                 sizeof(int)))
+                        return -EFAULT;
+                break;
 	default:
 		ret = -ENOTTY;
 		break;
@@ -341,6 +350,9 @@
 	int minor = -1;
 	int i, err = 0;
 	ptiglusb_t s;
+	struct usb_host_config *conf;
+        struct usb_host_interface *ifdata = NULL;
+        int max_ps;
 
 	dbg ("probing vendor id 0x%x, device id 0x%x",
 	     dev->descriptor.idVendor, dev->descriptor.idProduct);
@@ -355,19 +367,31 @@
 		goto out;
 	}
 
-	if ((dev->descriptor.idProduct != 0xe001)
-	    && (dev->descriptor.idVendor != 0x451)) {
+	if (dev->descriptor.idVendor != 0x451) {
 		err = -ENODEV;
 		goto out;
 	}
 
-	// NOTE:  it's already in this config, this shouldn't be needed.
-	// is this working around some hardware bug?
-	if (usb_reset_configuration (dev) < 0) {
-		err ("tiglusb_probe: reset_configuration failed");
-		err = -ENODEV;
-		goto out;
-	}
+	if ((dev->descriptor.idProduct != 0xe001) &&
+            (dev->descriptor.idProduct != 0xe004) &&
+            (dev->descriptor.idProduct != 0xe008)) {
+                err = -ENODEV;
+                goto out;
+        }
+
+	/*
+         * TI introduced some new handhelds with embedded USB port.
+         * Port advertises same config as SilverLink cable but with a 
+	 * different maximum packet size (64 rather than 32).
+         */
+
+        conf = dev->actconfig;
+        ifdata = conf->interface[0]->cur_altsetting;
+        max_ps = ifdata->endpoint[0].desc.wMaxPacketSize;
+
+        info("max packet size of %d/%d bytes\n",
+             ifdata->endpoint[0].desc.wMaxPacketSize,
+             ifdata->endpoint[1].desc.wMaxPacketSize);
 
 	/*
 	 * Find a tiglusb struct
@@ -390,6 +414,7 @@
 	down (&s->mutex);
 	s->remove_pending = 0;
 	s->dev = dev;
+	s->max_ps = max_ps;
 	up (&s->mutex);
 	dbg ("bound to interface");
 
diff -Nru a/drivers/usb/misc/tiglusb.h b/drivers/usb/misc/tiglusb.h
--- a/drivers/usb/misc/tiglusb.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/misc/tiglusb.h	2004-10-28 22:25:59 -07:00
@@ -18,12 +18,6 @@
 #define MAXTIGL		16
 
 /*
- * Max. packetsize for IN and OUT pipes
- */
-#define BULK_RCV_MAX	32
-#define BULK_SND_MAX	32
-
-/*
  * The driver context...
  */
 
@@ -42,6 +36,8 @@
 	driver_state_t	state;			/* started/stopped */
 	int		opened;			/* tru if open */
 	int	remove_pending;
+
+	int             max_ps;                 /* max packet size */
 } tiglusb_t, *ptiglusb_t;
 
 #endif
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/net/kaweth.c	2004-10-28 22:25:58 -07:00
@@ -246,7 +246,7 @@
 	struct kaweth_ethernet_configuration configuration;
 
 	struct net_device_stats stats;
-} __attribute__ ((packed));
+};
 
 
 /****************************************************************
@@ -651,7 +651,7 @@
  ****************************************************************/
 static int kaweth_open(struct net_device *net)
 {
-	struct kaweth_device *kaweth = (struct kaweth_device *)net->priv;
+	struct kaweth_device *kaweth = netdev_priv(net);
 	int res;
 
 	kaweth_dbg("Opening network device.");
@@ -689,7 +689,7 @@
  ****************************************************************/
 static int kaweth_close(struct net_device *net)
 {
-	struct kaweth_device *kaweth = net->priv;
+	struct kaweth_device *kaweth = netdev_priv(net);
 
 	netif_stop_queue(net);
 
@@ -729,7 +729,8 @@
 	struct sk_buff *skb = kaweth->tx_skb;
 
 	if (unlikely(urb->status != 0))
-		kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
+		if (urb->status != -ENOENT)
+			kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
 
 	netif_wake_queue(kaweth->net);
 	dev_kfree_skb_irq(skb);
@@ -740,7 +741,7 @@
  ****************************************************************/
 static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
-	struct kaweth_device *kaweth = net->priv;
+	struct kaweth_device *kaweth = netdev_priv(net);
 	__le16 *private_header;
 
 	int res;
@@ -811,7 +812,7 @@
  ****************************************************************/
 static void kaweth_set_rx_mode(struct net_device *net)
 {
-	struct kaweth_device *kaweth = net->priv;
+	struct kaweth_device *kaweth = netdev_priv(net);
 
 	__u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
                                      KAWETH_PACKET_FILTER_BROADCAST |
@@ -868,7 +869,8 @@
  ****************************************************************/
 static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev)
 {
-	return &((struct kaweth_device *)dev->priv)->stats;
+	struct kaweth_device *kaweth = netdev_priv(dev);
+	return &kaweth->stats;
 }
 
 /****************************************************************
@@ -876,7 +878,7 @@
  ****************************************************************/
 static void kaweth_tx_timeout(struct net_device *net)
 {
-	struct kaweth_device *kaweth = net->priv;
+	struct kaweth_device *kaweth = netdev_priv(net);
 
 	kaweth_warn("%s: Tx timed out. Resetting.", net->name);
 	kaweth->stats.tx_errors++;
@@ -911,12 +913,14 @@
 		 (int)dev->descriptor.bLength,
 		 (int)dev->descriptor.bDescriptorType);
 
-	if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL)))
+	netdev = alloc_etherdev(sizeof(*kaweth));
+	if (!netdev)
 		return -ENOMEM;
 
-	memset(kaweth, 0, sizeof(struct kaweth_device));
-
+	kaweth = netdev_priv(netdev);
 	kaweth->dev = dev;
+	kaweth->net = netdev;
+
 	spin_lock_init(&kaweth->device_lock);
 	init_waitqueue_head(&kaweth->term_wait);
 
@@ -941,9 +945,7 @@
 						      100,
 						      2)) < 0) {
 			kaweth_err("Error downloading firmware (%d)", result);
-			free_page((unsigned long)kaweth->firmware_buf);
-			kfree(kaweth);
-			return -EIO;
+			goto err_fw;
 		}
 
 		if ((result = kaweth_download_firmware(kaweth,
@@ -952,9 +954,7 @@
 						      100,
 						      3)) < 0) {
 			kaweth_err("Error downloading firmware fix (%d)", result);
-			free_page((unsigned long)kaweth->firmware_buf);
-			kfree(kaweth);
-			return -EIO;
+			goto err_fw;
 		}
 
 		if ((result = kaweth_download_firmware(kaweth,
@@ -963,9 +963,8 @@
 						      126,
 						      2)) < 0) {
 			kaweth_err("Error downloading trigger code (%d)", result);
-			free_page((unsigned long)kaweth->firmware_buf);
-			kfree(kaweth);
-			return -EIO;
+			goto err_fw;
+
 		}
 
 		if ((result = kaweth_download_firmware(kaweth,
@@ -974,23 +973,20 @@
 						      126,
 						      3)) < 0) {
 			kaweth_err("Error downloading trigger code fix (%d)", result);
-			free_page((unsigned long)kaweth->firmware_buf);
-			kfree(kaweth);
-			return -EIO;
+			goto err_fw;
 		}
 
 
 		if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
 			kaweth_err("Error triggering firmware (%d)", result);
-			free_page((unsigned long)kaweth->firmware_buf);
-			kfree(kaweth);
-			return -EIO;
+			goto err_fw;
 		}
 
 		/* Device will now disappear for a moment...  */
 		kaweth_info("Firmware loaded.  I'll be back...");
+err_fw:
 		free_page((unsigned long)kaweth->firmware_buf);
-		kfree(kaweth);
+		free_netdev(netdev);
 		return -EIO;
 	}
 
@@ -998,8 +994,7 @@
 
 	if(result < 0) {
 		kaweth_err("Error reading configuration (%d), no net device created", result);
-		kfree(kaweth);
-		return -EIO;
+		goto err_free_netdev;
 	}
 
 	kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask);
@@ -1017,18 +1012,17 @@
                    &bcast_addr,
 		   sizeof(bcast_addr))) {
 		kaweth_err("Firmware not functioning properly, no net device created");
-		kfree(kaweth);
-		return -EIO;
+		goto err_free_netdev;
 	}
 
 	if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
 		kaweth_dbg("Error setting URB size");
-		goto err_no_netdev;
+		goto err_free_netdev;
 	}
 
 	if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
 		kaweth_err("Error setting SOFS wait");
-		goto err_no_netdev;
+		goto err_free_netdev;
 	}
 
 	result = kaweth_set_receive_filter(kaweth,
@@ -1038,20 +1032,14 @@
 
 	if(result < 0) {
 		kaweth_err("Error setting receive filter");
-		kfree(kaweth);
-		return -EIO;
+		goto err_free_netdev;
 	}
 
 	kaweth_dbg("Initializing net device.");
 
-	if (!(netdev = alloc_etherdev(0))) {
-		kfree(kaweth);
-		return -ENOMEM;
-	}
-
 	kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!kaweth->tx_urb)
-		goto err_no_urb;
+		goto err_free_netdev;
 	kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!kaweth->rx_urb)
 		goto err_only_tx;
@@ -1072,26 +1060,23 @@
 	if (!kaweth->rx_buf)
 		goto err_all_but_rxbuf;
 
-	kaweth->net = netdev;
-	memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr));
-	memcpy(kaweth->net->dev_addr,
-               &kaweth->configuration.hw_addr,
+	memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr));
+	memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr,
                sizeof(kaweth->configuration.hw_addr));
 
-	kaweth->net->priv = kaweth;
-	kaweth->net->open = kaweth_open;
-	kaweth->net->stop = kaweth_close;
-
-	kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
-	kaweth->net->tx_timeout = kaweth_tx_timeout;
-
-	kaweth->net->hard_start_xmit = kaweth_start_xmit;
-	kaweth->net->set_multicast_list = kaweth_set_rx_mode;
-	kaweth->net->get_stats = kaweth_netdev_stats;
-	kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size);
-	SET_ETHTOOL_OPS(kaweth->net, &ops);
+	netdev->open = kaweth_open;
+	netdev->stop = kaweth_close;
+
+	netdev->watchdog_timeo = KAWETH_TX_TIMEOUT;
+	netdev->tx_timeout = kaweth_tx_timeout;
+
+	netdev->hard_start_xmit = kaweth_start_xmit;
+	netdev->set_multicast_list = kaweth_set_rx_mode;
+	netdev->get_stats = kaweth_netdev_stats;
+	netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size);
+	SET_ETHTOOL_OPS(netdev, &ops);
 
-	memset(&kaweth->stats, 0, sizeof(kaweth->stats));
+	/* kaweth is zeroed as part of alloc_netdev */
 
 	INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth);
 
@@ -1128,10 +1113,9 @@
 	usb_free_urb(kaweth->rx_urb);
 err_only_tx:
 	usb_free_urb(kaweth->tx_urb);
-err_no_urb:
+err_free_netdev:
 	free_netdev(netdev);
-err_no_netdev:
-	kfree(kaweth);
+
 	return -EIO;
 }
 
@@ -1141,6 +1125,7 @@
 static void kaweth_disconnect(struct usb_interface *intf)
 {
 	struct kaweth_device *kaweth = usb_get_intfdata(intf);
+	struct net_device *netdev;
 
 	kaweth_info("Unregistering");
 
@@ -1149,40 +1134,23 @@
 		kaweth_warn("unregistering non-existant device");
 		return;
 	}
-
+	netdev = kaweth->net;
 	kaweth->removed = 1;
 	usb_kill_urb(kaweth->irq_urb);
 	usb_kill_urb(kaweth->rx_urb);
+	usb_kill_urb(kaweth->tx_urb);
 
-	/* we need to wait for the urb to be cancelled, if it is active */
-	spin_lock(&kaweth->device_lock);
-	if (usb_unlink_urb(kaweth->tx_urb) == -EINPROGRESS) {
-		spin_unlock(&kaweth->device_lock);
-		wait_event(kaweth->term_wait, kaweth->end);
-	} else {
-		spin_unlock(&kaweth->device_lock);
-	}
-
-	if(kaweth->net) {
-		if(kaweth->net->flags & IFF_UP) {
-			kaweth_dbg("Closing net device");
-			dev_close(kaweth->net);
-		}
-
-		kaweth_dbg("Unregistering net device");
-		unregister_netdev(kaweth->net);
-		free_netdev(kaweth->net);
-	}
+	kaweth_dbg("Unregistering net device");
+	unregister_netdev(netdev);
 
 	usb_free_urb(kaweth->rx_urb);
 	usb_free_urb(kaweth->tx_urb);
 	usb_free_urb(kaweth->irq_urb);
 
-
 	usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);
 	usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);
 
-	kfree(kaweth);
+	free_netdev(netdev);
 }
 
 
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/net/usbnet.c	2004-10-28 22:25:58 -07:00
@@ -567,7 +567,7 @@
 
 static void ax8817x_set_multicast(struct net_device *net)
 {
-	struct usbnet *dev = (struct usbnet *) net->priv;
+	struct usbnet *dev = netdev_priv(net);
 	struct ax8817x_data *data = (struct ax8817x_data *)&dev->data;
 	u8 rx_ctl = 0x8c;
 
@@ -610,7 +610,7 @@
 
 static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc)
 {
-	struct usbnet *dev = netdev->priv;
+	struct usbnet *dev = netdev_priv(netdev);
 	u16 res;
 	u8 buf[1];
 
@@ -623,7 +623,7 @@
 
 static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
 {
-	struct usbnet *dev = netdev->priv;
+	struct usbnet *dev = netdev_priv(netdev);
 	u16 res = val;
 	u8 buf[1];
 
@@ -634,7 +634,7 @@
 
 static void ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
-	struct usbnet *dev = (struct usbnet *)net->priv;
+	struct usbnet *dev = netdev_priv(net);
 	u8 opt;
 
 	if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) {
@@ -654,7 +654,7 @@
 
 static int ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 {
-	struct usbnet *dev = (struct usbnet *)net->priv;
+	struct usbnet *dev = netdev_priv(net);
 	u8 opt = 0;
 	u8 buf[1];
 
@@ -675,7 +675,7 @@
 static int ax8817x_get_eeprom(struct net_device *net,
 			      struct ethtool_eeprom *eeprom, u8 *data)
 {
-	struct usbnet *dev = (struct usbnet *)net->priv;
+	struct usbnet *dev = netdev_priv(net);
 	u16 *ebuf = (u16 *)data;
 	int i;
 
@@ -704,14 +704,14 @@
 
 static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
-	struct usbnet *dev = (struct usbnet *)net->priv;
+	struct usbnet *dev = netdev_priv(net);
 
 	return mii_ethtool_gset(&dev->mii,cmd);
 }
 
 static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
-	struct usbnet *dev = (struct usbnet *)net->priv;
+	struct usbnet *dev = netdev_priv(net);
 
 	return mii_ethtool_sset(&dev->mii,cmd);
 }
@@ -2276,7 +2276,7 @@
 
 static int usbnet_change_mtu (struct net_device *net, int new_mtu)
 {
-	struct usbnet	*dev = (struct usbnet *) net->priv;
+	struct usbnet	*dev = netdev_priv(net);
 
 	if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
 		return -EINVAL;
@@ -2302,7 +2302,8 @@
 
 static struct net_device_stats *usbnet_get_stats (struct net_device *net)
 {
-	return &((struct usbnet *) net->priv)->stats;
+	struct usbnet	*dev = netdev_priv(net);
+	return &dev->stats;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -2569,7 +2570,7 @@
 
 static int usbnet_stop (struct net_device *net)
 {
-	struct usbnet		*dev = (struct usbnet *) net->priv;
+	struct usbnet		*dev = netdev_priv(net);
 	int			temp;
 	DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
 	DECLARE_WAITQUEUE (wait, current);
@@ -2616,7 +2617,7 @@
 
 static int usbnet_open (struct net_device *net)
 {
-	struct usbnet		*dev = (struct usbnet *) net->priv;
+	struct usbnet		*dev = netdev_priv(net);
 	int			retval = 0;
 	struct driver_info	*info = dev->driver_info;
 
@@ -2666,7 +2667,7 @@
 
 static void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
 {
-	struct usbnet *dev = net->priv;
+	struct usbnet *dev = netdev_priv(net);
 
 	strncpy (info->driver, driver_name, sizeof info->driver);
 	strncpy (info->version, DRIVER_VERSION, sizeof info->version);
@@ -2677,7 +2678,7 @@
 
 static u32 usbnet_get_link (struct net_device *net)
 {
-	struct usbnet *dev = net->priv;
+	struct usbnet *dev = netdev_priv(net);
 
 	/* If a check_connect is defined, return it's results */
 	if (dev->driver_info->check_connect)
@@ -2689,14 +2690,14 @@
 
 static u32 usbnet_get_msglevel (struct net_device *net)
 {
-	struct usbnet *dev = net->priv;
+	struct usbnet *dev = netdev_priv(net);
 
 	return dev->msg_level;
 }
 
 static void usbnet_set_msglevel (struct net_device *net, u32 level)
 {
-	struct usbnet *dev = net->priv;
+	struct usbnet *dev = netdev_priv(net);
 
 	dev->msg_level = level;
 }
@@ -2705,7 +2706,7 @@
 {
 #ifdef NEED_MII
 	{
-	struct usbnet *dev = (struct usbnet *)net->priv;
+	struct usbnet *dev = netdev_priv(net);
 
 	if (dev->mii.mdio_read != NULL && dev->mii.mdio_write != NULL)
 		return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
@@ -2817,7 +2818,7 @@
 
 static void usbnet_tx_timeout (struct net_device *net)
 {
-	struct usbnet		*dev = (struct usbnet *) net->priv;
+	struct usbnet		*dev = netdev_priv(net);
 
 	unlink_urbs (dev, &dev->txq);
 	tasklet_schedule (&dev->bh);
@@ -2829,7 +2830,7 @@
 
 static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
 {
-	struct usbnet		*dev = (struct usbnet *) net->priv;
+	struct usbnet		*dev = netdev_priv(net);
 	int			length;
 	int			retval = NET_XMIT_SUCCESS;
 	struct urb		*urb = NULL;
@@ -3014,6 +3015,7 @@
 {
 	struct usbnet		*dev;
 	struct usb_device	*xdev;
+	struct net_device	*net;
 
 	dev = usb_get_intfdata(intf);
 	usb_set_intfdata(intf, NULL);
@@ -3026,7 +3028,8 @@
 		xdev->bus->bus_name, xdev->devpath,
 		dev->driver_info->description);
 	
-	unregister_netdev (dev->net);
+	net = dev->net;
+	unregister_netdev (net);
 
 	/* we don't hold rtnl here ... */
 	flush_scheduled_work ();
@@ -3034,8 +3037,7 @@
 	if (dev->driver_info->unbind)
 		dev->driver_info->unbind (dev, intf);
 
-	free_netdev(dev->net);
-	kfree (dev);
+	free_netdev(net);
 	usb_put_dev (xdev);
 }
 
@@ -3069,12 +3071,13 @@
 	status = -ENOMEM;
 
 	// set up our own records
-	if (!(dev = kmalloc (sizeof *dev, GFP_KERNEL))) {
+	net = alloc_etherdev(sizeof(*dev));
+	if (!net) {
 		dbg ("can't kmalloc dev");
 		goto out;
 	}
-	memset (dev, 0, sizeof *dev);
 
+	dev = netdev_priv(net);
 	dev->udev = xdev;
 	dev->driver_info = info;
 	dev->msg_level = msg_level;
@@ -3088,14 +3091,8 @@
 	dev->delay.data = (unsigned long) dev;
 	init_timer (&dev->delay);
 
-	// set up network interface records
-	net = alloc_etherdev(0);
-	if (!net)
-		goto out1;
-
 	SET_MODULE_OWNER (net);
 	dev->net = net;
-	net->priv = dev;
 	strcpy (net->name, "usb%d");
 	memcpy (net->dev_addr, node_id, sizeof node_id);
 
@@ -3144,8 +3141,8 @@
 
 	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
 	
-	SET_NETDEV_DEV(dev->net, &udev->dev);
-	status = register_netdev (dev->net);
+	SET_NETDEV_DEV(net, &udev->dev);
+	status = register_netdev (net);
 	if (status)
 		goto out3;
 	devinfo (dev, "register usbnet at usb-%s-%s, %s",
@@ -3156,16 +3153,15 @@
 	usb_set_intfdata (udev, dev);
 
 	// start as if the link is up
-	netif_device_attach (dev->net);
+	netif_device_attach (net);
 
 	return 0;
 
 out3:
 	if (info->unbind)
 		info->unbind (dev, udev);
-	free_netdev(net);
 out1:
-	kfree(dev);
+	free_netdev(net);
 out:
 	usb_put_dev(xdev);
 	return status;
@@ -3251,6 +3247,10 @@
 }, {
 	// Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter"
 	USB_DEVICE (0x6189, 0x182d),
+	.driver_info =  (unsigned long) &ax8817x_info,
+}, {
+	// corega FEther USB2-TX
+	USB_DEVICE (0x07aa, 0x0017),
 	.driver_info =  (unsigned long) &ax8817x_info,
 }, {
 	// Surecom EP-1427X-2
diff -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/serial/belkin_sa.c	2004-10-28 22:25:58 -07:00
@@ -607,6 +607,7 @@
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_VERSION( DRIVER_VERSION );
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/serial/cyberjack.c	2004-10-28 22:25:59 -07:00
@@ -502,6 +502,7 @@
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_VERSION( DRIVER_VERSION );
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/serial/pl2303.c	2004-10-28 22:25:58 -07:00
@@ -90,6 +90,7 @@
 	{ USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
 	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
+       { USB_DEVICE(PHAROS_VENDOR_ID, PHAROS_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
@@ -1188,6 +1189,7 @@
 module_exit(pl2303_exit);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff -Nru a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
--- a/drivers/usb/serial/pl2303.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/serial/pl2303.h	2004-10-28 22:25:58 -07:00
@@ -50,3 +50,6 @@
 #define SAMSUNG_VENDOR_ID       0x04e8
 #define SAMSUNG_PRODUCT_ID      0x8001
 
+/* Pharos / Microsoft GPS puck */
+#define PHAROS_VENDOR_ID       0x067b
+#define PHAROS_PRODUCT_ID      0xaaa0
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/usb/serial/usb-serial.c	2004-10-28 22:25:59 -07:00
@@ -452,18 +452,12 @@
 			port = serial->port[i];
 			if (!port)
 				continue;
-			if (port->read_urb) {
-				usb_kill_urb(port->read_urb);
-				usb_free_urb(port->read_urb);
-			}
-			if (port->write_urb) {
-				usb_kill_urb(port->write_urb);
-				usb_free_urb(port->write_urb);
-			}
-			if (port->interrupt_in_urb) {
-				usb_kill_urb(port->interrupt_in_urb);
-				usb_free_urb(port->interrupt_in_urb);
-			}
+			usb_kill_urb(port->read_urb);
+			usb_free_urb(port->read_urb);
+			usb_kill_urb(port->write_urb);
+			usb_free_urb(port->write_urb);
+			usb_kill_urb(port->interrupt_in_urb);
+			usb_free_urb(port->interrupt_in_urb);
 			kfree(port->bulk_in_buffer);
 			kfree(port->bulk_out_buffer);
 			kfree(port->interrupt_in_buffer);
@@ -799,18 +793,12 @@
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 
 	dbg ("%s - %s", __FUNCTION__, dev->bus_id);
-	if (port->read_urb) {
-		usb_kill_urb(port->read_urb);
-		usb_free_urb(port->read_urb);
-	}
-	if (port->write_urb) {
-		usb_kill_urb(port->write_urb);
-		usb_free_urb(port->write_urb);
-	}
-	if (port->interrupt_in_urb) {
-		usb_kill_urb(port->interrupt_in_urb);
-		usb_free_urb(port->interrupt_in_urb);
-	}
+	usb_kill_urb(port->read_urb);
+	usb_free_urb(port->read_urb);
+	usb_kill_urb(port->write_urb);
+	usb_free_urb(port->write_urb);
+	usb_kill_urb(port->interrupt_in_urb);
+	usb_free_urb(port->interrupt_in_urb);
 	kfree(port->bulk_in_buffer);
 	kfree(port->bulk_out_buffer);
 	kfree(port->interrupt_in_buffer);
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/usb/serial/visor.c	2004-10-28 22:25:57 -07:00
@@ -381,10 +381,17 @@
 	.read_bulk_callback =	visor_read_bulk_callback,
 };
 
+struct visor_private {
+	spinlock_t lock;
+	int bytes_in;
+	int bytes_out;
+	int outstanding_urbs;
+};
 
-static int bytes_in;
-static int bytes_out;
+/* number of outstanding urbs to prevent userspace DoS from happening */
+#define URB_UPPER_LIMIT	42
 
+static int stats;
 
 /******************************************************************************
  * Handspring Visor specific driver functions
@@ -392,6 +399,8 @@
 static int visor_open (struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial *serial = port->serial;
+	struct visor_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 	int result = 0;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -402,8 +411,11 @@
 		return -ENODEV;
 	}
 
-	bytes_in = 0;
-	bytes_out = 0;
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->bytes_in = 0;
+	priv->bytes_out = 0;
+	priv->outstanding_urbs = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/*
 	 * Force low_latency on so that our tty_push actually forces the data
@@ -441,6 +453,7 @@
 
 static void visor_close (struct usb_serial_port *port, struct file * filp)
 {
+	struct visor_private *priv = usb_get_serial_port_data(port);
 	unsigned char *transfer_buffer;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -461,20 +474,32 @@
 		kfree (transfer_buffer);
 	}
 
-	/* Uncomment the following line if you want to see some statistics in your syslog */
-	/* dev_info (&port->dev, "Bytes In = %d  Bytes Out = %d\n", bytes_in, bytes_out); */
+	if (stats)
+		dev_info(&port->dev, "Bytes In = %d  Bytes Out = %d\n",
+			 priv->bytes_in, priv->bytes_out);
 }
 
 
 static int visor_write (struct usb_serial_port *port, const unsigned char *buf, int count)
 {
+	struct visor_private *priv = usb_get_serial_port_data(port);
 	struct usb_serial *serial = port->serial;
 	struct urb *urb;
 	unsigned char *buffer;
+	unsigned long flags;
 	int status;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	spin_lock_irqsave(&priv->lock, flags);
+	if (priv->outstanding_urbs > URB_UPPER_LIMIT) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		dev_dbg(&port->dev, "write limit hit\n");
+		return 0;
+	}
+	++priv->outstanding_urbs;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	buffer = kmalloc (count, GFP_ATOMIC);
 	if (!buffer) {
 		dev_err(&port->dev, "out of memory\n");
@@ -506,7 +531,10 @@
 		count = status;
 		kfree (buffer);
 	} else {
-		bytes_out += count;
+		spin_lock_irqsave(&priv->lock, flags);
+		++priv->outstanding_urbs;
+		priv->bytes_out += count;
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
 	/* we are done with this urb, so let the host driver
@@ -547,6 +575,8 @@
 static void visor_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct visor_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree (urb->transfer_buffer);
@@ -557,6 +587,10 @@
 		dbg("%s - nonzero write bulk status received: %d",
 		    __FUNCTION__, urb->status);
 
+	spin_lock_irqsave(&priv->lock, flags);
+	--priv->outstanding_urbs;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	schedule_work(&port->work);
 }
 
@@ -564,8 +598,10 @@
 static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-	struct tty_struct *tty;
+	struct visor_private *priv = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
+	struct tty_struct *tty;
+	unsigned long flags;
 	int i;
 	int result;
 
@@ -590,7 +626,9 @@
 		}
 		tty_flip_buffer_push(tty);
 	}
-	bytes_in += urb->actual_length;
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->bytes_in += urb->actual_length;
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* Continue trying to always read  */
 	usb_fill_bulk_urb (port->read_urb, port->serial->dev,
@@ -825,6 +863,22 @@
 	return num_ports;
 }
 
+static int generic_startup(struct usb_serial *serial)
+{
+	struct visor_private *priv;
+	int i;
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		priv = kmalloc (sizeof(*priv), GFP_KERNEL);
+		if (!priv)
+			return -ENOMEM;
+		memset (priv, 0x00, sizeof(*priv));
+		spin_lock_init(&priv->lock);
+		usb_set_serial_port_data(serial->port[i], priv);
+	}
+	return 0;
+}
+
 static int clie_3_5_startup (struct usb_serial *serial)
 {
 	struct device *dev = &serial->dev->dev;
@@ -864,7 +918,7 @@
 		return -EIO;
 	}
 
-	return 0;
+	return generic_startup(serial);
 }
  
 static int treo_attach (struct usb_serial *serial)
@@ -903,7 +957,7 @@
 	COPY_PORT(serial->port[1], swap_port);
 	kfree(swap_port);
 
-	return 0;
+	return generic_startup(serial);
 }
 
 static int clie_5_attach (struct usb_serial *serial)
@@ -924,7 +978,7 @@
 	/* port 0 now uses the modified endpoint Address */
 	serial->port[0]->bulk_out_endpointAddress = serial->port[1]->bulk_out_endpointAddress;
 
-	return 0;
+	return generic_startup(serial);
 }
 
 static void visor_shutdown (struct usb_serial *serial)
@@ -1080,8 +1134,11 @@
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
+module_param(stats, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(stats, "Enables statistics or not");
 
 module_param(vendor, ushort, 0);
 MODULE_PARM_DESC(vendor, "User specified vendor ID");
 module_param(product, ushort, 0);
 MODULE_PARM_DESC(product, "User specified product ID");
+
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/usb/storage/scsiglue.c	2004-10-28 22:25:58 -07:00
@@ -175,7 +175,7 @@
 	US_DEBUGP("%s called\n", __FUNCTION__);
 	srb->host_scribble = (unsigned char *)us;
 
-	/* enqueue the command */
+	/* check for state-transition errors */
 	if (us->sm_state != US_STATE_IDLE || us->srb != NULL) {
 		printk(KERN_ERR USB_STORAGE "Error in %s: " 
 			"state = %d, us->srb = %p\n",
@@ -183,10 +183,17 @@
 		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
+	/* fail the command if we are disconnecting */
+	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+		US_DEBUGP("Fail command during disconnect\n");
+		srb->result = DID_NO_CONNECT << 16;
+		done(srb);
+		return 0;
+	}
+
+	/* enqueue the command and wake up the control thread */
 	srb->scsi_done = done;
 	us->srb = srb;
-
-	/* wake up the process task */
 	up(&(us->sema));
 
 	return 0;
diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig
--- a/drivers/video/Kconfig	2004-10-28 22:25:56 -07:00
+++ b/drivers/video/Kconfig	2004-10-28 22:25:56 -07:00
@@ -41,7 +41,7 @@
 config FB_MODE_HELPERS
         bool "Enable Video Mode Handling Helpers"
         depends on FB
-	default y
+	default n
 	---help---
 	  This enables functions for handling video modes using the
 	  Generalized Timing Formula and the EDID parser. A few drivers rely
@@ -61,10 +61,10 @@
 	 parameters in terms of number of tiles instead of number of pixels.
 	 For example, to draw a single character, instead of using bitmaps,
 	 an index to an array of bitmaps will be used.  To clear or move a
-	 rectangular section of a screen, the rectangle willbe described in
+	 rectangular section of a screen, the rectangle will be described in
 	 terms of number of tiles in the x- and y-axis.
 
-	 This is particularly important to one driver, the matroxfb.  If
+	 This is particularly important to one driver, matroxfb.  If
 	 unsure, say N.
 
 config FB_CIRRUS
@@ -517,6 +517,27 @@
   
           If unsure, say N.
 
+config FB_INTEL
+	tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
+	depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
+	select AGP
+	select AGP_INTEL
+	help
+	  This driver supports the on-board graphics built in to the Intel
+          830M/845G/852GM/855GM/865G chipsets.
+          Say Y if you have and plan to use such a board.
+
+          To compile this driver as a module, choose M here: the
+	  module will be called intelfb.
+
+config FB_INTEL_DEBUG
+        bool "Intel driver Debug Messages"
+	depends on FB_INTEL
+	---help---
+	  Say Y here if you want the Intel driver to output all sorts
+	  of debugging informations to provide to the maintainer when
+	  something goes wrong.
+
 config FB_MATROX
 	tristate "Matrox acceleration"
 	depends on FB && PCI
@@ -750,6 +771,19 @@
 	  framebuffer device.  The ATI product support page for these boards
 	  is at <http://support.ati.com/products/pc/mach64/>.
 
+config FB_ATY_GENERIC_LCD
+	bool "Mach64 generic LCD support (EXPERIMENTAL)"
+	depends on FB_ATY_CT
+	help
+	  Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
+	  Rage XC, or Rage XL chipset.
+
+config FB_ATY_XL_INIT
+	bool "Rage XL No-BIOS Init support"
+	depends on FB_ATY_CT
+	help
+	  Say Y here to support booting a Rage XL without BIOS support.
+
 config FB_ATY_GX
 	bool "Mach64 GX support" if PCI
 	depends on FB_ATY
@@ -761,11 +795,41 @@
 	  is at
 	  <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
 
-config FB_ATY_XL_INIT
-	bool "  Rage XL No-BIOS Init support" if FB_ATY_CT
-	depends on FB_ATY
+config FB_SAVAGE
+	tristate "S3 Savage support"
+	depends on FB && PCI && EXPERIMENTAL
+	select I2C_ALGOBIT if FB_SAVAGE_I2C
+	select I2C if FB_SAVAGE_I2C
+	select FB_MODE_HELPERS
 	help
-	  Say Y here to support booting a Rage XL without BIOS support.
+	  This driver supports notebooks and computers with S3 Savage PCI/AGP
+	  chips.
+
+	  Say Y if you have such a graphics card.
+
+	  To compile this driver as a module, choose M here; the module
+	  will be called savagefb.
+
+config FB_SAVAGE_I2C
+       tristate "Enable DDC2 Support"
+       depends on FB_SAVAGE
+       help
+	  This enables I2C support for S3 Savage Chipsets.  This is used
+	  only for getting EDID information from the attached display
+	  allowing for robust video mode handling and switching.
+
+	  Because fbdev-2.6 requires that drivers must be able to
+	  independently validate video mode parameters, you should say Y
+	  here.
+
+config FB_SAVAGE_ACCEL
+       tristate "Enable Console Acceleration"
+       depends on FB_SAVAGE
+       default n
+       help
+          This option will compile in console acceleration support. If
+          the resulting framebuffer console has bothersome glitches, then
+          choose N here.
 
 config FB_SIS
 	tristate "SiS acceleration"
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	2004-10-28 22:25:57 -07:00
+++ b/drivers/video/Makefile	2004-10-28 22:25:57 -07:00
@@ -23,15 +23,20 @@
 obj-$(CONFIG_FB_PM3)		  += pm3fb.o
 
 obj-$(CONFIG_FB_MATROX)		  += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_RIVA)		  += riva/ cfbimgblt.o vgastate.o
+obj-$(CONFIG_FB_RIVA)		  += riva/ cfbimgblt.o cfbfillrect.o \
+				     cfbcopyarea.o vgastate.o
 obj-$(CONFIG_FB_ATY)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
 obj-$(CONFIG_FB_ATY128)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
 obj-$(CONFIG_FB_RADEON)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
 obj-$(CONFIG_FB_SIS)		  += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
 obj-$(CONFIG_FB_KYRO)             += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-
+obj-$(CONFIG_FB_SAVAGE)		  += savage/ cfbfillrect.o cfbcopyarea.o \
+				     cfbimgblt.o
 obj-$(CONFIG_FB_I810)             += cfbcopyarea.o cfbfillrect.o cfbimgblt.o \
 				     vgastate.o
+obj-$(CONFIG_FB_INTEL)            += cfbfillrect.o cfbcopyarea.o \
+	                             cfbimgblt.o
+
 obj-$(CONFIG_FB_RADEON_OLD)	  += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
 obj-$(CONFIG_FB_VIRGE)            += virgefb.o
diff -Nru a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h
--- a/drivers/video/aty/ati_ids.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/video/aty/ati_ids.h	2004-10-28 22:25:57 -07:00
@@ -64,6 +64,7 @@
 #define PCI_CHIP_MACH64LQ		0x4C51
 #define PCI_CHIP_MACH64LR		0x4C52
 #define PCI_CHIP_MACH64LS		0x4C53
+#define PCI_CHIP_MACH64LT		0x4C54
 #define PCI_CHIP_RADEON_LW		0x4C57
 #define PCI_CHIP_RADEON_LX		0x4C58
 #define PCI_CHIP_RADEON_LY		0x4C59
diff -Nru a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
--- a/drivers/video/aty/atyfb.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/video/aty/atyfb.h	2004-10-28 22:25:58 -07:00
@@ -3,6 +3,8 @@
  */
 
 #include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
     /*
      *  Elements of the hardware specific atyfb_par structure
      */
@@ -10,16 +12,60 @@
 struct crtc {
 	u32 vxres;
 	u32 vyres;
+	u32 xoffset;
+	u32 yoffset;
+	u32 bpp;
 	u32 h_tot_disp;
 	u32 h_sync_strt_wid;
 	u32 v_tot_disp;
 	u32 v_sync_strt_wid;
+	u32 vline_crnt_vline;
 	u32 off_pitch;
 	u32 gen_cntl;
 	u32 dp_pix_width;	/* acceleration */
 	u32 dp_chain_mask;	/* acceleration */
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	u32 horz_stretching;
+	u32 vert_stretching;
+	u32 ext_vert_stretch;
+	u32 shadow_h_tot_disp;
+	u32 shadow_h_sync_strt_wid;
+	u32 shadow_v_tot_disp;
+	u32 shadow_v_sync_strt_wid;
+	u32 lcd_gen_cntl;
+	u32 lcd_config_panel;
+	u32 lcd_index;
+#endif
+};
+
+struct aty_interrupt {
+	wait_queue_head_t wait;
+	unsigned int count;
+	int pan_display;
+};
+
+struct pll_info {
+	int pll_max;
+	int pll_min;
+	int sclk, mclk, mclk_pm, xclk;
+	int ref_div;
+	int ref_clk;
 };
 
+typedef struct {
+	u16 unknown1;
+	u16 PCLK_min_freq;
+	u16 PCLK_max_freq;
+	u16 unknown2;
+	u16 ref_freq;
+	u16 ref_divider;
+	u16 unknown3;
+	u16 MCLK_pwd;
+	u16 MCLK_max_freq;
+	u16 XCLK_max_freq;
+	u16 SCLK_freq;
+} __attribute__ ((packed)) PLL_BLOCK_MACH64;
+
 struct pll_514 {
 	u8 m;
 	u8 n;
@@ -36,16 +82,39 @@
 	u8 pll_ref_div;
 	u8 pll_gen_cntl;
 	u8 mclk_fb_div;
+	u8 mclk_fb_mult; /* 2 ro 4 */
+/*	u8 sclk_fb_div;*/
 	u8 pll_vclk_cntl;
 	u8 vclk_post_div;
 	u8 vclk_fb_div;
 	u8 pll_ext_cntl;
-	u32 dsp_config;		/* Mach64 GTB DSP */
-	u32 dsp_on_off;		/* Mach64 GTB DSP */
+/*	u8 ext_vpll_cntl;
+	u8 spll_cntl2;*/
+	u32 dsp_config; /* Mach64 GTB DSP */
+	u32 dsp_on_off; /* Mach64 GTB DSP */
+	u32 dsp_loop_latency;
+	u32 fifo_size;
+	u32 xclkpagefaultdelay;
+	u32 xclkmaxrasdelay;
+	u8 xclk_ref_div;
+	u8 xclk_post_div;
 	u8 mclk_post_div_real;
+	u8 xclk_post_div_real;
 	u8 vclk_post_div_real;
+	u8 features;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	u32 xres; /* use for LCD stretching/scaling */
+#endif
 };
 
+/*
+	for pll_ct.features
+*/
+#define DONT_USE_SPLL 0x1
+#define DONT_USE_XDLL 0x2
+#define USE_CPUCLK    0x4
+#define POWERDOWN_PLL 0x8
+
 union aty_pll {
 	struct pll_ct ct;
 	struct pll_514 ibm514;
@@ -56,42 +125,68 @@
      *  The hardware parameters for each card
      */
 
-struct aty_cursor {
-	u8 bits[8][64];
-	u8 mask[8][64];
-	u8 __iomem *ram;
-};
-
 struct atyfb_par {
 	struct aty_cmap_regs __iomem *aty_cmap_regs;
+	struct { u8 red, green, blue; } palette[256];
 	const struct aty_dac_ops *dac_ops;
 	const struct aty_pll_ops *pll_ops;
-	struct aty_cursor *cursor;
 	void __iomem *ati_regbase;
-	unsigned long clk_wr_offset;
+	unsigned long clk_wr_offset; /* meaning overloaded, clock id by CT */
 	struct crtc crtc;
 	union aty_pll pll;
+	struct pll_info pll_limits;
 	u32 features;
 	u32 ref_clk_per;
 	u32 pll_per;
 	u32 mclk_per;
+	u32 xclk_per;
 	u8 bus_type;
 	u8 ram_type;
 	u8 mem_refresh_rate;
-	u8 blitter_may_be_busy;
+	u16 pci_id;
 	u32 accel_flags;
+	int blitter_may_be_busy;
+	int asleep;
+	int lock_blank;
+	unsigned long res_start;
+	unsigned long res_size;
 #ifdef __sparc__
 	struct pci_mmap_map *mmap_map;
 	u8 mmaped;
+#endif
 	int open;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	unsigned long bios_base_phys;
+	unsigned long bios_base;
+	unsigned long lcd_table;
+	u16 lcd_width;
+	u16 lcd_height;
+	u32 lcd_pixclock;
+	u16 lcd_refreshrate;
+	u16 lcd_htotal;
+	u16 lcd_hdisp;
+	u16 lcd_hsync_dly;
+	u16 lcd_hsync_len;
+	u16 lcd_vtotal;
+	u16 lcd_vdisp;
+	u16 lcd_vsync_len;
+	u16 lcd_right_margin;
+	u16 lcd_lower_margin;
+	u16 lcd_hblank_len;
+	u16 lcd_vblank_len;
 #endif
-#ifdef CONFIG_PMAC_PBOOK
-	struct fb_info *next;
-	unsigned char *save_framebuffer;
-	unsigned long save_pll[64];
+	unsigned long aux_start; /* auxiliary aperture */
+	unsigned long aux_size;
+	struct aty_interrupt vblank;
+	unsigned long irq_flags;
+	unsigned int irq;
+	spinlock_t int_lock;
+#ifdef CONFIG_MTRR
+	int mtrr_aper;
+	int mtrr_reg;
 #endif
 };
-    
+
     /*
      *  ATI Mach64 features
      */
@@ -101,7 +196,7 @@
 #define M64F_RESET_3D		0x00000001
 #define M64F_MAGIC_FIFO		0x00000002
 #define M64F_GTB_DSP		0x00000004
-#define M64F_FIFO_24		0x00000008
+#define M64F_FIFO_32		0x00000008
 #define M64F_SDRAM_MAGIC_PLL	0x00000010
 #define M64F_MAGIC_POSTDIV	0x00000020
 #define M64F_INTEGRATED		0x00000040
@@ -116,9 +211,10 @@
 #define M64F_G3_PB_1_1		0x00008000
 #define M64F_G3_PB_1024x768	0x00010000
 #define M64F_EXTRA_BRIGHT	0x00020000
-#define M64F_LT_SLEEP		0x00040000
+#define M64F_LT_LCD_REGS	0x00040000
 #define M64F_XL_DLL		0x00080000
-
+#define M64F_MFB_FORCE_4	0x00100000
+#define M64F_HW_TRIPLE		0x00200000
 
     /*
      *  Register access
@@ -137,8 +233,7 @@
 #endif
 }
 
-static inline void aty_st_le32(int regindex, u32 val,
-			       const struct atyfb_par *par)
+static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *par)
 {
 	/* Hack for bloc 1, should be cleanly optimized by compiler */
 	if (regindex >= 0x400)
@@ -163,8 +258,7 @@
 #endif
 }
 
-static inline void aty_st_8(int regindex, u8 val,
-			    const struct atyfb_par *par)
+static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par)
 {
 	/* Hack for bloc 1, should be cleanly optimized by compiler */
 	if (regindex >= 0x400)
@@ -177,17 +271,10 @@
 #endif
 }
 
-static inline u8 aty_ld_pll(int offset, const struct atyfb_par *par)
-{
-	u8 res;
-
-	/* write addr byte */
-	aty_st_8(CLOCK_CNTL + 1, (offset << 2), par);
-	/* read the register value */
-	res = aty_ld_8(CLOCK_CNTL + 2, par);
-	return res;
-}
-
+#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
+extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par);
+extern u32 aty_ld_lcd(int index, const struct atyfb_par *par);
+#endif
 
     /*
      *  DAC operations
@@ -195,14 +282,14 @@
 
 struct aty_dac_ops {
 	int (*set_dac) (const struct fb_info * info,
-			const union aty_pll * pll, u32 bpp, u32 accel);
+		const union aty_pll * pll, u32 bpp, u32 accel);
 };
 
-extern const struct aty_dac_ops aty_dac_ibm514;	/* IBM RGB514 */
-extern const struct aty_dac_ops aty_dac_ati68860b;	/* ATI 68860-B */
-extern const struct aty_dac_ops aty_dac_att21c498;	/* AT&T 21C498 */
-extern const struct aty_dac_ops aty_dac_unsupported;	/* unsupported */
-extern const struct aty_dac_ops aty_dac_ct;	/* Integrated */
+extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */
+extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */
+extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */
+extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */
+extern const struct aty_dac_ops aty_dac_ct; /* Integrated */
 
 
     /*
@@ -210,37 +297,32 @@
      */
 
 struct aty_pll_ops {
-	int (*var_to_pll) (const struct fb_info * info, u32 vclk_per,
-			   u8 bpp, union aty_pll * pll);
-	 u32(*pll_to_var) (const struct fb_info * info,
-			   const union aty_pll * pll);
-	void (*set_pll) (const struct fb_info * info,
-			 const union aty_pll * pll);
+	int (*var_to_pll) (const struct fb_info * info, u32 vclk_per, u32 bpp, union aty_pll * pll);
+	u32 (*pll_to_var) (const struct fb_info * info, const union aty_pll * pll);
+	void (*set_pll)   (const struct fb_info * info, const union aty_pll * pll);
+	void (*get_pll)   (const struct fb_info *info, union aty_pll * pll);
+	int (*init_pll)   (const struct fb_info * info, union aty_pll * pll);
 };
 
-extern const struct aty_pll_ops aty_pll_ati18818_1;	/* ATI 18818 */
-extern const struct aty_pll_ops aty_pll_stg1703;	/* STG 1703 */
-extern const struct aty_pll_ops aty_pll_ch8398;	/* Chrontel 8398 */
-extern const struct aty_pll_ops aty_pll_att20c408;	/* AT&T 20C408 */
-extern const struct aty_pll_ops aty_pll_ibm514;	/* IBM RGB514 */
-extern const struct aty_pll_ops aty_pll_unsupported;	/* unsupported */
-extern const struct aty_pll_ops aty_pll_ct;	/* Integrated */
+extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */
+extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */
+extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */
+extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */
+extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */
+extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */
+extern const struct aty_pll_ops aty_pll_ct; /* Integrated */
 
 
-extern void aty_set_pll_ct(const struct fb_info *info,
-			   const union aty_pll *pll);
-extern void aty_calc_pll_ct(const struct fb_info *info,
-			    struct pll_ct *pll);
+extern void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll);
+extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
 
 
     /*
      *  Hardware cursor support
      */
 
-extern struct aty_cursor *aty_init_cursor(struct fb_info *info);
+extern int aty_init_cursor(struct fb_info *info);
 extern int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-extern void aty_set_cursor_color(struct fb_info *info);
-extern void aty_set_cursor_shape(struct fb_info *info);
 
     /*
      *  Hardware acceleration
@@ -260,6 +342,5 @@
 }
 
 extern void aty_reset_engine(const struct atyfb_par *par);
-extern void aty_init_engine(struct atyfb_par *par,
-			    struct fb_info *info);
+extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
 
diff -Nru a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
--- a/drivers/video/aty/atyfb_base.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/video/aty/atyfb_base.c	2004-10-28 22:25:58 -07:00
@@ -1,6 +1,7 @@
 /*
  *  ATI Frame Buffer Device Driver Core
  *
+ *	Copyright (C) 2004  Alex Kern <alex.kern@gmx.de>
  *	Copyright (C) 1997-2001  Geert Uytterhoeven
  *	Copyright (C) 1998  Bernd Harries
  *	Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -24,10 +25,13 @@
  *			   Harry AC Eaton
  *			   Anthony Tong <atong@uiuc.edu>
  *
+ *  Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern
+ *  Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug.
+ *
  *  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.
- *  
+ *
  *  Many thanks to Nitya from ATI devrel for support and patience !
  */
 
@@ -38,15 +42,16 @@
     - cursor support on all cards and all ramdacs.
     - cursor parameters controlable via ioctl()s.
     - guess PLL and MCLK based on the original PLL register values initialized
-      by the BIOS or Open Firmware (if they are initialized).
+      by Open Firmware (if they are initialized). BIOS is done
 
-						(Anyone to help with this?)
+    (Anyone with Mac to help with this?)
 
 ******************************************************************************/
 
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -54,19 +59,20 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
-#include <linux/selection.h>
 #include <linux/console.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/vt_kern.h>
-#include <linux/kd.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
 #include <video/mach64.h>
 #include "atyfb.h"
+#include "ati_ids.h"
 
 #ifdef __powerpc__
 #include <asm/prom.h>
@@ -87,23 +93,102 @@
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
-
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
 
 /*
  * Debug flags.
  */
-#undef DEBUG
+/*#undef DEBUG*/
+#define DEBUG
 
 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
 /*  - must be large enough to catch all GUI-Regs   */
 /*  - must be aligned to a PAGE boundary           */
 #define GUI_RESERVE	(1 * PAGE_SIZE)
 
-
 /* FIXME: remove the FAIL definition */
-#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
+#define FAIL(msg) do { printk(KERN_CRIT "atyfb: " msg "\n"); return -EINVAL; } while (0)
+#define FAIL_MAX(msg, x, _max_) do { if(x > _max_) { printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); return -EINVAL; } } while (0)
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...)	printk(KERN_DEBUG "atyfb: " fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define PRINTKI(fmt, args...)	printk(KERN_INFO "atyfb: " fmt, ## args)
+#define PRINTKE(fmt, args...)	 printk(KERN_ERR "atyfb: " fmt, ## args)
+
+#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
+static const u32 lt_lcd_regs[] = {
+	CONFIG_PANEL_LG,
+	LCD_GEN_CNTL_LG,
+	DSTN_CONTROL_LG,
+	HFB_PITCH_ADDR_LG,
+	HORZ_STRETCHING_LG,
+	VERT_STRETCHING_LG,
+	0, /* EXT_VERT_STRETCH */
+	LT_GIO_LG,
+	POWER_MANAGEMENT_LG
+};
+
+void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
+{
+	if (M64_HAS(LT_LCD_REGS)) {
+		aty_st_le32(lt_lcd_regs[index], val, par);
+	} else {
+		unsigned long temp;
+
+		/* write addr byte */
+		temp = aty_ld_le32(LCD_INDEX, par);
+		aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
+		/* write the register value */
+		aty_st_le32(LCD_DATA, val, par);
+	}
+}
+
+u32 aty_ld_lcd(int index, const struct atyfb_par *par)
+{
+	if (M64_HAS(LT_LCD_REGS)) {
+		return aty_ld_le32(lt_lcd_regs[index], par);
+	} else {
+		unsigned long temp;
+
+		/* write addr byte */
+		temp = aty_ld_le32(LCD_INDEX, par);
+		aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
+		/* read the register value */
+		return aty_ld_le32(LCD_DATA, par);
+	}
+}
+#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+/*
+ * ATIReduceRatio --
+ *
+ * Reduce a fraction by factoring out the largest common divider of the
+ * fraction's numerator and denominator.
+ */
+static void ATIReduceRatio(int *Numerator, int *Denominator)
+{
+    int Multiplier, Divider, Remainder;
 
+    Multiplier = *Numerator;
+    Divider = *Denominator;
 
+    while ((Remainder = Multiplier % Divider))
+    {
+        Multiplier = Divider;
+        Divider = Remainder;
+    }
+
+    *Numerator /= Divider;
+    *Denominator /= Divider;
+}
+#endif
     /*
      *  The Hardware parameters for each card
      */
@@ -138,22 +223,19 @@
 
 static int atyfb_open(struct fb_info *info, int user);
 static int atyfb_release(struct fb_info *info, int user);
-static int atyfb_check_var(struct fb_var_screeninfo *var,
-			   struct fb_info *info);
-static int atyfb_set_par(struct fb_info *info); 
+static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+static int atyfb_set_par(struct fb_info *info);
 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info);
-static int atyfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info);
+	u_int transp, struct fb_info *info);
+static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
 static int atyfb_blank(int blank, struct fb_info *info);
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, struct fb_info *info);
+	u_long arg, struct fb_info *info);
 extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
 extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
 extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
 #ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma);
+static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
 #endif
 static int atyfb_sync(struct fb_info *info);
 
@@ -166,15 +248,14 @@
 static int store_video_par(char *videopar, unsigned char m64_num);
 #endif
 
-static void aty_set_crtc(const struct atyfb_par *par,
-			 const struct crtc *crtc);
-static int aty_var_to_crtc(const struct fb_info *info,
-			   const struct fb_var_screeninfo *var,
-			   struct crtc *crtc);
-static int aty_crtc_to_var(const struct crtc *crtc,
-			   struct fb_var_screeninfo *var);
-static void set_off_pitch(struct atyfb_par *par,
-			  const struct fb_info *info);
+static struct crtc saved_crtc;
+static union aty_pll saved_pll;
+static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
+
+static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
+static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc);
+static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var);
+static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
 #ifdef CONFIG_PPC
 static int read_aty_sense(const struct atyfb_par *par);
 #endif
@@ -184,10 +265,19 @@
      *  Interface used by the world
      */
 
-int atyfb_init(void);
-#ifndef MODULE
-int atyfb_setup(char *);
-#endif
+struct fb_var_screeninfo default_var = {
+	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+	640, 480, 640, 480, 0, 0, 8, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+};
+
+static struct fb_videomode defmode = {
+	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
+	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+};
 
 static struct fb_ops atyfb_ops = {
 	.owner		= THIS_MODULE,
@@ -202,26 +292,31 @@
 	.fb_fillrect	= atyfb_fillrect,
 	.fb_copyarea	= atyfb_copyarea,
 	.fb_imageblit	= atyfb_imageblit,
-	.fb_cursor	= soft_cursor,
+	.fb_cursor	= atyfb_cursor,
 #ifdef __sparc__
 	.fb_mmap	= atyfb_mmap,
 #endif
 	.fb_sync	= atyfb_sync,
 };
 
-static char curblink __initdata = 1;
-static char noaccel __initdata = 0;
-static u32 default_vram __initdata = 0;
-static int default_pll __initdata = 0;
-static int default_mclk __initdata = 0;
-
-#ifndef MODULE
-static char *mode_option __initdata = NULL;
-#endif
+static int noaccel;
+#ifdef CONFIG_MTRR
+static int nomtrr;
+#endif
+static int vram;
+static int pll;
+static int mclk;
+static int xclk;
+static char *mode;
 
 #ifdef CONFIG_PPC
 static int default_vmode __initdata = VMODE_CHOOSE;
 static int default_cmode __initdata = CMODE_CHOOSE;
+
+module_param_named(vmode, default_vmode, int, 0);
+MODULE_PARM_DESC(vmode, "int: video mode for mac");
+module_param_named(cmode, default_cmode, int, 0);
+MODULE_PARM_DESC(cmode, "int: color mode for mac");
 #endif
 
 #ifdef CONFIG_ATARI
@@ -231,177 +326,185 @@
 static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
 #endif
 
-#ifdef CONFIG_FB_ATY_GX
-static char m64n_gx[] __initdata = "mach64GX (ATI888GX00)";
-static char m64n_cx[] __initdata = "mach64CX (ATI888CX00)";
-#endif /* CONFIG_FB_ATY_GX */
-#ifdef CONFIG_FB_ATY_CT
-static char m64n_ct[] __initdata = "mach64CT (ATI264CT)";
-static char m64n_et[] __initdata = "mach64ET (ATI264ET)";
-static char m64n_vta3[] __initdata = "mach64VTA3 (ATI264VT)";
-static char m64n_vta4[] __initdata = "mach64VTA4 (ATI264VT)";
-static char m64n_vtb[] __initdata = "mach64VTB (ATI264VTB)";
-static char m64n_vt4[] __initdata = "mach64VT4 (ATI264VT4)";
-static char m64n_gt[] __initdata = "3D RAGE (GT)";
-static char m64n_gtb[] __initdata = "3D RAGE II+ (GTB)";
-static char m64n_iic_p[] __initdata = "3D RAGE IIC (PCI)";
-static char m64n_iic_a[] __initdata = "3D RAGE IIC (AGP)";
-static char m64n_lt[] __initdata = "3D RAGE LT";
-static char m64n_ltg[] __initdata = "3D RAGE LT-G";
-static char m64n_gtc_ba[] __initdata = "3D RAGE PRO (BGA, AGP)";
-static char m64n_gtc_ba1[] __initdata = "3D RAGE PRO (BGA, AGP, 1x only)";
-static char m64n_gtc_bp[] __initdata = "3D RAGE PRO (BGA, PCI)";
-static char m64n_gtc_pp[] __initdata = "3D RAGE PRO (PQFP, PCI)";
-static char m64n_gtc_ppl[] __initdata =
-    "3D RAGE PRO (PQFP, PCI, limited 3D)";
-static char m64n_xl[] __initdata = "3D RAGE (XL)";
-static char m64n_ltp_a[] __initdata = "3D RAGE LT PRO (AGP)";
-static char m64n_ltp_p[] __initdata = "3D RAGE LT PRO (PCI)";
-static char m64n_mob_p[] __initdata = "3D RAGE Mobility (PCI)";
-static char m64n_mob_a[] __initdata = "3D RAGE Mobility (AGP)";
-#endif /* CONFIG_FB_ATY_CT */
+/* top -> down is an evolution of mach64 chipset, any corrections? */
+#define ATI_CHIP_88800GX   (M64F_GX)
+#define ATI_CHIP_88800CX   (M64F_GX)
+
+#define ATI_CHIP_264CT     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
+#define ATI_CHIP_264ET     (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)
+
+#define ATI_CHIP_264VT     (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)
+#define ATI_CHIP_264GT     (M64F_GT | M64F_INTEGRATED               | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)
+
+#define ATI_CHIP_264VTB    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)
+#define ATI_CHIP_264VT3    (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
+#define ATI_CHIP_264VT4    (M64F_VT | M64F_INTEGRATED               | M64F_GTB_DSP)
+
+#define ATI_CHIP_264LT     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP)
+
+/* make sets shorter */
+#define ATI_MODERN_SET     (M64F_GT | M64F_INTEGRATED               | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)
+
+#define ATI_CHIP_264GTB    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
+/*#define ATI_CHIP_264GTDVD  ?*/
+#define ATI_CHIP_264LTG    (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)
+
+#define ATI_CHIP_264GT2C   (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)
+#define ATI_CHIP_264GTPRO  (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
+#define ATI_CHIP_264LTPRO  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
+
+#define ATI_CHIP_264XL     (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4)
+#define ATI_CHIP_MOBILITY  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS)
 
 static struct {
-	u16 pci_id, chip_type;
-	u8 rev_mask, rev_val;
+	u16 pci_id;
 	const char *name;
-	int pll, mclk;
+	int pll, mclk, xclk;
 	u32 features;
 } aty_chips[] __initdata = {
 #ifdef CONFIG_FB_ATY_GX
 	/* Mach64 GX */
-	{
-	0x4758, 0x00d7, 0x00, 0x00, m64n_gx, 135, 50, M64F_GX}, {
-	0x4358, 0x0057, 0x00, 0x00, m64n_cx, 135, 50, M64F_GX},
-#endif				/* CONFIG_FB_ATY_GX */
+	{ PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX },
+	{ PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, ATI_CHIP_88800CX },
+#endif /* CONFIG_FB_ATY_GX */
+
 #ifdef CONFIG_FB_ATY_CT
-	    /* Mach64 CT */
-	{
-	0x4354, 0x4354, 0x00, 0x00, m64n_ct, 135, 60,
-		    M64F_CT | M64F_INTEGRATED | M64F_CT_BUS |
-		    M64F_MAGIC_FIFO}, {
-	0x4554, 0x4554, 0x00, 0x00, m64n_et, 135, 60,
-		    M64F_CT | M64F_INTEGRATED | M64F_CT_BUS |
-		    M64F_MAGIC_FIFO},
-	    /* Mach64 VT */
-	{
-	0x5654, 0x5654, 0xc7, 0x00, m64n_vta3, 170, 67,
-		    M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
-		    M64F_MAGIC_FIFO | M64F_FIFO_24}, {
-	0x5654, 0x5654, 0xc7, 0x40, m64n_vta4, 200, 67,
-		    M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
-		    M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV}, {
-	0x5654, 0x5654, 0x00, 0x00, m64n_vtb, 200, 67,
-		    M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
-		    M64F_GTB_DSP | M64F_FIFO_24}, {
-	0x5655, 0x5655, 0x00, 0x00, m64n_vtb, 200, 67,
-		    M64F_VT | M64F_INTEGRATED | M64F_VT_BUS |
-		    M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL}, {
-	0x5656, 0x5656, 0x00, 0x00, m64n_vt4, 230, 83,
-		    M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP},
-	    /* Mach64 GT (3D RAGE) */
-	{
-	0x4754, 0x4754, 0x07, 0x00, m64n_gt, 135, 63,
-		    M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO |
-		    M64F_FIFO_24 | M64F_EXTRA_BRIGHT}, {
-	0x4754, 0x4754, 0x07, 0x01, m64n_gt, 170, 67,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
-		    M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x4754, 0x4754, 0x07, 0x02, m64n_gt, 200, 67,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
-		    M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x4755, 0x4755, 0x00, 0x00, m64n_gtb, 200, 67,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
-		    M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x4756, 0x4756, 0x00, 0x00, m64n_iic_p, 230, 83,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
-		    M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x4757, 0x4757, 0x00, 0x00, m64n_iic_a, 230, 83,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
-		    M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x475a, 0x475a, 0x00, 0x00, m64n_iic_a, 230, 83,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
-		    M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT},
-	    /* Mach64 LT */
-	{
-	0x4c54, 0x4c54, 0x00, 0x00, m64n_lt, 135, 63,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP}, {
-	0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg, 230, 63,
-		    M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP |
-		    M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT |
-		    M64F_LT_SLEEP | M64F_G3_PB_1024x768},
-	    /* Mach64 GTC (3D RAGE PRO) */
-	{
-	0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE}, {
-	0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT}, {
-	0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT},
-	    /* 3D RAGE XL */
-	{
-	0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL |
-		    M64F_EXTRA_BRIGHT | M64F_XL_DLL},
-	    /* Mach64 LT PRO */
-	{
-	0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP}, {
-	0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP}, {
-	0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_EXTRA_BRIGHT |
-		    M64F_G3_PB_1_1 | M64F_G3_PB_1024x768}, {
-	0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p, 230, 100,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP},
-	    /* 3D RAGE Mobility */
-	{
-	0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p, 230, 50,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_MOBIL_BUS}, {
-	0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a, 230, 50,
-		    M64F_GT | M64F_INTEGRATED | M64F_RESET_3D |
-		    M64F_GTB_DSP | M64F_MOBIL_BUS},
-#endif				/* CONFIG_FB_ATY_CT */
+	{ PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, ATI_CHIP_264CT },
+	{ PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, ATI_CHIP_264ET },
+	{ PCI_CHIP_MACH64VT, "ATI264VT? (Mach64 VT)", 170, 67, 67, ATI_CHIP_264VT },
+	{ PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, ATI_CHIP_264GT },
+	/* FIXME { ...ATI_264GU, maybe ATI_CHIP_264GTDVD }, */
+	{ PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GTB)", 200, 67, 67, ATI_CHIP_264GTB  },
+	{ PCI_CHIP_MACH64VU, "ATI264VTB (Mach64 VU)", 200, 67, 67, ATI_CHIP_264VT3 },
+
+	{ PCI_CHIP_MACH64LT, "3D RAGE LT (Mach64 LT)", 135, 63, 63, ATI_CHIP_264LT },
+	 /* FIXME chipset maybe ATI_CHIP_264LTPRO ? */
+	{ PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
+
+	{ PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, ATI_CHIP_264VT4 },
+
+	{ PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
+	{ PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
+
+	{ PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
+	{ PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO },
+	{ PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, ATI_CHIP_264GTPRO },
+
+	{ PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
+	{ PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
+	{ PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
+
+	{ PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP)", 230, 83, 63, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GN, "3D RAGE XL (Mach64 GN, AGP)", 230, 83, 63, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66/BGA)", 230, 83, 63, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 230, 83, 63, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GL, "3D RAGE XL (Mach64 GL, PCI)", 230, 83, 63, ATI_CHIP_264XL },
+	{ PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL },
+
+	{ PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
+	{ PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
+#endif /* CONFIG_FB_ATY_CT */
 };
 
+/* can not fail */
+static int __devinit correct_chipset(struct atyfb_par *par)
+{
+	u8 rev;
+	u16 type;
+	u32 chip_id;
+	const char *name;
+	int i;
+
+	for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
+		if (par->pci_id == aty_chips[i].pci_id)
+			break;
+
+	name = aty_chips[i].name;
+	par->pll_limits.pll_max = aty_chips[i].pll;
+	par->pll_limits.mclk = aty_chips[i].mclk;
+	par->pll_limits.xclk = aty_chips[i].xclk;
+	par->features = aty_chips[i].features;
+
+	chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
+	type = chip_id & CFG_CHIP_TYPE;
+	rev = (chip_id & CFG_CHIP_REV) >> 24;
+
+	switch(par->pci_id) {
+#ifdef CONFIG_FB_ATY_GX
+	case PCI_CHIP_MACH64GX:
+		if(type != 0x00d7);
+			return -ENODEV;
+		break;
+	case PCI_CHIP_MACH64CX:
+		if(type != 0x0057);
+			return -ENODEV;
+		break;
+#endif
+#ifdef CONFIG_FB_ATY_CT
+	case PCI_CHIP_MACH64VT:
+		rev &= 0xc7;
+		if(rev == 0x00) {
+			name = "ATI264VTA3 (Mach64 VT)";
+			par->pll_limits.pll_max = 170;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->features = ATI_CHIP_264VT;
+		} else if(rev == 0x40) {
+			name = "ATI264VTA4 (Mach64 VT)";
+			par->pll_limits.pll_max = 200;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
+		} else {
+			name = "ATI264VTB (Mach64 VT)";
+			par->pll_limits.pll_max = 200;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->features = ATI_CHIP_264VTB;
+		}
+		break;
+	case PCI_CHIP_MACH64GT:
+		rev &= 0x07;
+		if(rev == 0x01) {
+			par->pll_limits.pll_max = 170;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->features = ATI_CHIP_264GTB;
+		} else if(rev == 0x02) {
+			par->pll_limits.pll_max = 200;
+			par->pll_limits.mclk = 67;
+			par->pll_limits.xclk = 67;
+			par->features = ATI_CHIP_264GTB;
+		}
+		break;
+#endif
+	}
+
+	PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);
+	return 0;
+}
+
 static char ram_dram[] __initdata = "DRAM";
+static char ram_resv[] __initdata = "RESV";
 #ifdef CONFIG_FB_ATY_GX
 static char ram_vram[] __initdata = "VRAM";
 #endif /* CONFIG_FB_ATY_GX */
 #ifdef CONFIG_FB_ATY_CT
 static char ram_edo[] __initdata = "EDO";
-static char ram_sdram[] __initdata = "SDRAM";
-static char ram_sgram[] __initdata = "SGRAM";
-static char ram_wram[] __initdata = "WRAM";
+static char ram_sdram[] __initdata = "SDRAM (1:1)";
+static char ram_sgram[] __initdata = "SGRAM (1:1)";
+static char ram_sdram32[] __initdata = "SDRAM (2:1) (32-bit)";
 static char ram_off[] __initdata = "OFF";
 #endif /* CONFIG_FB_ATY_CT */
-static char ram_resv[] __initdata = "RESV";
+
 
 static u32 pseudo_palette[17];
 
@@ -410,109 +513,226 @@
 	ram_dram, ram_vram, ram_vram, ram_dram,
 	ram_dram, ram_vram, ram_vram, ram_resv
 };
-#endif				/* CONFIG_FB_ATY_GX */
+#endif /* CONFIG_FB_ATY_GX */
 
 #ifdef CONFIG_FB_ATY_CT
 static char *aty_ct_ram[8] __initdata = {
 	ram_off, ram_dram, ram_edo, ram_edo,
-	ram_sdram, ram_sgram, ram_wram, ram_resv
+	ram_sdram, ram_sgram, ram_sdram32, ram_resv
 };
-#endif				/* CONFIG_FB_ATY_CT */
+#endif /* CONFIG_FB_ATY_CT */
 
+static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par)
+{
+	u32 pixclock = var->pixclock;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	u32 lcd_on_off;
+	par->pll.ct.xres = 0;
+	if (par->lcd_table != 0) {
+		lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);
+		if(lcd_on_off & LCD_ON) {
+			par->pll.ct.xres = var->xres;
+			pixclock = par->lcd_pixclock;
+		}
+	}
+#endif
+	return pixclock;
+}
 
 #if defined(CONFIG_PPC)
 
-    /*
-     *  Apple monitor sense
-     */
+/*
+ *  Apple monitor sense
+ */
 
 static int __init read_aty_sense(const struct atyfb_par *par)
 {
 	int sense, i;
 
-	aty_st_le32(GP_IO, 0x31003100, par);	/* drive outputs high */
+	aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */
 	__delay(200);
-	aty_st_le32(GP_IO, 0, par);	/* turn off outputs */
+	aty_st_le32(GP_IO, 0, par); /* turn off outputs */
 	__delay(2000);
-	i = aty_ld_le32(GP_IO, par);	/* get primary sense value */
+	i = aty_ld_le32(GP_IO, par); /* get primary sense value */
 	sense = ((i & 0x3000) >> 3) | (i & 0x100);
 
 	/* drive each sense line low in turn and collect the other 2 */
-	aty_st_le32(GP_IO, 0x20000000, par);	/* drive A low */
+	aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */
 	__delay(2000);
 	i = aty_ld_le32(GP_IO, par);
 	sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
-	aty_st_le32(GP_IO, 0x20002000, par);	/* drive A high again */
+	aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */
 	__delay(200);
 
-	aty_st_le32(GP_IO, 0x10000000, par);	/* drive B low */
+	aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */
 	__delay(2000);
 	i = aty_ld_le32(GP_IO, par);
 	sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
-	aty_st_le32(GP_IO, 0x10001000, par);	/* drive B high again */
+	aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */
 	__delay(200);
 
-	aty_st_le32(GP_IO, 0x01000000, par);	/* drive C low */
+	aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */
 	__delay(2000);
 	sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;
-	aty_st_le32(GP_IO, 0, par);	/* turn off outputs */
+	aty_st_le32(GP_IO, 0, par); /* turn off outputs */
 	return sense;
 }
 
-#endif				/* defined(CONFIG_PPC) */
-
-#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT)
-static void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
-{
-	unsigned long temp;
-
-	/* write addr byte */
-	temp = aty_ld_le32(LCD_INDEX, par);
-	aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
-	/* write the register value */
-	aty_st_le32(LCD_DATA, val, par);
-}
-
-static u32 aty_ld_lcd(int index, const struct atyfb_par *par)
-{
-	unsigned long temp;
-
-	/* write addr byte */
-	temp = aty_ld_le32(LCD_INDEX, par);
-	aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par);
-	/* read the register value */
-	return aty_ld_le32(LCD_DATA, par);
-}
-#endif				/* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT */
+#endif /* defined(CONFIG_PPC) */
 
 /* ------------------------------------------------------------------------- */
 
-    /*
-     *  CRTC programming
-     */
+/*
+ *  CRTC programming
+ */
 
-static void aty_set_crtc(const struct atyfb_par *par,
-			 const struct crtc *crtc)
+static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc)
 {
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		if(!M64_HAS(LT_LCD_REGS)) {
+		    crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);
+		    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
+		}
+		crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par);
+		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);
+
+
+		/* switch to non shadow registers */
+		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
+                    ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
+
+		/* save stretching */
+		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
+		crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);
+		if (!M64_HAS(LT_LCD_REGS))
+			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);
+	}
+#endif
+	crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
+	crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
+	crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
+	crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
+	crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);
+	crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);
+	crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* switch to shadow registers */
+		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
+			SHADOW_EN | SHADOW_RW_EN, par);
+
+		crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
+		crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
+		crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
+		crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
+
+		aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+}
+
+static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
+{
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* stop CRTC */
+		aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);
+
+		/* update non-shadow registers first */
+		aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par);
+		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &
+			~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);
+
+		/* temporarily disable stretching */
+		aty_st_lcd(HORZ_STRETCHING,
+			crtc->horz_stretching &
+			~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);
+		aty_st_lcd(VERT_STRETCHING,
+			crtc->vert_stretching &
+			~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |
+			VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);
+	}
+#endif
+	/* turn off CRT */
+	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);
+
+	DPRINTK("setting up CRTC\n");
+	PRINTKI("set primary CRT to %ix%i %c%c composite %c\n",
+	    ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1),
+	    (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P',
+	    (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N');
+
+	DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);
+	DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);
+	DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);
+	DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);
+	DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);
+	DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);
+	DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);
+
 	aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);
 	aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);
 	aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);
 	aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);
-	aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, par);
 	aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);
+	aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);
+
 	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);
+#if 0
+	FIXME
+	if (par->accel_flags & FB_ACCELF_TEXT)
+		aty_init_engine(par, info);
+#endif
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	/* after setting the CRTC registers we should set the LCD registers. */
+	if (par->lcd_table != 0) {
+		/* switch to shadow registers */
+		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
+			(SHADOW_EN | SHADOW_RW_EN), par);
+
+		PRINTKI("set secondary CRT to %ix%i %c%c\n",
+		    ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
+		    (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
+
+		DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp);
+		DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid);
+		DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp);
+		DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid);
+
+		aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);
+		aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);
+		aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);
+		aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);
+
+		/* restore CRTC selection & shadow state and enable stretching */
+		DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);
+		DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);
+		DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);
+		if(!M64_HAS(LT_LCD_REGS))
+		    DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);
+
+		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);
+		aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);
+		aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);
+		if(!M64_HAS(LT_LCD_REGS)) {
+		    aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);
+		    aty_ld_le32(LCD_INDEX, par);
+		    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);
+		}
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
 }
 
 static int aty_var_to_crtc(const struct fb_info *info,
-			   const struct fb_var_screeninfo *var,
-			   struct crtc *crtc)
+	const struct fb_var_screeninfo *var, struct crtc *crtc)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
-	u32 left, right, upper, lower, hslen, vslen, sync, vmode;
-	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,
-	    h_sync_pol;
-	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
+	u32 sync, vmode, vdisplay;
+	u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
+	u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
 	u32 pix_width, dp_pix_width, dp_chain_mask;
 
 	/* input */
@@ -523,53 +743,19 @@
 	xoffset = var->xoffset;
 	yoffset = var->yoffset;
 	bpp = var->bits_per_pixel;
-	left = var->left_margin;
-	right = var->right_margin;
-	upper = var->upper_margin;
-	lower = var->lower_margin;
-	hslen = var->hsync_len;
-	vslen = var->vsync_len;
+	if (bpp == 16)
+		bpp = (var->green.length == 5) ? 15 : 16;
 	sync = var->sync;
 	vmode = var->vmode;
 
 	/* convert (and round up) and validate */
-	xres = (xres + 7) & ~7;
-	xoffset = (xoffset + 7) & ~7;
-	vxres = (vxres + 7) & ~7;
 	if (vxres < xres + xoffset)
 		vxres = xres + xoffset;
-	h_disp = xres / 8 - 1;
-	if (h_disp > 0xff)
-		FAIL("h_disp too large");
-	h_sync_strt = h_disp + (right / 8);
-	if (h_sync_strt > 0x1ff)
-		FAIL("h_sync_start too large");
-	h_sync_dly = right & 7;
-	h_sync_wid = (hslen + 7) / 8;
-	if (h_sync_wid > 0x1f)
-		FAIL("h_sync_wid too large");
-	h_total = h_sync_strt + h_sync_wid + (h_sync_dly + left + 7) / 8;
-	if (h_total > 0x1ff)
-		FAIL("h_total too large");
-	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+	h_disp = xres;
 
 	if (vyres < yres + yoffset)
 		vyres = yres + yoffset;
-	v_disp = yres - 1;
-	if (v_disp > 0x7ff)
-		FAIL("v_disp too large");
-	v_sync_strt = v_disp + lower;
-	if (v_sync_strt > 0x7ff)
-		FAIL("v_sync_strt too large");
-	v_sync_wid = vslen;
-	if (v_sync_wid > 0x1f)
-		FAIL("v_sync_wid too large");
-	v_total = v_sync_strt + v_sync_wid + upper;
-	if (v_total > 0x7ff)
-		FAIL("v_total too large");
-	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
-	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
+	v_disp = yres;
 
 	if (bpp <= 8) {
 		bpp = 8;
@@ -577,54 +763,325 @@
 		dp_pix_width =
 		    HOST_8BPP | SRC_8BPP | DST_8BPP |
 		    BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = 0x8080;
-	} else if (bpp <= 16) {
+		dp_chain_mask = DP_CHAIN_8BPP;
+	} else if (bpp <= 15) {
 		bpp = 16;
 		pix_width = CRTC_PIX_WIDTH_15BPP;
 		dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
 		    BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = 0x4210;
+		dp_chain_mask = DP_CHAIN_15BPP;
+	} else if (bpp <= 16) {
+		bpp = 16;
+		pix_width = CRTC_PIX_WIDTH_16BPP;
+		dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |
+		    BYTE_ORDER_LSB_TO_MSB;
+		dp_chain_mask = DP_CHAIN_16BPP;
 	} else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
 		bpp = 24;
 		pix_width = CRTC_PIX_WIDTH_24BPP;
 		dp_pix_width =
 		    HOST_8BPP | SRC_8BPP | DST_8BPP |
 		    BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = 0x8080;
+		dp_chain_mask = DP_CHAIN_24BPP;
 	} else if (bpp <= 32) {
 		bpp = 32;
 		pix_width = CRTC_PIX_WIDTH_32BPP;
 		dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
 		    BYTE_ORDER_LSB_TO_MSB;
-		dp_chain_mask = 0x8080;
+		dp_chain_mask = DP_CHAIN_32BPP;
 	} else
 		FAIL("invalid bpp");
 
 	if (vxres * vyres * bpp / 8 > info->fix.smem_len)
 		FAIL("not enough video RAM");
 
-	if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-		FAIL("invalid vmode");
+	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+
+	if((xres > 1600) || (yres > 1200)) {
+		FAIL("MACH64 chips are designed for max 1600x1200\n"
+		"select anoter resolution.");
+	}
+	h_sync_strt = h_disp + var->right_margin;
+	h_sync_end = h_sync_strt + var->hsync_len;
+	h_sync_dly  = var->right_margin & 7;
+	h_total = h_sync_end + h_sync_dly + var->left_margin;
+
+	v_sync_strt = v_disp + var->lower_margin;
+	v_sync_end = v_sync_strt + var->vsync_len;
+	v_total = v_sync_end + var->upper_margin;
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		if(!M64_HAS(LT_LCD_REGS)) {
+		    u32 lcd_index = aty_ld_le32(LCD_INDEX, par);
+		    crtc->lcd_index = lcd_index &
+			~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS);
+		    aty_st_le32(LCD_INDEX, lcd_index, par);
+		}
+
+		if (!M64_HAS(MOBIL_BUS))
+			crtc->lcd_index |= CRTC2_DISPLAY_DIS;
+
+		crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;
+		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;
+
+		crtc->lcd_gen_cntl &=
+			~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |
+			/*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/
+			USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
+		crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;
+
+		if((crtc->lcd_gen_cntl & LCD_ON) &&
+			((xres > par->lcd_width) || (yres > par->lcd_height))) {
+			/* We cannot display the mode on the LCD. If the CRT is enabled
+			   we can turn off the LCD.
+			   If the CRT is off, it isn't a good idea to switch it on; we don't
+			   know if one is connected. So it's better to fail then.
+			 */
+			if (crtc->lcd_gen_cntl & CRT_ON) {
+				PRINTKI("Disable lcd panel, because video mode does not fit.\n");
+				crtc->lcd_gen_cntl &= ~LCD_ON;
+				/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
+			} else {
+				FAIL("Video mode exceeds size of lcd panel.\nConnect this computer to a conventional monitor if you really need this mode.");
+			}
+		}
+	}
+
+	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {
+		int VScan = 1;
+		/* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5
+		const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };
+		const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 };  */
+
+		vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
+
+		/* This is horror! When we simulate, say 640x480 on an 800x600
+		   lcd monitor, the CRTC should be programmed 800x600 values for
+		   the non visible part, but 640x480 for the visible part.
+		   This code has been tested on a laptop with it's 1400x1050 lcd
+		   monitor and a conventional monitor both switched on.
+		   Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
+		    works with little glitches also with DOUBLESCAN modes
+		 */
+		if (yres < par->lcd_height) {
+			VScan = par->lcd_height / yres;
+			if(VScan > 1) {
+				VScan = 2;
+				vmode |= FB_VMODE_DOUBLE;
+			}
+		}
+
+		h_sync_strt = h_disp + par->lcd_right_margin;
+		h_sync_end = h_sync_strt + par->lcd_hsync_len;
+		h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;
+		h_total = h_disp + par->lcd_hblank_len;
+
+		v_sync_strt = v_disp + par->lcd_lower_margin / VScan;
+		v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;
+		v_total = v_disp + par->lcd_vblank_len / VScan;
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+
+	h_disp = (h_disp >> 3) - 1;
+	h_sync_strt = (h_sync_strt >> 3) - 1;
+	h_sync_end = (h_sync_end >> 3) - 1;
+	h_total = (h_total >> 3) - 1;
+	h_sync_wid = h_sync_end - h_sync_strt;
+
+	FAIL_MAX("h_disp too large", h_disp, 0xff);
+	FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);
+	/*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/
+	if(h_sync_wid > 0x1f)
+		h_sync_wid = 0x1f;
+	FAIL_MAX("h_total too large", h_total, 0x1ff);
+
+	if (vmode & FB_VMODE_DOUBLE) {
+		v_disp <<= 1;
+		v_sync_strt <<= 1;
+		v_sync_end <<= 1;
+		v_total <<= 1;
+	}
+
+	vdisplay = yres;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))
+		vdisplay  = par->lcd_height;
+#endif
+
+	if(vdisplay < 400) {
+		h_sync_pol = 1;
+		v_sync_pol = 0;
+	} else if(vdisplay < 480) {
+		h_sync_pol = 0;
+		v_sync_pol = 1;
+	} else if(vdisplay < 768) {
+		h_sync_pol = 0;
+		v_sync_pol = 0;
+	} else {
+		h_sync_pol = 1;
+		v_sync_pol = 1;
+	}
+
+	v_disp--;
+	v_sync_strt--;
+	v_sync_end--;
+	v_total--;
+	v_sync_wid = v_sync_end - v_sync_strt;
+
+	FAIL_MAX("v_disp too large", v_disp, 0x7ff);
+	FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);
+	/*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/
+	if(v_sync_wid > 0x1f)
+		v_sync_wid = 0x1f;
+	FAIL_MAX("v_total too large", v_total, 0x7ff);
+
+	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
 
 	/* output */
 	crtc->vxres = vxres;
 	crtc->vyres = vyres;
-	crtc->h_tot_disp = h_total | (h_disp << 16);
-	crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) |
-	    ((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) |
-	    (h_sync_pol << 21);
-	crtc->v_tot_disp = v_total | (v_disp << 16);
-	crtc->v_sync_strt_wid =
-	    v_sync_strt | (v_sync_wid << 16) | (v_sync_pol << 21);
-	crtc->off_pitch =
-	    ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
-	crtc->gen_cntl =
-	    pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
+	crtc->xoffset = xoffset;
+	crtc->yoffset = yoffset;
+	crtc->bpp = bpp;
+	crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
+	crtc->vline_crnt_vline = 0;
+
+	crtc->h_tot_disp = h_total | (h_disp<<16);
+	crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
+		((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21);
+	crtc->v_tot_disp = v_total | (v_disp<<16);
+	crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
+
+	/* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */
+	crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;
+	crtc->gen_cntl |= CRTC_VGA_LINEAR;
+
+	/* Enable doublescan mode if requested */
+	if (vmode & FB_VMODE_DOUBLE)
+		crtc->gen_cntl |= CRTC_DBL_SCAN_EN;
+	/* Enable interlaced mode if requested */
+	if (vmode & FB_VMODE_INTERLACED)
+		crtc->gen_cntl |= CRTC_INTERLACE_EN;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		vdisplay = yres;
+		if(vmode & FB_VMODE_DOUBLE)
+			vdisplay <<= 1;
+		if(vmode & FB_VMODE_INTERLACED) {
+			vdisplay >>= 1;
+
+			/* The prefered mode for the lcd is not interlaced, so disable it if
+			   it was enabled. For doublescan there is no problem, because we can
+			   compensate for it in the hardware stretching (we stretch half as much)
+			 */
+			vmode &= ~FB_VMODE_INTERLACED;
+			/*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/
+		}
+		crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
+		crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
+			/*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
+			USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);
+		crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/);
+
+		/* MOBILITY M1 tested, FIXME: LT */
+		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);
+		if (!M64_HAS(LT_LCD_REGS))
+			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &
+				~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);
+
+		crtc->horz_stretching &=
+			~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
+			HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
+		if (xres < par->lcd_width) {
+			do {
+				/*
+				* The horizontal blender misbehaves when HDisplay is less than a
+				* a certain threshold (440 for a 1024-wide panel).  It doesn't
+				* stretch such modes enough.  Use pixel replication instead of
+				* blending to stretch modes that can be made to exactly fit the
+				* panel width.  The undocumented "NoLCDBlend" option allows the
+				* pixel-replicated mode to be slightly wider or narrower than the
+				* panel width.  It also causes a mode that is exactly half as wide
+				* as the panel to be pixel-replicated, rather than blended.
+				*/
+				int HDisplay  = xres & ~7;
+				int nStretch  = par->lcd_width / HDisplay;
+				int Remainder = par->lcd_width % HDisplay;
+
+				if ((!Remainder && ((nStretch > 2))) ||
+					(((HDisplay * 16) / par->lcd_width) < 7)) {
+					static const char StretchLoops[] = {10, 12, 13, 15, 16};
+					int horz_stretch_loop = -1, BestRemainder;
+					int Numerator = HDisplay, Denominator = par->lcd_width;
+					int Index = 5;
+					ATIReduceRatio(&Numerator, &Denominator);
+
+					BestRemainder = (Numerator * 16) / Denominator;
+					while (--Index >= 0) {
+						Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %
+							Denominator;
+						if (Remainder < BestRemainder) {
+							horz_stretch_loop = Index;
+							if (!(BestRemainder = Remainder))
+								break;
+						}
+					}
+
+					if ((horz_stretch_loop >= 0) && !BestRemainder) {
+						int horz_stretch_ratio = 0, Accumulator = 0;
+						int reuse_previous = 1;
+
+						Index = StretchLoops[horz_stretch_loop];
+
+						while (--Index >= 0) {
+							if (Accumulator > 0)
+								horz_stretch_ratio |= reuse_previous;
+							else
+								Accumulator += Denominator;
+							Accumulator -= Numerator;
+							reuse_previous <<= 1;
+						}
+
+						crtc->horz_stretching |= (HORZ_STRETCH_EN |
+							((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |
+							(horz_stretch_ratio & HORZ_STRETCH_RATIO));
+						break;      /* Out of the do { ... } while (0) */
+					}
+				}
+
+				crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |
+					(((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));
+			} while (0);
+		}
+
+		if (vdisplay < par->lcd_height) {
+			crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
+				(((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
+
+			if (!M64_HAS(LT_LCD_REGS) &&
+			    xres <= (M64_HAS(MOBIL_BUS)?1024:800))
+				crtc->ext_vert_stretch |= VERT_STRETCH_MODE;
+		} else {
+			/*
+			 * Don't use vertical blending if the mode is too wide or not
+			 * vertically stretched.
+			 */
+			crtc->vert_stretching = 0;
+		}
+		/* copy to shadow crtc */
+		crtc->shadow_h_tot_disp = crtc->h_tot_disp;
+		crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;
+		crtc->shadow_v_tot_disp = crtc->v_tot_disp;
+		crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+
 	if (M64_HAS(MAGIC_FIFO)) {
 		/* Not VTB/GTB */
 		/* FIXME: magic FIFO values */
-		crtc->gen_cntl |=
-		    aty_ld_le32(CRTC_GEN_CNTL, par) & 0x000e0000;
+		crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC2_PIX_WIDTH);
 	}
 	crtc->dp_pix_width = dp_pix_width;
 	crtc->dp_chain_mask = dp_chain_mask;
@@ -632,21 +1089,19 @@
 	return 0;
 }
 
-
-static int aty_crtc_to_var(const struct crtc *crtc,
-			   struct fb_var_screeninfo *var)
+static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var)
 {
 	u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
 	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,
 	    h_sync_pol;
 	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
 	u32 pix_width;
+	u32 double_scan, interlace;
 
 	/* input */
 	h_total = crtc->h_tot_disp & 0x1ff;
 	h_disp = (crtc->h_tot_disp >> 16) & 0xff;
-	h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
-	    ((crtc->h_sync_strt_wid >> 4) & 0x100);
+	h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | ((crtc->h_sync_strt_wid >> 4) & 0x100);
 	h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;
 	h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;
 	h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;
@@ -657,6 +1112,8 @@
 	v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;
 	c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
 	pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
+	double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
+	interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
 
 	/* convert */
 	xres = (h_disp + 1) * 8;
@@ -707,7 +1164,6 @@
 		var->transp.offset = 0;
 		var->transp.length = 0;
 		break;
-#if 0
 	case CRTC_PIX_WIDTH_16BPP:	/* RGB 565 */
 		bpp = 16;
 		var->red.offset = 11;
@@ -719,7 +1175,6 @@
 		var->transp.offset = 0;
 		var->transp.length = 0;
 		break;
-#endif
 	case CRTC_PIX_WIDTH_24BPP:	/* RGB 888 */
 		bpp = 24;
 		var->red.offset = 16;
@@ -760,6 +1215,21 @@
 	var->vsync_len = vslen;
 	var->sync = sync;
 	var->vmode = FB_VMODE_NONINTERLACED;
+	/* In double scan mode, the vertical parameters are doubled, so we need to
+	   half them to get the right values.
+	   In interlaced mode the values are already correct, so no correction is
+	   necessary.
+	 */
+	if (interlace)
+		var->vmode = FB_VMODE_INTERLACED;
+
+	if (double_scan) {
+		var->vmode = FB_VMODE_DOUBLE;
+		var->yres>>=1;
+		var->upper_margin>>=1;
+		var->lower_margin>>=1;
+		var->vsync_len>>=1;
+	}
 
 	return 0;
 }
@@ -770,58 +1240,116 @@
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	struct fb_var_screeninfo *var = &info->var;
-	u8 tmp;
-	u32 i;
+	u32 tmp, pixclock;
 	int err;
+#ifdef DEBUG
+	struct fb_var_screeninfo debug;
+	u32 pixclock_in_ps;
+#endif
+	if (par->asleep)
+		return 0;
 
-	if ((err = aty_var_to_crtc(info, var, &par->crtc)) ||
-	    (err = par->pll_ops->var_to_pll(info, var->pixclock,
-					var->bits_per_pixel, &par->pll)))
+	if ((err = aty_var_to_crtc(info, var, &par->crtc)))
 		return err;
 
-	par->accel_flags = var->accel_flags;	/* hack */
+	pixclock = atyfb_get_pixclock(var, par);
+
+	if (pixclock == 0) {
+		FAIL("Invalid pixclock");
+	} else {
+		if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll)))
+			return err;
+	}
+
+	par->accel_flags = var->accel_flags; /* hack */
 
 	if (par->blitter_may_be_busy)
 		wait_for_idle(par);
-	tmp = aty_ld_8(CRTC_GEN_CNTL + 3, par);
-	aty_set_crtc(par, &par->crtc);
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);
-	/* better call aty_StrobeClock ?? */
-	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, CLOCK_STROBE, par);
 
-	par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel,
-			      par->accel_flags);
+	aty_set_crtc(par, &par->crtc);
+	par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags);
 	par->pll_ops->set_pll(info, &par->pll);
 
+#ifdef DEBUG
+	if(par->pll_ops && par->pll_ops->pll_to_var)
+		pixclock_in_ps = par->pll_ops->pll_to_var(info, &(par->pll));
+	else
+		pixclock_in_ps = 0;
+
+	if(0 == pixclock_in_ps) {
+		PRINTKE("ALERT ops->pll_to_var get 0\n");
+		pixclock_in_ps = pixclock;
+	}
+
+	memset(&debug, 0, sizeof(debug));
+	if(!aty_crtc_to_var(&(par->crtc), &debug)) {
+		u32 hSync, vRefresh;
+		u32 h_disp, h_sync_strt, h_sync_end, h_total;
+		u32 v_disp, v_sync_strt, v_sync_end, v_total;
+
+		h_disp = debug.xres;
+		h_sync_strt = h_disp + debug.right_margin;
+		h_sync_end = h_sync_strt + debug.hsync_len;
+		h_total = h_sync_end + debug.left_margin;
+		v_disp = debug.yres;
+		v_sync_strt = v_disp + debug.lower_margin;
+		v_sync_end = v_sync_strt + debug.vsync_len;
+		v_total = v_sync_end + debug.upper_margin;
+
+		hSync = 1000000000 / (pixclock_in_ps * h_total);
+		vRefresh = (hSync * 1000) / v_total;
+        	if (par->crtc.gen_cntl & CRTC_INTERLACE_EN)
+            	vRefresh *= 2;
+        	if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
+            	vRefresh /= 2;
+
+		DPRINTK("atyfb_set_par\n");
+		DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n",
+			var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps);
+		DPRINTK(" Dot clock:           %i MHz\n", 1000000 / pixclock_in_ps);
+		DPRINTK(" Horizontal sync:     %i kHz\n", hSync);
+		DPRINTK(" Vertical refresh:    %i Hz\n", vRefresh);
+		DPRINTK(" x  style: %i.%03i %i %i %i %i   %i %i %i %i\n",
+			1000000 / pixclock_in_ps, 1000000 % pixclock_in_ps,
+			h_disp, h_sync_strt, h_sync_end, h_total,
+			v_disp, v_sync_strt, v_sync_end, v_total);
+		DPRINTK(" fb style: %i  %i %i %i %i %i %i %i %i\n",
+			pixclock_in_ps,
+			debug.left_margin, h_disp, debug.right_margin, debug.hsync_len,
+			debug.upper_margin, v_disp, debug.lower_margin, debug.vsync_len);
+	}
+#endif /* DEBUG */
+
 	if (!M64_HAS(INTEGRATED)) {
 		/* Don't forget MEM_CNTL */
-		i = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
+		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;
 		switch (var->bits_per_pixel) {
 		case 8:
-			i |= 0x02000000;
+			tmp |= 0x02000000;
 			break;
 		case 16:
-			i |= 0x03000000;
+			tmp |= 0x03000000;
 			break;
 		case 32:
-			i |= 0x06000000;
+			tmp |= 0x06000000;
 			break;
 		}
-		aty_st_le32(MEM_CNTL, i, par);
+		aty_st_le32(MEM_CNTL, tmp, par);
 	} else {
-		i = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
+		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;
 		if (!M64_HAS(MAGIC_POSTDIV))
-			i |= par->mem_refresh_rate << 20;
+			tmp |= par->mem_refresh_rate << 20;
 		switch (var->bits_per_pixel) {
 		case 8:
 		case 24:
-			i |= 0x00000000;
+			tmp |= 0x00000000;
 			break;
 		case 16:
-			i |= 0x04000000;
+			tmp |= 0x04000000;
 			break;
 		case 32:
-			i |= 0x08000000;
+			tmp |= 0x08000000;
 			break;
 		}
 		if (M64_HAS(CT_BUS)) {
@@ -832,16 +1360,14 @@
 			aty_st_le32(BUS_CNTL, 0x680000f9, par);
 		} else if (M64_HAS(MOBIL_BUS)) {
 			aty_st_le32(DAC_CNTL, 0x80010102, par);
-			aty_st_le32(BUS_CNTL, 0x7b33a040, par);
+			aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
 		} else {
 			/* GT */
 			aty_st_le32(DAC_CNTL, 0x86010102, par);
-			aty_st_le32(BUS_CNTL, 0x7b23a040, par);
-			aty_st_le32(EXT_MEM_CNTL,
-				    aty_ld_le32(EXT_MEM_CNTL,
-						par) | 0x5000001, par);
+			aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);
+			aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);
 		}
-		aty_st_le32(MEM_CNTL, i, par);
+		aty_st_le32(MEM_CNTL, tmp, par);
 	}
 	aty_st_8(DAC_MASK, 0xff, par);
 
@@ -855,29 +1381,98 @@
 
 #ifdef CONFIG_BOOTX_TEXT
 	btext_update_display(info->fix.smem_start,
-			     (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
-			     ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
-			     var->bits_per_pixel,
-			     par->crtc.vxres * var->bits_per_pixel / 8);
-#endif				/* CONFIG_BOOTX_TEXT */
+		(((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,
+		((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,
+		var->bits_per_pixel,
+		par->crtc.vxres * var->bits_per_pixel / 8);
+#endif /* CONFIG_BOOTX_TEXT */
+#if 0
+	/* switch to accelerator mode */
+	if (!(par->crtc.gen_cntl & CRTC_EXT_DISP_EN))
+		aty_st_le32(CRTC_GEN_CNTL, par->crtc.gen_cntl | CRTC_EXT_DISP_EN, par);
+#endif
+#ifdef DEBUG
+{
+	/* dump non shadow CRTC, pll, LCD registers */
+	int i; u32 base;
+
+	/* CRTC registers */
+	base = 0x2000;
+	printk("debug atyfb: Mach64 non-shadow register values:");
+	for (i = 0; i < 256; i = i+4) {
+		if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i);
+		printk(" %08X", aty_ld_le32(i, par));
+	}
+	printk("\n\n");
+
+#ifdef CONFIG_FB_ATY_CT
+	/* PLL registers */
+	base = 0x00;
+	printk("debug atyfb: Mach64 PLL register values:");
+	for (i = 0; i < 64; i++) {
+		if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
+		if(i%4 == 0)  printk(" ");
+		printk("%02X", aty_ld_pll_ct(i, par));
+	}
+	printk("\n\n");
+#endif	/* CONFIG_FB_ATY_CT */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* LCD registers */
+		base = 0x00;
+		printk("debug atyfb: LCD register values:");
+		if(M64_HAS(LT_LCD_REGS)) {
+		    for(i = 0; i <= POWER_MANAGEMENT; i++) {
+			if(i == EXT_VERT_STRETCH)
+			    continue;
+			printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]);
+			printk(" %08X", aty_ld_lcd(i, par));
+		    }
+
+		} else {
+		    for (i = 0; i < 64; i++) {
+			if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);
+			printk(" %08X", aty_ld_lcd(i, par));
+		    }
+		}
+		printk("\n\n");
+	}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+}
+#endif /* DEBUG */
 	return 0;
 }
 
-static int atyfb_check_var(struct fb_var_screeninfo *var,
-			   struct fb_info *info)
+static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	int err;
 	struct crtc crtc;
 	union aty_pll pll;
-	int err;
+	u32 pixclock;
 
-	if ((err = aty_var_to_crtc(info, var, &crtc)) ||
-	    (err = par->pll_ops->var_to_pll(info, var->pixclock,
-					var->bits_per_pixel, &pll)))
+	memcpy(&pll, &(par->pll), sizeof(pll));
+
+	if((err = aty_var_to_crtc(info, var, &crtc)))
 		return err;
 
-#if 0	/* fbmon is not done. uncomment for 2.5.x -brad */
-	if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
+	pixclock = atyfb_get_pixclock(var, par);
+
+	if (pixclock == 0) {
+		FAIL("Invalid pixclock");
+	} else {
+		if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))
+			return err;
+	}
+
+	if (var->accel_flags & FB_ACCELF_TEXT)
+		info->var.accel_flags = FB_ACCELF_TEXT;
+	else
+		info->var.accel_flags = 0;
+
+#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
+	if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
 		return -EINVAL;
 #endif
 	aty_crtc_to_var(&crtc, var);
@@ -885,17 +1480,14 @@
 	return 0;
 }
 
-static void set_off_pitch(struct atyfb_par *par,
-			  const struct fb_info *info)
+static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
 {
 	u32 xoffset = info->var.xoffset;
 	u32 yoffset = info->var.yoffset;
 	u32 vxres = par->crtc.vxres;
 	u32 bpp = info->var.bits_per_pixel;
 
-	par->crtc.off_pitch =
-	    ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
-	aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+	par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
 }
 
 
@@ -905,35 +1497,103 @@
 
 static int atyfb_open(struct fb_info *info, int user)
 {
-#ifdef __sparc__
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 
 	if (user) {
 		par->open++;
+#ifdef __sparc__
 		par->mmaped = 0;
-	}
 #endif
+	}
 	return (0);
 }
 
-struct fb_var_screeninfo default_var = {
-	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-	640, 480, 640, 480, 0, 0, 8, 0,
-	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-	0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
+static irqreturn_t aty_irq(int irq, void *dev_id, struct pt_regs *fp)
+{
+	struct atyfb_par *par = dev_id;
+	int handled = 0;
+	u32 int_cntl;
 
-static int atyfb_release(struct fb_info *info, int user)
+	spin_lock(&par->int_lock);
+
+	int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);
+
+	if (int_cntl & CRTC_VBLANK_INT) {
+		/* clear interrupt */
+		aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par);
+		par->vblank.count++;
+		if (par->vblank.pan_display) {
+			par->vblank.pan_display = 0;
+			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+		}
+		wake_up_interruptible(&par->vblank.wait);
+		handled = 1;
+	}
+
+	spin_unlock(&par->int_lock);
+
+	return IRQ_RETVAL(handled);
+}
+
+static int aty_enable_irq(struct atyfb_par *par, int reenable)
 {
-#ifdef __sparc__
-	struct atyfb_par *par = (struct atyfb_par *) info->par;	
+	u32 int_cntl;
 
+	if (!test_and_set_bit(0, &par->irq_flags)) {
+		if (request_irq(par->irq, aty_irq, SA_SHIRQ, "atyfb", par)) {
+			clear_bit(0, &par->irq_flags);
+			return -EINVAL;
+		}
+		spin_lock_irq(&par->int_lock);
+		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+		/* clear interrupt */
+		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);
+		/* enable interrupt */
+		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);
+		spin_unlock_irq(&par->int_lock);
+	} else if (reenable) {
+		spin_lock_irq(&par->int_lock);
+		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+		if (!(int_cntl & CRTC_VBLANK_INT_EN)) {
+			printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl);
+			/* re-enable interrupt */
+			aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par );
+		}
+		spin_unlock_irq(&par->int_lock);
+	}
+
+	return 0;
+}
+
+static int aty_disable_irq(struct atyfb_par *par)
+{
+	u32 int_cntl;
+
+	if (test_and_clear_bit(0, &par->irq_flags)) {
+		if (par->vblank.pan_display) {
+			par->vblank.pan_display = 0;
+			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+		}
+		spin_lock_irq(&par->int_lock);
+		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;
+		/* disable interrupt */
+		aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par );
+		spin_unlock_irq(&par->int_lock);
+		free_irq(par->irq, par);
+	}
+
+	return 0;
+}
+
+static int atyfb_release(struct fb_info *info, int user)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	if (user) {
 		par->open--;
 		mdelay(1);
 		wait_for_idle(par);
 		if (!par->open) {
+#ifdef __sparc__
 			int was_mmaped = par->mmaped;
 
 			par->mmaped = 0;
@@ -952,21 +1612,16 @@
 				else
 					var.accel_flags |= FB_ACCELF_TEXT;
 				if (var.yres == var.yres_virtual) {
-					u32 vram =
-					    (info->fix.smem_len -
-					     (PAGE_SIZE << 2));
-					var.yres_virtual =
-					    ((vram * 8) /
-					     var.bits_per_pixel) /
-					    var.xres_virtual;
+					u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
+					var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
 					if (var.yres_virtual < var.yres)
-						var.yres_virtual =
-						    var.yres;
+						var.yres_virtual = var.yres;
 				}
 			}
-		}
-	} 
 #endif
+			aty_disable_irq(par);
+		}
+	}
 	return (0);
 }
 
@@ -976,25 +1631,67 @@
      *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
      */
 
-static int atyfb_pan_display(struct fb_var_screeninfo *var,
-			     struct fb_info *info)
+static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	u32 xres, yres, xoffset, yoffset;
 
 	xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
 	yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
+	if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
+		yres >>= 1;
 	xoffset = (var->xoffset + 7) & ~7;
 	yoffset = var->yoffset;
-	if (xoffset + xres > par->crtc.vxres
-	    || yoffset + yres > par->crtc.vyres)
+	if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres)
 		return -EINVAL;
 	info->var.xoffset = xoffset;
 	info->var.yoffset = yoffset;
+	if (par->asleep)
+		return 0;
+
 	set_off_pitch(par, info);
+	if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {
+		par->vblank.pan_display = 1;
+	} else {
+		par->vblank.pan_display = 0;
+		aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
+	}
+
 	return 0;
 }
 
+static int aty_waitforvblank(struct atyfb_par *par, u32 crtc)
+{
+	struct aty_interrupt *vbl;
+	unsigned int count;
+	int ret;
+
+	switch (crtc) {
+	case 0:
+		vbl = &par->vblank;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	ret = aty_enable_irq(par, 0);
+	if (ret)
+		return ret;
+
+	count = vbl->count;
+	ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10);
+	if (ret < 0) {
+		return ret;
+	}
+	if (ret == 0) {
+		aty_enable_irq(par, 1);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+
 #ifdef DEBUG
 #define ATYIO_CLKR		0x41545900	/* ATY\00 */
 #define ATYIO_CLKW		0x41545901	/* ATY\01 */
@@ -1004,6 +1701,8 @@
 	u8 pll_ref_div;
 	u8 mclk_fb_div;
 	u8 mclk_post_div;	/* 1,2,3,4,8 */
+	u8 mclk_fb_mult;	/* 2 or 4 */
+	u8 xclk_post_div;	/* 1,2,3,4,8 */
 	u8 vclk_fb_div;
 	u8 vclk_post_div;	/* 1,2,3,4,6,8,12 */
 	u32 dsp_xclks_per_row;	/* 0-16383 */
@@ -1017,12 +1716,14 @@
 #define ATYIO_FEATW		0x41545903	/* ATY\03 */
 #endif
 
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, struct fb_info *info)
+	u_long arg, struct fb_info *info)
 {
-#if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT))
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-#endif				/* __sparc__ || DEBUG */
 #ifdef __sparc__
 	struct fbtype fbtyp;
 #endif
@@ -1036,31 +1737,44 @@
 		fbtyp.fb_depth = info->var.bits_per_pixel;
 		fbtyp.fb_cmsize = info->cmap.len;
 		fbtyp.fb_size = info->fix.smem_len;
-		if (copy_to_user
-		    ((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp)))
+		if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp)))
 			return -EFAULT;
 		break;
-#endif				/* __sparc__ */
+#endif /* __sparc__ */
+
+	case FBIO_WAITFORVSYNC:
+		{
+			u32 crtc;
+
+			if (get_user(crtc, (__u32 __user *) arg))
+				return -EFAULT;
+
+			return aty_waitforvblank(par, crtc);
+		}
+		break;
+
 #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
 	case ATYIO_CLKR:
 		if (M64_HAS(INTEGRATED)) {
 			struct atyclk clk;
-			union aty_pll *pll = par->pll;
+			union aty_pll *pll = &(par->pll);
 			u32 dsp_config = pll->ct.dsp_config;
 			u32 dsp_on_off = pll->ct.dsp_on_off;
 			clk.ref_clk_per = par->ref_clk_per;
 			clk.pll_ref_div = pll->ct.pll_ref_div;
 			clk.mclk_fb_div = pll->ct.mclk_fb_div;
 			clk.mclk_post_div = pll->ct.mclk_post_div_real;
+			clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
+			clk.xclk_post_div = pll->ct.xclk_post_div_real;
 			clk.vclk_fb_div = pll->ct.vclk_fb_div;
 			clk.vclk_post_div = pll->ct.vclk_post_div_real;
 			clk.dsp_xclks_per_row = dsp_config & 0x3fff;
 			clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;
 			clk.dsp_precision = (dsp_config >> 20) & 7;
-			clk.dsp_on = dsp_on_off & 0x7ff;
-			clk.dsp_off = (dsp_on_off >> 16) & 0x7ff;
-			if (copy_to_user
-			    ((struct atyclk *) arg, &clk, sizeof(clk)))
+			clk.dsp_off = dsp_on_off & 0x7ff;
+			clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;
+			if (copy_to_user((struct atyclk __user *) arg, &clk,
+					 sizeof(clk)))
 				return -EFAULT;
 		} else
 			return -EINVAL;
@@ -1068,40 +1782,34 @@
 	case ATYIO_CLKW:
 		if (M64_HAS(INTEGRATED)) {
 			struct atyclk clk;
-			union aty_pll *pll = par->pll;
-			if (copy_from_user
-			    (&clk, (struct atyclk *) arg, sizeof(clk)))
+			union aty_pll *pll = &(par->pll);
+			if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk)))
 				return -EFAULT;
 			par->ref_clk_per = clk.ref_clk_per;
 			pll->ct.pll_ref_div = clk.pll_ref_div;
 			pll->ct.mclk_fb_div = clk.mclk_fb_div;
 			pll->ct.mclk_post_div_real = clk.mclk_post_div;
+			pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
+			pll->ct.xclk_post_div_real = clk.xclk_post_div;
 			pll->ct.vclk_fb_div = clk.vclk_fb_div;
 			pll->ct.vclk_post_div_real = clk.vclk_post_div;
-			pll->ct.dsp_config =
-			    (clk.
-			     dsp_xclks_per_row & 0x3fff) | ((clk.
-							     dsp_loop_latency
-							     & 0xf) << 16)
-			    | ((clk.dsp_precision & 7) << 20);
-			pll->ct.dsp_on_off =
-			    (clk.
-			     dsp_on & 0x7ff) | ((clk.
-						 dsp_off & 0x7ff) << 16);
-			aty_calc_pll_ct(info, &pll->ct);
+			pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
+				((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20);
+			pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16);
+			/*aty_calc_pll_ct(info, &pll->ct);*/
 			aty_set_pll_ct(info, pll);
 		} else
 			return -EINVAL;
 		break;
 	case ATYIO_FEATR:
-		if (get_user(par->features, (u32 *) arg))
+		if (get_user(par->features, (u32 __user *) arg))
 			return -EFAULT;
 		break;
 	case ATYIO_FEATW:
-		if (put_user(par->features, (u32 *) arg))
+		if (put_user(par->features, (u32 __user *) arg))
 			return -EFAULT;
 		break;
-#endif				/* DEBUG && CONFIG_FB_ATY_CT */
+#endif /* DEBUG && CONFIG_FB_ATY_CT */
 	default:
 		return -EINVAL;
 	}
@@ -1118,8 +1826,7 @@
 }
 
 #ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
+static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	unsigned int size, page, map_size = 0;
@@ -1243,83 +1950,22 @@
 				info->var.yoffset = atyfb_save.yoffset;
 				set_off_pitch(par, info);
 			}
+			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);
 			break;
 		}
 	}
 }
-#endif				/* __sparc__ */
-
+#endif /* __sparc__ */
 
 
-#ifdef CONFIG_PMAC_PBOOK
 
-static struct fb_info *first_display = NULL;
+#if defined(CONFIG_PM) && defined(CONFIG_PCI)
 
 /* Power management routines. Those are used for PowerBook sleep.
- *
- * It appears that Rage LT and Rage LT Pro have different power
- * management registers. There's is some confusion about which
- * chipID is a Rage LT or LT pro :(
  */
-static int aty_power_mgmt_LT(int sleep, struct atyfb_par *par)
-{
-	unsigned int pm;
-	int timeout;
-
-	pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
-	aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
-	pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-
-	timeout = 200000;
-	if (sleep) {
-		/* Sleep */
-		pm &= ~PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-		udelay(10);
-		pm &= ~(PWR_BLON | AUTO_PWR_UP);
-		pm |= SUSPEND_NOW;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
-		do {
-			pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-			udelay(10);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) !=
-			 PWR_MGT_STATUS_SUSPEND);
-	} else {
-		/* Wakeup */
-		pm &= ~PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-		udelay(10);
-		pm |= (PWR_BLON | AUTO_PWR_UP);
-		pm &= ~SUSPEND_NOW;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, par);
-		do {
-			pm = aty_ld_le32(POWER_MANAGEMENT_LG, par);
-			udelay(10);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
-	}
-	mdelay(500);
-
-	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
-}
-
-static int aty_power_mgmt_LTPro(int sleep, struct atyfb_par *par)
+static int aty_power_mgmt(int sleep, struct atyfb_par *par)
 {
-	unsigned int pm;
+	u32 pm;
 	int timeout;
 
 	pm = aty_ld_lcd(POWER_MANAGEMENT, par);
@@ -1327,7 +1973,7 @@
 	aty_st_lcd(POWER_MANAGEMENT, pm, par);
 	pm = aty_ld_lcd(POWER_MANAGEMENT, par);
 
-	timeout = 200;
+	timeout = 2000;
 	if (sleep) {
 		/* Sleep */
 		pm &= ~PWR_MGT_ON;
@@ -1346,8 +1992,7 @@
 			mdelay(1);
 			if ((--timeout) == 0)
 				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) !=
-			 PWR_MGT_STATUS_SUSPEND);
+		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
 	} else {
 		/* Wakeup */
 		pm &= ~PWR_MGT_ON;
@@ -1368,88 +2013,92 @@
 				break;
 		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
 	}
+	mdelay(500);
 
-	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
+	return timeout ? -1 : 0;
 }
 
-static int aty_power_mgmt(int sleep, struct atyfb_par *par)
+static int atyfb_pci_suspend(struct pci_dev *pdev, u32 state)
 {
-	return M64_HAS(LT_SLEEP) ? aty_power_mgmt_LT(sleep, par)
-	    : aty_power_mgmt_LTPro(sleep, par);
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+#ifdef CONFIG_PPC_PMAC
+	/* HACK ALERT ! Once I find a proper way to say to each driver
+	 * individually what will happen with it's PCI slot, I'll change
+	 * that. On laptops, the AGP slot is just unclocked, so D2 is
+	 * expected, while on desktops, the card is powered off
+	 */
+	if (state >= 3)
+		state = 2;
+#endif /* CONFIG_PPC_PMAC */
+
+	if (state != 2 || state == pdev->dev.power_state)
+		return 0;
+
+	acquire_console_sem();
+
+	fb_set_suspend(info, 1);
+
+	/* Idle & reset engine */
+	wait_for_idle(par);
+	aty_reset_engine(par);
+
+	/* Blank display and LCD */
+	atyfb_blank(VESA_POWERDOWN + 1, info);
+
+	par->asleep = 1;
+	par->lock_blank = 1;
+
+	/* Set chip to "suspend" mode */
+	if (aty_power_mgmt(1, par)) {
+		par->asleep = 0;
+		par->lock_blank = 0;
+		atyfb_blank(0, info);
+		fb_set_suspend(info, 0);
+		release_console_sem();
+		return -EIO;
+	}
+
+	release_console_sem();
+
+	pdev->dev.power_state = state;
+
+	return 0;
 }
 
-/*
- * Save the contents of the frame buffer when we go to sleep,
- * and restore it when we wake up again.
- */
-static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
+static int atyfb_pci_resume(struct pci_dev *pdev)
 {
-	struct fb_info *info;
-	struct atyfb_par *par; 
-	int result;
+	struct fb_info *info = pci_get_drvdata(pdev);
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
 
-	result = PBOOK_SLEEP_OK;
+	if (pdev->dev.power_state == 0)
+		return 0;
 
-	for (info = first_display; info != NULL; info = par->next) {
-		int nb;
+	acquire_console_sem();
 
-		par = (struct atyfb_par *) info->par;
-		nb = info->var.yres * info->fix.line_length;
-
-		switch (when) {
-		case PBOOK_SLEEP_REQUEST:
-			par->save_framebuffer = vmalloc(nb);
-			if (par->save_framebuffer == NULL)
-				return PBOOK_SLEEP_REFUSE;
-			break;
-		case PBOOK_SLEEP_REJECT:
-			if (par->save_framebuffer) {
-				vfree(par->save_framebuffer);
-				par->save_framebuffer = NULL;
-			}
-			break;
-		case PBOOK_SLEEP_NOW:
-			if (par->blitter_may_be_busy)
-				wait_for_idle(par);
-			/* Stop accel engine (stop bus mastering) */
-			if (par->accel_flags & FB_ACCELF_TEXT)
-				aty_reset_engine(par);
-
-			/* Backup fb content */
-			if (par->save_framebuffer)
-				memcpy_fromio(par->save_framebuffer,
-					      (void *) info->screen_base, nb);
-
-			/* Blank display and LCD */
-			atyfb_blank(VESA_POWERDOWN + 1, info);
-
-			/* Set chip to "suspend" mode */
-			result = aty_power_mgmt(1, par);
-			break;
-		case PBOOK_WAKE:
-			/* Wakeup chip */
-			result = aty_power_mgmt(0, par);
-
-			/* Restore fb content */
-			if (par->save_framebuffer) {
-				memcpy_toio((void *) info->screen_base,
-					    par->save_framebuffer, nb);
-				vfree(par->save_framebuffer);
-				par->save_framebuffer = NULL;
-			}
-			/* Restore display */
-			atyfb_set_par(info);
-			atyfb_blank(0, info);
-			break;
-		}
-	}
-	return result;
+	if (pdev->dev.power_state == 2)
+		aty_power_mgmt(0, par);
+	par->asleep = 0;
+
+	/* Restore display */
+	atyfb_set_par(info);
+
+	/* Refresh */
+	fb_set_suspend(info, 0);
+
+	/* Unblank */
+	par->lock_blank = 0;
+	atyfb_blank(0, info);
+
+	release_console_sem();
+
+	pdev->dev.power_state = 0;
+
+	return 0;
 }
 
-static struct pmu_sleep_notifier aty_sleep_notifier = {
-	aty_sleep_notify, SLEEP_LEVEL_VIDEO,
-};
-#endif				/* CONFIG_PMAC_PBOOK */
+#endif /*  defined(CONFIG_PM) && defined(CONFIG_PCI) */
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 
@@ -1489,9 +2138,34 @@
 	aty_set_backlight_enable,
 	aty_set_backlight_level
 };
-#endif				/* CONFIG_PMAC_BACKLIGHT */
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
+static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
+{
+	const int ragepro_tbl[] = {
+		44, 50, 55, 66, 75, 80, 100
+	};
+	const int ragexl_tbl[] = {
+		50, 66, 75, 83, 90, 95, 100, 105,
+		110, 115, 120, 125, 133, 143, 166
+	};
+	const int *refresh_tbl;
+	int i, size;
+
+	if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
+		refresh_tbl = ragexl_tbl;
+		size = sizeof(ragexl_tbl)/sizeof(int);
+	} else {
+		refresh_tbl = ragepro_tbl;
+		size = sizeof(ragepro_tbl)/sizeof(int);
+	}
 
+	for (i=0; i < size; i++) {
+		if (xclk < refresh_tbl[i])
+		break;
+	}
+	par->mem_refresh_rate = i;
+}
 
     /*
      *  Initialisation
@@ -1502,37 +2176,36 @@
 static int __init aty_init(struct fb_info *info, const char *name)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	const char *chipname = NULL, *ramname = NULL, *xtal;
-	int j, pll, mclk, gtb_memsize;
+	const char *ramname = NULL, *xtal;
+	int gtb_memsize;
 	struct fb_var_screeninfo var;
-	u32 chip_id, i;
-	u16 type;
-	u8 rev;
+	u8 pll_ref_div;
+	u32 i;
 #if defined(CONFIG_PPC)
 	int sense;
 #endif
-	u8 pll_ref_div;
+
+	init_waitqueue_head(&par->vblank.wait);
+	spin_lock_init(&par->int_lock);
 
 	par->aty_cmap_regs =
 	    (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0);
-	chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
-	type = chip_id & CFG_CHIP_TYPE;
-	rev = (chip_id & CFG_CHIP_REV) >> 24;
-	for (j = 0; j < (sizeof(aty_chips) / sizeof(*aty_chips)); j++)
-		if (type == aty_chips[j].chip_type &&
-		    (rev & aty_chips[j].rev_mask) ==
-		    aty_chips[j].rev_val) {
-			chipname = aty_chips[j].name;
-			pll = aty_chips[j].pll;
-			mclk = aty_chips[j].mclk;
-			par->features = aty_chips[j].features;
-			goto found;
-		}
-	printk("atyfb: Unknown mach64 0x%04x rev 0x%04x\n", type, rev);
-	return 0;
 
-      found:
-	printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, type, rev);
+	if (pll)
+		par->pll_limits.pll_max = pll;
+	if (mclk)
+		par->pll_limits.mclk = mclk;
+	if (xclk)
+		par->pll_limits.xclk = xclk;
+
+	aty_calc_mem_refresh(par, par->pll_limits.xclk);
+	par->pll_per = 1000000/par->pll_limits.pll_max;
+	par->mclk_per = 1000000/par->pll_limits.mclk;
+	par->xclk_per = 1000000/par->pll_limits.xclk;
+
+	par->ref_clk_per = 1000000000000ULL / 14318180;
+	xtal = "14.31818";
+
 #ifdef CONFIG_FB_ATY_GX
 	if (!M64_HAS(INTEGRATED)) {
 		u32 stat0;
@@ -1549,9 +2222,7 @@
 		if (dac_type == 0x07)
 			dac_subtype = DAC_ATT20C408;
 		else
-			dac_subtype =
-			    (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) |
-			    dac_type;
+			dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, par) & 0xF0) | dac_type;
 #else
 		dac_type = DAC_IBMRGB514;
 		dac_subtype = DAC_IBMRGB514;
@@ -1570,8 +2241,7 @@
 			par->dac_ops = &aty_dac_att21c498;
 			break;
 		default:
-			printk
-			    (" atyfb_set_par: DAC type not implemented yet!\n");
+			PRINTKI("aty_init: DAC type not implemented yet!\n");
 			par->dac_ops = &aty_dac_unsupported;
 			break;
 		}
@@ -1592,33 +2262,30 @@
 			par->pll_ops = &aty_pll_ibm514;
 			break;
 		default:
-			printk
-			    (" atyfb_set_par: CLK type not implemented yet!");
+			PRINTKI("aty_init: CLK type not implemented yet!");
 			par->pll_ops = &aty_pll_unsupported;
 			break;
 		}
 	}
-#endif				/* CONFIG_FB_ATY_GX */
+#endif /* CONFIG_FB_ATY_GX */
 #ifdef CONFIG_FB_ATY_CT
 	if (M64_HAS(INTEGRATED)) {
+		par->dac_ops = &aty_dac_ct;
+		par->pll_ops = &aty_pll_ct;
 		par->bus_type = PCI;
 		par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
 		ramname = aty_ct_ram[par->ram_type];
-		par->dac_ops = &aty_dac_ct;
-		par->pll_ops = &aty_pll_ct;
+
 		/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
-		if (mclk == 67 && par->ram_type < SDRAM)
-			mclk = 63;
+		if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
+			par->pll_limits.mclk = 63;
 	}
-#endif				/* CONFIG_FB_ATY_CT */
 
-	par->ref_clk_per = 1000000000000ULL / 14318180;
-	xtal = "14.31818";
 	if (M64_HAS(GTB_DSP)
-	    && (pll_ref_div = aty_ld_pll(PLL_REF_DIV, par))) {
+	    && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) {
 		int diff1, diff2;
-		diff1 = 510 * 14 / pll_ref_div - pll;
-		diff2 = 510 * 29 / pll_ref_div - pll;
+		diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max;
+		diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max;
 		if (diff1 < 0)
 			diff1 = -diff1;
 		if (diff2 < 0)
@@ -1628,6 +2295,12 @@
 			xtal = "29.498928";
 		}
 	}
+#endif /* CONFIG_FB_ATY_CT */
+
+	/* save previous video mode */
+	aty_get_crtc(par, &saved_crtc);
+	if(par->pll_ops->get_pll)
+		par->pll_ops->get_pll(info, &saved_pll);
 
 	i = aty_ld_le32(MEM_CNTL, par);
 	gtb_memsize = M64_HAS(GTB_DSP);
@@ -1682,8 +2355,8 @@
 			info->fix.smem_len += 0x400000;
 	}
 
-	if (default_vram) {
-		info->fix.smem_len = default_vram * 1024;
+	if (vram) {
+		info->fix.smem_len = vram * 1024;
 		i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
 		if (info->fix.smem_len <= 0x80000)
 			i |= MEM_SIZE_512K;
@@ -1701,7 +2374,7 @@
 	}
 
 	/*
-	 *  Reg Block 0 (CT-compatible block) is at mmio_start 
+	 *  Reg Block 0 (CT-compatible block) is at mmio_start
 	 *  Reg Block 1 (multimedia extensions) is at mmio_start - 0x400
 	 */
 	if (M64_HAS(GX)) {
@@ -1711,78 +2384,74 @@
 		info->fix.mmio_len = 0x400;
 		info->fix.accel = FB_ACCEL_ATI_MACH64CT;
 	} else if (M64_HAS(VT)) {
-		info->fix.mmio_start = -0x400;
+		info->fix.mmio_start -= 0x400;
 		info->fix.mmio_len = 0x800;
 		info->fix.accel = FB_ACCEL_ATI_MACH64VT;
-	} else {		/* if (M64_HAS(GT)) */
-
-		info->fix.mmio_start = -0x400;
+	} else {/* GT */
+		info->fix.mmio_start -= 0x400;
 		info->fix.mmio_len = 0x800;
 		info->fix.accel = FB_ACCEL_ATI_MACH64GT;
 	}
 
-	if (default_pll)
-		pll = default_pll;
-	if (default_mclk)
-		mclk = default_mclk;
-
-	printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
-	       info->fix.smem_len ==
-	       0x80000 ? 512 : (info->fix.smem_len >> 20),
-	       info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname,
-	       xtal, pll, mclk);
-
-	if (mclk < 44)
-		par->mem_refresh_rate = 0;	/* 000 = 10 Mhz - 43 Mhz */
-	else if (mclk < 50)
-		par->mem_refresh_rate = 1;	/* 001 = 44 Mhz - 49 Mhz */
-	else if (mclk < 55)
-		par->mem_refresh_rate = 2;	/* 010 = 50 Mhz - 54 Mhz */
-	else if (mclk < 66)
-		par->mem_refresh_rate = 3;	/* 011 = 55 Mhz - 65 Mhz */
-	else if (mclk < 75)
-		par->mem_refresh_rate = 4;	/* 100 = 66 Mhz - 74 Mhz */
-	else if (mclk < 80)
-		par->mem_refresh_rate = 5;	/* 101 = 75 Mhz - 79 Mhz */
-	else if (mclk < 100)
-		par->mem_refresh_rate = 6;	/* 110 = 80 Mhz - 100 Mhz */
-	else
-		par->mem_refresh_rate = 7;	/* 111 = 100 Mhz and above */
-	par->pll_per = 1000000 / pll;
-	par->mclk_per = 1000000 / mclk;
+	PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n",
+	       info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20),
+	       info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max,
+	       par->pll_limits.mclk, par->pll_limits.xclk);
 
-#ifdef DEBUG
+#if defined(DEBUG) && defined(CONFIG_ATY_CT)
 	if (M64_HAS(INTEGRATED)) {
 		int i;
-		printk
-		    ("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
-		     "DSP_CONFIG DSP_ON_OFF\n"
-		     "%08x %08x %08x %08x     %08x      %08x   %08x\n"
-		     "PLL", aty_ld_le32(BUS_CNTL, par),
-		     aty_ld_le32(DAC_CNTL, par), aty_ld_le32(MEM_CNTL,
-							     par),
-		     aty_ld_le32(EXT_MEM_CNTL, par),
-		     aty_ld_le32(CRTC_GEN_CNTL, par),
-		     aty_ld_le32(DSP_CONFIG, par), aty_ld_le32(DSP_ON_OFF,
-							       par));
-		for (i = 0; i < 16; i++)
-			printk(" %02x", aty_ld_pll(i, par));
+		printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
+		       "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n"
+		       "debug atyfb: %08x %08x %08x %08x     %08x      %08x   %08x   %08x\n"
+		       "debug atyfb: PLL",
+			aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par),
+			aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par),
+			aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par),
+			aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par));
+		for (i = 0; i < 40; i++)
+			printk(" %02x", aty_ld_pll_ct(i, par));
 		printk("\n");
 	}
 #endif
+	if(par->pll_ops->init_pll)
+		par->pll_ops->init_pll(info, &par->pll);
 
 	/*
 	 *  Last page of 8 MB (4 MB on ISA) aperture is MMIO
 	 *  FIXME: we should use the auxiliary aperture instead so we can access
 	 *  the full 8 MB of video RAM on 8 MB boards
 	 */
-	if (info->fix.smem_len == 0x800000 ||
-	    (par->bus_type == ISA 
-	     && info->fix.smem_len == 0x400000))
+
+	if (!par->aux_start &&
+		(info->fix.smem_len == 0x800000 || (par->bus_type == ISA && info->fix.smem_len == 0x400000)))
 		info->fix.smem_len -= GUI_RESERVE;
 
-	/* Clear the video memory */
-	fb_memset(info->screen_base, 0, info->fix.smem_len);
+	/*
+	 *  Disable register access through the linear aperture
+	 *  if the auxiliary aperture is used so we can access
+	 *  the full 8 MB of video RAM on 8 MB boards.
+	 */
+	if (par->aux_start)
+		aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);
+
+#ifdef CONFIG_MTRR
+	par->mtrr_aper = -1;
+	par->mtrr_reg = -1;
+	if (!nomtrr) {
+		/* Cover the whole resource. */
+		 par->mtrr_aper = mtrr_add(par->res_start, par->res_size, MTRR_TYPE_WRCOMB, 1);
+		 if (par->mtrr_aper >= 0 && !par->aux_start) {
+			/* Make a hole for mmio. */
+			par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - GUI_RESERVE,
+				GUI_RESERVE, MTRR_TYPE_UNCACHABLE, 1);
+			if (par->mtrr_reg < 0) {
+				mtrr_del(par->mtrr_aper, 0, 0);
+				par->mtrr_aper = -1;
+			}
+		 }
+	}
+#endif
 
 	info->fbops = &atyfb_ops;
 	info->pseudo_palette = pseudo_palette;
@@ -1791,18 +2460,12 @@
 #ifdef CONFIG_PMAC_BACKLIGHT
 	if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
 		/* these bits let the 101 powerbook wake up from sleep -- paulus */
-		aty_st_lcd(POWER_MANAGEMENT,
-			   aty_ld_lcd(POWER_MANAGEMENT, par)
+		aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
 			   | (USE_F32KHZ | TRISTATE_MEM_EN), par);
-	}
-	if (M64_HAS(MOBIL_BUS))
-		register_backlight_controller(&aty_backlight_controller,
-					      info, "ati");
-#endif				/* CONFIG_PMAC_BACKLIGHT */
+	} else if (M64_HAS(MOBIL_BUS))
+		register_backlight_controller(&aty_backlight_controller, info, "ati");
+#endif /* CONFIG_PMAC_BACKLIGHT */
 
-#ifdef MODULE
-	var = default_var;
-#else				/* !MODULE */
 	memset(&var, 0, sizeof(var));
 #ifdef CONFIG_PPC
 	if (_machine == _MACH_Pmac) {
@@ -1810,9 +2473,8 @@
 		 *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
 		 *         applies to all Mac video cards
 		 */
-		if (mode_option) {
-			if (!mac_find_mode
-			    (&var, info, mode_option, 8))
+		if (mode) {
+			if (!mac_find_mode(&var, info, mode, 8))
 				var = default_var;
 		} else {
 			if (default_vmode == VMODE_CHOOSE) {
@@ -1828,483 +2490,950 @@
 				else
 					default_vmode = VMODE_640_480_67;
 				sense = read_aty_sense(par);
-				printk(KERN_INFO
-				       "atyfb: monitor sense=%x, mode %d\n",
-				       sense,
-				       mac_map_monitor_sense(sense));
+				PRINTKI("monitor sense=%x, mode %d\n",
+					sense,  mac_map_monitor_sense(sense));
 			}
-			if (default_vmode <= 0
-			    || default_vmode > VMODE_MAX)
+			if (default_vmode <= 0 || default_vmode > VMODE_MAX)
 				default_vmode = VMODE_640_480_60;
-			if (default_cmode < CMODE_8
-			    || default_cmode > CMODE_32)
+			if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
 				default_cmode = CMODE_8;
-			if (mac_vmode_to_var
-			    (default_vmode, default_cmode, &var))
+			if (mac_vmode_to_var(default_vmode, default_cmode, &var))
 				var = default_var;
 		}
 	} else
-	    if (!fb_find_mode
-		(&var, info, mode_option, NULL, 0, NULL, 8))
-		var = default_var;
-#else				/* !CONFIG_PPC */
-#ifdef __sparc__
-	if (mode_option) {
-		if (!fb_find_mode
-		    (&var, info, mode_option, NULL, 0, NULL, 8))
-			var = default_var;
-	} else
-		var = default_var;
-#else
-	if (!fb_find_mode
-	    (&var, info, mode_option, NULL, 0, NULL, 8))
+#endif /* !CONFIG_PPC */
+	if (!fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
 		var = default_var;
-#endif				/* !__sparc__ */
-#endif				/* !CONFIG_PPC */
-#endif				/* !MODULE */
+
 	if (noaccel)
 		var.accel_flags &= ~FB_ACCELF_TEXT;
 	else
 		var.accel_flags |= FB_ACCELF_TEXT;
 
 	if (var.yres == var.yres_virtual) {
-		u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));
-		var.yres_virtual =
-		    ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
+		u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
+		var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
 		if (var.yres_virtual < var.yres)
 			var.yres_virtual = var.yres;
 	}
 
 	if (atyfb_check_var(&var, info)) {
-		printk("atyfb: can't set default video mode\n");
-		return 0;
+		PRINTKE("can't set default video mode\n");
+		goto aty_init_exit;
 	}
+
 #ifdef __sparc__
 	atyfb_save_palette(par, 0);
 #endif
 
 #ifdef CONFIG_FB_ATY_CT
-	if (curblink && M64_HAS(INTEGRATED))
-		par->cursor = aty_init_cursor(info);
-#endif				/* CONFIG_FB_ATY_CT */
+	if (!noaccel && M64_HAS(INTEGRATED))
+		aty_init_cursor(info);
+#endif /* CONFIG_FB_ATY_CT */
 	info->var = var;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
 
 	if (register_framebuffer(info) < 0)
-		return 0;
+		goto aty_init_exit;
 
 	fb_list = info;
 
-	printk("fb%d: %s frame buffer device on %s\n",
+	PRINTKI("fb%d: %s frame buffer device on %s\n",
 	       info->node, info->fix.id, name);
-	return 1;
+	return 0;
+
+aty_init_exit:
+	/* restore video mode */
+	aty_set_crtc(par, &saved_crtc);
+	par->pll_ops->set_pll(info, &saved_pll);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr_reg >= 0) {
+	    mtrr_del(par->mtrr_reg, 0, 0);
+	    par->mtrr_reg = -1;
+	}
+	if (par->mtrr_aper >= 0) {
+	    mtrr_del(par->mtrr_aper, 0, 0);
+	    par->mtrr_aper = -1;
+	}
+#endif
+	return -1;
 }
 
-int __init atyfb_do_init(void)
+#ifdef CONFIG_ATARI
+static int __init store_video_par(char *video_str, unsigned char m64_num)
 {
-#if defined(CONFIG_PCI)
-	unsigned long addr, res_start, res_size;
-	struct atyfb_par *default_par;
-	struct pci_dev *pdev = NULL;
-	struct fb_info *info;
-	int i;
+	char *p;
+	unsigned long vmembase, size, guiregbase;
+
+	PRINTKI("store_video_par() '%s' \n", video_str);
+
+	if (!(p = strsep(&video_str, ";")) || !*p)
+		goto mach64_invalid;
+	vmembase = simple_strtoul(p, NULL, 0);
+	if (!(p = strsep(&video_str, ";")) || !*p)
+		goto mach64_invalid;
+	size = simple_strtoul(p, NULL, 0);
+	if (!(p = strsep(&video_str, ";")) || !*p)
+		goto mach64_invalid;
+	guiregbase = simple_strtoul(p, NULL, 0);
+
+	phys_vmembase[m64_num] = vmembase;
+	phys_size[m64_num] = size;
+	phys_guiregbase[m64_num] = guiregbase;
+	PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
+	       guiregbase);
+	return 0;
+
+      mach64_invalid:
+	phys_vmembase[m64_num] = 0;
+	return -1;
+}
+#endif /* CONFIG_ATARI */
+
+    /*
+     *  Blank the display.
+     */
+
+static int atyfb_blank(int blank, struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u8 gen_cntl;
+
+	if (par->lock_blank || par->asleep)
+		return 0;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if ((_machine == _MACH_Pmac) && blank)
+		set_backlight_enable(0);
+#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+	if (par->lcd_table && blank &&
+	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		pm &= ~PWR_BLON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+	}
+#endif
+
+	gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par);
+	if (blank > 0)
+		switch (blank - 1) {
+		case VESA_NO_BLANKING:
+			gen_cntl |= 0x40;
+			break;
+		case VESA_VSYNC_SUSPEND:
+			gen_cntl |= 0x8;
+			break;
+		case VESA_HSYNC_SUSPEND:
+			gen_cntl |= 0x4;
+			break;
+		case VESA_POWERDOWN:
+			gen_cntl |= 0x4c;
+			break;
+	} else
+		gen_cntl &= ~(0x4c);
+	aty_st_8(CRTC_GEN_CNTL, gen_cntl, par);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if ((_machine == _MACH_Pmac) && !blank)
+		set_backlight_enable(1);
+#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
+	if (par->lcd_table && !blank &&
+	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+		u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
+		pm |= PWR_BLON;
+		aty_st_lcd(POWER_MANAGEMENT, pm, par);
+	}
+#endif
+
+	return 0;
+}
+
+static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue,
+		       const struct atyfb_par *par)
+{
+#ifdef CONFIG_ATARI
+	out_8(&par->aty_cmap_regs->windex, regno);
+	out_8(&par->aty_cmap_regs->lut, red);
+	out_8(&par->aty_cmap_regs->lut, green);
+	out_8(&par->aty_cmap_regs->lut, blue);
+#else
+	writeb(regno, &par->aty_cmap_regs->windex);
+	writeb(red, &par->aty_cmap_regs->lut);
+	writeb(green, &par->aty_cmap_regs->lut);
+	writeb(blue, &par->aty_cmap_regs->lut);
+#endif
+}
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     *  !! 4 & 8 =  PSEUDO, > 8 = DIRECTCOLOR
+     */
+
+static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+	u_int transp, struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	int i, depth;
+	u32 *pal = info->pseudo_palette;
+
+	depth = info->var.bits_per_pixel;
+	if (depth == 16)
+		depth = (info->var.green.length == 5) ? 15 : 16;
+
+	if (par->asleep)
+		return 0;
+
+	if (regno > 255 ||
+	    (depth == 16 && regno > 63) ||
+	    (depth == 15 && regno > 31))
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	par->palette[regno].red = red;
+	par->palette[regno].green = green;
+	par->palette[regno].blue = blue;
+
+	if (regno < 16) {
+		switch (depth) {
+		case 15:
+			pal[regno] = (regno << 10) | (regno << 5) | regno;
+			break;
+		case 16:
+			pal[regno] = (regno << 11) | (regno << 5) | regno;
+			break;
+		case 24:
+			pal[regno] = (regno << 16) | (regno << 8) | regno;
+			break;
+		case 32:
+			i = (regno << 8) | regno;
+			pal[regno] = (i << 16) | i;
+			break;
+		}
+	}
+
+	i = aty_ld_8(DAC_CNTL, par) & 0xfc;
+	if (M64_HAS(EXTRA_BRIGHT))
+		i |= 0x2; /* DAC_CNTL | 0x2 turns off the extra brightness for gt */
+	aty_st_8(DAC_CNTL, i, par);
+	aty_st_8(DAC_MASK, 0xff, par);
+
+	if (M64_HAS(INTEGRATED)) {
+		if (depth == 16) {
+			if (regno < 32)
+				aty_st_pal(regno << 3, red,
+					   par->palette[regno<<1].green,
+					   blue, par);
+			red = par->palette[regno>>1].red;
+			blue = par->palette[regno>>1].blue;
+			regno <<= 2;
+		} else if (depth == 15) {
+			regno <<= 3;
+			for(i = 0; i < 8; i++) {
+			    aty_st_pal(regno + i, red, green, blue, par);
+			}
+		}
+	}
+	aty_st_pal(regno, red, green, blue, par);
+
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+
 #ifdef __sparc__
-	extern void (*prom_palette) (int);
+
+extern void (*prom_palette) (int);
+
+static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
+			struct fb_info *info, unsigned long addr)
+{
 	extern int con_is_present(void);
+
+	struct atyfb_par *par = info->par;
 	struct pcidev_cookie *pcp;
 	char prop[128];
-	int node, len, j;
+	int node, len, i, j, ret;
 	u32 mem, chip_id;
-#else
-	u16 tmp;
-#endif
 
-#ifdef __sparc__
 	/* Do not attach when we have a serial console. */
 	if (!con_is_present())
 		return -ENXIO;
-#endif
 
-	while ((pdev =
-		pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
-		if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
-			struct resource *rp;
-
-			for (i =
-			     sizeof(aty_chips) / sizeof(*aty_chips) - 1;
-			     i >= 0; i--)
-				if (pdev->device == aty_chips[i].pci_id)
-					break;
-			if (i < 0)
-				continue;
+	/*
+	 * Map memory-mapped registers.
+	 */
+	par->ati_regbase = (void *)addr + 0x7ffc00UL;
+	info->fix.mmio_start = addr + 0x7ffc00UL;
 
-			rp = &pdev->resource[0];
-			if (rp->flags & IORESOURCE_IO)
-				rp = &pdev->resource[1];
-			addr = rp->start;
-			if (!addr)
-				continue;
+	/*
+	 * Map in big-endian aperture.
+	 */
+	info->screen_base = (char *) (addr + 0x800000UL);
+	info->fix.smem_start = addr + 0x800000UL;
 
-			res_start = rp->start;
-			res_size = rp->end - rp->start + 1;
-			if (!request_mem_region
-			    (res_start, res_size, "atyfb"))
-				continue;
+	/*
+	 * Figure mmap addresses from PCI config space.
+	 * Split Framebuffer in big- and little-endian halfs.
+	 */
+	for (i = 0; i < 6 && pdev->resource[i].start; i++)
+		/* nothing */ ;
+	j = i + 4;
 
-			info =
-			    kmalloc(sizeof(struct fb_info), GFP_ATOMIC);
-			if (!info) {
-				printk
-				    ("atyfb_init: can't alloc fb_info\n");
-				return -ENXIO;
-			}
-			memset(info, 0, sizeof(struct fb_info));
+	par->mmap_map = kmalloc(j * sizeof(*par->mmap_map), GFP_ATOMIC);
+	if (!par->mmap_map) {
+		PRINTKE("atyfb_setup_sparc() can't alloc mmap_map\n");
+		return -ENOMEM;
+	}
+	memset(par->mmap_map, 0, j * sizeof(*par->mmap_map));
 
-			default_par =
-			    kmalloc(sizeof(struct atyfb_par), GFP_ATOMIC);
-			if (!default_par) {
-				printk
-				    ("atyfb_init: can't alloc atyfb_par\n");
-				kfree(info);
-				return -ENXIO;
-			}
-			memset(default_par, 0, sizeof(struct atyfb_par));
+	for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
+		struct resource *rp = &pdev->resource[i];
+		int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
+		unsigned long base;
+		u32 size, pbase;
 
-			info->fix = atyfb_fix;
-			info->par = default_par;
-			info->device = &pdev->dev;
-#ifdef __sparc__
-			/*
-			 * Map memory-mapped registers.
-			 */
-			default_par->ati_regbase = addr + 0x7ffc00UL;
-			info->fix.mmio_start = addr + 0x7ffc00UL;
+		base = rp->start;
 
-			/*
-			 * Map in big-endian aperture.
-			 */
-			info->screen_base = (char *) (addr + 0x800000UL);
-			info->fix.smem_start = addr + 0x800000UL;
+		io = (rp->flags & IORESOURCE_IO);
 
-			/*
-			 * Figure mmap addresses from PCI config space.
-			 * Split Framebuffer in big- and little-endian halfs.
-			 */
-			for (i = 0; i < 6 && pdev->resource[i].start; i++)
-				/* nothing */ ;
-			j = i + 4;
-
-			default_par->mmap_map =
-			    kmalloc(j * sizeof(*default_par->mmap_map),
-				    GFP_ATOMIC);
-			if (!default_par->mmap_map) {
-				printk
-				    ("atyfb_init: can't alloc mmap_map\n");
-				kfree(default_par);
-				kfree(info);
-				release_mem_region(res_start, res_size);
-				return -ENXIO;
+		size = rp->end - base + 1;
+
+		pci_read_config_dword(pdev, breg, &pbase);
+
+		if (io)
+			size &= ~1;
+
+		/*
+		 * Map the framebuffer a second time, this time without
+		 * the braindead _PAGE_IE setting. This is used by the
+		 * fixed Xserver, but we need to maintain the old mapping
+		 * to stay compatible with older ones...
+		 */
+		if (base == addr) {
+			par->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
+			par->mmap_map[j].poff = base & PAGE_MASK;
+			par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+			par->mmap_map[j].prot_mask = _PAGE_CACHE;
+			par->mmap_map[j].prot_flag = _PAGE_E;
+			j++;
+		}
+
+		/*
+		 * Here comes the old framebuffer mapping with _PAGE_IE
+		 * set for the big endian half of the framebuffer...
+		 */
+		if (base == addr) {
+			par->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
+			par->mmap_map[j].poff = (base + 0x800000) & PAGE_MASK;
+			par->mmap_map[j].size = 0x800000;
+			par->mmap_map[j].prot_mask = _PAGE_CACHE;
+			par->mmap_map[j].prot_flag = _PAGE_E | _PAGE_IE;
+			size -= 0x800000;
+			j++;
+		}
+
+		par->mmap_map[j].voff = pbase & PAGE_MASK;
+		par->mmap_map[j].poff = base & PAGE_MASK;
+		par->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+		par->mmap_map[j].prot_mask = _PAGE_CACHE;
+		par->mmap_map[j].prot_flag = _PAGE_E;
+		j++;
+	}
+
+	if((ret = correct_chipset(par)))
+		return ret;
+
+	if (IS_XL(pdev->device)) {
+		/*
+		 * Fix PROMs idea of MEM_CNTL settings...
+		 */
+		mem = aty_ld_le32(MEM_CNTL, par);
+		chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
+		if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) {
+			switch (mem & 0x0f) {
+			case 3:
+				mem = (mem & ~(0x0f)) | 2;
+				break;
+			case 7:
+				mem = (mem & ~(0x0f)) | 3;
+				break;
+			case 9:
+				mem = (mem & ~(0x0f)) | 4;
+				break;
+			case 11:
+				mem = (mem & ~(0x0f)) | 5;
+				break;
+			default:
+				break;
 			}
-			memset(default_par->mmap_map, 0,
-			       j * sizeof(*default_par->mmap_map));
+			if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM)
+				mem &= ~(0x00700000);
+		}
+		mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
+		aty_st_le32(MEM_CNTL, mem, par);
+	}
 
-			for (i = 0, j = 2;
-			     i < 6 && pdev->resource[i].start; i++) {
-				struct resource *rp = &pdev->resource[i];
-				int io, breg =
-				    PCI_BASE_ADDRESS_0 + (i << 2);
-				unsigned long base;
-				u32 size, pbase;
+	/*
+	 * If this is the console device, we will set default video
+	 * settings to what the PROM left us with.
+	 */
+	node = prom_getchild(prom_root_node);
+	node = prom_searchsiblings(node, "aliases");
+	if (node) {
+		len = prom_getproperty(node, "screen", prop, sizeof(prop));
+		if (len > 0) {
+			prop[len] = '\0';
+			node = prom_finddevice(prop);
+		} else
+			node = 0;
+	}
 
-				base = rp->start;
+	pcp = pdev->sysdata;
+	if (node == pcp->prom_node) {
+		struct fb_var_screeninfo *var = &default_var;
+		unsigned int N, P, Q, M, T, R;
+		u32 v_total, h_total;
+		struct crtc crtc;
+		u8 pll_regs[16];
+		u8 clock_cntl;
+
+		crtc.vxres = prom_getintdefault(node, "width", 1024);
+		crtc.vyres = prom_getintdefault(node, "height", 768);
+		var->bits_per_pixel = prom_getintdefault(node, "depth", 8);
+		var->xoffset = var->yoffset = 0;
+		crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);
+		crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);
+		crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);
+		crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);
+		crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+		aty_crtc_to_var(&crtc, var);
 
-				io = (rp->flags & IORESOURCE_IO);
+		h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+		v_total = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
 
-				size = rp->end - base + 1;
+		/*
+		 * Read the PLL to figure actual Refresh Rate.
+		 */
+		clock_cntl = aty_ld_8(CLOCK_CNTL, par);
+		/* DPRINTK("CLOCK_CNTL %02x\n", clock_cntl); */
+		for (i = 0; i < 16; i++)
+			pll_regs[i] = aty_ld_pll_ct(i, par);
 
-				pci_read_config_dword(pdev, breg, &pbase);
+		/*
+		 * PLL Reference Divider M:
+		 */
+		M = pll_regs[2];
 
-				if (io)
-					size &= ~1;
+		/*
+		 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
+		 */
+		N = pll_regs[7 + (clock_cntl & 3)];
 
-				/*
-				 * Map the framebuffer a second time, this time without
-				 * the braindead _PAGE_IE setting. This is used by the
-				 * fixed Xserver, but we need to maintain the old mapping
-				 * to stay compatible with older ones...
-				 */
-				if (base == addr) {
-					default_par->mmap_map[j].voff =
-					    (pbase +
-					     0x10000000) & PAGE_MASK;
-					default_par->mmap_map[j].poff =
-					    base & PAGE_MASK;
-					default_par->mmap_map[j].size =
-					    (size +
-					     ~PAGE_MASK) & PAGE_MASK;
-					default_par->mmap_map[j].prot_mask =
-					    _PAGE_CACHE;
-					default_par->mmap_map[j].prot_flag =
-					    _PAGE_E;
-					j++;
-				}
+		/*
+		 * PLL Post Divider P (Dependant on CLOCK_CNTL):
+		 */
+		P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
 
-				/*
-				 * Here comes the old framebuffer mapping with _PAGE_IE
-				 * set for the big endian half of the framebuffer...
-				 */
-				if (base == addr) {
-					default_par->mmap_map[j].voff =
-					    (pbase + 0x800000) & PAGE_MASK;
-					default_par->mmap_map[j].poff =
-					    (base + 0x800000) & PAGE_MASK;
-					default_par->mmap_map[j].size = 0x800000;
-					default_par->mmap_map[j].prot_mask =
-					    _PAGE_CACHE;
-					default_par->mmap_map[j].prot_flag =
-					    _PAGE_E | _PAGE_IE;
-					size -= 0x800000;
-					j++;
-				}
+		/*
+		 * PLL Divider Q:
+		 */
+		Q = N / P;
 
-				default_par->mmap_map[j].voff = pbase & PAGE_MASK;
-				default_par->mmap_map[j].poff = base & PAGE_MASK;
-				default_par->mmap_map[j].size =
-				    (size + ~PAGE_MASK) & PAGE_MASK;
-				default_par->mmap_map[j].prot_mask = _PAGE_CACHE;
-				default_par->mmap_map[j].prot_flag = _PAGE_E;
-				j++;
-			}
+		/*
+		 * Target Frequency:
+		 *
+		 *      T * M
+		 * Q = -------
+		 *      2 * R
+		 *
+		 * where R is XTALIN (= 14318 or 29498 kHz).
+		 */
+		if (IS_XL(pdev->device))
+			R = 29498;
+		else
+			R = 14318;
 
-			if (pdev->device != XL_CHIP_ID) {
-				/*
-				 * Fix PROMs idea of MEM_CNTL settings...
-				 */
-				mem = aty_ld_le32(MEM_CNTL, default_par);
-				chip_id = aty_ld_le32(CONFIG_CHIP_ID, default_par);
-				if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID)
-				    && !((chip_id >> 24) & 1)) {
-					switch (mem & 0x0f) {
-					case 3:
-						mem = (mem & ~(0x0f)) | 2;
-						break;
-					case 7:
-						mem = (mem & ~(0x0f)) | 3;
-						break;
-					case 9:
-						mem = (mem & ~(0x0f)) | 4;
-						break;
-					case 11:
-						mem = (mem & ~(0x0f)) | 5;
-						break;
-					default:
-						break;
-					}
-					if ((aty_ld_le32(CONFIG_STAT0, default_par) & 7) >= SDRAM)
-						mem &= ~(0x00700000);
-				}
-				mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
-				aty_st_le32(MEM_CNTL, mem, default_par);
-			}
+		T = 2 * Q * R / M;
 
-			/*
-			 * If this is the console device, we will set default video
-			 * settings to what the PROM left us with.
-			 */
-			node = prom_getchild(prom_root_node);
-			node = prom_searchsiblings(node, "aliases");
-			if (node) {
-				len =
-				    prom_getproperty(node, "screen", prop,
-						     sizeof(prop));
-				if (len > 0) {
-					prop[len] = '\0';
-					node = prom_finddevice(prop);
+		default_var.pixclock = 1000000000 / T;
+	}
+
+	return 0;
+}
+
+#else /* __sparc__ */
+
+#ifdef __i386__
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+{
+	u32 driv_inf_tab, sig;
+	u16 lcd_ofs;
+
+	/* To support an LCD panel, we should know it's dimensions and
+	 *  it's desired pixel clock.
+	 * There are two ways to do it:
+	 *  - Check the startup video mode and calculate the panel
+	 *    size from it. This is unreliable.
+	 *  - Read it from the driver information table in the video BIOS.
+	*/
+	/* Address of driver information table is at offset 0x78. */
+	driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78));
+
+	/* Check for the driver information table signature. */
+	sig = (*(u32 *)driv_inf_tab);
+	if ((sig == 0x54504c24) || /* Rage LT pro */
+		(sig == 0x544d5224) || /* Rage mobility */
+		(sig == 0x54435824) || /* Rage XC */
+		(sig == 0x544c5824)) { /* Rage XL */
+		PRINTKI("BIOS contains driver information table.\n");
+		lcd_ofs = (*(u16 *)(driv_inf_tab + 10));
+		par->lcd_table = 0;
+		if (lcd_ofs != 0) {
+			par->lcd_table = bios_base + lcd_ofs;
+		}
+	}
+
+	if (par->lcd_table != 0) {
+		char model[24];
+		char strbuf[16];
+		char refresh_rates_buf[100];
+		int id, tech, f, i, m, default_refresh_rate;
+		char *txtcolour;
+		char *txtmonitor;
+		char *txtdual;
+		char *txtformat;
+		u16 width, height, panel_type, refresh_rates;
+		u16 *lcdmodeptr;
+		u32 format;
+		u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200};
+		/* The most important information is the panel size at
+		 * offset 25 and 27, but there's some other nice information
+		 * which we print to the screen.
+		 */
+		id = *(u8 *)par->lcd_table;
+		strncpy(model,(char *)par->lcd_table+1,24);
+		model[23]=0;
+
+		width = par->lcd_width = *(u16 *)(par->lcd_table+25);
+		height = par->lcd_height = *(u16 *)(par->lcd_table+27);
+		panel_type = *(u16 *)(par->lcd_table+29);
+		if (panel_type & 1)
+			txtcolour = "colour";
+		else
+			txtcolour = "monochrome";
+		if (panel_type & 2)
+			txtdual = "dual (split) ";
+		else
+			txtdual = "";
+		tech = (panel_type>>2) & 63;
+		switch (tech) {
+		case 0:
+			txtmonitor = "passive matrix";
+			break;
+		case 1:
+			txtmonitor = "active matrix";
+			break;
+		case 2:
+			txtmonitor = "active addressed STN";
+			break;
+		case 3:
+			txtmonitor = "EL";
+			break;
+		case 4:
+			txtmonitor = "plasma";
+			break;
+		default:
+			txtmonitor = "unknown";
+		}
+		format = *(u32 *)(par->lcd_table+57);
+		if (tech == 0 || tech == 2) {
+			switch (format & 7) {
+			case 0:
+				txtformat = "12 bit interface";
+				break;
+			case 1:
+				txtformat = "16 bit interface";
+				break;
+			case 2:
+				txtformat = "24 bit interface";
+				break;
+			default:
+				txtformat = "unkown format";
+			}
+		} else {
+			switch (format & 7) {
+			case 0:
+				txtformat = "8 colours";
+				break;
+			case 1:
+				txtformat = "512 colours";
+				break;
+			case 2:
+				txtformat = "4096 colours";
+				break;
+			case 4:
+				txtformat = "262144 colours (LT mode)";
+				break;
+			case 5:
+				txtformat = "16777216 colours";
+				break;
+			case 6:
+				txtformat = "262144 colours (FDPI-2 mode)";
+				break;
+			default:
+				txtformat = "unkown format";
+			}
+		}
+		PRINTKI("%s%s %s monitor detected: %s\n",
+			txtdual ,txtcolour, txtmonitor, model);
+		PRINTKI("       id=%d, %dx%d pixels, %s\n",
+			id, width, height, txtformat);
+		refresh_rates_buf[0] = 0;
+		refresh_rates = *(u16 *)(par->lcd_table+62);
+		m = 1;
+		f = 0;
+		for (i=0;i<16;i++) {
+			if (refresh_rates & m) {
+				if (f == 0) {
+					sprintf(strbuf, "%d", lcd_refresh_rates[i]);
+					f++;
 				} else {
-					node = 0;
+					sprintf(strbuf, ",%d", lcd_refresh_rates[i]);
 				}
+				strcat(refresh_rates_buf,strbuf);
+			}
+			m = m << 1;
+		}
+		default_refresh_rate = (*(u8 *)(par->lcd_table+61) & 0xf0) >> 4;
+		PRINTKI("       supports refresh rates [%s], default %d Hz\n",
+			refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
+		par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
+		/* We now need to determine the crtc parameters for the
+		 * lcd monitor. This is tricky, because they are not stored
+		 * individually in the BIOS. Instead, the BIOS contains a
+		 * table of display modes that work for this monitor.
+		 *
+		 * The idea is that we search for a mode of the same dimensions
+		 * as the dimensions of the lcd monitor. Say our lcd monitor
+		 * is 800x600 pixels, we search for a 800x600 monitor.
+		 * The CRTC parameters we find here are the ones that we need
+		 * to use to simulate other resolutions on the lcd screen.
+		 */
+		lcdmodeptr = (u16 *)(par->lcd_table + 64);
+		while (*lcdmodeptr != 0) {
+			u32 modeptr;
+			u16 mwidth, mheight, lcd_hsync_start, lcd_vsync_start;
+			modeptr = bios_base + *lcdmodeptr;
+
+			mwidth = *((u16 *)(modeptr+0));
+			mheight = *((u16 *)(modeptr+2));
+
+			if (mwidth == width && mheight == height) {
+				par->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
+				par->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
+				par->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
+				lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
+				par->lcd_hsync_dly = (*((u16 *)(modeptr+21)) >> 9) & 7;
+				par->lcd_hsync_len = *((u8 *)(modeptr+23)) & 63;
+
+				par->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
+				par->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
+				lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
+				par->lcd_vsync_len = (*((u16 *)(modeptr+28)) >> 11) & 31;
+
+				par->lcd_htotal = (par->lcd_htotal + 1) * 8;
+				par->lcd_hdisp = (par->lcd_hdisp + 1) * 8;
+				lcd_hsync_start = (lcd_hsync_start + 1) * 8;
+				par->lcd_hsync_len = par->lcd_hsync_len * 8;
+
+				par->lcd_vtotal++;
+				par->lcd_vdisp++;
+				lcd_vsync_start++;
+
+				par->lcd_right_margin = lcd_hsync_start - par->lcd_hdisp;
+				par->lcd_lower_margin = lcd_vsync_start - par->lcd_vdisp;
+				par->lcd_hblank_len = par->lcd_htotal - par->lcd_hdisp;
+				par->lcd_vblank_len = par->lcd_vtotal - par->lcd_vdisp;
+				break;
 			}
 
-			pcp = pdev->sysdata;
-			if (node == pcp->prom_node) {
+			lcdmodeptr++;
+		}
+		if (*lcdmodeptr == 0) {
+			PRINTKE("LCD monitor CRTC parameters not found!!!\n");
+			/* To do: Switch to CRT if possible. */
+		} else {
+			PRINTKI("       LCD CRTC parameters: %d.%d  %d %d %d %d  %d %d %d %d\n",
+				1000000 / par->lcd_pixclock, 1000000 % par->lcd_pixclock,
+				par->lcd_hdisp,
+				par->lcd_hdisp + par->lcd_right_margin,
+				par->lcd_hdisp + par->lcd_right_margin
+					+ par->lcd_hsync_dly + par->lcd_hsync_len,
+				par->lcd_htotal,
+				par->lcd_vdisp,
+				par->lcd_vdisp + par->lcd_lower_margin,
+				par->lcd_vdisp + par->lcd_lower_margin + par->lcd_vsync_len,
+				par->lcd_vtotal);
+			PRINTKI("                          : %d %d %d %d %d %d %d %d %d\n",
+				par->lcd_pixclock,
+				par->lcd_hblank_len - (par->lcd_right_margin +
+					par->lcd_hsync_dly + par->lcd_hsync_len),
+				par->lcd_hdisp,
+				par->lcd_right_margin,
+				par->lcd_hsync_len,
+				par->lcd_vblank_len - (par->lcd_lower_margin + par->lcd_vsync_len),
+				par->lcd_vdisp,
+				par->lcd_lower_margin,
+				par->lcd_vsync_len);
+		}
+	}
+}
+#endif /* CONFIG_FB_ATY_GENERIC_LCD */
+
+static int __devinit init_from_bios(struct atyfb_par *par)
+{
+	u32 bios_base, rom_addr;
+	int ret;
+
+	rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1, par) & 0x7f) << 11);
+	bios_base = (unsigned long)ioremap(rom_addr, 0x10000);
+
+	/* The BIOS starts with 0xaa55. */
+	if (*((u16 *)bios_base) == 0xaa55) {
+
+		u8 *bios_ptr;
+		u16 rom_table_offset, freq_table_offset;
+		PLL_BLOCK_MACH64 pll_block;
+
+		PRINTKI("Mach64 BIOS is located at %x, mapped at %x.\n", rom_addr, bios_base);
+
+		/* check for frequncy table */
+		bios_ptr = (u8*)bios_base;
+		rom_table_offset = (u16)(bios_ptr[0x48] | (bios_ptr[0x49] << 8));
+		freq_table_offset = bios_ptr[rom_table_offset + 16] | (bios_ptr[rom_table_offset + 17] << 8);
+		memcpy(&pll_block, bios_ptr + freq_table_offset, sizeof(PLL_BLOCK_MACH64));
+
+		PRINTKI("BIOS frequency table:\n");
+		PRINTKI("PCLK_min_freq %d, PCLK_max_freq %d, ref_freq %d, ref_divider %d\n",
+			pll_block.PCLK_min_freq, pll_block.PCLK_max_freq,
+			pll_block.ref_freq, pll_block.ref_divider);
+		PRINTKI("MCLK_pwd %d, MCLK_max_freq %d, XCLK_max_freq %d, SCLK_freq %d\n",
+			pll_block.MCLK_pwd, pll_block.MCLK_max_freq,
+			pll_block.XCLK_max_freq, pll_block.SCLK_freq);
+
+		par->pll_limits.pll_min = pll_block.PCLK_min_freq/100;
+		par->pll_limits.pll_max = pll_block.PCLK_max_freq/100;
+		par->pll_limits.ref_clk = pll_block.ref_freq/100;
+		par->pll_limits.ref_div = pll_block.ref_divider;
+		par->pll_limits.sclk = pll_block.SCLK_freq/100;
+		par->pll_limits.mclk = pll_block.MCLK_max_freq/100;
+		par->pll_limits.mclk_pm = pll_block.MCLK_pwd/100;
+		par->pll_limits.xclk = pll_block.XCLK_max_freq/100;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+		aty_init_lcd(par, bios_base);
+#endif
+		ret = 0;
+	} else {
+		PRINTKE("no BIOS frequency table found, use parameters\n");
+		ret = -ENXIO;
+	}
+	iounmap((void* __iomem )bios_base);
 
-				struct fb_var_screeninfo *var =
-				    &default_var;
-				unsigned int N, P, Q, M, T, R;
-				u32 v_total, h_total;
-				struct crtc crtc;
-				u8 pll_regs[16];
-				u8 clock_cntl;
-
-				crtc.vxres =
-				    prom_getintdefault(node, "width",
-						       1024);
-				crtc.vyres =
-				    prom_getintdefault(node, "height",
-						       768);
-				var->bits_per_pixel =
-				    prom_getintdefault(node, "depth", 8);
-				var->xoffset = var->yoffset = 0;
-				crtc.h_tot_disp =
-				    aty_ld_le32(CRTC_H_TOTAL_DISP, default_par);
-				crtc.h_sync_strt_wid =
-				    aty_ld_le32(CRTC_H_SYNC_STRT_WID,
-						default_par);
-				crtc.v_tot_disp =
-				    aty_ld_le32(CRTC_V_TOTAL_DISP, default_par);
-				crtc.v_sync_strt_wid =
-				    aty_ld_le32(CRTC_V_SYNC_STRT_WID,
-						default_par);
-				crtc.gen_cntl =
-				    aty_ld_le32(CRTC_GEN_CNTL, default_par);
-				aty_crtc_to_var(&crtc, var);
-
-				h_total = var->xres + var->right_margin +
-				    var->hsync_len + var->left_margin;
-				v_total = var->yres + var->lower_margin +
-				    var->vsync_len + var->upper_margin;
+	return ret;
+}
+#endif /* __i386__ */
 
-				/*
-				 * Read the PLL to figure actual Refresh Rate.
-				 */
-				clock_cntl = aty_ld_8(CLOCK_CNTL, default_par);
-				/* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
-				for (i = 0; i < 16; i++)
-					pll_regs[i] = aty_ld_pll(i, default_par);
+static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr)
+{
+	struct atyfb_par *par = info->par;
+	u16 tmp;
+	unsigned long raddr;
+	struct resource *rrp;
+	int ret = 0;
+
+	raddr = addr + 0x7ff000UL;
+	rrp = &pdev->resource[2];
+	if ((rrp->flags & IORESOURCE_MEM) && request_mem_region(rrp->start, rrp->end - rrp->start + 1, "atyfb")) {
+		par->aux_start = rrp->start;
+		par->aux_size = rrp->end - rrp->start + 1;
+		raddr = rrp->start;
+		PRINTKI("using auxiliary register aperture\n");
+	}
+
+	info->fix.mmio_start = raddr;
+	par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
+	if (par->ati_regbase == 0)
+		return -ENOMEM;
 
-				/*
-				 * PLL Reference Divider M:
-				 */
-				M = pll_regs[2];
+	info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00;
+	par->ati_regbase += par->aux_start ? 0x400 : 0xc00;
 
-				/*
-				 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
-				 */
-				N = pll_regs[7 + (clock_cntl & 3)];
+	/*
+	 * Enable memory-space accesses using config-space
+	 * command register.
+	 */
+	pci_read_config_word(pdev, PCI_COMMAND, &tmp);
+	if (!(tmp & PCI_COMMAND_MEMORY)) {
+		tmp |= PCI_COMMAND_MEMORY;
+		pci_write_config_word(pdev, PCI_COMMAND, tmp);
+	}
+#ifdef __BIG_ENDIAN
+	/* Use the big-endian aperture */
+	addr += 0x800000;
+#endif
 
-				/*
-				 * PLL Post Divider P (Dependant on CLOCK_CNTL):
-				 */
-				P = 1 << (pll_regs[6] >>
-					  ((clock_cntl & 3) << 1));
+	/* Map in frame buffer */
+	info->fix.smem_start = addr;
+	info->screen_base = ioremap(addr, 0x800000);
+	if (info->screen_base == NULL) {
+		ret = -ENOMEM;
+		goto atyfb_setup_generic_fail;
+	}
+
+	if((ret = correct_chipset(par)))
+		goto atyfb_setup_generic_fail;
+#ifdef __i386__
+	if((ret = init_from_bios(par)))
+		goto atyfb_setup_generic_fail;
+#endif
+	if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN))
+		par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2;
+	else
+		par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
 
-				/*
-				 * PLL Divider Q:
-				 */
-				Q = N / P;
+	/* according to ATI, we should use clock 3 for acelerated mode */
+	par->clk_wr_offset = 3;
 
-				/*
-				 * Target Frequency:
-				 *
-				 *      T * M
-				 * Q = -------
-				 *      2 * R
-				 *
-				 * where R is XTALIN (= 14318 or 29498 kHz).
-				 */
-				if (pdev->device == XL_CHIP_ID)
-					R = 29498;
-				else
-					R = 14318;
+	return 0;
 
-				T = 2 * Q * R / M;
+atyfb_setup_generic_fail:
+	iounmap(par->ati_regbase);
+	par->ati_regbase = NULL;
+	return ret;
+}
 
-				default_var.pixclock = 1000000000 / T;
-			}
-#else				/* __sparc__ */
+#endif /* !__sparc__ */
 
-			info->fix.mmio_start = 0x7ff000 + addr;
-			default_par->ati_regbase = 
-			    ioremap(info->fix.mmio_start, 0x1000);
+static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	unsigned long addr, res_start, res_size;
+	struct fb_info *info;
+	struct resource *rp;
+	struct atyfb_par *par;
+	int i, rc = -ENOMEM;
 
-			if (!default_par->ati_regbase) {
-#ifdef __sparc__
-				kfree(default_par->mmap_map);
-#endif
-				kfree(default_par);
-				kfree(info);
-				release_mem_region(res_start, res_size);
-				return -ENOMEM;
-			}
+	for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--)
+		if (pdev->device == aty_chips[i].pci_id)
+			break;
 
-			info->fix.mmio_start += 0xc00;
-			default_par->ati_regbase += 0xc00;
+	if (i < 0)
+		return -ENODEV;
 
-			/*
-			 * Enable memory-space accesses using config-space
-			 * command register.
-			 */
-			pci_read_config_word(pdev, PCI_COMMAND, &tmp);
-			if (!(tmp & PCI_COMMAND_MEMORY)) {
-				tmp |= PCI_COMMAND_MEMORY;
-				pci_write_config_word(pdev, PCI_COMMAND,
-						      tmp);
-			}
-#ifdef __BIG_ENDIAN
-			/* Use the big-endian aperture */
-			addr += 0x800000;
-#endif
+	/* Enable device in PCI config */
+	if (pci_enable_device(pdev)) {
+		PRINTKE("Cannot enable PCI device\n");
+		return -ENXIO;
+	}
 
-			/* Map in frame buffer */
-			info->fix.smem_start = addr;
-			info->screen_base = ioremap(addr, 0x800000);
+	/* Find which resource to use */
+	rp = &pdev->resource[0];
+	if (rp->flags & IORESOURCE_IO)
+		rp = &pdev->resource[1];
+	addr = rp->start;
+	if (!addr)
+		return -ENXIO;
+
+	/* Reserve space */
+	res_start = rp->start;
+	res_size = rp->end - rp->start + 1;
+	if (!request_mem_region (res_start, res_size, "atyfb"))
+		return -EBUSY;
+
+        /* Allocate framebuffer */
+	info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev);
+	if (!info) {
+		PRINTKE("atyfb_pci_probe() can't alloc fb_info\n");
+		return -ENOMEM;
+	}
+	par = info->par;
+	info->fix = atyfb_fix;
+	info->device = &pdev->dev;
+	par->pci_id = aty_chips[i].pci_id;
+	par->res_start = res_start;
+	par->res_size = res_size;
+	par->irq = pdev->irq;
 
-			if (!info->screen_base) {
+	/* Setup "info" structure */
 #ifdef __sparc__
-				kfree(default_par->mmap_map);
+	rc = atyfb_setup_sparc(pdev, info, addr);
+#else
+	rc = atyfb_setup_generic(pdev, info, addr);
 #endif
-				kfree(default_par);
-				kfree(info);
-				release_mem_region(res_start, res_size);
-				return -ENXIO;
-			}
-#endif				/* __sparc__ */
+	if (rc)
+		goto err_release_mem;
+
+	pci_set_drvdata(pdev, info);
+
+	/* Init chip & register framebuffer */
+	if (aty_init(info, "PCI"))
+		goto err_release_io;
 
-			if (!aty_init(info, "PCI")) {
-#ifdef __sparc__	
-				if (default_par->mmap_map)
-					kfree(default_par->mmap_map);
-#endif
-				kfree(default_par);
-				kfree(info);
-				release_mem_region(res_start, res_size);
-				return -ENXIO;
-			}
 #ifdef __sparc__
-			if (!prom_palette)
-				prom_palette = atyfb_palette;
+	if (!prom_palette)
+		prom_palette = atyfb_palette;
 
-			/*
-			 * Add /dev/fb mmap values.
-			 */
-			default_par->mmap_map[0].voff = 0x8000000000000000UL;
-			default_par->mmap_map[0].poff =
-			    (unsigned long) info->screen_base & PAGE_MASK;
-			default_par->mmap_map[0].size =
-			    info->fix.smem_len;
-			default_par->mmap_map[0].prot_mask = _PAGE_CACHE;
-			default_par->mmap_map[0].prot_flag = _PAGE_E;
-			default_par->mmap_map[1].voff =
-			    default_par->mmap_map[0].voff +
-			    info->fix.smem_len;
-			default_par->mmap_map[1].poff =
-			    default_par->ati_regbase & PAGE_MASK;
-			default_par->mmap_map[1].size = PAGE_SIZE;
-			default_par->mmap_map[1].prot_mask = _PAGE_CACHE;
-			default_par->mmap_map[1].prot_flag = _PAGE_E;
-#endif				/* __sparc__ */
-
-#ifdef CONFIG_PMAC_PBOOK
-			if (first_display == NULL)
-				pmu_register_sleep_notifier(&aty_sleep_notifier);
-			default_par->next = first_display;
+	/*
+	 * Add /dev/fb mmap values.
+	 */
+	par->mmap_map[0].voff = 0x8000000000000000UL;
+	par->mmap_map[0].poff = (unsigned long) info->screen_base & PAGE_MASK;
+	par->mmap_map[0].size = info->fix.smem_len;
+	par->mmap_map[0].prot_mask = _PAGE_CACHE;
+	par->mmap_map[0].prot_flag = _PAGE_E;
+	par->mmap_map[1].voff = par->mmap_map[0].voff + info->fix.smem_len;
+	par->mmap_map[1].poff = (long)par->ati_regbase & PAGE_MASK;
+	par->mmap_map[1].size = PAGE_SIZE;
+	par->mmap_map[1].prot_mask = _PAGE_CACHE;
+	par->mmap_map[1].prot_flag = _PAGE_E;
+#endif /* __sparc__ */
+
+	return 0;
+
+err_release_io:
+#ifdef __sparc__
+	if (par->mmap_map)
+		kfree(par->mmap_map);
+#else
+	if (par->ati_regbase)
+		iounmap(par->ati_regbase);
+	if (info->screen_base)
+		iounmap(info->screen_base);
 #endif
-		}
-	}
+err_release_mem:
+	if(par->aux_start)
+		release_mem_region(par->aux_start, par->aux_size);
+
+	release_mem_region(par->res_start, par->res_size);
+	framebuffer_release(info);
 
-#elif defined(CONFIG_ATARI)
-	struct atyfb_par *default_par;
+	return rc;
+}
+
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_ATARI
+
+static int __devinit atyfb_atari_probe(void)
+{
+	struct aty_par *par;
 	struct fb_info *info;
 	int m64_num;
 	u32 clock_r;
@@ -2312,85 +3441,136 @@
 	for (m64_num = 0; m64_num < mach64_count; m64_num++) {
 		if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
 		    !phys_guiregbase[m64_num]) {
-			printk
-			    (" phys_*[%d] parameters not set => returning early. \n",
-			     m64_num);
+		    PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num);
 			continue;
 		}
 
-		info = kmalloc(sizeof(struct fb_info), GFP_ATOMIC);
+		info = framebuffer_alloc(sizeof(struct atyfb_par), NULL);
 		if (!info) {
-			printk("atyfb_init: can't alloc fb_info\n");
+			PRINTKE("atyfb_atari_probe() can't alloc fb_info\n");
 			return -ENOMEM;
 		}
-		memset(info, 0, sizeof(struct fb_info));
-
-		default_par = kmalloc(sizeof(struct atyfb_par), GFP_ATOMIC);
-		if (!default_par) {
-			printk
-			    ("atyfb_init: can't alloc atyfb_par\n");
-			kfree(info);
-			return -ENXIO;
-		}
-		memset(default_par, 0, sizeof(struct atyfb_par));
+		par = info->par;
 
 		info->fix = atyfb_fix;
-		info->par = default_par;
+
+		par->irq = (unsigned int) -1; /* something invalid */
 
 		/*
 		 *  Map the video memory (physical address given) to somewhere in the
 		 *  kernel address space.
 		 */
-		info->screen_base = ioremap(phys_vmembase[m64_num],
-					 		   phys_size[m64_num]);	
-		info->fix.smem_start = (unsigned long)info->screen_base;	/* Fake! */
-		default_par->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num],
-							  0x10000) + 0xFC00ul;
-		info->fix.mmio_start = default_par->ati_regbase; /* Fake! */
+		info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
+		info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
+		par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
+						0xFC00ul;
+		info->fix.mmio_start = (unsigned long)par->ati_regbase; /* Fake! */
 
-		aty_st_le32(CLOCK_CNTL, 0x12345678, default_par);
-		clock_r = aty_ld_le32(CLOCK_CNTL, default_par);
+		aty_st_le32(CLOCK_CNTL, 0x12345678, par);
+		clock_r = aty_ld_le32(CLOCK_CNTL, par);
 
 		switch (clock_r & 0x003F) {
 		case 0x12:
-			default_par->clk_wr_offset = 3;	/*  */
+			par->clk_wr_offset = 3; /*  */
 			break;
 		case 0x34:
-			default_par->clk_wr_offset = 2;	/* Medusa ST-IO ISA Adapter etc. */
+			par->clk_wr_offset = 2; /* Medusa ST-IO ISA Adapter etc. */
 			break;
 		case 0x16:
-			default_par->clk_wr_offset = 1;	/*  */
+			par->clk_wr_offset = 1; /*  */
 			break;
 		case 0x38:
-			default_par->clk_wr_offset = 0;	/* Panther 1 ISA Adapter (Gerald) */
+			par->clk_wr_offset = 0; /* Panther 1 ISA Adapter (Gerald) */
 			break;
 		}
 
-		if (!aty_init(info, "ISA bus")) {
-			kfree(default_par);
-			kfree(info);
+		if (aty_init(info, "ISA bus")) {
+			framebuffer_release(info);
 			/* This is insufficient! kernel_map has added two large chunks!! */
 			return -ENXIO;
 		}
 	}
-#endif				/* CONFIG_ATARI */
-	return 0;
 }
 
-int __init atyfb_init(void)
+#endif /* CONFIG_ATARI */
+
+static void __devexit atyfb_remove(struct fb_info *info)
 {
-#ifndef MODULE
-	char *option = NULL;
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
 
-	if (fb_get_options("atyfb", &option))
-		return -ENODEV;
-	atyfb_setup(option);
+	/* restore video mode */
+	aty_set_crtc(par, &saved_crtc);
+	par->pll_ops->set_pll(info, &saved_pll);
+
+	unregister_framebuffer(info);
+
+#ifdef CONFIG_MTRR
+	if (par->mtrr_reg >= 0) {
+	    mtrr_del(par->mtrr_reg, 0, 0);
+	    par->mtrr_reg = -1;
+	}
+	if (par->mtrr_aper >= 0) {
+	    mtrr_del(par->mtrr_aper, 0, 0);
+	    par->mtrr_aper = -1;
+	}
 #endif
-	return atyfb_do_init();
+#ifndef __sparc__
+	if (par->ati_regbase)
+		iounmap(par->ati_regbase);
+	if (info->screen_base)
+		iounmap(info->screen_base);
+#ifdef __BIG_ENDIAN
+	if (info->sprite.addr)
+		iounmap(info->sprite.addr);
+#endif
+#endif
+#ifdef __sparc__
+	if (par->mmap_map)
+		kfree(par->mmap_map);
+#endif
+	if (par->aux_start)
+		release_mem_region(par->aux_start, par->aux_size);
+
+	if (par->res_start)
+		release_mem_region(par->res_start, par->res_size);
+
+	framebuffer_release(info);
 }
 
+#ifdef CONFIG_PCI
+
+static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
+{
+	struct fb_info *info = pci_get_drvdata(pdev);
+
+	atyfb_remove(info);
+}
+
+/*
+ * This driver uses its own matching table. That will be more difficult
+ * to fix, so for now, we just match against any ATI ID and let the
+ * probe() function find out what's up. That also mean we don't have
+ * a module ID table though.
+ */
+static struct pci_device_id atyfb_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ATI, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+	  PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 },
+	{ 0, }
+};
+
+static struct pci_driver atyfb_driver = {
+	.name		= "atyfb",
+	.id_table	= atyfb_pci_tbl,
+	.probe		= atyfb_pci_probe,
+	.remove		= __devexit_p(atyfb_pci_remove),
+#ifdef CONFIG_PM
+	.suspend	= atyfb_pci_suspend,
+	.resume		= atyfb_pci_resume,
+#endif /* CONFIG_PM */
+};
+
+#endif /* CONFIG_PCI */
 
-#ifndef MODULE
 int __init atyfb_setup(char *options)
 {
 	char *this_opt;
@@ -2399,19 +3579,20 @@
 		return 0;
 
 	while ((this_opt = strsep(&options, ",")) != NULL) {
-		if (!strncmp(this_opt, "noblink", 7)) {
-			curblink = 0;
-		} else if (!strncmp(this_opt, "noaccel", 7)) {
+		if (!strncmp(this_opt, "noaccel", 7)) {
 			noaccel = 1;
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
 		} else if (!strncmp(this_opt, "vram:", 5))
-			default_vram =
-			    simple_strtoul(this_opt + 5, NULL, 0);
+			vram = simple_strtoul(this_opt + 5, NULL, 0);
 		else if (!strncmp(this_opt, "pll:", 4))
-			default_pll =
-			    simple_strtoul(this_opt + 4, NULL, 0);
+			pll = simple_strtoul(this_opt + 4, NULL, 0);
 		else if (!strncmp(this_opt, "mclk:", 5))
-			default_mclk =
-			    simple_strtoul(this_opt + 5, NULL, 0);
+			mclk = simple_strtoul(this_opt + 5, NULL, 0);
+		else if (!strncmp(this_opt, "xclk:", 5))
+			xclk = simple_strtoul(this_opt+5, NULL, 0);
 #ifdef CONFIG_PPC
 		else if (!strncmp(this_opt, "vmode:", 6)) {
 			unsigned int vmode =
@@ -2454,182 +3635,57 @@
 		}
 #endif
 		else
-			mode_option = this_opt;
+			mode = this_opt;
 	}
 	return 0;
 }
-module_init(atyfb_init);
-#endif				/* !MODULE */
-
-#ifdef CONFIG_ATARI
-static int __init store_video_par(char *video_str, unsigned char m64_num)
-{
-	char *p;
-	unsigned long vmembase, size, guiregbase;
-
-	printk("store_video_par() '%s' \n", video_str);
-
-	if (!(p = strsep(&video_str, ";")) || !*p)
-		goto mach64_invalid;
-	vmembase = simple_strtoul(p, NULL, 0);
-	if (!(p = strsep(&video_str, ";")) || !*p)
-		goto mach64_invalid;
-	size = simple_strtoul(p, NULL, 0);
-	if (!(p = strsep(&video_str, ";")) || !*p)
-		goto mach64_invalid;
-	guiregbase = simple_strtoul(p, NULL, 0);
 
-	phys_vmembase[m64_num] = vmembase;
-	phys_size[m64_num] = size;
-	phys_guiregbase[m64_num] = guiregbase;
-	printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
-	       guiregbase);
-	return 0;
-
-      mach64_invalid:
-	phys_vmembase[m64_num] = 0;
-	return -1;
-}
-#endif				/* CONFIG_ATARI */
-
-/*
-#ifdef CONFIG_FB_ATY_CT
-   * Erase HW Cursor *
-    if (par->cursor && (info->currcon >= 0))
-	atyfb_cursor(&fb_display[par->currcon], CM_ERASE,
-		     par->cursor->pos.x, par->cursor->pos.y);
-#endif * CONFIG_FB_ATY_CT *
-
-#ifdef CONFIG_FB_ATY_CT
-    * Install hw cursor *
-    if (par->cursor) {
-	aty_set_cursor_color(info);
-	aty_set_cursor_shape(info);
-    }
-#endif * CONFIG_FB_ATY_CT */
-
-    /*
-     *  Blank the display.
-     */
-
-static int atyfb_blank(int blank, struct fb_info *info)
+int __init atyfb_init(void)
 {
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u8 gen_cntl;
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && blank)
-		set_backlight_enable(0);
-#endif				/* CONFIG_PMAC_BACKLIGHT */
-
-	gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par);
-	if (blank > 0)
-		switch (blank - 1) {
-		case VESA_NO_BLANKING:
-			gen_cntl |= 0x40;
-			break;
-		case VESA_VSYNC_SUSPEND:
-			gen_cntl |= 0x8;
-			break;
-		case VESA_HSYNC_SUSPEND:
-			gen_cntl |= 0x4;
-			break;
-		case VESA_POWERDOWN:
-			gen_cntl |= 0x4c;
-			break;
-	} else
-		gen_cntl &= ~(0x4c);
-	aty_st_8(CRTC_GEN_CNTL, gen_cntl, par);
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if ((_machine == _MACH_Pmac) && !blank)
-		set_backlight_enable(1);
-#endif				/* CONFIG_PMAC_BACKLIGHT */
-	return 0;
-}
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
+#ifndef MODULE
+    char *option = NULL;
 
-static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	int i, scale;
-	u32 *pal = info->pseudo_palette;
+    if (fb_get_options("atyfb", &option))
+	return -ENODEV;
+    atyfb_setup(option);
+#endif
 
-	if (regno > 255)
-		return 1;
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	i = aty_ld_8(DAC_CNTL, par) & 0xfc;
-	if (M64_HAS(EXTRA_BRIGHT))
-		i |= 0x2;	/*DAC_CNTL|0x2 turns off the extra brightness for gt */
-	aty_st_8(DAC_CNTL, i, par);
-	aty_st_8(DAC_MASK, 0xff, par);
-	scale = (M64_HAS(INTEGRATED) && info->var.bits_per_pixel == 16) ? 3 : 0;
+#ifdef CONFIG_PCI
+    pci_module_init(&atyfb_driver);
+#endif
 #ifdef CONFIG_ATARI
-	out_8(&par->aty_cmap_regs->windex, regno << scale);
-	out_8(&par->aty_cmap_regs->lut, red);
-	out_8(&par->aty_cmap_regs->lut, green);
-	out_8(&par->aty_cmap_regs->lut, blue);
-#else
-	writeb(regno << scale, &par->aty_cmap_regs->windex);
-	writeb(red, &par->aty_cmap_regs->lut);
-	writeb(green, &par->aty_cmap_regs->lut);
-	writeb(blue, &par->aty_cmap_regs->lut);
+    atyfb_atari_probe();
 #endif
-	if (regno < 16)
-		switch (info->var.bits_per_pixel) {
-		case 16:
-			pal[regno] = (regno << 10) | (regno << 5) | regno;
-			break;
-		case 24:
-			pal[regno] = (regno << 16) | (regno << 8) | regno;
-			break;
-		case 32:
-			i = (regno << 8) | regno;
-			pal[regno] = (i << 16) | i;
-			break;
-		}
-	return 0;
+    return 0;
 }
 
-#ifdef MODULE
-int __init init_module(void)
-{
-	atyfb_init();
-	return fb_list ? 0 : -ENXIO;
-}
-
-void cleanup_module(void)
+void __exit atyfb_exit(void)
 {
-	struct fb_info *info = fb_list;
-	struct atyfb_par *par = (struct atyfb_par *) info->par;		
-	unregister_framebuffer(info);
-
-#ifndef __sparc__
-	if (par->ati_regbase)
-		iounmap(par->ati_regbase);
-	if (info->screen_base)
-		iounmap(info->screen_base);
-#ifdef __BIG_ENDIAN
-	if (par->cursor && par->cursor->ram)
-		iounmap(par->cursor->ram);
-#endif
-#endif
-	if (par->cursor)
-		kfree(par->cursor);
-#ifdef __sparc__
-	if (par->mmap_map)
-		kfree(par->mmap_map);
+#ifdef CONFIG_PCI
+	pci_unregister_driver(&atyfb_driver);
 #endif
-	kfree(info);
 }
 
+module_init(atyfb_init);
+#ifdef MODULE
+module_exit(atyfb_exit);
 #endif
+
+MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
 MODULE_LICENSE("GPL");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+module_param(vram, int, 0);
+MODULE_PARM_DESC(vram, "int: override size of video ram");
+module_param(pll, int, 0);
+MODULE_PARM_DESC(pll, "int: override video clock");
+module_param(mclk, int, 0);
+MODULE_PARM_DESC(mclk, "int: override memory clock");
+module_param(xclk, int, 0);
+MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
+module_param(mode, charp, 0);
+MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
+#endif
diff -Nru a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
--- a/drivers/video/aty/mach64_accel.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/video/aty/mach64_accel.c	2004-10-28 22:25:56 -07:00
@@ -13,22 +13,41 @@
      *  Generic Mach64 routines
      */
 
+/* this is for DMA GUI engine! work in progress */
+typedef struct {
+	u32 frame_buf_offset;
+	u32 system_mem_addr;
+	u32 command;
+	u32 reserved;
+} BM_DESCRIPTOR_ENTRY;
+
+#define LAST_DESCRIPTOR (1 << 31)
+#define SYSTEM_TO_FRAME_BUFFER 0
+
+static u32 rotation24bpp(u32 dx, u32 direction)
+{
+	u32 rotation;
+	if (direction & DST_X_LEFT_TO_RIGHT) {
+		rotation = (dx / 4) % 6;
+	} else {
+		rotation = ((dx + 2) / 4) % 6;
+	}
+
+	return ((rotation << 8) | DST_24_ROTATION_ENABLE);
+}
+
 void aty_reset_engine(const struct atyfb_par *par)
 {
 	/* reset engine */
 	aty_st_le32(GEN_TEST_CNTL,
-		    aty_ld_le32(GEN_TEST_CNTL, par) & ~GUI_ENGINE_ENABLE,
-		    par);
+		aty_ld_le32(GEN_TEST_CNTL, par) & ~GUI_ENGINE_ENABLE, par);
 	/* enable engine */
 	aty_st_le32(GEN_TEST_CNTL,
-		    aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE,
-		    par);
+		aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par);
 	/* ensure engine is not locked up by clearing any FIFO or */
 	/* HOST errors */
 	aty_st_le32(BUS_CNTL,
-		    aty_ld_le32(BUS_CNTL,
-				par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK,
-		    par);
+		aty_ld_le32(BUS_CNTL, par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK, par);
 }
 
 static void reset_GTC_3D_engine(const struct atyfb_par *par)
@@ -51,7 +70,7 @@
 	if (info->var.bits_per_pixel == 24) {
 		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
 		/* horizontal coordinates and widths must be adjusted */
-		pitch_value = pitch_value * 3;
+		pitch_value *= 3;
 	}
 
 	/* On GTC (RagePro), we need to reset the 3D engine before */
@@ -146,7 +165,7 @@
 	aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, par);
 
 	wait_for_fifo(5, par);
-	aty_st_le32(SCALE_3D_CNTL, 0, par);
+ 	aty_st_le32(SCALE_3D_CNTL, 0, par);
 	aty_st_le32(Z_CNTL, 0, par);
 	aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, par) & ~0x20,
 		    par);
@@ -174,9 +193,10 @@
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	u32 dy = area->dy, sy = area->sy, direction = DST_LAST_PEL;
-	u32 sx = area->sx, dx = area->dx, width = area->width;	
-	u32 pitch_value;
+	u32 sx = area->sx, dx = area->dx, width = area->width, rotation = 0;
 
+	if (par->asleep)
+		return;
 	if (!area->width || !area->height)
 		return;
 	if (!par->accel_flags) {
@@ -186,11 +206,9 @@
 		return;
 	}
 
-	pitch_value = info->var.xres_virtual;
 	if (info->var.bits_per_pixel == 24) {
 		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
 		/* horizontal coordinates and widths must be adjusted */
-		pitch_value *= 3;
 		sx *= 3;
 		dx *= 3;
 		width *= 3;
@@ -208,19 +226,25 @@
 	} else
 		direction |= DST_X_LEFT_TO_RIGHT;
 
+	if (info->var.bits_per_pixel == 24) {
+		rotation = rotation24bpp(dx, direction);
+	}
+
 	wait_for_fifo(4, par);
 	aty_st_le32(DP_SRC, FRGD_SRC_BLIT, par);
 	aty_st_le32(SRC_Y_X, (sx << 16) | sy, par);
 	aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | area->height, par);
-	aty_st_le32(DST_CNTL, direction, par);
+	aty_st_le32(DST_CNTL, direction | rotation, par);
 	draw_rect(dx, dy, width, area->height, par);
 }
 
 void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 color = rect->color, dx = rect->dx, width = rect->width;
+	u32 color = rect->color, dx = rect->dx, width = rect->width, rotation = 0;
 
+	if (par->asleep)
+		return;
 	if (!rect->width || !rect->height)
 		return;
 	if (!par->accel_flags) {
@@ -238,6 +262,7 @@
 		/* horizontal coordinates and widths must be adjusted */
 		dx *= 3;
 		width *= 3;
+		rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
 	}
 
 	wait_for_fifo(3, par);
@@ -247,15 +272,162 @@
 		    par);
 	aty_st_le32(DST_CNTL,
 		    DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
-		    DST_X_LEFT_TO_RIGHT, par);
+		    DST_X_LEFT_TO_RIGHT | rotation, par);
 	draw_rect(dx, rect->dy, width, rect->height, par);
 }
 
 void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-    
-	if (par->blitter_may_be_busy)
-		wait_for_idle(par);
-	cfb_imageblit(info, image);
+	u32 src_bytes, dx = image->dx, dy = image->dy, width = image->width;
+	u32 pix_width_save, pix_width, host_cntl, rotation = 0, src, mix;
+
+	if (par->asleep)
+		return;
+	if (!image->width || !image->height)
+		return;
+	if (!par->accel_flags ||
+	    (image->depth != 1 && info->var.bits_per_pixel != image->depth)) {
+		if (par->blitter_may_be_busy)
+			wait_for_idle(par);
+
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	wait_for_idle(par);
+	pix_width = pix_width_save = aty_ld_le32(DP_PIX_WIDTH, par);
+	host_cntl = aty_ld_le32(HOST_CNTL, par) | HOST_BYTE_ALIGN;
+
+	switch (image->depth) {
+	case 1:
+	    pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
+	    pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_1BPP);
+	    break;
+	case 4:
+	    pix_width &= ~(BYTE_ORDER_MASK | HOST_MASK);
+	    pix_width |= (BYTE_ORDER_MSB_TO_LSB | HOST_4BPP);
+	    break;
+	case 8:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_8BPP;
+	    break;
+	case 15:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_15BPP;
+	    break;
+	case 16:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_16BPP;
+	    break;
+	case 24:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_24BPP;
+	    break;
+	case 32:
+	    pix_width &= ~HOST_MASK;
+	    pix_width |= HOST_32BPP;
+	    break;
+	}
+
+	if (info->var.bits_per_pixel == 24) {
+		/* In 24 bpp, the engine is in 8 bpp - this requires that all */
+		/* horizontal coordinates and widths must be adjusted */
+		dx *= 3;
+		width *= 3;
+
+		rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
+
+		pix_width &= ~DST_MASK;
+		pix_width |= DST_8BPP;
+
+		/*
+		 * since Rage 3D IIc we have DP_HOST_TRIPLE_EN bit
+		 * this hwaccelerated triple has an issue with not aligned data
+		 */
+		if (M64_HAS(HW_TRIPLE) && image->width % 8 == 0)
+			pix_width |= DP_HOST_TRIPLE_EN;
+	}
+
+	if (image->depth == 1) {
+		u32 fg, bg;
+		if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+		    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+			fg = ((u32*)(info->pseudo_palette))[image->fg_color];
+			bg = ((u32*)(info->pseudo_palette))[image->bg_color];
+		} else {
+			fg = image->fg_color;
+			bg = image->bg_color;
+		}
+
+		wait_for_fifo(2, par);
+		aty_st_le32(DP_BKGD_CLR, bg, par);
+		aty_st_le32(DP_FRGD_CLR, fg, par);
+		src = MONO_SRC_HOST | FRGD_SRC_FRGD_CLR | BKGD_SRC_BKGD_CLR;
+		mix = FRGD_MIX_S | BKGD_MIX_S;
+	} else {
+		src = MONO_SRC_ONE | FRGD_SRC_HOST;
+		mix = FRGD_MIX_D_XOR_S | BKGD_MIX_D;
+	}
+
+	wait_for_fifo(6, par);
+	aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
+	aty_st_le32(DP_PIX_WIDTH, pix_width, par);
+	aty_st_le32(DP_MIX, mix, par);
+	aty_st_le32(DP_SRC, src, par);
+	aty_st_le32(HOST_CNTL, host_cntl, par);
+	aty_st_le32(DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT | rotation, par);
+
+	draw_rect(dx, dy, width, image->height, par);
+	src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
+
+	/* manual triple each pixel */
+	if (info->var.bits_per_pixel == 24 && !(pix_width & DP_HOST_TRIPLE_EN)) {
+		int inbit, outbit, mult24, byte_id_in_dword, width;
+		u8 *pbitmapin = (u8*)image->data, *pbitmapout;
+		u32 hostdword;
+
+		for (width = image->width, inbit = 7, mult24 = 0; src_bytes; ) {
+			for (hostdword = 0, pbitmapout = (u8*)&hostdword, byte_id_in_dword = 0;
+				byte_id_in_dword < 4 && src_bytes;
+				byte_id_in_dword++, pbitmapout++) {
+				for (outbit = 7; outbit >= 0; outbit--) {
+					*pbitmapout |= (((*pbitmapin >> inbit) & 1) << outbit);
+					mult24++;
+					/* next bit */
+					if (mult24 == 3) {
+						mult24 = 0;
+						inbit--;
+						width--;
+					}
+
+					/* next byte */
+					if (inbit < 0 || width == 0) {
+						src_bytes--;
+						pbitmapin++;
+						inbit = 7;
+
+						if (width == 0) {
+						    width = image->width;
+						    outbit = 0;
+						}
+					}
+				}
+			}
+			wait_for_fifo(1, par);
+			aty_st_le32(HOST_DATA0, hostdword, par);
+		}
+	} else {
+		u32 *pbitmap, dwords = (src_bytes + 3) / 4;
+		for (pbitmap = (u32*)(image->data); dwords; dwords--, pbitmap++) {
+			wait_for_fifo(1, par);
+			aty_st_le32(HOST_DATA0, le32_to_cpup(pbitmap), par);
+		}
+	}
+
+	wait_for_idle(par);
+
+	/* restore pix_width */
+	wait_for_fifo(1, par);
+	aty_st_le32(DP_PIX_WIDTH, pix_width_save, par);
 }
diff -Nru a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
--- a/drivers/video/aty/mach64_ct.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/video/aty/mach64_ct.c	2004-10-28 22:25:56 -07:00
@@ -4,214 +4,236 @@
  */
 
 #include <linux/fb.h>
-
+#include <linux/delay.h>
 #include <asm/io.h>
-
 #include <video/mach64.h>
 #include "atyfb.h"
 
+#undef DEBUG
 
-/* FIXME: remove the FAIL definition */
-#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
-
-static void aty_st_pll(int offset, u8 val, const struct atyfb_par *par);
-static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per,
-			    struct pll_ct *pll);
-static int aty_dsp_gt(const struct fb_info *info, u8 bpp,
-		      struct pll_ct *pll);
-static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per,
-			     u8 bpp, union aty_pll *pll);
-static u32 aty_pll_ct_to_var(const struct fb_info *info,
-			     const union aty_pll *pll);
+static int aty_valid_pll_ct (const struct fb_info *info, u32 vclk_per, struct pll_ct *pll);
+static int aty_dsp_gt       (const struct fb_info *info, u32 bpp, struct pll_ct *pll);
+static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll);
+static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll);
 
+u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par)
+{
+	u8 res;
 
+	/* write addr byte */
+	aty_st_8(CLOCK_CNTL_ADDR, (offset << 2) & PLL_ADDR, par);
+	/* read the register value */
+	res = aty_ld_8(CLOCK_CNTL_DATA, par);
+	return res;
+}
 
-static void aty_st_pll(int offset, u8 val, const struct atyfb_par *par)
+void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par)
 {
 	/* write addr byte */
-	aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, par);
+	aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) | PLL_WR_EN, par);
 	/* write the register value */
-	aty_st_8(CLOCK_CNTL + 2, val, par);
-	aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, par);
+	aty_st_8(CLOCK_CNTL_DATA, val & PLL_DATA, par);
+	aty_st_8(CLOCK_CNTL_ADDR, ((offset << 2) & PLL_ADDR) & ~PLL_WR_EN, par);
 }
 
+/*
+ * by Daniel Mantione
+ *                                  <daniel.mantione@freepascal.org>
+ *
+ *
+ * ATI Mach64 CT clock synthesis description.
+ *
+ * All clocks on the Mach64 can be calculated using the same principle:
+ *
+ *       XTALIN * x * FB_DIV
+ * CLK = ----------------------
+ *       PLL_REF_DIV * POST_DIV
+ *
+ * XTALIN is a fixed speed clock. Common speeds are 14.31 MHz and 29.50 MHz.
+ * PLL_REF_DIV can be set by the user, but is the same for all clocks.
+ * FB_DIV can be set by the user for each clock individually, it should be set
+ * between 128 and 255, the chip will generate a bad clock signal for too low
+ * values.
+ * x depends on the type of clock; usually it is 2, but for the MCLK it can also
+ * be set to 4.
+ * POST_DIV can be set by the user for each clock individually, Possible values
+ * are 1,2,4,8 and for some clocks other values are available too.
+ * CLK is of course the clock speed that is generated.
+ *
+ * The Mach64 has these clocks:
+ *
+ * MCLK			The clock rate of the chip
+ * XCLK			The clock rate of the on-chip memory
+ * VCLK0		First pixel clock of first CRT controller
+ * VCLK1    Second pixel clock of first CRT controller
+ * VCLK2		Third pixel clock of first CRT controller
+ * VCLK3    Fourth pixel clock of first CRT controller
+ * VCLK			Selected pixel clock, one of VCLK0, VCLK1, VCLK2, VCLK3
+ * V2CLK		Pixel clock of the second CRT controller.
+ * SCLK			Multi-purpose clock
+ *
+ * - MCLK and XCLK use the same FB_DIV
+ * - VCLK0 .. VCLK3 use the same FB_DIV
+ * - V2CLK is needed when the second CRTC is used (can be used for dualhead);
+ *   i.e. CRT monitor connected to laptop has different resolution than built
+ *   in LCD monitor.
+ * - SCLK is not available on all cards; it is know to exist on the Rage LT-PRO,
+ *   Rage XL and Rage Mobility. It is know not to exist on the Mach64 VT.
+ * - V2CLK is not available on all cards, most likely only the Rage LT-PRO,
+ *   the Rage XL and the Rage Mobility
+ *
+ * SCLK can be used to:
+ * - Clock the chip instead of MCLK
+ * - Replace XTALIN with a user defined frequency
+ * - Generate the pixel clock for the LCD monitor (instead of VCLK)
+ */
+
+ /*
+  * It can be quite hard to calculate XCLK and MCLK if they don't run at the
+  * same frequency. Luckily, until now all cards that need asynchrone clock
+  * speeds seem to have SCLK.
+  * So this driver uses SCLK to clock the chip and XCLK to clock the memory.
+  */
 
 /* ------------------------------------------------------------------------- */
 
-    /*
-     *  PLL programming (Mach64 CT family)
-     */
+/*
+ *  PLL programming (Mach64 CT family)
+ *
+ *
+ * This procedure sets the display fifo. The display fifo is a buffer that
+ * contains data read from the video memory that waits to be processed by
+ * the CRT controller.
+ *
+ * On the more modern Mach64 variants, the chip doesn't calculate the
+ * interval after which the display fifo has to be reloaded from memory
+ * automatically, the driver has to do it instead.
+ */
+
+#define Maximum_DSP_PRECISION 7
+static u8 postdividers[] = {1,2,4,8,3};
 
-static int aty_dsp_gt(const struct fb_info *info, u8 bpp,
-		      struct pll_ct *pll)
+static int aty_dsp_gt(const struct fb_info *info, u32 bpp, struct pll_ct *pll)
 {
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off,
-	    dsp_on;
-	u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
-
-	/* xclocks_per_row<<11 */
-	xclks_per_row =
-	    (pll->mclk_fb_div * pll->vclk_post_div_real * 64 << 11) /
-	    (pll->vclk_fb_div * pll->mclk_post_div_real * bpp);
-	if (xclks_per_row < (1 << 11))
-		FAIL("Dotclock to high");
-	if (M64_HAS(FIFO_24)) {
-		fifo_size = 24;
-		dsp_loop_latency = 0;
-	} else {
-		fifo_size = 32;
-		dsp_loop_latency = 2;
+	u32 dsp_off, dsp_on, dsp_xclks;
+	u32 multiplier, divider, ras_multiplier, ras_divider, tmp;
+	u8 vshift, xshift;
+	s8 dsp_precision;
+
+	multiplier = ((u32)pll->mclk_fb_div) * pll->vclk_post_div_real;
+	divider = ((u32)pll->vclk_fb_div) * pll->xclk_ref_div;
+
+	ras_multiplier = pll->xclkmaxrasdelay;
+	ras_divider = 1;
+
+	if (bpp>=8)
+		divider = divider * (bpp >> 2);
+
+	vshift = (6 - 2) - pll->xclk_post_div;	/* FIFO is 64 bits wide in accelerator mode ... */
+
+	if (bpp == 0)
+		vshift--;	/* ... but only 32 bits in VGA mode. */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (pll->xres != 0) {
+		struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+		multiplier = multiplier * par->lcd_width;
+		divider = divider * pll->xres & ~7;
+
+		ras_multiplier = ras_multiplier * par->lcd_width;
+		ras_divider = ras_divider * pll->xres & ~7;
 	}
-	dsp_precision = 0;
-	y = (xclks_per_row * fifo_size) >> 11;
-	while (y) {
-		y >>= 1;
-		dsp_precision++;
-	}
-	dsp_precision -= 5;
-	/* fifo_off<<6 */
-	fifo_off = ((xclks_per_row * (fifo_size - 1)) >> 5) + (3 << 6);
-
-	if (info->fix.smem_len > 1 * 1024 * 1024) {
-		if (par->ram_type >= SDRAM) {
-			/* >1 MB SDRAM */
-			dsp_loop_latency += 8;
-			page_size = 8;
-		} else {
-			/* >1 MB DRAM */
-			dsp_loop_latency += 6;
-			page_size = 9;
-		}
-	} else {
-		if (par->ram_type >= SDRAM) {
-			/* <2 MB SDRAM */
-			dsp_loop_latency += 9;
-			page_size = 10;
-		} else {
-			/* <2 MB DRAM */
-			dsp_loop_latency += 8;
-			page_size = 10;
-		}
+#endif
+	/* If we don't do this, 32 bits for multiplier & divider won't be
+	enough in certain situations! */
+	while (((multiplier | divider) & 1) == 0) {
+		multiplier = multiplier >> 1;
+		divider = divider >> 1;
 	}
-	/* fifo_on<<6 */
-	if (xclks_per_row >= (page_size << 11))
-		fifo_on =
-		    ((2 * page_size + 1) << 6) + (xclks_per_row >> 5);
-	else
-		fifo_on = (3 * page_size + 2) << 6;
 
-	dsp_xclks_per_row = xclks_per_row >> dsp_precision;
-	dsp_on = fifo_on >> dsp_precision;
-	dsp_off = fifo_off >> dsp_precision;
-
-	pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
-	    ((dsp_loop_latency & 0xf) << 16) | ((dsp_precision & 7) << 20);
-	pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff) << 16);
-	return 0;
-}
+	/* Determine DSP precision first */
+	tmp = ((multiplier * pll->fifo_size) << vshift) / divider;
 
-static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per,
-			    struct pll_ct *pll)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u32 q, x;		/* x is a workaround for sparc64-linux-gcc */
-	x = x;			/* x is a workaround for sparc64-linux-gcc */
+	for (dsp_precision = -5;  tmp;  dsp_precision++)
+		tmp >>= 1;
+	if (dsp_precision < 0)
+		dsp_precision = 0;
+	else if (dsp_precision > Maximum_DSP_PRECISION)
+		dsp_precision = Maximum_DSP_PRECISION;
+
+	xshift = 6 - dsp_precision;
+	vshift += xshift;
+
+	/* Move on to dsp_off */
+	dsp_off = ((multiplier * (pll->fifo_size - 1)) << vshift) / divider -
+		(1 << (vshift - xshift));
+
+/*    if (bpp == 0)
+        dsp_on = ((multiplier * 20 << vshift) + divider) / divider;
+    else */
+	{
+		dsp_on = ((multiplier << vshift) + divider) / divider;
+		tmp = ((ras_multiplier << xshift) + ras_divider) / ras_divider;
+		if (dsp_on < tmp)
+		dsp_on = tmp;
+		dsp_on = dsp_on + (tmp * 2) + (pll->xclkpagefaultdelay << xshift);
+	}
 
-	pll->pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
+	/* Calculate rounding factor and apply it to dsp_on */
+	tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1;
+	dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1);
+
+	if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1))) {
+		dsp_on = dsp_off - (multiplier << vshift) / divider;
+		dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
+	}
 
-	/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
-	q = par->ref_clk_per * pll->pll_ref_div * 4 / par->mclk_per;	/* actually 8*q */
-	if (q < 16 * 8 || q > 255 * 8)
-		FAIL("mclk out of range");
-	else if (q < 32 * 8)
-		pll->mclk_post_div_real = 8;
-	else if (q < 64 * 8)
-		pll->mclk_post_div_real = 4;
-	else if (q < 128 * 8)
-		pll->mclk_post_div_real = 2;
-	else
-		pll->mclk_post_div_real = 1;
-	pll->mclk_fb_div = q * pll->mclk_post_div_real / 8;
+	/* Last but not least:  dsp_xclks */
+	dsp_xclks = ((multiplier << (vshift + 5)) + divider) / divider;
 
-	/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
-	q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per;	/* actually 8*q */
-	if (q < 16 * 8 || q > 255 * 8)
-		FAIL("vclk out of range");
-	else if (q < 32 * 8)
-		pll->vclk_post_div_real = 8;
-	else if (q < 64 * 8)
-		pll->vclk_post_div_real = 4;
-	else if (q < 128 * 8)
-		pll->vclk_post_div_real = 2;
-	else
-		pll->vclk_post_div_real = 1;
-	pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
+	/* Get register values. */
+	pll->dsp_on_off = (dsp_on << 16) + dsp_off;
+	pll->dsp_config = (dsp_precision << 20) | (pll->dsp_loop_latency << 16) | dsp_xclks;
+#ifdef DEBUG
+	printk("atyfb(%s): dsp_config 0x%08x, dsp_on_off 0x%08x\n",
+		__FUNCTION__, pll->dsp_config, pll->dsp_on_off);
+#endif
 	return 0;
 }
 
-void aty_calc_pll_ct(const struct fb_info *info, struct pll_ct *pll)
+static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll_ct *pll)
 {
+	u32 q;
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	u8 mpostdiv = 0;
-	u8 vpostdiv = 0;
+#ifdef DEBUG
+	int pllvclk;
+#endif
 
-	if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
-		pll->pll_gen_cntl = 0x04;
-	else
-		pll->pll_gen_cntl = 0x84;
-
-	switch (pll->mclk_post_div_real) {
-	case 1:
-		mpostdiv = 0;
-		break;
-	case 2:
-		mpostdiv = 1;
-		break;
-	case 3:
-		mpostdiv = 4;
-		break;
-	case 4:
-		mpostdiv = 2;
-		break;
-	case 8:
-		mpostdiv = 3;
-		break;
-	}
-	pll->pll_gen_cntl |= mpostdiv << 4;	/* mclk */
-
-	if (M64_HAS(MAGIC_POSTDIV))
-		pll->pll_ext_cntl = 0;
-	else
-		pll->pll_ext_cntl = mpostdiv;	/* xclk == mclk */
-
-	switch (pll->vclk_post_div_real) {
-	case 2:
-		vpostdiv = 1;
-		break;
-	case 3:
-		pll->pll_ext_cntl |= 0x10;
-	case 1:
-		vpostdiv = 0;
-		break;
-	case 6:
-		pll->pll_ext_cntl |= 0x10;
-	case 4:
-		vpostdiv = 2;
-		break;
-	case 12:
-		pll->pll_ext_cntl |= 0x10;
-	case 8:
-		vpostdiv = 3;
-		break;
+	/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
+	q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per;
+	if (q < 16*8 || q > 255*8) {
+		printk(KERN_CRIT "atyfb: vclk out of range\n");
+		return -EINVAL;
+	} else {
+		pll->vclk_post_div  = (q < 128*8);
+		pll->vclk_post_div += (q <  64*8);
+		pll->vclk_post_div += (q <  32*8);
 	}
-
-	pll->pll_vclk_cntl = 0x03;	/* VCLK = PLL_VCLK/VCLKx_POST */
-	pll->vclk_post_div = vpostdiv;
+	pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
+	//    pll->vclk_post_div <<= 6;
+	pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
+#ifdef DEBUG
+	pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
+		(par->ref_clk_per * pll->pll_ref_div);
+	printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
+		__FUNCTION__, pllvclk, pllvclk / pll->vclk_post_div_real);
+#endif
+	pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
+	return 0;
 }
 
-static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per,
-			     u8 bpp, union aty_pll *pll)
+static int aty_var_to_pll_ct(const struct fb_info *info, u32 vclk_per, u32 bpp, union aty_pll *pll)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	int err;
@@ -220,47 +242,360 @@
 		return err;
 	if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
 		return err;
-	aty_calc_pll_ct(info, &pll->ct);
+	/*aty_calc_pll_ct(info, &pll->ct);*/
 	return 0;
 }
 
-static u32 aty_pll_ct_to_var(const struct fb_info *info,
-			     const union aty_pll *pll)
+static u32 aty_pll_to_var_ct(const struct fb_info *info, const union aty_pll *pll)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-
-	u32 ref_clk_per = par->ref_clk_per;
-	u8 pll_ref_div = pll->ct.pll_ref_div;
-	u8 vclk_fb_div = pll->ct.vclk_fb_div;
-	u8 vclk_post_div = pll->ct.vclk_post_div_real;
-
-	return ref_clk_per * pll_ref_div * vclk_post_div / vclk_fb_div / 2;
+	u32 ret;
+	ret = par->ref_clk_per * pll->ct.pll_ref_div * pll->ct.vclk_post_div_real / pll->ct.vclk_fb_div / 2;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if(pll->ct.xres > 0) {
+		ret *= par->lcd_width;
+		ret /= pll->ct.xres;
+	}
+#endif
+#ifdef DEBUG
+	printk("atyfb(%s): calculated 0x%08X(%i)\n", __FUNCTION__, ret, ret);
+#endif
+	return ret;
 }
 
-void aty_set_pll_ct(const struct fb_info *info,
-		    const union aty_pll *pll)
+void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u32 crtc_gen_cntl, lcd_gen_cntrl;
+	u8 tmp, tmp2;
+
+	lcd_gen_cntrl = 0;
+#ifdef DEBUG
+	printk("atyfb(%s): about to program:\n"
+		"pll_ext_cntl=0x%02x pll_gen_cntl=0x%02x pll_vclk_cntl=0x%02x\n",
+		__FUNCTION__,
+		pll->ct.pll_ext_cntl, pll->ct.pll_gen_cntl, pll->ct.pll_vclk_cntl);
+
+	printk("atyfb(%s): setting clock %lu for FeedBackDivider %i, ReferenceDivider %i, PostDivider %i(%i)\n",
+		__FUNCTION__,
+		par->clk_wr_offset, pll->ct.vclk_fb_div,
+		pll->ct.pll_ref_div, pll->ct.vclk_post_div, pll->ct.vclk_post_div_real);
+#endif
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* turn off LCD */
+		lcd_gen_cntrl = aty_ld_lcd(LCD_GEN_CNTL, par);
+		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl & ~LCD_ON, par);
+	}
+#endif
+	aty_st_8(CLOCK_CNTL, par->clk_wr_offset | CLOCK_STROBE, par);
 
-	aty_st_pll(PLL_REF_DIV, pll->ct.pll_ref_div, par);
-	aty_st_pll(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
-	aty_st_pll(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
-	aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
-	aty_st_pll(VCLK_POST_DIV, pll->ct.vclk_post_div, par);
-	aty_st_pll(VCLK0_FB_DIV, pll->ct.vclk_fb_div, par);
-	aty_st_pll(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
+	/* Temporarily switch to accelerator mode */
+	crtc_gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
+	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN, par);
+
+	/* Reset VCLK generator */
+	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
+
+	/* Set post-divider */
+	tmp2 = par->clk_wr_offset << 1;
+	tmp = aty_ld_pll_ct(VCLK_POST_DIV, par);
+	tmp &= ~(0x03U << tmp2);
+	tmp |= ((pll->ct.vclk_post_div & 0x03U) << tmp2);
+	aty_st_pll_ct(VCLK_POST_DIV, tmp, par);
+
+	/* Set extended post-divider */
+	tmp = aty_ld_pll_ct(PLL_EXT_CNTL, par);
+	tmp &= ~(0x10U << par->clk_wr_offset);
+	tmp &= 0xF0U;
+	tmp |= pll->ct.pll_ext_cntl;
+	aty_st_pll_ct(PLL_EXT_CNTL, tmp, par);
+
+	/* Set feedback divider */
+	tmp = VCLK0_FB_DIV + par->clk_wr_offset;
+	aty_st_pll_ct(tmp, (pll->ct.vclk_fb_div & 0xFFU), par);
+
+	aty_st_pll_ct(PLL_GEN_CNTL, (pll->ct.pll_gen_cntl & (~(PLL_OVERRIDE | PLL_MCLK_RST))) | OSC_EN, par);
+
+	/* End VCLK generator reset */
+	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl & ~(PLL_VCLK_RST), par);
+	mdelay(5);
+
+	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
+	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);
+	mdelay(1);
+
+	/* Restore mode register */
+	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))
+		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl, par);
 
 	if (M64_HAS(GTB_DSP)) {
+		u8 dll_cntl;
+
 		if (M64_HAS(XL_DLL))
-			aty_st_pll(DLL_CNTL, 0x80, par);
+			dll_cntl = 0x80;
 		else if (par->ram_type >= SDRAM)
-			aty_st_pll(DLL_CNTL, 0xa6, par);
+			dll_cntl = 0xa6;
 		else
-			aty_st_pll(DLL_CNTL, 0xa0, par);
-		aty_st_pll(VFC_CNTL, 0x1b, par);
+			dll_cntl = 0xa0;
+		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
+		aty_st_pll_ct(VFC_CNTL, 0x1b, par);
 		aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par);
 		aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par);
+
+		mdelay(10);
+		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);
+		mdelay(10);
+		aty_st_pll_ct(DLL_CNTL, dll_cntl | 0x40, par);
+		mdelay(10);
+		aty_st_pll_ct(DLL_CNTL, dll_cntl & ~0x40, par);
+	}
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+	if (par->lcd_table != 0) {
+		/* restore LCD */
+		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl, par);
 	}
+#endif
+}
+
+void __init aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u8 tmp, clock;
+
+	clock = aty_ld_8(CLOCK_CNTL, par) & 0x03U;
+	tmp = clock << 1;
+	pll->ct.vclk_post_div = (aty_ld_pll_ct(VCLK_POST_DIV, par) >> tmp) & 0x03U;
+
+	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par) & 0x0FU;
+	pll->ct.vclk_fb_div = aty_ld_pll_ct(VCLK0_FB_DIV + clock, par) & 0xFFU;
+	pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+	pll->ct.mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
+
+	pll->ct.pll_gen_cntl = aty_ld_pll_ct(PLL_GEN_CNTL, par);
+	pll->ct.pll_vclk_cntl = aty_ld_pll_ct(PLL_VCLK_CNTL, par);
+
+	if (M64_HAS(GTB_DSP)) {
+		pll->ct.dsp_config = aty_ld_le32(DSP_CONFIG, par);
+		pll->ct.dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
+	}
+}
+
+int __init aty_init_pll_ct(const struct fb_info *info, union aty_pll *pll) {
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2;
+	u32 q, i, memcntl, trp;
+	u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;
+#ifdef DEBUG
+	int pllmclk, pllsclk;
+#endif
+	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
+	pll->ct.xclk_post_div = pll->ct.pll_ext_cntl & 0x07;
+	pll->ct.xclk_ref_div = 1;
+	switch (pll->ct.xclk_post_div) {
+	case 0:  case 1:  case 2:  case 3:
+		break;
+
+	case 4:
+		pll->ct.xclk_ref_div = 3;
+		pll->ct.xclk_post_div = 0;
+		break;
+
+	default:
+		printk(KERN_CRIT "atyfb: Unsupported xclk source:  %d.\n", pll->ct.xclk_post_div);
+		return -EINVAL;
+	}
+	pll->ct.mclk_fb_mult = 2;
+	if(pll->ct.pll_ext_cntl & PLL_MFB_TIMES_4_2B) {
+		pll->ct.mclk_fb_mult = 4;
+		pll->ct.xclk_post_div -= 1;
+	}
+
+#ifdef DEBUG
+	printk("atyfb(%s): mclk_fb_mult=%d, xclk_post_div=%d\n",
+		__FUNCTION__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div);
+#endif
+
+	memcntl = aty_ld_le32(MEM_CNTL, par);
+	trp = (memcntl & 0x300) >> 8;
+
+	pll->ct.xclkpagefaultdelay = ((memcntl & 0xc00) >> 10) + ((memcntl & 0x1000) >> 12) + trp + 2;
+	pll->ct.xclkmaxrasdelay = ((memcntl & 0x70000) >> 16) + trp + 2;
+
+	if (M64_HAS(FIFO_32)) {
+		pll->ct.fifo_size = 32;
+	} else {
+		pll->ct.fifo_size = 24;
+		pll->ct.xclkpagefaultdelay += 2;
+		pll->ct.xclkmaxrasdelay += 3;
+	}
+
+	switch (par->ram_type) {
+	case DRAM:
+		if (info->fix.smem_len<=ONE_MB) {
+			pll->ct.dsp_loop_latency = 10;
+		} else {
+			pll->ct.dsp_loop_latency = 8;
+			pll->ct.xclkpagefaultdelay += 2;
+		}
+		break;
+	case EDO:
+	case PSEUDO_EDO:
+		if (info->fix.smem_len<=ONE_MB) {
+			pll->ct.dsp_loop_latency = 9;
+		} else {
+			pll->ct.dsp_loop_latency = 8;
+			pll->ct.xclkpagefaultdelay += 1;
+		}
+		break;
+	case SDRAM:
+		if (info->fix.smem_len<=ONE_MB) {
+			pll->ct.dsp_loop_latency = 11;
+		} else {
+			pll->ct.dsp_loop_latency = 10;
+			pll->ct.xclkpagefaultdelay += 1;
+		}
+		break;
+	case SGRAM:
+		pll->ct.dsp_loop_latency = 8;
+		pll->ct.xclkpagefaultdelay += 3;
+		break;
+	default:
+		pll->ct.dsp_loop_latency = 11;
+		pll->ct.xclkpagefaultdelay += 3;
+		break;
+	}
+
+	if (pll->ct.xclkmaxrasdelay <= pll->ct.xclkpagefaultdelay)
+		pll->ct.xclkmaxrasdelay = pll->ct.xclkpagefaultdelay + 1;
+
+	/* Allow BIOS to override */
+	dsp_config = aty_ld_le32(DSP_CONFIG, par);
+	dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);
+	vga_dsp_config = aty_ld_le32(VGA_DSP_CONFIG, par);
+	vga_dsp_on_off = aty_ld_le32(VGA_DSP_ON_OFF, par);
+
+	if (dsp_config)
+		pll->ct.dsp_loop_latency = (dsp_config & DSP_LOOP_LATENCY) >> 16;
+#if 0
+	FIXME: is it relevant for us?
+	if ((!dsp_on_off && !M64_HAS(RESET_3D)) ||
+		((dsp_on_off == vga_dsp_on_off) &&
+		(!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) {
+		vga_dsp_on_off &= VGA_DSP_OFF;
+		vga_dsp_config &= VGA_DSP_XCLKS_PER_QW;
+		if (ATIDivide(vga_dsp_on_off, vga_dsp_config, 5, 1) > 24)
+			pll->ct.fifo_size = 32;
+		else
+			pll->ct.fifo_size = 24;
+	}
+#endif
+	/* Exit if the user does not want us to tamper with the clock
+	rates of her chip. */
+	if (par->mclk_per == 0) {
+		u8 mclk_fb_div, pll_ext_cntl;
+		pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);
+		pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);
+		pll->ct.xclk_post_div_real = postdividers[pll_ext_cntl & 0x07];
+		mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);
+		if (pll_ext_cntl & PLL_MFB_TIMES_4_2B)
+			mclk_fb_div <<= 1;
+		pll->ct.mclk_fb_div = mclk_fb_div;
+		return 0;
+	}
+
+	pll->ct.pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;
+
+	/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
+	q = par->ref_clk_per * pll->ct.pll_ref_div * 8 /
+		(pll->ct.mclk_fb_mult * par->xclk_per);
+
+	if (q < 16*8 || q > 255*8) {
+		printk(KERN_CRIT "atxfb: xclk out of range\n");
+		return -EINVAL;
+	} else {
+		xpost_div  = (q < 128*8);
+		xpost_div += (q <  64*8);
+		xpost_div += (q <  32*8);
+	}
+	pll->ct.xclk_post_div_real = postdividers[xpost_div];
+	pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8;
+
+#ifdef DEBUG
+	pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) /
+			(par->ref_clk_per * pll->ct.pll_ref_div);
+	printk("atyfb(%s): pllmclk=%d MHz, xclk=%d MHz\n",
+		__FUNCTION__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);
+#endif
+
+	if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))
+		pll->ct.pll_gen_cntl = OSC_EN;
+	else
+		pll->ct.pll_gen_cntl = OSC_EN | DLL_PWDN /* | FORCE_DCLK_TRI_STATE */;
+
+	if (M64_HAS(MAGIC_POSTDIV))
+		pll->ct.pll_ext_cntl = 0;
+	else
+		pll->ct.pll_ext_cntl = xpost_div;
+
+	if (pll->ct.mclk_fb_mult == 4)
+		pll->ct.pll_ext_cntl |= PLL_MFB_TIMES_4_2B;
+
+	if (par->mclk_per == par->xclk_per) {
+		pll->ct.pll_gen_cntl |= (xpost_div << 4); /* mclk == xclk */
+	} else {
+		/*
+		* The chip clock is not equal to the memory clock.
+		* Therefore we will use sclk to clock the chip.
+		*/
+		pll->ct.pll_gen_cntl |= (6 << 4); /* mclk == sclk */
+
+		q = par->ref_clk_per * pll->ct.pll_ref_div * 4 / par->mclk_per;
+		if (q < 16*8 || q > 255*8) {
+			printk(KERN_CRIT "atyfb: mclk out of range\n");
+			return -EINVAL;
+		} else {
+			mpost_div  = (q < 128*8);
+			mpost_div += (q <  64*8);
+			mpost_div += (q <  32*8);
+		}
+		sclk_post_div_real = postdividers[mpost_div];
+		sclk_fb_div = q * sclk_post_div_real / 8;
+		spll_cntl2 = mpost_div << 4;
+#ifdef DEBUG
+		pllsclk = (1000000 * 2 * sclk_fb_div) /
+			(par->ref_clk_per * pll->ct.pll_ref_div);
+		printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",
+			__FUNCTION__, pllsclk, pllsclk / sclk_post_div_real);
+#endif
+		/*
+		* This disables the sclk, crashes the computer as reported:
+		* aty_st_pll_ct(SPLL_CNTL2, 3, info);
+		*
+		* So it seems the sclk must be enabled before it is used;
+		* so PLL_GEN_CNTL must be programmed *after* the sclk.
+		*/
+		aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par);
+		aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par);
+		/*
+		 * The sclk has been started. However, I believe the first clock
+		 * ticks it generates are not very stable. Hope this primitive loop
+		 * helps for Rage Mobilities that sometimes crash when
+		 * we switch to sclk. (Daniel Mantione, 13-05-2003)
+		 */
+		for (i=0;i<=0x1ffff;i++);
+	}
+
+	aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par);
+	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);
+	aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);
+	aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);
+	/* Disable the extra precision pixel clock controls since we do not use them. */
+	aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) &
+		~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par);
+
+	return 0;
 }
 
 static int dummy(void)
@@ -274,6 +609,8 @@
 
 const struct aty_pll_ops aty_pll_ct = {
 	.var_to_pll	= aty_var_to_pll_ct,
-	.pll_to_var	= aty_pll_ct_to_var,
+	.pll_to_var	= aty_pll_to_var_ct,
 	.set_pll	= aty_set_pll_ct,
+	.get_pll	= aty_get_pll_ct,
+	.init_pll       = aty_init_pll_ct
 };
diff -Nru a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
--- a/drivers/video/aty/mach64_cursor.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/video/aty/mach64_cursor.c	2004-10-28 22:25:59 -07:00
@@ -1,12 +1,11 @@
-
 /*
  *  ATI Mach64 CT/VT/GT/LT Cursor Support
  */
 
 #include <linux/slab.h>
-#include <linux/console.h>
 #include <linux/fb.h>
 #include <linux/init.h>
+#include <linux/string.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -19,13 +18,49 @@
 #include <video/mach64.h>
 #include "atyfb.h"
 
+/*
+ * The hardware cursor definition requires 2 bits per pixel. The
+ * Cursor size reguardless of the visible cursor size is 64 pixels
+ * by 64 lines. The total memory required to define the cursor is
+ * 16 bytes / line for 64 lines or 1024 bytes of data. The data
+ * must be in a contigiuos format. The 2 bit cursor code values are
+ * as follows:
+ *
+ *	00 - pixel colour = CURSOR_CLR_0
+ *	01 - pixel colour = CURSOR_CLR_1
+ *	10 - pixel colour = transparent (current display pixel)
+ *	11 - pixel colour = 1's complement of current display pixel
+ *
+ *	Cursor Offset        64 pixels		 Actual Displayed Area
+ *            \_________________________/
+ *	      |			|	|	|
+ *	      |<--------------->|	|	|
+ *	      | CURS_HORZ_OFFSET|	|	|
+ *	      |			|_______|	|  64 Lines
+ *	      |			   ^	|	|
+ *	      |			   |	|	|
+ *	      |		CURS_VERT_OFFSET|	|
+ *	      |			   |	|	|
+ *	      |____________________|____|	|
+ *
+ *
+ * The Screen position of the top left corner of the displayed
+ * cursor is specificed by CURS_HORZ_VERT_POSN. Care must be taken
+ * when the cursor hot spot is not the top left corner and the
+ * physical cursor position becomes negative. It will be be displayed
+ * if either the horizontal or vertical cursor position is negative
+ *
+ * If x becomes negative the cursor manager must adjust the CURS_HORZ_OFFSET
+ * to a larger number and saturate CUR_HORZ_POSN to zero.
+ *
+ * if Y becomes negative, CUR_VERT_OFFSET must be adjusted to a larger number,
+ * CUR_OFFSET must be adjusted to a point to the appropraite line in the cursor
+ * definitation and CUR_VERT_POSN must be saturated to zero.
+ */
+
     /*
      *  Hardware Cursor support.
      */
-
-static const u8 cursor_pixel_map[2] = { 0, 15 };
-static const u8 cursor_color_map[2] = { 0, 0xff };
-
 static const u8 cursor_bits_lookup[16] = {
 	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
@@ -36,90 +71,25 @@
 	0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
 };
 
-void aty_set_cursor_color(struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	struct aty_cursor *c = par->cursor;
-	const u8 *pixel = cursor_pixel_map;	/* ++Geert: Why?? */
-	const u8 *red = cursor_color_map;
-	const u8 *green = cursor_color_map;
-	const u8 *blue = cursor_color_map;
-	u32 fg_color, bg_color;
-
-	if (!c)
-		return;
-
-#ifdef __sparc__
-	if (par->mmaped)
-		return;
-#endif
-	fg_color = (u32) red[0] << 24;
-	fg_color |= (u32) green[0] << 16;
-	fg_color |= (u32) blue[0] << 8;
-	fg_color |= (u32) pixel[0];
-
-	bg_color = (u32) red[1] << 24;
-	bg_color |= (u32) green[1] << 16;
-	bg_color |= (u32) blue[1] << 8;
-	bg_color |= (u32) pixel[1];
-
-	wait_for_fifo(2, par);
-	aty_st_le32(CUR_CLR0, fg_color, par);
-	aty_st_le32(CUR_CLR1, bg_color, par);
-}
-
-void aty_set_cursor_shape(struct fb_info *info)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	struct fb_cursor *cursor = &info->cursor;
-	struct aty_cursor *c = par->cursor;
-	u8 m, b;
-	u8 __iomem *ram;
-	int x, y;
-
-	if (!c)
-		return;
-#ifdef __sparc__
-	if (par->mmaped)
-		return;
-#endif
-
-	ram = c->ram;
-	for (y = 0; y < cursor->image.height; y++) {
-		for (x = 0; x < cursor->image.width >> 2; x++) {
-			m = c->mask[x][y];
-			b = c->bits[x][y];
-			fb_writeb(cursor_mask_lookup[m >> 4] |
-				  cursor_bits_lookup[(b & m) >> 4], ram++);
-			fb_writeb(cursor_mask_lookup[m & 0x0f] |
-				  cursor_bits_lookup[(b & m) & 0x0f],
-				  ram++);
-		}
-		for (; x < 8; x++) {
-			fb_writeb(0xaa, ram++);
-			fb_writeb(0xaa, ram++);
-		}
-	}
-	fb_memset(ram, 0xaa, (64 - cursor->image.height) * 16);
-}
-
-static void aty_set_cursor(struct fb_info *info)
+int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	struct fb_cursor *cursor = &info->cursor;
-	struct aty_cursor *c = par->cursor;
 	u16 xoff, yoff;
 	int x, y;
 
-	if (!c)
-		return;
-
 #ifdef __sparc__
 	if (par->mmaped)
-		return;
+		return -EPERM;
 #endif
+	if (par->asleep)
+		return -EPERM;
 
-	if (cursor->enable) {
+	/* Hide cursor */
+	wait_for_fifo(1, par);
+	aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) & ~HWCURSOR_ENABLE, par);
+
+	/* set position */
+	if (cursor->set & FB_CUR_SETPOS) {
 		x = cursor->image.dx - cursor->hot.x - info->var.xoffset;
 		if (x < 0) {
 			xoff = -x;
@@ -136,107 +106,118 @@
 			yoff = 0;
 		}
 
+		/*
+		 * In doublescan mode, the cursor location also needs to be
+		 * doubled.
+		 */
+                if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
+			y<<=1;
 		wait_for_fifo(4, par);
-		aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1),
-			    par);
+		aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par);
 		aty_st_le32(CUR_HORZ_VERT_OFF,
 			    ((u32) (64 - cursor->image.height + yoff) << 16) | xoff,
 			    par);
 		aty_st_le32(CUR_HORZ_VERT_POSN, ((u32) y << 16) | x, par);
-		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
-			    | HWCURSOR_ENABLE, par);
-	} else {
-		wait_for_fifo(1, par);
-		aty_st_le32(GEN_TEST_CNTL,
-			    aty_ld_le32(GEN_TEST_CNTL,
-					par) & ~HWCURSOR_ENABLE, par);
 	}
-	if (par->blitter_may_be_busy)
-		wait_for_idle(par);
-}
-
-int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	struct aty_cursor *c = par->cursor;
-
-	if (!c)
-		return -1;
 
-#ifdef __sparc__
-	if (par->mmaped)
-		return 0;
-#endif
+	/* Set color map */
+	if (cursor->set & FB_CUR_SETCMAP) {
+		u32 fg_idx, bg_idx, fg, bg;
+
+		fg_idx = cursor->image.fg_color;
+		bg_idx = cursor->image.bg_color;
+
+		fg = (info->cmap.red[fg_idx] << 24) |
+		     (info->cmap.green[fg_idx] << 16) |
+		     (info->cmap.blue[fg_idx] << 8) | 15;
+
+		bg = (info->cmap.red[bg_idx] << 24) |
+		     (info->cmap.green[bg_idx] << 16) |
+		     (info->cmap.blue[bg_idx] << 8);
+
+		wait_for_fifo(2, par);
+		aty_st_le32(CUR_CLR0, bg, par);
+		aty_st_le32(CUR_CLR1, fg, par);
+	}
 
-	aty_set_cursor(info);
-	cursor->image.dx = info->cursor.image.dx;
-	cursor->image.dy = info->cursor.image.dy;
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+	    u8 *src = (u8 *)cursor->image.data;
+	    u8 *msk = (u8 *)cursor->mask;
+	    u8 __iomem *dst = (u8 __iomem *)info->sprite.addr;
+	    unsigned int width = (cursor->image.width + 7) >> 3;
+	    unsigned int height = cursor->image.height;
+	    unsigned int align = info->sprite.scan_align;
+
+	    unsigned int i, j, offset;
+	    u8 m, b;
+
+	    // Clear cursor image with 1010101010...
+	    fb_memset(dst, 0xaa, 1024);
+
+	    offset = align - width*2;
+
+	    for (i = 0; i < height; i++) {
+		for (j = 0; j < width; j++) {
+			b = *src++;
+			m = *msk++;
+			switch (cursor->rop) {
+			case ROP_XOR:
+			    // Upper 4 bits of mask data
+			    fb_writeb(cursor_mask_lookup[m >> 4 ] |
+				cursor_bits_lookup[(b ^ m) >> 4], dst++);
+			    // Lower 4 bits of mask
+			    fb_writeb(cursor_mask_lookup[m & 0x0f ] |
+				cursor_bits_lookup[(b ^ m) & 0x0f], dst++);
+			    break;
+			case ROP_COPY:
+			    // Upper 4 bits of mask data
+			    fb_writeb(cursor_mask_lookup[m >> 4 ] |
+				cursor_bits_lookup[(b & m) >> 4], dst++);
+			    // Lower 4 bits of mask
+			    fb_writeb(cursor_mask_lookup[m & 0x0f ] |
+				cursor_bits_lookup[(b & m) & 0x0f], dst++);
+			    break;
+			}
+		}
+		dst += offset;
+	    }
+	}
 
-	aty_set_cursor(info);
+	if (cursor->enable) {
+		wait_for_fifo(1, par);
+		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par)
+			    | HWCURSOR_ENABLE, par);
+	}
 	return 0;
 }
 
-struct aty_cursor *__init aty_init_cursor(struct fb_info *info)
+int __init aty_init_cursor(struct fb_info *info)
 {
-	struct aty_cursor *cursor;
-	void __iomem *addr;
-
-	cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
-	if (!cursor)
-		return NULL;
-	memset(cursor, 0, sizeof(*cursor));
+	unsigned long addr;
 
 	info->fix.smem_len -= PAGE_SIZE;
 
 #ifdef __sparc__
 	addr = (unsigned long) info->screen_base - 0x800000 + info->fix.smem_len;
-	cursor->ram = (u8 *) addr;
+	info->sprite.addr = (u8 *) addr;
 #else
 #ifdef __BIG_ENDIAN
 	addr = info->fix.smem_start - 0x800000 + info->fix.smem_len;
-	cursor->ram = (u8 *) ioremap(addr, 1024);
+	info->sprite.addr = (u8 *) ioremap(addr, 1024);
 #else
-	addr = info->screen_base + info->fix.smem_len;
-	cursor->ram = addr;
+	addr = (unsigned long) info->screen_base + info->fix.smem_len;
+	info->sprite.addr = (u8 *) addr;
 #endif
 #endif
-	if (!cursor->ram) {
-		kfree(cursor);
-		return NULL;
-	}
-	return cursor;
-}
+	if (!info->sprite.addr)
+		return -ENXIO;
+	info->sprite.size = PAGE_SIZE;
+	info->sprite.scan_align = 16;	/* Scratch pad 64 bytes wide */
+	info->sprite.buf_align = 16; 	/* and 64 lines tall. */
+	info->sprite.flags = FB_PIXMAP_IO;
 
-int atyfb_set_font(struct fb_info *info, int width, int height)
-{
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
-	struct fb_cursor *cursor = &info->cursor;
-	struct aty_cursor *c = par->cursor;
-	int i, j;
-
-	if (c) {
-		if (!width || !height) {
-			width = 8;
-			height = 16;
-		}
-
-		cursor->hot.x = 0;
-		cursor->hot.y = 0;
-		cursor->image.width = width;
-		cursor->image.height = height;
-
-		memset(c->bits, 0xff, sizeof(c->bits));
-		memset(c->mask, 0, sizeof(c->mask));
-
-		for (i = 0, j = width; j >= 0; j -= 8, i++) {
-			c->mask[i][height - 2] =
-			    (j >= 8) ? 0xff : (0xff << (8 - j));
-			c->mask[i][height - 1] =
-			    (j >= 8) ? 0xff : (0xff << (8 - j));
-		}
+	info->fbops->fb_cursor = atyfb_cursor;
 
-		aty_set_cursor_color(info);
-		aty_set_cursor_shape(info);
-	}
-	return 1;
+	return 0;
 }
+
diff -Nru a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c
--- a/drivers/video/aty/mach64_gx.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/video/aty/mach64_gx.c	2004-10-28 22:25:57 -07:00
@@ -121,7 +121,7 @@
 }
 
 static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per,
-			      u8 bpp, union aty_pll *pll)
+			      u32 bpp, union aty_pll *pll)
 {
 	/*
 	 *  FIXME: use real calculations instead of using fixed values from the old
@@ -253,9 +253,9 @@
 	temp = aty_ld_8(DAC_CNTL, par);
 	aty_st_8(DAC_CNTL, temp | DAC_EXT_SEL_RS2 | DAC_EXT_SEL_RS3, par);
 
-	if (info->fix.smem_len < MEM_SIZE_1M)
+	if (info->fix.smem_len < ONE_MB)
 		mask = 0x04;
-	else if (info->fix.smem_len == MEM_SIZE_1M)
+	else if (info->fix.smem_len == ONE_MB)
 		mask = 0x08;
 	else
 		mask = 0x0C;
@@ -339,8 +339,8 @@
      *  ATI 18818 / ICS 2595 Clock Chip
      */
 
-static int aty_var_to_pll_18818(const struct fb_info *info,
-				u32 vclk_per, u8 bpp, union aty_pll *pll)
+static int aty_var_to_pll_18818(const struct fb_info *info, u32 vclk_per,
+				u32 bpp, union aty_pll *pll)
 {
 	u32 MHz100;		/* in 0.01 MHz */
 	u32 program_bits;
@@ -495,8 +495,8 @@
      *  STG 1703 Clock Chip
      */
 
-static int aty_var_to_pll_1703(const struct fb_info *info,
-			       u32 vclk_per, u8 bpp, union aty_pll *pll)
+static int aty_var_to_pll_1703(const struct fb_info *info, u32 vclk_per,
+			       u32 bpp, union aty_pll *pll)
 {
 	u32 mhz100;		/* in 0.01 MHz */
 	u32 program_bits;
@@ -611,8 +611,8 @@
      *  Chrontel 8398 Clock Chip
      */
 
-static int aty_var_to_pll_8398(const struct fb_info *info,
-			       u32 vclk_per, u8 bpp, union aty_pll *pll)
+static int aty_var_to_pll_8398(const struct fb_info *info, u32 vclk_per,
+			       u32 bpp, union aty_pll *pll)
 {
 	u32 tempA, tempB, fOut, longMHz100, diff, preDiff;
 
@@ -736,7 +736,7 @@
      */
 
 static int aty_var_to_pll_408(const struct fb_info *info, u32 vclk_per,
-			      u8 bpp, union aty_pll *pll)
+			      u32 bpp, union aty_pll *pll)
 {
 	u32 mhz100;		/* in 0.01 MHz */
 	u32 program_bits;
diff -Nru a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
--- a/drivers/video/aty/radeon_base.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/video/aty/radeon_base.c	2004-10-28 22:25:57 -07:00
@@ -2186,7 +2186,9 @@
 	       		rinfo->video_ram = 8192 * 1024;
 	       		break;
 	       	default:
-	       		break;
+			printk (KERN_ERR "radeonfb: no video RAM reported\n");
+			ret = -ENXIO;
+			goto err_unmap_rom;
 		}
 	}
 
diff -Nru a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
--- a/drivers/video/aty/radeon_monitor.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/video/aty/radeon_monitor.c	2004-10-28 22:25:56 -07:00
@@ -7,10 +7,25 @@
 #endif /* CONFIG_PPC_OF */
 
 static struct fb_var_screeninfo radeonfb_default_var = {
-        640, 480, 640, 480, 0, 0, 8, 0,
-        {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-        0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,
-        0, FB_VMODE_NONINTERLACED
+	.xres		= 640,
+	.yres		= 480,
+	.xres_virtual	= 640,
+	.yres_virtual	= 480,
+	.bits_per_pixel = 8,
+	.red		= { 0, 6, 0 },
+	.green		= { 0, 6, 0 },
+	.blue		= { 0, 6, 0 },
+	.activate	= FB_ACTIVATE_NOW,
+	.height		= -1,
+	.width		= -1,
+	.pixclock	= 39721,
+	.left_margin	= 40,
+	.right_margin	= 24,
+	.upper_margin	= 32,
+	.lower_margin	= 11,
+	.hsync_len	= 96,
+	.vsync_len	= 2,
+	.vmode		= FB_VMODE_NONINTERLACED
 };
 
 static char *radeon_get_mon_name(int type)
diff -Nru a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c
--- a/drivers/video/aty/xlinit.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/video/aty/xlinit.c	2004-10-28 22:25:58 -07:00
@@ -148,15 +148,15 @@
 static void init_dll(struct atyfb_par *par)
 {
 	// enable DLL
-	aty_st_pll(PLL_GEN_CNTL,
-		   aty_ld_pll(PLL_GEN_CNTL, par) & 0x7f,
+	aty_st_pll_ct(PLL_GEN_CNTL,
+		   aty_ld_pll_ct(PLL_GEN_CNTL, par) & 0x7f,
 		   par);
 
 	// reset DLL
-	aty_st_pll(DLL_CNTL, 0x82, par);
-	aty_st_pll(DLL_CNTL, 0xE2, par);
+	aty_st_pll_ct(DLL_CNTL, 0x82, par);
+	aty_st_pll_ct(DLL_CNTL, 0xE2, par);
 	mdelay(5);
-	aty_st_pll(DLL_CNTL, 0x82, par);
+	aty_st_pll_ct(DLL_CNTL, 0x82, par);
 	mdelay(6);
 }
 
@@ -164,8 +164,8 @@
 			 int hsync_enb)
 {
 	reset_gui(par);
-	aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, par);
-	aty_st_pll(SCLK_FB_DIV, pll->sclk_fb_div, par);
+	aty_st_pll_ct(MCLK_FB_DIV, pll->mclk_fb_div, par);
+	aty_st_pll_ct(SCLK_FB_DIV, pll->sclk_fb_div, par);
 
 	mdelay(15);
 	init_dll(par);
@@ -177,9 +177,9 @@
 	aty_st_8(CRTC_GEN_CNTL+3,
 		 hsync_enb ? 0x00 : 0x04, par);
 
-	aty_st_pll(SPLL_CNTL2, pll->spll_cntl2, par);
-	aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
-	aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
+	aty_st_pll_ct(SPLL_CNTL2, pll->spll_cntl2, par);
+	aty_st_pll_ct(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
+	aty_st_pll_ct(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
 }
 
 int atyfb_xl_init(struct fb_info *info)
@@ -216,31 +216,31 @@
 	if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll)))
 		return err;
 
-	aty_st_pll(LVDS_CNTL0, 0x00, par);
-	aty_st_pll(DLL2_CNTL, card->dll2_cntl, par);
-	aty_st_pll(V2PLL_CNTL, 0x10, par);
-	aty_st_pll(MPLL_CNTL, MPLL_GAIN, par);
-	aty_st_pll(VPLL_CNTL, VPLL_GAIN, par);
-	aty_st_pll(PLL_VCLK_CNTL, 0x00, par);
-	aty_st_pll(VFC_CNTL, 0x1B, par);
-	aty_st_pll(PLL_REF_DIV, pll.ct.pll_ref_div, par);
-	aty_st_pll(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
-	aty_st_pll(SPLL_CNTL2, 0x03, par);
-	aty_st_pll(PLL_GEN_CNTL, 0x44, par);
+	aty_st_pll_ct(LVDS_CNTL0, 0x00, par);
+	aty_st_pll_ct(DLL2_CNTL, card->dll2_cntl, par);
+	aty_st_pll_ct(V2PLL_CNTL, 0x10, par);
+	aty_st_pll_ct(MPLL_CNTL, MPLL_GAIN, par);
+	aty_st_pll_ct(VPLL_CNTL, VPLL_GAIN, par);
+	aty_st_pll_ct(PLL_VCLK_CNTL, 0x00, par);
+	aty_st_pll_ct(VFC_CNTL, 0x1B, par);
+	aty_st_pll_ct(PLL_REF_DIV, pll.ct.pll_ref_div, par);
+	aty_st_pll_ct(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
+	aty_st_pll_ct(SPLL_CNTL2, 0x03, par);
+	aty_st_pll_ct(PLL_GEN_CNTL, 0x44, par);
 
 	reset_clocks(par, &pll.ct, 0);
 	mdelay(10);
 
-	aty_st_pll(VCLK_POST_DIV, 0x03, par);
-	aty_st_pll(VCLK0_FB_DIV, 0xDA, par);
-	aty_st_pll(VCLK_POST_DIV, 0x0F, par);
-	aty_st_pll(VCLK1_FB_DIV, 0xF5, par);
-	aty_st_pll(VCLK_POST_DIV, 0x3F, par);
-	aty_st_pll(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
-	aty_st_pll(VCLK2_FB_DIV, 0x00, par);
-	aty_st_pll(VCLK_POST_DIV, 0xFF, par);
-	aty_st_pll(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
-	aty_st_pll(VCLK3_FB_DIV, 0x00, par);
+	aty_st_pll_ct(VCLK_POST_DIV, 0x03, par);
+	aty_st_pll_ct(VCLK0_FB_DIV, 0xDA, par);
+	aty_st_pll_ct(VCLK_POST_DIV, 0x0F, par);
+	aty_st_pll_ct(VCLK1_FB_DIV, 0xF5, par);
+	aty_st_pll_ct(VCLK_POST_DIV, 0x3F, par);
+	aty_st_pll_ct(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
+	aty_st_pll_ct(VCLK2_FB_DIV, 0x00, par);
+	aty_st_pll_ct(VCLK_POST_DIV, 0xFF, par);
+	aty_st_pll_ct(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
+	aty_st_pll_ct(VCLK3_FB_DIV, 0x00, par);
 
 	aty_st_8(BUS_CNTL, 0x01, par);
 	aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, par);
@@ -295,7 +295,7 @@
 	aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
 	mdelay(10);
 
-	aty_st_pll(PLL_YCLK_CNTL, 0x25, par);
+	aty_st_pll_ct(PLL_YCLK_CNTL, 0x25, par);
 
 	aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, par);
 	aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, par);
@@ -309,9 +309,9 @@
 
 	aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, par);
 
-	aty_st_pll(PLL_YCLK_CNTL, 0x01, par);
+	aty_st_pll_ct(PLL_YCLK_CNTL, 0x01, par);
 	mdelay(15);
-	aty_st_pll(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
+	aty_st_pll_ct(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
 	mdelay(1);
 	
 	reset_clocks(par, &pll.ct, 0);
diff -Nru a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
--- a/drivers/video/console/bitblit.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/video/console/bitblit.c	2004-10-28 22:25:59 -07:00
@@ -239,118 +239,134 @@
 		       struct display *p, int mode, int fg, int bg)
 {
 	struct fb_cursor cursor;
+	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	int w = (vc->vc_font.width + 7) >> 3, c;
 	int y = real_y(p, vc->vc_y);
 	int attribute;
 	char *src;
 
+	cursor.set = 0;
+
  	c = scr_readw((u16 *) vc->vc_pos);
 	attribute = get_attribute(info, c);
 	src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+
+	if (ops->cursor_state.image.data != src) {
+	    ops->cursor_state.image.data = src;
+	    cursor.set |= FB_CUR_SETIMAGE;
+	}
+
 	if (attribute) {
 		u8 *dst;
 
 		dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
 		if (!dst)
 			return;
-		if (info->cursor.data)
-			kfree(info->cursor.data);
-		info->cursor.data = dst;
+		if (ops->cursor_data)
+			kfree(ops->cursor_data);
+		ops->cursor_data = dst;
 		update_attr(dst, src, attribute, vc);
 		src = dst;
 	}
 
-	cursor.image.data = src;
-	cursor.set = FB_CUR_SETCUR;
-	cursor.image.depth = 1;
+	if (ops->cursor_state.image.fg_color != fg ||
+	    ops->cursor_state.image.bg_color != bg) {
+		ops->cursor_state.image.fg_color = fg;
+		ops->cursor_state.image.bg_color = bg;
+		cursor.set |= FB_CUR_SETCMAP;
+	}
 
-	switch (mode) {
-	case CM_ERASE:
-		if (info->cursor.rop == ROP_XOR) {
-			info->cursor.enable = 0;
-			info->cursor.rop = ROP_COPY;
-			info->fbops->fb_cursor(info, &cursor);
-		}
-		break;
-	case CM_MOVE:
-	case CM_DRAW:
-		info->cursor.enable = 1;
-        	info->cursor.rop = ROP_XOR;
+	if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) ||
+	    (ops->cursor_state.image.dy != (vc->vc_font.height * y))) {
+		ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x;
+		ops->cursor_state.image.dy = vc->vc_font.height * y;
+		cursor.set |= FB_CUR_SETPOS;
+	}
 
-		if (info->cursor.image.fg_color != fg ||
-		    info->cursor.image.bg_color != bg) {
-			cursor.image.fg_color = fg;
-			cursor.image.bg_color = bg;
-			cursor.set |= FB_CUR_SETCMAP;
-		}
+	if (ops->cursor_state.image.height != vc->vc_font.height ||
+	    ops->cursor_state.image.width != vc->vc_font.width) {
+		ops->cursor_state.image.height = vc->vc_font.height;
+		ops->cursor_state.image.width = vc->vc_font.width;
+		cursor.set |= FB_CUR_SETSIZE;
+	}
 
-		if ((info->cursor.image.dx != (vc->vc_font.width * vc->vc_x)) ||
-		    (info->cursor.image.dy != (vc->vc_font.height * y))) {
-			cursor.image.dx = vc->vc_font.width * vc->vc_x;
-			cursor.image.dy = vc->vc_font.height * y;
-			cursor.set |= FB_CUR_SETPOS;
-		}
+	if (ops->cursor_state.hot.x || ops->cursor_state.hot.y) {
+		ops->cursor_state.hot.x = cursor.hot.y = 0;
+		cursor.set |= FB_CUR_SETHOT;
+	}
 
-		if (info->cursor.image.height != vc->vc_font.height ||
-		    info->cursor.image.width != vc->vc_font.width) {
-			cursor.image.height = vc->vc_font.height;
-			cursor.image.width = vc->vc_font.width;
-			cursor.set |= FB_CUR_SETSIZE;
-		}
+	if ((cursor.set & FB_CUR_SETSIZE) ||
+	    ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
+	    || ops->cursor_state.mask == NULL) {
+		char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
+		int cur_height, size, i = 0;
+		u8 msk = 0xff;
 
-		if (info->cursor.hot.x || info->cursor.hot.y) {
-			cursor.hot.x = cursor.hot.y = 0;
-			cursor.set |= FB_CUR_SETHOT;
-		}
+		if (!mask)
+			return;
 
-		if ((cursor.set & FB_CUR_SETSIZE) ||
-		    ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
-		    || info->cursor.mask == NULL) {
-			char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
-			int cur_height, size, i = 0;
-			u8 msk = 0xff;
-
-			if (!mask)
-				return;
-
-			if (info->cursor.mask)
-				kfree(info->cursor.mask);
-			info->cursor.mask = mask;
-			p->cursor_shape = vc->vc_cursor_type & 0x0f;
-			cursor.set |= FB_CUR_SETSHAPE;
-
-			switch (vc->vc_cursor_type & 0x0f) {
-			case CUR_NONE:
-				cur_height = 0;
-				break;
-			case CUR_UNDERLINE:
-				cur_height = (vc->vc_font.height < 10) ? 1 : 2;
-				break;
-			case CUR_LOWER_THIRD:
-				cur_height = vc->vc_font.height/3;
-				break;
-			case CUR_LOWER_HALF:
-				cur_height = vc->vc_font.height >> 1;
-				break;
-			case CUR_TWO_THIRDS:
-				cur_height = (vc->vc_font.height << 1)/3;
-				break;
-			case CUR_BLOCK:
-			default:
-				cur_height = vc->vc_font.height;
-				break;
-			}
-			size = (vc->vc_font.height - cur_height) * w;
-			while (size--)
-				mask[i++] = ~msk;
-			size = cur_height * w;
-			while (size--)
-				mask[i++] = msk;
-		}
-		info->fbops->fb_cursor(info, &cursor);
+		if (ops->cursor_state.mask)
+			kfree(ops->cursor_state.mask);
+		ops->cursor_state.mask = mask;
+		p->cursor_shape = vc->vc_cursor_type & 0x0f;
+		cursor.set |= FB_CUR_SETSHAPE;
+
+		switch (vc->vc_cursor_type & 0x0f) {
+		case CUR_NONE:
+			cur_height = 0;
+			break;
+		case CUR_UNDERLINE:
+			cur_height = (vc->vc_font.height < 10) ? 1 : 2;
+			break;
+		case CUR_LOWER_THIRD:
+			cur_height = vc->vc_font.height/3;
+			break;
+		case CUR_LOWER_HALF:
+			cur_height = vc->vc_font.height >> 1;
+			break;
+		case CUR_TWO_THIRDS:
+			cur_height = (vc->vc_font.height << 1)/3;
+			break;
+		case CUR_BLOCK:
+		default:
+			cur_height = vc->vc_font.height;
+			break;
+		}
+		size = (vc->vc_font.height - cur_height) * w;
+		while (size--)
+			mask[i++] = ~msk;
+		size = cur_height * w;
+		while (size--)
+			mask[i++] = msk;
+	}
+
+	switch (mode) {
+	case CM_ERASE:
+		ops->cursor_state.enable = 0;
+		break;
+	case CM_DRAW:
+	case CM_MOVE:
+	default:
+		ops->cursor_state.enable = 1;
 		break;
 	}
+
+	cursor.image.data = src;
+	cursor.image.fg_color = ops->cursor_state.image.fg_color;
+	cursor.image.bg_color = ops->cursor_state.image.bg_color;
+	cursor.image.dx = ops->cursor_state.image.dx;
+	cursor.image.dy = ops->cursor_state.image.dy;
+	cursor.image.height = ops->cursor_state.image.height;
+	cursor.image.width = ops->cursor_state.image.width;
+	cursor.hot.x = ops->cursor_state.hot.x;
+	cursor.hot.y = ops->cursor_state.hot.y;
+	cursor.mask = ops->cursor_state.mask;
+	cursor.enable = ops->cursor_state.enable;
+	cursor.image.depth = 1;
+	cursor.rop = ROP_XOR;
+
+	info->fbops->fb_cursor(info, &cursor);
 }
 
 void fbcon_set_bitops(struct fbcon_ops *ops)
diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
--- a/drivers/video/console/fbcon.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/video/console/fbcon.c	2004-10-28 22:25:58 -07:00
@@ -100,12 +100,20 @@
 #  define DPRINTK(fmt, args...)
 #endif
 
+enum {
+	FBCON_LOGO_CANSHOW	= -1,	/* the logo can be shown */
+	FBCON_LOGO_DRAW		= -2,	/* draw the logo to a console */
+	FBCON_LOGO_DONTSHOW	= -3	/* do not show the logo */
+};
+
 struct display fb_display[MAX_NR_CONSOLES];
 signed char con2fb_map[MAX_NR_CONSOLES];
 signed char con2fb_map_boot[MAX_NR_CONSOLES];
 static int logo_height;
 static int logo_lines;
-static int logo_shown = -1;
+/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
+   enums.  */
+static int logo_shown = FBCON_LOGO_CANSHOW;
 /* Software scrollback */
 int fbcon_softback_size = 32768;
 static unsigned long softback_buf, softback_curr;
@@ -234,8 +242,8 @@
 
 static void fb_flashcursor(void *private)
 {
-	struct fb_info *info = (struct fb_info *) private;
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fb_info *info = private;
+	struct fbcon_ops *ops = info->fbcon_par;
 	struct display *p;
 	struct vc_data *vc = NULL;
 	int c;
@@ -245,14 +253,15 @@
 		vc = vc_cons[info->currcon].d;
 
 	if (info->state != FBINFO_STATE_RUNNING ||
-	    !vc || !CON_IS_VISIBLE(vc) || !info->cursor.flash ||
+	    !vc || !CON_IS_VISIBLE(vc) ||
 	    vt_cons[vc->vc_num]->vc_mode != KD_TEXT ||
- 	    registered_fb[(int) con2fb_map[vc->vc_num]] != info)
+ 	    registered_fb[con2fb_map[vc->vc_num]] != info)
 		return;
+	acquire_console_sem();
 	p = &fb_display[vc->vc_num];
 	c = scr_readw((u16 *) vc->vc_pos);
-	acquire_console_sem();
-	mode = (info->cursor.enable) ? CM_ERASE : CM_DRAW;
+	mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
+		CM_ERASE : CM_DRAW;
 	ops->cursor(vc, info, p, mode, get_color(vc, info, c, 1),
 		    get_color(vc, info, c, 0));
 	release_console_sem();
@@ -337,24 +346,24 @@
 
 static int search_fb_in_map(int idx)
 {
-	int i;
+	int i, retval = 0;
 
 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
 		if (con2fb_map[i] == idx)
-			return 1;
+			retval = 1;
 	}
-	return 0;
+	return retval;
 }
 
 static int search_for_mapped_con(void)
 {
-	int i;
+	int i, retval = 0;
 
 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
 		if (con2fb_map[i] != -1)
-			return 1;
+			retval = 1;
 	}
-	return 0;
+	return retval;
 }
 
 static int fbcon_takeover(int show_logo)
@@ -365,7 +374,7 @@
 		return -ENODEV;
 
 	if (!show_logo)
-		logo_shown = -3;
+		logo_shown = FBCON_LOGO_DONTSHOW;
 
 	for (i = first_fb_vc; i <= last_fb_vc; i++)
 		con2fb_map[i] = info_idx;
@@ -447,11 +456,11 @@
 	}
 
 	if (logo_lines > vc->vc_bottom) {
-		logo_shown = -1;
+		logo_shown = FBCON_LOGO_CANSHOW;
 		printk(KERN_INFO
 		       "fbcon_init: disable boot-logo (boot-logo bigger than screen).\n");
-	} else if (logo_shown != -3) {
-		logo_shown = -2;
+	} else if (logo_shown != FBCON_LOGO_DONTSHOW) {
+		logo_shown = FBCON_LOGO_DRAW;
 		vc->vc_top = logo_lines;
 	}
 }
@@ -460,7 +469,7 @@
 static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
 			      struct display *p)
 {
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 
 	if ((info->flags & FBINFO_MISC_TILEBLITTING))
 		fbcon_set_tileops(vc, info, p, ops);
@@ -471,7 +480,7 @@
 static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
 			      struct display *p)
 {
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 
 	info->flags &= ~FBINFO_MISC_TILEBLITTING;
 	fbcon_set_bitops(ops);
@@ -533,6 +542,7 @@
 		}
 
 		if (!err) {
+			memset(ops, 0, sizeof(struct fbcon_ops));
 			info->fbcon_par = ops;
 			set_blitting_type(vc, info, NULL);
 		}
@@ -550,6 +560,8 @@
 	 * fbcon should release it.
 	 */
 	if (oldinfo && !search_fb_in_map(oldidx)) {
+		struct fbcon_ops *ops = (struct fbcon_ops *) oldinfo->fbcon_par;
+
 		if (oldinfo->fbops->fb_release &&
 		    oldinfo->fbops->fb_release(oldinfo, 0)) {
 			con2fb_map[unit] = oldidx;
@@ -564,6 +576,8 @@
 		if (oldinfo->queue.func == fb_flashcursor)
 			del_timer_sync(&oldinfo->cursor_timer);
 
+		kfree(ops->cursor_state.mask);
+		kfree(ops->cursor_data);
 		kfree(oldinfo->fbcon_par);
 		module_put(oldinfo->fbops->owner);
 	}
@@ -592,9 +606,9 @@
 	else
 		fbcon_preset_disp(info, unit);
 
-	if (fg_console == 0 && !user && logo_shown != -3) {
+	if (fg_console == 0 && !user && logo_shown != FBCON_LOGO_DONTSHOW) {
 		struct vc_data *vc = vc_cons[fg_console].d;
-		struct fb_info *fg_info = registered_fb[(int) con2fb_map[fg_console]];
+		struct fb_info *fg_info = registered_fb[con2fb_map[fg_console]];
 
 		fbcon_prepare_logo(vc, fg_info, vc->vc_cols, vc->vc_rows,
 				   vc->vc_cols, vc->vc_rows);
@@ -692,6 +706,7 @@
 		return NULL;
 	}
 
+	memset(ops, 0, sizeof(struct fbcon_ops));
 	info->fbcon_par = ops;
 	set_blitting_type(vc, info, NULL);
 
@@ -817,7 +832,7 @@
 
 static void fbcon_init(struct vc_data *vc, int init)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct vc_data **default_mode = vc->vc_display_fg;
 	struct vc_data *svc = *default_mode;
 	struct display *t, *p = &fb_display[vc->vc_num];
@@ -827,7 +842,7 @@
 
 	if (info_idx == -1 || info == NULL)
 	    return;
-	if (vc->vc_num != display_fg || logo_shown == -3 ||
+	if (vc->vc_num != display_fg || logo_shown == FBCON_LOGO_DONTSHOW ||
 	    (info->fix.type == FB_TYPE_TEXT))
 		logo = 0;
 
@@ -957,8 +972,8 @@
 static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
 			int width)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+	struct fbcon_ops *ops = info->fbcon_par;
 
 	struct display *p = &fb_display[vc->vc_num];
 	u_int y_break;
@@ -986,9 +1001,9 @@
 static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
 			int count, int ypos, int xpos)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 
 	if (!info->fbops->fb_blank && console_blanked)
 		return;
@@ -1005,32 +1020,35 @@
 
 static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
 {
-	fbcon_putcs(vc, (const unsigned short *) &c, 1, ypos, xpos);
+	unsigned short chr;
+
+	scr_writew(c, &chr);
+	fbcon_putcs(vc, &chr, 1, ypos, xpos);
 }
 
 static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+	struct fbcon_ops *ops = info->fbcon_par;
 
 	ops->clear_margins(vc, info, bottom_only);
 }
 
 static void fbcon_cursor(struct vc_data *vc, int mode)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+	struct fbcon_ops *ops = info->fbcon_par;
 	struct display *p = &fb_display[vc->vc_num];
 	int y = real_y(p, vc->vc_y);
  	int c = scr_readw((u16 *) vc->vc_pos);
 
-	info->cursor.flash = 1;
+	ops->cursor_flash = 1;
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
 		if (softback_lines) {
 			if (y + softback_lines >= vc->vc_rows) {
 				mode = CM_ERASE;
-				info->cursor.flash = 0;
+				ops->cursor_flash = 0;
 			}
 			else
 				y += softback_lines;
@@ -1132,7 +1150,7 @@
 
 static __inline__ void ywrap_up(struct vc_data *vc, int count)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	
 	p->yscroll += count;
@@ -1150,7 +1168,7 @@
 
 static __inline__ void ywrap_down(struct vc_data *vc, int count)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	
 	p->yscroll -= count;
@@ -1168,9 +1186,9 @@
 
 static __inline__ void ypan_up(struct vc_data *vc, int count)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 
 	p->yscroll += count;
 	if (p->yscroll > p->vrows - vc->vc_rows) {
@@ -1191,7 +1209,7 @@
 
 static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	int redraw = 0;
 
@@ -1216,9 +1234,9 @@
 
 static __inline__ void ypan_down(struct vc_data *vc, int count)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 	
 	p->yscroll -= count;
 	if (p->yscroll < 0) {
@@ -1239,7 +1257,7 @@
 
 static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	int redraw = 0;
 
@@ -1471,9 +1489,9 @@
 static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
 			int count)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fbcon_ops *ops = info->fbcon_par;
 	int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK;
 
 	if (!info->fbops->fb_blank && console_blanked)
@@ -1666,7 +1684,7 @@
 static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
 			int height, int width)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	
 	if (!info->fbops->fb_blank && console_blanked)
@@ -1689,8 +1707,8 @@
 static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, 
 			    int dy, int dx, int height, int width, u_int y_break)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+	struct fbcon_ops *ops = info->fbcon_par;
 	u_int b;
 
 	if (sy < y_break && sy + height > y_break) {
@@ -1767,7 +1785,7 @@
 static int fbcon_resize(struct vc_data *vc, unsigned int width, 
 			unsigned int height)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	struct fb_var_screeninfo var = info->var;
 	int x_diff, y_diff;
@@ -1824,7 +1842,7 @@
 	struct fb_var_screeninfo var;
 	int i, prev_console, do_set_par = 0;
 
-	info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	info = registered_fb[con2fb_map[vc->vc_num]];
 	if (softback_top) {
 		int l = fbcon_softback_size / vc->vc_size_row;
 		if (softback_lines)
@@ -1846,7 +1864,7 @@
 		if (conp2->vc_top == logo_lines
 		    && conp2->vc_bottom == conp2->vc_rows)
 			conp2->vc_top = 0;
-		logo_shown = -1;
+		logo_shown = FBCON_LOGO_CANSHOW;
 	}
 
 	prev_console = info->currcon;
@@ -1877,7 +1895,7 @@
 	fb_set_var(info, &var);
 
 	if (prev_console != -1 &&
-	    registered_fb[(int) con2fb_map[prev_console]] != info)
+	    registered_fb[con2fb_map[prev_console]] != info)
 		do_set_par = 1;
 
 	if (do_set_par || info->flags & FBINFO_MISC_MODESWITCH) {
@@ -1914,7 +1932,7 @@
 
 	if (vt_cons[vc->vc_num]->vc_mode == KD_TEXT)
 		fbcon_clear_margins(vc, 0);
-	if (logo_shown == -2) {
+	if (logo_shown == FBCON_LOGO_DRAW) {
 
 		logo_shown = fg_console;
 		/* This is protected above by initmem_freed */
@@ -1931,7 +1949,8 @@
 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
 {
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
 	struct display *p = &fb_display[vc->vc_num];
 
 	if (mode_switch) {
@@ -1961,7 +1980,7 @@
 	}
 
 	fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
-	info->cursor.flash = (!blank);
+	ops->cursor_flash = (!blank);
 
 	if (!info->fbops->fb_blank) {
 		if (blank) {
@@ -2049,7 +2068,7 @@
 static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
 			     u8 * data, int userfont)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	int resize;
 	int cnt;
@@ -2261,7 +2280,7 @@
 
 static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct font_desc *f;
 
 	if (!name)
@@ -2284,7 +2303,7 @@
 
 static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
+	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	int i, j, k, depth;
 	u8 val;
 
@@ -2393,7 +2412,7 @@
 
 static int fbcon_scrolldelta(struct vc_data *vc, int lines)
 {
-	struct fb_info *info = registered_fb[(int) con2fb_map[fg_console]];
+	struct fb_info *info = registered_fb[con2fb_map[fg_console]];
 	struct display *p = &fb_display[fg_console];
 	int offset, limit, scrollback_old;
 
@@ -2429,7 +2448,7 @@
 				update_region(vc->vc_num, vc->vc_origin,
 					      logo_lines * vc->vc_cols);
 			}
-			logo_shown = -1;
+			logo_shown = FBCON_LOGO_CANSHOW;
 		}
 		fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
 		fbcon_redraw_softback(vc, p, lines);
@@ -2555,7 +2574,7 @@
 
 	/* before deletion, ensure that mode is not in use */
 	for (i = first_fb_vc; i <= last_fb_vc; i++) {
-		j = (int) con2fb_map[i];
+		j = con2fb_map[i];
 		if (j == -1)
 			continue;
 		fb_info = registered_fb[j];
@@ -2598,7 +2617,7 @@
 static int fbcon_event_notify(struct notifier_block *self, 
 			      unsigned long action, void *data)
 {
-	struct fb_event *event = (struct fb_event *) data;
+	struct fb_event *event = data;
 	struct fb_info *info = event->info;
 	struct fb_videomode *mode;
 	struct fb_con2fbmap *con2fb;
@@ -2615,19 +2634,19 @@
 		fbcon_modechanged(info);
 		break;
 	case FB_EVENT_MODE_DELETE:
-		mode = (struct fb_videomode *) event->data;
+		mode = event->data;
 		ret = fbcon_mode_deleted(info, mode);
 		break;
 	case FB_EVENT_FB_REGISTERED:
 		ret = fbcon_fb_registered(info->node);
 		break;
 	case FB_EVENT_SET_CONSOLE_MAP:
-		con2fb = (struct fb_con2fbmap *) event->data;
+		con2fb = event->data;
 		ret = set_con2fb_map(con2fb->console - 1,
 				     con2fb->framebuffer, 1);
 		break;
 	case FB_EVENT_GET_CONSOLE_MAP:
-		con2fb = (struct fb_con2fbmap *) event->data;
+		con2fb = event->data;
 		con2fb->framebuffer = con2fb_map[con2fb->console - 1];
 		break;
 	}
diff -Nru a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
--- a/drivers/video/console/fbcon.h	2004-10-28 22:25:58 -07:00
+++ b/drivers/video/console/fbcon.h	2004-10-28 22:25:58 -07:00
@@ -60,6 +60,10 @@
 			      int bottom_only);
 	void (*cursor)(struct vc_data *vc, struct fb_info *info,
 		       struct display *p, int mode, int fg, int bg);
+
+	struct fb_cursor cursor_state;
+	int    cursor_flash;
+	char  *cursor_data;
 };
     /*
      *  Attribute Decoding
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	2004-10-28 22:25:56 -07:00
+++ b/drivers/video/fbmem.c	2004-10-28 22:25:56 -07:00
@@ -51,7 +51,7 @@
      *  Frame buffer device initialization and setup routines
      */
 
-#define FBPIXMAPSIZE	16384
+#define FBPIXMAPSIZE	(1024 * 8)
 
 static struct notifier_block *fb_notifier_list;
 struct fb_info *registered_fb[FB_MAX];
@@ -652,116 +652,6 @@
 }
 #endif /* CONFIG_KMOD */
 
-void
-fb_load_cursor_image(struct fb_info *info)
-{
-	unsigned int width = (info->cursor.image.width + 7) >> 3;
-	u8 *data = (u8 *) info->cursor.image.data;
-
-	if (info->sprite.outbuf)
-	    info->sprite.outbuf(info, info->sprite.addr, data,
-				width);
-	else
-	    memcpy(info->sprite.addr, data, width);
-}
-
-int
-fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
-{
-	struct fb_cursor_user cursor_user;
-	struct fb_cursor cursor;
-	char *data = NULL, *mask = NULL, *info_mask = NULL;
-	u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL;
-	int err = -EINVAL;
-	
-	if (copy_from_user(&cursor_user, sprite, sizeof(struct fb_cursor_user)))
-		return -EFAULT;
-
-	memcpy(&cursor, &cursor_user, sizeof(cursor_user));
-	cursor.mask = info->cursor.mask;
-	cursor.image.data = info->cursor.image.data;
-	cursor.image.cmap.red = info->cursor.image.cmap.red;
-	cursor.image.cmap.green = info->cursor.image.cmap.green;
-	cursor.image.cmap.blue = info->cursor.image.cmap.blue;
-	cursor.image.cmap.transp = info->cursor.image.cmap.transp;
-	cursor.data = NULL;
-	cursor.flash = 0;
-
-	if (cursor.set & FB_CUR_SETCUR)
-		info->cursor.enable = 1;
-	
-	if (cursor.set & FB_CUR_SETCMAP) {
-		unsigned len = cursor.image.cmap.len;
-		if ((int)len <= 0)
-			goto out;
-		len *= 2;
-		err = -ENOMEM;
-		red = kmalloc(len, GFP_USER);
-		green = kmalloc(len, GFP_USER);
-		blue = kmalloc(len, GFP_USER);
-		if (!red || !green || !blue)
-			goto out;
-		if (cursor_user.image.cmap.transp) {
-			transp = kmalloc(len, GFP_USER);
-			if (!transp)
-				goto out;
-		}
-		err = -EFAULT;
-		if (copy_from_user(red, cursor_user.image.cmap.red, len))
-			goto out;
-		if (copy_from_user(green, cursor_user.image.cmap.green, len))
-			goto out;
-		if (copy_from_user(blue, cursor_user.image.cmap.blue, len))
-			goto out;
-		if (transp) {
-			if (copy_from_user(transp,
-					   cursor_user.image.cmap.transp, len))
-				goto out;
-		}
-		cursor.image.cmap.red = red;
-		cursor.image.cmap.green = green;
-		cursor.image.cmap.blue = blue;
-		cursor.image.cmap.transp = transp;
-	}
-	
-	if (cursor.set & FB_CUR_SETSHAPE) {
-		int size = ((cursor.image.width + 7) >> 3) * cursor.image.height;		
-
-		if ((cursor.image.height != info->cursor.image.height) ||
-		    (cursor.image.width != info->cursor.image.width))
-			cursor.set |= FB_CUR_SETSIZE;
-		
-		err = -ENOMEM;
-		data = kmalloc(size, GFP_USER);
-		mask = kmalloc(size, GFP_USER);
-		if (!mask || !data)
-			goto out;
-		
-		err = -EFAULT;
-		if (copy_from_user(data, cursor_user.image.data, size) ||
-		    copy_from_user(mask, cursor_user.mask, size))
-			goto out;
-		
-		cursor.image.data = data;
-		cursor.mask = mask;
-		info_mask = (char *) info->cursor.mask;
-		info->cursor.mask = mask;
-	}
-	info->cursor.set = cursor.set;
-	info->cursor.rop = cursor.rop;
-	err = info->fbops->fb_cursor(info, &cursor);
-out:
-	kfree(data);
-	kfree(mask);
-	kfree(red);
-	kfree(green);
-	kfree(blue);
-	kfree(transp);
-	if (info_mask)
-		info->cursor.mask = info_mask;
-	return err;
-}
-
 int
 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
 {
@@ -860,17 +750,19 @@
 	
 	if (info->fbops->fb_blank && !info->fbops->fb_blank(blank, info))
 		return 0;
+
+	cmap = info->cmap;
+
 	if (blank) { 
 		black = kmalloc(sizeof(u16) * info->cmap.len, GFP_KERNEL);
-		if (!black) {
+		if (black) {
 			memset(black, 0, info->cmap.len * sizeof(u16));
 			cmap.red = cmap.green = cmap.blue = black;
 			cmap.transp = info->cmap.transp ? black : NULL;
 			cmap.start = info->cmap.start;
 			cmap.len = info->cmap.len;
 		}
-	} else
-		cmap = info->cmap;
+	}
 
 	err = fb_set_cmap(&cmap, info);
 	kfree(black);
@@ -934,10 +826,7 @@
 			return -EFAULT;
 		return 0;
 	case FBIO_CURSOR:
-		acquire_console_sem();
-		i = fb_cursor(info, argp);
-		release_console_sem();
-		return i;
+		return -EINVAL;
 	case FBIOGET_CON2FBMAP:
 		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
 			return -EFAULT;
@@ -1175,18 +1064,6 @@
 	}	
 	fb_info->pixmap.offset = 0;
 
-	if (fb_info->sprite.addr == NULL) {
-		fb_info->sprite.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
-		if (fb_info->sprite.addr) {
-			fb_info->sprite.size = FBPIXMAPSIZE;
-			fb_info->sprite.buf_align = 1;
-			fb_info->sprite.scan_align = 1;
-			fb_info->sprite.access_align = 4;
-			fb_info->sprite.flags = FB_PIXMAP_DEFAULT;
-		}
-	}
-	fb_info->sprite.offset = 0;
-
 	if (!fb_info->modelist.prev ||
 	    !fb_info->modelist.next ||
 	    list_empty(&fb_info->modelist)) {
@@ -1230,8 +1107,6 @@
 
 	if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->pixmap.addr);
-	if (fb_info->sprite.addr && (fb_info->sprite.flags & FB_PIXMAP_DEFAULT))
-		kfree(fb_info->sprite.addr);
 	fb_destroy_modelist(&fb_info->modelist);
 	registered_fb[i]=NULL;
 	num_registered_fb--;
@@ -1307,8 +1182,7 @@
 }
 module_init(fbmem_init);
 
-#define NR_FB_DRIVERS 64
-static char *video_options[NR_FB_DRIVERS];
+static char *video_options[FB_MAX];
 static int ofonly;
 
 /**
@@ -1329,7 +1203,7 @@
 		retval = 1;
 
 	if (name_len && !retval) {
-		for (i = 0; i < NR_FB_DRIVERS; i++) {
+		for (i = 0; i < FB_MAX; i++) {
 			if (video_options[i] == NULL)
 				continue;
 			opt_len = strlen(video_options[i]);
@@ -1371,7 +1245,7 @@
 	if (!options || !*options)
 		return 0;
 
-	for (i = 0; i < NR_FB_DRIVERS; i++) {
+	for (i = 0; i < FB_MAX; i++) {
 		if (!strncmp(options, "ofonly", 6))
 			ofonly = 1;
 		if (video_options[i] == NULL) {
@@ -1402,7 +1276,6 @@
 EXPORT_SYMBOL(fb_iomove_buf_aligned);
 EXPORT_SYMBOL(fb_sysmove_buf_unaligned);
 EXPORT_SYMBOL(fb_sysmove_buf_aligned);
-EXPORT_SYMBOL(fb_load_cursor_image);
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
diff -Nru a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
--- a/drivers/video/i810/i810.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/video/i810/i810.h	2004-10-28 22:25:59 -07:00
@@ -251,7 +251,6 @@
 	struct heap_data         iring;
 	struct heap_data         cursor_heap;
 	struct vgastate          state;
-	drm_agp_t                *drm_agp;
 	atomic_t                 use_count;
 	u32 pseudo_palette[17];
 	unsigned long mmio_start_phys;
diff -Nru a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
--- a/drivers/video/i810/i810_main.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/video/i810/i810_main.c	2004-10-28 22:25:57 -07:00
@@ -1416,62 +1416,50 @@
 
 	i810_enable_cursor(mmio, OFF);
 
-	if (cursor->set & FB_CUR_SETHOT)
-		info->cursor.hot = cursor->hot;
-	
 	if (cursor->set & FB_CUR_SETPOS) {
 		u32 tmp;
 
-		info->cursor.image.dx = cursor->image.dx;
-		info->cursor.image.dy = cursor->image.dy;
-		tmp = (info->cursor.image.dx - info->var.xoffset) & 0xffff;
-		tmp |= (info->cursor.image.dy - info->var.yoffset) << 16;
+		tmp = (cursor->image.dx - info->var.xoffset) & 0xffff;
+		tmp |= (cursor->image.dy - info->var.yoffset) << 16;
 		i810_writel(CURPOS, mmio, tmp);
 	}
 
-	if (cursor->set & FB_CUR_SETSIZE) {
+	if (cursor->set & FB_CUR_SETSIZE)
 		i810_reset_cursor_image(par);
-		info->cursor.image.height = cursor->image.height;
-		info->cursor.image.width = cursor->image.width;
-	}
 
-	if (cursor->set & FB_CUR_SETCMAP) {
+	if (cursor->set & FB_CUR_SETCMAP)
 		i810_load_cursor_colors(cursor->image.fg_color,
 					cursor->image.bg_color,
 					info);
-		info->cursor.image.fg_color = cursor->image.fg_color;
-		info->cursor.image.bg_color = cursor->image.bg_color;
-
-	}
 
-	if (cursor->set & (FB_CUR_SETSHAPE)) {
-		int size = ((info->cursor.image.width + 7) >> 3) * 
-			info->cursor.image.height;
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
+		int size = ((cursor->image.width + 7) >> 3) *
+			cursor->image.height;
 		int i;
 		u8 *data = kmalloc(64 * 8, GFP_KERNEL);
 
 		if (data == NULL)
 			return -ENOMEM;
-		info->cursor.image.data = cursor->image.data;
 
-		switch (info->cursor.rop) {
+		switch (cursor->rop) {
 		case ROP_XOR:
 			for (i = 0; i < size; i++)
-				data[i] = info->cursor.image.data[i] ^ info->cursor.mask[i];
+				data[i] = cursor->image.data[i] ^ cursor->mask[i];
 			break;
 		case ROP_COPY:
 		default:
 			for (i = 0; i < size; i++)
-				data[i] = info->cursor.image.data[i] & info->cursor.mask[i];
+				data[i] = cursor->image.data[i] & cursor->mask[i];
 			break;
 		}
-		i810_load_cursor_image(info->cursor.image.width, 
-				       info->cursor.image.height, data,
+
+		i810_load_cursor_image(cursor->image.width,
+				       cursor->image.height, data,
 				       par);
 		kfree(data);
 	}
 
-	if (info->cursor.enable)
+	if (cursor->enable)
 		i810_enable_cursor(mmio, ON);
 
 	return 0;
@@ -1523,8 +1511,8 @@
 	info->fbops->fb_blank(blank, info);
 
 	if (!prev_state) { 
-		par->drm_agp->unbind_memory(par->i810_gtt.i810_fb_memory);
-		par->drm_agp->unbind_memory(par->i810_gtt.i810_cursor_memory);
+		agp_unbind_memory(par->i810_gtt.i810_fb_memory);
+		agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
 		pci_disable_device(dev);
 	}
 	pci_save_state(dev);
@@ -1544,10 +1532,10 @@
 	pci_restore_state(dev);
 	pci_set_power_state(dev, 0);
 	pci_enable_device(dev);
-	par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory, 
-				  par->fb.offset);
-	par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory, 
-				  par->cursor_heap.offset);
+	agp_bind_memory(par->i810_gtt.i810_fb_memory,
+			par->fb.offset);
+	agp_bind_memory(par->i810_gtt.i810_cursor_memory,
+			par->cursor_heap.offset);
 
 	info->fbops->fb_blank(VESA_NO_BLANKING, info);
 
@@ -1599,39 +1587,36 @@
 	i810_fix_offsets(par);
 	size = par->fb.size + par->iring.size;
 
-	par->drm_agp = (drm_agp_t *) inter_module_get("drm_agp");
-	if (!par->drm_agp) {
-		printk("i810fb: cannot acquire agp\n");
+	if (agp_backend_acquire()) {
+		printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
 		return -ENODEV;
 	}
-	par->drm_agp->acquire(); 
-
 	if (!(par->i810_gtt.i810_fb_memory = 
-	      par->drm_agp->allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) {
+	      agp_allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) {
 		printk("i810fb_alloc_fbmem: can't allocate framebuffer "
 		       "memory\n");
-		par->drm_agp->release();
+		agp_backend_release();
 		return -ENOMEM;
 	}
-	if (par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory, 
-				      par->fb.offset)) {
+	if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
+			    par->fb.offset)) {
 		printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
-		par->drm_agp->release();
+		agp_backend_release();
 		return -EBUSY;
 	}	
 	
 	if (!(par->i810_gtt.i810_cursor_memory = 
-	      par->drm_agp->allocate_memory(par->cursor_heap.size >> 12, 
-					    AGP_PHYSICAL_MEMORY))) {
+	      agp_allocate_memory(par->cursor_heap.size >> 12,
+				  AGP_PHYSICAL_MEMORY))) {
 		printk("i810fb_alloc_cursormem:  can't allocate" 
 		       "cursor memory\n");
-		par->drm_agp->release();
+		agp_backend_release();
 		return -ENOMEM;
 	}
-	if (par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory, 
+	if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
 			    par->cursor_heap.offset)) {
 		printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
-		par->drm_agp->release();
+		agp_backend_release();
 		return -EBUSY;
 	}	
 
@@ -1639,7 +1624,7 @@
 
 	i810_fix_pointers(par);
 
-	par->drm_agp->release();
+	agp_backend_release();
 
 	return 0;
 }
@@ -1874,12 +1859,12 @@
 	par = (struct i810fb_par *) info->par;
 	par->dev = dev;
 
-	if (!(info->pixmap.addr = kmalloc(64*1024, GFP_KERNEL))) {
+	if (!(info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL))) {
 		i810fb_release_resource(info, par);
 		return -ENOMEM;
 	}
-	memset(info->pixmap.addr, 0, 64*1024);
-	info->pixmap.size = 64*1024;
+	memset(info->pixmap.addr, 0, 8*1024);
+	info->pixmap.size = 8*1024;
 	info->pixmap.buf_align = 8;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
@@ -1945,19 +1930,13 @@
 static void i810fb_release_resource(struct fb_info *info, 
 				    struct i810fb_par *par)
 {
+	struct gtt_data *gtt = &par->i810_gtt;
 	unset_mtrr(par);
-	if (par->drm_agp) {
-		drm_agp_t *agp = par->drm_agp;
-		struct gtt_data *gtt = &par->i810_gtt;
-
-		if (par->i810_gtt.i810_cursor_memory)
-			agp->free_memory(gtt->i810_cursor_memory);
-		if (par->i810_gtt.i810_fb_memory)
-			agp->free_memory(gtt->i810_fb_memory);
 
-		inter_module_put("drm_agp");
-		par->drm_agp = NULL;
-	}
+	if (par->i810_gtt.i810_cursor_memory)
+		agp_free_memory(gtt->i810_cursor_memory);
+	if (par->i810_gtt.i810_fb_memory)
+		agp_free_memory(gtt->i810_fb_memory);
 
 	if (par->mmio_start_virtual)
 		iounmap(par->mmio_start_virtual);
diff -Nru a/drivers/video/intelfb/Makefile b/drivers/video/intelfb/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/intelfb/Makefile	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,8 @@
+obj-$(CONFIG_FB_INTEL) += intelfb.o
+
+intelfb-objs := intelfbdrv.o intelfbhw.o
+
+ifdef CONFIG_FB_INTEL_DEBUG
+#EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP
+EXTRA_CFLAGS += -DDEBUG -DREGDUMP
+endif
diff -Nru a/drivers/video/intelfb/builtinmodes.c b/drivers/video/intelfb/builtinmodes.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/intelfb/builtinmodes.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,222 @@
+
+/*
+ * THIS FILE IS AUTOMATICALLY GENERATED BY fbmode.pl -- DO NOT EDIT
+ */
+
+static struct fb_videomode modedb[] = {
+    {
+	/* 640x350 @ 85 Hz, 37.9 kHz hsync */
+	"640x350@85", 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
+	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 640x400 @ 85 Hz, 37.9 kHz hsync */
+	"640x400@85", 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 720x400 @ 85 Hz, 37.9 kHz hsync */
+	"720x400@85", 85, 720, 400, 28169, 108, 36, 42, 1, 72, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 640x480 @ 60 Hz, 31.5 kHz hsync */
+	"640x480@60", 60, 640, 480, 39683, 48, 16, 33, 10, 96, 2,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 640x480 @ 73 Hz, 37.9 kHz hsync */
+	"640x480@73", 73, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 640x480 @ 75 Hz, 37.5 kHz hsync */
+	"640x480@75", 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 640x480 @ 85 Hz, 43.3 kHz hsync */
+	"640x480@85", 85, 640, 480, 27778, 80, 56, 25, 1, 56, 3,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 800x600 @ 56 Hz, 35.2 kHz hsync */
+	"800x600@56", 56, 800, 600, 27778, 128, 24, 22, 1, 72, 2,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 800x600 @ 60 Hz, 37.9 kHz hsync */
+	"800x600@60", 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 800x600 @ 72 Hz, 48.1 kHz hsync */
+	"800x600@72", 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 800x600 @ 75 Hz, 46.9 kHz hsync */
+	"800x600@75", 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 800x600 @ 85 Hz, 53.7 kHz hsync */
+	"800x600@85", 85, 800, 600, 17762, 152, 32, 27, 1, 64, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1024x768 @ 60 Hz, 48.4 kHz hsync */
+	"1024x768@60", 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1024x768 @ 70 Hz, 56.5 kHz hsync */
+	"1024x768@70", 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1024x768 @ 75 Hz, 60.1 kHz hsync */
+	"1024x768@75", 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1024x768 @ 85 Hz, 68.7 kHz hsync */
+	"1024x768@85", 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1152x864 @ 75 Hz, 67.5 kHz hsync */
+	"1152x864@75", 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1280x960 @ 60 Hz, 60.0 kHz hsync */
+	"1280x960@60", 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1280x960 @ 85 Hz, 85.9 kHz hsync */
+	"1280x960@85", 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1280x1024 @ 60 Hz, 64.0 kHz hsync */
+	"1280x1024@60", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1280x1024 @ 75 Hz, 80.0 kHz hsync */
+	"1280x1024@75", 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1280x1024 @ 85 Hz, 91.1 kHz hsync */
+	"1280x1024@85", 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1600x1200 @ 60 Hz, 75.0 kHz hsync */
+	"1600x1200@60", 60, 1600, 1200, 6173, 304, 64, 46, 1, 192, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1600x1200 @ 65 Hz, 81.2 kHz hsync */
+	"1600x1200@65", 65, 1600, 1200, 5698, 304, 64, 46, 1, 192, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1600x1200 @ 70 Hz, 87.5 kHz hsync */
+	"1600x1200@70", 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1600x1200 @ 75 Hz, 93.8 kHz hsync */
+	"1600x1200@75", 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1600x1200 @ 85 Hz, 106.2 kHz hsync */
+	"1600x1200@85", 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1792x1344 @ 60 Hz, 83.7 kHz hsync */
+	"1792x1344@60", 60, 1792, 1344, 4883, 328, 128, 46, 1, 200, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1792x1344 @ 75 Hz, 106.3 kHz hsync */
+	"1792x1344@75", 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1856x1392 @ 60 Hz, 86.4 kHz hsync */
+	"1856x1392@60", 60, 1856, 1392, 4581, 352, 96, 43, 1, 224, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1856x1392 @ 75 Hz, 112.5 kHz hsync */
+	"1856x1392@75", 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1920x1440 @ 60 Hz, 90.0 kHz hsync */
+	"1920x1440@60", 60, 1920, 1440, 4274, 344, 128, 56, 1, 208, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1920x1440 @ 75 Hz, 112.5 kHz hsync */
+	"1920x1440@75", 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 832x624 @ 75 Hz, 49.7 kHz hsync */
+	"832x624@75", 75, 832, 624, 17457, 224, 32, 39, 1, 64, 3,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1152x768 @ 55 Hz, 44.2 kHz hsync */
+	"1152x768@55", 55, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1400x1050 @ 60 Hz, 64.9 kHz hsync */
+	"1400x1050@60", 60, 1400, 1050, 8197, 240, 88, 18, 2, 152, 12,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1400x1050 @ 75 Hz, 81.5 kHz hsync */
+	"1400x1050@75", 75, 1400, 1050, 6418, 128, 64, 26, 2, 320, 12,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1600x1024 @ 60 Hz, 64.0 kHz hsync */
+	"1600x1024@60", 60, 1600, 1024, 9354, 30, 20, 37, 3, 20, 3,
+	0, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 1920x1440 @ 85 Hz, 128.5 kHz hsync */
+	"1920x1440@85", 85, 1920, 1440, 2930, 368, 152, 68, 1, 216, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 2048x1536 @ 60 Hz, 95.3 kHz hsync */
+	"2048x1536@60", 60, 2048, 1536, 3746, 376, 152, 49, 1, 224, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 2048x1536 @ 75 Hz, 120.2 kHz hsync */
+	"2048x1536@75", 75, 2048, 1536, 2937, 392, 168, 63, 1, 224, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    },
+    {
+	/* 2048x1536 @ 85 Hz, 137.0 kHz hsync */
+	"2048x1536@85", 85, 2048, 1536, 2577, 392, 168, 72, 1, 224, 3,
+	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }
+};
+
+static int num_modes = sizeof(modedb) / sizeof(modedb[0]);
+
+#define DFLT_MODE 3
+
diff -Nru a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/intelfb/intelfb.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,294 @@
+#ifndef _INTELFB_H
+#define _INTELFB_H
+
+/* $DHD: intelfb/intelfb.h,v 1.40 2003/06/27 15:06:25 dawes Exp $ */
+
+#include <linux/agp_backend.h>
+#include <linux/fb.h>
+
+
+/*** Version/name ***/
+#define INTELFB_VERSION			"0.9.0"
+#define INTELFB_MODULE_NAME		"intelfb"
+#define SUPPORTED_CHIPSETS		"830M/845G/852GM/855GM/865G"
+
+
+/*** Debug/feature defines ***/
+
+#ifndef DEBUG
+#define DEBUG				0
+#endif
+
+#ifndef VERBOSE
+#define VERBOSE				0
+#endif
+
+#ifndef REGDUMP
+#define REGDUMP				0
+#endif
+
+#ifndef DETECT_VGA_CLASS_ONLY
+#define DETECT_VGA_CLASS_ONLY		1
+#endif
+
+#ifndef ALLOCATE_FOR_PANNING
+#define ALLOCATE_FOR_PANNING		1
+#endif
+
+#ifndef BAILOUT_EARLY
+#define BAILOUT_EARLY			0
+#endif
+
+#ifndef TEST_MODE_TO_HW
+#define TEST_MODE_TO_HW			0
+#endif
+
+#ifndef PREFERRED_MODE
+#define PREFERRED_MODE			"1024x768-16@60"
+#endif
+
+/*** hw-related values ***/
+
+/* PCI ids for supported devices */
+#define PCI_DEVICE_ID_INTEL_830M	0x3577
+#define PCI_DEVICE_ID_INTEL_845G	0x2562
+#define PCI_DEVICE_ID_INTEL_85XGM	0x3582
+#define PCI_DEVICE_ID_INTEL_865G	0x2572
+
+/* Size of MMIO region */
+#define INTEL_REG_SIZE			0x80000
+
+#define STRIDE_ALIGNMENT		16
+
+#define PALETTE_8_ENTRIES		256
+
+
+/*** Macros ***/
+
+/* basic arithmetic */
+#define KB(x)			((x) * 1024)
+#define MB(x)			((x) * 1024 * 1024)
+#define BtoKB(x)		((x) / 1024)
+#define BtoMB(x)		((x) / 1024 / 1024)
+
+#define GTT_PAGE_SIZE           KB(4)
+
+#define ROUND_UP_TO(x, y)	(((x) + (y) - 1) / (y) * (y))
+#define ROUND_DOWN_TO(x, y)	((x) / (y) * (y))
+#define ROUND_UP_TO_PAGE(x)	ROUND_UP_TO((x), GTT_PAGE_SIZE)
+#define ROUND_DOWN_TO_PAGE(x)	ROUND_DOWN_TO((x), GTT_PAGE_SIZE)
+
+/* messages */
+#define PFX			INTELFB_MODULE_NAME ": "
+
+#define ERR_MSG(fmt, args...)	printk(KERN_ERR PFX fmt, ## args)
+#define WRN_MSG(fmt, args...)	printk(KERN_WARNING PFX fmt, ## args)
+#define NOT_MSG(fmt, args...)	printk(KERN_NOTICE PFX fmt, ## args)
+#define INF_MSG(fmt, args...)	printk(KERN_INFO PFX fmt, ## args)
+#if DEBUG
+#define DBG_MSG(fmt, args...)	printk(KERN_DEBUG PFX fmt, ## args)
+#else
+#define DBG_MSG(fmt, args...)	while (0) printk(fmt, ## args)
+#endif
+
+/* get commonly used pointers */
+#define GET_DINFO(info)		(info)->par
+
+/* module parameters */
+#define INTELFB_INT_PARAM(name, default, desc)				\
+	static int name = default;					\
+	MODULE_PARM(name, "i");					        \
+	MODULE_PARM_DESC(name, desc);
+
+#define INTELFB_STR_PARAM(name, default, desc)				\
+	static const char *name = default;				\
+	MODULE_PARM(name, "s");				                \
+	MODULE_PARM_DESC(name, desc);
+
+/* misc macros */
+#define TEXT_ACCEL(d, v)						\
+	((d)->accel && (d)->ring_active &&				\
+	 ((v)->accel_flags & FB_ACCELF_TEXT))
+
+/*#define NOACCEL_CHIPSET(d)						\
+	((d)->chipset != INTEL_865G)*/
+#define NOACCEL_CHIPSET(d)						\
+	(0)
+
+#define FIXED_MODE(d) ((d)->fixed_mode)
+
+/*** Driver paramters ***/
+
+#define RINGBUFFER_SIZE		KB(64)
+#define HW_CURSOR_SIZE		KB(4)
+
+/* Intel agpgart driver */
+#define AGP_PHYSICAL_MEMORY     2
+
+/*** Data Types ***/
+
+/* supported chipsets */
+enum intel_chips {
+	INTEL_830M,
+	INTEL_845G,
+	INTEL_85XGM,
+	INTEL_852GM,
+	INTEL_852GME,
+	INTEL_855GM,
+	INTEL_855GME,
+	INTEL_865G
+};
+
+struct intelfb_hwstate {
+	u32 vga0_divisor;
+	u32 vga1_divisor;
+	u32 vga_pd;
+	u32 dpll_a;
+	u32 dpll_b;
+	u32 fpa0;
+	u32 fpa1;
+	u32 fpb0;
+	u32 fpb1;
+	u32 palette_a[PALETTE_8_ENTRIES];
+	u32 palette_b[PALETTE_8_ENTRIES];
+	u32 htotal_a;
+	u32 hblank_a;
+	u32 hsync_a;
+	u32 vtotal_a;
+	u32 vblank_a;
+	u32 vsync_a;
+	u32 src_size_a;
+	u32 bclrpat_a;
+	u32 htotal_b;
+	u32 hblank_b;
+	u32 hsync_b;
+	u32 vtotal_b;
+	u32 vblank_b;
+	u32 vsync_b;
+	u32 src_size_b;
+	u32 bclrpat_b;
+	u32 adpa;
+	u32 dvoa;
+	u32 dvob;
+	u32 dvoc;
+	u32 dvoa_srcdim;
+	u32 dvob_srcdim;
+	u32 dvoc_srcdim;
+	u32 lvds;
+	u32 pipe_a_conf;
+	u32 pipe_b_conf;
+	u32 disp_arb;
+	u32 cursor_a_control;
+	u32 cursor_b_control;
+	u32 cursor_a_base;
+	u32 cursor_b_base;
+	u32 cursor_size;
+	u32 disp_a_ctrl;
+	u32 disp_b_ctrl;
+	u32 disp_a_base;
+	u32 disp_b_base;
+	u32 cursor_a_palette[4];
+	u32 cursor_b_palette[4];
+	u32 disp_a_stride;
+	u32 disp_b_stride;
+	u32 vgacntrl;
+	u32 add_id;
+	u32 swf0x[7];
+	u32 swf1x[7];
+	u32 swf3x[3];
+	u32 fence[8];
+	u32 instpm;
+	u32 mem_mode;
+	u32 fw_blc_0;
+	u32 fw_blc_1;
+};
+
+struct intelfb_heap_data {
+	u32 physical;
+	u32 __iomem *virtual;
+	u32 offset;  // in GATT pages
+	u32 size;    // in bytes
+};
+
+struct intelfb_info {
+	struct fb_info *info;
+	struct fb_ops  *fbops;
+	struct pci_dev *pdev;
+
+	struct intelfb_hwstate save_state;
+
+	/* agpgart structs */
+	struct agp_memory *gtt_fb_mem;     // use all stolen memory
+	struct agp_memory *gtt_ring_mem;   // ring buffer
+	struct agp_memory *gtt_cursor_mem; // hw cursor
+
+	/* mtrr support */
+	u32 mtrr_reg;
+	u32 has_mtrr;
+
+	/* heap data */
+	struct intelfb_heap_data aperture;
+	struct intelfb_heap_data fb;
+	struct intelfb_heap_data ring;
+	struct intelfb_heap_data cursor;
+
+	/* mmio regs */
+	u32 mmio_base_phys;
+	u32 __iomem *mmio_base;
+
+	/* fb start offset (in bytes) */
+	u32 fb_start;
+
+	/* ring buffer */
+	u32 __iomem *ring_head;
+	u32 ring_tail;
+	u32 ring_tail_mask;
+	u32 ring_space;
+	u32 ring_lockup;
+
+	/* palette */
+	u32 pseudo_palette[17];
+	struct { u8 red, green, blue, pad; } palette[256];
+
+	/* chip info */
+	int pci_chipset;
+	int chipset;
+	const char *name;
+	int mobile;
+
+	/* current mode */
+	int bpp, depth;
+	u32 visual;
+	int xres, yres, pitch;
+	int pixclock;
+
+	/* current pipe */
+	int pipe;
+
+	/* some flags */
+	int accel;
+	int hwcursor;
+	int fixed_mode;
+	int ring_active;
+
+	/* hw cursor */
+	int cursor_on;
+	int cursor_blanked;
+	u8  cursor_src[64];
+
+	/* initial parameters */
+	int initial_vga;
+	struct fb_var_screeninfo initial_var;
+	u32 initial_fb_base;
+	u32 initial_video_ram;
+	u32 initial_pitch;
+
+	/* driver registered */
+	int registered;
+};
+
+/*** function prototypes ***/
+
+extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
+
+#endif /* _INTELFB_H */
diff -Nru a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/intelfb/intelfbdrv.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,1628 @@
+/*
+ * intelfb
+ *
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G
+ * integrated graphics chips.
+ *
+ * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+ *                   2004 Sylvain Meyer
+ *
+ * This driver consists of two parts.  The first part (intelfbdrv.c) provides
+ * the basic fbdev interfaces, is derived in part from the radeonfb and
+ * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c)
+ * provides the code to program the hardware.  Most of it is derived from
+ * the i810/i830 XFree86 driver.  The HW-specific code is covered here
+ * under a dual license (GPL and MIT/XFree86 license).
+ *
+ * Author: David Dawes
+ *
+ */
+
+/* $DHD: intelfb/intelfbdrv.c,v 1.20 2003/06/27 15:17:40 dawes Exp $ */
+
+/*
+ * Changes:
+ *    01/2003 - Initial driver (0.1.0), no mode switching, no acceleration.
+ *		This initial version is a basic core that works a lot like
+ *		the vesafb driver.  It must be built-in to the kernel,
+ *		and the initial video mode must be set with vga=XXX at
+ *		boot time.  (David Dawes)
+ *
+ *    01/2003 - Version 0.2.0: Mode switching added, colormap support
+ *		implemented, Y panning, and soft screen blanking implemented.
+ *		No acceleration yet.  (David Dawes)
+ *
+ *    01/2003 - Version 0.3.0: fbcon acceleration support added.  Module
+ *		option handling added.  (David Dawes)
+ *
+ *    01/2003 - Version 0.4.0: fbcon HW cursor support added.  (David Dawes)
+ *
+ *    01/2003 - Version 0.4.1: Add auto-generation of built-in modes.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.4.2: Add check for active non-CRT devices, and
+ *		mode validation checks.  (David Dawes)
+ *
+ *    02/2003 - Version 0.4.3: Check when the VC is in graphics mode so that
+ *		acceleration is disabled while an XFree86 server is running.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.4.4: Monitor DPMS support.  (David Dawes)
+ *
+ *    02/2003 - Version 0.4.5: Basic XFree86 + fbdev working.  (David Dawes)
+ *
+ *    02/2003 - Version 0.5.0: Modify to work with the 2.5.32 kernel as well
+ *		as 2.4.x kernels.  (David Dawes)
+ *
+ *    02/2003 - Version 0.6.0: Split out HW-specifics into a separate file.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.7.0: Test on 852GM/855GM.  Acceleration and HW
+ *		cursor are disabled on this platform.  (David Dawes)
+ *
+ *    02/2003 - Version 0.7.1: Test on 845G.  Acceleration is disabled
+ *		on this platform.  (David Dawes)
+ *
+ *    02/2003 - Version 0.7.2: Test on 830M.  Acceleration and HW
+ *		cursor are disabled on this platform.  (David Dawes)
+ *
+ *    02/2003 - Version 0.7.3: Fix 8-bit modes for mobile platforms
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.7.4: Add checks for FB and FBCON_HAS_CFB* configured
+ *		in the kernel, and add mode bpp verification and default
+ *		bpp selection based on which FBCON_HAS_CFB* are configured.
+ *		(David Dawes)
+ *
+ *    02/2003 - Version 0.7.5: Add basic package/install scripts based on the
+ *		DRI packaging scripts.  (David Dawes)
+ *
+ *    04/2003 - Version 0.7.6: Fix typo that affects builds with SMP-enabled
+ *		kernels.  (David Dawes, reported by Anupam).
+ *
+ *    06/2003 - Version 0.7.7:
+ *              Fix Makefile.kernel build problem (Tsutomu Yasuda).
+ *		Fix mis-placed #endif (2.4.21 kernel).
+ *
+ *    09/2004 - Version 0.9.0 - by Sylvain Meyer
+ *              Port to linux 2.6 kernel fbdev
+ *              Fix HW accel and HW cursor on i845G
+ *              Add TV-Out functionality (tested with a ch7011 tv encoder)
+ *              Use of agpgart for fb memory reservation
+ *              Add mtrr support
+ *
+ * TODO:
+ *
+ *
+ * Wish List:
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/kd.h>
+#include <linux/vt_kern.h>
+#include <linux/pagemap.h>
+#include <linux/version.h>
+
+#include <asm/io.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "intelfb.h"
+#include "intelfbdrv.h"
+#include "intelfbhw.h"
+
+#include "builtinmodes.c"
+
+#define FB_ACCEL_I830 42
+
+/*
+ * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
+ * mobile chipsets from being registered.
+ */
+#if DETECT_VGA_CLASS_ONLY
+#define INTELFB_CLASS_MASK ~0 << 8
+#else
+#define INTELFB_CLASS_MASK 0
+#endif
+
+static struct pci_device_id intelfb_pci_table[] __devinitdata = {
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
+	{ 0, }
+};
+
+/* Global data */
+static int num_registered = 0;
+
+/* fb ops */
+static struct fb_ops intel_fb_ops = {
+	.owner =		THIS_MODULE,
+	.fb_check_var =         intelfb_check_var,
+	.fb_set_par =           intelfb_set_par,
+	.fb_setcolreg =		intelfb_setcolreg,
+	.fb_blank =		intelfb_blank,
+	.fb_pan_display =       intelfb_pan_display,
+	.fb_fillrect  =         intelfb_fillrect,
+	.fb_copyarea  =         intelfb_copyarea,
+	.fb_imageblit =         intelfb_imageblit,
+	.fb_cursor =            intelfb_cursor,
+	.fb_sync =              intelfb_sync,
+	.fb_ioctl =		intelfb_ioctl
+};
+
+/* PCI driver module table */
+static struct pci_driver intelfb_driver = {
+	.name =		"Intel(R) " SUPPORTED_CHIPSETS " Framebuffer Driver",
+	.id_table =	intelfb_pci_table,
+	.probe =	intelfb_pci_register,
+	.remove =	__devexit_p(intelfb_pci_unregister)
+};
+
+/* Module description/parameters */
+MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
+	      "Sylvain Meyer <sylvain.meyer@worldonline.fr>");
+MODULE_DESCRIPTION(
+	"Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS " chipsets");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
+
+INTELFB_INT_PARAM(accel, 1, "Enable console acceleration");
+INTELFB_INT_PARAM(hwcursor, 1, "Enable HW cursor");
+INTELFB_INT_PARAM(mtrr, 1, "Enable MTRR support");
+INTELFB_INT_PARAM(fixed, 0, "Disable mode switching");
+INTELFB_INT_PARAM(noinit, 0, "Don't initialise graphics mode when loading");
+INTELFB_INT_PARAM(noregister, 0, "Don't register, just probe and exit (debug)");
+INTELFB_INT_PARAM(probeonly, 0, "Do a minimal probe (debug)");
+INTELFB_INT_PARAM(idonly, 0,
+		  "Just identify without doing anything else (debug)");
+INTELFB_INT_PARAM(bailearly, 0, "Bail out early, depending on value (debug)");
+INTELFB_STR_PARAM(mode, NULL,
+		  "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
+/***************************************************************
+ *                     modules entry points                    *
+ ***************************************************************/
+
+/* module load/unload entry points */
+int __init
+intelfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+#endif
+
+	DBG_MSG("intelfb_init\n");
+
+	INF_MSG("Framebuffer driver for "
+		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
+	INF_MSG("Version " INTELFB_VERSION "\n");
+
+	if (idonly)
+		return -ENODEV;
+
+#ifndef MODULE
+	if (fb_get_options("intelfb", &option))
+		return -ENODEV;
+	intelfb_setup(option);
+
+#endif
+
+	return pci_module_init(&intelfb_driver);
+}
+
+static void __exit
+intelfb_exit(void)
+{
+	DBG_MSG("intelfb_exit\n");
+	pci_unregister_driver(&intelfb_driver);
+}
+
+#ifndef MODULE
+#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
+#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), NULL, 0)
+#define OPT_STRVAL(opt, name) (opt + strlen(name))
+
+static __inline__ char *
+get_opt_string(const char *this_opt, const char *name)
+{
+	const char *p;
+	int i;
+	char *ret;
+
+	p = OPT_STRVAL(this_opt, name);
+	i = 0;
+	while (p[i] && p[i] != ' ' && p[i] != ',')
+		i++;
+	ret = kmalloc(i + 1, GFP_KERNEL);
+	if (ret) {
+		strncpy(ret, p, i);
+		ret[i] = '\0';
+	}
+	return ret;
+}
+
+static __inline__ int
+get_opt_bool(const char *this_opt, const char *name, int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (OPT_EQUAL(this_opt, name)) {
+		if (this_opt[strlen(name)] == '=')
+			*ret = simple_strtoul(this_opt + strlen(name) + 1,
+					      NULL, 0);
+		else
+			*ret = 1;
+	} else {
+		if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
+			*ret = 0;
+		else
+			return 0;
+	}
+	return 1;
+}
+
+static __inline__ int
+get_opt_int(const char *this_opt, const char *name, int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (!OPT_EQUAL(this_opt, name))
+		return 0;
+
+	*ret = OPT_INTVAL(this_opt, name);
+	return 1;
+}
+
+int __init
+intelfb_setup(char *options)
+{
+	char *this_opt;
+
+	DBG_MSG("intelfb_setup\n");
+
+	if (!options || !*options) {
+		DBG_MSG("no options\n");
+		return 0;
+	} else
+		DBG_MSG("options: %s\n", options);
+
+	/*
+	 * These are the built-in options analogous to the module parameters
+	 * defined above.
+	 *
+	 * The syntax is:
+	 *
+	 *    video=intelfb:[mode][,<param>=<val>] ...
+	 *
+	 * e.g.,
+	 *
+	 *    video=intelfb:1024x768-16@75,accel=0
+	 */
+
+	while ((this_opt = strsep(&options, ","))) {
+		if (!*this_opt)
+			continue;
+		if (get_opt_bool(this_opt, "accel", &accel))
+			;
+		else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
+			;
+		else if (get_opt_bool(this_opt, "mtrr", &mtrr))
+			;
+		else if (get_opt_bool(this_opt, "fixed", &fixed))
+			;
+		else if (get_opt_bool(this_opt, "init", &noinit))
+			noinit = !noinit;
+		else if (OPT_EQUAL(this_opt, "mode="))
+			mode = get_opt_string(this_opt, "mode=");
+		else
+			mode = this_opt;
+	}
+
+	return 0;
+}
+
+#endif
+
+module_init(intelfb_init);
+
+#ifdef MODULE
+module_exit(intelfb_exit);
+#endif
+
+/***************************************************************
+ *                     mtrr support functions                  *
+ ***************************************************************/
+
+#ifdef CONFIG_MTRR
+static inline void __devinit set_mtrr(struct intelfb_info *dinfo)
+{
+	dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,
+				   dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);
+	if (dinfo->mtrr_reg < 0) {
+		ERR_MSG("unable to set MTRR\n");
+		return;
+	}
+	dinfo->has_mtrr = 1;
+}
+static inline void unset_mtrr(struct intelfb_info *dinfo)
+{
+  	if (dinfo->has_mtrr)
+  		mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
+			 dinfo->aperture.size);
+}
+#else
+#define set_mtrr(x) WRN_MSG("MTRR is disabled in the kernel\n")
+
+#define unset_mtrr(x) do { } while (0)
+#endif /* CONFIG_MTRR */
+
+/***************************************************************
+ *                        driver init / cleanup                *
+ ***************************************************************/
+
+static void
+cleanup(struct intelfb_info *dinfo)
+{
+	DBG_MSG("cleanup\n");
+
+	if (!dinfo)
+		return;
+
+	fb_dealloc_cmap(&dinfo->info->cmap);
+	kfree(dinfo->info->pixmap.addr);
+
+	if (dinfo->registered)
+		unregister_framebuffer(dinfo->info);
+
+	unset_mtrr(dinfo);
+
+	if (dinfo->gtt_fb_mem)
+		agp_unbind_memory(dinfo->gtt_fb_mem);
+	if (dinfo->gtt_cursor_mem) {
+		agp_unbind_memory(dinfo->gtt_cursor_mem);
+		agp_free_memory(dinfo->gtt_cursor_mem);
+	}
+	if (dinfo->gtt_ring_mem) {
+		agp_unbind_memory(dinfo->gtt_ring_mem);
+		agp_free_memory(dinfo->gtt_ring_mem);
+	}
+
+	if (dinfo->mmio_base)
+		iounmap((void __iomem *)dinfo->mmio_base);
+	if (dinfo->aperture.virtual)
+		iounmap((void __iomem *)dinfo->aperture.virtual);
+
+	if (dinfo->mmio_base_phys)
+		release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
+	if (dinfo->aperture.physical)
+		release_mem_region(dinfo->aperture.physical,
+				   dinfo->aperture.size);
+	framebuffer_release(dinfo->info);
+}
+
+#define bailout(dinfo) do {						\
+	DBG_MSG("bailout\n");						\
+	cleanup(dinfo);							\
+	INF_MSG("Not going to register framebuffer, exiting...\n");	\
+	return -ENODEV;							\
+} while (0)
+
+
+static int __devinit
+intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct intelfb_info *dinfo;
+	int i, j, err, dvo;
+	int aperture_size, stolen_size;
+	struct agp_kern_info gtt_info;
+	int agp_memtype;
+	const char *s;
+
+	DBG_MSG("intelfb_pci_register\n");
+
+	num_registered++;
+	if (num_registered != 1) {
+		ERR_MSG("Attempted to register %d devices "
+			"(should be only 1).\n", num_registered);
+		return -ENODEV;
+	}
+
+	info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);
+	if (!info) {
+		ERR_MSG("Could not allocate memory for intelfb_info.\n");
+		return -ENODEV;
+	}
+	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
+		ERR_MSG("Could not allocate cmap for intelfb_info.\n");
+		goto err_out_cmap;
+		return -ENODEV;
+	}
+
+	dinfo = info->par;
+	dinfo->info  = info;
+	dinfo->fbops = &intel_fb_ops;
+	dinfo->pdev  = pdev;
+
+	/* Reserve pixmap space. */
+	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
+	if (info->pixmap.addr == NULL) {
+		ERR_MSG("Cannot reserve pixmap memory.\n");
+		goto err_out_pixmap;
+	}
+	memset(info->pixmap.addr, 0, 64 * 1024);
+
+	/* set early this option because it could be changed by tv encoder
+	   driver */
+	dinfo->fixed_mode = fixed;
+
+	/* Enable device. */
+	if ((err = pci_enable_device(pdev))) {
+		ERR_MSG("Cannot enable device.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	/* Set base addresses. */
+	dinfo->aperture.physical = pci_resource_start(pdev, 0);
+	dinfo->aperture.size     = pci_resource_len(pdev, 0);
+	dinfo->mmio_base_phys    = pci_resource_start(pdev, 1);
+
+	DBG_MSG("fb aperture: 0x%lx/0x%lx, MMIO region: 0x%lx/0x%lx\n",
+		pci_resource_start(pdev, 0), pci_resource_len(pdev, 0),
+		pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+
+	/* Reserve the fb and MMIO regions */
+	if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
+				INTELFB_MODULE_NAME)) {
+		ERR_MSG("Cannot reserve FB region.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+	if (!request_mem_region(dinfo->mmio_base_phys,
+				INTEL_REG_SIZE,
+				INTELFB_MODULE_NAME)) {
+		ERR_MSG("Cannot reserve MMIO region.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	/* Map the fb and MMIO regions */
+	dinfo->aperture.virtual = (u32 __iomem *)ioremap_nocache
+		(dinfo->aperture.physical, dinfo->aperture.size);
+	if (!dinfo->aperture.virtual) {
+		ERR_MSG("Cannot remap FB region.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+	dinfo->mmio_base =
+		(u32 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
+					       INTEL_REG_SIZE);
+	if (!dinfo->mmio_base) {
+		ERR_MSG("Cannot remap MMIO region.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	/* Get the chipset info. */
+	dinfo->pci_chipset = pdev->device;
+
+	if (intelfbhw_get_chipset(pdev, &dinfo->name, &dinfo->chipset,
+				  &dinfo->mobile)) {
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) {
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "
+		"stolen memory %dkB\n",
+		pdev->bus->number, PCI_SLOT(pdev->devfn),
+		PCI_FUNC(pdev->devfn), dinfo->name,
+		BtoMB(aperture_size), BtoKB(stolen_size));
+
+	/* Set these from the options. */
+	dinfo->accel    = accel;
+	dinfo->hwcursor = hwcursor;
+
+	if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {
+		INF_MSG("Acceleration is not supported for the %s chipset.\n",
+			dinfo->name);
+		dinfo->accel = 0;
+	}
+
+	/* Framebuffer parameters - Use all the stolen memory */
+	dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
+	dinfo->fb.offset = 0;   // starts at offset 0
+	dinfo->fb.physical = dinfo->aperture.physical
+		+ (dinfo->fb.offset << 12);
+	dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);
+	dinfo->fb_start = dinfo->fb.offset << 12;
+
+	/* Allocate space for the ring buffer and HW cursor if enabled. */
+	if (dinfo->accel) {
+		dinfo->ring.size = RINGBUFFER_SIZE;
+		dinfo->ring_tail_mask = dinfo->ring.size - 1;
+	}
+	if (dinfo->hwcursor) {
+		dinfo->cursor.size = HW_CURSOR_SIZE;
+	}
+
+	/* Use agpgart to manage the GATT */
+	if (agp_backend_acquire()) {
+		ERR_MSG("cannot acquire agp\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	/* get the current gatt info */
+	if (agp_copy_info(&gtt_info)) {
+		ERR_MSG("cannot get agp info\n");
+		agp_backend_release();
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	/* set the mem offsets - set them after the already used pages */
+	if (dinfo->accel) {
+		dinfo->ring.offset = (stolen_size >> 12)
+			+ gtt_info.current_memory;
+	}
+	if (dinfo->hwcursor) {
+		dinfo->cursor.offset = (stolen_size >> 12) +
+			+ gtt_info.current_memory + (dinfo->ring.size >> 12);
+	}
+
+	/* Allocate memories (which aren't stolen) */
+	if (dinfo->accel) {
+		if (!(dinfo->gtt_ring_mem =
+		      agp_allocate_memory(dinfo->ring.size >> 12,
+					  AGP_NORMAL_MEMORY))) {
+			ERR_MSG("cannot allocate ring buffer memory\n");
+			agp_backend_release();
+			cleanup(dinfo);
+			return -ENOMEM;
+		}
+		if (agp_bind_memory(dinfo->gtt_ring_mem,
+				    dinfo->ring.offset)) {
+			ERR_MSG("cannot bind ring buffer memory\n");
+			agp_backend_release();
+			cleanup(dinfo);
+			return -EBUSY;
+		}
+		dinfo->ring.physical = dinfo->aperture.physical
+			+ (dinfo->ring.offset << 12);
+		dinfo->ring.virtual  = dinfo->aperture.virtual
+			+ (dinfo->ring.offset << 12);
+		dinfo->ring_head = dinfo->ring.virtual;
+	}
+	if (dinfo->hwcursor) {
+		agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
+			: AGP_NORMAL_MEMORY;
+		if (!(dinfo->gtt_cursor_mem =
+		      agp_allocate_memory(dinfo->cursor.size >> 12,
+					  agp_memtype))) {
+			ERR_MSG("cannot allocate cursor memory\n");
+			agp_backend_release();
+			cleanup(dinfo);
+			return -ENOMEM;
+		}
+		if (agp_bind_memory(dinfo->gtt_cursor_mem,
+				    dinfo->cursor.offset)) {
+			ERR_MSG("cannot bind cursor memory\n");
+			agp_backend_release();
+			cleanup(dinfo);
+			return -EBUSY;
+		}
+		if (dinfo->mobile)
+			dinfo->cursor.physical
+				= dinfo->gtt_cursor_mem->physical;
+		else
+			dinfo->cursor.physical = dinfo->aperture.physical
+				+ (dinfo->cursor.offset << 12);
+		dinfo->cursor.virtual = dinfo->aperture.virtual
+			+ (dinfo->cursor.offset << 12);
+	}
+
+	/* release agpgart */
+	agp_backend_release();
+
+	if (mtrr)
+		set_mtrr(dinfo);
+
+	DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%x)\n",
+		dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
+		(u32 __iomem ) dinfo->fb.virtual);
+	DBG_MSG("MMIO: 0x%x/0x%x (0x%x)\n",
+		dinfo->mmio_base_phys, INTEL_REG_SIZE,
+		(u32 __iomem) dinfo->mmio_base);
+	DBG_MSG("ring buffer: 0x%x/0x%x (0x%x)\n",
+		dinfo->ring.physical, dinfo->ring.size,
+		(u32 __iomem ) dinfo->ring.virtual);
+	DBG_MSG("HW cursor: 0x%x/0x%x (0x%x) (offset 0x%x) (phys 0x%x)\n",
+		dinfo->cursor.physical, dinfo->cursor.size,
+		(u32 __iomem ) dinfo->cursor.virtual, dinfo->cursor.offset,
+		dinfo->cursor.physical);
+
+	DBG_MSG("options: accel = %d, hwcursor = %d, fixed = %d, "
+		"noinit = %d\n", accel, hwcursor, fixed, noinit);
+	DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");
+
+	if (probeonly)
+		bailout(dinfo);
+
+	/*
+	 * Check if the LVDS port or any DVO ports are enabled.  If so,
+	 * don't allow mode switching
+	 */
+	dvo = intelfbhw_check_non_crt(dinfo);
+	if (dvo) {
+		dinfo->fixed_mode = 1;
+		WRN_MSG("Non-CRT device is enabled ( ");
+		i = 0;
+		while (dvo) {
+			if (dvo & 1) {
+				s = intelfbhw_dvo_to_string(1 << i);
+				if (s)
+					printk("%s ", s);
+			}
+			dvo >>= 1;
+			++i;
+		}
+		printk(").  Disabling mode switching.\n");
+	}
+
+	if (bailearly == 1)
+		bailout(dinfo);
+
+	if (FIXED_MODE(dinfo) && ORIG_VIDEO_ISVGA != VIDEO_TYPE_VLFB) {
+		ERR_MSG("Video mode must be programmed at boot time.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (bailearly == 2)
+		bailout(dinfo);
+
+	/* Initialise dinfo and related data. */
+	/* If an initial mode was programmed at boot time, get its details. */
+	if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB)
+		get_initial_mode(dinfo);
+
+	if (bailearly == 3)
+		bailout(dinfo);
+
+	if (FIXED_MODE(dinfo)) {
+		/* remap fb address */
+		update_dinfo(dinfo, &dinfo->initial_var);
+	}
+
+	if (bailearly == 4)
+		bailout(dinfo);
+
+
+	if (intelfb_set_fbinfo(dinfo)) {
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	if (bailearly == 5)
+		bailout(dinfo);
+
+	for (i = 0; i < 16; i++) {
+		j = color_table[i];
+		dinfo->palette[i].red = default_red[j];
+		dinfo->palette[i].green = default_grn[j];
+		dinfo->palette[i].blue = default_blu[j];
+	}
+
+	if (bailearly == 6)
+		bailout(dinfo);
+
+	pci_set_drvdata(pdev, dinfo);
+
+	/* Save the initial register state. */
+	i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,
+				    bailearly > 6 ? bailearly - 6 : 0);
+	if (i != 0) {
+		DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);
+		bailout(dinfo);
+	}
+
+	intelfbhw_print_hw_state(dinfo, &dinfo->save_state);
+
+	if (bailearly == 18)
+		bailout(dinfo);
+
+#if TEST_MODE_TO_HW
+	{
+		struct intelfb_hwstate hw;
+		struct fb_var_screeninfo var;
+		int i;
+
+		for (i = 0; i < num_modes; i++) {
+			mode_to_var(&modedb[i], &var, 8);
+			intelfbhw_read_hw_state(dinfo, &hw, 0);
+			if (intelfbhw_mode_to_hw(dinfo, &hw, &var)) {
+				DBG_MSG("Failed to set hw for mode %dx%d\n",
+					var.xres, var.yres);
+			} else {
+				DBG_MSG("HW state for mode %dx%d\n",
+					var.xres, var.yres);
+				intelfbhw_print_hw_state(dinfo, &hw);
+			}
+		}
+	}
+#endif
+
+	/* Cursor initialisation */
+	if (dinfo->hwcursor) {
+		intelfbhw_cursor_init(dinfo);
+		intelfbhw_cursor_reset(dinfo);
+	}
+
+	if (bailearly == 19)
+		bailout(dinfo);
+
+	/* 2d acceleration init */
+	if (dinfo->accel)
+		intelfbhw_2d_start(dinfo);
+
+	if (bailearly == 20)
+		bailout(dinfo);
+
+	if (noregister)
+		bailout(dinfo);
+
+	if (register_framebuffer(dinfo->info) < 0) {
+		ERR_MSG("Cannot register framebuffer.\n");
+		cleanup(dinfo);
+		return -ENODEV;
+	}
+
+	dinfo->registered = 1;
+
+	return 0;
+
+err_out_pixmap:
+	fb_dealloc_cmap(&info->cmap);
+err_out_cmap:
+	framebuffer_release(info);
+	return -ENODEV;
+}
+
+static void __devexit
+intelfb_pci_unregister(struct pci_dev *pdev)
+{
+	struct intelfb_info *dinfo = pci_get_drvdata(pdev);
+
+	DBG_MSG("intelfb_pci_unregister\n");
+
+	if (!dinfo)
+		return;
+
+	cleanup(dinfo);
+
+	pci_set_drvdata(pdev, NULL);
+}
+
+/***************************************************************
+ *                       helper functions                      *
+ ***************************************************************/
+
+/*
+ * A simplified version of fb_find_mode.  The latter doesn't seem to work
+ * too well -- haven't figured out why yet.
+ */
+static int
+intelfb_find_mode(struct fb_var_screeninfo *var,
+		  struct fb_info *info, const char *mode_option,
+		  const struct fb_videomode *db, unsigned int dbsize,
+		  const struct fb_videomode *default_mode,
+		  unsigned int default_bpp)
+{
+	int i;
+	char mname[20] = "", tmp[20] = "", *p, *q;
+	unsigned int bpp = 0;
+
+	DBG_MSG("intelfb_find_mode\n");
+
+	/* Set up defaults */
+	if (!db) {
+		db = modedb;
+		dbsize = sizeof(modedb) / sizeof(*modedb);
+	}
+
+	if (!default_bpp)
+		default_bpp = 16;
+
+	var->activate = FB_ACTIVATE_TEST;
+	if (mode_option && *mode_option) {
+		if (strlen(mode_option) < sizeof(tmp) - 1) {
+			strcat(tmp, mode_option);
+			q = tmp;
+			p = strsep(&q, "-");
+			strcat(mname, p);
+			if (q) {
+				p = strsep(&q, "@");
+				bpp = simple_strtoul(p, NULL, 10);
+				if (q) {
+					strcat(mname, "@");
+					strcat(mname, q);
+				}
+			}
+		}
+		if (!bpp)
+			bpp = default_bpp;
+		DBG_MSG("Mode is %s, bpp %d\n", mname, bpp);
+	}
+	if (*mname) {
+		for (i = 0; i < dbsize; i++) {
+			if (!strncmp(db[i].name, mname, strlen(mname))) {
+				mode_to_var(&db[i], var, bpp);
+				if (!intelfb_check_var(var, info))
+					return 1;
+			}
+		}
+	}
+
+	if (!default_mode)
+		return 0;
+
+	mode_to_var(default_mode, var, default_bpp);
+	if (!intelfb_check_var(var, info))
+		return 3;
+
+	for (i = 0; i < dbsize; i++) {
+		mode_to_var(&db[i], var, default_bpp);
+		if (!intelfb_check_var(var, info))
+			return 4;
+	}
+
+	return 0;
+}
+
+int
+intelfb_var_to_depth(const struct fb_var_screeninfo *var)
+{
+	DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
+		var->bits_per_pixel, var->green.length);
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		return (var->green.length == 6) ? 16 : 15;
+	case 32:
+		return 24;
+	default:
+		return var->bits_per_pixel;
+	}
+}
+
+static void
+get_initial_mode(struct intelfb_info *dinfo)
+{
+	struct fb_var_screeninfo *var;
+	int xtot, ytot;
+
+	DBG_MSG("get_initial_mode\n");
+
+	dinfo->initial_vga = 1;
+	dinfo->initial_fb_base = screen_info.lfb_base;
+	dinfo->initial_video_ram = screen_info.lfb_size * KB(64);
+	dinfo->initial_pitch = screen_info.lfb_linelength;
+
+	var = &dinfo->initial_var;
+	memset(var, 0, sizeof(*var));
+	var->xres = screen_info.lfb_width;
+	var->yres = screen_info.lfb_height;
+	var->xres_virtual = var->xres;
+#if ALLOCATE_FOR_PANNING
+	/* Allow use of half of the video ram for panning */
+	var->yres_virtual =
+		dinfo->initial_video_ram / 2 / dinfo->initial_pitch;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+#else
+	var->yres_virtual = var->yres;
+#endif
+	var->bits_per_pixel = screen_info.lfb_depth;
+	switch (screen_info.lfb_depth) {
+	case 15:
+		var->bits_per_pixel = 16;
+		break;
+	case 24:
+		var->bits_per_pixel = 32;
+		break;
+	}
+
+	DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",
+		dinfo->initial_fb_base, dinfo->initial_video_ram,
+		BtoKB(dinfo->initial_video_ram));
+
+	DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",
+		var->xres, var->yres, var->bits_per_pixel,
+		dinfo->initial_pitch);
+
+	/* Dummy timing values (assume 60Hz) */
+	var->left_margin = (var->xres / 8) & 0xf8;
+	var->right_margin = 32;
+	var->upper_margin = 16;
+	var->lower_margin = 4;
+	var->hsync_len = (var->xres / 8) & 0xf8;
+	var->vsync_len = 4;
+
+	xtot = var->xres + var->left_margin +
+		var->right_margin + var->hsync_len;
+	ytot = var->yres + var->upper_margin +
+		var->lower_margin + var->vsync_len;
+	var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;
+
+	var->height = -1;
+	var->width = -1;
+
+	if (var->bits_per_pixel > 8) {
+		var->red.offset = screen_info.red_pos;
+		var->red.length = screen_info.red_size;
+		var->green.offset = screen_info.green_pos;
+		var->green.length = screen_info.green_size;
+		var->blue.offset = screen_info.blue_pos;
+		var->blue.length = screen_info.blue_size;
+		var->transp.offset = screen_info.rsvd_pos;
+		var->transp.length = screen_info.rsvd_size;
+	} else {
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+	}
+}
+
+/* Convert a mode to a var, also making the bpp a supported value. */
+static void
+mode_to_var(const struct fb_videomode *mode, struct fb_var_screeninfo *var,
+	    u32 bpp)
+{
+	if (!mode || !var)
+		return;
+
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->xres_virtual = mode->xres;
+	var->yres_virtual = mode->yres;
+	var->xoffset = 0;
+	var->yoffset = 0;
+	if (bpp <= 8)
+		var->bits_per_pixel = 8;
+	else if (bpp <= 16) {
+		if (bpp == 16)
+			var->green.length = 6;
+		var->bits_per_pixel = 16;
+	} else if (bpp <= 32)
+		var->bits_per_pixel = 32;
+	else {
+		WRN_MSG("var_to_mode: bad bpp: %d\n", bpp);
+		var->bits_per_pixel = bpp;
+	}
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->sync = mode->sync;
+	var->vmode = mode->vmode;
+	var->width = -1;
+	var->height = -1;
+}
+
+static __inline__ int
+var_to_refresh(const struct fb_var_screeninfo *var)
+{
+	int xtot = var->xres + var->left_margin + var->right_margin +
+		   var->hsync_len;
+	int ytot = var->yres + var->upper_margin + var->lower_margin +
+		   var->vsync_len;
+
+	return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
+}
+
+/***************************************************************
+ *                Various intialisation functions              *
+ ***************************************************************/
+
+static int __devinit
+intelfb_init_var(struct intelfb_info *dinfo)
+{
+	int msrc = 0;
+
+	DBG_MSG("intelfb_init_disp_var\n");
+
+	if (dinfo->fixed_mode) {
+	        memcpy(&dinfo->info->var, &dinfo->initial_var,
+		       sizeof(struct fb_var_screeninfo));
+		msrc = 5;
+	} else {
+		if (mode) {
+			msrc = intelfb_find_mode(&dinfo->info->var,
+						 dinfo->info, mode,
+						 modedb, num_modes, NULL, 0);
+			if (msrc)
+				msrc |= 8;
+		}
+		if (!msrc) {
+			msrc = intelfb_find_mode(&dinfo->info->var,
+						 dinfo->info, PREFERRED_MODE,
+						 modedb, num_modes,
+						 &modedb[DFLT_MODE], 0);
+		}
+	}
+
+	if (!msrc) {
+		ERR_MSG("Cannot find a suitable video mode.\n");
+		return 1;
+	}
+
+	INF_MSG("Initial video mode is %dx%d-%d@%d.\n", dinfo->info->var.xres,
+		dinfo->info->var.yres, intelfb_var_to_depth(&dinfo->info->var),
+		var_to_refresh(&dinfo->info->var));
+
+	DBG_MSG("Initial video mode is from %d.\n", msrc);
+
+	if (dinfo->accel)
+		dinfo->info->var.accel_flags |= FB_ACCELF_TEXT;
+	else
+		dinfo->info->var.accel_flags &= ~FB_ACCELF_TEXT;
+
+	return 0;
+}
+
+static int __devinit
+intelfb_set_fbinfo(struct intelfb_info *dinfo)
+{
+	struct fb_info *info = dinfo->info;
+
+	DBG_MSG("intelfb_set_fbinfo\n");
+
+	//info->currcon = -1;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &intel_fb_ops;
+	info->pseudo_palette = dinfo->pseudo_palette;
+
+	info->pixmap.size = 64*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if (intelfb_init_var(dinfo))
+		return 1;
+
+	info->pixmap.scan_align = 1;
+
+	update_dinfo(dinfo, &info->var);
+
+	return 0;
+}
+
+/* Update dinfo to match the active video mode. */
+static void
+update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
+{
+	DBG_MSG("update_dinfo\n");
+
+	dinfo->bpp = var->bits_per_pixel;
+	dinfo->depth = intelfb_var_to_depth(var);
+	dinfo->xres = var->xres;
+	dinfo->yres = var->xres;
+	dinfo->pixclock = var->pixclock;
+
+	intelfb_get_fix(&dinfo->info->fix, dinfo->info);
+
+	switch (dinfo->bpp) {
+	case 8:
+		dinfo->visual = FB_VISUAL_PSEUDOCOLOR;
+		dinfo->pitch = var->xres_virtual;
+		break;
+	case 16:
+		dinfo->visual = FB_VISUAL_TRUECOLOR;
+		dinfo->pitch = var->xres_virtual * 2;
+		break;
+	case 32:
+		dinfo->visual = FB_VISUAL_TRUECOLOR;
+		dinfo->pitch = var->xres_virtual * 4;
+		break;
+	}
+
+	/* Make sure the line length is a aligned correctly. */
+	dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
+
+	if (FIXED_MODE(dinfo))
+		dinfo->pitch = dinfo->initial_pitch;
+
+	dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual;
+	dinfo->info->fix.line_length = dinfo->pitch;
+	dinfo->info->fix.visual = dinfo->visual;
+}
+
+/* fbops functions */
+
+static int
+intelfb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+
+	DBG_MSG("intelfb_get_fix\n");
+
+	memset(fix, 0, sizeof(*fix));
+	strcpy(fix->id, dinfo->name);
+	fix->smem_start = dinfo->fb.physical;
+	fix->smem_len = dinfo->fb.size;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+	fix->visual = dinfo->visual;
+	fix->xpanstep = 8;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->line_length = dinfo->pitch;
+	fix->mmio_start = dinfo->mmio_base_phys;
+	fix->mmio_len = INTEL_REG_SIZE;
+	fix->accel = FB_ACCEL_I830;
+	return 0;
+}
+
+/***************************************************************
+ *                       fbdev interface                       *
+ ***************************************************************/
+
+static int
+intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	int change_var = 0;
+	struct fb_var_screeninfo v;
+	struct intelfb_info *dinfo;
+	static int first = 1;
+
+	DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
+
+	dinfo = GET_DINFO(info);
+
+	if (intelfbhw_validate_mode(dinfo, var) != 0)
+		return -EINVAL;
+
+	memcpy(&v, var, sizeof(v));
+
+	/* Check for a supported bpp. */
+	if (v.bits_per_pixel <= 8) {
+		v.bits_per_pixel = 8;
+	} else if (v.bits_per_pixel <= 16) {
+		if (v.bits_per_pixel == 16)
+			v.green.length = 6;
+		v.bits_per_pixel = 16;
+	} else if (v.bits_per_pixel <= 32) {
+		v.bits_per_pixel = 32;
+	} else
+		return -EINVAL;
+
+	change_var = ((info->var.xres != var->xres) ||
+		      (info->var.yres != var->yres) ||
+		      (info->var.xres_virtual != var->xres_virtual) ||
+		      (info->var.yres_virtual != var->yres_virtual) ||
+		      (info->var.bits_per_pixel != var->bits_per_pixel) ||
+		      memcmp(&info->var.red, &var->red, sizeof(var->red)) ||
+		      memcmp(&info->var.green, &var->green,
+			     sizeof(var->green)) ||
+		      memcmp(&info->var.blue, &var->blue, sizeof(var->blue)));
+
+	if (FIXED_MODE(dinfo) &&
+	    (change_var ||
+	     var->yres_virtual > dinfo->initial_var.yres_virtual ||
+	     var->yres_virtual < dinfo->initial_var.yres ||
+	     var->xoffset || var->nonstd)) {
+		if (first) {
+			ERR_MSG("Changing the video mode is not supported.\n");
+			first = 0;
+		}
+		return -EINVAL;
+	}
+
+	switch (intelfb_var_to_depth(&v)) {
+	case 8:
+		v.red.offset = v.green.offset = v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 8;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 15:
+		v.red.offset = 10;
+		v.green.offset = 5;
+		v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 5;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 16:
+		v.red.offset = 11;
+		v.green.offset = 5;
+		v.blue.offset = 0;
+		v.red.length = 5;
+		v.green.length = 6;
+		v.blue.length = 5;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 24:
+		v.red.offset = 16;
+		v.green.offset = 8;
+		v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 8;
+		v.transp.offset = v.transp.length = 0;
+		break;
+	case 32:
+		v.red.offset = 16;
+		v.green.offset = 8;
+		v.blue.offset = 0;
+		v.red.length = v.green.length = v.blue.length = 8;
+		v.transp.offset = 24;
+		v.transp.length = 8;
+		break;
+	}
+
+	if (v.xoffset < 0)
+		v.xoffset = 0;
+	if (v.yoffset < 0)
+		v.yoffset = 0;
+
+	if (v.xoffset > v.xres_virtual - v.xres)
+		v.xoffset = v.xres_virtual - v.xres;
+	if (v.yoffset > v.yres_virtual - v.yres)
+		v.yoffset = v.yres_virtual - v.yres;
+
+	v.red.msb_right = v.green.msb_right = v.blue.msb_right =
+			  v.transp.msb_right = 0;
+
+        memcpy(var, &v, sizeof(v));
+
+	return 0;
+}
+
+static int
+intelfb_set_par(struct fb_info *info)
+{
+	struct intelfb_hwstate hw;
+
+        struct intelfb_info *dinfo = GET_DINFO(info);
+
+	if (FIXED_MODE(dinfo)) {
+		ERR_MSG("Changing the video mode is not supported.\n");
+		return -EINVAL;
+	}
+
+	DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
+		info->var.yres, intelfb_var_to_depth(&info->var));
+
+	intelfb_blank(1, info);
+
+	if (dinfo->accel)
+		intelfbhw_2d_stop(dinfo);
+
+	mdelay(100);
+
+	memcpy(&hw, &dinfo->save_state, sizeof(hw));
+	if (intelfbhw_mode_to_hw(dinfo, &hw, &info->var))
+		return -EINVAL;
+	if (intelfbhw_program_mode(dinfo, &hw, 0))
+		return -EINVAL;
+
+#if REGDUMP > 0
+	intelfbhw_read_hw_state(dinfo, &hw, 0);
+	intelfbhw_print_hw_state(dinfo, &hw);
+#endif
+
+	update_dinfo(dinfo, &info->var);
+
+	mdelay(100);
+
+	if (dinfo->accel)
+		intelfbhw_2d_start(dinfo);
+
+	intelfbhw_pan_display(&info->var, info);
+
+	intelfb_blank(0, info);
+
+	return 0;
+}
+
+static int
+intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+		  unsigned blue, unsigned transp, struct fb_info *info)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);
+#endif
+
+	if (regno > 255)
+		return 1;
+
+	switch (dinfo->depth) {
+	case 8:
+		{
+			red >>= 8;
+			green >>= 8;
+			blue >>= 8;
+
+			dinfo->palette[regno].red = red;
+			dinfo->palette[regno].green = green;
+			dinfo->palette[regno].blue = blue;
+
+			intelfbhw_setcolreg(dinfo, regno, red, green, blue,
+					    transp);
+		}
+		break;
+	case 15:
+		dinfo->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
+					       ((green & 0xf800) >>  6) |
+					       ((blue & 0xf800) >> 11);
+		break;
+	case 16:
+		dinfo->pseudo_palette[regno] = (red & 0xf800) |
+					       ((green & 0xfc00) >>  5) |
+					       ((blue  & 0xf800) >> 11);
+		break;
+	case 24:
+		dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
+					       (green & 0xff00) |
+					       ((blue  & 0xff00) >> 8);
+		break;
+	}
+	return 0;
+}
+
+static int
+intelfb_blank(int blank, struct fb_info *info)
+{
+	intelfbhw_do_blank(blank, info);
+	return 0;
+}
+
+static int
+intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	intelfbhw_pan_display(var, info);
+	return 0;
+}
+
+/* When/if we have our own ioctls. */
+static int
+intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	      unsigned long arg, struct fb_info *info)
+{
+	int retval = 0;
+
+	return retval;
+}
+
+static void
+intelfb_fillrect (struct fb_info *info, const struct fb_fillrect *rect)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 rop, color;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_fillrect\n");
+#endif
+
+	if (!dinfo->accel || dinfo->ring_lockup || dinfo->depth == 4)
+		return cfb_fillrect(info, rect);
+
+	if (rect->rop == ROP_COPY)
+		rop = PAT_ROP_GXCOPY;
+	else // ROP_XOR
+		rop = PAT_ROP_GXXOR;
+
+	if (dinfo->depth != 8)
+		color = dinfo->pseudo_palette[rect->color];
+	else
+		color = rect->color;
+
+	intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy,
+			      rect->width, rect->height, color,
+			      dinfo->pitch, info->var.bits_per_pixel,
+			      rop);
+}
+
+static void
+intelfb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_copyarea\n");
+#endif
+
+	if (!dinfo->accel || dinfo->ring_lockup || dinfo->depth == 4)
+		return cfb_copyarea(info, region);
+
+	intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
+			    region->dy, region->width, region->height,
+			    dinfo->pitch, info->var.bits_per_pixel);
+}
+
+static void
+intelfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 fgcolor, bgcolor;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_imageblit\n");
+#endif
+
+	if (!dinfo->accel || dinfo->ring_lockup || dinfo->depth == 4
+	    || image->depth != 1)
+		return cfb_imageblit(info, image);
+
+	if (dinfo->depth != 8) {
+		fgcolor = dinfo->pseudo_palette[image->fg_color];
+		bgcolor = dinfo->pseudo_palette[image->bg_color];
+	} else {
+		fgcolor = image->fg_color;
+		bgcolor = image->bg_color;
+	}
+
+	if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width,
+				    image->height, image->data,
+				    image->dx, image->dy,
+				    dinfo->pitch, info->var.bits_per_pixel))
+		return cfb_imageblit(info, image);
+}
+
+static int
+intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_cursor\n");
+#endif
+
+	if (!dinfo->hwcursor)
+		return soft_cursor(info, cursor);
+
+	intelfbhw_cursor_hide(dinfo);
+
+	/* If XFree killed the cursor - restore it */
+	if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.physical) {
+		u32 fg, bg;
+
+		DBG_MSG("the cursor was killed - restore it !!\n");
+		DBG_MSG("size %d, %d   pos %d, %d\n",
+			cursor->image.width, cursor->image.height,
+			cursor->image.dx, cursor->image.dy);
+
+		intelfbhw_cursor_init(dinfo);
+		intelfbhw_cursor_reset(dinfo);
+		intelfbhw_cursor_setpos(dinfo, cursor->image.dx,
+					cursor->image.dy);
+
+		if (dinfo->depth != 8) {
+			fg =dinfo->pseudo_palette[cursor->image.fg_color];
+			bg =dinfo->pseudo_palette[cursor->image.bg_color];
+		} else {
+			fg = cursor->image.fg_color;
+			bg = cursor->image.bg_color;
+		}
+		intelfbhw_cursor_setcolor(dinfo, bg, fg);
+		intelfbhw_cursor_load(dinfo, cursor->image.width,
+				      cursor->image.height,
+				      dinfo->cursor_src);
+
+		if (cursor->enable)
+			intelfbhw_cursor_show(dinfo);
+		return 0;
+	}
+
+	if (cursor->set & FB_CUR_SETPOS) {
+		u32 dx, dy;
+
+		dx = cursor->image.dx - info->var.xoffset;
+		dy = cursor->image.dy - info->var.yoffset;
+
+		intelfbhw_cursor_setpos(dinfo, dx, dy);
+	}
+
+	if (cursor->set & FB_CUR_SETSIZE) {
+		if (cursor->image.width > 64 || cursor->image.height > 64)
+			return -ENXIO;
+
+		intelfbhw_cursor_reset(dinfo);
+	}
+
+	if (cursor->set & FB_CUR_SETCMAP) {
+		u32 fg, bg;
+
+		if (dinfo->depth != 8) {
+			fg = dinfo->pseudo_palette[cursor->image.fg_color];
+			bg = dinfo->pseudo_palette[cursor->image.bg_color];
+		} else {
+			fg = cursor->image.fg_color;
+			bg = cursor->image.bg_color;
+		}
+
+		intelfbhw_cursor_setcolor(dinfo, bg, fg);
+	}
+
+	if (cursor->set & FB_CUR_SETSHAPE) {
+		u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8);
+		u32 size = s_pitch * cursor->image.height;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) cursor->mask;
+		u8 src[64];
+		u32 i;
+
+		if (cursor->image.depth != 1)
+			return -ENXIO;
+
+		switch (cursor->rop) {
+		case ROP_XOR:
+			for (i = 0; i < size; i++)
+				src[i] = dat[i] ^ msk[i];
+			break;
+		case ROP_COPY:
+		default:
+			for (i = 0; i < size; i++)
+				src[i] = dat[i] & msk[i];
+			break;
+		}
+
+		/* save the bitmap to restore it when XFree will
+		   make the cursor dirty */
+		memcpy(dinfo->cursor_src, src, size);
+
+		intelfbhw_cursor_load(dinfo, cursor->image.width,
+				      cursor->image.height, src);
+	}
+
+	if (cursor->enable)
+		intelfbhw_cursor_show(dinfo);
+
+	return 0;
+}
+
+static int
+intelfb_sync(struct fb_info *info)
+{
+        struct intelfb_info *dinfo = GET_DINFO(info);
+
+#if VERBOSE > 0
+	DBG_MSG("intelfb_sync\n");
+#endif
+
+	if (dinfo->ring_lockup)
+		return 0;
+
+	intelfbhw_do_sync(dinfo);
+	return 0;
+}
+
diff -Nru a/drivers/video/intelfb/intelfbdrv.h b/drivers/video/intelfb/intelfbdrv.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/intelfb/intelfbdrv.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,77 @@
+#ifndef _INTELFBDRV_H
+#define _INTELFBDRV_H
+
+/*
+ ******************************************************************************
+ * intelfb
+ *
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G
+ * integrated graphics chips.
+ *
+ * Copyright © 2004 Sylvain Meyer
+ *
+ * Author: Sylvain Meyer
+ *
+ ******************************************************************************
+ *    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.
+*/
+
+int __init intelfb_setup(char *options);
+static void get_initial_mode(struct intelfb_info *dinfo);
+static void update_dinfo(struct intelfb_info *dinfo,
+			 struct fb_var_screeninfo *var);
+static int intelfb_get_fix(struct fb_fix_screeninfo *fix,
+			   struct fb_info *info);
+static void mode_to_var(const struct fb_videomode *mode,
+			struct fb_var_screeninfo *var, u32 bpp);
+static int
+intelfb_find_mode(struct fb_var_screeninfo *var,
+		  struct fb_info *info, const char *mode_option,
+		  const struct fb_videomode *db, unsigned int dbsize,
+		  const struct fb_videomode *default_mode,
+		  unsigned int default_bpp);
+
+static int intelfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info);
+static int intelfb_set_par(struct fb_info *info);
+static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			     unsigned blue, unsigned transp,
+			     struct fb_info *info);
+
+static int intelfb_blank(int blank, struct fb_info *info);
+static int intelfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info);
+
+static void intelfb_fillrect(struct fb_info *info,
+			     const struct fb_fillrect *rect);
+static void intelfb_copyarea(struct fb_info *info,
+			     const struct fb_copyarea *region);
+static void intelfb_imageblit(struct fb_info *info,
+			      const struct fb_image *image);
+static int intelfb_cursor(struct fb_info *info,
+			   struct fb_cursor *cursor);
+
+static int intelfb_sync(struct fb_info *info);
+
+static int intelfb_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg,
+			 struct fb_info *info);
+
+static int intelfb_pci_register(struct pci_dev *pdev,
+				const struct pci_device_id *ent);
+static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);
+static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
+
+#endif
diff -Nru a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/intelfb/intelfbhw.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,1753 @@
+/*
+ * intelfb
+ *
+ * Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
+ *
+ * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
+ *                   2004 Sylvain Meyer
+ *
+ * This driver consists of two parts.  The first part (intelfbdrv.c) provides
+ * the basic fbdev interfaces, is derived in part from the radeonfb and
+ * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c)
+ * provides the code to program the hardware.  Most of it is derived from
+ * the i810/i830 XFree86 driver.  The HW-specific code is covered here
+ * under a dual license (GPL and MIT/XFree86 license).
+ *
+ * Author: David Dawes
+ *
+ */
+
+/* $DHD: intelfb/intelfbhw.c,v 1.9 2003/06/27 15:06:25 dawes Exp $ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/kd.h>
+#include <linux/vt_kern.h>
+#include <linux/pagemap.h>
+#include <linux/version.h>
+
+#include <asm/io.h>
+
+#include "intelfb.h"
+#include "intelfbhw.h"
+
+int
+intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,
+		      int *mobile)
+{
+	u32 tmp;
+
+	if (!pdev || !name || !chipset || !mobile)
+		return 1;
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_830M:
+		*name = "Intel(R) 830M";
+		*chipset = INTEL_830M;
+		*mobile = 1;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_845G:
+		*name = "Intel(R) 845G";
+		*chipset = INTEL_845G;
+		*mobile = 0;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_85XGM:
+		tmp = 0;
+		*mobile = 1;
+		pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
+		switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
+			INTEL_85X_VARIANT_MASK) {
+		case INTEL_VAR_855GME:
+			*name = "Intel(R) 855GME";
+			*chipset = INTEL_855GME;
+			return 0;
+		case INTEL_VAR_855GM:
+			*name = "Intel(R) 855GM";
+			*chipset = INTEL_855GM;
+			return 0;
+		case INTEL_VAR_852GME:
+			*name = "Intel(R) 852GME";
+			*chipset = INTEL_852GME;
+			return 0;
+		case INTEL_VAR_852GM:
+			*name = "Intel(R) 852GM";
+			*chipset = INTEL_852GM;
+			return 0;
+		default:
+			*name = "Intel(R) 852GM/855GM";
+			*chipset = INTEL_85XGM;
+			return 0;
+		}
+		break;
+	case PCI_DEVICE_ID_INTEL_865G:
+		*name = "Intel(R) 865G";
+		*chipset = INTEL_865G;
+		*mobile = 0;
+		return 0;
+	default:
+		return 1;
+	}
+}
+
+int
+intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
+		     int *stolen_size)
+{
+	struct pci_dev *bridge_dev;
+	u16 tmp;
+
+	if (!pdev || !aperture_size || !stolen_size)
+		return 1;
+
+	/* Find the bridge device.  It is always 0:0.0 */
+	if (!(bridge_dev = pci_find_slot(0, PCI_DEVFN(0, 0)))) {
+		ERR_MSG("cannot find bridge device\n");
+		return 1;
+	}
+
+	/* Get the fb aperture size and "stolen" memory amount. */
+	tmp = 0;
+	pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_INTEL_830M:
+	case PCI_DEVICE_ID_INTEL_845G:
+		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
+			*aperture_size = MB(64);
+		else
+			*aperture_size = MB(128);
+		switch (tmp & INTEL_830_GMCH_GMS_MASK) {
+		case INTEL_830_GMCH_GMS_STOLEN_512:
+			*stolen_size = KB(512) - KB(132);
+			return 0;
+		case INTEL_830_GMCH_GMS_STOLEN_1024:
+			*stolen_size = MB(1) - KB(132);
+			return 0;
+		case INTEL_830_GMCH_GMS_STOLEN_8192:
+			*stolen_size = MB(8) - KB(132);
+			return 0;
+		case INTEL_830_GMCH_GMS_LOCAL:
+			ERR_MSG("only local memory found\n");
+			return 1;
+		case INTEL_830_GMCH_GMS_DISABLED:
+			ERR_MSG("video memory is disabled\n");
+			return 1;
+		default:
+			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
+				tmp & INTEL_830_GMCH_GMS_MASK);
+			return 1;
+		}
+		break;
+	default:
+		*aperture_size = MB(128);
+		switch (tmp & INTEL_855_GMCH_GMS_MASK) {
+		case INTEL_855_GMCH_GMS_STOLEN_1M:
+			*stolen_size = MB(1) - KB(132);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_4M:
+			*stolen_size = MB(4) - KB(132);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_8M:
+			*stolen_size = MB(8) - KB(132);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_16M:
+			*stolen_size = MB(16) - KB(132);
+			return 0;
+		case INTEL_855_GMCH_GMS_STOLEN_32M:
+			*stolen_size = MB(32) - KB(132);
+			return 0;
+		case INTEL_855_GMCH_GMS_DISABLED:
+			ERR_MSG("video memory is disabled\n");
+			return 0;
+		default:
+			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
+				tmp & INTEL_855_GMCH_GMS_MASK);
+			return 1;
+		}
+	}
+}
+
+int
+intelfbhw_check_non_crt(struct intelfb_info *dinfo)
+{
+	int dvo = 0;
+
+	if (INREG(LVDS) & PORT_ENABLE)
+		dvo |= LVDS_PORT;
+	if (INREG(DVOA) & PORT_ENABLE)
+		dvo |= DVOA_PORT;
+	if (INREG(DVOB) & PORT_ENABLE)
+		dvo |= DVOB_PORT;
+	if (INREG(DVOC) & PORT_ENABLE)
+		dvo |= DVOC_PORT;
+
+	return dvo;
+}
+
+const char *
+intelfbhw_dvo_to_string(int dvo)
+{
+	if (dvo & DVOA_PORT)
+		return "DVO port A";
+	else if (dvo & DVOB_PORT)
+		return "DVO port B";
+	else if (dvo & DVOC_PORT)
+		return "DVO port C";
+	else if (dvo & LVDS_PORT)
+		return "LVDS port";
+	else
+		return NULL;
+}
+
+
+int
+intelfbhw_validate_mode(struct intelfb_info *dinfo,
+			struct fb_var_screeninfo *var)
+{
+	int bytes_per_pixel;
+	int tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_validate_mode\n");
+#endif
+
+	bytes_per_pixel = var->bits_per_pixel / 8;
+	if (bytes_per_pixel == 3)
+		bytes_per_pixel = 4;
+
+	/* Check if enough video memory. */
+	tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;
+	if (tmp > dinfo->fb.size) {
+		WRN_MSG("Not enough video ram for mode "
+			"(%d KByte vs %d KByte).\n",
+			BtoKB(tmp), BtoKB(dinfo->fb.size));
+		return 1;
+	}
+
+	/* Check if x/y limits are OK. */
+	if (var->xres - 1 > HACTIVE_MASK) {
+		WRN_MSG("X resolution too large (%d vs %d).\n",
+			var->xres, HACTIVE_MASK + 1);
+		return 1;
+	}
+	if (var->yres - 1 > VACTIVE_MASK) {
+		WRN_MSG("Y resolution too large (%d vs %d).\n",
+			var->yres, VACTIVE_MASK + 1);
+		return 1;
+	}
+
+	/* Check for interlaced/doublescan modes. */
+	if (var->vmode & FB_VMODE_INTERLACED) {
+		WRN_MSG("Mode is interlaced.\n");
+		return 1;
+	}
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		WRN_MSG("Mode is double-scan.\n");
+		return 1;
+	}
+
+	/* Check if clock is OK. */
+	tmp = 1000000000 / var->pixclock;
+	if (tmp < MIN_CLOCK) {
+		WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",
+			(tmp + 500) / 1000, MIN_CLOCK / 1000);
+		return 1;
+	}
+	if (tmp > MAX_CLOCK) {
+		WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",
+			(tmp + 500) / 1000, MAX_CLOCK / 1000);
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 offset, xoffset, yoffset;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_pan_display\n");
+#endif
+
+	xoffset = ROUND_DOWN_TO(var->xoffset, 8);
+	yoffset = var->yoffset;
+
+	if ((xoffset + var->xres > var->xres_virtual) ||
+	    (yoffset + var->yres > var->yres_virtual))
+		return EINVAL;
+
+	offset = (yoffset * dinfo->pitch) +
+		 (xoffset * var->bits_per_pixel) / 8;
+
+	offset += dinfo->fb.offset >> 12;
+
+	OUTREG(DSPABASE, offset);
+
+	return 0;
+}
+
+/* Blank the screen. */
+void
+intelfbhw_do_blank(int blank, struct fb_info *info)
+{
+	struct intelfb_info *dinfo = GET_DINFO(info);
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);
+#endif
+
+	/* Turn plane A on or off */
+	tmp = INREG(DSPACNTR);
+	if (blank)
+		tmp &= ~DISPPLANE_PLANE_ENABLE;
+	else
+		tmp |= DISPPLANE_PLANE_ENABLE;
+	OUTREG(DSPACNTR, tmp);
+	/* Flush */
+	tmp = INREG(DSPABASE);
+	OUTREG(DSPABASE, tmp);
+
+	/* Turn off/on the HW cursor */
+#if VERBOSE > 0
+	DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
+#endif
+	if (dinfo->cursor_on) {
+		if (blank) {
+			intelfbhw_cursor_hide(dinfo);
+		} else {
+			intelfbhw_cursor_show(dinfo);
+		}
+		dinfo->cursor_on = 1;
+	}
+	dinfo->cursor_blanked = blank;
+
+	/* Set DPMS level */
+	tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;
+	switch (blank) {
+	case 0:
+	case 1:
+		tmp |= ADPA_DPMS_D0;
+		break;
+	case 2:
+		tmp |= ADPA_DPMS_D1;
+		break;
+	case 3:
+		tmp |= ADPA_DPMS_D2;
+		break;
+	case 4:
+		tmp |= ADPA_DPMS_D3;
+		break;
+	}
+	OUTREG(ADPA, tmp);
+
+	return;
+}
+
+
+void
+intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
+		    unsigned red, unsigned green, unsigned blue,
+		    unsigned transp)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
+		regno, red, green, blue);
+#endif
+
+	u32 palette_reg = (dinfo->pipe == PIPE_A) ?
+			  PALETTE_A : PALETTE_B;
+
+	OUTREG(palette_reg + (regno << 2),
+	       (red << PALETTE_8_RED_SHIFT) |
+	       (green << PALETTE_8_GREEN_SHIFT) |
+	       (blue << PALETTE_8_BLUE_SHIFT));
+}
+
+
+int
+intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
+			int flag)
+{
+	int i;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_read_hw_state\n");
+#endif
+
+	if (!hw || !dinfo)
+		return -1;
+
+	/* Read in as much of the HW state as possible. */
+	hw->vga0_divisor = INREG(VGA0_DIVISOR);
+	hw->vga1_divisor = INREG(VGA1_DIVISOR);
+	hw->vga_pd = INREG(VGAPD);
+	hw->dpll_a = INREG(DPLL_A);
+	hw->dpll_b = INREG(DPLL_B);
+	hw->fpa0 = INREG(FPA0);
+	hw->fpa1 = INREG(FPA1);
+	hw->fpb0 = INREG(FPB0);
+	hw->fpb1 = INREG(FPB1);
+
+	if (flag == 1)
+		return flag;
+
+#if 0
+	/* This seems to be a problem with the 852GM/855GM */
+	for (i = 0; i < PALETTE_8_ENTRIES; i++) {
+		hw->palette_a[i] = INREG(PALETTE_A + (i << 2));
+		hw->palette_b[i] = INREG(PALETTE_B + (i << 2));
+	}
+#endif
+
+	if (flag == 2)
+		return flag;
+
+	hw->htotal_a = INREG(HTOTAL_A);
+	hw->hblank_a = INREG(HBLANK_A);
+	hw->hsync_a = INREG(HSYNC_A);
+	hw->vtotal_a = INREG(VTOTAL_A);
+	hw->vblank_a = INREG(VBLANK_A);
+	hw->vsync_a = INREG(VSYNC_A);
+	hw->src_size_a = INREG(SRC_SIZE_A);
+	hw->bclrpat_a = INREG(BCLRPAT_A);
+	hw->htotal_b = INREG(HTOTAL_B);
+	hw->hblank_b = INREG(HBLANK_B);
+	hw->hsync_b = INREG(HSYNC_B);
+	hw->vtotal_b = INREG(VTOTAL_B);
+	hw->vblank_b = INREG(VBLANK_B);
+	hw->vsync_b = INREG(VSYNC_B);
+	hw->src_size_b = INREG(SRC_SIZE_B);
+	hw->bclrpat_b = INREG(BCLRPAT_B);
+
+	if (flag == 3)
+		return flag;
+
+	hw->adpa = INREG(ADPA);
+	hw->dvoa = INREG(DVOA);
+	hw->dvob = INREG(DVOB);
+	hw->dvoc = INREG(DVOC);
+	hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
+	hw->dvob_srcdim = INREG(DVOB_SRCDIM);
+	hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
+	hw->lvds = INREG(LVDS);
+
+	if (flag == 4)
+		return flag;
+
+	hw->pipe_a_conf = INREG(PIPEACONF);
+	hw->pipe_b_conf = INREG(PIPEBCONF);
+	hw->disp_arb = INREG(DISPARB);
+
+	if (flag == 5)
+		return flag;
+
+	hw->cursor_a_control = INREG(CURSOR_A_CONTROL);
+	hw->cursor_b_control = INREG(CURSOR_B_CONTROL);
+	hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);
+	hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);
+
+	if (flag == 6)
+		return flag;
+
+	for (i = 0; i < 4; i++) {
+		hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));
+		hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));
+	}
+
+	if (flag == 7)
+		return flag;
+
+	hw->cursor_size = INREG(CURSOR_SIZE);
+
+	if (flag == 8)
+		return flag;
+
+	hw->disp_a_ctrl = INREG(DSPACNTR);
+	hw->disp_b_ctrl = INREG(DSPBCNTR);
+	hw->disp_a_base = INREG(DSPABASE);
+	hw->disp_b_base = INREG(DSPBBASE);
+	hw->disp_a_stride = INREG(DSPASTRIDE);
+	hw->disp_b_stride = INREG(DSPBSTRIDE);
+
+	if (flag == 9)
+		return flag;
+
+	hw->vgacntrl = INREG(VGACNTRL);
+
+	if (flag == 10)
+		return flag;
+
+	hw->add_id = INREG(ADD_ID);
+
+	if (flag == 11)
+		return flag;
+
+	for (i = 0; i < 7; i++) {
+		hw->swf0x[i] = INREG(SWF00 + (i << 2));
+		hw->swf1x[i] = INREG(SWF10 + (i << 2));
+		if (i < 3)
+			hw->swf3x[i] = INREG(SWF30 + (i << 2));
+	}
+
+	for (i = 0; i < 8; i++)
+		hw->fence[i] = INREG(FENCE + (i << 2));
+
+	hw->instpm = INREG(INSTPM);
+	hw->mem_mode = INREG(MEM_MODE);
+	hw->fw_blc_0 = INREG(FW_BLC_0);
+	hw->fw_blc_1 = INREG(FW_BLC_1);
+
+	return 0;
+}
+
+
+void
+intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
+{
+#if REGDUMP
+	int i, m1, m2, n, p1, p2;
+
+	DBG_MSG("intelfbhw_print_hw_state\n");
+
+	if (!hw || !dinfo)
+		return;
+	/* Read in as much of the HW state as possible. */
+	printk("hw state dump start\n");
+	printk("	VGA0_DIVISOR:		0x%08x\n", hw->vga0_divisor);
+	printk("	VGA1_DIVISOR:		0x%08x\n", hw->vga1_divisor);
+	printk("	VGAPD: 			0x%08x\n", hw->vga_pd);
+	n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2)
+		p1 = 0;
+	else
+		p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK;
+	p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK;
+	printk("	VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+		m1, m2, n, p1, p2);
+	printk("	VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+
+	n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2)
+		p1 = 0;
+	else
+		p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK;
+	p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK;
+	printk("	VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+		m1, m2, n, p1, p2);
+	printk("	VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+
+	printk("	DPLL_A:			0x%08x\n", hw->dpll_a);
+	printk("	DPLL_B:			0x%08x\n", hw->dpll_b);
+	printk("	FPA0:			0x%08x\n", hw->fpa0);
+	printk("	FPA1:			0x%08x\n", hw->fpa1);
+	printk("	FPB0:			0x%08x\n", hw->fpb0);
+	printk("	FPB1:			0x%08x\n", hw->fpb1);
+
+	n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
+		p1 = 0;
+	else
+		p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
+	p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+	printk("	PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+		m1, m2, n, p1, p2);
+	printk("	PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+
+	n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
+	if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
+		p1 = 0;
+	else
+		p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
+	p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+	printk("	PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
+		m1, m2, n, p1, p2);
+	printk("	PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+
+#if 0
+	printk("	PALETTE_A:\n");
+	for (i = 0; i < PALETTE_8_ENTRIES)
+		printk("	%3d:	0x%08x\n", i, hw->palette_a[i];
+	printk("	PALETTE_B:\n");
+	for (i = 0; i < PALETTE_8_ENTRIES)
+		printk("	%3d:	0x%08x\n", i, hw->palette_b[i];
+#endif
+
+	printk("	HTOTAL_A:		0x%08x\n", hw->htotal_a);
+	printk("	HBLANK_A:		0x%08x\n", hw->hblank_a);
+	printk("	HSYNC_A:		0x%08x\n", hw->hsync_a);
+	printk("	VTOTAL_A:		0x%08x\n", hw->vtotal_a);
+	printk("	VBLANK_A:		0x%08x\n", hw->vblank_a);
+	printk("	VSYNC_A:		0x%08x\n", hw->vsync_a);
+	printk("	SRC_SIZE_A:		0x%08x\n", hw->src_size_a);
+	printk("	BCLRPAT_A:		0x%08x\n", hw->bclrpat_a);
+	printk("	HTOTAL_B:		0x%08x\n", hw->htotal_b);
+	printk("	HBLANK_B:		0x%08x\n", hw->hblank_b);
+	printk("	HSYNC_B:		0x%08x\n", hw->hsync_b);
+	printk("	VTOTAL_B:		0x%08x\n", hw->vtotal_b);
+	printk("	VBLANK_B:		0x%08x\n", hw->vblank_b);
+	printk("	VSYNC_B:		0x%08x\n", hw->vsync_b);
+	printk("	SRC_SIZE_B:		0x%08x\n", hw->src_size_b);
+	printk("	BCLRPAT_B:		0x%08x\n", hw->bclrpat_b);
+
+	printk("	ADPA:			0x%08x\n", hw->adpa);
+	printk("	DVOA:			0x%08x\n", hw->dvoa);
+	printk("	DVOB:			0x%08x\n", hw->dvob);
+	printk("	DVOC:			0x%08x\n", hw->dvoc);
+	printk("	DVOA_SRCDIM:		0x%08x\n", hw->dvoa_srcdim);
+	printk("	DVOB_SRCDIM:		0x%08x\n", hw->dvob_srcdim);
+	printk("	DVOC_SRCDIM:		0x%08x\n", hw->dvoc_srcdim);
+	printk("	LVDS:			0x%08x\n", hw->lvds);
+
+	printk("	PIPEACONF:		0x%08x\n", hw->pipe_a_conf);
+	printk("	PIPEBCONF:		0x%08x\n", hw->pipe_b_conf);
+	printk("	DISPARB:		0x%08x\n", hw->disp_arb);
+
+	printk("	CURSOR_A_CONTROL:	0x%08x\n", hw->cursor_a_control);
+	printk("	CURSOR_B_CONTROL:	0x%08x\n", hw->cursor_b_control);
+	printk("	CURSOR_A_BASEADDR:	0x%08x\n", hw->cursor_a_base);
+	printk("	CURSOR_B_BASEADDR:	0x%08x\n", hw->cursor_b_base);
+
+	printk("	CURSOR_A_PALETTE:	");
+	for (i = 0; i < 4; i++) {
+		printk("0x%08x", hw->cursor_a_palette[i]);
+		if (i < 3)
+			printk(", ");
+	}
+	printk("\n");
+	printk("	CURSOR_B_PALETTE:	");
+	for (i = 0; i < 4; i++) {
+		printk("0x%08x", hw->cursor_b_palette[i]);
+		if (i < 3)
+			printk(", ");
+	}
+	printk("\n");
+
+	printk("	CURSOR_SIZE:		0x%08x\n", hw->cursor_size);
+
+	printk("	DSPACNTR:		0x%08x\n", hw->disp_a_ctrl);
+	printk("	DSPBCNTR:		0x%08x\n", hw->disp_b_ctrl);
+	printk("	DSPABASE:		0x%08x\n", hw->disp_a_base);
+	printk("	DSPBBASE:		0x%08x\n", hw->disp_b_base);
+	printk("	DSPASTRIDE:		0x%08x\n", hw->disp_a_stride);
+	printk("	DSPBSTRIDE:		0x%08x\n", hw->disp_b_stride);
+
+	printk("	VGACNTRL:		0x%08x\n", hw->vgacntrl);
+	printk("	ADD_ID:			0x%08x\n", hw->add_id);
+
+	for (i = 0; i < 7; i++) {
+		printk("	SWF0%d			0x%08x\n", i,
+			hw->swf0x[i]);
+	}
+	for (i = 0; i < 7; i++) {
+		printk("	SWF1%d			0x%08x\n", i,
+			hw->swf1x[i]);
+	}
+	for (i = 0; i < 3; i++) {
+		printk("	SWF3%d			0x%08x\n", i,
+			hw->swf3x[i]);
+	}
+	for (i = 0; i < 8; i++)
+		printk("	FENCE%d			0x%08x\n", i,
+			hw->fence[i]);
+
+	printk("	INSTPM			0x%08x\n", hw->instpm);
+	printk("	MEM_MODE		0x%08x\n", hw->mem_mode);
+	printk("	FW_BLC_0		0x%08x\n", hw->fw_blc_0);
+	printk("	FW_BLC_1		0x%08x\n", hw->fw_blc_1);
+
+	printk("hw state dump end\n");
+#endif
+}
+
+/* Split the M parameter into M1 and M2. */
+static int
+splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2)
+{
+	int m1, m2;
+
+	m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2;
+	if (m1 < MIN_M1)
+		m1 = MIN_M1;
+	if (m1 > MAX_M1)
+		m1 = MAX_M1;
+	m2 = m - 5 * (m1 + 2) - 2;
+	if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) {
+		return 1;
+	} else {
+		*retm1 = (unsigned int)m1;
+		*retm2 = (unsigned int)m2;
+		return 0;
+	}
+}
+
+/* Split the P parameter into P1 and P2. */
+static int
+splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2)
+{
+	int p1, p2;
+
+	if (p % 4 == 0)
+		p2 = 1;
+	else
+		p2 = 0;
+	p1 = (p / (1 << (p2 + 1))) - 2;
+	if (p % 4 == 0 && p1 < MIN_P1) {
+		p2 = 0;
+		p1 = (p / (1 << (p2 + 1))) - 2;
+	}
+	if (p1  < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) {
+		return 1;
+	} else {
+		*retp1 = (unsigned int)p1;
+		*retp2 = (unsigned int)p2;
+		return 0;
+	}
+}
+
+static int
+calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
+		u32 *retp2, u32 *retclock)
+{
+	u32 m1, m2, n, p1, p2, n1;
+	u32 f_vco, p, p_best = 0, m, f_out;
+	u32 err_max, err_target, err_best = 10000000;
+	u32 n_best = 0, m_best = 0, f_best, f_err;
+	u32 p_min, p_max, p_inc, div_min, div_max;
+
+	/* Accept 0.5% difference, but aim for 0.1% */
+	err_max = 5 * clock / 1000;
+	err_target = clock / 1000;
+
+	DBG_MSG("Clock is %d\n", clock);
+
+	div_max = MAX_VCO_FREQ / clock;
+	div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock;
+
+	if (clock <= P_TRANSITION_CLOCK)
+		p_inc = 4;
+	else
+		p_inc = 2;
+	p_min = ROUND_UP_TO(div_min, p_inc);
+	p_max = ROUND_DOWN_TO(div_max, p_inc);
+	if (p_min < MIN_P)
+		p_min = 4;
+	if (p_max > MAX_P)
+		p_max = 128;
+
+	DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
+
+	p = p_min;
+	do {
+		if (splitp(p, &p1, &p2)) {
+			WRN_MSG("cannot split p = %d\n", p);
+			p += p_inc;
+			continue;
+		}
+		n = MIN_N;
+		f_vco = clock * p;
+
+		do {
+			m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK;
+			if (m < MIN_M)
+				m = MIN_M;
+			if (m > MAX_M)
+				m = MAX_M;
+			f_out = CALC_VCLOCK3(m, n, p);
+			if (splitm(m, &m1, &m2)) {
+				WRN_MSG("cannot split m = %d\n", m);
+				n++;
+				continue;
+			}
+			if (clock > f_out)
+				f_err = clock - f_out;
+			else
+				f_err = f_out - clock;
+
+			if (f_err < err_best) {
+				m_best = m;
+				n_best = n;
+				p_best = p;
+				f_best = f_out;
+				err_best = f_err;
+			}
+			n++;
+		} while ((n <= MAX_N) && (f_out >= clock));
+		p += p_inc;
+	} while ((p <= p_max));
+
+	if (!m_best) {
+		WRN_MSG("cannot find parameters for clock %d\n", clock);
+		return 1;
+	}
+	m = m_best;
+	n = n_best;
+	p = p_best;
+	splitm(m, &m1, &m2);
+	splitp(p, &p1, &p2);
+	n1 = n - 2;
+
+	DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
+		"f: %d (%d), VCO: %d\n",
+		m, m1, m2, n, n1, p, p1, p2,
+		CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2),
+		CALC_VCLOCK3(m, n, p) * p);
+	*retm1 = m1;
+	*retm2 = m2;
+	*retn = n1;
+	*retp1 = p1;
+	*retp2 = p2;
+	*retclock = CALC_VCLOCK(m1, m2, n1, p1, p2);
+
+	return 0;
+}
+
+static __inline__ int
+check_overflow(u32 value, u32 limit, const char *description)
+{
+	if (value > limit) {
+		WRN_MSG("%s value %d exceeds limit %d\n",
+			description, value, limit);
+		return 1;
+	}
+	return 0;
+}
+
+/* It is assumed that hw is filled in with the initial state information. */
+int
+intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
+		     struct fb_var_screeninfo *var)
+{
+	int pipe = PIPE_A;
+	u32 *dpll, *fp0, *fp1;
+	u32 m1, m2, n, p1, p2, clock_target, clock;
+	u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
+	u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
+	u32 vsync_pol, hsync_pol;
+	u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
+
+	DBG_MSG("intelfbhw_mode_to_hw\n");
+
+	/* Disable VGA */
+	hw->vgacntrl |= VGA_DISABLE;
+
+	/* Check whether pipe A or pipe B is enabled. */
+	if (hw->pipe_a_conf & PIPECONF_ENABLE)
+		pipe = PIPE_A;
+	else if (hw->pipe_b_conf & PIPECONF_ENABLE)
+		pipe = PIPE_B;
+
+	/* Set which pipe's registers will be set. */
+	if (pipe == PIPE_B) {
+		dpll = &hw->dpll_b;
+		fp0 = &hw->fpb0;
+		fp1 = &hw->fpb1;
+		hs = &hw->hsync_b;
+		hb = &hw->hblank_b;
+		ht = &hw->htotal_b;
+		vs = &hw->vsync_b;
+		vb = &hw->vblank_b;
+		vt = &hw->vtotal_b;
+		ss = &hw->src_size_b;
+		pipe_conf = &hw->pipe_b_conf;
+	} else {
+		dpll = &hw->dpll_a;
+		fp0 = &hw->fpa0;
+		fp1 = &hw->fpa1;
+		hs = &hw->hsync_a;
+		hb = &hw->hblank_a;
+		ht = &hw->htotal_a;
+		vs = &hw->vsync_a;
+		vb = &hw->vblank_a;
+		vt = &hw->vtotal_a;
+		ss = &hw->src_size_a;
+		pipe_conf = &hw->pipe_a_conf;
+	}
+
+	/* Use ADPA register for sync control. */
+	hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
+
+	/* sync polarity */
+	hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ?
+			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
+	vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ?
+			ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
+	hw->adpa &= ~((ADPA_SYNC_ACTIVE_MASK << ADPA_VSYNC_ACTIVE_SHIFT) |
+		      (ADPA_SYNC_ACTIVE_MASK << ADPA_HSYNC_ACTIVE_SHIFT));
+	hw->adpa |= (hsync_pol << ADPA_HSYNC_ACTIVE_SHIFT) |
+		    (vsync_pol << ADPA_VSYNC_ACTIVE_SHIFT);
+
+	/* Connect correct pipe to the analog port DAC */
+	hw->adpa &= ~(PIPE_MASK << ADPA_PIPE_SELECT_SHIFT);
+	hw->adpa |= (pipe << ADPA_PIPE_SELECT_SHIFT);
+
+	/* Set DPMS state to D0 (on) */
+	hw->adpa &= ~ADPA_DPMS_CONTROL_MASK;
+	hw->adpa |= ADPA_DPMS_D0;
+
+	hw->adpa |= ADPA_DAC_ENABLE;
+
+	*dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
+	*dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
+	*dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
+
+	/* Desired clock in kHz */
+	clock_target = 1000000000 / var->pixclock;
+
+	if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) {
+		WRN_MSG("calc_pll_params failed\n");
+		return 1;
+	}
+
+	/* Check for overflow. */
+	if (check_overflow(p1, DPLL_P1_MASK, "PLL P1 parameter"))
+		return 1;
+	if (check_overflow(p2, DPLL_P2_MASK, "PLL P2 parameter"))
+		return 1;
+	if (check_overflow(m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
+		return 1;
+	if (check_overflow(m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
+		return 1;
+	if (check_overflow(n, FP_DIVISOR_MASK, "PLL N parameter"))
+		return 1;
+
+	*dpll &= ~DPLL_P1_FORCE_DIV2;
+	*dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
+		   (DPLL_P1_MASK << DPLL_P1_SHIFT));
+	*dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
+	*fp0 = (n << FP_N_DIVISOR_SHIFT) |
+	       (m1 << FP_M1_DIVISOR_SHIFT) |
+	       (m2 << FP_M2_DIVISOR_SHIFT);
+	*fp1 = *fp0;
+
+	hw->dvob &= ~PORT_ENABLE;
+	hw->dvoc &= ~PORT_ENABLE;
+
+	/* Use display plane A. */
+	hw->disp_a_ctrl |= DISPPLANE_PLANE_ENABLE;
+	hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
+	hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
+	switch (intelfb_var_to_depth(var)) {
+	case 8:
+		hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
+		break;
+	case 15:
+		hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
+		break;
+	case 16:
+		hw->disp_a_ctrl |= DISPPLANE_16BPP;
+		break;
+	case 24:
+		hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
+		break;
+	}
+	hw->disp_a_ctrl &= ~(PIPE_MASK << DISPPLANE_SEL_PIPE_SHIFT);
+	hw->disp_a_ctrl |= (pipe << DISPPLANE_SEL_PIPE_SHIFT);
+
+	/* Set CRTC registers. */
+	hactive = var->xres;
+	hsync_start = hactive + var->right_margin;
+	hsync_end = hsync_start + var->hsync_len;
+	htotal = hsync_end + var->left_margin;
+	hblank_start = hactive;
+	hblank_end = htotal;
+
+	DBG_MSG("H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
+		hactive, hsync_start, hsync_end, htotal, hblank_start,
+		hblank_end);
+
+	vactive = var->yres;
+	vsync_start = vactive + var->lower_margin;
+	vsync_end = vsync_start + var->vsync_len;
+	vtotal = vsync_end + var->upper_margin;
+	vblank_start = vactive;
+	vblank_end = vtotal;
+	vblank_end = vsync_end + 1;
+
+	DBG_MSG("V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
+		vactive, vsync_start, vsync_end, vtotal, vblank_start,
+		vblank_end);
+
+	/* Adjust for register values, and check for overflow. */
+	hactive--;
+	if (check_overflow(hactive, HACTIVE_MASK, "CRTC hactive"))
+		return 1;
+	hsync_start--;
+	if (check_overflow(hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
+		return 1;
+	hsync_end--;
+	if (check_overflow(hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
+		return 1;
+	htotal--;
+	if (check_overflow(htotal, HTOTAL_MASK, "CRTC htotal"))
+		return 1;
+	hblank_start--;
+	if (check_overflow(hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
+		return 1;
+	hblank_end--;
+	if (check_overflow(hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
+		return 1;
+
+	vactive--;
+	if (check_overflow(vactive, VACTIVE_MASK, "CRTC vactive"))
+		return 1;
+	vsync_start--;
+	if (check_overflow(vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
+		return 1;
+	vsync_end--;
+	if (check_overflow(vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
+		return 1;
+	vtotal--;
+	if (check_overflow(vtotal, VTOTAL_MASK, "CRTC vtotal"))
+		return 1;
+	vblank_start--;
+	if (check_overflow(vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
+		return 1;
+	vblank_end--;
+	if (check_overflow(vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
+		return 1;
+
+	*ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
+	*hb = (hblank_start << HBLANKSTART_SHIFT) |
+	      (hblank_end << HSYNCEND_SHIFT);
+	*hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
+
+	*vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
+	*vb = (vblank_start << VBLANKSTART_SHIFT) |
+	      (vblank_end << VSYNCEND_SHIFT);
+	*vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
+	*ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
+	      (vactive << SRC_SIZE_VERT_SHIFT);
+
+	hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8;
+	DBG_MSG("pitch is %d\n", hw->disp_a_stride);
+
+	hw->disp_a_base = hw->disp_a_stride * var->yoffset +
+			  var->xoffset * var->bits_per_pixel / 8;
+
+	hw->disp_a_base += dinfo->fb.offset << 12;
+
+	/* Check stride alignment. */
+	if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) {
+		WRN_MSG("display stride %d has bad alignment %d\n",
+			hw->disp_a_stride, STRIDE_ALIGNMENT);
+		return 1;
+	}
+
+	/* Set the palette to 8-bit mode. */
+	*pipe_conf &= ~PIPECONF_GAMMA;
+	return 0;
+}
+
+/* Program a (non-VGA) video mode. */
+int
+intelfbhw_program_mode(struct intelfb_info *dinfo,
+		     const struct intelfb_hwstate *hw, int blank)
+{
+	int pipe = PIPE_A;
+	u32 tmp;
+	const u32 *dpll, *fp0, *fp1, *pipe_conf;
+	const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
+	u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg;
+	u32 hsync_reg, htotal_reg, hblank_reg;
+	u32 vsync_reg, vtotal_reg, vblank_reg;
+	u32 src_size_reg;
+
+	/* Assume single pipe, display plane A, analog CRT. */
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_program_mode\n");
+#endif
+
+	/* Disable VGA */
+	tmp = INREG(VGACNTRL);
+	tmp |= VGA_DISABLE;
+	OUTREG(VGACNTRL, tmp);
+
+	/* Check whether pipe A or pipe B is enabled. */
+	if (hw->pipe_a_conf & PIPECONF_ENABLE)
+		pipe = PIPE_A;
+	else if (hw->pipe_b_conf & PIPECONF_ENABLE)
+		pipe = PIPE_B;
+
+	dinfo->pipe = pipe;
+
+	if (pipe == PIPE_B) {
+		dpll = &hw->dpll_b;
+		fp0 = &hw->fpb0;
+		fp1 = &hw->fpb1;
+		pipe_conf = &hw->pipe_b_conf;
+		hs = &hw->hsync_b;
+		hb = &hw->hblank_b;
+		ht = &hw->htotal_b;
+		vs = &hw->vsync_b;
+		vb = &hw->vblank_b;
+		vt = &hw->vtotal_b;
+		ss = &hw->src_size_b;
+		dpll_reg = DPLL_B;
+		fp0_reg = FPB0;
+		fp1_reg = FPB1;
+		pipe_conf_reg = PIPEBCONF;
+		hsync_reg = HSYNC_B;
+		htotal_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		vsync_reg = VSYNC_B;
+		vtotal_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		src_size_reg = SRC_SIZE_B;
+	} else {
+		dpll = &hw->dpll_a;
+		fp0 = &hw->fpa0;
+		fp1 = &hw->fpa1;
+		pipe_conf = &hw->pipe_a_conf;
+		hs = &hw->hsync_a;
+		hb = &hw->hblank_a;
+		ht = &hw->htotal_a;
+		vs = &hw->vsync_a;
+		vb = &hw->vblank_a;
+		vt = &hw->vtotal_a;
+		ss = &hw->src_size_a;
+		dpll_reg = DPLL_A;
+		fp0_reg = FPA0;
+		fp1_reg = FPA1;
+		pipe_conf_reg = PIPEACONF;
+		hsync_reg = HSYNC_A;
+		htotal_reg = HTOTAL_A;
+		hblank_reg = HBLANK_A;
+		vsync_reg = VSYNC_A;
+		vtotal_reg = VTOTAL_A;
+		vblank_reg = VBLANK_A;
+		src_size_reg = SRC_SIZE_A;
+	}
+
+	/* Disable planes A and B. */
+	tmp = INREG(DSPACNTR);
+	tmp &= ~DISPPLANE_PLANE_ENABLE;
+	OUTREG(DSPACNTR, tmp);
+	tmp = INREG(DSPBCNTR);
+	tmp &= ~DISPPLANE_PLANE_ENABLE;
+	OUTREG(DSPBCNTR, tmp);
+
+	/* Wait for vblank.  For now, just wait for a 50Hz cycle (20ms)) */
+	mdelay(20);
+
+	/* Disable Sync */
+	tmp = INREG(ADPA);
+	tmp &= ~ADPA_DPMS_CONTROL_MASK;
+	tmp |= ADPA_DPMS_D3;
+	OUTREG(ADPA, tmp);
+
+	/* turn off pipe */
+	tmp = INREG(pipe_conf_reg);
+	tmp &= ~PIPECONF_ENABLE;
+	OUTREG(pipe_conf_reg, tmp);
+
+	/* turn off PLL */
+	tmp = INREG(dpll_reg);
+	dpll_reg &= ~DPLL_VCO_ENABLE;
+	OUTREG(dpll_reg, tmp);
+
+	/* Set PLL parameters */
+	OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE);
+	OUTREG(fp0_reg, *fp0);
+	OUTREG(fp1_reg, *fp1);
+
+	/* Set pipe parameters */
+	OUTREG(hsync_reg, *hs);
+	OUTREG(hblank_reg, *hb);
+	OUTREG(htotal_reg, *ht);
+	OUTREG(vsync_reg, *vs);
+	OUTREG(vblank_reg, *vb);
+	OUTREG(vtotal_reg, *vt);
+	OUTREG(src_size_reg, *ss);
+
+	/* Set DVOs B/C */
+	OUTREG(DVOB, hw->dvob);
+	OUTREG(DVOC, hw->dvoc);
+
+	/* Set ADPA */
+	OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
+
+	/* Enable PLL */
+	tmp = INREG(dpll_reg);
+	tmp |= DPLL_VCO_ENABLE;
+	OUTREG(dpll_reg, tmp);
+
+	/* Enable pipe */
+	OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
+
+	/* Enable sync */
+	tmp = INREG(ADPA);
+	tmp &= ~ADPA_DPMS_CONTROL_MASK;
+	tmp |= ADPA_DPMS_D0;
+	OUTREG(ADPA, tmp);
+
+	/* setup display plane */
+	OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
+	OUTREG(DSPASTRIDE, hw->disp_a_stride);
+	OUTREG(DSPABASE, hw->disp_a_base);
+
+	/* Enable plane */
+	if (!blank) {
+		tmp = INREG(DSPACNTR);
+		tmp |= DISPPLANE_PLANE_ENABLE;
+		OUTREG(DSPACNTR, tmp);
+		OUTREG(DSPABASE, hw->disp_a_base);
+	}
+
+	return 0;
+}
+
+/* forward declarations */
+static void refresh_ring(struct intelfb_info *dinfo);
+static void reset_state(struct intelfb_info *dinfo);
+static void do_flush(struct intelfb_info *dinfo);
+
+static int
+wait_ring(struct intelfb_info *dinfo, int n)
+{
+	int i = 0;
+	unsigned long end;
+	u32 last_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
+
+#if VERBOSE > 0
+	DBG_MSG("wait_ring: %d\n", n);
+#endif
+
+	end = jiffies + (HZ * 3);
+	while (dinfo->ring_space < n) {
+		dinfo->ring_head = (u32 __iomem *)(INREG(PRI_RING_HEAD) &
+						   RING_HEAD_MASK);
+		if (dinfo->ring_tail + RING_MIN_FREE <
+		    (u32 __iomem) dinfo->ring_head)
+			dinfo->ring_space = (u32 __iomem) dinfo->ring_head
+				- (dinfo->ring_tail + RING_MIN_FREE);
+		else
+			dinfo->ring_space = (dinfo->ring.size +
+					     (u32 __iomem) dinfo->ring_head)
+				- (dinfo->ring_tail + RING_MIN_FREE);
+		if ((u32 __iomem) dinfo->ring_head != last_head) {
+			end = jiffies + (HZ * 3);
+			last_head = (u32 __iomem) dinfo->ring_head;
+		}
+		i++;
+		if (time_before(end, jiffies)) {
+			if (!i) {
+				/* Try again */
+				reset_state(dinfo);
+				refresh_ring(dinfo);
+				do_flush(dinfo);
+				end = jiffies + (HZ * 3);
+				i = 1;
+			} else {
+				WRN_MSG("ring buffer : space: %d wanted %d\n",
+					dinfo->ring_space, n);
+				WRN_MSG("lockup - turning off hardware "
+					"acceleration\n");
+				dinfo->ring_lockup = 1;
+				break;
+			}
+		}
+		udelay(1);
+	}
+	return i;
+}
+
+static void
+do_flush(struct intelfb_info *dinfo) {
+	START_RING(2);
+	OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+	OUT_RING(MI_NOOP);
+	ADVANCE_RING();
+}
+
+void
+intelfbhw_do_sync(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_sync\n");
+#endif
+
+	if (!dinfo->accel)
+		return;
+
+	/*
+	 * Send a flush, then wait until the ring is empty.  This is what
+	 * the XFree86 driver does, and actually it doesn't seem a lot worse
+	 * than the recommended method (both have problems).
+	 */
+	do_flush(dinfo);
+	wait_ring(dinfo, dinfo->ring.size - RING_MIN_FREE);
+	dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
+}
+
+static void
+refresh_ring(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("refresh_ring\n");
+#endif
+
+	dinfo->ring_head = (u32 __iomem *) (INREG(PRI_RING_HEAD) &
+		RING_HEAD_MASK);
+	dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
+	if (dinfo->ring_tail + RING_MIN_FREE < (u32 __iomem)dinfo->ring_head)
+		dinfo->ring_space = (u32 __iomem) dinfo->ring_head
+			- (dinfo->ring_tail + RING_MIN_FREE);
+	else
+		dinfo->ring_space = (dinfo->ring.size +
+				     (u32 __iomem) dinfo->ring_head)
+			- (dinfo->ring_tail + RING_MIN_FREE);
+}
+
+static void
+reset_state(struct intelfb_info *dinfo)
+{
+	int i;
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("reset_state\n");
+#endif
+
+	for (i = 0; i < FENCE_NUM; i++)
+		OUTREG(FENCE + (i << 2), 0);
+
+	/* Flush the ring buffer if it's enabled. */
+	tmp = INREG(PRI_RING_LENGTH);
+	if (tmp & RING_ENABLE) {
+#if VERBOSE > 0
+		DBG_MSG("reset_state: ring was enabled\n");
+#endif
+		refresh_ring(dinfo);
+		intelfbhw_do_sync(dinfo);
+		DO_RING_IDLE();
+	}
+
+	OUTREG(PRI_RING_LENGTH, 0);
+	OUTREG(PRI_RING_HEAD, 0);
+	OUTREG(PRI_RING_TAIL, 0);
+	OUTREG(PRI_RING_START, 0);
+}
+
+/* Stop the 2D engine, and turn off the ring buffer. */
+void
+intelfbhw_2d_stop(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n", dinfo->accel,
+		dinfo->ring_active);
+#endif
+
+	if (!dinfo->accel)
+		return;
+
+	dinfo->ring_active = 0;
+	reset_state(dinfo);
+}
+
+/*
+ * Enable the ring buffer, and initialise the 2D engine.
+ * It is assumed that the graphics engine has been stopped by previously
+ * calling intelfb_2d_stop().
+ */
+void
+intelfbhw_2d_start(struct intelfb_info *dinfo)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
+		dinfo->accel, dinfo->ring_active);
+#endif
+
+	if (!dinfo->accel)
+		return;
+
+	/* Initialise the primary ring buffer. */
+	OUTREG(PRI_RING_LENGTH, 0);
+	OUTREG(PRI_RING_TAIL, 0);
+	OUTREG(PRI_RING_HEAD, 0);
+
+	OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);
+	OUTREG(PRI_RING_LENGTH,
+		((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |
+		RING_NO_REPORT | RING_ENABLE);
+	refresh_ring(dinfo);
+	dinfo->ring_active = 1;
+}
+
+/* 2D fillrect (solid fill or invert) */
+void
+intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w, u32 h,
+		      u32 color, u32 pitch, u32 bpp, u32 rop)
+{
+	u32 br00, br09, br13, br14, br16;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "
+		"rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);
+#endif
+
+	br00 = COLOR_BLT_CMD;
+	br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));
+	br13 = (rop << ROP_SHIFT) | pitch;
+	br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);
+	br16 = color;
+
+	switch (bpp) {
+	case 8:
+		br13 |= COLOR_DEPTH_8;
+		break;
+	case 16:
+		br13 |= COLOR_DEPTH_16;
+		break;
+	case 32:
+		br13 |= COLOR_DEPTH_32;
+		br00 |= WRITE_ALPHA | WRITE_RGB;
+		break;
+	}
+
+	START_RING(6);
+	OUT_RING(br00);
+	OUT_RING(br13);
+	OUT_RING(br14);
+	OUT_RING(br09);
+	OUT_RING(br16);
+	OUT_RING(MI_NOOP);
+	ADVANCE_RING();
+
+#if VERBOSE > 0
+	DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,
+		dinfo->ring_tail, dinfo->ring_space);
+#endif
+}
+
+void
+intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
+		    u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp)
+{
+	u32 br00, br09, br11, br12, br13, br22, br23, br26;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",
+		curx, cury, dstx, dsty, w, h, pitch, bpp);
+#endif
+
+	br00 = XY_SRC_COPY_BLT_CMD;
+	br09 = dinfo->fb_start;
+	br11 = (pitch << PITCH_SHIFT);
+	br12 = dinfo->fb_start;
+	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
+	br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);
+	br23 = ((dstx + w) << WIDTH_SHIFT) |
+	       ((dsty + h) << HEIGHT_SHIFT);
+	br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);
+
+	switch (bpp) {
+	case 8:
+		br13 |= COLOR_DEPTH_8;
+		break;
+	case 16:
+		br13 |= COLOR_DEPTH_16;
+		break;
+	case 32:
+		br13 |= COLOR_DEPTH_32;
+		br00 |= WRITE_ALPHA | WRITE_RGB;
+		break;
+	}
+
+	START_RING(8);
+	OUT_RING(br00);
+	OUT_RING(br13);
+	OUT_RING(br22);
+	OUT_RING(br23);
+	OUT_RING(br09);
+	OUT_RING(br26);
+	OUT_RING(br11);
+	OUT_RING(br12);
+	ADVANCE_RING();
+}
+
+int
+intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
+		       u32 h, const u8* cdat, u32 x, u32 y, u32 pitch, u32 bpp)
+{
+	int nbytes, ndwords, pad, tmp;
+	u32 br00, br09, br13, br18, br19, br22, br23;
+	int dat, ix, iy, iw;
+	int i, j;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);
+#endif
+
+	/* size in bytes of a padded scanline */
+	nbytes = ROUND_UP_TO(w, 16) / 8;
+
+	/* Total bytes of padded scanline data to write out. */
+	nbytes = nbytes * h;
+
+	/*
+	 * Check if the glyph data exceeds the immediate mode limit.
+	 * It would take a large font (1K pixels) to hit this limit.
+	 */
+	if (nbytes > MAX_MONO_IMM_SIZE)
+		return 0;
+
+	/* Src data is packaged a dword (32-bit) at a time. */
+	ndwords = ROUND_UP_TO(nbytes, 4) / 4;
+
+	/*
+	 * Ring has to be padded to a quad word. But because the command starts
+	   with 7 bytes, pad only if there is an even number of ndwords
+	 */
+	pad = !(ndwords % 2);
+
+	tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;
+	br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;
+	br09 = dinfo->fb_start;
+	br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
+	br18 = bg;
+	br19 = fg;
+	br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);
+	br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);
+
+	switch (bpp) {
+	case 8:
+		br13 |= COLOR_DEPTH_8;
+		break;
+	case 16:
+		br13 |= COLOR_DEPTH_16;
+		break;
+	case 32:
+		br13 |= COLOR_DEPTH_32;
+		br00 |= WRITE_ALPHA | WRITE_RGB;
+		break;
+	}
+
+	START_RING(8 + ndwords);
+	OUT_RING(br00);
+	OUT_RING(br13);
+	OUT_RING(br22);
+	OUT_RING(br23);
+	OUT_RING(br09);
+	OUT_RING(br18);
+	OUT_RING(br19);
+	ix = iy = 0;
+	iw = ROUND_UP_TO(w, 8) / 8;
+	while (ndwords--) {
+		dat = 0;
+		for (j = 0; j < 2; ++j) {
+			for (i = 0; i < 2; ++i) {
+				if (ix != iw || i == 0)
+					dat |= cdat[iy*iw + ix++] << (i+j*2)*8;
+			}
+			if (ix == iw && iy != (h-1)) {
+				ix = 0;
+				++iy;
+			}
+		}
+		OUT_RING(dat);
+	}
+	if (pad)
+		OUT_RING(MI_NOOP);
+	ADVANCE_RING();
+
+	return 1;
+}
+
+/* HW cursor functions. */
+void
+intelfbhw_cursor_init(struct intelfb_info *dinfo)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_init\n");
+#endif
+
+	if (dinfo->mobile) {
+		if (!dinfo->cursor.physical)
+			return;
+		tmp = INREG(CURSOR_A_CONTROL);
+		tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |
+			 CURSOR_MEM_TYPE_LOCAL |
+			 (1 << CURSOR_PIPE_SELECT_SHIFT));
+		tmp |= CURSOR_MODE_DISABLE;
+		OUTREG(CURSOR_A_CONTROL, tmp);
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+	} else {
+		tmp = INREG(CURSOR_CONTROL);
+		tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
+			 CURSOR_ENABLE | CURSOR_STRIDE_MASK);
+		tmp = CURSOR_FORMAT_3C;
+		OUTREG(CURSOR_CONTROL, tmp);
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+		tmp = (64 << CURSOR_SIZE_H_SHIFT) |
+		      (64 << CURSOR_SIZE_V_SHIFT);
+		OUTREG(CURSOR_SIZE, tmp);
+	}
+}
+
+void
+intelfbhw_cursor_hide(struct intelfb_info *dinfo)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_hide\n");
+#endif
+
+	dinfo->cursor_on = 0;
+	if (dinfo->mobile) {
+		if (!dinfo->cursor.physical)
+			return;
+		tmp = INREG(CURSOR_A_CONTROL);
+		tmp &= ~CURSOR_MODE_MASK;
+		tmp |= CURSOR_MODE_DISABLE;
+		OUTREG(CURSOR_A_CONTROL, tmp);
+		/* Flush changes */
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+	} else {
+		tmp = INREG(CURSOR_CONTROL);
+		tmp &= ~CURSOR_ENABLE;
+		OUTREG(CURSOR_CONTROL, tmp);
+	}
+}
+
+void
+intelfbhw_cursor_show(struct intelfb_info *dinfo)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_show\n");
+#endif
+
+	dinfo->cursor_on = 1;
+
+	if (dinfo->cursor_blanked)
+		return;
+
+	if (dinfo->mobile) {
+		if (!dinfo->cursor.physical)
+			return;
+		tmp = INREG(CURSOR_A_CONTROL);
+		tmp &= ~CURSOR_MODE_MASK;
+		tmp |= CURSOR_MODE_64_4C_AX;
+		OUTREG(CURSOR_A_CONTROL, tmp);
+		/* Flush changes */
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+	} else {
+		tmp = INREG(CURSOR_CONTROL);
+		tmp |= CURSOR_ENABLE;
+		OUTREG(CURSOR_CONTROL, tmp);
+	}
+}
+
+void
+intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
+{
+	u32 tmp;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);
+#endif
+
+	/*
+	 * Sets the position.  The coordinates are assumed to already
+	 * have any offset adjusted.  Assume that the cursor is never
+	 * completely off-screen, and that x, y are always >= 0.
+	 */
+
+	tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
+	      ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+	OUTREG(CURSOR_A_POSITION, tmp);
+}
+
+void
+intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
+{
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_setcolor\n");
+#endif
+
+	OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);
+	OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);
+	OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);
+	OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
+}
+
+void
+intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
+		      u8 *data)
+{
+	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
+	int i, j, w = width / 8;
+	int mod = width % 8, t_mask, d_mask;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_load\n");
+#endif
+
+	if (!dinfo->cursor.virtual)
+		return;
+
+	t_mask = 0xff >> mod;
+	d_mask = ~(0xff >> mod);
+	for (i = height; i--; ) {
+		for (j = 0; j < w; j++) {
+			writeb(0x00, addr + j);
+			writeb(*(data++), addr + j+8);
+		}
+		if (mod) {
+			writeb(t_mask, addr + j);
+			writeb(*(data++) & d_mask, addr + j+8);
+		}
+		addr += 16;
+	}
+}
+
+void
+intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
+	u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
+	int i, j;
+
+#if VERBOSE > 0
+	DBG_MSG("intelfbhw_cursor_reset\n");
+#endif
+
+	if (!dinfo->cursor.virtual)
+		return;
+
+	for (i = 64; i--; ) {
+		for (j = 0; j < 8; j++) {
+			writeb(0xff, addr + j+0);
+			writeb(0x00, addr + j+8);
+		}
+		addr += 16;
+	}
+}
diff -Nru a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/intelfb/intelfbhw.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,567 @@
+#ifndef _INTELFBHW_H
+#define _INTELFBHW_H
+
+/* $DHD: intelfb/intelfbhw.h,v 1.5 2003/06/27 15:06:25 dawes Exp $ */
+
+
+/*** HW-specific data ***/
+
+/* Information about the 852GM/855GM variants */
+#define INTEL_85X_CAPID		0x44
+#define INTEL_85X_VARIANT_MASK		0x7
+#define INTEL_85X_VARIANT_SHIFT		5
+#define INTEL_VAR_855GME		0x0
+#define INTEL_VAR_855GM			0x4
+#define INTEL_VAR_852GME		0x2
+#define INTEL_VAR_852GM			0x5
+
+/* Information about DVO/LVDS Ports */
+#define DVOA_PORT  0x1
+#define DVOB_PORT  0x2
+#define DVOC_PORT  0x4
+#define LVDS_PORT  0x8
+
+/*
+ * The Bridge device's PCI config space has information about the
+ * fb aperture size and the amount of pre-reserved memory.
+ */
+#define INTEL_GMCH_CTRL		0x52
+#define INTEL_GMCH_ENABLED		0x4
+#define INTEL_GMCH_MEM_MASK		0x1
+#define INTEL_GMCH_MEM_64M		0x1
+#define INTEL_GMCH_MEM_128M		0
+
+#define INTEL_830_GMCH_GMS_MASK		(0x7 << 4)
+#define INTEL_830_GMCH_GMS_DISABLED	(0x0 << 4)
+#define INTEL_830_GMCH_GMS_LOCAL	(0x1 << 4)
+#define INTEL_830_GMCH_GMS_STOLEN_512	(0x2 << 4)
+#define INTEL_830_GMCH_GMS_STOLEN_1024	(0x3 << 4)
+#define INTEL_830_GMCH_GMS_STOLEN_8192	(0x4 << 4)
+
+#define INTEL_855_GMCH_GMS_MASK		(0x7 << 4)
+#define INTEL_855_GMCH_GMS_DISABLED	(0x0 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_1M	(0x1 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_4M	(0x2 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_8M	(0x3 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_16M	(0x4 << 4)
+#define INTEL_855_GMCH_GMS_STOLEN_32M	(0x5 << 4)
+
+/* HW registers */
+
+/* Fence registers */
+#define FENCE			0x2000
+#define FENCE_NUM			8
+
+/* Primary ring buffer */
+#define PRI_RING_TAIL		0x2030
+#define RING_TAIL_MASK			0x001ffff8
+#define RING_INUSE			0x1
+
+#define PRI_RING_HEAD		0x2034
+#define RING_HEAD_WRAP_MASK		0x7ff
+#define RING_HEAD_WRAP_SHIFT		21
+#define RING_HEAD_MASK			0x001ffffc
+
+#define PRI_RING_START		0x2038
+#define RING_START_MASK			0xfffff000
+
+#define PRI_RING_LENGTH		0x203c
+#define RING_LENGTH_MASK		0x001ff000
+#define RING_REPORT_MASK		(0x3 << 1)
+#define RING_NO_REPORT			(0x0 << 1)
+#define RING_REPORT_64K			(0x1 << 1)
+#define RING_REPORT_4K			(0x2 << 1)
+#define RING_REPORT_128K		(0x3 << 1)
+#define RING_ENABLE			0x1
+
+/*
+ * Tail can't wrap to any closer than RING_MIN_FREE bytes of the head,
+ * and the last RING_MIN_FREE bytes need to be padded with MI_NOOP
+ */
+#define RING_MIN_FREE			64
+
+#define IPEHR     		0x2088
+
+#define INSTDONE		0x2090
+#define PRI_RING_EMPTY			1
+
+#define INSTPM			0x20c0
+#define SYNC_FLUSH_ENABLE		(1 << 5)
+
+#define INSTPS			0x20c4
+
+#define MEM_MODE		0x20cc
+
+#define MASK_SHIFT			16
+
+#define FW_BLC_0		0x20d8
+#define FW_DISPA_WM_SHIFT		0
+#define FW_DISPA_WM_MASK		0x3f
+#define FW_DISPA_BL_SHIFT		8
+#define FW_DISPA_BL_MASK		0xf
+#define FW_DISPB_WM_SHIFT		16
+#define FW_DISPB_WM_MASK		0x1f
+#define FW_DISPB_BL_SHIFT		24
+#define FW_DISPB_BL_MASK		0x7
+
+#define FW_BLC_1		0x20dc
+#define FW_DISPC_WM_SHIFT		0
+#define FW_DISPC_WM_MASK		0x1f
+#define FW_DISPC_BL_SHIFT		8
+#define FW_DISPC_BL_MASK		0x7
+
+
+/* PLL registers */
+#define VGA0_DIVISOR		0x06000
+#define VGA1_DIVISOR		0x06004
+#define VGAPD			0x06010
+#define VGAPD_0_P1_SHIFT		0
+#define VGAPD_0_P1_FORCE_DIV2		(1 << 5)
+#define VGAPD_0_P2_SHIFT		7
+#define VGAPD_1_P1_SHIFT		8
+#define VGAPD_1_P1_FORCE_DIV2		(1 << 13)
+#define VGAPD_1_P2_SHIFT		15
+
+#define DPLL_A			0x06014
+#define DPLL_B			0x06018
+#define DPLL_VCO_ENABLE			(1 << 31)
+#define DPLL_2X_CLOCK_ENABLE		(1 << 30)
+#define DPLL_SYNCLOCK_ENABLE		(1 << 29)
+#define DPLL_VGA_MODE_DISABLE		(1 << 28)
+#define DPLL_P2_MASK			1
+#define DPLL_P2_SHIFT			23
+#define DPLL_P1_FORCE_DIV2		(1 << 21)
+#define DPLL_P1_MASK			0x1f
+#define DPLL_P1_SHIFT			16
+#define DPLL_REFERENCE_SELECT_MASK	(0x3 << 13)
+#define DPLL_REFERENCE_DEFAULT		(0x0 << 13)
+#define DPLL_REFERENCE_TVCLK		(0x2 << 13)
+#define DPLL_RATE_SELECT_MASK		(1 << 8)
+#define DPLL_RATE_SELECT_FP0		(0 << 8)
+#define DPLL_RATE_SELECT_FP1		(1 << 8)
+
+#define FPA0			0x06040
+#define FPA1			0x06044
+#define FPB0			0x06048
+#define FPB1			0x0604c
+#define FP_DIVISOR_MASK			0x3f
+#define FP_N_DIVISOR_SHIFT		16
+#define FP_M1_DIVISOR_SHIFT		8
+#define FP_M2_DIVISOR_SHIFT		0
+
+/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
+/* Clock values are in units of kHz */
+#define PLL_REFCLK		48000
+#define MIN_VCO_FREQ		930000
+#define MAX_VCO_FREQ		1400000
+#define MIN_CLOCK		25000
+#define MAX_CLOCK		350000
+#define P_TRANSITION_CLOCK	165000
+#define MIN_M			108
+#define MAX_M			140
+#define MIN_M1			18
+#define MAX_M1			26
+#define MIN_M2			6
+#define MAX_M2			16
+#define MIN_P			4
+#define MAX_P			128
+#define MIN_P1			0
+#define MAX_P1			31
+#define MIN_N			3
+#define MAX_N			16
+
+#define CALC_VCLOCK(m1, m2, n, p1, p2) \
+        ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \
+        (((p1) + 2) * (1 << (p2 + 1))))
+
+#define CALC_VCLOCK3(m, n, p)	((PLL_REFCLK * (m) / (n)) / (p))
+
+/* Two pipes */
+#define PIPE_A			0
+#define PIPE_B			1
+#define PIPE_MASK		1
+
+/* palette registers */
+#define PALETTE_A		0x0a000
+#define PALETTE_B		0x0a800
+#ifndef PALETTE_8_ENTRIES
+#define PALETTE_8_ENTRIES		256
+#endif
+#define PALETTE_8_SIZE			(PALETTE_8_ENTRIES * 4)
+#define PALETTE_10_ENTRIES		128
+#define PALETTE_10_SIZE			(PALETTE_10_ENTRIES * 8)
+#define PALETTE_8_MASK			0xff
+#define PALETTE_8_RED_SHIFT		16
+#define PALETTE_8_GREEN_SHIFT		8
+#define PALETTE_8_BLUE_SHIFT		0
+
+/* CRTC registers */
+#define HTOTAL_A		0x60000
+#define HBLANK_A		0x60004
+#define HSYNC_A			0x60008
+#define VTOTAL_A		0x6000c
+#define VBLANK_A		0x60010
+#define VSYNC_A			0x60014
+#define SRC_SIZE_A		0x6001c
+#define BCLRPAT_A		0x60020
+
+#define HTOTAL_B		0x61000
+#define HBLANK_B		0x61004
+#define HSYNC_B			0x61008
+#define VTOTAL_B		0x6100c
+#define VBLANK_B		0x61010
+#define VSYNC_B			0x61014
+#define SRC_SIZE_B		0x6101c
+#define BCLRPAT_B		0x61020
+
+#define HTOTAL_MASK			0xfff
+#define HTOTAL_SHIFT			16
+#define HACTIVE_MASK			0x7ff
+#define HACTIVE_SHIFT			0
+#define HBLANKEND_MASK			0xfff
+#define HBLANKEND_SHIFT			16
+#define HBLANKSTART_MASK		0xfff
+#define HBLANKSTART_SHIFT		0
+#define HSYNCEND_MASK			0xfff
+#define HSYNCEND_SHIFT			16
+#define HSYNCSTART_MASK			0xfff
+#define HSYNCSTART_SHIFT		0
+#define VTOTAL_MASK			0xfff
+#define VTOTAL_SHIFT			16
+#define VACTIVE_MASK			0x7ff
+#define VACTIVE_SHIFT			0
+#define VBLANKEND_MASK			0xfff
+#define VBLANKEND_SHIFT			16
+#define VBLANKSTART_MASK		0xfff
+#define VBLANKSTART_SHIFT		0
+#define VSYNCEND_MASK			0xfff
+#define VSYNCEND_SHIFT			16
+#define VSYNCSTART_MASK			0xfff
+#define VSYNCSTART_SHIFT		0
+#define SRC_SIZE_HORIZ_MASK		0x7ff
+#define SRC_SIZE_HORIZ_SHIFT		16
+#define SRC_SIZE_VERT_MASK		0x7ff
+#define SRC_SIZE_VERT_SHIFT		0
+
+#define ADPA			0x61100
+#define ADPA_DAC_ENABLE			(1 << 31)
+#define ADPA_DAC_DISABLE		0
+#define ADPA_PIPE_SELECT_SHIFT		30
+#define ADPA_USE_VGA_HVPOLARITY		(1 << 15)
+#define ADPA_SETS_HVPOLARITY		0
+#define ADPA_DPMS_CONTROL_MASK		(0x3 << 10)
+#define ADPA_DPMS_D0			(0x0 << 10)
+#define ADPA_DPMS_D2			(0x1 << 10)
+#define ADPA_DPMS_D1			(0x2 << 10)
+#define ADPA_DPMS_D3			(0x3 << 10)
+#define ADPA_VSYNC_ACTIVE_SHIFT		4
+#define ADPA_HSYNC_ACTIVE_SHIFT		3
+#define ADPA_SYNC_ACTIVE_MASK		1
+#define ADPA_SYNC_ACTIVE_HIGH		1
+#define ADPA_SYNC_ACTIVE_LOW		0
+
+#define DVOA			0x61120
+#define DVOB			0x61140
+#define DVOC			0x61160
+#define LVDS			0x61180
+#define PORT_ENABLE		        (1 << 31)
+#define PORT_PIPE_SELECT_SHIFT	        30
+#define PORT_TV_FLAGS_MASK              0xFF
+#define PORT_TV_FLAGS                   0xC4  // ripped from my BIOS
+                                              // to understand and correct
+
+#define DVOA_SRCDIM		0x61124
+#define DVOB_SRCDIM		0x61144
+#define DVOC_SRCDIM		0x61164
+
+#define PIPEACONF		0x70008
+#define PIPEBCONF		0x71008
+#define PIPECONF_ENABLE			(1 << 31)
+#define PIPECONF_DISABLE		0
+#define PIPECONF_DOUBLE_WIDE		(1 << 30)
+#define PIPECONF_SINGLE_WIDE		0
+#define PIPECONF_LOCKED			(1 << 25)
+#define PIPECONF_UNLOCKED		0
+#define PIPECONF_GAMMA			(1 << 24)
+#define PIPECONF_PALETTE		0
+
+#define DISPARB			0x70030
+#define DISPARB_AEND_MASK		0x1ff
+#define DISPARB_AEND_SHIFT		0
+#define DISPARB_BEND_MASK		0x3ff
+#define DISPARB_BEND_SHIFT		9
+
+/* Desktop HW cursor */
+#define CURSOR_CONTROL		0x70080
+#define CURSOR_ENABLE			(1 << 31)
+#define CURSOR_GAMMA_ENABLE		(1 << 30)
+#define CURSOR_STRIDE_MASK		(0x3 << 28)
+#define CURSOR_STRIDE_256		(0x0 << 28)
+#define CURSOR_STRIDE_512		(0x1 << 28)
+#define CURSOR_STRIDE_1K		(0x2 << 28)
+#define CURSOR_STRIDE_2K		(0x3 << 28)
+#define CURSOR_FORMAT_MASK		(0x7 << 24)
+#define CURSOR_FORMAT_2C		(0x0 << 24)
+#define CURSOR_FORMAT_3C		(0x1 << 24)
+#define CURSOR_FORMAT_4C		(0x2 << 24)
+#define CURSOR_FORMAT_ARGB		(0x4 << 24)
+#define CURSOR_FORMAT_XRGB		(0x5 << 24)
+
+/* Mobile HW cursor (and i810) */
+#define CURSOR_A_CONTROL	CURSOR_CONTROL
+#define CURSOR_B_CONTROL	0x700c0
+#define CURSOR_MODE_MASK		0x27
+#define CURSOR_MODE_DISABLE		0
+#define CURSOR_MODE_64_3C		0x04
+#define CURSOR_MODE_64_4C_AX		0x05
+#define CURSOR_MODE_64_4C		0x06
+#define CURSOR_MODE_64_32B_AX		0x07
+#define CURSOR_MODE_64_ARGB_AX		0x27
+#define CURSOR_PIPE_SELECT_SHIFT	28
+#define CURSOR_MOBILE_GAMMA_ENABLE	(1 << 26)
+#define CURSOR_MEM_TYPE_LOCAL		(1 << 25)
+
+/* All platforms (desktop has no pipe B) */
+#define CURSOR_A_BASEADDR	0x70084
+#define CURSOR_B_BASEADDR	0x700c4
+#define CURSOR_BASE_MASK		0xffffff00
+
+#define CURSOR_A_POSITION	0x70088
+#define CURSOR_B_POSITION	0x700c8
+#define CURSOR_POS_SIGN			(1 << 15)
+#define CURSOR_POS_MASK			0x7ff
+#define CURSOR_X_SHIFT			0
+#define CURSOR_Y_SHIFT			16
+
+#define CURSOR_A_PALETTE0	0x70090
+#define CURSOR_A_PALETTE1	0x70094
+#define CURSOR_A_PALETTE2	0x70098
+#define CURSOR_A_PALETTE3	0x7009c
+#define CURSOR_B_PALETTE0	0x700d0
+#define CURSOR_B_PALETTE1	0x700d4
+#define CURSOR_B_PALETTE2	0x700d8
+#define CURSOR_B_PALETTE3	0x700dc
+#define CURSOR_COLOR_MASK			0xff
+#define CURSOR_RED_SHIFT			16
+#define CURSOR_GREEN_SHIFT			8
+#define CURSOR_BLUE_SHIFT			0
+#define CURSOR_PALETTE_MASK			0xffffff
+
+/* Desktop only */
+#define CURSOR_SIZE		0x700a0
+#define CURSOR_SIZE_MASK		0x3ff
+#define CURSOR_SIZE_H_SHIFT		0
+#define CURSOR_SIZE_V_SHIFT		12
+
+#define DSPACNTR		0x70180
+#define DSPBCNTR		0x71180
+#define DISPPLANE_PLANE_ENABLE		(1 << 31)
+#define DISPPLANE_PLANE_DISABLE		0
+#define DISPPLANE_GAMMA_ENABLE		(1<<30)
+#define DISPPLANE_GAMMA_DISABLE		0
+#define DISPPLANE_PIXFORMAT_MASK	(0xf<<26)
+#define DISPPLANE_8BPP			(0x2<<26)
+#define DISPPLANE_15_16BPP		(0x4<<26)
+#define DISPPLANE_16BPP			(0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA 	(0x6<<26)
+#define DISPPLANE_32BPP			(0x7<<26)
+#define DISPPLANE_STEREO_ENABLE		(1<<25)
+#define DISPPLANE_STEREO_DISABLE	0
+#define DISPPLANE_SEL_PIPE_SHIFT	24
+#define DISPPLANE_SRC_KEY_ENABLE	(1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE	0
+#define DISPPLANE_LINE_DOUBLE		(1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE	0
+#define DISPPLANE_STEREO_POLARITY_FIRST	0
+#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE	(1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE	0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA	0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY	1
+
+#define DSPABASE		0x70184
+#define DSPASTRIDE		0x70188
+
+#define DSPBBASE		0x71184
+#define DSPBSTRIDE		0x71188
+
+#define VGACNTRL		0x71400
+#define VGA_DISABLE			(1 << 31)
+#define VGA_ENABLE			0
+#define VGA_PIPE_SELECT_SHIFT		29
+#define VGA_PALETTE_READ_SELECT		23
+#define VGA_PALETTE_A_WRITE_DISABLE	(1 << 22)
+#define VGA_PALETTE_B_WRITE_DISABLE	(1 << 21)
+#define VGA_LEGACY_PALETTE		(1 << 20)
+#define VGA_6BIT_DAC			0
+#define VGA_8BIT_DAC			(1 << 20)
+
+#define ADD_ID			0x71408
+#define ADD_ID_MASK			0xff
+
+/* BIOS scratch area registers (830M and 845G). */
+#define SWF0			0x71410
+#define SWF1			0x71414
+#define SWF2			0x71418
+#define SWF3			0x7141c
+#define SWF4			0x71420
+#define SWF5			0x71424
+#define SWF6			0x71428
+
+/* BIOS scratch area registers (852GM, 855GM, 865G). */
+#define SWF00			0x70410
+#define SWF01			0x70414
+#define SWF02			0x70418
+#define SWF03			0x7041c
+#define SWF04			0x70420
+#define SWF05			0x70424
+#define SWF06			0x70428
+
+#define SWF10			SWF0
+#define SWF11			SWF1
+#define SWF12			SWF2
+#define SWF13			SWF3
+#define SWF14			SWF4
+#define SWF15			SWF5
+#define SWF16			SWF6
+
+#define SWF30			0x72414
+#define SWF31			0x72418
+#define SWF32			0x7241c
+
+/* Memory Commands */
+#define MI_NOOP			(0x00 << 23)
+#define MI_NOOP_WRITE_ID		(1 << 22)
+#define MI_NOOP_ID_MASK			((1 << 22) - 1)
+
+#define MI_FLUSH		(0x04 << 23)
+#define MI_WRITE_DIRTY_STATE		(1 << 4)
+#define MI_END_SCENE			(1 << 3)
+#define MI_INHIBIT_RENDER_CACHE_FLUSH	(1 << 2)
+#define MI_INVALIDATE_MAP_CACHE		(1 << 0)
+
+#define MI_STORE_DWORD_IMM	((0x20 << 23) | 1)
+
+/* 2D Commands */
+#define COLOR_BLT_CMD		((2 << 29) | (0x40 << 22) | 3)
+#define XY_COLOR_BLT_CMD	((2 << 29) | (0x50 << 22) | 4)
+#define XY_SETUP_CLIP_BLT_CMD	((2 << 29) | (0x03 << 22) | 1)
+#define XY_SRC_COPY_BLT_CMD	((2 << 29) | (0x53 << 22) | 6)
+#define SRC_COPY_BLT_CMD	((2 << 29) | (0x43 << 22) | 4)
+#define XY_MONO_PAT_BLT_CMD	((2 << 29) | (0x52 << 22) | 7)
+#define XY_MONO_SRC_BLT_CMD	((2 << 29) | (0x54 << 22) | 6)
+#define XY_MONO_SRC_IMM_BLT_CMD	((2 << 29) | (0x71 << 22) | 5)
+#define TXT_IMM_BLT_CMD	        ((2 << 29) | (0x30 << 22) | 2)
+#define SETUP_BLT_CMD	        ((2 << 29) | (0x00 << 22) | 6)
+
+#define DW_LENGTH_MASK			0xff
+
+#define WRITE_ALPHA			(1 << 21)
+#define WRITE_RGB			(1 << 20)
+#define VERT_SEED			(3 << 8)
+#define HORIZ_SEED			(3 << 12)
+
+#define COLOR_DEPTH_8			(0 << 24)
+#define COLOR_DEPTH_16			(1 << 24)
+#define COLOR_DEPTH_32			(3 << 24)
+
+#define SRC_ROP_GXCOPY			0xcc
+#define SRC_ROP_GXXOR			0x66
+
+#define PAT_ROP_GXCOPY                  0xf0
+#define PAT_ROP_GXXOR                   0x5a
+
+#define PITCH_SHIFT			0
+#define ROP_SHIFT			16
+#define WIDTH_SHIFT			0
+#define HEIGHT_SHIFT			16
+
+/* in bytes */
+#define MAX_MONO_IMM_SIZE		128
+
+
+/*** Macros ***/
+
+/* I/O macros */
+#define INREG8(addr)	      readb((u8 __iomem *)(dinfo->mmio_base + (addr)))
+#define INREG(addr)	      readl((u32 __iomem *)(dinfo->mmio_base + (addr)))
+#define OUTREG8(addr, val)    writeb((val),(u8 __iomem *)(dinfo->mmio_base + \
+							   (addr)))
+#define OUTREG(addr, val)     writel((val),(u32 __iomem *)(dinfo->mmio_base + \
+                                     (addr)))
+
+/* Ring buffer macros */
+#define OUT_RING(n)	do {						\
+	writel((n), (u32 __iomem *)(dinfo->ring.virtual + dinfo->ring_tail));\
+	dinfo->ring_tail += 4;						\
+	dinfo->ring_tail &= dinfo->ring_tail_mask;			\
+} while (0)
+
+#define START_RING(n)	do {						\
+	if (dinfo->ring_space < (n) * 4)				\
+		wait_ring(dinfo,(n) * 4);				\
+	dinfo->ring_space -= (n) * 4;					\
+} while (0)
+
+#define ADVANCE_RING()	do {						\
+	OUTREG(PRI_RING_TAIL, dinfo->ring_tail);                        \
+} while (0)
+
+#define DO_RING_IDLE()	do {						\
+	u32 head, tail;							\
+	do {								\
+		head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;		\
+		tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;		\
+		udelay(10);						\
+	} while (head != tail);						\
+} while (0)
+
+
+/* function protoypes */
+extern int intelfbhw_get_chipset(struct pci_dev *pdev, const char **name,
+				 int *chipset, int *mobile);
+extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
+				int *stolen_size);
+extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
+extern const char *intelfbhw_dvo_to_string(int dvo);
+extern int intelfbhw_validate_mode(struct intelfb_info *dinfo,
+				   struct fb_var_screeninfo *var);
+extern int intelfbhw_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info);
+extern void intelfbhw_do_blank(int blank, struct fb_info *info);
+extern void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
+				unsigned red, unsigned green, unsigned blue,
+				unsigned transp);
+extern int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
+				   struct intelfb_hwstate *hw, int flag);
+extern void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
+				     struct intelfb_hwstate *hw);
+extern int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
+				struct intelfb_hwstate *hw,
+				struct fb_var_screeninfo *var);
+extern int intelfbhw_program_mode(struct intelfb_info *dinfo,
+				  const struct intelfb_hwstate *hw, int blank);
+extern void intelfbhw_do_sync(struct intelfb_info *dinfo);
+extern void intelfbhw_2d_stop(struct intelfb_info *dinfo);
+extern void intelfbhw_2d_start(struct intelfb_info *dinfo);
+extern void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y,
+				  u32 w, u32 h, u32 color, u32 pitch, u32 bpp,
+				  u32 rop);
+extern void intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
+				u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch,
+				u32 bpp);
+extern int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg,
+				  u32 w, u32 h, const u8* cdat, u32 x, u32 y,
+				  u32 pitch, u32 bpp);
+extern void intelfbhw_cursor_init(struct intelfb_info *dinfo);
+extern void intelfbhw_cursor_hide(struct intelfb_info *dinfo);
+extern void intelfbhw_cursor_show(struct intelfb_info *dinfo);
+extern void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y);
+extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,
+				      u32 fg);
+extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width,
+				  int height, u8 *data);
+extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
+
+#endif /* _INTELFBHW_H */
diff -Nru a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
--- a/drivers/video/pm2fb.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/video/pm2fb.c	2004-10-28 22:25:59 -07:00
@@ -877,7 +877,6 @@
 		green = CNVT_TOHW(green, info->var.green.length);
 		blue = CNVT_TOHW(blue, info->var.blue.length);
 		transp = CNVT_TOHW(transp, info->var.transp.length);
-		set_color(par, regno, red, green, blue);
 		break;
 	case FB_VISUAL_DIRECTCOLOR:
 		/* example here assumes 8 bit DAC. Might be different 
@@ -904,12 +903,8 @@
 
 		switch (info->var.bits_per_pixel) {
 		case 8:
-			/* Yes some hand held devices have this. */ 
-           		((u8*)(info->pseudo_palette))[regno] = v;
 			break;	
    		case 16:
-           		((u16*)(info->pseudo_palette))[regno] = v;
-			break;
 		case 24:
 		case 32:	
            		((u32*)(info->pseudo_palette))[regno] = v;
@@ -917,7 +912,9 @@
 		}
 		return 0;
 	}
-	/* ... */
+	else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+		set_color(par, regno, red, green, blue);
+
 	return 0;
 }
 
@@ -973,24 +970,26 @@
 
 	DPRINTK("blank_mode %d\n", blank_mode);
 
-	/* Turn everything on, then disable as requested. */
-	video |= (PM2F_VIDEO_ENABLE | PM2F_HSYNC_MASK | PM2F_VSYNC_MASK);
-
 	switch (blank_mode) {
-	case 0: 	/* Screen: On; HSync: On, VSync: On */
+	case 0:
+		/* Screen: On */
+		video |= PM2F_VIDEO_ENABLE;
 		break;
-	case 1: 	/* Screen: Off; HSync: On, VSync: On */
+	case VESA_NO_BLANKING + 1:
+		/* Screen: Off */
 		video &= ~PM2F_VIDEO_ENABLE;
 		break;
-	case 2: /* Screen: Off; HSync: On, VSync: Off */
-		video &= ~(PM2F_VIDEO_ENABLE | PM2F_VSYNC_MASK | PM2F_BLANK_LOW );
-		break;
-	case 3: /* Screen: Off; HSync: Off, VSync: On */
-		video &= ~(PM2F_VIDEO_ENABLE | PM2F_HSYNC_MASK | PM2F_BLANK_LOW );
-		break;
-	case 4: /* Screen: Off; HSync: Off, VSync: Off */
-		video &= ~(PM2F_VIDEO_ENABLE | PM2F_VSYNC_MASK | PM2F_HSYNC_MASK|
-			   PM2F_BLANK_LOW);
+	case VESA_VSYNC_SUSPEND + 1:
+		/* VSync: Off */
+		video &= ~(PM2F_VSYNC_MASK | PM2F_BLANK_LOW );
+		break;
+	case VESA_HSYNC_SUSPEND + 1:
+		/* HSync: Off */
+		video &= ~(PM2F_HSYNC_MASK | PM2F_BLANK_LOW );
+		break;
+	case VESA_POWERDOWN + 1:
+		/* HSync: Off, VSync: Off */
+		video &= ~(PM2F_VSYNC_MASK | PM2F_HSYNC_MASK| PM2F_BLANK_LOW);
 		break;
 	}
 	set_video(par, video);
diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
--- a/drivers/video/riva/fbdev.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/video/riva/fbdev.c	2004-10-28 22:25:58 -07:00
@@ -205,6 +205,7 @@
 /* command line data, set in rivafb_setup() */
 static int flatpanel __initdata = -1; /* Autodetect later */
 static int forceCRTC __initdata = -1;
+static int noaccel   __initdata = 0;
 #ifdef CONFIG_MTRR
 static int nomtrr __initdata = 0;
 #endif
@@ -231,7 +232,6 @@
 	.activate	= FB_ACTIVATE_NOW,
 	.height		= -1,
 	.width		= -1,
-	.accel_flags	= FB_ACCELF_TEXT,
 	.pixclock	= 39721,
 	.left_margin	= 40,
 	.right_margin	= 24,
@@ -1008,8 +1008,6 @@
 			par->state.flags |= VGA_SAVE_CMAP;
 		save_vga(&par->state);
 #endif
-		riva_common_setup(par);
-		RivaGetConfig(&par->riva, par->Chipset);
 		/* vgaHWunlock() + riva unlock (0x7F) */
 		CRTCout(par, 0x11, 0xFF);
 		par->riva.LockUnlock(&par->riva, 0);
@@ -1157,20 +1155,22 @@
 	struct riva_par *par = (struct riva_par *) info->par;
 
 	NVTRACE_ENTER();
-	riva_common_setup(par);
-	RivaGetConfig(&par->riva, par->Chipset);
 	/* vgaHWunlock() + riva unlock (0x7F) */
 	CRTCout(par, 0x11, 0xFF);
 	par->riva.LockUnlock(&par->riva, 0);
-
 	riva_load_video_mode(info);
-	riva_setup_accel(info);
+	if(!(info->flags & FBINFO_HWACCEL_DISABLED))
+		riva_setup_accel(info);
 	
-	memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+	par->cursor_reset = 1;
 	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
 
+	if (info->flags & FBINFO_HWACCEL_DISABLED)
+		info->pixmap.scan_align = 1;
+	else
+		info->pixmap.scan_align = 4;
 	NVTRACE_LEAVE();
 	return 0;
 }
@@ -1378,6 +1378,11 @@
 	struct riva_par *par = (struct riva_par *) info->par;
 	u_int color, rop = 0;
 
+	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
+		cfb_fillrect(info, rect);
+		return;
+	}
+
 	if (info->var.bits_per_pixel == 8)
 		color = rect->color;
 	else {
@@ -1428,6 +1433,11 @@
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 
+	if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
+		cfb_copyarea(info, region);
+		return;
+	}
+
 	RIVA_FIFO_FREE(par->riva, Blt, 3);
 	par->riva.Blt->TopLeftSrc  = (region->sy << 16) | region->sx;
 	par->riva.Blt->TopLeftDst  = (region->dy << 16) | region->dx;
@@ -1470,7 +1480,7 @@
 	volatile u32 *d;
 	int i, size;
 
-	if (image->depth != 1) {
+	if ((info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) {
 		cfb_imageblit(info, image);
 		return;
 	}
@@ -1552,15 +1562,21 @@
 	struct riva_par *par = (struct riva_par *) info->par;
 	u8 data[MAX_CURS * MAX_CURS/8];
 	u16 fg, bg;
-	int i;
+	int i, set = cursor->set;
 
 	par->riva.ShowHideCursor(&par->riva, 0);
 
-	if (cursor->set & FB_CUR_SETPOS) {
+	if (par->cursor_reset) {
+		set = FB_CUR_SETALL;
+		par->cursor_reset = 0;
+	}
+
+	if (set & FB_CUR_SETSIZE)
+		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+
+	if (set & FB_CUR_SETPOS) {
 		u32 xx, yy, temp;
 
-		info->cursor.image.dx = cursor->image.dx;
-		info->cursor.image.dy = cursor->image.dy;
 		yy = cursor->image.dy - info->var.yoffset;
 		xx = cursor->image.dx - info->var.xoffset;
 		temp = xx & 0xFFFF;
@@ -1569,43 +1585,32 @@
 		par->riva.PRAMDAC[0x0000300/4] = temp;
 	}
 
-	if (cursor->set & FB_CUR_SETSIZE) {
-		info->cursor.image.height = cursor->image.height;
-		info->cursor.image.width = cursor->image.width;
-		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
-	}
-
-	if (cursor->set & FB_CUR_SETCMAP) {
-		info->cursor.image.bg_color = cursor->image.bg_color;
-		info->cursor.image.fg_color = cursor->image.fg_color;
-	}
 
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETCUR)) {
-		u32 bg_idx = info->cursor.image.bg_color;
-		u32 fg_idx = info->cursor.image.fg_color;
-		u32 s_pitch = (info->cursor.image.width+7) >> 3;
+	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		u32 bg_idx = cursor->image.bg_color;
+		u32 fg_idx = cursor->image.fg_color;
+		u32 s_pitch = (cursor->image.width+7) >> 3;
 		u32 d_pitch = MAX_CURS/8;
 		u8 *dat = (u8 *) cursor->image.data;
-		u8 *msk = (u8 *) info->cursor.mask;
+		u8 *msk = (u8 *) cursor->mask;
 		u8 src[64];	
 		
-		info->cursor.image.data = cursor->image.data;
-		switch (info->cursor.rop) {
+		switch (cursor->rop) {
 		case ROP_XOR:
-			for (i = 0; i < s_pitch * info->cursor.image.height;
+			for (i = 0; i < s_pitch * cursor->image.height;
 			     i++)
 				src[i] = dat[i] ^ msk[i];
 			break;
 		case ROP_COPY:
 		default:
-			for (i = 0; i < s_pitch * info->cursor.image.height;
+			for (i = 0; i < s_pitch * cursor->image.height;
 			     i++)
 				src[i] = dat[i] & msk[i];
 			break;
 		}
 		
-		fb_sysmove_buf_aligned(info, &info->sprite, data, d_pitch, src,
-				       s_pitch, info->cursor.image.height);
+		fb_sysmove_buf_aligned(info, &info->pixmap, data, d_pitch, src,
+				       s_pitch, cursor->image.height);
 
 		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
 		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
@@ -1618,11 +1623,13 @@
 		par->riva.LockUnlock(&par->riva, 0);
 
 		rivafb_load_cursor_image(par, data, bg, fg,
-					 info->cursor.image.width, 
-					 info->cursor.image.height);
+					 cursor->image.width,
+					 cursor->image.height);
 	}
-	if (info->cursor.enable)
+
+	if (cursor->enable)
 		par->riva.ShowHideCursor(&par->riva, 1);
+
 	return 0;
 }
 
@@ -1670,6 +1677,13 @@
 		    | FBINFO_HWACCEL_FILLRECT
 		    | FBINFO_HWACCEL_IMAGEBLIT
 	            | FBINFO_MISC_MODESWITCHLATE;
+
+	/* Accel seems to not work properly on NV30 yet...*/
+	if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
+	    	printk(KERN_DEBUG PFX "disabling acceleration\n");
+  		info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+
 	info->var = rivafb_default_var;
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
@@ -1679,9 +1693,8 @@
 	cmap_len = riva_get_cmap_len(&info->var);
 	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
 
-	info->pixmap.size = 64 * 1024;
+	info->pixmap.size = 8 * 1024;
 	info->pixmap.buf_align = 4;
-	info->pixmap.scan_align = 4;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 	info->var.yres_virtual = -1;
 	NVTRACE_LEAVE();
@@ -1711,13 +1724,14 @@
 			pedid = (unsigned char *)
 				get_property(dp, propnames[i], NULL);
 			if (pedid != NULL) {
-		par->EDID = pedid;
-		return 1;
+				par->EDID = pedid;
+				NVTRACE("LCD found.\n");
+				return 1;
 			}
 		}
 	}
 	NVTRACE_LEAVE();
-		return 0;
+	return 0;
 }
 #endif /* CONFIG_PPC_OF */
 
@@ -1732,7 +1746,7 @@
 	for (i = par->bus; i >= 1; i--) {
 		riva_probe_i2c_connector(par, i, &par->EDID);
 		if (par->EDID) {
-			printk("rivafb: Found EDID Block from BUS %i\n", i);
+			printk(PFX "Found EDID Block from BUS %i\n", i);
 			break;
 		}
 	}
@@ -1771,7 +1785,6 @@
 		var->bits_per_pixel = 8;
 		riva_update_var(var, &modedb);
 	}
-	var->accel_flags |= FB_ACCELF_TEXT;
 	NVTRACE_LEAVE();
 }
 
@@ -1781,10 +1794,10 @@
 	NVTRACE_ENTER();
 #ifdef CONFIG_PPC_OF
 	if (!riva_get_EDID_OF(info, pdev))
-		printk("rivafb: could not retrieve EDID from OF\n");
+		printk(PFX "could not retrieve EDID from OF\n");
 #elif CONFIG_FB_RIVA_I2C
 	if (!riva_get_EDID_i2c(info))
-		printk("rivafb: could not retrieve EDID from DDC/I2C\n");
+		printk(PFX "could not retrieve EDID from DDC/I2C\n");
 #endif
 	NVTRACE_LEAVE();
 }
@@ -1866,10 +1879,10 @@
 	default_par = (struct riva_par *) info->par;
 	default_par->pdev = pd;
 
-	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
+	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
 	if (info->pixmap.addr == NULL)
 		goto err_out_kfree;
-	memset(info->pixmap.addr, 0, 64 * 1024);
+	memset(info->pixmap.addr, 0, 8 * 1024);
 
 	if (pci_enable_device(pd)) {
 		printk(KERN_ERR PFX "cannot enable PCI device\n");
@@ -1942,7 +1955,6 @@
 			printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
 			goto err_out_free_nv3_pramin;
 		}
-		rivafb_fix.accel = FB_ACCEL_NV3;
 		break;
 	case NV_ARCH_04:
 	case NV_ARCH_10:
@@ -1950,14 +1962,13 @@
 	case NV_ARCH_30:
 		default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);
 		default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
-		rivafb_fix.accel = FB_ACCEL_NV4;
 		break;
 	}
-
 	riva_common_setup(default_par);
 
 	if (default_par->riva.Architecture == NV_ARCH_03) {
-		default_par->riva.PCRTC = default_par->riva.PCRTC0 = default_par->riva.PGRAPH;
+		default_par->riva.PCRTC = default_par->riva.PCRTC0
+		                        = default_par->riva.PGRAPH;
 	}
 
 	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
@@ -2107,6 +2118,8 @@
 #endif
 		} else if (!strncmp(this_opt, "strictmode", 10)) {
 			strictmode = 1;
+		} else if (!strncmp(this_opt, "noaccel", 7)) {
+			noaccel = 1;
 		} else
 			mode_option = this_opt;
 	}
@@ -2152,19 +2165,20 @@
 }
 
 module_exit(rivafb_exit);
+#endif /* MODULE */
 
-MODULE_PARM(flatpanel, "i");
+module_param(noaccel, bool, 0);
+MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
+module_param(flatpanel, int, -1);
 MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");
-MODULE_PARM(forceCRTC, "i");
+module_param(forceCRTC, int, -1);
 MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");
-
 #ifdef CONFIG_MTRR
-MODULE_PARM(nomtrr, "i");
+module_param(nomtrr, bool, 0);
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
 #endif
-MODULE_PARM(strictmode, "i");
+module_param(strictmode, bool, 0);
 MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
-#endif /* MODULE */
 
 MODULE_AUTHOR("Ani Joshi, maintainer");
 MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");
diff -Nru a/drivers/video/riva/nv_driver.c b/drivers/video/riva/nv_driver.c
--- a/drivers/video/riva/nv_driver.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/video/riva/nv_driver.c	2004-10-28 22:25:59 -07:00
@@ -104,12 +104,33 @@
 riva_is_second(struct riva_par *par)
 {
 	if (par->FlatPanel == 1) {
-		switch(par->Chipset) {
-		case NV_CHIP_GEFORCE4_440_GO:
-		case NV_CHIP_GEFORCE4_440_GO_M64:
-		case NV_CHIP_GEFORCE4_420_GO:
-		case NV_CHIP_GEFORCE4_420_GO_M32:
-		case NV_CHIP_QUADRO4_500_GOGL:
+		switch(par->Chipset & 0xffff) {
+		case 0x0174:
+		case 0x0175:
+		case 0x0176:
+		case 0x0177:
+		case 0x0179:
+		case 0x017C:
+		case 0x017D:
+		case 0x0186:
+		case 0x0187:
+		/* this might not be a good default for the chips below */
+		case 0x0286:
+		case 0x028C:
+		case 0x0316:
+		case 0x0317:
+		case 0x031A:
+		case 0x031B:
+		case 0x031C:
+		case 0x031D:
+		case 0x031E:
+		case 0x031F:
+		case 0x0324:
+		case 0x0325:
+		case 0x0328:
+		case 0x0329:
+		case 0x032C:
+		case 0x032D:
 			par->SecondCRTC = TRUE;
 			break;
 		default:
@@ -308,13 +329,33 @@
 	par->riva.IO = (MISCin(par) & 0x01) ? 0x3D0 : 0x3B0;
 	
 	if (par->FlatPanel == -1) {
-		switch (par->Chipset) {
-		case NV_CHIP_GEFORCE4_440_GO:
-		case NV_CHIP_GEFORCE4_440_GO_M64:
-		case NV_CHIP_GEFORCE4_420_GO:
-		case NV_CHIP_GEFORCE4_420_GO_M32:
-		case NV_CHIP_QUADRO4_500_GOGL:
-		case NV_CHIP_GEFORCE2_GO:
+		switch (par->Chipset & 0xffff) {
+		case 0x0112:   /* known laptop chips */
+		case 0x0174:
+		case 0x0175:
+		case 0x0176:
+		case 0x0177:
+		case 0x0179:
+		case 0x017C:
+		case 0x017D:
+		case 0x0186:
+		case 0x0187:
+		case 0x0286:
+		case 0x028C:
+		case 0x0316:
+		case 0x0317:
+		case 0x031A:
+		case 0x031B:
+		case 0x031C:
+		case 0x031D:
+		case 0x031E:
+		case 0x031F:
+		case 0x0324:
+		case 0x0325:
+		case 0x0328:
+		case 0x0329:
+		case 0x032C:
+		case 0x032D:
 			printk(KERN_INFO PFX 
 				"On a laptop.  Assuming Digital Flat Panel\n");
 			par->FlatPanel = 1;
@@ -339,6 +380,11 @@
 	case 0x01F0:
 	case 0x0250:
 	case 0x0280:
+	case 0x0300:
+	case 0x0310:
+	case 0x0320:
+	case 0x0330:
+	case 0x0340:
 		riva_is_second(par);
 		break;
 	default:
@@ -362,5 +408,7 @@
 		par->FlatPanel = 0;
 	}
 	par->riva.flatPanel = (par->FlatPanel > 0) ? TRUE : FALSE;
+
+	RivaGetConfig(&par->riva, par->Chipset);
 }
 
diff -Nru a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
--- a/drivers/video/riva/riva_hw.c	2004-10-28 22:25:59 -07:00
+++ b/drivers/video/riva/riva_hw.c	2004-10-28 22:25:59 -07:00
@@ -1536,13 +1536,13 @@
             chip->PMC[0x00001588/4] = 0;
 
             chip->PFB[0x00000240/4] = 0;
-            chip->PFB[0x00000244/4] = 0;
-            chip->PFB[0x00000248/4] = 0;
-            chip->PFB[0x0000024C/4] = 0;
             chip->PFB[0x00000250/4] = 0;
-            chip->PFB[0x00000254/4] = 0;
-            chip->PFB[0x00000258/4] = 0;
-            chip->PFB[0x0000025C/4] = 0;
+            chip->PFB[0x00000260/4] = 0;
+            chip->PFB[0x00000270/4] = 0;
+            chip->PFB[0x00000280/4] = 0;
+            chip->PFB[0x00000290/4] = 0;
+            chip->PFB[0x000002A0/4] = 0;
+            chip->PFB[0x000002B0/4] = 0;
 
             chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
             chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
@@ -2067,7 +2067,8 @@
 
 #ifdef __BIG_ENDIAN
     /* turn on big endian register access */
-    chip->PMC[0x00000004/4] = 0x01000001;
+    if(!(chip->PMC[0x00000004/4] & 0x01000001))
+    	chip->PMC[0x00000004/4] = 0x01000001;
 #endif
 
     /*
@@ -2128,6 +2129,11 @@
     case 0x01F0:
     case 0x0250:
     case 0x0280:
+    case 0x0300:
+    case 0x0310:
+    case 0x0320:
+    case 0x0330:
+    case 0x0340:
        if(chip->PEXTDEV[0x0000/4] & (1 << 22))
            chip->CrystalFreqKHz = 27000;
        break;
@@ -2159,6 +2165,11 @@
     case 0x01F0:
     case 0x0250:
     case 0x0280:
+    case 0x0300:
+    case 0x0310:
+    case 0x0320:
+    case 0x0330:
+    case 0x0340:
         chip->twoHeads = TRUE;
         break;
     default:
diff -Nru a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
--- a/drivers/video/riva/riva_hw.h	2004-10-28 22:25:59 -07:00
+++ b/drivers/video/riva/riva_hw.h	2004-10-28 22:25:59 -07:00
@@ -541,8 +541,10 @@
 
 #define RIVA_FIFO_FREE(hwinst,hwptr,cnt)                            \
 {                                                                   \
-    while ((hwinst).FifoFreeCount < (cnt))                          \
+    while ((hwinst).FifoFreeCount < (cnt)) {                        \
+	mb();mb();						    \
         (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2;     \
+    }								    \
     (hwinst).FifoFreeCount -= (cnt);                                \
 }
 #endif /* __RIVA_HW_H__ */
diff -Nru a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
--- a/drivers/video/riva/rivafb.h	2004-10-28 22:25:57 -07:00
+++ b/drivers/video/riva/rivafb.h	2004-10-28 22:25:57 -07:00
@@ -62,6 +62,7 @@
 	int FlatPanel;
 	struct pci_dev *pdev;
 	int bus;
+	int cursor_reset;
 #ifdef CONFIG_MTRR
 	struct { int vram; int vram_valid; } mtrr;
 #endif
diff -Nru a/drivers/video/savage/Makefile b/drivers/video/savage/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/savage/Makefile	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,8 @@
+#
+# Makefile for the S3 Savage framebuffer driver
+#
+
+obj-$(CONFIG_FB_SAVAGE)		+= savagefb.o
+obj-$(CONFIG_FB_SAVAGE_I2C)     += savagefb-i2c.o
+obj-$(CONFIG_FB_SAVAGE_ACCEL)   += savagefb_accel.o
+
diff -Nru a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/savage/savagefb-i2c.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,262 @@
+/*
+ * linux/drivers/video/savage/savagefb-i2c.c - S3 Savage DDC2
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based partly on rivafb-i2c.c
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+#include "savagefb.h"
+
+#define SAVAGE_DDC 	0x50
+
+#define VGA_CR_IX	0x3d4
+#define VGA_CR_DATA	0x3d5
+
+#define CR_SERIAL1	0xa0	/* I2C serial communications interface */
+#define MM_SERIAL1	0xff20
+#define CR_SERIAL2	0xb1	/* DDC2 monitor communications interface */
+
+/* based on vt8365 documentation */
+#define PROSAVAGE_I2C_ENAB	0x10
+#define PROSAVAGE_I2C_SCL_OUT	0x01
+#define PROSAVAGE_I2C_SDA_OUT	0x02
+#define PROSAVAGE_I2C_SCL_IN	0x04
+#define PROSAVAGE_I2C_SDA_IN	0x08
+
+#define SAVAGE4_I2C_ENAB	0x00000020
+#define SAVAGE4_I2C_SCL_OUT	0x00000001
+#define SAVAGE4_I2C_SDA_OUT	0x00000002
+#define SAVAGE4_I2C_SCL_IN	0x00000008
+#define SAVAGE4_I2C_SDA_IN	0x00000010
+
+#define SET_CR_IX(base, val)	writeb((val), base + 0x8000 + VGA_CR_IX)
+#define SET_CR_DATA(base, val)	writeb((val), base + 0x8000 + VGA_CR_DATA)
+#define GET_CR_DATA(base)	readb(base + 0x8000 + VGA_CR_DATA)
+
+static void savage4_gpio_setscl(void *data, int val)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	unsigned int r;
+
+	r = readl(chan->ioaddr + chan->reg);
+	if(val)
+		r |= SAVAGE4_I2C_SCL_OUT;
+	else
+		r &= ~SAVAGE4_I2C_SCL_OUT;
+	writel(r, chan->ioaddr + chan->reg);
+	readl(chan->ioaddr + chan->reg);	/* flush posted write */
+}
+
+static void savage4_gpio_setsda(void *data, int val)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+
+	unsigned int r;
+	r = readl(chan->ioaddr + chan->reg);
+	if(val)
+		r |= SAVAGE4_I2C_SDA_OUT;
+	else
+		r &= ~SAVAGE4_I2C_SDA_OUT;
+	writel(r, chan->ioaddr + chan->reg);
+	readl(chan->ioaddr + chan->reg);	/* flush posted write */
+}
+
+static int savage4_gpio_getscl(void *data)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+
+	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));
+}
+
+static int savage4_gpio_getsda(void *data)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+
+	return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));
+}
+
+static void prosavage_gpio_setscl(void* data, int val)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	u32			  r;
+
+	SET_CR_IX(chan->ioaddr, chan->reg);
+	r = GET_CR_DATA(chan->ioaddr);
+	r |= PROSAVAGE_I2C_ENAB;
+	if (val) {
+		r |= PROSAVAGE_I2C_SCL_OUT;
+	} else {
+		r &= ~PROSAVAGE_I2C_SCL_OUT;
+	}
+	SET_CR_DATA(chan->ioaddr, r);
+}
+
+static void prosavage_gpio_setsda(void* data, int val)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+	unsigned int r;
+
+	SET_CR_IX(chan->ioaddr, chan->reg);
+	r = GET_CR_DATA(chan->ioaddr);
+	r |= PROSAVAGE_I2C_ENAB;
+	if (val) {
+		r |= PROSAVAGE_I2C_SDA_OUT;
+	} else {
+		r &= ~PROSAVAGE_I2C_SDA_OUT;
+	}
+	SET_CR_DATA(chan->ioaddr, r);
+}
+
+static int prosavage_gpio_getscl(void* data)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+
+	SET_CR_IX(chan->ioaddr, chan->reg);
+	return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN));
+}
+
+static int prosavage_gpio_getsda(void* data)
+{
+	struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+
+	SET_CR_IX(chan->ioaddr, chan->reg);
+	return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
+}
+
+#define I2C_ALGO_SAVAGE   0x0f0000
+static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
+				const char *name)
+{
+	int rc;
+
+	strcpy(chan->adapter.name, name);
+	chan->adapter.owner		= THIS_MODULE;
+	chan->adapter.id		= I2C_ALGO_SAVAGE;
+	chan->adapter.algo_data		= &chan->algo;
+	chan->adapter.dev.parent	= &chan->par->pcidev->dev;
+	chan->algo.udelay		= 40;
+	chan->algo.mdelay               = 5;
+	chan->algo.timeout		= 20;
+	chan->algo.data 		= chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	/* Raise SCL and SDA */
+	chan->algo.setsda(chan, 1);
+	chan->algo.setscl(chan, 1);
+	udelay(20);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		dev_dbg(&chan->par->pcidev->dev,
+			"I2C bus %s registered.\n", name);
+	else
+		dev_warn(&chan->par->pcidev->dev,
+			 "Failed to register I2C bus %s.\n", name);
+	return rc;
+}
+
+void savagefb_create_i2c_busses(struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	par->chan.par	= par;
+
+	switch(info->fix.accel) {
+	case FB_ACCEL_PROSAVAGE_DDRK:
+	case FB_ACCEL_PROSAVAGE_PM:
+		par->chan.reg         = CR_SERIAL2;
+		par->chan.ioaddr      = par->mmio.vbase;
+		par->chan.algo.setsda = prosavage_gpio_setsda;
+		par->chan.algo.setscl = prosavage_gpio_setscl;
+		par->chan.algo.getsda = prosavage_gpio_getsda;
+		par->chan.algo.getscl = prosavage_gpio_getscl;
+		break;
+	case FB_ACCEL_SAVAGE4:
+		par->chan.reg         = 0xff20;
+		par->chan.ioaddr      = par->mmio.vbase;
+		par->chan.algo.setsda = savage4_gpio_setsda;
+		par->chan.algo.setscl = savage4_gpio_setscl;
+		par->chan.algo.getsda = savage4_gpio_getsda;
+		par->chan.algo.getscl = savage4_gpio_getscl;
+		break;
+	}
+
+	savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");
+}
+EXPORT_SYMBOL(savagefb_create_i2c_busses);
+
+void savagefb_delete_i2c_busses(struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	if (par->chan.par)
+		i2c_bit_del_bus(&par->chan.adapter);
+	par->chan.par = NULL;
+}
+EXPORT_SYMBOL(savagefb_delete_i2c_busses);
+
+static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
+{
+	u8 start = 0x0;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= SAVAGE_DDC,
+			.len	= 1,
+			.buf	= &start,
+		}, {
+			.addr	= SAVAGE_DDC,
+			.flags	= I2C_M_RD,
+			.len	= EDID_LENGTH,
+		},
+	};
+	u8 *buf;
+
+	buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!buf) {
+		dev_warn(&chan->par->pcidev->dev, "Out of memory!\n");
+		return NULL;
+	}
+	msgs[1].buf = buf;
+
+	if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
+		return buf;
+	dev_dbg(&chan->par->pcidev->dev, "Unable to read EDID block.\n");
+	kfree(buf);
+	return NULL;
+}
+
+int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
+{
+	u8 *edid = NULL;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		/* Do the real work */
+		edid = savage_do_probe_i2c_edid(&par->chan);
+		if (edid)
+			break;
+	}
+	if (out_edid)
+		*out_edid = edid;
+	if (!edid)
+		return 1;
+
+	return 0;
+}
+EXPORT_SYMBOL(savagefb_probe_i2c_connector);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/savage/savagefb.c b/drivers/video/savage/savagefb.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/savage/savagefb.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,2277 @@
+/*
+ * linux/drivers/video/savagefb.c -- S3 Savage Framebuffer Driver
+ *
+ * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
+ *                          Sven Neumann <neo@directfb.org>
+ *
+ *
+ * Card specific code is based on XFree86's savage driver.
+ * Framebuffer framework code is based on code of cyber2000fb and tdfxfb.
+ *
+ * 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.
+ *
+ * 0.4.0 (neo)
+ *  - hardware accelerated clear and move
+ *
+ * 0.3.2 (dok)
+ *  - wait for vertical retrace before writing to cr67
+ *    at the beginning of savagefb_set_par
+ *  - use synchronization registers cr23 and cr26
+ *
+ * 0.3.1 (dok)
+ *  - reset 3D engine
+ *  - don't return alpha bits for 32bit format
+ *
+ * 0.3.0 (dok)
+ *  - added WaitIdle functions for all Savage types
+ *  - do WaitIdle before mode switching
+ *  - code cleanup
+ *
+ * 0.2.0 (dok)
+ *  - first working version
+ *
+ *
+ * TODO
+ * - clock validations in decode_var
+ *
+ * BUGS
+ * - white margin on bootup
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "savagefb.h"
+
+
+#define SAVAGEFB_VERSION "0.4.0_2.6"
+
+/* --------------------------------------------------------------------- */
+
+
+static char *mode_option __initdata = NULL;
+static int   paletteEnabled = 0;
+
+#ifdef MODULE
+
+MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");
+MODULE_PARM(disabled, "i");
+MODULE_PARM_DESC(disabled, "Disable this driver's initialization.");
+
+#endif
+
+
+/* --------------------------------------------------------------------- */
+
+static void vgaHWSeqReset (struct savagefb_par *par, int start)
+{
+	if (start)
+		VGAwSEQ (0x00, 0x01);		/* Synchronous Reset */
+	else
+		VGAwSEQ (0x00, 0x03);		/* End Reset */
+}
+
+static void vgaHWProtect (struct savagefb_par *par, int on)
+{
+	unsigned char tmp;
+
+	if (on) {
+		/*
+		 * Turn off screen and disable sequencer.
+		 */
+		tmp = VGArSEQ (0x01);
+
+		vgaHWSeqReset (par, 1);	        /* start synchronous reset */
+		VGAwSEQ (0x01, tmp | 0x20);	/* disable the display */
+
+		VGAenablePalette();
+	} else {
+		/*
+		 * Reenable sequencer, then turn on screen.
+		 */
+
+		tmp = VGArSEQ (0x01);
+
+		VGAwSEQ (0x01, tmp & ~0x20);	/* reenable display */
+		vgaHWSeqReset (par, 0);	        /* clear synchronous reset */
+
+		VGAdisablePalette();
+	}
+}
+
+static void vgaHWRestore (struct savagefb_par  *par)
+{
+	int i;
+
+	VGAwMISC (par->MiscOutReg);
+
+	for (i = 1; i < 5; i++)
+		VGAwSEQ (i, par->Sequencer[i]);
+
+	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
+	   CRTC[17] */
+	VGAwCR (17, par->CRTC[17] & ~0x80);
+
+	for (i = 0; i < 25; i++)
+		VGAwCR (i, par->CRTC[i]);
+
+	for (i = 0; i < 9; i++)
+		VGAwGR (i, par->Graphics[i]);
+
+	VGAenablePalette();
+
+	for (i = 0; i < 21; i++)
+		VGAwATTR (i, par->Attribute[i]);
+
+	VGAdisablePalette();
+}
+
+static void vgaHWInit (struct fb_var_screeninfo *var,
+		       struct savagefb_par            *par,
+		       struct xtimings                *timings)
+{
+	par->MiscOutReg = 0x23;
+
+	if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
+		par->MiscOutReg |= 0x40;
+
+	if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
+		par->MiscOutReg |= 0x80;
+
+	/*
+	 * Time Sequencer
+	 */
+	par->Sequencer[0x00] = 0x00;
+	par->Sequencer[0x01] = 0x01;
+	par->Sequencer[0x02] = 0x0F;
+	par->Sequencer[0x03] = 0x00;          /* Font select */
+	par->Sequencer[0x04] = 0x0E;          /* Misc */
+
+	/*
+	 * CRTC Controller
+	 */
+	par->CRTC[0x00] = (timings->HTotal >> 3) - 5;
+	par->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
+	par->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
+	par->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
+	par->CRTC[0x04] = (timings->HSyncStart >> 3);
+	par->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
+		(((timings->HSyncEnd >> 3)) & 0x1f);
+	par->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
+	par->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
+		(((timings->VDisplay - 1) & 0x100) >> 7) |
+		((timings->VSyncStart & 0x100) >> 6) |
+		(((timings->VSyncStart - 1) & 0x100) >> 5) |
+		0x10 |
+		(((timings->VTotal - 2) & 0x200) >> 4) |
+		(((timings->VDisplay - 1) & 0x200) >> 3) |
+		((timings->VSyncStart & 0x200) >> 2);
+	par->CRTC[0x08] = 0x00;
+	par->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
+
+	if (timings->dblscan)
+		par->CRTC[0x09] |= 0x80;
+
+	par->CRTC[0x0a] = 0x00;
+	par->CRTC[0x0b] = 0x00;
+	par->CRTC[0x0c] = 0x00;
+	par->CRTC[0x0d] = 0x00;
+	par->CRTC[0x0e] = 0x00;
+	par->CRTC[0x0f] = 0x00;
+	par->CRTC[0x10] = timings->VSyncStart & 0xff;
+	par->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
+	par->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
+	par->CRTC[0x13] = var->xres_virtual >> 4;
+	par->CRTC[0x14] = 0x00;
+	par->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
+	par->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
+	par->CRTC[0x17] = 0xc3;
+	par->CRTC[0x18] = 0xff;
+
+	/*
+	 * are these unnecessary?
+	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
+	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
+	 */
+
+	/*
+	 * Graphics Display Controller
+	 */
+	par->Graphics[0x00] = 0x00;
+	par->Graphics[0x01] = 0x00;
+	par->Graphics[0x02] = 0x00;
+	par->Graphics[0x03] = 0x00;
+	par->Graphics[0x04] = 0x00;
+	par->Graphics[0x05] = 0x40;
+	par->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
+	par->Graphics[0x07] = 0x0F;
+	par->Graphics[0x08] = 0xFF;
+
+
+	par->Attribute[0x00]  = 0x00; /* standard colormap translation */
+	par->Attribute[0x01]  = 0x01;
+	par->Attribute[0x02]  = 0x02;
+	par->Attribute[0x03]  = 0x03;
+	par->Attribute[0x04]  = 0x04;
+	par->Attribute[0x05]  = 0x05;
+	par->Attribute[0x06]  = 0x06;
+	par->Attribute[0x07]  = 0x07;
+	par->Attribute[0x08]  = 0x08;
+	par->Attribute[0x09]  = 0x09;
+	par->Attribute[0x0a] = 0x0A;
+	par->Attribute[0x0b] = 0x0B;
+	par->Attribute[0x0c] = 0x0C;
+	par->Attribute[0x0d] = 0x0D;
+	par->Attribute[0x0e] = 0x0E;
+	par->Attribute[0x0f] = 0x0F;
+	par->Attribute[0x10] = 0x41;
+	par->Attribute[0x11] = 0xFF;
+	par->Attribute[0x12] = 0x0F;
+	par->Attribute[0x13] = 0x00;
+	par->Attribute[0x14] = 0x00;
+}
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Acceleration for SavageFB
+ */
+
+/* Wait for fifo space */
+static void
+savage3D_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C00) & 0x0000ffff) > slots);
+}
+
+static void
+savage4_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C60) & 0x001fffff) > slots);
+}
+
+static void
+savage2000_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C60) & 0x0000ffff) > slots);
+}
+
+/* Wait for idle accelerator */
+static void
+savage3D_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C00) & 0x0008ffff) != 0x80000);
+}
+
+static void
+savage4_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C60) & 0x00a00000) != 0x00a00000);
+}
+
+static void
+savage2000_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C60) & 0x009fffff));
+}
+
+
+static void
+SavageSetup2DEngine (struct savagefb_par  *par)
+{
+	unsigned long GlobalBitmapDescriptor;
+
+	GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;
+	BCI_BD_SET_BPP (GlobalBitmapDescriptor, par->depth);
+	BCI_BD_SET_STRIDE (GlobalBitmapDescriptor, par->vwidth);
+
+	switch(par->chip) {
+	case S3_SAVAGE3D:
+	case S3_SAVAGE_MX:
+		/* Disable BCI */
+		savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
+		/* Setup BCI command overflow buffer */
+		savage_out32(0x48C14, (par->cob_offset >> 11) | (par->cob_index << 29));
+		/* Program shadow status update. */
+		savage_out32(0x48C10, 0x78207220);
+		savage_out32(0x48C0C, 0);
+		/* Enable BCI and command overflow buffer */
+		savage_out32(0x48C18, savage_in32(0x48C18) | 0x0C);
+		break;
+	case S3_SAVAGE4:
+	case S3_PROSAVAGE:
+	case S3_SUPERSAVAGE:
+		/* Disable BCI */
+		savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
+		/* Program shadow status update */
+		savage_out32(0x48C10, 0x00700040);
+		savage_out32(0x48C0C, 0);
+		/* Enable BCI without the COB */
+		savage_out32(0x48C18, savage_in32(0x48C18) | 0x08);
+		break;
+	case S3_SAVAGE2000:
+		/* Disable BCI */
+		savage_out32(0x48C18, 0);
+		/* Setup BCI command overflow buffer */
+		savage_out32(0x48C18, (par->cob_offset >> 7) | (par->cob_index));
+		/* Disable shadow status update */
+		savage_out32(0x48A30, 0);
+		/* Enable BCI and command overflow buffer */
+		savage_out32(0x48C18, savage_in32(0x48C18) | 0x00280000 );
+		break;
+	    default:
+		break;
+	}
+	/* Turn on 16-bit register access. */
+	vga_out8(0x3d4, 0x31);
+	vga_out8(0x3d5, 0x0c);
+
+	/* Set stride to use GBD. */
+	vga_out8 (0x3d4, 0x50);
+	vga_out8 (0x3d5, vga_in8 (0x3d5 ) | 0xC1);
+
+	/* Enable 2D engine. */
+	vga_out8 (0x3d4, 0x40 );
+	vga_out8 (0x3d5, 0x01 );
+
+	savage_out32 (MONO_PAT_0, ~0);
+	savage_out32 (MONO_PAT_1, ~0);
+
+	/* Setup plane masks */
+	savage_out32 (0x8128, ~0 ); /* enable all write planes */
+	savage_out32 (0x812C, ~0 ); /* enable all read planes */
+	savage_out16 (0x8134, 0x27 );
+	savage_out16 (0x8136, 0x07 );
+
+	/* Now set the GBD */
+	par->bci_ptr = 0;
+	par->SavageWaitFifo (par, 4);
+
+	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD1 );
+	BCI_SEND( 0 );
+	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD2 );
+	BCI_SEND( GlobalBitmapDescriptor );
+}
+
+
+static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
+			    int min_n2, int max_n2, long freq_min,
+			    long freq_max, unsigned int *mdiv,
+			    unsigned int *ndiv, unsigned int *r)
+{
+	long diff, best_diff;
+	unsigned int m;
+	unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
+
+	if (freq < freq_min / (1 << max_n2)) {
+		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
+		freq = freq_min / (1 << max_n2);
+	}
+	if (freq > freq_max / (1 << min_n2)) {
+		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
+		freq = freq_max / (1 << min_n2);
+	}
+
+	/* work out suitable timings */
+	best_diff = freq;
+
+	for (n2=min_n2; n2<=max_n2; n2++) {
+		for (n1=min_n1+2; n1<=max_n1+2; n1++) {
+			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
+				BASE_FREQ;
+			if (m < min_m+2 || m > 127+2)
+				continue;
+			if ((m * BASE_FREQ >= freq_min * n1) &&
+			    (m * BASE_FREQ <= freq_max * n1)) {
+				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
+				if (diff < 0)
+					diff = -diff;
+				if (diff < best_diff) {
+					best_diff = diff;
+					best_m = m;
+					best_n1 = n1;
+					best_n2 = n2;
+				}
+			}
+		}
+	}
+
+	*ndiv = best_n1 - 2;
+	*r = best_n2;
+	*mdiv = best_m - 2;
+}
+
+static int common_calc_clock(long freq, int min_m, int min_n1, int max_n1,
+			     int min_n2, int max_n2, long freq_min,
+			     long freq_max, unsigned char *mdiv,
+			     unsigned char *ndiv)
+{
+	long diff, best_diff;
+	unsigned int m;
+	unsigned char n1, n2;
+	unsigned char best_n1 = 16+2, best_n2 = 2, best_m = 125+2;
+
+	best_diff = freq;
+
+	for (n2 = min_n2; n2 <= max_n2; n2++) {
+		for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {
+			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
+				BASE_FREQ;
+			if (m < min_m + 2 || m > 127+2)
+				continue;
+			if((m * BASE_FREQ >= freq_min * n1) &&
+			   (m * BASE_FREQ <= freq_max * n1)) {
+				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
+				if(diff < 0)
+					diff = -diff;
+				if(diff < best_diff) {
+					best_diff = diff;
+					best_m = m;
+					best_n1 = n1;
+					best_n2 = n2;
+				}
+			}
+		}
+	}
+
+	if(max_n1 == 63)
+		*ndiv = (best_n1 - 2) | (best_n2 << 6);
+	else
+		*ndiv = (best_n1 - 2) | (best_n2 << 5);
+
+	*mdiv = best_m - 2;
+
+	return 0;
+}
+
+#ifdef SAVAGEFB_DEBUG
+/* This function is used to debug, it prints out the contents of s3 regs */
+
+static void SavagePrintRegs(void)
+{
+	unsigned char i;
+	int vgaCRIndex = 0x3d4;
+	int vgaCRReg = 0x3d5;
+
+	printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "
+	       "xF" );
+
+	for( i = 0; i < 0x70; i++ ) {
+		if( !(i % 16) )
+			printk(KERN_DEBUG "\nSR%xx ", i >> 4 );
+		vga_out8( 0x3c4, i );
+		printk(KERN_DEBUG " %02x", vga_in8(0x3c5) );
+	}
+
+	printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
+	       "xD xE xF" );
+
+	for( i = 0; i < 0xB7; i++ ) {
+		if( !(i % 16) )
+			printk(KERN_DEBUG "\nCR%xx ", i >> 4 );
+		vga_out8( vgaCRIndex, i );
+		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg) );
+	}
+
+	printk(KERN_DEBUG "\n\n");
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static void savage_get_default_par(struct savagefb_par *par)
+{
+	unsigned char cr3a, cr53, cr66;
+
+	vga_out16 (0x3d4, 0x4838);
+	vga_out16 (0x3d4, 0xa039);
+	vga_out16 (0x3c4, 0x0608);
+
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x80);
+	vga_out8 (0x3d4, 0x3a);
+	cr3a = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3a | 0x80);
+	vga_out8 (0x3d4, 0x53);
+	cr53 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr53 & 0x7f);
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+
+	/* unlock extended seq regs */
+	vga_out8 (0x3c4, 0x08);
+	par->SR08 = vga_in8 (0x3c5);
+	vga_out8 (0x3c5, 0x06);
+
+	/* now save all the extended regs we need */
+	vga_out8 (0x3d4, 0x31);
+	par->CR31 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x32);
+	par->CR32 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x34);
+	par->CR34 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x36);
+	par->CR36 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x3a);
+	par->CR3A = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x40);
+	par->CR40 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x42);
+	par->CR42 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x45);
+	par->CR45 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x50);
+	par->CR50 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x51);
+	par->CR51 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x53);
+	par->CR53 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x58);
+	par->CR58 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x60);
+	par->CR60 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x66);
+	par->CR66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x67);
+	par->CR67 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x68);
+	par->CR68 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x69);
+	par->CR69 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x6f);
+	par->CR6F = vga_in8 (0x3d5);
+
+	vga_out8 (0x3d4, 0x33);
+	par->CR33 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x86);
+	par->CR86 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x88);
+	par->CR88 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x90);
+	par->CR90 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x91);
+	par->CR91 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0xb0);
+	par->CRB0 = vga_in8 (0x3d5) | 0x80;
+
+	/* extended mode timing regs */
+	vga_out8 (0x3d4, 0x3b);
+	par->CR3B = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x3c);
+	par->CR3C = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x43);
+	par->CR43 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x5d);
+	par->CR5D = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x5e);
+	par->CR5E = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x65);
+	par->CR65 = vga_in8 (0x3d5);
+
+	/* save seq extended regs for DCLK PLL programming */
+	vga_out8 (0x3c4, 0x0e);
+	par->SR0E = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x0f);
+	par->SR0F = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x10);
+	par->SR10 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x11);
+	par->SR11 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x12);
+	par->SR12 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x13);
+	par->SR13 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x29);
+	par->SR29 = vga_in8 (0x3c5);
+
+	vga_out8 (0x3c4, 0x15);
+	par->SR15 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x30);
+	par->SR30 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x18);
+	par->SR18 = vga_in8 (0x3c5);
+
+	/* Save flat panel expansion regsters. */
+	if (par->chip == S3_SAVAGE_MX) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			vga_out8 (0x3c4, 0x54+i);
+			par->SR54[i] = vga_in8 (0x3c5);
+		}
+	}
+
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x80);
+	vga_out8 (0x3d4, 0x3a);
+	cr3a = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3a | 0x80);
+
+	/* now save MIU regs */
+	if (par->chip != S3_SAVAGE_MX) {
+		par->MMPR0 = savage_in32(FIFO_CONTROL_REG);
+		par->MMPR1 = savage_in32(MIU_CONTROL_REG);
+		par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG);
+		par->MMPR3 = savage_in32(MISC_TIMEOUT_REG);
+	}
+
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+}
+
+static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+{
+	var->xres = var->xres_virtual = modedb->xres;
+	var->yres = modedb->yres;
+        if (var->yres_virtual < var->yres)
+	    var->yres_virtual = var->yres;
+        var->xoffset = var->yoffset = 0;
+        var->pixclock = modedb->pixclock;
+        var->left_margin = modedb->left_margin;
+        var->right_margin = modedb->right_margin;
+        var->upper_margin = modedb->upper_margin;
+        var->lower_margin = modedb->lower_margin;
+        var->hsync_len = modedb->hsync_len;
+        var->vsync_len = modedb->vsync_len;
+        var->sync = modedb->sync;
+        var->vmode = modedb->vmode;
+}
+
+static int savagefb_check_var (struct fb_var_screeninfo   *var,
+			       struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int memlen, vramlen, mode_valid = 0;
+
+	DBG("savagefb_check_var");
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = var->green.offset =
+			var->blue.offset = 0;
+		var->red.length = var->green.length =
+			var->blue.length = var->bits_per_pixel;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (!fb_validate_mode(var, info))
+		mode_valid = 1;
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+
+	if (!mode_valid) {
+		struct fb_videomode *mode;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			savage_update_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && !list_empty(&info->modelist))
+		return -EINVAL;
+
+	/* Is the mode larger than the LCD panel? */
+	if (par->SavagePanelWidth &&
+	    (var->xres > par->SavagePanelWidth ||
+	     var->yres > par->SavagePanelHeight)) {
+		printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel "
+			"(%dx%d)\n", var->xres,  var->yres,
+			par->SavagePanelWidth,
+			par->SavagePanelHeight);
+		return -1;
+	}
+
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	vramlen = info->fix.smem_len;
+
+	memlen = var->xres_virtual * var->bits_per_pixel *
+		var->yres_virtual / 8;
+	if (memlen > vramlen) {
+		var->yres_virtual = vramlen * 8 /
+			(var->xres_virtual * var->bits_per_pixel);
+		memlen = var->xres_virtual * var->bits_per_pixel *
+			var->yres_virtual / 8;
+	}
+
+	/* we must round yres/xres down, we already rounded y/xres_virtual up
+	   if it was possible. We should return -EINVAL, but I disagree */
+	if (var->yres_virtual < var->yres)
+		var->yres = var->yres_virtual;
+	if (var->xres_virtual < var->xres)
+		var->xres = var->xres_virtual;
+	if (var->xoffset + var->xres > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	return 0;
+}
+
+
+static int savagefb_decode_var (struct fb_var_screeninfo   *var,
+				struct savagefb_par        *par)
+{
+	struct xtimings timings;
+	int width, dclk, i, j; /*, refresh; */
+	unsigned int m, n, r;
+	unsigned char tmp = 0;
+	unsigned int pixclock = var->pixclock;
+
+	DBG("savagefb_decode_var");
+
+	memset (&timings, 0, sizeof(timings));
+
+	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
+	timings.Clock = 1000000000 / pixclock;
+	if (timings.Clock < 1) timings.Clock = 1;
+	timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
+	timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
+	timings.HDisplay = var->xres;
+	timings.HSyncStart = timings.HDisplay + var->right_margin;
+	timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
+	timings.HTotal = timings.HSyncEnd + var->left_margin;
+	timings.VDisplay = var->yres;
+	timings.VSyncStart = timings.VDisplay + var->lower_margin;
+	timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
+	timings.VTotal = timings.VSyncEnd + var->upper_margin;
+	timings.sync = var->sync;
+
+
+	par->depth  = var->bits_per_pixel;
+	par->vwidth = var->xres_virtual;
+
+	if (var->bits_per_pixel == 16  &&  par->chip == S3_SAVAGE3D) {
+		timings.HDisplay *= 2;
+		timings.HSyncStart *= 2;
+		timings.HSyncEnd *= 2;
+		timings.HTotal *= 2;
+	}
+
+	/*
+	 * This will allocate the datastructure and initialize all of the
+	 * generic VGA registers.
+	 */
+	vgaHWInit (var, par, &timings);
+
+	/* We need to set CR67 whether or not we use the BIOS. */
+
+	dclk = timings.Clock;
+	par->CR67 = 0x00;
+
+	switch( var->bits_per_pixel ) {
+	case 8:
+		if( (par->chip == S3_SAVAGE2000) && (dclk >= 230000) )
+			par->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
+		else
+			par->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
+		break;
+	case 15:
+		if ( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		     ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
+			par->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
+		else
+			par->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
+		break;
+	case 16:
+		if( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
+			par->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
+		else
+			par->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
+		break;
+	case 24:
+		par->CR67 = 0x70;
+		break;
+	case 32:
+		par->CR67 = 0xd0;
+		break;
+	}
+
+	/*
+	 * Either BIOS use is disabled, or we failed to find a suitable
+	 * match.  Fall back to traditional register-crunching.
+	 */
+
+	vga_out8 (0x3d4, 0x3a);
+	tmp = vga_in8 (0x3d5);
+	if (1 /*FIXME:psav->pci_burst*/)
+		par->CR3A = (tmp & 0x7f) | 0x15;
+	else
+		par->CR3A = tmp | 0x95;
+
+	par->CR53 = 0x00;
+	par->CR31 = 0x8c;
+	par->CR66 = 0x89;
+
+	vga_out8 (0x3d4, 0x58);
+	par->CR58 = vga_in8 (0x3d5) & 0x80;
+	par->CR58 |= 0x13;
+
+	par->SR15 = 0x03 | 0x80;
+	par->SR18 = 0x00;
+	par->CR43 = par->CR45 = par->CR65 = 0x00;
+
+	vga_out8 (0x3d4, 0x40);
+	par->CR40 = vga_in8 (0x3d5) & ~0x01;
+
+	par->MMPR0 = 0x010400;
+	par->MMPR1 = 0x00;
+	par->MMPR2 = 0x0808;
+	par->MMPR3 = 0x08080810;
+
+	SavageCalcClock (dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
+	/* m = 107; n = 4; r = 2; */
+
+	if (par->MCLK <= 0) {
+		par->SR10 = 255;
+		par->SR11 = 255;
+	} else {
+		common_calc_clock (par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
+				   &par->SR11, &par->SR10);
+		/*      par->SR10 = 80; // MCLK == 286000 */
+		/*      par->SR11 = 125; */
+	}
+
+	par->SR12 = (r << 6) | (n & 0x3f);
+	par->SR13 = m & 0xff;
+	par->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
+
+	if (var->bits_per_pixel < 24)
+		par->MMPR0 -= 0x8000;
+	else
+		par->MMPR0 -= 0x4000;
+
+	if (timings.interlaced)
+		par->CR42 = 0x20;
+	else
+		par->CR42 = 0x00;
+
+	par->CR34 = 0x10; /* display fifo */
+
+	i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |
+		((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |
+		((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) |
+		((timings.HSyncStart & 0x800) >> 7);
+
+	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64)
+		i |= 0x08;
+	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)
+		i |= 0x20;
+
+	j = (par->CRTC[0] + ((i & 0x01) << 8) +
+	     par->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
+
+	if (j - (par->CRTC[4] + ((i & 0x10) << 4)) < 4) {
+		if (par->CRTC[4] + ((i & 0x10) << 4) + 4 <=
+		    par->CRTC[0] + ((i & 0x01) << 8))
+			j = par->CRTC[4] + ((i & 0x10) << 4) + 4;
+		else
+			j = par->CRTC[0] + ((i & 0x01) << 8) + 1;
+	}
+
+	par->CR3B = j & 0xff;
+	i |= (j & 0x100) >> 2;
+	par->CR3C = (par->CRTC[0] + ((i & 0x01) << 8)) / 2;
+	par->CR5D = i;
+	par->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
+		(((timings.VDisplay - 1) & 0x400) >> 9) |
+		(((timings.VSyncStart) & 0x400) >> 8) |
+		(((timings.VSyncStart) & 0x400) >> 6) | 0x40;
+	width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;
+	par->CR91 = par->CRTC[19] = 0xff & width;
+	par->CR51 = (0x300 & width) >> 4;
+	par->CR90 = 0x80 | (width >> 8);
+	par->MiscOutReg |= 0x0c;
+
+	/* Set frame buffer description. */
+
+	if (var->bits_per_pixel <= 8)
+		par->CR50 = 0;
+	else if (var->bits_per_pixel <= 16)
+		par->CR50 = 0x10;
+	else
+		par->CR50 = 0x30;
+
+	if (var->xres_virtual <= 640)
+		par->CR50 |= 0x40;
+	else if (var->xres_virtual == 800)
+		par->CR50 |= 0x80;
+	else if (var->xres_virtual == 1024)
+		par->CR50 |= 0x00;
+	else if (var->xres_virtual == 1152)
+		par->CR50 |= 0x01;
+	else if (var->xres_virtual == 1280)
+		par->CR50 |= 0xc0;
+	else if (var->xres_virtual == 1600)
+		par->CR50 |= 0x81;
+	else
+		par->CR50 |= 0xc1;	/* Use GBD */
+
+	if( par->chip == S3_SAVAGE2000 )
+		par->CR33 = 0x08;
+	else
+		par->CR33 = 0x20;
+
+	par->CRTC[0x17] = 0xeb;
+
+	par->CR67 |= 1;
+
+	vga_out8(0x3d4, 0x36);
+	par->CR36 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x68);
+	par->CR68 = vga_in8 (0x3d5);
+	par->CR69 = 0;
+	vga_out8 (0x3d4, 0x6f);
+	par->CR6F = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x86);
+	par->CR86 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x88);
+	par->CR88 = vga_in8 (0x3d5) | 0x08;
+	vga_out8 (0x3d4, 0xb0);
+	par->CRB0 = vga_in8 (0x3d5) | 0x80;
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
+static int savagefb_setcolreg(unsigned        regno,
+			      unsigned        red,
+			      unsigned        green,
+			      unsigned        blue,
+			      unsigned        transp,
+			      struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	if (regno >= NR_PALETTE)
+		return -EINVAL;
+
+	par->palette[regno].red    = red;
+	par->palette[regno].green  = green;
+	par->palette[regno].blue   = blue;
+	par->palette[regno].transp = transp;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		vga_out8 (0x3c8, regno);
+
+		vga_out8 (0x3c9, red   >> 10);
+		vga_out8 (0x3c9, green >> 10);
+		vga_out8 (0x3c9, blue  >> 10);
+		break;
+
+	case 16:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((red   & 0xf800)      ) |
+				((green & 0xfc00) >>  5) |
+				((blue  & 0xf800) >> 11);
+		break;
+
+	case 24:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((red    & 0xff00) <<  8) |
+				((green  & 0xff00)      ) |
+				((blue   & 0xff00) >>  8);
+		break;
+	case 32:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((transp & 0xff00) << 16) |
+				((red    & 0xff00) <<  8) |
+				((green  & 0xff00)      ) |
+				((blue   & 0xff00) >>  8);
+		break;
+
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+static void savagefb_set_par_int (struct savagefb_par  *par)
+{
+	unsigned char tmp, cr3a, cr66, cr67;
+
+	DBG ("savagefb_set_par_int");
+
+	par->SavageWaitIdle (par);
+
+	vga_out8 (0x3c2, 0x23);
+
+	vga_out16 (0x3d4, 0x4838);
+	vga_out16 (0x3d4, 0xa539);
+	vga_out16 (0x3c4, 0x0608);
+
+	vgaHWProtect (par, 1);
+
+	/*
+	 * Some Savage/MX and /IX systems go nuts when trying to exit the
+	 * server after WindowMaker has displayed a gradient background.  I
+	 * haven't been able to find what causes it, but a non-destructive
+	 * switch to mode 3 here seems to eliminate the issue.
+	 */
+
+	VerticalRetraceWait();
+	vga_out8 (0x3d4, 0x67);
+	cr67 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c); /* no STREAMS yet */
+
+	vga_out8 (0x3d4, 0x23);
+	vga_out8 (0x3d5, 0x00);
+	vga_out8 (0x3d4, 0x26);
+	vga_out8 (0x3d5, 0x00);
+
+	/* restore extended regs */
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, par->CR66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, par->CR3A);
+	vga_out8 (0x3d4, 0x31);
+	vga_out8 (0x3d5, par->CR31);
+	vga_out8 (0x3d4, 0x32);
+	vga_out8 (0x3d5, par->CR32);
+	vga_out8 (0x3d4, 0x58);
+	vga_out8 (0x3d5, par->CR58);
+	vga_out8 (0x3d4, 0x53);
+	vga_out8 (0x3d5, par->CR53 & 0x7f);
+
+	vga_out16 (0x3c4, 0x0608);
+
+	/* Restore DCLK registers. */
+
+	vga_out8 (0x3c4, 0x0e);
+	vga_out8 (0x3c5, par->SR0E);
+	vga_out8 (0x3c4, 0x0f);
+	vga_out8 (0x3c5, par->SR0F);
+	vga_out8 (0x3c4, 0x29);
+	vga_out8 (0x3c5, par->SR29);
+	vga_out8 (0x3c4, 0x15);
+	vga_out8 (0x3c5, par->SR15);
+
+	/* Restore flat panel expansion regsters. */
+	if( par->chip == S3_SAVAGE_MX ) {
+		int i;
+
+		for( i = 0; i < 8; i++ ) {
+			vga_out8 (0x3c4, 0x54+i);
+			vga_out8 (0x3c5, par->SR54[i]);
+		}
+	}
+
+	vgaHWRestore (par);
+
+	/* extended mode timing registers */
+	vga_out8 (0x3d4, 0x53);
+	vga_out8 (0x3d5, par->CR53);
+	vga_out8 (0x3d4, 0x5d);
+	vga_out8 (0x3d5, par->CR5D);
+	vga_out8 (0x3d4, 0x5e);
+	vga_out8 (0x3d5, par->CR5E);
+	vga_out8 (0x3d4, 0x3b);
+	vga_out8 (0x3d5, par->CR3B);
+	vga_out8 (0x3d4, 0x3c);
+	vga_out8 (0x3d5, par->CR3C);
+	vga_out8 (0x3d4, 0x43);
+	vga_out8 (0x3d5, par->CR43);
+	vga_out8 (0x3d4, 0x65);
+	vga_out8 (0x3d5, par->CR65);
+
+	/* restore the desired video mode with cr67 */
+	vga_out8 (0x3d4, 0x67);
+	/* following part not present in X11 driver */
+	cr67 = vga_in8 (0x3d5) & 0xf;
+	vga_out8 (0x3d5, 0x50 | cr67);
+	udelay (10000);
+	vga_out8 (0x3d4, 0x67);
+	/* end of part */
+	vga_out8 (0x3d5, par->CR67 & ~0x0c);
+
+	/* other mode timing and extended regs */
+	vga_out8 (0x3d4, 0x34);
+	vga_out8 (0x3d5, par->CR34);
+	vga_out8 (0x3d4, 0x40);
+	vga_out8 (0x3d5, par->CR40);
+	vga_out8 (0x3d4, 0x42);
+	vga_out8 (0x3d5, par->CR42);
+	vga_out8 (0x3d4, 0x45);
+	vga_out8 (0x3d5, par->CR45);
+	vga_out8 (0x3d4, 0x50);
+	vga_out8 (0x3d5, par->CR50);
+	vga_out8 (0x3d4, 0x51);
+	vga_out8 (0x3d5, par->CR51);
+
+	/* memory timings */
+	vga_out8 (0x3d4, 0x36);
+	vga_out8 (0x3d5, par->CR36);
+	vga_out8 (0x3d4, 0x60);
+	vga_out8 (0x3d5, par->CR60);
+	vga_out8 (0x3d4, 0x68);
+	vga_out8 (0x3d5, par->CR68);
+	vga_out8 (0x3d4, 0x69);
+	vga_out8 (0x3d5, par->CR69);
+	vga_out8 (0x3d4, 0x6f);
+	vga_out8 (0x3d5, par->CR6F);
+
+	vga_out8 (0x3d4, 0x33);
+	vga_out8 (0x3d5, par->CR33);
+	vga_out8 (0x3d4, 0x86);
+	vga_out8 (0x3d5, par->CR86);
+	vga_out8 (0x3d4, 0x88);
+	vga_out8 (0x3d5, par->CR88);
+	vga_out8 (0x3d4, 0x90);
+	vga_out8 (0x3d5, par->CR90);
+	vga_out8 (0x3d4, 0x91);
+	vga_out8 (0x3d5, par->CR91);
+
+	if (par->chip == S3_SAVAGE4) {
+		vga_out8 (0x3d4, 0xb0);
+		vga_out8 (0x3d5, par->CRB0);
+	}
+
+	vga_out8 (0x3d4, 0x32);
+	vga_out8 (0x3d5, par->CR32);
+
+	/* unlock extended seq regs */
+	vga_out8 (0x3c4, 0x08);
+	vga_out8 (0x3c5, 0x06);
+
+	/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
+	 * that we should leave the default SR10 and SR11 values there.
+	 */
+	if (par->SR10 != 255) {
+		vga_out8 (0x3c4, 0x10);
+		vga_out8 (0x3c5, par->SR10);
+		vga_out8 (0x3c4, 0x11);
+		vga_out8 (0x3c5, par->SR11);
+	}
+
+	/* restore extended seq regs for dclk */
+	vga_out8 (0x3c4, 0x0e);
+	vga_out8 (0x3c5, par->SR0E);
+	vga_out8 (0x3c4, 0x0f);
+	vga_out8 (0x3c5, par->SR0F);
+	vga_out8 (0x3c4, 0x12);
+	vga_out8 (0x3c5, par->SR12);
+	vga_out8 (0x3c4, 0x13);
+	vga_out8 (0x3c5, par->SR13);
+	vga_out8 (0x3c4, 0x29);
+	vga_out8 (0x3c5, par->SR29);
+
+	vga_out8 (0x3c4, 0x18);
+	vga_out8 (0x3c5, par->SR18);
+
+	/* load new m, n pll values for dclk & mclk */
+	vga_out8 (0x3c4, 0x15);
+	tmp = vga_in8 (0x3c5) & ~0x21;
+
+	vga_out8 (0x3c5, tmp | 0x03);
+	vga_out8 (0x3c5, tmp | 0x23);
+	vga_out8 (0x3c5, tmp | 0x03);
+	vga_out8 (0x3c5, par->SR15);
+	udelay (100);
+
+	vga_out8 (0x3c4, 0x30);
+	vga_out8 (0x3c5, par->SR30);
+	vga_out8 (0x3c4, 0x08);
+	vga_out8 (0x3c5, par->SR08);
+
+	/* now write out cr67 in full, possibly starting STREAMS */
+	VerticalRetraceWait();
+	vga_out8 (0x3d4, 0x67);
+	vga_out8 (0x3d5, par->CR67);
+
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x80);
+	vga_out8 (0x3d4, 0x3a);
+	cr3a = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3a | 0x80);
+
+	if (par->chip != S3_SAVAGE_MX) {
+		VerticalRetraceWait();
+		savage_out32 (FIFO_CONTROL_REG, par->MMPR0);
+		par->SavageWaitIdle (par);
+		savage_out32 (MIU_CONTROL_REG, par->MMPR1);
+		par->SavageWaitIdle (par);
+		savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2);
+		par->SavageWaitIdle (par);
+		savage_out32 (MISC_TIMEOUT_REG, par->MMPR3);
+	}
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+
+	SavageSetup2DEngine (par);
+	vgaHWProtect (par, 0);
+}
+
+static void savagefb_update_start (struct savagefb_par      *par,
+				   struct fb_var_screeninfo *var)
+{
+	int base;
+
+	base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
+		* ((var->bits_per_pixel+7) / 8)) >> 2;
+
+	/* now program the start address registers */
+	vga_out16(0x3d4, (base & 0x00ff00) | 0x0c);
+	vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d);
+	vga_out8 (0x3d4, 0x69);
+	vga_out8 (0x3d5, (base & 0x7f0000) >> 16);
+}
+
+
+static void savagefb_set_fix(struct fb_info *info)
+{
+	info->fix.line_length = info->var.xres_virtual *
+		info->var.bits_per_pixel / 8;
+
+	if (info->var.bits_per_pixel == 8)
+		info->fix.visual      = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual      = FB_VISUAL_TRUECOLOR;
+}
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+static void savagefb_set_clip(struct fb_info *info)
+{
+    struct savagefb_par *par = (struct savagefb_par *)info->par;
+    int cmd;
+
+    cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
+    par->bci_ptr = 0;
+    par->SavageWaitFifo(par,3);
+    BCI_SEND(cmd);
+    BCI_SEND(BCI_CLIP_TL(0, 0));
+    BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
+}
+#endif
+
+static int savagefb_set_par (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int err;
+
+	DBG("savagefb_set_par");
+	err = savagefb_decode_var (var, par);
+	if (err)
+		return err;
+
+	if (par->dacSpeedBpp <= 0) {
+		if (var->bits_per_pixel > 24)
+			par->dacSpeedBpp = par->clock[3];
+		else if (var->bits_per_pixel >= 24)
+			par->dacSpeedBpp = par->clock[2];
+		else if ((var->bits_per_pixel > 8) && (var->bits_per_pixel < 24))
+			par->dacSpeedBpp = par->clock[1];
+		else if (var->bits_per_pixel <= 8)
+			par->dacSpeedBpp = par->clock[0];
+	}
+
+	/* Set ramdac limits */
+	par->maxClock = par->dacSpeedBpp;
+	par->minClock = 10000;
+
+	savagefb_set_par_int (par);
+	savagefb_update_start (par, var);
+	fb_set_cmap (&info->cmap, info);
+	savagefb_set_fix(info);
+	savagefb_set_clip(info);
+
+	SavagePrintRegs();
+	return 0;
+}
+
+/*
+ *    Pan or Wrap the Display
+ */
+static int savagefb_pan_display (struct fb_var_screeninfo *var,
+				 struct fb_info           *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	u_int y_bottom;
+
+	y_bottom = var->yoffset;
+
+	if (!(var->vmode & FB_VMODE_YWRAP))
+		y_bottom += var->yres;
+
+	if (var->xoffset > (var->xres_virtual - var->xres))
+		return -EINVAL;
+	if (y_bottom > info->var.yres_virtual)
+		return -EINVAL;
+
+	savagefb_update_start (par, var);
+
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+
+	return 0;
+}
+
+
+static struct fb_ops savagefb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_check_var   = savagefb_check_var,
+	.fb_set_par     = savagefb_set_par,
+	.fb_setcolreg   = savagefb_setcolreg,
+	.fb_pan_display = savagefb_pan_display,
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	.fb_fillrect    = savagefb_fillrect,
+	.fb_copyarea    = savagefb_copyarea,
+	.fb_imageblit   = savagefb_imageblit,
+	.fb_sync        = savagefb_sync,
+#else
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+#endif
+	.fb_cursor      = soft_cursor,
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo __devinitdata savagefb_var800x600x8 = {
+	.accel_flags =	FB_ACCELF_TEXT,
+	.xres =		800,
+	.yres =		600,
+	.xres_virtual =  800,
+	.yres_virtual =  600,
+	.bits_per_pixel = 8,
+	.pixclock =	25000,
+	.left_margin =	88,
+	.right_margin =	40,
+	.upper_margin =	23,
+	.lower_margin =	1,
+	.hsync_len =	128,
+	.vsync_len =	4,
+	.sync =		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode =	FB_VMODE_NONINTERLACED
+};
+
+static void savage_enable_mmio (struct savagefb_par *par)
+{
+	unsigned char val;
+
+	DBG ("savage_enable_mmio\n");
+
+	val = vga_in8 (0x3c3);
+	vga_out8 (0x3c3, val | 0x01);
+	val = vga_in8 (0x3cc);
+	vga_out8 (0x3c2, val | 0x01);
+
+	if (par->chip >= S3_SAVAGE4) {
+		vga_out8 (0x3d4, 0x40);
+		val = vga_in8 (0x3d5);
+		vga_out8 (0x3d5, val | 1);
+	}
+}
+
+
+void savage_disable_mmio (struct savagefb_par *par)
+{
+	unsigned char val;
+
+	DBG ("savage_disable_mmio\n");
+
+	if(par->chip >= S3_SAVAGE4 ) {
+		vga_out8 (0x3d4, 0x40);
+		val = vga_in8 (0x3d5);
+		vga_out8 (0x3d5, val | 1);
+	}
+}
+
+
+static int __devinit savage_map_mmio (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	DBG ("savage_map_mmio");
+
+	if (S3_SAVAGE3D_SERIES (par->chip))
+		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
+			SAVAGE_NEWMMIO_REGBASE_S3;
+	else
+		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
+			SAVAGE_NEWMMIO_REGBASE_S4;
+
+	par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
+
+	par->mmio.vbase = ioremap (par->mmio.pbase, par->mmio.len);
+	if (!par->mmio.vbase) {
+		printk ("savagefb: unable to map memory mapped IO\n");
+		return -ENOMEM;
+	} else
+		printk (KERN_INFO "savagefb: mapped io at %p\n",
+			par->mmio.vbase);
+
+	info->fix.mmio_start = par->mmio.pbase;
+	info->fix.mmio_len   = par->mmio.len;
+
+	par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
+	par->bci_ptr  = 0;
+
+	savage_enable_mmio (par);
+
+	return 0;
+}
+
+static void __devinit savage_unmap_mmio (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	DBG ("savage_unmap_mmio");
+
+	savage_disable_mmio(par);
+
+	if (par->mmio.vbase) {
+		iounmap ((void __iomem *)par->mmio.vbase);
+		par->mmio.vbase = NULL;
+	}
+}
+
+static int __devinit savage_map_video (struct fb_info *info,
+				       int video_len)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int resource;
+
+	DBG("savage_map_video");
+
+	if (S3_SAVAGE3D_SERIES (par->chip))
+		resource = 0;
+	else
+		resource = 1;
+
+	par->video.pbase = pci_resource_start (par->pcidev, resource);
+	par->video.len   = video_len;
+	par->video.vbase = ioremap (par->video.pbase, par->video.len);
+
+	if (!par->video.vbase) {
+		printk ("savagefb: unable to map screen memory\n");
+		return -ENOMEM;
+	} else
+		printk (KERN_INFO "savagefb: mapped framebuffer at %p, "
+			"pbase == %x\n", par->video.vbase, par->video.pbase);
+
+	info->fix.smem_start = par->video.pbase;
+	info->fix.smem_len   = par->video.len - par->cob_size;
+	info->screen_base    = par->video.vbase;
+
+#ifdef CONFIG_MTRR
+	par->video.mtrr = mtrr_add (par->video.pbase, video_len,
+				     MTRR_TYPE_WRCOMB, 1);
+#endif
+	return 0;
+}
+
+static void __devinit savage_unmap_video (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	DBG("savage_unmap_video");
+
+	if (par->video.vbase) {
+#ifdef CONFIG_MTRR
+		mtrr_del (par->video.mtrr, par->video.pbase, par->video.len);
+#endif
+
+		iounmap (par->video.vbase);
+		par->video.vbase = NULL;
+		info->screen_base = NULL;
+	}
+}
+
+static int __devinit savage_init_hw (struct savagefb_par *par)
+{
+	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
+
+	static unsigned char RamSavage3D[] = { 8, 4, 4, 2 };
+	static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
+	static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
+	static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
+
+	int videoRam, videoRambytes;
+
+	DBG("savage_init_hw");
+
+	/* unprotect CRTC[0-7] */
+	vga_out8(0x3d4, 0x11);
+	tmp = vga_in8(0x3d5);
+	vga_out8(0x3d5, tmp & 0x7f);
+
+	/* unlock extended regs */
+	vga_out16(0x3d4, 0x4838);
+	vga_out16(0x3d4, 0xa039);
+	vga_out16(0x3c4, 0x0608);
+
+	vga_out8(0x3d4, 0x40);
+	tmp = vga_in8(0x3d5);
+	vga_out8(0x3d5, tmp & ~0x01);
+
+	/* unlock sys regs */
+	vga_out8(0x3d4, 0x38);
+	vga_out8(0x3d5, 0x48);
+
+	/* Unlock system registers. */
+	vga_out16(0x3d4, 0x4838);
+
+	/* Next go on to detect amount of installed ram */
+
+	vga_out8(0x3d4, 0x36);            /* for register CR36 (CONFG_REG1), */
+	config1 = vga_in8(0x3d5);           /* get amount of vram installed */
+
+	/* Compute the amount of video memory and offscreen memory. */
+
+	switch  (par->chip) {
+	case S3_SAVAGE3D:
+		videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024;
+		break;
+
+	case S3_SAVAGE4:
+		/*
+		 * The Savage4 has one ugly special case to consider.  On
+		 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
+		 * when it really means 8MB.  Why do it the same when you
+		 * can do it different...
+		 */
+		vga_out8(0x3d4, 0x68);	/* memory control 1 */
+		if( (vga_in8(0x3d5) & 0xC0) == (0x01 << 6) )
+			RamSavage4[1] = 8;
+
+		/*FALLTHROUGH*/
+
+	case S3_SAVAGE2000:
+		videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024;
+		break;
+
+	case S3_SAVAGE_MX:
+	case S3_SUPERSAVAGE:
+		videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024;
+		break;
+
+	case S3_PROSAVAGE:
+		videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024;
+		break;
+
+	default:
+		/* How did we get here? */
+		videoRam = 0;
+		break;
+	}
+
+	videoRambytes = videoRam * 1024;
+
+	printk (KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
+
+	/* reset graphics engine to avoid memory corruption */
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x02);
+	udelay (10000);
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66 & ~0x02);	/* clear reset flag */
+	udelay (10000);
+
+
+	/*
+	 * reset memory interface, 3D engine, AGP master, PCI master,
+	 * master engine unit, motion compensation/LPB
+	 */
+	vga_out8 (0x3d4, 0x3f);
+	cr3f = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3f | 0x08);
+	udelay (10000);
+
+	vga_out8 (0x3d4, 0x3f);
+	vga_out8 (0x3d5, cr3f & ~0x08);	/* clear reset flags */
+	udelay (10000);
+
+	/* Savage ramdac speeds */
+	par->numClocks = 4;
+	par->clock[0] = 250000;
+	par->clock[1] = 250000;
+	par->clock[2] = 220000;
+	par->clock[3] = 220000;
+
+	/* detect current mclk */
+	vga_out8(0x3c4, 0x08);
+	sr8 = vga_in8(0x3c5);
+	vga_out8(0x3c5, 0x06);
+	vga_out8(0x3c4, 0x10);
+	n = vga_in8(0x3c5);
+	vga_out8(0x3c4, 0x11);
+	m = vga_in8(0x3c5);
+	vga_out8(0x3c4, 0x08);
+	vga_out8(0x3c5, sr8);
+	m &= 0x7f;
+	n1 = n & 0x1f;
+	n2 = (n >> 5) & 0x03;
+	par->MCLK = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
+	printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
+		par->MCLK);
+
+	/* Check LCD panel parrmation */
+
+	if (par->chip == S3_SAVAGE_MX) {
+		unsigned char cr6b = VGArCR( 0x6b );
+
+		int panelX = (VGArSEQ (0x61) +
+			      ((VGArSEQ (0x66) & 0x02) << 7) + 1) * 8;
+		int panelY = (VGArSEQ (0x69) +
+			      ((VGArSEQ (0x6e) & 0x70) << 4) + 1);
+
+		char * sTechnology = "Unknown";
+
+		/* OK, I admit it.  I don't know how to limit the max dot clock
+		 * for LCD panels of various sizes.  I thought I copied the
+		 * formula from the BIOS, but many users have parrmed me of
+		 * my folly.
+		 *
+		 * Instead, I'll abandon any attempt to automatically limit the
+		 * clock, and add an LCDClock option to XF86Config.  Some day,
+		 * I should come back to this.
+		 */
+
+		enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */
+			ActiveCRT = 0x01,
+			ActiveLCD = 0x02,
+			ActiveTV = 0x04,
+			ActiveCRT2 = 0x20,
+			ActiveDUO = 0x80
+		};
+
+		if ((VGArSEQ (0x39) & 0x03) == 0) {
+			sTechnology = "TFT";
+		} else if ((VGArSEQ (0x30) & 0x01) == 0) {
+			sTechnology = "DSTN";
+		} else 	{
+			sTechnology = "STN";
+		}
+
+		printk (KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
+			panelX, panelY, sTechnology,
+			cr6b & ActiveLCD ? "and active" : "but not active");
+
+		if( cr6b & ActiveLCD ) 	{
+			/*
+			 * If the LCD is active and panel expansion is enabled,
+			 * we probably want to kill the HW cursor.
+			 */
+
+			printk (KERN_INFO "savagefb: Limiting video mode to "
+				"%dx%d\n", panelX, panelY );
+
+			par->SavagePanelWidth = panelX;
+			par->SavagePanelHeight = panelY;
+
+		}
+	}
+
+	savage_get_default_par (par);
+
+	if( S3_SAVAGE4_SERIES(par->chip) ) {
+		/*
+		 * The Savage4 and ProSavage have COB coherency bugs which
+		 * render the buffer useless.  We disable it.
+		 */
+		par->cob_index = 2;
+		par->cob_size = 0x8000 << par->cob_index;
+		par->cob_offset = videoRambytes;
+	} else {
+		/* We use 128kB for the COB on all chips. */
+
+		par->cob_index  = 7;
+		par->cob_size   = 0x400 << par->cob_index;
+		par->cob_offset = videoRambytes - par->cob_size;
+	}
+
+	return videoRambytes;
+}
+
+static int __devinit savage_init_fb_info (struct fb_info *info,
+					  struct pci_dev *dev,
+					  const struct pci_device_id *id)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int err = 0;
+
+	par->pcidev  = dev;
+
+	info->fix.type	   = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux	   = 0;
+	info->fix.xpanstep	   = 2;
+	info->fix.ypanstep	   = 1;
+	info->fix.ywrapstep   = 0;
+	info->fix.accel       = id->driver_data;
+
+	switch (info->fix.accel) {
+	case FB_ACCEL_SUPERSAVAGE:
+		par->chip = S3_SUPERSAVAGE;
+		snprintf (info->fix.id, 16, "S3 SuperSavage");
+		break;
+	case FB_ACCEL_SAVAGE4:
+		par->chip = S3_SAVAGE4;
+		snprintf (info->fix.id, 16, "S3 Savage4");
+		break;
+	case FB_ACCEL_SAVAGE3D:
+		par->chip = S3_SAVAGE3D;
+		snprintf (info->fix.id, 16, "S3 Savage3D");
+		break;
+	case FB_ACCEL_SAVAGE3D_MV:
+		par->chip = S3_SAVAGE3D;
+		snprintf (info->fix.id, 16, "S3 Savage3D-MV");
+		break;
+	case FB_ACCEL_SAVAGE2000:
+		par->chip = S3_SAVAGE2000;
+		snprintf (info->fix.id, 16, "S3 Savage2000");
+		break;
+	case FB_ACCEL_SAVAGE_MX_MV:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "S3 Savage/MX-MV");
+		break;
+	case FB_ACCEL_SAVAGE_MX:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "S3 Savage/MX");
+		break;
+	case FB_ACCEL_SAVAGE_IX_MV:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "S3 Savage/IX-MV");
+		break;
+	case FB_ACCEL_SAVAGE_IX:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "S3 Savage/IX");
+		break;
+	case FB_ACCEL_PROSAVAGE_PM:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "S3 ProSavage");
+		break;
+	case FB_ACCEL_PROSAVAGE_KM:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "S3 ProSavage");
+		break;
+	case FB_ACCEL_S3TWISTER_P:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "S3 Twister");
+		break;
+	case FB_ACCEL_S3TWISTER_K:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "S3 TwisterK");
+		break;
+	case FB_ACCEL_PROSAVAGE_DDR:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "S3 ProSavage DDR");
+		break;
+	case FB_ACCEL_PROSAVAGE_DDRK:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "S3 ProSavage DDR-K");
+		break;
+	}
+
+	if (S3_SAVAGE3D_SERIES(par->chip)) {
+		par->SavageWaitIdle = savage3D_waitidle;
+		par->SavageWaitFifo = savage3D_waitfifo;
+	} else if (S3_SAVAGE4_SERIES(par->chip) ||
+		   S3_SUPERSAVAGE == par->chip) {
+		par->SavageWaitIdle = savage4_waitidle;
+		par->SavageWaitFifo = savage4_waitfifo;
+	} else {
+		par->SavageWaitIdle = savage2000_waitidle;
+		par->SavageWaitFifo = savage2000_waitfifo;
+	}
+
+	info->var.nonstd      = 0;
+	info->var.activate    = FB_ACTIVATE_NOW;
+	info->var.width       = -1;
+	info->var.height      = -1;
+	info->var.accel_flags = 0;
+
+	info->fbops          = &savagefb_ops;
+	info->flags          = FBINFO_DEFAULT |
+		               FBINFO_HWACCEL_YPAN |
+		               FBINFO_HWACCEL_XPAN;
+
+	info->pseudo_palette = par->pseudo_palette;
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	/* FIFO size + padding for commands */
+	info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL);
+
+	err = -ENOMEM;
+	if (info->pixmap.addr) {
+		memset(info->pixmap.addr, 0, 8*1024);
+		info->pixmap.size = 8*1024;
+		info->pixmap.scan_align = 4;
+		info->pixmap.buf_align = 4;
+		info->pixmap.access_align = 4;
+
+		fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+		info->flags |= FBINFO_HWACCEL_COPYAREA |
+	                       FBINFO_HWACCEL_FILLRECT |
+		               FBINFO_HWACCEL_IMAGEBLIT;
+
+		err = 0;
+	}
+#endif
+	return err;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int __devinit savagefb_probe (struct pci_dev* dev,
+				     const struct pci_device_id* id)
+{
+	struct fb_info *info;
+	struct savagefb_par *par;
+	u_int h_sync, v_sync;
+	int err, lpitch;
+	int video_len;
+
+	DBG("savagefb_probe");
+	SavagePrintRegs();
+
+	info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+	err = pci_enable_device(dev);
+	if (err)
+		goto failed_enable;
+
+	if (pci_request_regions(dev, "savagefb")) {
+		printk(KERN_ERR "cannot request PCI regions\n");
+		goto failed_enable;
+	}
+
+	err = -ENOMEM;
+
+	if (savage_init_fb_info(info, dev, id))
+		goto failed_init;
+
+	err = savage_map_mmio(info);
+	if (err)
+		goto failed_mmio;
+
+	video_len = savage_init_hw(par);
+	if (video_len < 0) {
+		err = video_len;
+		goto failed_mmio;
+	}
+
+	err = savage_map_video(info, video_len);
+	if (err)
+		goto failed_video;
+
+	INIT_LIST_HEAD(&info->modelist);
+#if defined(CONFIG_FB_SAVAGE_I2C)
+	savagefb_create_i2c_busses(info);
+	savagefb_probe_i2c_connector(par, &par->edid);
+	fb_edid_to_monspecs(par->edid, &info->monspecs);
+	fb_videomode_to_modelist(info->monspecs.modedb,
+				 info->monspecs.modedb_len,
+				 &info->modelist);
+#endif
+	info->var = savagefb_var800x600x8;
+
+	if (mode_option) {
+		fb_find_mode(&info->var, info, mode_option,
+			     info->monspecs.modedb, info->monspecs.modedb_len,
+			     NULL, 8);
+	} else if (info->monspecs.modedb != NULL) {
+		struct fb_monspecs *specs = &info->monspecs;
+		struct fb_videomode modedb;
+
+		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
+			int i;
+
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = specs->modedb[i];
+					break;
+				}
+			}
+		} else {
+			/* otherwise, get first mode in database */
+			modedb = specs->modedb[0];
+		}
+
+		savage_update_var(&info->var, &modedb);
+	}
+
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len/lpitch;
+
+	if (info->var.yres_virtual < info->var.yres)
+		goto failed;
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	/*
+	 * The clipping coordinates are masked with 0xFFF, so limit our
+	 * virtual resolutions to these sizes.
+	 */
+	if (info->var.yres_virtual > 0x1000)
+		info->var.yres_virtual = 0x1000;
+
+	if (info->var.xres_virtual > 0x1000)
+		info->var.xres_virtual = 0x1000;
+#endif
+	savagefb_check_var(&info->var, info);
+	savagefb_set_fix(info);
+
+	/*
+	 * Calculate the hsync and vsync frequencies.  Note that
+	 * we split the 1e12 constant up so that we can preserve
+	 * the precision and fit the results into 32-bit registers.
+	 *  (1953125000 * 512 = 1e12)
+	 */
+	h_sync = 1953125000 / info->var.pixclock;
+	h_sync = h_sync * 512 / (info->var.xres + info->var.left_margin +
+				 info->var.right_margin +
+				 info->var.hsync_len);
+	v_sync = h_sync / (info->var.yres + info->var.upper_margin +
+			   info->var.lower_margin + info->var.vsync_len);
+
+	printk(KERN_INFO "savagefb v" SAVAGEFB_VERSION ": "
+	       "%dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+	       info->fix.smem_len >> 10,
+	       info->var.xres, info->var.yres,
+	       h_sync / 1000, h_sync % 1000, v_sync);
+
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb_len = 0;
+	info->monspecs.modedb = NULL;
+
+	err = register_framebuffer (info);
+	if (err < 0)
+		goto failed;
+
+	printk (KERN_INFO "fb: %s frame buffer device\n",
+		info->fix.id);
+
+	/*
+	 * Our driver data
+	 */
+	pci_set_drvdata(dev, info);
+
+	return 0;
+
+ failed:
+#ifdef CONFIG_FB_SAVAGE_I2C
+	savagefb_delete_i2c_busses(info);
+#endif
+	fb_alloc_cmap (&info->cmap, 0, 0);
+	savage_unmap_video(info);
+ failed_video:
+	savage_unmap_mmio (info);
+ failed_mmio:
+	kfree(info->pixmap.addr);
+ failed_init:
+	pci_release_regions(dev);
+ failed_enable:
+	framebuffer_release(info);
+
+	return err;
+}
+
+static void __devexit savagefb_remove (struct pci_dev *dev)
+{
+	struct fb_info *info =
+		(struct fb_info *)pci_get_drvdata(dev);
+
+	DBG("savagefb_remove");
+
+	if (info) {
+		/*
+		 * If unregister_framebuffer fails, then
+		 * we will be leaving hooks that could cause
+		 * oopsen laying around.
+		 */
+		if (unregister_framebuffer (info))
+			printk (KERN_WARNING "savagefb: danger danger! "
+				"Oopsen imminent!\n");
+
+#ifdef CONFIG_FB_SAVAGE_I2C
+		savagefb_delete_i2c_busses(info);
+#endif
+		fb_alloc_cmap (&info->cmap, 0, 0);
+		savage_unmap_video (info);
+		savage_unmap_mmio (info);
+		kfree(info->pixmap.addr);
+		pci_release_regions(dev);
+		framebuffer_release(info);
+
+		/*
+		 * Ensure that the driver data is no longer
+		 * valid.
+		 */
+		pci_set_drvdata(dev, NULL);
+	}
+}
+
+static int savagefb_suspend (struct pci_dev* dev, u32 state)
+{
+	struct fb_info *info =
+		(struct fb_info *)pci_get_drvdata(dev);
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	DBG("savagefb_suspend");
+	printk(KERN_DEBUG "state: %u\n", state);
+
+	acquire_console_sem();
+	fb_set_suspend(info, state);
+	savage_disable_mmio(par);
+	release_console_sem();
+
+	pci_disable_device(dev);
+	pci_set_power_state(dev, state);
+
+	return 0;
+}
+
+static int savagefb_resume (struct pci_dev* dev)
+{
+	struct fb_info *info =
+		(struct fb_info *)pci_get_drvdata(dev);
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	DBG("savage_resume");
+
+	pci_set_power_state(dev, 0);
+	pci_restore_state(dev);
+	if(pci_enable_device(dev))
+		DBG("err");
+
+	SavagePrintRegs();
+
+	acquire_console_sem();
+
+	savage_enable_mmio(par);
+	savage_init_hw(par);
+	savagefb_set_par (info);
+
+	fb_set_suspend (info, 0);
+	release_console_sem();
+
+	return 0;
+}
+
+
+static struct pci_device_id savagefb_devices[] __devinitdata = {
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64C,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCSDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCDDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE4},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE2000},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_PM,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_PM},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_KM,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_KM},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_P,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_P},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_K,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_K},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDR},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDRK,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDRK},
+
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, savagefb_devices);
+
+static struct pci_driver savagefb_driver = {
+	.name =     "savagefb",
+	.id_table = savagefb_devices,
+	.probe =    savagefb_probe,
+	.suspend =  savagefb_suspend,
+	.resume =   savagefb_resume,
+	.remove =   __devexit_p(savagefb_remove)
+};
+
+/* **************************** exit-time only **************************** */
+
+static void __exit savage_done (void)
+{
+	DBG("savage_done");
+	pci_unregister_driver (&savagefb_driver);
+}
+
+
+/* ************************* init in-kernel code ************************** */
+
+int __init savagefb_setup(char *options)
+{
+#ifndef MODULE
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		mode_option = this_opt;
+	}
+#endif /* !MODULE */
+	return 0;
+}
+
+int __init savagefb_init(void)
+{
+	char *option;
+
+	DBG("savagefb_init");
+
+	if (fb_get_options("savagefb", &option))
+		return -ENODEV;
+
+	savagefb_setup(option);
+	return pci_register_driver (&savagefb_driver);
+
+}
+
+module_init(savagefb_init);
+module_exit(savage_done);
diff -Nru a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/savage/savagefb.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,354 @@
+/*
+ * linux/drivers/video/savagefb.h -- S3 Savage Framebuffer Driver
+ *
+ * Copyright (c) 2001  Denis Oliver Kropp <dok@convergence.de>
+ *
+ * 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.
+ */
+
+
+#ifndef __SAVAGEFB_H__
+#define __SAVAGEFB_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+#include "../edid.h"
+
+#ifdef SAVAGEFB_DEBUG
+# define DBG(x)		printk (KERN_DEBUG "savagefb: %s\n", (x));
+#else
+# define DBG(x)
+# define SavagePrintRegs(...)
+#endif
+
+
+#define PCI_CHIP_SAVAGE4      0x8a22
+#define PCI_CHIP_SAVAGE3D     0x8a20
+#define PCI_CHIP_SAVAGE3D_MV  0x8a21
+#define PCI_CHIP_SAVAGE2000   0x9102
+#define PCI_CHIP_SAVAGE_MX_MV 0x8c10
+#define PCI_CHIP_SAVAGE_MX    0x8c11
+#define PCI_CHIP_SAVAGE_IX_MV 0x8c12
+#define PCI_CHIP_SAVAGE_IX    0x8c13
+#define PCI_CHIP_PROSAVAGE_PM 0x8a25
+#define PCI_CHIP_PROSAVAGE_KM 0x8a26
+ /* Twister is a code name; hope I get the real name soon. */
+#define PCI_CHIP_S3TWISTER_P  0x8d01
+#define PCI_CHIP_S3TWISTER_K  0x8d02
+#define PCI_CHIP_PROSAVAGE_DDR          0x8d03
+#define PCI_CHIP_PROSAVAGE_DDRK         0x8d04
+#define PCI_CHIP_SUPSAV_MX128		0x8c22
+#define PCI_CHIP_SUPSAV_MX64		0x8c24
+#define PCI_CHIP_SUPSAV_MX64C		0x8c26
+#define PCI_CHIP_SUPSAV_IX128SDR	0x8c2a
+#define PCI_CHIP_SUPSAV_IX128DDR	0x8c2b
+#define PCI_CHIP_SUPSAV_IX64SDR		0x8c2c
+#define PCI_CHIP_SUPSAV_IX64DDR		0x8c2d
+#define PCI_CHIP_SUPSAV_IXCSDR		0x8c2e
+#define PCI_CHIP_SUPSAV_IXCDDR		0x8c2f
+
+
+
+#define S3_SAVAGE3D_SERIES(chip)  ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX))
+
+#define S3_SAVAGE4_SERIES(chip)   ((chip==S3_SAVAGE4) || (chip==S3_PROSAVAGE))
+
+#define S3_SAVAGE_MOBILE_SERIES(chip)  ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE))
+
+#define S3_SAVAGE_SERIES(chip)    ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
+
+
+/* Chip tags.  These are used to group the adapters into
+ * related families.
+ */
+
+typedef enum {
+  S3_UNKNOWN = 0,
+  S3_SAVAGE3D,
+  S3_SAVAGE_MX,
+  S3_SAVAGE4,
+  S3_PROSAVAGE,
+  S3_SUPERSAVAGE,
+  S3_SAVAGE2000,
+  S3_LAST
+} savage_chipset;
+
+#define BIOS_BSIZE		     1024
+#define BIOS_BASE		     0xc0000
+
+#define SAVAGE_NEWMMIO_REGBASE_S3    0x1000000  /* 16MB */
+#define SAVAGE_NEWMMIO_REGBASE_S4    0x0000000
+#define SAVAGE_NEWMMIO_REGSIZE	     0x0080000  /* 512kb */
+#define SAVAGE_NEWMMIO_VGABASE	     0x8000
+
+#define BASE_FREQ		     14318
+#define HALF_BASE_FREQ               7159
+
+#define FIFO_CONTROL_REG	     0x8200
+#define MIU_CONTROL_REG		     0x8204
+#define STREAMS_TIMEOUT_REG	     0x8208
+#define MISC_TIMEOUT_REG	     0x820c
+
+#define MONO_PAT_0                   0xa4e8
+#define MONO_PAT_1                   0xa4ec
+
+#define MAXFIFO                      0x7f00
+
+#define BCI_CMD_NOP                  0x40000000
+#define BCI_CMD_SETREG               0x96000000
+#define BCI_CMD_RECT                 0x48000000
+#define BCI_CMD_RECT_XP              0x01000000
+#define BCI_CMD_RECT_YP              0x02000000
+#define BCI_CMD_SEND_COLOR           0x00008000
+#define BCI_CMD_DEST_GBD             0x00000000
+#define BCI_CMD_SRC_GBD              0x00000020
+#define BCI_CMD_SRC_SOLID            0x00000000
+#define BCI_CMD_SRC_MONO             0x00000060
+#define BCI_CMD_CLIP_NEW             0x00006000
+#define BCI_CMD_CLIP_LR              0x00004000
+
+#define BCI_CLIP_LR(l, r)            ((((r) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_TL(t, l)            ((((t) << 16) | (l)) & 0x0FFF0FFF)
+#define BCI_CLIP_BR(b, r)            ((((b) << 16) | (r)) & 0x0FFF0FFF)
+#define BCI_W_H(w, h)                (((h) << 16) | ((w) & 0xFFF))
+#define BCI_X_Y(x, y)                (((y) << 16) | ((x) & 0xFFF))
+
+#define BCI_GBD1                     0xE0
+#define BCI_GBD2                     0xE1
+
+#define BCI_BUFFER_OFFSET            0x10000
+#define BCI_SIZE                     0x4000
+
+#define BCI_SEND(dw)                 writel(dw, par->bci_base + par->bci_ptr++)
+
+#define BCI_CMD_GET_ROP(cmd)         (((cmd) >> 16) & 0xFF)
+#define BCI_CMD_SET_ROP(cmd, rop)    ((cmd) |= ((rop & 0xFF) << 16))
+#define BCI_CMD_SEND_COLOR           0x00008000
+
+struct xtimings {
+	unsigned int Clock;
+	unsigned int HDisplay;
+	unsigned int HSyncStart;
+	unsigned int HSyncEnd;
+	unsigned int HTotal;
+	unsigned int HAdjusted;
+	unsigned int VDisplay;
+	unsigned int VSyncStart;
+	unsigned int VSyncEnd;
+	unsigned int VTotal;
+	unsigned int sync;
+	int	       dblscan;
+	int	       interlaced;
+};
+
+
+/* --------------------------------------------------------------------- */
+
+#define NR_PALETTE	256
+
+
+struct savagefb_par;
+
+struct savagefb_i2c_chan {
+	struct savagefb_par *par;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+	volatile u8 __iomem *ioaddr;
+	u32   reg;
+};
+
+struct savagefb_par {
+	struct pci_dev *pcidev;
+	savage_chipset  chip;
+	struct savagefb_i2c_chan chan;
+	unsigned char   *edid;
+	u32 pseudo_palette[16];
+	int dacSpeedBpp;
+	int maxClock;
+	int minClock;
+	int numClocks;
+	int clock[4];
+	struct {
+		u8   __iomem *vbase;
+		u32    pbase;
+		u32    len;
+#ifdef CONFIG_MTRR
+		int    mtrr;
+#endif
+	} video;
+
+	struct {
+		volatile u8  __iomem *vbase;
+		u32           pbase;
+		u32           len;
+	} mmio;
+
+	volatile u32  __iomem *bci_base;
+	unsigned int  bci_ptr;
+
+	u32           cob_offset;
+	u32           cob_size;
+	int           cob_index;
+
+	void (*SavageWaitIdle) (struct savagefb_par *par);
+	void (*SavageWaitFifo) (struct savagefb_par *par, int space);
+
+	int MCLK, REFCLK, LCDclk;
+	int HorizScaleFactor;
+
+	/* Panels size */
+	int SavagePanelWidth;
+	int SavagePanelHeight;
+
+	struct {
+		u16 red, green, blue, transp;
+	} palette[NR_PALETTE];
+
+	int depth;
+	int vwidth;
+
+	unsigned char MiscOutReg;     /* Misc */
+	unsigned char CRTC[25];       /* Crtc Controller */
+	unsigned char Sequencer[5];   /* Video Sequencer */
+	unsigned char Graphics[9];    /* Video Graphics */
+	unsigned char Attribute[21];  /* Video Atribute */
+
+	unsigned int mode, refresh;
+	unsigned char SR08, SR0E, SR0F;
+	unsigned char SR10, SR11, SR12, SR13, SR15, SR18, SR29, SR30;
+	unsigned char SR54[8];
+	unsigned char Clock;
+	unsigned char CR31, CR32, CR33, CR34, CR36, CR3A, CR3B, CR3C;
+	unsigned char CR40, CR41, CR42, CR43, CR45;
+	unsigned char CR50, CR51, CR53, CR55, CR58, CR5B, CR5D, CR5E;
+	unsigned char CR60, CR63, CR65, CR66, CR67, CR68, CR69, CR6D, CR6F;
+	unsigned char CR86, CR88;
+	unsigned char CR90, CR91, CRB0;
+	unsigned int  STREAMS[22];	/* yuck, streams regs */
+	unsigned int  MMPR0, MMPR1, MMPR2, MMPR3;
+};
+
+#define BCI_BD_BW_DISABLE            0x10000000
+#define BCI_BD_SET_BPP(bd, bpp)      ((bd) |= (((bpp) & 0xFF) << 16))
+#define BCI_BD_SET_STRIDE(bd, st)    ((bd) |= ((st) & 0xFFFF))
+
+
+/* IO functions */
+
+#define  vga_in8(addr)         (inb (addr))
+#define vga_in16(addr)         (inw (addr))
+#define vga_in32(addr)         (inl (addr))
+
+#define  vga_out8(addr,val)    (outb ((val), (addr)))
+#define vga_out16(addr,val)    (outw ((val), (addr)))
+#define vga_out32(addr,val)    (outl ((val), (addr)))
+
+#define savage_in16(addr)      readw(par->mmio.vbase + (addr))
+#define savage_in32(addr)      readl(par->mmio.vbase + (addr))
+
+#define savage_out16(addr,val) writew((val), par->mmio.vbase + (addr))
+#define savage_out32(addr,val) writel((val), par->mmio.vbase + (addr))
+
+static inline u8 VGArCR (u8 index)
+{
+  outb (index, 0x3d4);
+  return inb (0x3d5);
+}
+
+static inline u8 VGArGR (u8 index)
+{
+  outb (index, 0x3ce);
+  return inb (0x3cf);
+}
+
+static inline u8 VGArSEQ (u8 index)
+{
+  outb (index, 0x3c4);
+  return inb (0x3c5);
+}
+
+#define VGAwCR(index, val) \
+do {                       \
+  vga_out8 (0x3d4, index); \
+  vga_out8 (0x3d5, val);   \
+} while (0)
+
+#define VGAwGR(index, val) \
+do {                       \
+  vga_out8 (0x3ce, index); \
+  vga_out8 (0x3cf, val);   \
+} while (0)
+
+#define VGAwSEQ(index, val) \
+do {                        \
+  vga_out8 (0x3c4, index);  \
+  vga_out8 (0x3c5, val);    \
+} while (0)
+
+#define VGAenablePalette() \
+do {                       \
+  u8 tmp;                  \
+                           \
+  tmp = vga_in8 (0x3da);   \
+  vga_out8 (0x3c0, 0x00);  \
+  paletteEnabled = 1;      \
+} while (0)
+
+#define VGAdisablePalette() \
+do {                        \
+  u8 tmp;                   \
+                            \
+  tmp = vga_in8 (0x3da);    \
+  vga_out8 (0x3c0, 0x20);   \
+  paletteEnabled = 0;       \
+} while (0)
+
+#define VGAwATTR(index, value) \
+do {                           \
+  u8 tmp;                      \
+                               \
+  if (paletteEnabled)          \
+    index &= ~0x20;            \
+  else                         \
+    index |= 0x20;             \
+                               \
+  tmp = vga_in8 (0x3da);       \
+  vga_out8 (0x3c0, index);     \
+  vga_out8 (0x3c0, value);     \
+} while (0)
+
+#define VGAwMISC(value)    \
+do {                       \
+  vga_out8 (0x3c2, value); \
+} while (0)
+
+#ifndef CONFIG_FB_SAVAGE_ACCEL
+#define savagefb_set_clip(x)
+#endif
+
+#define VerticalRetraceWait() \
+{ \
+	vga_out8 (0x3d4, 0x17); \
+	if (vga_in8 (0x3d5) & 0x80) { \
+		while ((vga_in8(0x3da) & 0x08) == 0x08) ; \
+		while ((vga_in8(0x3da) & 0x08) == 0x00) ; \
+	} \
+}
+
+extern int savagefb_probe_i2c_connector(struct savagefb_par *par,
+					u8 **out_edid);
+extern void savagefb_create_i2c_busses(struct fb_info *info);
+extern void savagefb_delete_i2c_busses(struct fb_info *info);
+extern int  savagefb_sync(struct fb_info *info);
+extern void savagefb_copyarea(struct fb_info *info,
+			      const struct fb_copyarea *region);
+extern void savagefb_fillrect(struct fb_info *info,
+			      const struct fb_fillrect *rect);
+extern void savagefb_imageblit(struct fb_info *info,
+			       const struct fb_image *image);
+
+
+#endif /* __SAVAGEFB_H__ */
diff -Nru a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/savage/savagefb_accel.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,140 @@
+/*-*- linux-c -*-
+ *  linux/drivers/video/savage/savage_accel.c -- Hardware Acceleration
+ *
+ *      Copyright (C) 2004 Antonino Daplas<adaplas@pol.net>
+ *      All Rights Reserved
+ *
+ *  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/string.h>
+#include <linux/fb.h>
+
+#include "savagefb.h"
+
+static u32 savagefb_rop[] = {
+	0xCC, /* ROP_COPY */
+	0x5A  /* ROP_XOR  */
+};
+
+int savagefb_sync(struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	par->SavageWaitIdle(par);
+	return 0;
+}
+EXPORT_SYMBOL(savagefb_sync);
+
+void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int sx = region->sx, dx = region->dx;
+	int sy = region->sy, dy = region->dy;
+	int cmd;
+
+	if (!region->width || !region->height)
+		return;
+	par->bci_ptr = 0;
+	cmd = BCI_CMD_RECT | BCI_CMD_DEST_GBD | BCI_CMD_SRC_GBD;
+	BCI_CMD_SET_ROP(cmd, savagefb_rop[0]);
+
+	if (dx <= sx) {
+		cmd |= BCI_CMD_RECT_XP;
+	} else {
+		sx += region->width - 1;
+		dx += region->width - 1;
+	}
+
+	if (dy <= sy) {
+		cmd |= BCI_CMD_RECT_YP;
+	} else {
+		sy += region->height - 1;
+		dy += region->height - 1;
+	}
+
+	par->SavageWaitFifo(par,4);
+	BCI_SEND(cmd);
+	BCI_SEND(BCI_X_Y(sx, sy));
+	BCI_SEND(BCI_X_Y(dx, dy));
+	BCI_SEND(BCI_W_H(region->width, region->height));
+}
+EXPORT_SYMBOL(savagefb_copyarea);
+
+void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int cmd, color;
+
+	if (!rect->width || !rect->height)
+		return;
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+		color = rect->color;
+	else
+		color = ((u32 *)info->pseudo_palette)[rect->color];
+
+	cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+	      BCI_CMD_DEST_GBD | BCI_CMD_SRC_SOLID |
+	      BCI_CMD_SEND_COLOR;
+
+	par->bci_ptr = 0;
+	BCI_CMD_SET_ROP(cmd, savagefb_rop[rect->rop]);
+
+	par->SavageWaitFifo(par,4);
+	BCI_SEND(cmd);
+	BCI_SEND(color);
+	BCI_SEND( BCI_X_Y(rect->dx, rect->dy) );
+	BCI_SEND( BCI_W_H(rect->width, rect->height) );
+}
+EXPORT_SYMBOL(savagefb_fillrect);
+
+void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int fg, bg, size, i, width;
+	int cmd;
+	u32 *src = (u32 *) image->data;
+
+	if (!image->width || !image->height)
+		return;
+
+	if (image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		fg = image->fg_color;
+		bg = image->bg_color;
+	} else {
+		fg = ((u32 *)info->pseudo_palette)[image->fg_color];
+		bg = ((u32 *)info->pseudo_palette)[image->bg_color];
+	}
+
+	cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |
+	      BCI_CMD_CLIP_LR | BCI_CMD_DEST_GBD | BCI_CMD_SRC_MONO |
+	      BCI_CMD_SEND_COLOR;
+
+	par->bci_ptr = 0;
+	BCI_CMD_SET_ROP(cmd, savagefb_rop[0]);
+
+	width = (image->width + 31) & ~31;
+	size = (width * image->height)/8;
+	size >>= 2;
+
+	par->SavageWaitFifo(par, size + 5);
+	BCI_SEND(cmd);
+	BCI_SEND(BCI_CLIP_LR(image->dx, image->dx + image->width - 1));
+	BCI_SEND(fg);
+	BCI_SEND(bg);
+	BCI_SEND(BCI_X_Y(image->dx, image->dy));
+	BCI_SEND(BCI_W_H(width, image->height));
+	for (i = 0; i < size; i++)
+		BCI_SEND(src[i]);
+}
+EXPORT_SYMBOL(savagefb_imageblit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
--- a/drivers/video/skeletonfb.c	2004-10-28 22:25:57 -07:00
+++ b/drivers/video/skeletonfb.c	2004-10-28 22:25:57 -07:00
@@ -477,6 +477,28 @@
  *		Used internally by the driver.	 
  *      @hot:	The hot spot. 
  *	@image:	The actual data for the cursor image.
+ *
+ *      NOTES ON FLAGS (cursor->set):
+ *
+ *      FB_CUR_SETIMAGE - the cursor image has changed (cursor->image.data)
+ *      FB_CUR_SETPOS   - the cursor position has changed (cursor->image.dx|dy)
+ *      FB_CUR_SETHOT   - the cursor hot spot has changed (cursor->hot.dx|dy)
+ *      FB_CUR_SETCMAP  - the cursor colors has changed (cursor->fg_color|bg_color)
+ *      FB_CUR_SETSHAPE - the cursor bitmask has changed (cursor->mask)
+ *      FB_CUR_SETSIZE  - the cursor size has changed (cursor->width|height)
+ *      FB_CUR_SETALL   - everything has changed
+ *
+ *      NOTES ON ROPs (cursor->rop, Raster Operation)
+ *
+ *      ROP_XOR         - cursor->image.data XOR cursor->mask
+ *      ROP_COPY        - curosr->image.data AND cursor->mask
+ *
+ *      OTHER NOTES:
+ *
+ *      - fbcon only supports a 2-color cursor (cursor->image.depth = 1)
+ *      - The fb_cursor structure, @cursor, _will_ always contain valid
+ *        fields, whether any particular bitfields in cursor->set is set
+ *        or not.
  */
 }
 
@@ -529,6 +551,17 @@
 {
     int cmap_len, retval;	
    
+    /*
+     *  For kernel boot options (in 'video=xxxfb:<options>' format)
+     */
+#ifndef MODULE
+    char *option = NULL;
+
+    if (fb_get_options("xxxfb", &option))
+	    return -ENODEV;
+    xxxfb_setup(option);
+#endif
+
     /* 
      * Here we set the screen_base to the vitrual memory address
      * for the framebuffer. Usually we obtain the resource address
@@ -582,17 +615,6 @@
 
 static void __exit xxxfb_cleanup(void)
 {
-    /*
-     *  For kernel boot options (in 'video=xxxfb:<options>' format)
-     */
-#ifndef MODULE
-    char *option = NULL;
-
-    if (fb_get_options("xxxfb", &option))
-	    return -ENODEV;
-    xxxfb_setup(option);
-#endif
-
     /*
      *  If your driver supports multiple boards, you should unregister and
      *  clean up all instances.
diff -Nru a/drivers/video/softcursor.c b/drivers/video/softcursor.c
--- a/drivers/video/softcursor.c	2004-10-28 22:25:58 -07:00
+++ b/drivers/video/softcursor.c	2004-10-28 22:25:58 -07:00
@@ -19,79 +19,53 @@
 
 int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
-	unsigned int scan_align = info->sprite.scan_align - 1;
-	unsigned int buf_align = info->sprite.buf_align - 1;
+	unsigned int scan_align = info->pixmap.scan_align - 1;
+	unsigned int buf_align = info->pixmap.buf_align - 1;
 	unsigned int i, size, dsize, s_pitch, d_pitch;
-	struct fb_cursor *cur;
+	struct fb_image *image;
 	u8 *dst, *src;
 
-	if (cursor->set & FB_CUR_SETSIZE) {
-		info->cursor.image.height = cursor->image.height;
-		info->cursor.image.width = cursor->image.width;
-	}
-
-	if (cursor->set & FB_CUR_SETPOS) {
-		info->cursor.image.dx = cursor->image.dx;
-		info->cursor.image.dy = cursor->image.dy;
-	}
-
-	if (cursor->set & FB_CUR_SETHOT)
-		info->cursor.hot = cursor->hot;
-	
-	if (cursor->set & FB_CUR_SETCMAP) {
-		if (cursor->image.depth == 1) {
-			info->cursor.image.bg_color = cursor->image.bg_color;
-			info->cursor.image.fg_color = cursor->image.fg_color;
-		} else {
-			if (cursor->image.cmap.len)
-				fb_copy_cmap(&cursor->image.cmap, &info->cursor.image.cmap);
-		}
-		info->cursor.image.depth = cursor->image.depth;
-	}	
-
-	info->cursor.image.data = cursor->image.data;
-
 	if (info->state != FBINFO_STATE_RUNNING)
 		return 0;
 
-	src = kmalloc(64 + sizeof(struct fb_cursor), GFP_ATOMIC);
+	src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
+
 	if (!src)
 		return -ENOMEM;
-	cur = (struct fb_cursor *) (src + 64);
-	*cur = info->cursor;
 
-	s_pitch = (info->cursor.image.width + 7) >> 3;
-	dsize = s_pitch * info->cursor.image.height;
+	image = (struct fb_image *) (src + 64);
+	*image = cursor->image;
+	s_pitch = (image->width + 7) >> 3;
+	dsize = s_pitch * image->height;
 	d_pitch = (s_pitch + scan_align) & ~scan_align;
-	size = d_pitch * info->cursor.image.height + buf_align;
+	size = d_pitch * image->height + buf_align;
 	size &= ~buf_align;
-	dst = fb_get_buffer_offset(info, &info->sprite, size);
+	dst = fb_get_buffer_offset(info, &info->pixmap, size);
 
-	if (info->cursor.enable) {
-		switch (info->cursor.rop) {
+	if (cursor->enable) {
+		switch (cursor->rop) {
 		case ROP_XOR:
 			for (i = 0; i < dsize; i++)
-				src[i] = cursor->image.data[i] ^ info->cursor.mask[i]; 
+				src[i] = image->data[i] ^ cursor->mask[i];
 			break;
 		case ROP_COPY:
 		default:
 			for (i = 0; i < dsize; i++)
-				src[i] = cursor->image.data[i] & info->cursor.mask[i];
+				src[i] = image->data[i] & cursor->mask[i];
 			break;
 		}
 	} else 
-		memcpy(src, cursor->image.data, dsize);
+		memcpy(src, image->data, dsize);
 	
-	if (info->sprite.outbuf)
-		fb_iomove_buf_aligned(info, &info->sprite, dst, d_pitch, src,
-				  s_pitch, info->cursor.image.height);
+	if (info->pixmap.outbuf)
+		fb_iomove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
+				  s_pitch, image->height);
 	else
-		fb_sysmove_buf_aligned(info, &info->sprite, dst, d_pitch, src,
-				   s_pitch, info->cursor.image.height);
-	cur->image.data = dst;
-	
-	info->fbops->fb_imageblit(info, &cur->image);
+		fb_sysmove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
+				   s_pitch, image->height);
 
+	image->data = dst;
+	info->fbops->fb_imageblit(info, image);
 	kfree(src);
 
 	return 0;
diff -Nru a/fs/char_dev.c b/fs/char_dev.c
--- a/fs/char_dev.c	2004-10-28 22:25:57 -07:00
+++ b/fs/char_dev.c	2004-10-28 22:25:57 -07:00
@@ -207,8 +207,8 @@
 
 	cdev->owner = fops->owner;
 	cdev->ops = fops;
-	strcpy(cdev->kobj.name, name);
-	for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/'))
+	kobject_set_name(&cdev->kobj, "%s", name);
+	for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/'))
 		*s = '!';
 		
 	err = cdev_add(cdev, MKDEV(cd->major, 0), 256);
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	2004-10-28 22:25:57 -07:00
+++ b/fs/dcache.c	2004-10-28 22:25:57 -07:00
@@ -743,6 +743,16 @@
 	return dentry;
 }
 
+struct dentry *d_alloc_name(struct dentry *parent, const char *name)
+{
+	struct qstr q;
+
+	q.name = name;
+	q.len = strlen(name);
+	q.hash = full_name_hash(q.name, q.len);
+	return d_alloc(parent, &q);
+}
+
 /**
  * d_instantiate - fill in inode information for a dentry
  * @entry: dentry to complete
diff -Nru a/fs/dquot.c b/fs/dquot.c
--- a/fs/dquot.c	2004-10-28 22:25:58 -07:00
+++ b/fs/dquot.c	2004-10-28 22:25:58 -07:00
@@ -811,22 +811,22 @@
 	tty_write_message(current->signal->tty, quotatypes[dquot->dq_type]);
 	switch (warntype) {
 		case IHARDWARN:
-			msg = " file limit reached.\n";
+			msg = " file limit reached.\r\n";
 			break;
 		case ISOFTLONGWARN:
-			msg = " file quota exceeded too long.\n";
+			msg = " file quota exceeded too long.\r\n";
 			break;
 		case ISOFTWARN:
-			msg = " file quota exceeded.\n";
+			msg = " file quota exceeded.\r\n";
 			break;
 		case BHARDWARN:
-			msg = " block limit reached.\n";
+			msg = " block limit reached.\r\n";
 			break;
 		case BSOFTLONGWARN:
-			msg = " block quota exceeded too long.\n";
+			msg = " block quota exceeded too long.\r\n";
 			break;
 		case BSOFTWARN:
-			msg = " block quota exceeded.\n";
+			msg = " block quota exceeded.\r\n";
 			break;
 	}
 	tty_write_message(current->signal->tty, msg);
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	2004-10-28 22:25:57 -07:00
+++ b/fs/exec.c	2004-10-28 22:25:57 -07:00
@@ -984,7 +984,7 @@
  */
 int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 {
-	int try,retval=0;
+	int try,retval;
 	struct linux_binfmt *fmt;
 #ifdef __alpha__
 	/* handle /sbin/loader.. */
@@ -1028,6 +1028,7 @@
 	/* kernel module loader fixup */
 	/* so we don't try to load run modprobe in kernel space. */
 	set_fs(USER_DS);
+	retval = -ENOENT;
 	for (try=0; try<2; try++) {
 		read_lock(&binfmt_lock);
 		for (fmt = formats ; fmt ; fmt = fmt->next) {
@@ -1411,7 +1412,8 @@
 
 	retval = binfmt->core_dump(signr, regs, file);
 
-	current->signal->group_exit_code |= 0x80;
+	if (retval)
+		current->signal->group_exit_code |= 0x80;
 close_fail:
 	filp_close(file, NULL);
 fail_unlock:
diff -Nru a/fs/ext2/ext2.h b/fs/ext2/ext2.h
--- a/fs/ext2/ext2.h	2004-10-28 22:25:59 -07:00
+++ b/fs/ext2/ext2.h	2004-10-28 22:25:59 -07:00
@@ -116,7 +116,6 @@
 /* inode.c */
 extern void ext2_read_inode (struct inode *);
 extern int ext2_write_inode (struct inode *, int);
-extern void ext2_put_inode (struct inode *);
 extern void ext2_delete_inode (struct inode *);
 extern int ext2_sync_inode (struct inode *);
 extern void ext2_discard_prealloc (struct inode *);
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	2004-10-28 22:25:56 -07:00
+++ b/fs/ext2/inode.c	2004-10-28 22:25:56 -07:00
@@ -53,19 +53,6 @@
 }
 
 /*
- * Called at each iput().
- *
- * The inode may be "bad" if ext2_read_inode() saw an error from
- * ext2_get_inode(), so we need to check that to avoid freeing random disk
- * blocks.
- */
-void ext2_put_inode(struct inode *inode)
-{
-	if (!is_bad_inode(inode))
-		ext2_discard_prealloc(inode);
-}
-
-/*
  * Called at the last iput() if i_nlink is zero.
  */
 void ext2_delete_inode (struct inode * inode)
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c	2004-10-28 22:25:58 -07:00
+++ b/fs/ext2/super.c	2004-10-28 22:25:58 -07:00
@@ -181,10 +181,9 @@
 		printk(KERN_INFO "ext2_inode_cache: not all structures were freed\n");
 }
 
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
-
 static void ext2_clear_inode(struct inode *inode)
 {
+#ifdef CONFIG_EXT2_FS_POSIX_ACL
 	struct ext2_inode_info *ei = EXT2_I(inode);
 
 	if (ei->i_acl && ei->i_acl != EXT2_ACL_NOT_CACHED) {
@@ -195,18 +194,17 @@
 		posix_acl_release(ei->i_default_acl);
 		ei->i_default_acl = EXT2_ACL_NOT_CACHED;
 	}
+#endif
+	if (!is_bad_inode(inode))
+		ext2_discard_prealloc(inode);
 }
 
-#else
-# define ext2_clear_inode NULL
-#endif
 
 static struct super_operations ext2_sops = {
 	.alloc_inode	= ext2_alloc_inode,
 	.destroy_inode	= ext2_destroy_inode,
 	.read_inode	= ext2_read_inode,
 	.write_inode	= ext2_write_inode,
-	.put_inode	= ext2_put_inode,
 	.delete_inode	= ext2_delete_inode,
 	.put_super	= ext2_put_super,
 	.write_super	= ext2_write_super,
diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c
--- a/fs/ext2/xattr.c	2004-10-28 22:25:58 -07:00
+++ b/fs/ext2/xattr.c	2004-10-28 22:25:58 -07:00
@@ -64,11 +64,6 @@
 #include "xattr.h"
 #include "acl.h"
 
-/* These symbols may be needed by a module. */
-EXPORT_SYMBOL(ext2_xattr_get);
-EXPORT_SYMBOL(ext2_xattr_list);
-EXPORT_SYMBOL(ext2_xattr_set);
-
 #define HDR(bh) ((struct ext2_xattr_header *)((bh)->b_data))
 #define ENTRY(ptr) ((struct ext2_xattr_entry *)(ptr))
 #define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
diff -Nru a/fs/fcntl.c b/fs/fcntl.c
--- a/fs/fcntl.c	2004-10-28 22:25:58 -07:00
+++ b/fs/fcntl.c	2004-10-28 22:25:58 -07:00
@@ -431,11 +431,12 @@
 };
 
 static inline int sigio_perm(struct task_struct *p,
-                             struct fown_struct *fown)
+                             struct fown_struct *fown, int sig)
 {
-	return ((fown->euid == 0) ||
- 	        (fown->euid == p->suid) || (fown->euid == p->uid) ||
- 	        (fown->uid == p->suid) || (fown->uid == p->uid));
+	return (((fown->euid == 0) ||
+		 (fown->euid == p->suid) || (fown->euid == p->uid) ||
+		 (fown->uid == p->suid) || (fown->uid == p->uid)) &&
+		!security_file_send_sigiotask(p, fown, sig));
 }
 
 static void send_sigio_to_task(struct task_struct *p,
@@ -443,10 +444,7 @@
 			       int fd,
 			       int reason)
 {
-	if (!sigio_perm(p, fown))
-		return;
-
-	if (security_file_send_sigiotask(p, fown, fd, reason))
+	if (!sigio_perm(p, fown, fown->signum))
 		return;
 
 	switch (fown->signum) {
@@ -508,7 +506,7 @@
 static void send_sigurg_to_task(struct task_struct *p,
                                 struct fown_struct *fown)
 {
-	if (sigio_perm(p, fown))
+	if (sigio_perm(p, fown, SIGURG))
 		send_group_sig_info(SIGURG, SEND_SIG_PRIV, p);
 }
 
diff -Nru a/fs/hfs/Makefile b/fs/hfs/Makefile
--- a/fs/hfs/Makefile	2004-10-28 22:25:59 -07:00
+++ b/fs/hfs/Makefile	2004-10-28 22:25:59 -07:00
@@ -5,6 +5,6 @@
 obj-$(CONFIG_HFS_FS) += hfs.o
 
 hfs-objs := bitmap.o bfind.o bnode.o brec.o btree.o \
-	    catalog.o dir.o extent.o inode.o mdb.o \
+	    catalog.o dir.o extent.o inode.o attr.o mdb.o \
             part_tbl.o string.o super.o sysdep.o trans.o
 
diff -Nru a/fs/hfs/attr.c b/fs/hfs/attr.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/hfs/attr.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,121 @@
+/*
+ *  linux/fs/hfs/attr.c
+ *
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ *
+ * Export hfs data via xattr
+ */
+
+
+#include <linux/fs.h>
+#include <linux/xattr.h>
+
+#include "hfs_fs.h"
+#include "btree.h"
+
+int hfs_setxattr(struct dentry *dentry, const char *name,
+		 const void *value, size_t size, int flags)
+{
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	hfs_cat_rec rec;
+	struct hfs_cat_file *file;
+	int res;
+
+	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
+	if (res)
+		return res;
+	fd.search_key->cat = HFS_I(inode)->cat_key;
+	res = hfs_brec_find(&fd);
+	if (res)
+		goto out;
+	hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
+			sizeof(struct hfs_cat_file));
+	file = &rec.file;
+
+	if (!strcmp(name, "hfs.type")) {
+		if (size == 4)
+			memcpy(&file->UsrWds.fdType, value, 4);
+		else
+			res = -ERANGE;
+	} else if (!strcmp(name, "hfs.creator")) {
+		if (size == 4)
+			memcpy(&file->UsrWds.fdCreator, value, 4);
+		else
+			res = -ERANGE;
+	} else
+		res = -EOPNOTSUPP;
+	if (!res)
+		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
+				sizeof(struct hfs_cat_file));
+out:
+	hfs_find_exit(&fd);
+	return res;
+}
+
+ssize_t hfs_getxattr(struct dentry *dentry, const char *name,
+			 void *value, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	hfs_cat_rec rec;
+	struct hfs_cat_file *file;
+	ssize_t res = 0;
+
+	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	if (size) {
+		res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
+		if (res)
+			return res;
+		fd.search_key->cat = HFS_I(inode)->cat_key;
+		res = hfs_brec_find(&fd);
+		if (res)
+			goto out;
+		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
+				sizeof(struct hfs_cat_file));
+	}
+	file = &rec.file;
+
+	if (!strcmp(name, "hfs.type")) {
+		if (size >= 4) {
+			memcpy(value, &file->UsrWds.fdType, 4);
+			res = 4;
+		} else
+			res = size ? -ERANGE : 4;
+	} else if (!strcmp(name, "hfs.creator")) {
+		if (size >= 4) {
+			memcpy(value, &file->UsrWds.fdCreator, 4);
+			res = 4;
+		} else
+			res = size ? -ERANGE : 4;
+	} else
+		res = -ENODATA;
+out:
+	if (size)
+		hfs_find_exit(&fd);
+	return res;
+}
+
+#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
+
+ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	if (!buffer || !size)
+		return HFS_ATTRLIST_SIZE;
+	if (size < HFS_ATTRLIST_SIZE)
+		return -ERANGE;
+	strcpy(buffer, "hfs.type");
+	strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
+
+	return HFS_ATTRLIST_SIZE;
+}
diff -Nru a/fs/hfs/btree.c b/fs/hfs/btree.c
--- a/fs/hfs/btree.c	2004-10-28 22:25:57 -07:00
+++ b/fs/hfs/btree.c	2004-10-28 22:25:57 -07:00
@@ -201,10 +201,12 @@
 		res = hfs_extend_file(inode);
 		if (res)
 			return ERR_PTR(res);
-		inode->i_blocks = HFS_I(inode)->alloc_blocks *
-				  HFS_SB(tree->sb)->fs_div;
 		HFS_I(inode)->phys_size = inode->i_size =
-			(loff_t)inode->i_blocks << tree->sb->s_blocksize_bits;
+				(loff_t)HFS_I(inode)->alloc_blocks *
+				HFS_SB(tree->sb)->alloc_blksz;
+		HFS_I(inode)->fs_blocks = inode->i_size >>
+					  tree->sb->s_blocksize_bits;
+		inode_set_bytes(inode, inode->i_size);
 		count = inode->i_size >> tree->node_size_shift;
 		tree->free_nodes = count - tree->node_count;
 		tree->node_count = count;
diff -Nru a/fs/hfs/dir.c b/fs/hfs/dir.c
--- a/fs/hfs/dir.c	2004-10-28 22:25:59 -07:00
+++ b/fs/hfs/dir.c	2004-10-28 22:25:59 -07:00
@@ -306,6 +306,9 @@
 	res = hfs_cat_move(old_dentry->d_inode->i_ino,
 			   old_dir, &old_dentry->d_name,
 			   new_dir, &new_dentry->d_name);
+	if (!res)
+		hfs_cat_build_key((btree_key *)&HFS_I(old_dentry->d_inode)->cat_key,
+				  new_dir->i_ino, &new_dentry->d_name);
 	return res;
 }
 
diff -Nru a/fs/hfs/extent.c b/fs/hfs/extent.c
--- a/fs/hfs/extent.c	2004-10-28 22:25:58 -07:00
+++ b/fs/hfs/extent.c	2004-10-28 22:25:58 -07:00
@@ -328,8 +328,8 @@
 	/* Convert inode block to disk allocation block */
 	ablock = (u32)block / HFS_SB(sb)->fs_div;
 
-	if (block >= inode->i_blocks) {
-		if (block > inode->i_blocks || !create)
+	if (block >= HFS_I(inode)->fs_blocks) {
+		if (block > HFS_I(inode)->fs_blocks || !create)
 			return -EIO;
 		if (ablock >= HFS_I(inode)->alloc_blocks) {
 			res = hfs_extend_file(inode);
@@ -363,7 +363,8 @@
 	if (create) {
 		set_buffer_new(bh_result);
 		HFS_I(inode)->phys_size += sb->s_blocksize;
-		inode->i_blocks++;
+		HFS_I(inode)->fs_blocks++;
+		inode_add_bytes(inode, sb->s_blocksize);
 		mark_inode_dirty(inode);
 	}
 	return 0;
@@ -521,6 +522,7 @@
 	HFS_I(inode)->alloc_blocks = blk_cnt;
 out:
 	HFS_I(inode)->phys_size = inode->i_size;
+	HFS_I(inode)->fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits);
 	mark_inode_dirty(inode);
-	inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 }
diff -Nru a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
--- a/fs/hfs/hfs_fs.h	2004-10-28 22:25:58 -07:00
+++ b/fs/hfs/hfs_fs.h	2004-10-28 22:25:58 -07:00
@@ -60,6 +60,7 @@
 	struct semaphore extents_lock;
 
 	u16 alloc_blocks, clump_blocks;
+	sector_t fs_blocks;
 	/* Allocation extents from catlog record or volume header */
 	hfs_extent_rec first_extents;
 	u16 first_blocks;
@@ -205,6 +206,13 @@
 extern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *);
 extern void hfs_clear_inode(struct inode *);
 extern void hfs_delete_inode(struct inode *);
+
+/* attr.c */
+extern int hfs_setxattr(struct dentry *dentry, const char *name,
+			const void *value, size_t size, int flags);
+extern ssize_t hfs_getxattr(struct dentry *dentry, const char *name,
+			    void *value, size_t size);
+extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
 
 /* mdb.c */
 extern int hfs_mdb_get(struct super_block *);
diff -Nru a/fs/hfs/inode.c b/fs/hfs/inode.c
--- a/fs/hfs/inode.c	2004-10-28 22:25:59 -07:00
+++ b/fs/hfs/inode.c	2004-10-28 22:25:59 -07:00
@@ -170,8 +170,10 @@
 	inode->i_gid = current->fsgid;
 	inode->i_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_blksize = HFS_SB(sb)->alloc_blksz;
 	HFS_I(inode)->flags = 0;
 	HFS_I(inode)->rsrc_inode = NULL;
+	HFS_I(inode)->fs_blocks = 0;
 	if (S_ISDIR(inode->i_mode)) {
 		inode->i_size = 2;
 		HFS_SB(sb)->folder_count++;
@@ -243,7 +245,8 @@
 	HFS_I(inode)->first_blocks = count;
 
 	inode->i_size = HFS_I(inode)->phys_size = log_size;
-	inode->i_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	HFS_I(inode)->fs_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	inode_set_bytes(inode, HFS_I(inode)->fs_blocks << sb->s_blocksize_bits);
 	HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) /
 				     HFS_SB(sb)->alloc_blksz;
 	HFS_I(inode)->clump_blocks = clump_size / HFS_SB(sb)->alloc_blksz;
@@ -291,6 +294,7 @@
 	inode->i_uid = hsb->s_uid;
 	inode->i_gid = hsb->s_gid;
 	inode->i_nlink = 1;
+	inode->i_blksize = HFS_SB(inode->i_sb)->alloc_blksz;
 
 	if (idata->key)
 		HFS_I(inode)->cat_key = *idata->key;
@@ -320,15 +324,14 @@
 		inode->i_op = &hfs_file_inode_operations;
 		inode->i_fop = &hfs_file_operations;
 		inode->i_mapping->a_ops = &hfs_aops;
-		HFS_I(inode)->phys_size = inode->i_size;
 		break;
 	case HFS_CDR_DIR:
 		inode->i_ino = be32_to_cpu(rec->dir.DirID);
-		inode->i_blocks = 0;
 		inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
+		HFS_I(inode)->fs_blocks = 0;
 		inode->i_mode = S_IFDIR | (S_IRWXUGO & hsb->s_dir_umask);
 		inode->i_ctime = inode->i_atime = inode->i_mtime =
-				hfs_m_to_utime(rec->file.MdDat);
+				hfs_m_to_utime(rec->dir.MdDat);
 		inode->i_op = &hfs_dir_inode_operations;
 		inode->i_fop = &hfs_dir_operations;
 		break;
@@ -383,6 +386,7 @@
 
 int hfs_write_inode(struct inode *inode, int unused)
 {
+	struct inode *main_inode = inode;
 	struct hfs_find_data fd;
 	hfs_cat_rec rec;
 
@@ -405,24 +409,22 @@
 		}
 	}
 
-	if (HFS_IS_RSRC(inode)) {
-		mark_inode_dirty(HFS_I(inode)->rsrc_inode);
-		return 0;
-	}
+	if (HFS_IS_RSRC(inode))
+		main_inode = HFS_I(inode)->rsrc_inode;
 
-	if (!inode->i_nlink)
+	if (!main_inode->i_nlink)
 		return 0;
 
-	if (hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd))
+	if (hfs_find_init(HFS_SB(main_inode->i_sb)->cat_tree, &fd))
 		/* panic? */
 		return -EIO;
 
-	fd.search_key->cat = HFS_I(inode)->cat_key;
+	fd.search_key->cat = HFS_I(main_inode)->cat_key;
 	if (hfs_brec_find(&fd))
 		/* panic? */
 		goto out;
 
-	if (S_ISDIR(inode->i_mode)) {
+	if (S_ISDIR(main_inode->i_mode)) {
 		if (fd.entrylength < sizeof(struct hfs_cat_dir))
 			/* panic? */;
 		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
@@ -436,6 +438,13 @@
 
 		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
 			    sizeof(struct hfs_cat_dir));
+	} else if (HFS_IS_RSRC(inode)) {
+		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
+			       sizeof(struct hfs_cat_file));
+		hfs_inode_write_fork(inode, rec.file.RExtRec,
+				     &rec.file.RLgLen, &rec.file.RPyLen);
+		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
+				sizeof(struct hfs_cat_file));
 	} else {
 		if (fd.entrylength < sizeof(struct hfs_cat_file))
 			/* panic? */;
@@ -450,9 +459,6 @@
 		else
 			rec.file.Flags |= HFS_FIL_LOCK;
 		hfs_inode_write_fork(inode, rec.file.ExtRec, &rec.file.LgLen, &rec.file.PyLen);
-		if (HFS_I(inode)->rsrc_inode)
-			hfs_inode_write_fork(HFS_I(inode)->rsrc_inode, rec.file.RExtRec,
-					     &rec.file.RLgLen, &rec.file.RPyLen);
 		rec.file.MdDat = hfs_u_to_mtime(inode->i_mtime);
 
 		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
@@ -621,4 +627,7 @@
 	.truncate	= hfs_file_truncate,
 	.setattr	= hfs_inode_setattr,
 	.permission	= hfs_permission,
+	.setxattr	= hfs_setxattr,
+	.getxattr	= hfs_getxattr,
+	.listxattr	= hfs_listxattr,
 };
diff -Nru a/fs/hfs/mdb.c b/fs/hfs/mdb.c
--- a/fs/hfs/mdb.c	2004-10-28 22:25:57 -07:00
+++ b/fs/hfs/mdb.c	2004-10-28 22:25:57 -07:00
@@ -200,8 +200,7 @@
 	}
 
 	attrib = mdb->drAtrb;
-	if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))
-	    || (attrib & cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT))) {
+	if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
 		hfs_warn("HFS-fs warning: Filesystem was not cleanly unmounted, "
 			 "running fsck.hfs is recommended.  mounting read-only.\n");
 		sb->s_flags |= MS_RDONLY;
@@ -212,8 +211,9 @@
 	}
 	if (!(sb->s_flags & MS_RDONLY)) {
 		/* Mark the volume uncleanly unmounted in case we crash */
-		mdb->drAtrb = attrib & cpu_to_be16(~HFS_SB_ATTRIB_UNMNT);
-		mdb->drAtrb = attrib | cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT);
+		attrib &= cpu_to_be16(~HFS_SB_ATTRIB_UNMNT);
+		attrib |= cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT);
+		mdb->drAtrb = attrib;
 		mdb->drWrCnt = cpu_to_be32(be32_to_cpu(mdb->drWrCnt) + 1);
 		mdb->drLsMod = hfs_mtime();
 
diff -Nru a/fs/hfs/super.c b/fs/hfs/super.c
--- a/fs/hfs/super.c	2004-10-28 22:25:57 -07:00
+++ b/fs/hfs/super.c	2004-10-28 22:25:57 -07:00
@@ -98,8 +98,7 @@
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		return 0;
 	if (!(*flags & MS_RDONLY)) {
-		if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))
-		    || (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT))) {
+		if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
 			printk("HFS-fs warning: Filesystem was not cleanly unmounted, "
 			       "running fsck.hfs is recommended.  leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
diff -Nru a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
--- a/fs/hfsplus/btree.c	2004-10-28 22:25:57 -07:00
+++ b/fs/hfsplus/btree.c	2004-10-28 22:25:57 -07:00
@@ -187,10 +187,12 @@
 		res = hfsplus_file_extend(inode);
 		if (res)
 			return ERR_PTR(res);
-		inode->i_blocks = HFSPLUS_I(inode).alloc_blocks <<
-				  HFSPLUS_SB(tree->sb).fs_shift;
 		HFSPLUS_I(inode).phys_size = inode->i_size =
-			(loff_t)inode->i_blocks << tree->sb->s_blocksize_bits;
+				(loff_t)HFSPLUS_I(inode).alloc_blocks <<
+				HFSPLUS_SB(tree->sb).alloc_blksz_shift;
+		HFSPLUS_I(inode).fs_blocks = HFSPLUS_I(inode).alloc_blocks <<
+					     HFSPLUS_SB(tree->sb).fs_shift;
+		inode_set_bytes(inode, inode->i_size);
 		count = inode->i_size >> tree->node_size_shift;
 		tree->free_nodes = count - tree->node_count;
 		tree->node_count = count;
diff -Nru a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
--- a/fs/hfsplus/extents.c	2004-10-28 22:25:56 -07:00
+++ b/fs/hfsplus/extents.c	2004-10-28 22:25:56 -07:00
@@ -183,8 +183,8 @@
 	shift = HFSPLUS_SB(sb).alloc_blksz_shift - sb->s_blocksize_bits;
 	ablock = iblock >> HFSPLUS_SB(sb).fs_shift;
 
-	if (iblock >= inode->i_blocks) {
-		if (iblock > inode->i_blocks || !create)
+	if (iblock >= HFSPLUS_I(inode).fs_blocks) {
+		if (iblock > HFSPLUS_I(inode).fs_blocks || !create)
 			return -EIO;
 		if (ablock >= HFSPLUS_I(inode).alloc_blocks) {
 			res = hfsplus_file_extend(inode);
@@ -217,7 +217,8 @@
 	if (create) {
 		set_buffer_new(bh_result);
 		HFSPLUS_I(inode).phys_size += sb->s_blocksize;
-		inode->i_blocks++;
+		HFSPLUS_I(inode).fs_blocks++;
+		inode_add_bytes(inode, sb->s_blocksize);
 		mark_inode_dirty(inode);
 	}
 	return 0;
@@ -497,6 +498,7 @@
 	HFSPLUS_I(inode).alloc_blocks = blk_cnt;
 out:
 	HFSPLUS_I(inode).phys_size = inode->i_size;
+	HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits);
 	mark_inode_dirty(inode);
-	inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 }
diff -Nru a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
--- a/fs/hfsplus/hfsplus_fs.h	2004-10-28 22:25:59 -07:00
+++ b/fs/hfsplus/hfsplus_fs.h	2004-10-28 22:25:59 -07:00
@@ -155,6 +155,7 @@
 struct hfsplus_inode_info {
 	struct semaphore extents_lock;
 	u32 clump_blocks, alloc_blocks;
+	sector_t fs_blocks;
 	/* Allocation extents from catalog record or volume header */
 	hfsplus_extent_rec first_extents;
 	u32 first_blocks;
@@ -340,6 +341,11 @@
 /* ioctl.c */
 int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 		  unsigned long arg);
+int hfsplus_setxattr(struct dentry *dentry, const char *name,
+		     const void *value, size_t size, int flags);
+ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+			 void *value, size_t size);
+ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
 
 /* options.c */
 int parse_options(char *, struct hfsplus_sb_info *);
diff -Nru a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
--- a/fs/hfsplus/inode.c	2004-10-28 22:25:57 -07:00
+++ b/fs/hfsplus/inode.c	2004-10-28 22:25:57 -07:00
@@ -301,6 +301,9 @@
 	.lookup		= hfsplus_file_lookup,
 	.truncate	= hfsplus_file_truncate,
 	.permission	= hfsplus_permission,
+	.setxattr	= hfsplus_setxattr,
+	.getxattr	= hfsplus_getxattr,
+	.listxattr	= hfsplus_listxattr,
 };
 
 struct file_operations hfsplus_file_operations = {
@@ -332,6 +335,7 @@
 	inode->i_gid = current->fsgid;
 	inode->i_nlink = 1;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_blksize = HFSPLUS_SB(sb).alloc_blksz;
 	INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
 	init_MUTEX(&HFSPLUS_I(inode).extents_lock);
 	atomic_set(&HFSPLUS_I(inode).opencnt, 0);
@@ -343,6 +347,7 @@
 	HFSPLUS_I(inode).cached_start = 0;
 	HFSPLUS_I(inode).cached_blocks = 0;
 	HFSPLUS_I(inode).phys_size = 0;
+	HFSPLUS_I(inode).fs_blocks = 0;
 	HFSPLUS_I(inode).rsrc_inode = NULL;
 	if (S_ISDIR(inode->i_mode)) {
 		inode->i_size = 2;
@@ -408,7 +413,8 @@
 
 	HFSPLUS_I(inode).alloc_blocks = be32_to_cpu(fork->total_blocks);
 	inode->i_size = HFSPLUS_I(inode).phys_size = be64_to_cpu(fork->total_size);
-	inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	HFSPLUS_I(inode).fs_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+	inode_set_bytes(inode, HFSPLUS_I(inode).fs_blocks << sb->s_blocksize_bits);
 	HFSPLUS_I(inode).clump_blocks = be32_to_cpu(fork->clump_size) >> HFSPLUS_SB(sb).alloc_blksz_shift;
 	if (!HFSPLUS_I(inode).clump_blocks)
 		HFSPLUS_I(inode).clump_blocks = HFSPLUS_IS_RSRC(inode) ? HFSPLUS_SB(sb).rsrc_clump_blocks :
@@ -432,7 +438,7 @@
 	type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
 
 	HFSPLUS_I(inode).dev = 0;
-	inode->i_blksize = PAGE_SIZE; /* Doesn't seem to be useful... */
+	inode->i_blksize = HFSPLUS_SB(inode->i_sb).alloc_blksz;
 	if (type == HFSPLUS_FOLDER) {
 		struct hfsplus_cat_folder *folder = &entry.folder;
 
@@ -446,7 +452,7 @@
 		inode->i_atime = hfsp_mt2ut(folder->access_date);
 		inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
 		inode->i_ctime = inode->i_mtime;
-		inode->i_blocks = 0;
+		HFSPLUS_I(inode).fs_blocks = 0;
 		inode->i_op = &hfsplus_dir_inode_operations;
 		inode->i_fop = &hfsplus_dir_operations;
 	} else if (type == HFSPLUS_FILE) {
@@ -486,26 +492,25 @@
 
 int hfsplus_cat_write_inode(struct inode *inode)
 {
+	struct inode *main_inode = inode;
 	struct hfs_find_data fd;
 	hfsplus_cat_entry entry;
 
-	if (HFSPLUS_IS_RSRC(inode)) {
-		mark_inode_dirty(HFSPLUS_I(inode).rsrc_inode);
-		return 0;
-	}
+	if (HFSPLUS_IS_RSRC(inode))
+		main_inode = HFSPLUS_I(inode).rsrc_inode;
 
-	if (!inode->i_nlink)
+	if (!main_inode->i_nlink)
 		return 0;
 
-	if (hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd))
+	if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb).cat_tree, &fd))
 		/* panic? */
 		return -EIO;
 
-	if (hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd))
+	if (hfsplus_find_cat(main_inode->i_sb, main_inode->i_ino, &fd))
 		/* panic? */
 		goto out;
 
-	if (S_ISDIR(inode->i_mode)) {
+	if (S_ISDIR(main_inode->i_mode)) {
 		struct hfsplus_cat_folder *folder = &entry.folder;
 
 		if (fd.entrylength < sizeof(struct hfsplus_cat_folder))
@@ -520,6 +525,13 @@
 		folder->valence = cpu_to_be32(inode->i_size - 2);
 		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
 					 sizeof(struct hfsplus_cat_folder));
+	} else if (HFSPLUS_IS_RSRC(inode)) {
+		struct hfsplus_cat_file *file = &entry.file;
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+			       sizeof(struct hfsplus_cat_file));
+		hfsplus_inode_write_fork(inode, &file->rsrc_fork);
+		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
+				sizeof(struct hfsplus_cat_file));
 	} else {
 		struct hfsplus_cat_file *file = &entry.file;
 
@@ -528,8 +540,6 @@
 		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
 					sizeof(struct hfsplus_cat_file));
 		hfsplus_inode_write_fork(inode, &file->data_fork);
-		if (HFSPLUS_I(inode).rsrc_inode)
-			hfsplus_inode_write_fork(HFSPLUS_I(inode).rsrc_inode, &file->rsrc_fork);
 		if (S_ISREG(inode->i_mode))
 			HFSPLUS_I(inode).dev = inode->i_nlink;
 		if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
diff -Nru a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
--- a/fs/hfsplus/ioctl.c	2004-10-28 22:25:57 -07:00
+++ b/fs/hfsplus/ioctl.c	2004-10-28 22:25:57 -07:00
@@ -14,6 +14,7 @@
 
 #include <linux/fs.h>
 #include <linux/sched.h>
+#include <linux/xattr.h>
 #include <asm/uaccess.h>
 #include "hfsplus_fs.h"
 
@@ -79,4 +80,109 @@
 	default:
 		return -ENOTTY;
 	}
+}
+
+int hfsplus_setxattr(struct dentry *dentry, const char *name,
+		     const void *value, size_t size, int flags)
+{
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	hfsplus_cat_entry entry;
+	struct hfsplus_cat_file *file;
+	int res;
+
+	if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
+	if (res)
+		return res;
+	res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+	if (res)
+		goto out;
+	hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+			sizeof(struct hfsplus_cat_file));
+	file = &entry.file;
+
+	if (!strcmp(name, "hfs.type")) {
+		if (size == 4)
+			memcpy(&file->user_info.fdType, value, 4);
+		else
+			res = -ERANGE;
+	} else if (!strcmp(name, "hfs.creator")) {
+		if (size == 4)
+			memcpy(&file->user_info.fdCreator, value, 4);
+		else
+			res = -ERANGE;
+	} else
+		res = -EOPNOTSUPP;
+	if (!res)
+		hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
+				sizeof(struct hfsplus_cat_file));
+out:
+	hfs_find_exit(&fd);
+	return res;
+}
+
+ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
+			 void *value, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+	struct hfs_find_data fd;
+	hfsplus_cat_entry entry;
+	struct hfsplus_cat_file *file;
+	ssize_t res = 0;
+
+	if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	if (size) {
+		res = hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
+		if (res)
+			return res;
+		res = hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd);
+		if (res)
+			goto out;
+		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+				sizeof(struct hfsplus_cat_file));
+	}
+	file = &entry.file;
+
+	if (!strcmp(name, "hfs.type")) {
+		if (size >= 4) {
+			memcpy(value, &file->user_info.fdType, 4);
+			res = 4;
+		} else
+			res = size ? -ERANGE : 4;
+	} else if (!strcmp(name, "hfs.creator")) {
+		if (size >= 4) {
+			memcpy(value, &file->user_info.fdCreator, 4);
+			res = 4;
+		} else
+			res = size ? -ERANGE : 4;
+	} else
+		res = -ENODATA;
+out:
+	if (size)
+		hfs_find_exit(&fd);
+	return res;
+}
+
+#define HFSPLUS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
+
+ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (!S_ISREG(inode->i_mode) || HFSPLUS_IS_RSRC(inode))
+		return -EOPNOTSUPP;
+
+	if (!buffer || !size)
+		return HFSPLUS_ATTRLIST_SIZE;
+	if (size < HFSPLUS_ATTRLIST_SIZE)
+		return -ERANGE;
+	strcpy(buffer, "hfs.type");
+	strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
+
+	return HFSPLUS_ATTRLIST_SIZE;
 }
diff -Nru a/fs/hfsplus/super.c b/fs/hfsplus/super.c
--- a/fs/hfsplus/super.c	2004-10-28 22:25:57 -07:00
+++ b/fs/hfsplus/super.c	2004-10-28 22:25:57 -07:00
@@ -246,8 +246,7 @@
 	if (!(*flags & MS_RDONLY)) {
 		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
 
-		if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
-		    !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+		if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
 			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
 			       "running fsck.hfsplus is recommended.  leaving read-only.\n");
 			sb->s_flags |= MS_RDONLY;
@@ -332,8 +331,7 @@
 	sb->s_op = &hfsplus_sops;
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 
-	if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
-	    !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+	if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
 		if (!silent)
 			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
 			       "running fsck.hfsplus is recommended.  mounting read-only.\n");
diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
--- a/fs/hugetlbfs/inode.c	2004-10-28 22:25:59 -07:00
+++ b/fs/hugetlbfs/inode.c	2004-10-28 22:25:59 -07:00
@@ -105,6 +105,7 @@
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
+	unsigned long start_addr;
 
 	if (len & ~HPAGE_MASK)
 		return -EINVAL;
@@ -119,12 +120,25 @@
 			return addr;
 	}
 
-	addr = ALIGN(mm->free_area_cache, HPAGE_SIZE);
+	start_addr = mm->free_area_cache;
+
+full_search:
+	addr = ALIGN(start_addr, HPAGE_SIZE);
 
 	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
 		/* At this point:  (!vma || addr < vma->vm_end). */
-		if (TASK_SIZE - len < addr)
+		if (TASK_SIZE - len < addr) {
+			/*
+			 * Start a new search - just in case we missed
+			 * some holes.
+			 */
+			if (start_addr != TASK_UNMAPPED_BASE) {
+				start_addr = TASK_UNMAPPED_BASE;
+				goto full_search;
+			}
 			return -ENOMEM;
+		}
+
 		if (!vma || addr + len <= vma->vm_start)
 			return addr;
 		addr = ALIGN(vma->vm_end, HPAGE_SIZE);
diff -Nru a/fs/libfs.c b/fs/libfs.c
--- a/fs/libfs.c	2004-10-28 22:25:56 -07:00
+++ b/fs/libfs.c	2004-10-28 22:25:56 -07:00
@@ -391,13 +391,9 @@
 		return -ENOMEM;
 	}
 	for (i = 0; !files->name || files->name[0]; i++, files++) {
-		struct qstr name;
 		if (!files->name)
 			continue;
-		name.name = files->name;
-		name.len = strlen(name.name);
-		name.hash = full_name_hash(name.name, name.len);
-		dentry = d_alloc(root, &name);
+		dentry = d_alloc_name(root, files->name);
 		if (!dentry)
 			goto out;
 		inode = new_inode(s);
@@ -530,6 +526,7 @@
 EXPORT_SYMBOL(simple_dir_inode_operations);
 EXPORT_SYMBOL(simple_dir_operations);
 EXPORT_SYMBOL(simple_empty);
+EXPORT_SYMBOL(d_alloc_name);
 EXPORT_SYMBOL(simple_fill_super);
 EXPORT_SYMBOL(simple_getattr);
 EXPORT_SYMBOL(simple_link);
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	2004-10-28 22:25:57 -07:00
+++ b/fs/namei.c	2004-10-28 22:25:57 -07:00
@@ -913,20 +913,20 @@
 	return 1;
 }
 
-int __set_fs_altroot(const char *altroot)
+void set_fs_altroot(void)
 {
+	char *emul = __emul_prefix();
 	struct nameidata nd;
 	struct vfsmount *mnt = NULL, *oldmnt;
 	struct dentry *dentry = NULL, *olddentry;
 	int err;
-	if (!altroot)
+
+	if (!emul)
 		goto set_it;
-	err = path_lookup(altroot, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd);
+	err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd);
 	if (!err) {
 		mnt = nd.mnt;
 		dentry = nd.dentry;
-	} else {
-		return err;
 	}
 set_it:
 	write_lock(&current->fs->lock);
@@ -939,58 +939,6 @@
 		dput(olddentry);
 		mntput(oldmnt);
 	}
-	return 0;
-}
-
-void set_fs_altroot(void)
-{
-	char *emul = __emul_prefix();
-
-	__set_fs_altroot(emul);
-}
-
-asmlinkage long sys_setaltroot(const char __user * altroot)
-{
-	char *emul = NULL;
-	int ret;
-
-	if (altroot) {
-		emul = getname(altroot);
-		if (IS_ERR(emul)) {
-			ret = PTR_ERR(emul);
-			goto out;
-		}
-	}
-
-	if (atomic_read(&current->fs->count) != 1) {
-		struct fs_struct *fsp, *ofsp;
-
-		fsp = copy_fs_struct(current->fs);
-		if (fsp == NULL) {
-			ret = -ENOMEM;
-			goto out_putname;
-		}
-
-		task_lock(current);
-		ofsp = current->fs;
-		current->fs = fsp;
-		task_unlock(current);
-
-		put_fs_struct(ofsp);
-	}
-
-	/*
-	 * At that point we are guaranteed to be the sole owner of
-	 * current->fs.
-	 */
-
-	ret = __set_fs_altroot(emul);
-
-out_putname:
-	if (emul)
-		putname(emul);
-out:
-	return ret;
 }
 
 int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
@@ -2388,18 +2336,6 @@
 	}
 }
 
-int page_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	struct page *page = NULL;
-	char *s = page_getlink(dentry, &page);
-	int res = __vfs_follow_link(nd, s);
-	if (page) {
-		kunmap(page);
-		page_cache_release(page);
-	}
-	return res;
-}
-
 int page_symlink(struct inode *inode, const char *symname, int len)
 {
 	struct address_space *mapping = inode->i_mapping;
@@ -2455,7 +2391,6 @@
 EXPORT_SYMBOL(lock_rename);
 EXPORT_SYMBOL(lookup_hash);
 EXPORT_SYMBOL(lookup_one_len);
-EXPORT_SYMBOL(page_follow_link);
 EXPORT_SYMBOL(page_follow_link_light);
 EXPORT_SYMBOL(page_put_link);
 EXPORT_SYMBOL(page_readlink);
diff -Nru a/fs/ntfs/compress.c b/fs/ntfs/compress.c
--- a/fs/ntfs/compress.c	2004-10-28 22:25:58 -07:00
+++ b/fs/ntfs/compress.c	2004-10-28 22:25:58 -07:00
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
+#include <linux/vmalloc.h>
 
 #include "attrib.h"
 #include "inode.h"
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	2004-10-28 22:25:57 -07:00
+++ b/fs/proc/proc_misc.c	2004-10-28 22:25:57 -07:00
@@ -204,7 +204,6 @@
 		"Slab:         %8lu kB\n"
 		"CommitLimit:  %8lu kB\n"
 		"Committed_AS: %8lu kB\n"
-		"CommitAvail:  %8ld kB\n"
 		"PageTables:   %8lu kB\n"
 		"VmallocTotal: %8lu kB\n"
 		"VmallocUsed:  %8lu kB\n"
@@ -228,7 +227,6 @@
 		K(ps.nr_slab),
 		K(allowed),
 		K(committed),
-		K(allowed - committed),
 		K(ps.nr_page_table_pages),
 		vmtot,
 		vmi.used,
diff -Nru a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
--- a/fs/proc/task_mmu.c	2004-10-28 22:25:57 -07:00
+++ b/fs/proc/task_mmu.c	2004-10-28 22:25:57 -07:00
@@ -37,10 +37,10 @@
 int task_statm(struct mm_struct *mm, int *shared, int *text,
 	       int *data, int *resident)
 {
-	*shared = mm->shared_vm;
+	*shared = mm->rss - mm->anon_rss;
 	*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
 								>> PAGE_SHIFT;
-	*data = mm->total_vm - mm->shared_vm - *text;
+	*data = mm->total_vm - mm->shared_vm;
 	*resident = mm->rss;
 	return mm->total_vm;
 }
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	2004-10-28 22:25:58 -07:00
+++ b/fs/read_write.c	2004-10-28 22:25:58 -07:00
@@ -146,7 +146,6 @@
 bad:
 	return retval;
 }
-EXPORT_SYMBOL_GPL(sys_lseek);
 
 #ifdef __ARCH_WANT_SYS_LLSEEK
 asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
diff -Nru a/fs/sysfs/dir.c b/fs/sysfs/dir.c
--- a/fs/sysfs/dir.c	2004-10-28 22:25:57 -07:00
+++ b/fs/sysfs/dir.c	2004-10-28 22:25:57 -07:00
@@ -181,7 +181,7 @@
 	new_dentry = sysfs_get_dentry(parent, new_name);
 	if (!IS_ERR(new_dentry)) {
   		if (!new_dentry->d_inode) {
-			error = kobject_set_name(kobj,new_name);
+			error = kobject_set_name(kobj, "%s", new_name);
 			if (!error)
 				d_move(kobj->dentry, new_dentry);
 		}
diff -Nru a/fs/udf/file.c b/fs/udf/file.c
--- a/fs/udf/file.c	2004-10-28 22:25:58 -07:00
+++ b/fs/udf/file.c	2004-10-28 22:25:58 -07:00
@@ -254,30 +254,10 @@
 	return 0;
 }
 
-/*
- * udf_open_file
- *
- * PURPOSE
- *  Called when an inode is about to be open.
- *
- * DESCRIPTION
- *  Use this to disallow opening RW large files on 32 bit systems.
- *  On 64 bit systems we force on O_LARGEFILE in sys_open.
- *
- * HISTORY
- *
- */
-static int udf_open_file(struct inode * inode, struct file * filp)
-{
-	if ((inode->i_size & 0xFFFFFFFF80000000ULL) && !(filp->f_flags & O_LARGEFILE))
-		return -EFBIG;
-	return 0;
-}
-
 struct file_operations udf_file_operations = {
 	.read			= generic_file_read,
 	.ioctl			= udf_ioctl,
-	.open			= udf_open_file,
+	.open			= generic_file_open,
 	.mmap			= generic_file_mmap,
 	.write			= udf_file_write,
 	.release		= udf_release_file,
diff -Nru a/fs/ufs/inode.c b/fs/ufs/inode.c
--- a/fs/ufs/inode.c	2004-10-28 22:25:57 -07:00
+++ b/fs/ufs/inode.c	2004-10-28 22:25:57 -07:00
@@ -629,7 +629,7 @@
 		}
 	} else
 		init_special_inode(inode, inode->i_mode,
-			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+			ufs_get_inode_dev(sb, ufsi));
 
 	brelse (bh);
 
@@ -705,7 +705,7 @@
 		}
 	} else   /* TODO  : here ...*/
 		init_special_inode(inode, inode->i_mode,
-			old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0])));
+			ufs_get_inode_dev(sb, ufsi));
 
 	brelse(bh);
 
diff -Nru a/fs/ufs/namei.c b/fs/ufs/namei.c
--- a/fs/ufs/namei.c	2004-10-28 22:25:59 -07:00
+++ b/fs/ufs/namei.c	2004-10-28 22:25:59 -07:00
@@ -30,6 +30,7 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include "swab.h"	/* will go away - see comment in mknod() */
+#include "util.h"
 
 /*
 #undef UFS_NAMEI_DEBUG
@@ -125,8 +126,7 @@
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, mode, rdev);
 		/* NOTE: that'll go when we get wide dev_t */
-		UFS_I(inode)->i_u1.i_data[0] = cpu_to_fs32(inode->i_sb,
-							old_encode_dev(rdev));
+		ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
 		mark_inode_dirty(inode);
 		lock_kernel();
 		err = ufs_add_nondir(dentry, inode);
diff -Nru a/fs/ufs/util.c b/fs/ufs/util.c
--- a/fs/ufs/util.c	2004-10-28 22:25:57 -07:00
+++ b/fs/ufs/util.c	2004-10-28 22:25:57 -07:00
@@ -202,3 +202,56 @@
 		bhno++;
 	}
 }
+
+dev_t
+ufs_get_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi)
+{
+	__fs32 fs32;
+	dev_t dev;
+
+	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+		fs32 = ufsi->i_u1.i_data[1];
+	else
+		fs32 = ufsi->i_u1.i_data[0];
+	fs32 = fs32_to_cpu(sb, fs32);
+	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+	case UFS_ST_SUNx86:
+	case UFS_ST_SUN:
+		if ((fs32 & 0xffff0000) == 0 ||
+		    (fs32 & 0xffff0000) == 0xffff0000)
+			dev = old_decode_dev(fs32 & 0x7fff);
+		else
+			dev = MKDEV(sysv_major(fs32), sysv_minor(fs32));
+		break;
+
+	default:
+		dev = old_decode_dev(fs32);
+		break;
+	}
+	return dev;
+}
+
+void
+ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev)
+{
+	__fs32 fs32;
+
+	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
+	case UFS_ST_SUNx86:
+	case UFS_ST_SUN:
+		fs32 = sysv_encode_dev(dev);
+		if ((fs32 & 0xffff8000) == 0) {
+			fs32 = old_encode_dev(dev);
+		}
+		break;
+
+	default:
+		fs32 = old_encode_dev(dev);
+		break;
+	}
+	fs32 = cpu_to_fs32(sb, fs32);
+	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+		ufsi->i_u1.i_data[1] = fs32;
+	else
+		ufsi->i_u1.i_data[0] = fs32;
+}
diff -Nru a/fs/ufs/util.h b/fs/ufs/util.h
--- a/fs/ufs/util.h	2004-10-28 22:25:58 -07:00
+++ b/fs/ufs/util.h	2004-10-28 22:25:58 -07:00
@@ -223,6 +223,8 @@
 	inode->ui_u1.oldids.ui_sgid =  cpu_to_fs16(sb, value);
 }
 
+extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *);
+extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t);
 
 /*
  * These functions manipulate ufs buffers
diff -Nru a/include/asm-alpha/core_cia.h b/include/asm-alpha/core_cia.h
--- a/include/asm-alpha/core_cia.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-alpha/core_cia.h	2004-10-28 22:25:58 -07:00
@@ -347,14 +347,14 @@
 	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, base_and_type;
 
-	/* We can use CIA_MEM_R1_MASK for io ports too, since it is large
-	   enough to cover all io ports, and smaller than CIA_IO.  */
-	addr &= CIA_MEM_R1_MASK;
 	if (addr >= CIA_DENSE_MEM)
 		base_and_type = CIA_SPARSE_MEM + 0x00;
 	else
 		base_and_type = CIA_IO + 0x00;
 
+	/* We can use CIA_MEM_R1_MASK for io ports too, since it is large
+	   enough to cover all io ports, and smaller than CIA_IO.  */
+	addr &= CIA_MEM_R1_MASK;
 	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extbl(result, addr & 3);
 }
@@ -364,12 +364,12 @@
 	unsigned long addr = (unsigned long) xaddr;
 	unsigned long w, base_and_type;
 
-	addr &= CIA_MEM_R1_MASK;
 	if (addr >= CIA_DENSE_MEM)
 		base_and_type = CIA_SPARSE_MEM + 0x00;
 	else
 		base_and_type = CIA_IO + 0x00;
 
+	addr &= CIA_MEM_R1_MASK;
 	w = __kernel_insbl(b, addr & 3);
 	*(vuip) ((addr << 5) + base_and_type) = w;
 }
@@ -379,12 +379,12 @@
 	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, base_and_type;
 
-	addr &= CIA_MEM_R1_MASK;
 	if (addr >= CIA_DENSE_MEM)
 		base_and_type = CIA_SPARSE_MEM + 0x08;
 	else
 		base_and_type = CIA_IO + 0x08;
 
+	addr &= CIA_MEM_R1_MASK;
 	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extwl(result, addr & 3);
 }
@@ -394,12 +394,12 @@
 	unsigned long addr = (unsigned long) xaddr;
 	unsigned long w, base_and_type;
 
-	addr &= CIA_MEM_R1_MASK;
 	if (addr >= CIA_DENSE_MEM)
 		base_and_type = CIA_SPARSE_MEM + 0x08;
 	else
 		base_and_type = CIA_IO + 0x08;
 
+	addr &= CIA_MEM_R1_MASK;
 	w = __kernel_inswl(b, addr & 3);
 	*(vuip) ((addr << 5) + base_and_type) = w;
 }
diff -Nru a/include/asm-alpha/errno.h b/include/asm-alpha/errno.h
--- a/include/asm-alpha/errno.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-alpha/errno.h	2004-10-28 22:25:57 -07:00
@@ -110,9 +110,10 @@
 
 #define ENOMEDIUM	129	/* No medium found */
 #define EMEDIUMTYPE	130	/* Wrong medium type */
-#define	ENOKEY		131	/* Required key not available */
-#define	EKEYEXPIRED	132	/* Key has expired */
-#define	EKEYREVOKED	133	/* Key has been revoked */
-#define	EKEYREJECTED	134	/* Key was rejected by service */
+#define	ECANCELED	131	/* Operation Cancelled */
+#define	ENOKEY		132	/* Required key not available */
+#define	EKEYEXPIRED	133	/* Key has expired */
+#define	EKEYREVOKED	134	/* Key has been revoked */
+#define	EKEYREJECTED	135	/* Key was rejected by service */
 
 #endif
diff -Nru a/include/asm-alpha/io.h b/include/asm-alpha/io.h
--- a/include/asm-alpha/io.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-alpha/io.h	2004-10-28 22:25:59 -07:00
@@ -282,6 +282,12 @@
 	return IO_CONCAT(__IO_PREFIX,ioremap) (port, size);
 }
 
+static inline void __iomem *__ioremap(unsigned long port, unsigned long size,
+				      unsigned long flags)
+{
+	return ioremap(port, size);
+}
+
 static inline void __iomem * ioremap_nocache(unsigned long offset,
 					     unsigned long size)
 {
@@ -488,6 +494,8 @@
 #define readw_relaxed(addr) __raw_readw(addr)
 #define readl_relaxed(addr) __raw_readl(addr)
 #define readq_relaxed(addr) __raw_readq(addr)
+
+#define mmiowb()
 
 /*
  * String version of IO memory access ops:
diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
--- a/include/asm-alpha/pgtable.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-alpha/pgtable.h	2004-10-28 22:25:57 -07:00
@@ -327,8 +327,12 @@
 #define kern_addr_valid(addr)	(1)
 #endif
 
-#define io_remap_page_range(vma, start, busaddr, size, prot) \
-    remap_pfn_range(vma, start, virt_to_phys(ioremap(busaddr, size)) >> PAGE_SHIFT, size, prot)
+#define io_remap_page_range(vma, start, busaddr, size, prot)	\
+({								\
+	void *va = (void __force *)ioremap(busaddr, size);	\
+	unsigned long pfn = virt_to_phys(va) >> PAGE_SHIFT;	\
+	remap_pfn_range(vma, start, pfn, size, prot);		\
+})
 
 #define pte_ERROR(e) \
 	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
diff -Nru a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
--- a/include/asm-arm/arch-omap/board-h2.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-arm/arch-omap/board-h2.h	2004-10-28 22:25:58 -07:00
@@ -36,10 +36,14 @@
 #define OMAP1610_ETHR_SIZE		SZ_4K
 #define OMAP1610_ETHR_START		0x04000000
 
-/* Intel STRATA NOR flash at CS3 */
-#define OMAP1610_NOR_FLASH_BASE		0xD8000000
-#define OMAP1610_NOR_FLASH_SIZE		SZ_32M
-#define OMAP1610_NOR_FLASH_START	0x0C000000
+/* Intel STRATA NOR flash at CS3 or CS2B(NAND Boot) */
+#define OMAP_NOR_FLASH_SIZE             SZ_32M
+#define OMAP_NOR_FLASH_START1           0x0C000000 /* CS3 */
+#define OMAP_NOR_FLASH_START2           0x0A000000 /* CS2B */
+
+/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
+#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
+#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
 
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 
diff -Nru a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
--- a/include/asm-arm/arch-omap/board-h3.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-arm/arch-omap/board-h3.h	2004-10-28 22:25:59 -07:00
@@ -32,10 +32,14 @@
 #define OMAP1710_ETHR_SIZE		SZ_4K
 #define OMAP1710_ETHR_START		0x04000000
 
-/* Intel STRATA NOR flash at CS3 */
-#define OMAP_NOR_FLASH_BASE		0xD8000000
-#define OMAP_NOR_FLASH_SIZE		SZ_32M
-#define OMAP_NOR_FLASH_START		0x00000000
+/* Intel STRATA NOR flash at CS3 or CS2B(NAND Boot) */
+#define OMAP_NOR_FLASH_SIZE             SZ_32M
+#define OMAP_NOR_FLASH_START1 		0x0C000000 /* CS3 */
+#define OMAP_NOR_FLASH_START2 		0x0A000000 /* CS2B */
+
+/* Samsung NAND flash at CS2B or CS3(NAND Boot) */
+#define OMAP_NAND_FLASH_START1           0x0A000000 /* CS2B */
+#define OMAP_NAND_FLASH_START2           0x0C000000 /* CS3 */
 
 #define MAXIRQNUM			(IH_BOARD_BASE)
 #define MAXFIQNUM			MAXIRQNUM
@@ -43,65 +47,5 @@
 
 #define NR_IRQS				(MAXIRQNUM + 1)
 
-#define OMAP_MCBSP1_BASE		OMAP1610_MCBSP1_BASE
-#define AUDIO_DRR2  (OMAP_MCBSP1_BASE + 0x00)
-#define AUDIO_DRR1  (OMAP_MCBSP1_BASE + 0x02)
-#define AUDIO_DXR2  (OMAP_MCBSP1_BASE + 0x04)
-#define AUDIO_DXR1  (OMAP_MCBSP1_BASE + 0x06)
-#define AUDIO_SPCR2 (OMAP_MCBSP1_BASE + 0x08)
-#define AUDIO_SPCR1 (OMAP_MCBSP1_BASE + 0x0a)
-#define AUDIO_RCR2  (OMAP_MCBSP1_BASE + 0x0c)
-#define AUDIO_RCR1  (OMAP_MCBSP1_BASE + 0x0e)
-#define AUDIO_XCR2  (OMAP_MCBSP1_BASE + 0x10)
-#define AUDIO_XCR1  (OMAP_MCBSP1_BASE + 0x12)
-#define AUDIO_SRGR2 (OMAP_MCBSP1_BASE + 0x14)
-#define AUDIO_SRGR1 (OMAP_MCBSP1_BASE + 0x16)
-#define AUDIO_MCR2  (OMAP_MCBSP1_BASE + 0x18)
-#define AUDIO_MCR1  (OMAP_MCBSP1_BASE + 0x1a)
-#define AUDIO_RCERA (OMAP_MCBSP1_BASE + 0x1c)
-#define AUDIO_RCERB (OMAP_MCBSP1_BASE + 0x1e)
-#define AUDIO_XCERA (OMAP_MCBSP1_BASE + 0x20)
-#define AUDIO_XCERB (OMAP_MCBSP1_BASE + 0x22)
-#define AUDIO_PCR0  (OMAP_MCBSP1_BASE + 0x24)
-
-/* UART3 Registers Maping through MPU bus */
-#define OMAP_MPU_UART3_BASE     0xFFFB9800      /* UART3 through MPU bus */
-#define UART3_RHR               (OMAP_MPU_UART3_BASE + 0)
-#define UART3_THR               (OMAP_MPU_UART3_BASE + 0)
-#define UART3_DLL               (OMAP_MPU_UART3_BASE + 0)
-#define UART3_IER               (OMAP_MPU_UART3_BASE + 4)
-#define UART3_DLH               (OMAP_MPU_UART3_BASE + 4)
-#define UART3_IIR               (OMAP_MPU_UART3_BASE + 8)
-#define UART3_FCR               (OMAP_MPU_UART3_BASE + 8)
-#define UART3_EFR               (OMAP_MPU_UART3_BASE + 8)
-#define UART3_LCR               (OMAP_MPU_UART3_BASE + 0x0C)
-#define UART3_MCR               (OMAP_MPU_UART3_BASE + 0x10)
-#define UART3_XON1_ADDR1        (OMAP_MPU_UART3_BASE + 0x10)
-#define UART3_XON2_ADDR2        (OMAP_MPU_UART3_BASE + 0x14)
-#define UART3_LSR               (OMAP_MPU_UART3_BASE + 0x14)
-#define UART3_TCR               (OMAP_MPU_UART3_BASE + 0x18)
-#define UART3_MSR               (OMAP_MPU_UART3_BASE + 0x18)
-#define UART3_XOFF1             (OMAP_MPU_UART3_BASE + 0x18)
-#define UART3_XOFF2             (OMAP_MPU_UART3_BASE + 0x1C)
-#define UART3_SPR               (OMAP_MPU_UART3_BASE + 0x1C)
-#define UART3_TLR               (OMAP_MPU_UART3_BASE + 0x1C)
-#define UART3_MDR1              (OMAP_MPU_UART3_BASE + 0x20)
-#define UART3_MDR2              (OMAP_MPU_UART3_BASE + 0x24)
-#define UART3_SFLSR             (OMAP_MPU_UART3_BASE + 0x28)
-#define UART3_TXFLL             (OMAP_MPU_UART3_BASE + 0x28)
-#define UART3_RESUME            (OMAP_MPU_UART3_BASE + 0x2C)
-#define UART3_TXFLH             (OMAP_MPU_UART3_BASE + 0x2C)
-#define UART3_SFREGL            (OMAP_MPU_UART3_BASE + 0x30)
-#define UART3_RXFLL             (OMAP_MPU_UART3_BASE + 0x30)
-#define UART3_SFREGH            (OMAP_MPU_UART3_BASE + 0x34)
-#define UART3_RXFLH             (OMAP_MPU_UART3_BASE + 0x34)
-#define UART3_BLR               (OMAP_MPU_UART3_BASE + 0x38)
-#define UART3_ACREG             (OMAP_MPU_UART3_BASE + 0x3C)
-#define UART3_DIV16             (OMAP_MPU_UART3_BASE + 0x3C)
-#define UART3_SCR               (OMAP_MPU_UART3_BASE + 0x40)
-#define UART3_SSR               (OMAP_MPU_UART3_BASE + 0x44)
-#define UART3_EBLR              (OMAP_MPU_UART3_BASE + 0x48)
-#define UART3_OSC_12M_SEL       (OMAP_MPU_UART3_BASE + 0x4C)
-#define UART3_MVR               (OMAP_MPU_UART3_BASE + 0x50)
 
 #endif /*  __ASM_ARCH_OMAP_H3_H */
diff -Nru a/include/asm-arm/arch-omap/board-innovator.h b/include/asm-arm/arch-omap/board-innovator.h
--- a/include/asm-arm/arch-omap/board-innovator.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-arm/arch-omap/board-innovator.h	2004-10-28 22:25:59 -07:00
@@ -71,17 +71,11 @@
 
 #endif /* CONFIG_ARCH_OMAP1510 */
 
-#if defined (CONFIG_ARCH_OMAP1610)
+#if defined (CONFIG_ARCH_OMAP16XX)
 
 /* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
-#define OMAP1610_ETHR_BASE		0xE8000000
-#define OMAP1610_ETHR_SIZE		SZ_4K
-#define OMAP1610_ETHR_START		0x04000000
-
-/* Intel STRATA NOR flash at CS3 */
-#define OMAP1610_NOR_FLASH_BASE		0xD8000000
-#define OMAP1610_NOR_FLASH_SIZE		SZ_32M
-#define OMAP1610_NOR_FLASH_START	0x0C000000
+#define INNOVATOR1610_ETHR_START	0x04000000
+#define INNOVATOR1610_ETHR_SIZE		SZ_4K
 
 #endif /* CONFIG_ARCH_OMAP1610 */
 #endif /* __ASM_ARCH_OMAP_INNOVATOR_H */
diff -Nru a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
--- a/include/asm-arm/arch-omap/board.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-arm/arch-omap/board.h	2004-10-28 22:25:58 -07:00
@@ -17,7 +17,12 @@
 #define OMAP_TAG_CLOCK		0x4f01
 #define OMAP_TAG_MMC		0x4f02
 #define OMAP_TAG_UART		0x4f03
-#define OMAP_TAG_USB            0x4f04
+#define OMAP_TAG_USB		0x4f04
+#define OMAP_TAG_LCD		0x4f05
+#define OMAP_TAG_GPIO_SWITCH	0x4f06
+
+#define OMAP_TAG_BOOT_REASON    0x4f80
+#define OMAP_TAG_FLASH_PART	0x4f81
 
 struct omap_clock_config {
 	/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
@@ -26,8 +31,8 @@
 
 struct omap_mmc_config {
 	u8 mmc_blocks;
-	s8 mmc1_power_pin, mmc2_power_pin;
-	s8 mmc1_switch_pin, mmc2_switch_pin;
+	s16 mmc1_power_pin, mmc2_power_pin;
+	s16 mmc1_switch_pin, mmc2_switch_pin;
 };
 
 struct omap_uart_config {
@@ -63,6 +68,38 @@
 	u8		pins[3];
 };
 
+struct omap_lcd_config {
+	char panel_name[16];
+	char ctrl_name[16];
+};
+
+/* Cover:
+ *      high -> closed
+ *      low  -> open
+ * Connection:
+ *      high -> connected
+ *      low  -> disconnected
+ */
+#define OMAP_GPIO_SWITCH_TYPE_COVER		0x0000
+#define OMAP_GPIO_SWITCH_TYPE_CONNECTION	0x0001
+#define OMAP_GPIO_SWITCH_FLAG_INVERTED          0x0001
+struct omap_gpio_switch_config {
+	char name[12];
+	u16 gpio;
+	int flags:4;
+	int type:4;
+	int key_code:24; /* Linux key code */
+};
+
+struct omap_flash_part_config {
+	char part_table[0];
+};
+
+struct omap_boot_reason_config {
+	char reason_str[12];
+};
+
+
 struct omap_board_config_entry {
 	u16 tag;
 	u16 len;
@@ -74,10 +111,14 @@
 	const void *data;
 };
 
-extern const void *__omap_get_config(u16 tag, size_t len);
+extern const void *__omap_get_config(u16 tag, size_t len, int nr);
 
 #define omap_get_config(tag, type) \
-	((const type *) __omap_get_config((tag), sizeof(type)))
+	((const type *) __omap_get_config((tag), sizeof(type), 0))
+#define omap_get_nr_config(tag, type, nr) \
+	((const type *) __omap_get_config((tag), sizeof(type), (nr)))
+
+extern const void *omap_get_var_config(u16 tag, size_t *len);
 
 extern struct omap_board_config_kernel *omap_board_config;
 extern int omap_board_config_size;
diff -Nru a/include/asm-arm/arch-omap/cpu.h b/include/asm-arm/arch-omap/cpu.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-omap/cpu.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,183 @@
+/*
+ * linux/include/asm-arm/arch-omap/cpu.h
+ *
+ * OMAP cpu type detection
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ *
+ * Written by Tony Lindgren <tony.lindgren@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ASM_ARCH_OMAP_CPU_H
+#define __ASM_ARCH_OMAP_CPU_H
+
+extern unsigned int system_rev;
+
+#define OMAP_DIE_ID_0		0xfffe1800
+#define OMAP_DIE_ID_1		0xfffe1804
+#define OMAP_PRODUCTION_ID_0	0xfffe2000
+#define OMAP_PRODUCTION_ID_1	0xfffe2004
+#define OMAP32_ID_0		0xfffed400
+#define OMAP32_ID_1		0xfffed404
+
+/*
+ * Test if multicore OMAP support is needed
+ */
+#undef MULTI_OMAP
+#undef OMAP_NAME
+
+#ifdef CONFIG_ARCH_OMAP730
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP
+#  define MULTI_OMAP
+# else
+#  define OMAP_NAME omap730
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP1510
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP
+#  define MULTI_OMAP
+# else
+#  define OMAP_NAME omap1510
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP
+#  define MULTI_OMAP
+# else
+#  define OMAP_NAME omap1610
+# endif
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP
+#  define MULTI_OMAP
+# else
+#  define OMAP_NAME omap1710
+# endif
+#endif
+
+/*
+ * Generate various OMAP cpu specific macros, and cpu class
+ * specific macros
+ */
+#define GET_OMAP_TYPE	((system_rev >> 24) & 0xff)
+#define GET_OMAP_CLASS	(system_rev & 0xff)
+
+#define IS_OMAP_TYPE(type, id)				\
+static inline int is_omap ##type (void)			\
+{							\
+	return (GET_OMAP_TYPE == (id)) ? 1 : 0;		\
+}
+
+#define IS_OMAP_CLASS(class, id)			\
+static inline int is_omap ##class (void)		\
+{							\
+	return (GET_OMAP_CLASS == (id)) ? 1 : 0;	\
+}
+
+IS_OMAP_TYPE(730, 0x07)
+IS_OMAP_TYPE(1510, 0x15)
+IS_OMAP_TYPE(1610, 0x16)
+IS_OMAP_TYPE(5912, 0x16)
+IS_OMAP_TYPE(1710, 0x17)
+IS_OMAP_TYPE(2420, 0x24)
+
+IS_OMAP_CLASS(7xx, 0x07)
+IS_OMAP_CLASS(15xx, 0x15)
+IS_OMAP_CLASS(16xx, 0x16)
+IS_OMAP_CLASS(24xx, 0x24)
+
+/*
+ * Macros to group OMAP types into cpu classes.
+ * These can be used in most places.
+ * cpu_is_omap15xx():	True for 1510 and 5910
+ * cpu_is_omap16xx():	True for 1610, 5912 and 1710
+ */
+#if defined(MULTI_OMAP)
+# define cpu_is_omap7xx()		is_omap7xx()
+# define cpu_is_omap15xx()		is_omap15xx()
+# if !(defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_ARCH_OMAP730))
+#  define cpu_is_omap16xx()		1
+# else
+#  define cpu_is_omap16xx()		is_omap16xx()
+# endif
+#else
+# if defined(CONFIG_ARCH_OMAP730)
+#  define cpu_is_omap7xx()		1
+# else
+#  define cpu_is_omap7xx()		0
+# endif
+# if defined(CONFIG_ARCH_OMAP1510)
+#  define cpu_is_omap15xx()		1
+# else
+#  define cpu_is_omap15xx()		0
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+#  define cpu_is_omap16xx()		1
+# else
+#  define cpu_is_omap16xx()		0
+# endif
+#endif
+
+#if defined(MULTI_OMAP)
+# define cpu_is_omap730()		is_omap730()
+# define cpu_is_omap1510()		is_omap1510()
+# define cpu_is_omap1610()		is_omap1610()
+# define cpu_is_omap5912()		is_omap5912()
+# define cpu_is_omap1710()		is_omap1710()
+#else
+# if defined(CONFIG_ARCH_OMAP730)
+#  define cpu_is_omap730()		1
+# else
+#  define cpu_is_omap730()		0
+# endif
+# if defined(CONFIG_ARCH_OMAP1510)
+#  define cpu_is_omap1510()		1
+# else
+#  define cpu_is_omap1510()		0
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+#  define cpu_is_omap1610()		1
+# else
+#  define cpu_is_omap1610()		0
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+#  define cpu_is_omap5912()		1
+# else
+#  define cpu_is_omap5912()		0
+# endif
+# if defined(CONFIG_ARCH_OMAP16XX)
+# define cpu_is_omap1610()		is_omap1610()
+# define cpu_is_omap5912()		is_omap5912()
+# define cpu_is_omap1710()		is_omap1710()
+# else
+# define cpu_is_omap1610()		0
+# define cpu_is_omap5912()		0
+# define cpu_is_omap1710()		0
+# endif
+# if defined(CONFIG_ARCH_OMAP2420)
+#  define cpu_is_omap2420()		1
+# else
+#  define cpu_is_omap2420()		0
+# endif
+#endif
+
+#endif
diff -Nru a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
--- a/include/asm-arm/arch-omap/dma.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/arch-omap/dma.h	2004-10-28 22:25:57 -07:00
@@ -194,11 +194,19 @@
 	OMAP_LCD_DMA_B2_BOTTOM
 };
 
-enum {
+enum omap_dma_burst_mode {
+	OMAP_DMA_DATA_BURST_DIS = 0,
 	OMAP_DMA_DATA_BURST_4,
 	OMAP_DMA_DATA_BURST_8
 };
 
+enum omap_dma_color_mode {
+	OMAP_DMA_COLOR_DIS = 0,
+	OMAP_DMA_CONSTANT_FILL,
+	OMAP_DMA_TRANSPARENT_COPY
+};
+
+extern void omap_set_dma_priority(int dst_port, int priority);
 extern int omap_request_dma(int dev_id, const char *dev_name,
 			    void (* callback)(int lch, u16 ch_status, void *data),
 			    void *data, int *dma_ch);
@@ -210,20 +218,22 @@
 extern void omap_set_dma_transfer_params(int lch, int data_type,
 					 int elem_count, int frame_count,
 					 int sync_mode);
-extern void omap_set_dma_constant_fill(int lch, u32 color);
-extern void omap_set_dma_transparent_copy(int lch, u32 color);
+extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
+				    u32 color);
 
 extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
 				    unsigned long src_start);
 extern void omap_set_dma_src_index(int lch, int eidx, int fidx);
 extern void omap_set_dma_src_data_pack(int lch, int enable);
-extern void omap_set_dma_src_burst_mode(int lch, int burst_mode);
+extern void omap_set_dma_src_burst_mode(int lch,
+					enum omap_dma_burst_mode burst_mode);
 
 extern void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
 				     unsigned long dest_start);
 extern void omap_set_dma_dest_index(int lch, int eidx, int fidx);
 extern void omap_set_dma_dest_data_pack(int lch, int enable);
-extern void omap_set_dma_dest_burst_mode(int lch, int burst_mode);
+extern void omap_set_dma_dest_burst_mode(int lch,
+					 enum omap_dma_burst_mode burst_mode);
 
 extern void omap_dma_link_lch (int lch_head, int lch_queue);
 extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
@@ -235,10 +245,16 @@
 extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
 				void *data);
 extern void omap_free_lcd_dma(void);
-extern void omap_start_lcd_dma(void);
+extern void omap_setup_lcd_dma(void);
+extern void omap_enable_lcd_dma(void);
 extern void omap_stop_lcd_dma(void);
+extern void omap_set_lcd_dma_ext_controller(int external);
+extern void omap_set_lcd_dma_single_transfer(int single);
 extern void omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres,
 				int data_type);
 extern void omap_set_lcd_dma_b1_rotation(int rotate);
+extern void omap_set_lcd_dma_b1_vxres(unsigned long vxres);
+extern void omap_set_lcd_dma_b1_mirror(int mirror);
+extern void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale);
 
 #endif /* __ASM_ARCH_DMA_H */
diff -Nru a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
--- a/include/asm-arm/arch-omap/hardware.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/arch-omap/hardware.h	2004-10-28 22:25:57 -07:00
@@ -40,6 +40,7 @@
 #include <linux/config.h>
 #ifndef __ASSEMBLER__
 #include <asm/types.h>
+#include <asm/arch/cpu.h>
 #endif
 #include <asm/arch/io.h>
 
@@ -64,6 +65,7 @@
 #define ARM_RSTCT1		(CLKGEN_REG_BASE + 0x10)
 #define ARM_RSTCT2		(CLKGEN_REG_BASE + 0x14)
 #define ARM_SYSST		(CLKGEN_REG_BASE + 0x18)
+#define ARM_IDLECT3		(CLKGEN_REG_BASE + 0x24)
 
 #define CK_RATEF		1
 #define CK_IDLEF		2
@@ -140,12 +142,12 @@
 #define MPUTIM_AR		(1<<1)
 #define MPUTIM_ST		(1<<0)
 
-/* Watchdog */
-#define OMAP_WATCHDOG_BASE	(0xfffec800)
-#define OMAP_WDT_TIMER		(OMAP_WATCHDOG_BASE + 0x0)
-#define OMAP_WDT_LOAD_TIM	(OMAP_WATCHDOG_BASE + 0x4)
-#define OMAP_WDT_READ_TIM	(OMAP_WATCHDOG_BASE + 0x4)
-#define OMAP_WDT_TIMER_MODE	(OMAP_WATCHDOG_BASE + 0x8)
+/* Watchdog timer within the OMAP3.2 gigacell */
+#define OMAP_MPU_WATCHDOG_BASE	(0xfffec800)
+#define OMAP_WDT_TIMER		(OMAP_MPU_WATCHDOG_BASE + 0x0)
+#define OMAP_WDT_LOAD_TIM	(OMAP_MPU_WATCHDOG_BASE + 0x4)
+#define OMAP_WDT_READ_TIM	(OMAP_MPU_WATCHDOG_BASE + 0x4)
+#define OMAP_WDT_TIMER_MODE	(OMAP_MPU_WATCHDOG_BASE + 0x8)
 
 /*
  * ---------------------------------------------------------------------------
@@ -186,22 +188,22 @@
  * ---------------------------------------------------------------------------
  */
 #define TCMIF_BASE		0xfffecc00
-#define IMIF_PRIO_REG		__REG32(TCMIF_BASE + 0x00)
-#define EMIFS_PRIO_REG		__REG32(TCMIF_BASE + 0x04)
-#define EMIFF_PRIO_REG		__REG32(TCMIF_BASE + 0x08)
-#define EMIFS_CONFIG_REG	__REG32(TCMIF_BASE + 0x0c)
-#define EMIFS_CS0_CONFIG_REG	__REG32(TCMIF_BASE + 0x10)
-#define EMIFS_CS1_CONFIG_REG	__REG32(TCMIF_BASE + 0x14)
-#define EMIFS_CS2_CONFIG_REG	__REG32(TCMIF_BASE + 0x18)
-#define EMIFS_CS3_CONFIG_REG	__REG32(TCMIF_BASE + 0x1c)
-#define EMIFF_SDRAM_CONFIG_REG	__REG32(TCMIF_BASE + 0x20)
-#define EMIFF_MRS_REG		__REG32(TCMIF_BASE + 0x24)
-#define TC_TIMEOUT1_REG		__REG32(TCMIF_BASE + 0x28)
-#define TC_TIMEOUT2_REG		__REG32(TCMIF_BASE + 0x2c)
-#define TC_TIMEOUT3_REG		__REG32(TCMIF_BASE + 0x30)
-#define TC_ENDIANISM_REG	__REG32(TCMIF_BASE + 0x34)
-#define EMIFF_SDRAM_CONFIG_2_REG __REG32(TCMIF_BASE + 0x3c)
-#define EMIF_CFG_DYNAMIC_WS_REG	__REG32(TCMIF_BASE + 0x40)
+#define IMIF_PRIO		(TCMIF_BASE + 0x00)
+#define EMIFS_PRIO		(TCMIF_BASE + 0x04)
+#define EMIFF_PRIO		(TCMIF_BASE + 0x08)
+#define EMIFS_CONFIG		(TCMIF_BASE + 0x0c)
+#define EMIFS_CS0_CONFIG	(TCMIF_BASE + 0x10)
+#define EMIFS_CS1_CONFIG	(TCMIF_BASE + 0x14)
+#define EMIFS_CS2_CONFIG	(TCMIF_BASE + 0x18)
+#define EMIFS_CS3_CONFIG	(TCMIF_BASE + 0x1c)
+#define EMIFF_SDRAM_CONFIG	(TCMIF_BASE + 0x20)
+#define EMIFF_MRS		(TCMIF_BASE + 0x24)
+#define TC_TIMEOUT1		(TCMIF_BASE + 0x28)
+#define TC_TIMEOUT2		(TCMIF_BASE + 0x2c)
+#define TC_TIMEOUT3		(TCMIF_BASE + 0x30)
+#define TC_ENDIANISM		(TCMIF_BASE + 0x34)
+#define EMIFF_SDRAM_CONFIG_2	(TCMIF_BASE + 0x3c)
+#define EMIF_CFG_DYNAMIC_WS	(TCMIF_BASE + 0x40)
 
 /*
  * ----------------------------------------------------------------------------
@@ -235,6 +237,7 @@
 #define PULL_DWN_CTRL_1		0xfffe1044
 #define PULL_DWN_CTRL_2		0xfffe1048
 #define PULL_DWN_CTRL_3		0xfffe104c
+#define PULL_DWN_CTRL_4		0xfffe10ac
 
 /* OMAP-1610 specific multiplexing registers */
 #define FUNC_MUX_CTRL_E		0xfffe1090
@@ -248,6 +251,9 @@
 #define PU_PD_SEL_3		0xfffe10c0
 #define PU_PD_SEL_4		0xfffe10c4
 
+/* Timer32K for 1610 and 1710*/
+#define OMAP_TIMER32K_BASE	0xFFFBC400
+
 /*
  * ---------------------------------------------------------------------------
  * TIPB bus interface
@@ -277,62 +283,24 @@
 
 /*
  * ---------------------------------------------------------------------------
- * Processor differentiation
+ * Processor specific defines
  * ---------------------------------------------------------------------------
  */
-#define OMAP_ID_BASE		(0xfffed400)
-#define OMAP_ID_REG		__REG32(OMAP_ID_BASE +  0x04)
-
-#define ID_SHIFT		12
-#define ID_MASK			0x7fff
-
-/* See also uncompress.h */
-#define OMAP_ID_730		0x355F
-#define OMAP_ID_1510		0x3470
-#define OMAP_ID_1610		0x3576
-#define OMAP_ID_1710		0x35F7
-#define OMAP_ID_5912		0x358C
-#define OMAP_ID_1611            0x358C
-
 #ifdef CONFIG_ARCH_OMAP730
 #include "omap730.h"
-#define cpu_is_omap730()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_730)
-#else
-#define cpu_is_omap730()	0
 #endif
 
 #ifdef CONFIG_ARCH_OMAP1510
 #include "omap1510.h"
-#define cpu_is_omap1510()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1510)
-#else
-#define cpu_is_omap1510()	0
-#endif
-
-#ifdef CONFIG_ARCH_OMAP1610
-#include "omap1610.h"
-#define cpu_is_omap1610()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1610) || \
-				(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1611)
-#else
-#define cpu_is_omap1610()	0
-#endif
-
-#ifdef CONFIG_ARCH_OMAP1710
-#include "omap1610.h"
-#define cpu_is_omap1710()       (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1710)
-#else
-#define cpu_is_omap1710()	0
 #endif
 
-#ifdef CONFIG_ARCH_OMAP5912
-#include "omap5912.h"
-#define cpu_is_omap5912()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_5912)
-#else
-#define cpu_is_omap5912()	0
+#ifdef CONFIG_ARCH_OMAP16XX
+#include "omap16xx.h"
 #endif
 
 /*
  * ---------------------------------------------------------------------------
- * Board differentiation
+ * Board specific defines
  * ---------------------------------------------------------------------------
  */
 
diff -Nru a/include/asm-arm/arch-omap/irqs.h b/include/asm-arm/arch-omap/irqs.h
--- a/include/asm-arm/arch-omap/irqs.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-arm/arch-omap/irqs.h	2004-10-28 22:25:56 -07:00
@@ -192,8 +192,6 @@
 #define INT_730_TIMER32K	(22 + IH2_BASE)
 #define INT_730_MMC_SDIO	(23 + IH2_BASE)
 #define INT_730_UPLD		(24 + IH2_BASE)
-#define INT_730_RTC_TIMER	(25 + IH2_BASE)
-#define INT_730_RTC_ALARM	(26 + IH2_BASE)
 #define INT_730_USB_HHC_1	(27 + IH2_BASE)
 #define INT_730_USB_HHC_2	(28 + IH2_BASE)
 #define INT_730_USB_GENI	(29 + IH2_BASE)
@@ -224,24 +222,6 @@
 #define INT_730_DMA_CH15	(62 + IH2_BASE)
 #define INT_730_NAND		(63 + IH2_BASE)
 
-/* OMAP-730 differences */
-#ifdef CONFIG_ARCH_OMAP730
-#undef	INT_IH2_IRQ
-#define INT_IH2_IRQ		INT_730_IH2_IRQ
-#undef	INT_KEYBOARD
-#define INT_KEYBOARD		INT_730_MPUIO_KEYPAD
-#undef	INT_UART1
-#define INT_UART1		INT_730_UART_MODEM_1
-#undef	INT_UART2
-#define INT_UART2		INT_730_UART_MODEM_IRDA_2
-#undef	INT_MPUIO
-#define INT_MPUIO		INT_730_MPUIO
-#undef	INT_RTC_TIMER
-#define INT_RTC_TIMER		INT_730_RTC_TIMER
-#undef	INT_RTC_ALARM
-#define INT_RTC_ALARM		INT_730_RTC_ALARM
-#endif
-
 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and
  * 16 MPUIO lines */
 #define OMAP_MAX_GPIO_LINES	192
@@ -260,7 +240,7 @@
 #include <asm/arch/hardware.h>
 
 #ifndef NR_IRQS
-#define NR_IRQS                 256
+#define NR_IRQS                 IH_BOARD_BASE
 #endif
 
 #endif
diff -Nru a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h
--- a/include/asm-arm/arch-omap/mcbsp.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/arch-omap/mcbsp.h	2004-10-28 22:25:57 -07:00
@@ -29,7 +29,7 @@
 #define OMAP730_MCBSP1_BASE	0xfffb1000
 #define OMAP730_MCBSP2_BASE	0xfffb1800
 
-#define OMAP1510_MCBSP1_BASE	0xe1011000
+#define OMAP1510_MCBSP1_BASE	0xe1011800
 #define OMAP1510_MCBSP2_BASE	0xfffb1000
 #define OMAP1510_MCBSP3_BASE	0xe1017000
 
diff -Nru a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
--- a/include/asm-arm/arch-omap/memory.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/arch-omap/memory.h	2004-10-28 22:25:57 -07:00
@@ -59,12 +59,14 @@
  * OMAP-1510 bus address is translated into a Local Bus address if the
  * OMAP bus type is lbus. We do the address translation based on the
  * device overriding the defaults used in the dma-mapping API.
+ * Note that the is_lbus_device() test is not very efficient on 1510
+ * because of the strncmp().
  */
 #ifdef CONFIG_ARCH_OMAP1510
 
 #define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
 #define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev)	(cpu_is_omap1510() && dev && dev->coherent_dma_mask == 0x0fffffff)
+#define is_lbus_device(dev)	(cpu_is_omap1510() && dev && (strncmp(dev->bus_id, "ohci", 4) == 0))
 
 #define __arch_page_to_dma(dev, page)	({is_lbus_device(dev) ? \
 					(dma_addr_t)virt_to_lbus(page_address(page)) : \
diff -Nru a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
--- a/include/asm-arm/arch-omap/mux.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/arch-omap/mux.h	2004-10-28 22:25:57 -07:00
@@ -43,9 +43,7 @@
 #define PU_PD_SEL_NA		0	/* No pu_pd reg available */
 #define PULL_DWN_CTRL_NA	0	/* No pull-down control needed */
 
-#define DEBUG_MUX
-
-#ifdef DEBUG_MUX
+#ifdef	CONFIG_OMAP_MUX_DEBUG
 #define MUX_REG(reg, mode_offset, mode) .mux_reg_name = "FUNC_MUX_CTRL_"#reg, \
 					.mux_reg = FUNC_MUX_CTRL_##reg, \
 					.mask_offset = mode_offset, \
@@ -73,7 +71,7 @@
 #define PU_PD_REG(reg, status)		.pu_pd_reg = PU_PD_SEL_##reg, \
 					.pu_pd_val = status,
 
-#endif // DEBUG_MUX
+#endif /* CONFIG_OMAP_MUX_DEBUG */
 
 #define MUX_CFG(desc, mux_reg, mode_offset, mode,	\
 		pull_reg, pull_bit, pull_status,	\
@@ -134,6 +132,7 @@
 	UART3_RTS,
 	UART3_CLKREQ,
 	UART3_BCLK,	/* 12MHz clock out */
+	Y15_1610_UART3_RTS,
 
 	/* PWT & PWL */
 	PWT,
@@ -174,8 +173,13 @@
 	R19_1510_GPIO1,
 	M14_1510_GPIO2,
 
+	/* OMAP1610 GPIO */
+	Y15_1610_GPIO17,
+
 	/* OMAP-1710 GPIO */
 	R18_1710_GPIO0,
+	V2_1710_GPIO10,
+	N21_1710_GPIO14,
 	W15_1710_GPIO40,
 
 	/* MPUIO */
@@ -244,6 +248,10 @@
 	P15_1610_UWIRE_CS0,
 	N15_1610_UWIRE_CS1,
 
+	/* OMAP-1610 Flash */
+	L3_1610_FLASH_CS2B_OE,
+	M8_1610_FLASH_CS2B_WE,
+
 	/* First MMC */
 	MMC_CMD,
 	MMC_DAT1,
@@ -310,7 +318,8 @@
  * Table of various FUNC_MUX and PULL_DWN combinations for each device.
  * See also reg_cfg_t above for the lookup table.
  */
-static reg_cfg_set reg_cfg_table[] = {
+static reg_cfg_set __initdata_or_module
+reg_cfg_table[] = {
 /*
  *	 description		mux  mode   mux	 pull pull  pull  pu_pd	 pu  dbg
  *				reg  offset mode reg  bit   ena	  reg
@@ -331,6 +340,7 @@
 MUX_CFG("UART3_RTS",		 5,   15,    2,	  0,  25,   0,	 NA,	 0,  0)
 MUX_CFG("UART3_CLKREQ",		 9,   27,    0,	  2,   5,   0,	 NA,	 0,  0)
 MUX_CFG("UART3_BCLK",		 A,    0,    0,	  2,   6,   0,	 NA,	 0,  0)
+MUX_CFG("Y15_1610_UART3_RTS",	 A,    0,    1,	  2,   6,   0,	 NA,	 0,  0)
 
 /* PWT & PWL, conflicts with UART3 */
 MUX_CFG("PWT",		 	 6,    0,    2,	  0,  30,   0,	 NA,	 0,  0)
@@ -371,9 +381,14 @@
 MUX_CFG("R19_1510_GPIO1",	 7,    6,    0,   1,  10,   1,    0,     0,  1)
 MUX_CFG("M14_1510_GPIO2",	 7,    3,    0,   1,   9,   1,    0,     0,  1)
 
+/* OMAP1610 GPIO */
+MUX_CFG("Y15_1610_GPIO17",	 A,    0,    7,   2,   6,   0,   NA,     0,  1)
+
 /* OMAP-1710 GPIO */
-MUX_CFG("R18_1710_GPIO0",	 7,    9,    0,   1,  11,   1,    1,     1,  1)
-MUX_CFG("W15_1710_GPIO40",	 9,   27,    7,   2,   5,   1,    2,     1,  1)
+MUX_CFG("R18_1710_GPIO0",        7,    9,    0,   1,  11,   1,    1,     1,  1)
+MUX_CFG("V2_1710_GPIO10",        F,   27,    1,   4,   3,   1,    4,     1,  1)
+MUX_CFG("N21_1710_GPIO14",       6,    9,    0,   1,   1,   1,    1,     1,  1)
+MUX_CFG("W15_1710_GPIO40",       9,   27,    7,   2,   5,   1,    2,     1,  1)
 
 /* MPUIO */
 MUX_CFG("MPUIO2",		 7,   18,    0,	  1,   1,   1,	 NA,	 0,  1)
@@ -442,6 +457,10 @@
 MUX_CFG("P15_1610_UWIRE_CS3",	 8,   12,    1,	  1,  22,   0,	  1,	 1,  1)
 MUX_CFG("N15_1610_UWIRE_CS1",	 7,   18,    2,	  1,  14,   0,	 NA,	 0,  1)
 
+/* OMAP-1610 Flash */
+MUX_CFG("L3_1610_FLASH_CS2B_OE",10,    6,    1,	 NA,   0,   0,	 NA,	 0,  1)
+MUX_CFG("M8_1610_FLASH_CS2B_WE",10,    3,    1,	 NA,   0,   0,	 NA,	 0,  1)
+
 /* First MMC interface, same on 1510, 1610 and 1710 */
 MUX_CFG("MMC_CMD",		 A,   27,    0,	  2,  15,   1,	  2,	 1,  1)
 MUX_CFG("MMC_DAT1",		 A,   24,    0,	  2,  14,   1,	  2,	 1,  1)
@@ -501,6 +520,12 @@
 
 #endif	/* __MUX_C__ */
 
+#ifdef	CONFIG_OMAP_MUX
+/* setup pin muxing in Linux */
 extern int omap_cfg_reg(reg_cfg_t reg_cfg);
+#else
+/* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
+static inline int omap_cfg_reg(reg_cfg_t reg_cfg) { return 0; }
+#endif
 
 #endif
diff -Nru a/include/asm-arm/arch-omap/omap1610.h b/include/asm-arm/arch-omap/omap1610.h
--- a/include/asm-arm/arch-omap/omap1610.h	2004-10-28 22:25:56 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,129 +0,0 @@
-/* linux/include/asm-arm/arch-omap/omap1610.h
- *
- * Hardware definitions for TI OMAP1610 processor.
- *
- * Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_OMAP1610_H
-#define __ASM_ARCH_OMAP1610_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP1610_SRAM_BASE	0xD0000000
-#define OMAP1610_SRAM_SIZE	(SZ_16K)
-#define OMAP1610_SRAM_START	0x20000000
-
-#define OMAP1610_DSP_BASE	0xE0000000
-#define OMAP1610_DSP_SIZE	0x28000
-#define OMAP1610_DSP_START	0xE0000000
-
-#define OMAP1610_DSPREG_BASE	0xE1000000
-#define OMAP1610_DSPREG_SIZE	SZ_128K
-#define OMAP1610_DSPREG_START	0xE1000000
-
-/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP1610_SRAM_IDLE_SUSPEND	(OMAP1610_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
-#define OMAP1610_SRAM_API_SUSPEND	(OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
-
-/*
- * ---------------------------------------------------------------------------
- * Interrupts
- * ---------------------------------------------------------------------------
- */
-#define OMAP_IH2_0_BASE		(0xfffe0000)
-#define OMAP_IH2_1_BASE		(0xfffe0100)
-#define OMAP_IH2_2_BASE		(0xfffe0200)
-#define OMAP_IH2_3_BASE		(0xfffe0300)
-
-#define OMAP_IH2_0_ITR		(OMAP_IH2_0_BASE + 0x00)
-#define OMAP_IH2_0_MIR		(OMAP_IH2_0_BASE + 0x04)
-#define OMAP_IH2_0_SIR_IRQ	(OMAP_IH2_0_BASE + 0x10)
-#define OMAP_IH2_0_SIR_FIQ	(OMAP_IH2_0_BASE + 0x14)
-#define OMAP_IH2_0_CONTROL	(OMAP_IH2_0_BASE + 0x18)
-#define OMAP_IH2_0_ILR0		(OMAP_IH2_0_BASE + 0x1c)
-#define OMAP_IH2_0_ISR		(OMAP_IH2_0_BASE + 0x9c)
-
-#define OMAP_IH2_1_ITR		(OMAP_IH2_1_BASE + 0x00)
-#define OMAP_IH2_1_MIR		(OMAP_IH2_1_BASE + 0x04)
-#define OMAP_IH2_1_SIR_IRQ	(OMAP_IH2_1_BASE + 0x10)
-#define OMAP_IH2_1_SIR_FIQ	(OMAP_IH2_1_BASE + 0x14)
-#define OMAP_IH2_1_CONTROL	(OMAP_IH2_1_BASE + 0x18)
-#define OMAP_IH2_1_ILR1		(OMAP_IH2_1_BASE + 0x1c)
-#define OMAP_IH2_1_ISR		(OMAP_IH2_1_BASE + 0x9c)
-
-#define OMAP_IH2_2_ITR		(OMAP_IH2_2_BASE + 0x00)
-#define OMAP_IH2_2_MIR		(OMAP_IH2_2_BASE + 0x04)
-#define OMAP_IH2_2_SIR_IRQ	(OMAP_IH2_2_BASE + 0x10)
-#define OMAP_IH2_2_SIR_FIQ	(OMAP_IH2_2_BASE + 0x14)
-#define OMAP_IH2_2_CONTROL	(OMAP_IH2_2_BASE + 0x18)
-#define OMAP_IH2_2_ILR2		(OMAP_IH2_2_BASE + 0x1c)
-#define OMAP_IH2_2_ISR		(OMAP_IH2_2_BASE + 0x9c)
-
-#define OMAP_IH2_3_ITR		(OMAP_IH2_3_BASE + 0x00)
-#define OMAP_IH2_3_MIR		(OMAP_IH2_3_BASE + 0x04)
-#define OMAP_IH2_3_SIR_IRQ	(OMAP_IH2_3_BASE + 0x10)
-#define OMAP_IH2_3_SIR_FIQ	(OMAP_IH2_3_BASE + 0x14)
-#define OMAP_IH2_3_CONTROL	(OMAP_IH2_3_BASE + 0x18)
-#define OMAP_IH2_3_ILR3		(OMAP_IH2_3_BASE + 0x1c)
-#define OMAP_IH2_3_ISR		(OMAP_IH2_3_BASE + 0x9c)
-
-/*
- * ----------------------------------------------------------------------------
- * Clocks
- * ----------------------------------------------------------------------------
- */
-#define OMAP1610_ARM_IDLECT3	(CLKGEN_REG_BASE + 0x24)
-
-/*
- * ----------------------------------------------------------------------------
- * Pin configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP1610_CONF_VOLTAGE_VDDSHV6	(1 << 8)
-#define OMAP1610_CONF_VOLTAGE_VDDSHV7	(1 << 9)
-#define OMAP1610_CONF_VOLTAGE_VDDSHV8	(1 << 10)
-#define OMAP1610_CONF_VOLTAGE_VDDSHV9	(1 << 11)
-#define OMAP1610_SUBLVDS_CONF_VALID	(1 << 13)
-
-/*
- * ---------------------------------------------------------------------------
- * TIPB bus interface
- * ---------------------------------------------------------------------------
- */
-#define TIPB_SWITCH_BASE		 (0xfffbc800)
-#define OMAP1610_MMCSD2_SSW_MPU_CONF	(TIPB_SWITCH_BASE + 0x160)
-
-#endif /*  __ASM_ARCH_OMAP1610_H */
-
diff -Nru a/include/asm-arm/arch-omap/omap16xx.h b/include/asm-arm/arch-omap/omap16xx.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-omap/omap16xx.h	2004-10-28 22:25:56 -07:00
@@ -0,0 +1,179 @@
+/* linux/include/asm-arm/arch-omap/omap16xx.h
+ *
+ * Hardware definitions for TI OMAP1610/5912/1710 processors.
+ *
+ * Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the  GNU General Public License along
+ * with this program; if not, write  to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_ARCH_OMAP16XX_H
+#define __ASM_ARCH_OMAP16XX_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Base addresses
+ * ----------------------------------------------------------------------------
+ */
+
+/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
+
+#define OMAP16XX_SRAM_BASE	0xD0000000
+#define OMAP1610_SRAM_SIZE	(SZ_16K)
+#define OMAP5912_SRAM_SIZE	0x3E800
+#define OMAP16XX_SRAM_START	0x20000000
+
+#define OMAP16XX_DSP_BASE	0xE0000000
+#define OMAP16XX_DSP_SIZE	0x28000
+#define OMAP16XX_DSP_START	0xE0000000
+
+#define OMAP16XX_DSPREG_BASE	0xE1000000
+#define OMAP16XX_DSPREG_SIZE	SZ_128K
+#define OMAP16XX_DSPREG_START	0xE1000000
+
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP1610_SRAM_IDLE_SUSPEND	(OMAP16XX_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
+#define OMAP5912_SRAM_IDLE_SUSPEND	(OMAP16XX_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
+#define OMAP1610_SRAM_API_SUSPEND	(OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
+
+/*
+ * ---------------------------------------------------------------------------
+ * Interrupts
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP_IH2_0_BASE		(0xfffe0000)
+#define OMAP_IH2_1_BASE		(0xfffe0100)
+#define OMAP_IH2_2_BASE		(0xfffe0200)
+#define OMAP_IH2_3_BASE		(0xfffe0300)
+
+#define OMAP_IH2_0_ITR		(OMAP_IH2_0_BASE + 0x00)
+#define OMAP_IH2_0_MIR		(OMAP_IH2_0_BASE + 0x04)
+#define OMAP_IH2_0_SIR_IRQ	(OMAP_IH2_0_BASE + 0x10)
+#define OMAP_IH2_0_SIR_FIQ	(OMAP_IH2_0_BASE + 0x14)
+#define OMAP_IH2_0_CONTROL	(OMAP_IH2_0_BASE + 0x18)
+#define OMAP_IH2_0_ILR0		(OMAP_IH2_0_BASE + 0x1c)
+#define OMAP_IH2_0_ISR		(OMAP_IH2_0_BASE + 0x9c)
+
+#define OMAP_IH2_1_ITR		(OMAP_IH2_1_BASE + 0x00)
+#define OMAP_IH2_1_MIR		(OMAP_IH2_1_BASE + 0x04)
+#define OMAP_IH2_1_SIR_IRQ	(OMAP_IH2_1_BASE + 0x10)
+#define OMAP_IH2_1_SIR_FIQ	(OMAP_IH2_1_BASE + 0x14)
+#define OMAP_IH2_1_CONTROL	(OMAP_IH2_1_BASE + 0x18)
+#define OMAP_IH2_1_ILR1		(OMAP_IH2_1_BASE + 0x1c)
+#define OMAP_IH2_1_ISR		(OMAP_IH2_1_BASE + 0x9c)
+
+#define OMAP_IH2_2_ITR		(OMAP_IH2_2_BASE + 0x00)
+#define OMAP_IH2_2_MIR		(OMAP_IH2_2_BASE + 0x04)
+#define OMAP_IH2_2_SIR_IRQ	(OMAP_IH2_2_BASE + 0x10)
+#define OMAP_IH2_2_SIR_FIQ	(OMAP_IH2_2_BASE + 0x14)
+#define OMAP_IH2_2_CONTROL	(OMAP_IH2_2_BASE + 0x18)
+#define OMAP_IH2_2_ILR2		(OMAP_IH2_2_BASE + 0x1c)
+#define OMAP_IH2_2_ISR		(OMAP_IH2_2_BASE + 0x9c)
+
+#define OMAP_IH2_3_ITR		(OMAP_IH2_3_BASE + 0x00)
+#define OMAP_IH2_3_MIR		(OMAP_IH2_3_BASE + 0x04)
+#define OMAP_IH2_3_SIR_IRQ	(OMAP_IH2_3_BASE + 0x10)
+#define OMAP_IH2_3_SIR_FIQ	(OMAP_IH2_3_BASE + 0x14)
+#define OMAP_IH2_3_CONTROL	(OMAP_IH2_3_BASE + 0x18)
+#define OMAP_IH2_3_ILR3		(OMAP_IH2_3_BASE + 0x1c)
+#define OMAP_IH2_3_ISR		(OMAP_IH2_3_BASE + 0x9c)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Clocks
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP16XX_ARM_IDLECT3	(CLKGEN_REG_BASE + 0x24)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Pin configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV6	(1 << 8)
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV7	(1 << 9)
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV8	(1 << 10)
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV9	(1 << 11)
+#define OMAP16XX_SUBLVDS_CONF_VALID	(1 << 13)
+
+/*
+ * ---------------------------------------------------------------------------
+ * TIPB bus interface
+ * ---------------------------------------------------------------------------
+ */
+#define TIPB_SWITCH_BASE		 (0xfffbc800)
+#define OMAP16XX_MMCSD2_SSW_MPU_CONF	(TIPB_SWITCH_BASE + 0x160)
+
+/* UART3 Registers Maping through MPU bus */
+#define UART3_RHR               (OMAP_UART3_BASE + 0)
+#define UART3_THR               (OMAP_UART3_BASE + 0)
+#define UART3_DLL               (OMAP_UART3_BASE + 0)
+#define UART3_IER               (OMAP_UART3_BASE + 4)
+#define UART3_DLH               (OMAP_UART3_BASE + 4)
+#define UART3_IIR               (OMAP_UART3_BASE + 8)
+#define UART3_FCR               (OMAP_UART3_BASE + 8)
+#define UART3_EFR               (OMAP_UART3_BASE + 8)
+#define UART3_LCR               (OMAP_UART3_BASE + 0x0C)
+#define UART3_MCR               (OMAP_UART3_BASE + 0x10)
+#define UART3_XON1_ADDR1        (OMAP_UART3_BASE + 0x10)
+#define UART3_XON2_ADDR2        (OMAP_UART3_BASE + 0x14)
+#define UART3_LSR               (OMAP_UART3_BASE + 0x14)
+#define UART3_TCR               (OMAP_UART3_BASE + 0x18)
+#define UART3_MSR               (OMAP_UART3_BASE + 0x18)
+#define UART3_XOFF1             (OMAP_UART3_BASE + 0x18)
+#define UART3_XOFF2             (OMAP_UART3_BASE + 0x1C)
+#define UART3_SPR               (OMAP_UART3_BASE + 0x1C)
+#define UART3_TLR               (OMAP_UART3_BASE + 0x1C)
+#define UART3_MDR1              (OMAP_UART3_BASE + 0x20)
+#define UART3_MDR2              (OMAP_UART3_BASE + 0x24)
+#define UART3_SFLSR             (OMAP_UART3_BASE + 0x28)
+#define UART3_TXFLL             (OMAP_UART3_BASE + 0x28)
+#define UART3_RESUME            (OMAP_UART3_BASE + 0x2C)
+#define UART3_TXFLH             (OMAP_UART3_BASE + 0x2C)
+#define UART3_SFREGL            (OMAP_UART3_BASE + 0x30)
+#define UART3_RXFLL             (OMAP_UART3_BASE + 0x30)
+#define UART3_SFREGH            (OMAP_UART3_BASE + 0x34)
+#define UART3_RXFLH             (OMAP_UART3_BASE + 0x34)
+#define UART3_BLR               (OMAP_UART3_BASE + 0x38)
+#define UART3_ACREG             (OMAP_UART3_BASE + 0x3C)
+#define UART3_DIV16             (OMAP_UART3_BASE + 0x3C)
+#define UART3_SCR               (OMAP_UART3_BASE + 0x40)
+#define UART3_SSR               (OMAP_UART3_BASE + 0x44)
+#define UART3_EBLR              (OMAP_UART3_BASE + 0x48)
+#define UART3_OSC_12M_SEL       (OMAP_UART3_BASE + 0x4C)
+#define UART3_MVR               (OMAP_UART3_BASE + 0x50)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Pulse-Width Light
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP16XX_PWL_BASE	(0xfffb5800)
+#define OMAP16XX_PWL_ENABLE	(OMAP16XX_PWL_BASE + 0x00)
+#define OMAP16XX_PWL_CLK_ENABLE	(OMAP16XX_PWL_BASE + 0x04)
+
+#endif /*  __ASM_ARCH_OMAP16XX_H */
+
diff -Nru a/include/asm-arm/arch-omap/omap5912.h b/include/asm-arm/arch-omap/omap5912.h
--- a/include/asm-arm/arch-omap/omap5912.h	2004-10-28 22:25:57 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,112 +0,0 @@
-/* linux/include/asm-arm/arch-omap/omap5912.h
- *
- * Hardware definitions for TI OMAP5912 processor.
- *
- * Written by Dirk Behme <dirk.behme@de.bosch.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_OMAP5912_H
-#define __ASM_ARCH_OMAP5912_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-/* OMAP5912 internal SRAM size is 250kByte */
-#define OMAP5912_SRAM_BASE	0xD0000000
-#define OMAP5912_SRAM_SIZE	0x3E800
-#define OMAP5912_SRAM_START	0x20000000
-
-#define OMAP5912_DSP_BASE	0xE0000000
-#define OMAP5912_DSP_SIZE	0x50000
-#define OMAP5912_DSP_START	0xE0000000
-
-#define OMAP5912_DSPREG_BASE	0xE1000000
-#define OMAP5912_DSPREG_SIZE	SZ_128K
-#define OMAP5912_DSPREG_START	0xE1000000
-
-/*
- * ----------------------------------------------------------------------------
- * Memory used by power management
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP5912_SRAM_IDLE_SUSPEND	(OMAP5912_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
-#define OMAP5912_SRAM_API_SUSPEND	(OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
-
-/*
- * ---------------------------------------------------------------------------
- * Interrupts
- * ---------------------------------------------------------------------------
- */
-#define OMAP_IH2_0_BASE		(0xfffe0000)
-#define OMAP_IH2_1_BASE		(0xfffe0100)
-#define OMAP_IH2_2_BASE		(0xfffe0200)
-#define OMAP_IH2_3_BASE		(0xfffe0300)
-
-#define OMAP_IH2_0_ITR		(OMAP_IH2_0_BASE + 0x00)
-#define OMAP_IH2_0_MIR		(OMAP_IH2_0_BASE + 0x04)
-#define OMAP_IH2_0_SIR_IRQ	(OMAP_IH2_0_BASE + 0x10)
-#define OMAP_IH2_0_SIR_FIQ	(OMAP_IH2_0_BASE + 0x14)
-#define OMAP_IH2_0_CONTROL	(OMAP_IH2_0_BASE + 0x18)
-#define OMAP_IH2_0_ILR0		(OMAP_IH2_0_BASE + 0x1c)
-#define OMAP_IH2_0_ISR		(OMAP_IH2_0_BASE + 0x9c)
-
-#define OMAP_IH2_1_ITR		(OMAP_IH2_1_BASE + 0x00)
-#define OMAP_IH2_1_MIR		(OMAP_IH2_1_BASE + 0x04)
-#define OMAP_IH2_1_SIR_IRQ	(OMAP_IH2_1_BASE + 0x10)
-#define OMAP_IH2_1_SIR_FIQ	(OMAP_IH2_1_BASE + 0x14)
-#define OMAP_IH2_1_CONTROL	(OMAP_IH2_1_BASE + 0x18)
-#define OMAP_IH2_1_ILR1		(OMAP_IH2_1_BASE + 0x1c)
-#define OMAP_IH2_1_ISR		(OMAP_IH2_1_BASE + 0x9c)
-
-#define OMAP_IH2_2_ITR		(OMAP_IH2_2_BASE + 0x00)
-#define OMAP_IH2_2_MIR		(OMAP_IH2_2_BASE + 0x04)
-#define OMAP_IH2_2_SIR_IRQ	(OMAP_IH2_2_BASE + 0x10)
-#define OMAP_IH2_2_SIR_FIQ	(OMAP_IH2_2_BASE + 0x14)
-#define OMAP_IH2_2_CONTROL	(OMAP_IH2_2_BASE + 0x18)
-#define OMAP_IH2_2_ILR2		(OMAP_IH2_2_BASE + 0x1c)
-#define OMAP_IH2_2_ISR		(OMAP_IH2_2_BASE + 0x9c)
-
-#define OMAP_IH2_3_ITR		(OMAP_IH2_3_BASE + 0x00)
-#define OMAP_IH2_3_MIR		(OMAP_IH2_3_BASE + 0x04)
-#define OMAP_IH2_3_SIR_IRQ	(OMAP_IH2_3_BASE + 0x10)
-#define OMAP_IH2_3_SIR_FIQ	(OMAP_IH2_3_BASE + 0x14)
-#define OMAP_IH2_3_CONTROL	(OMAP_IH2_3_BASE + 0x18)
-#define OMAP_IH2_3_ILR3		(OMAP_IH2_3_BASE + 0x1c)
-#define OMAP_IH2_3_ISR		(OMAP_IH2_3_BASE + 0x9c)
-
-/*
- * ----------------------------------------------------------------------------
- * System control registers
- * ----------------------------------------------------------------------------
- */
-
-#define OMAP5912_ARM_IDLECT3	(CLKGEN_REG_BASE + 0x24)
-
-#endif /*  __ASM_ARCH_OMAP5912_H */
-
diff -Nru a/include/asm-arm/arch-omap/pm.h b/include/asm-arm/arch-omap/pm.h
--- a/include/asm-arm/arch-omap/pm.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-arm/arch-omap/pm.h	2004-10-28 22:25:56 -07:00
@@ -1,13 +1,15 @@
 /*
- * FILE NAME include/asm/arch-omap/pm.h
+ * linux/include/asm/arch-omap/pm.h
  *
- * BRIEF MODULE DESCRIPTION
+ * Header file for OMAP Power Management Routines
  *
  * Author: MontaVista Software, Inc.
  *	   support@mvista.com
  *
  * Copyright 2002 MontaVista Software Inc.
  *
+ * Cleanup 2004 for Linux 2.6 by Dirk Behme <dirk.behme@de.bosch.com>
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -29,158 +31,199 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/*
- * List of global OMAP registers to preserve.  All registers are 16 bits
- * and must be accessed with 16 read/writes.
- * More ones like CP and general purpose register values are preserved
- * with the stack pointer in sleep.S.
- */
 #ifndef __ASM_ARCH_OMAP_PM_H
 #define __ASM_ARCH_OMAP_PM_H
 
-#define ARM_REG_BASE		(0xfffece00)
-#define ARM_ASM_IDLECT1		(ARM_REG_BASE + 0x4)
-#define ARM_ASM_IDLECT2		(ARM_REG_BASE + 0x8)
-#define ARM_ASM_RSTCT1		(ARM_REG_BASE + 0x10)
-#define ARM_ASM_RSTCT2		(ARM_REG_BASE + 0x14)
-#define ARM_ASM_SYSST		(ARM_REG_BASE + 0x18)
 /*
- * Traffic Controller Memory Interface Registers
+ * ----------------------------------------------------------------------------
+ * Register and offset definitions to be used in PM assembler code
+ * ----------------------------------------------------------------------------
  */
-#define TCMIF_BASE		0xfffecc00
-#define EMIFS_ASM_CONFIG_REG	(TCMIF_BASE + 0x0c)
-#define EMIFF_ASM_SDRAM_CONFIG	(TCMIF_BASE + 0x20)
-#define IRQ_MIR1		(OMAP_IH1_BASE + IRQ_MIR)
-
-#ifdef CONFIG_ARCH_OMAP1510
-#define IRQ_MIR2		(OMAP_IH2_BASE + IRQ_MIR)
-#else /* CONFIG_ARCH_OMAP1610 */
-#define IRQ_MIR2_0		(OMAP_IH2_0_BASE + IRQ_MIR)
-#define IRQ_MIR2_1		(OMAP_IH2_1_BASE + IRQ_MIR)
-#define IRQ_MIR2_2		(OMAP_IH2_2_BASE + IRQ_MIR)
-#define IRQ_MIR2_3		(OMAP_IH2_3_BASE + IRQ_MIR)
-#endif
+#define CLKGEN_REG_ASM_BASE		io_p2v(0xfffece00)
+#define ARM_IDLECT1_ASM_OFFSET		0x04
+#define ARM_IDLECT2_ASM_OFFSET		0x08
+
+#define TCMIF_ASM_BASE			io_p2v(0xfffecc00)
+#define EMIFS_CONFIG_ASM_OFFSET		0x0c
+#define EMIFF_SDRAM_CONFIG_ASM_OFFSET	0x20
 
+/*
+ * ----------------------------------------------------------------------------
+ * Powermanagement bitmasks
+ * ----------------------------------------------------------------------------
+ */
 #define IDLE_WAIT_CYCLES		0x00000fff
 #define PERIPHERAL_ENABLE		0x2
 
-#ifdef CONFIG_ARCH_OMAP1510
-#define DEEP_SLEEP_REQUEST		0x0ec7
-#define BIG_SLEEP_REQUEST		0x0cc5
-#define IDLE_LOOP_REQUEST		0x0c00
-#define IDLE_CLOCK_DOMAINS		0x2
-#else /* CONFIG_ARCH_OMAP1610 */
-#define DEEP_SLEEP_REQUEST		0x17c7
-#define BIG_SLEEP_REQUEST		TBD
-#define IDLE_LOOP_REQUEST		0x0400
-#define IDLE_CLOCK_DOMAINS		0x09c7
-#endif
-
 #define SELF_REFRESH_MODE		0x0c000001
 #define IDLE_EMIFS_REQUEST		0xc
 #define MODEM_32K_EN			0x1
+#define PER_EN				0x1
 
-#ifndef __ASSEMBLER__
-extern void omap_pm_idle(void);
-extern void omap_pm_suspend(void);
-extern int omap_cpu_suspend(unsigned short, unsigned short);
-extern int omap_idle_loop_suspend(void);
-
-#ifdef CONFIG_ARCH_OMAP1510
-#define OMAP_SRAM_IDLE_SUSPEND	0xd002F000
-#define OMAP_SRAM_API_SUSPEND	0xd002F200
-#else /* CONFIG_ARCH_OMAP1610 */
-#define OMAP_SRAM_IDLE_SUSPEND	0xd0000400
-#define OMAP_SRAM_API_SUSPEND	0xd0000600
-#endif
-
-#define CPU_SUSPEND_SIZE	200
-#define ARM_REG_BASE		(0xfffece00)
-#define ARM_ASM_IDLECT1		(ARM_REG_BASE + 0x4)
-#define ARM_ASM_IDLECT2		(ARM_REG_BASE + 0x8)
-#define ARM_ASM_RSTCT1		(ARM_REG_BASE + 0x10)
-#define ARM_ASM_RSTCT2		(ARM_REG_BASE + 0x14)
-#define ARM_ASM_SYSST		(ARM_REG_BASE + 0x18)
-
-#define TCMIF_BASE		0xfffecc00
-#define PM_EMIFS_CONFIG_REG	(TCMIF_BASE + 0x0c)
-#define PM_EMIFF_SDRAM_CONFIG	(TCMIF_BASE + 0x20)
-#define FUNC_MUX_CTRL_LOW_PWR	(0xfffe1020)
-
-#ifdef CONFIG_ARCH_OMAP1510
-#define ULPD_LOW_POWER_REQ             0x0001
-#else /* CONFIG_ARCH_OMAP1610 */
-#define ULPD_LOW_POWER_REQ             0x3
-#endif
-#define ULPD_LOW_PWR                   0x1000
-#define ULPD_LOW_POWER_EN              0x0001
+#define CPU_SUSPEND_SIZE		200
+#define ULPD_LOW_POWER_EN		0x0001
 
 #define DSP_IDLE_DELAY			10
 #define DSP_IDLE			0x0040
+#define DSP_RST				0x0004
 #define DSP_ENABLE			0x0002
 #define SUFFICIENT_DSP_RESET_TIME	1000
 #define DEFAULT_MPUI_CONFIG		0x05cf
 #define ENABLE_XORCLK			0x2
-#define DSP_RESET			0x2000
+#define DSP_CLOCK_ENABLE		0x2000
+#define DSP_IDLE_MODE			0x2
 #define TC_IDLE_REQUEST			(0x0000000c)
-#define EMIFF_CONFIG_REG		EMIFF_SDRAM_CONFIG
 
+#define IRQ_LEVEL2			(1<<0)
+#define IRQ_KEYBOARD			(1<<1)
+#define IRQ_UART2			(1<<15)
+
+#define PDE_BIT				0x08
+#define PWD_EN_BIT			0x04
+#define EN_PERCK_BIT			0x04
+
+#define OMAP1510_DEEP_SLEEP_REQUEST	0x0ec7
+#define OMAP1510_BIG_SLEEP_REQUEST	0x0cc5
+#define OMAP1510_IDLE_LOOP_REQUEST	0x0c00
+#define OMAP1510_IDLE_CLOCK_DOMAINS	0x2
+#define OMAP1510_ULPD_LOW_POWER_REQ	0x0001
+
+#define OMAP1610_DEEP_SLEEP_REQUEST	0x17c7
+#define OMAP1610_BIG_SLEEP_REQUEST	TBD
+#define OMAP1610_IDLE_LOOP_REQUEST	0x0400
+#define OMAP1610_IDLE_CLOCK_DOMAINS	0x09c7
+#define OMAP1610_ULPD_LOW_POWER_REQ	0x3
 
-#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readw(x)
-#define ARM_RESTORE(x) omap_writew((unsigned short)arm_sleep_save[ARM_SLEEP_SAVE_##x], x)
+#ifndef OMAP1510_SRAM_IDLE_SUSPEND
+#define OMAP1510_SRAM_IDLE_SUSPEND 0
+#endif
+#ifndef OMAP1610_SRAM_IDLE_SUSPEND
+#define OMAP1610_SRAM_IDLE_SUSPEND 0
+#endif
+#ifndef OMAP5912_SRAM_IDLE_SUSPEND
+#define OMAP5912_SRAM_IDLE_SUSPEND 0
+#endif
+
+#ifndef OMAP1510_SRAM_API_SUSPEND
+#define OMAP1510_SRAM_API_SUSPEND 0
+#endif
+#ifndef OMAP1610_SRAM_API_SUSPEND
+#define OMAP1610_SRAM_API_SUSPEND 0
+#endif
+#ifndef OMAP5912_SRAM_API_SUSPEND
+#define OMAP5912_SRAM_API_SUSPEND 0
+#endif
+
+#if     !defined(CONFIG_ARCH_OMAP1510) && \
+	!defined(CONFIG_ARCH_OMAP16XX)
+#error "Power management for this processor not implemented yet"
+#endif
+
+#ifndef __ASSEMBLER__
+extern void omap_pm_idle(void);
+extern void omap_pm_suspend(void);
+extern int omap1510_cpu_suspend(unsigned short, unsigned short);
+extern int omap1610_cpu_suspend(unsigned short, unsigned short);
+extern int omap1510_idle_loop_suspend(void);
+extern int omap1610_idle_loop_suspend(void);
+extern unsigned int omap1510_cpu_suspend_sz;
+extern unsigned int omap1510_idle_loop_suspend_sz;
+extern unsigned int omap1610_cpu_suspend_sz;
+extern unsigned int omap1610_idle_loop_suspend_sz;
+
+#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x)
+#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x))
 #define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x]
 
 #define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x)
-#define ULPD_RESTORE(x) omap_writew((unsigned short)ulpd_sleep_save[ULPD_SLEEP_SAVE_##x], x)
+#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x))
 #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]
 
-#define MPUI_SAVE(x) mpui_sleep_save[MPUI_SLEEP_SAVE_##x] = omap_readl(x)
-#define MPUI_RESTORE(x) omap_writel((unsigned int)mpui_sleep_save[MPUI_SLEEP_SAVE_##x], x)
-#define MPUI_SHOW(x) (unsigned int)mpui_sleep_save[MPUI_SLEEP_SAVE_##x]
+#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x))
+#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]
+
+#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x)
+#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x))
+#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]
+
+/*
+ * List of global OMAP registers to preserve.
+ * More ones like CP and general purpose register values are preserved
+ * with the stack pointer in sleep.S.
+ */
 
 enum arm_save_state {
 	ARM_SLEEP_SAVE_START = 0,
 	/*
-	 * 9 MPU control registers, all 16 bits
+	 * MPU control registers 32 bits
 	 */
-	ARM_SLEEP_SAVE_ARM_CKCTL, ARM_SLEEP_SAVE_ARM_IDLECT1,
-	ARM_SLEEP_SAVE_ARM_IDLECT2, ARM_SLEEP_SAVE_ARM_EWUPCT,
-	ARM_SLEEP_SAVE_ARM_RSTCT1, ARM_SLEEP_SAVE_ARM_RSTCT2,
+	ARM_SLEEP_SAVE_ARM_CKCTL,
+	ARM_SLEEP_SAVE_ARM_IDLECT1,
+	ARM_SLEEP_SAVE_ARM_IDLECT2,
+	ARM_SLEEP_SAVE_ARM_EWUPCT,
+	ARM_SLEEP_SAVE_ARM_RSTCT1,
+	ARM_SLEEP_SAVE_ARM_RSTCT2,
 	ARM_SLEEP_SAVE_ARM_SYSST,
-
 	ARM_SLEEP_SAVE_SIZE
 };
 
 enum ulpd_save_state {
 	ULPD_SLEEP_SAVE_START = 0,
-	ULPD_SLEEP_SAVE_ULPD_IT_STATUS_REG, ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL_REG,
-	ULPD_SLEEP_SAVE_ULPD_SOFT_REQ_REG, ULPD_SLEEP_SAVE_ULPD_STATUS_REQ_REG,
-	ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL_REG, ULPD_SLEEP_SAVE_ULPD_POWER_CTRL_REG,
+	/*
+	 * ULPD registers 16 bits
+	 */
+	ULPD_SLEEP_SAVE_ULPD_IT_STATUS,
+	ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL,
+	ULPD_SLEEP_SAVE_ULPD_SOFT_REQ,
+	ULPD_SLEEP_SAVE_ULPD_STATUS_REQ,
+	ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL,
+	ULPD_SLEEP_SAVE_ULPD_POWER_CTRL,
 	ULPD_SLEEP_SAVE_SIZE
 };
 
-enum mpui_save_state {
+enum mpui1510_save_state {
+	MPUI1510_SLEEP_SAVE_START = 0,
 	/*
 	 * MPUI registers 32 bits
 	 */
-	MPUI_SLEEP_SAVE_MPUI_CTRL_REG, MPUI_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
-	MPUI_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
-	MPUI_SLEEP_SAVE_MPUI_DSP_STATUS_REG,
-	MPUI_SLEEP_SAVE_PM_EMIFF_SDRAM_CONFIG,
-	MPUI_SLEEP_SAVE_PM_EMIFS_CONFIG_REG,
-	MPUI_SLEEP_SAVE_IRQ_MIR1,
-#ifdef CONFIG_ARCH_OMAP1510
-	MPUI_SLEEP_SAVE_IRQ_MIR2,
-#else /* CONFIG_ARCH_OMAP1610 */
-	MPUI_SLEEP_SAVE_IRQ_MIR2_0,
-	MPUI_SLEEP_SAVE_IRQ_MIR2_1,
-	MPUI_SLEEP_SAVE_IRQ_MIR2_2,
-	MPUI_SLEEP_SAVE_IRQ_MIR2_3,
+	MPUI1510_SLEEP_SAVE_MPUI_CTRL,
+	MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+	MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+	MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS,
+	MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+	MPUI1510_SLEEP_SAVE_EMIFS_CONFIG,
+	MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR,
+	MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR,
+#if defined(CONFIG_ARCH_OMAP1510)
+	MPUI1510_SLEEP_SAVE_SIZE
+#else
+	MPUI1510_SLEEP_SAVE_SIZE = 0
 #endif
-
-	MPUI_SLEEP_SAVE_SIZE
 };
 
-
-#endif	/* ASSEMBLER */
+enum mpui1610_save_state {
+	MPUI1610_SLEEP_SAVE_START = 0,
+	/*
+	 * MPUI registers 32 bits
+	 */
+	MPUI1610_SLEEP_SAVE_MPUI_CTRL,
+	MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG,
+	MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG,
+	MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS,
+	MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG,
+	MPUI1610_SLEEP_SAVE_EMIFS_CONFIG,
+	MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR,
+	MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR,
+#if defined(CONFIG_ARCH_OMAP16XX)
+	MPUI1610_SLEEP_SAVE_SIZE
+#else
+	MPUI1610_SLEEP_SAVE_SIZE = 0
 #endif
+};
+
+#endif /* ASSEMBLER */
+#endif /* __ASM_ARCH_OMAP_PM_H */
diff -Nru a/include/asm-arm/arch-omap/serial.h b/include/asm-arm/arch-omap/serial.h
--- a/include/asm-arm/arch-omap/serial.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/arch-omap/serial.h	2004-10-28 22:25:57 -07:00
@@ -12,6 +12,8 @@
 #define OMAP_UART1_BASE		(unsigned char *)0xfffb0000
 #define OMAP_UART2_BASE		(unsigned char *)0xfffb0800
 #define OMAP_UART3_BASE		(unsigned char *)0xfffb9800
+#define OMAP_MAX_NR_PORTS	3
+#define PORT_OMAP		16	/* Temporary */
 
 #ifndef __ASSEMBLY__
 
@@ -19,7 +21,9 @@
 #include <asm/irq.h>
 
 #define OMAP1510_BASE_BAUD	(12000000/16)
-#define OMAP1610_BASE_BAUD	(48000000/16)
+#define OMAP16XX_BASE_BAUD	(48000000/16)
+
+#define UART_SYSC		0x15
 
 /* OMAP FCR trigger  redefinitions */
 #define UART_FCR_R_TRIGGER_8	0x00	/* Mask for receive trigger set at 8 */
diff -Nru a/include/asm-arm/arch-omap/tc.h b/include/asm-arm/arch-omap/tc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-omap/tc.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,64 @@
+/*
+ * linux/include/asm-arm/arch-omap/tc.h
+ *
+ * OMAP Traffic Controller
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __ASM_ARCH_TC_H
+#define __ASM_ARCH_TC_H
+
+#define OMAP_TC_OCPT1_PRIOR	0xFFFECC00
+#define OMAP_TC_EMIFS_PRIOR	0xFFFECC04
+#define OMAP_TC_EMIFF_PRIOR	0xFFFECC08
+#define OMAP_TC_OCPT2_PRIOR	0xFFFECCD0
+
+
+/* EMIF Slow Interface Configuration Register */
+#define	OMAP_EMIFS_CONFIG_REG	__REG32(EMIFS_CONFIG)
+
+#define OMAP_EMIFS_CONFIG_FR		(1 << 4)
+#define OMAP_EMIFS_CONFIG_PDE		(1 << 3)
+#define OMAP_EMIFS_CONFIG_PWD_EN	(1 << 2)
+#define OMAP_EMIFS_CONFIG_BM		(1 << 1)
+#define OMAP_EMIFS_CONFIG_WP		(1 << 0)
+
+/* external EMIFS chipselect regions */
+#define	OMAP_CS1_PHYS		0x04000000
+#define	OMAP_CS1_SIZE		SZ_64M
+
+#define	OMAP_CS1A_PHYS		OMAP_CS1_PHYS
+#define	OMAP_CS1A_SIZE		SZ_32M
+
+#define	OMAP_CS1B_PHYS		(OMAP_CS1A_PHYS + OMAP_CS1A_SIZE)
+#define	OMAP_CS1B_SIZE		SZ_32M
+
+#define	OMAP_CS2_PHYS		0x08000000
+#define	OMAP_CS2_SIZE		SZ_64M
+
+#define	OMAP_CS2A_PHYS		OMAP_CS2_PHYS
+#define	OMAP_CS2A_SIZE		SZ_32M
+
+#define	OMAP_CS2B_PHYS		(OMAP_CS2A_PHYS + OMAP_CS2A_SIZE)
+#define	OMAP_CS2B_SIZE		SZ_32M
+
+#define	OMAP_CS3_PHYS		0x0c000000
+#define	OMAP_CS3_SIZE		SZ_64M
+
+#endif	/* __ASM_ARCH_TC_H */
diff -Nru a/include/asm-arm/arch-omap/timex.h b/include/asm-arm/arch-omap/timex.h
--- a/include/asm-arm/arch-omap/timex.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-arm/arch-omap/timex.h	2004-10-28 22:25:56 -07:00
@@ -28,8 +28,6 @@
 #if !defined(__ASM_ARCH_OMAP_TIMEX_H)
 #define __ASM_ARCH_OMAP_TIMEX_H
 
-#include <asm/arch/clocks.h>
-/* TC clock */
-#define CLOCK_TICK_RATE		((OMAP_CK_MAX_RATE*1000000)/2)
+#define CLOCK_TICK_RATE		(HZ * 100000UL)
 
 #endif /* __ASM_ARCH_OMAP_TIMEX_H */
diff -Nru a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h
--- a/include/asm-arm/arch-omap/uncompress.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-arm/arch-omap/uncompress.h	2004-10-28 22:25:59 -07:00
@@ -20,10 +20,13 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/serial_reg.h>
-#include <asm/hardware.h>
 #include <asm/arch/serial.h>
 
+unsigned int system_rev;
+
 #define UART_OMAP_MDR1		0x08	/* mode definition register */
+#define OMAP_ID_730		0x355F
+#define ID_MASK			0x7fff
 #define check_port(base, shift) ((base[UART_OMAP_MDR1 << shift] & 7) == 0)
 #define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK
 
@@ -31,7 +34,7 @@
 putstr(const char *s)
 {
 	volatile u8 * uart = 0;
-	int shift = 0;
+	int shift;
 
 #ifdef	CONFIG_OMAP_LL_DEBUG_UART3
 	uart = (volatile u8 *)(OMAP_UART3_BASE);
@@ -46,21 +49,11 @@
 		/* MMU is not on, so cpu_is_omapXXXX() won't work here */
 		unsigned int omap_id = omap_get_id();
 
-		if (omap_id == OMAP_ID_1510 || omap_id == OMAP_ID_1610 ||
-		    omap_id == OMAP_ID_1710 || omap_id == OMAP_ID_5912) {
-			shift = 2;
-		} else if (omap_id == OMAP_ID_730) {
+		if (omap_id == OMAP_ID_730)
 			shift = 0;
-		} else {
-			/* Assume nothing for unknown OMAP processors.
-			 * Add an entry for your OMAP type to select
-			 * the default serial console here. If the
-			 * serial port is enabled, we'll use it to
-			 * display status messages. Else we'll be
-			 * quiet.
-			 */
-			return;
-		}
+		else
+			shift = 2;
+
 		if (check_port(uart, shift))
 			break;
 		/* Silent boot if no serial ports are enabled. */
diff -Nru a/include/asm-arm/arch-s3c2410/bast-pmu.h b/include/asm-arm/arch-s3c2410/bast-pmu.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/bast-pmu.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,43 @@
+/* linux/include/asm-arm/arch-s3c2410/bast-pmu.h
+ *
+ * (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	Vincent Sanders <vince@simtec.co.uk>
+ *
+ * Machine BAST - Power Management chip
+ *
+ * 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.
+ *
+ * Changelog:
+ *	08-Oct-2003	BJD	Initial creation
+*/
+
+#ifndef __ASM_ARCH_BASTPMU_H
+#define __ASM_ARCH_BASTPMU_H "08_OCT_2004"
+
+#define BASTPMU_REG_IDENT	(0x00)
+#define BASTPMU_REG_VERSION	(0x01)
+#define BASTPMU_REG_DDCCTRL	(0x02)
+#define BASTPMU_REG_POWER	(0x03)
+#define BASTPMU_REG_RESET	(0x04)
+#define BASTPMU_REG_GWO		(0x05)
+#define BASTPMU_REG_WOL		(0x06)
+#define BASTPMU_REG_WOR		(0x07)
+#define BASTPMU_REG_UID		(0x09)
+
+#define BASTPMU_EEPROM		(0xC0)
+
+#define BASTPMU_EEP_UID		(BASTPMU_EEPROM + 0)
+#define BASTPMU_EEP_WOL		(BASTPMU_EEPROM + 8)
+#define BASTPMU_EEP_WOR		(BASTPMU_EEPROM + 9)
+
+#define BASTPMU_IDENT_0		0x53
+#define BASTPMU_IDENT_1		0x42
+#define BASTPMU_IDENT_2		0x50
+#define BASTPMU_IDENT_3		0x4d
+
+#define BASTPMU_RESET_GUARD	(0x55)
+
+#endif /* __ASM_ARCH_BASTPMU_H */
diff -Nru a/include/asm-arm/arch-s3c2410/iic.h b/include/asm-arm/arch-s3c2410/iic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/iic.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,36 @@
+/* linux/include/asm-arm/arch-s3c2410/iic.h
+ *
+ * (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 - I2C Controller platfrom_device info
+ *
+ * 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.
+ *
+ * Changelog:
+ *	05-Oct-2004 BJD  Created file
+ *	19-Oct-2004 BJD	 Updated for s3c2440
+*/
+
+#ifndef __ASM_ARCH_IIC_H
+#define __ASM_ARCH_IIC_H __FILE__
+
+#define S3C_IICFLG_FILTER	(1<<0)	/* enable s3c2440 filter */
+
+/* Notes:
+ *	1) All frequencies are expressed in Hz
+ *	2) A value of zero is `do not care`
+*/
+
+struct s3c2410_platform_i2c {
+	unsigned int	flags;
+	unsigned int	slave_addr;	/* slave address for controller */
+	unsigned long	bus_freq;	/* standard bus frequency */
+	unsigned long	max_freq;	/* max frequency for the bus */
+	unsigned long	min_freq;	/* min frequency for the bus */
+	unsigned int	sda_delay;	/* pclks (s3c2440 only) */
+};
+
+#endif /* __ASM_ARCH_IIC_H */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-iic.h b/include/asm-arm/arch-s3c2410/regs-iic.h
--- a/include/asm-arm/arch-s3c2410/regs-iic.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-arm/arch-s3c2410/regs-iic.h	2004-10-28 22:25:56 -07:00
@@ -13,8 +13,8 @@
  *	03-Oct-2004  BJD  Initial include for Linux
 */
 
-#ifndef __ASM_ARCH_IIC_H
-#define __ASM_ARCH_IIC_H __FILE__
+#ifndef __ASM_ARCH_REGS_IIC_H
+#define __ASM_ARCH_REGS_IIC_H __FILE__
 
 /* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
 
@@ -47,4 +47,4 @@
 #define S3C2410_IICSTAT_ADDR0		(1<<1)
 #define S3C2410_IICSTAT_LASTBIT		(1<<0)
 
-#endif /* __ASM_ARCH_IIC_H */
+#endif /* __ASM_ARCH_REGS_IIC_H */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h	2004-10-28 22:25:59 -07:00
@@ -29,7 +29,7 @@
 #define S3C2410_LCDCON5	    S3C2410_LCDREG(0x10)
 
 #define S3C2410_LCDCON1_CLKVAL(x)  ((x) << 8)
-#define S3C2410_LCDCON1_MMODE	   (1<<6)
+#define S3C2410_LCDCON1_MMODE	   (1<<7)
 #define S3C2410_LCDCON1_DSCAN4	   (0<<5)
 #define S3C2410_LCDCON1_STN4	   (1<<5)
 #define S3C2410_LCDCON1_STN8	   (2<<5)
@@ -48,15 +48,15 @@
 #define S3C2410_LCDCON1_TFT16BPP   (12<<1)
 #define S3C2410_LCDCON1_TFT24BPP   (13<<1)
 
-#define S3C2410_LCDCON1_ENVDI	   (1)
+#define S3C2410_LCDCON1_ENVID	   (1)
 
 #define S3C2410_LCDCON2_VBPD(x)	    ((x) << 24)
 #define S3C2410_LCDCON2_LINEVAL(x)  ((x) << 14)
 #define S3C2410_LCDCON2_VFPD(x)	    ((x) << 6)
 #define S3C2410_LCDCON2_VSPW(x)	    ((x) << 0)
 
-#define S3C2410_LCDCON3_HBPD(x)	    ((x) << 25)
-#define S3C2410_LCDCON3_WDLY(x)	    ((x) << 25)
+#define S3C2410_LCDCON3_HBPD(x)	    ((x) << 19)
+#define S3C2410_LCDCON3_WDLY(x)	    ((x) << 19)
 #define S3C2410_LCDCON3_HOZVAL(x)   ((x) << 8)
 #define S3C2410_LCDCON3_HFPD(x)	    ((x) << 0)
 #define S3C2410_LCDCON3_LINEBLANK(x)((x) << 0)
@@ -83,6 +83,12 @@
 #define S3C2410_LCDSADDR1   S3C2410_LCDREG(0x14)
 #define S3C2410_LCDSADDR2   S3C2410_LCDREG(0x18)
 #define S3C2410_LCDSADDR3   S3C2410_LCDREG(0x1C)
+
+#define S3C2410_LCDBANK(x)	((x) << 21)
+#define S3C2410_LCDBASEU(x)	(x)
+
+#define S3C2410_OFFSIZE(x)	((x) << 11)
+#define S3C2410_PAGEWIDTH(x)	(x)
 
 /* colour lookup and miscellaneous controls */
 
diff -Nru a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
--- a/include/asm-arm/arch-s3c2410/regs-serial.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h	2004-10-28 22:25:58 -07:00
@@ -66,6 +66,7 @@
 #define S3C2410_LCON_PMASK	  (0x7 << 3)
 
 #define S3C2410_LCON_STOPB	  (1<<2)
+#define S3C2410_LCON_IRM          (1<<6)
 
 #define S3C2410_UCON_UCLK	  (1<<10)
 #define S3C2410_UCON_SBREAK	  (1<<4)
@@ -97,6 +98,14 @@
 #define S3C2410_UFSTAT_RXMASK	  (15<<0)
 #define S3C2410_UFSTAT_RXSHIFT	  (0)
 
+#define S3C2440_UFSTAT_TXFULL	  (1<<14)
+#define S3C2440_UFSTAT_RXFULL	  (1<<6)
+#define S3C2440_UFSTAT_TXSHIFT	  (8)
+#define S3C2440_UFSTAT_RXSHIFT	  (0)
+#define S3C2440_UFSTAT_TXMASK	  (63<<8)
+#define S3C2440_UFSTAT_RXMASK	  (63)
+
+#define S3C2410_UTRSTAT_TXE	  (1<<2)
 #define S3C2410_UTRSTAT_TXFE	  (1<<1)
 #define S3C2410_UTRSTAT_RXDR	  (1<<0)
 
diff -Nru a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
--- a/include/asm-arm/arch-s3c2410/regs-udc.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/arch-s3c2410/regs-udc.h	2004-10-28 22:25:57 -07:00
@@ -8,8 +8,9 @@
  * the License, or (at your option) any later version.
  *
  *  Changelog:
- *    01-08-2004	initial creation
- *    12-09-2004	cleanup for submission
+ *    01-08-2004	Initial creation
+ *    12-09-2004	Cleanup for submission
+ *    24-10-2004	Fixed S3C2410_UDC_MAXP_REG definition
  */
 
 #ifndef __ASM_ARCH_REGS_UDC_H
@@ -68,7 +69,7 @@
 
 /* indexed registers */
 
-#define S3C2410_UDC_MAXP_REG		S3C2410_USBDREG(0x018c)
+#define S3C2410_UDC_MAXP_REG		S3C2410_USBDREG(0x0180)
 
 #define S3C2410_UDC_EP0_CSR_REG		S3C2410_USBDREG(0x0184)
 
diff -Nru a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
--- a/include/asm-arm/arch-s3c2410/uncompress.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-arm/arch-s3c2410/uncompress.h	2004-10-28 22:25:59 -07:00
@@ -13,21 +13,29 @@
  *  22-May-2003 BJD  Created
  *  08-Sep-2003 BJD  Moved to linux v2.6
  *  12-Mar-2004 BJD  Updated header protection
+ *  12-Oct-2004 BJD  Take account of debug uart configuration
 */
 
 #ifndef __ASM_ARCH_UNCOMPRESS_H
 #define __ASM_ARCH_UNCOMPRESS_H
 
+#include <config/debug/s3c2410/port.h>
+
 /* defines for UART registers */
 #include "asm/arch/regs-serial.h"
+#include "asm/arch/regs-gpio.h"
 
 #include <asm/arch/map.h>
 
+/* working in physical space... */
+#undef S3C2410_GPIOREG
+#define S3C2410_GPIOREG(x) ((S3C2410_PA_GPIO + (x)))
+
 /* how many bytes we allow into the FIFO at a time in FIFO mode */
 #define FIFO_MAX	 (14)
 
 #if 1
-#define uart_base S3C2410_PA_UART
+#define uart_base S3C2410_PA_UART + (0x4000 * CONFIG_DEBUG_S3C2410_UART)
 #else
 static unsigned int uart_base = S3C2410_PA_UART;
 #endif
@@ -74,6 +82,10 @@
 static void
 putc(char ch)
 {
+	int cpuid = *((volatile unsigned int *)S3C2410_GSTATUS1);
+
+	cpuid &= S3C2410_GSTATUS1_IDMASK;
+
 	if (ch == '\n')
 		putc('\r');    /* expand newline to \r\n */
 
@@ -82,8 +94,14 @@
 
 		while (1) {
 			level = uart_rd(S3C2410_UFSTAT);
-			level &= S3C2410_UFSTAT_TXMASK;
-			level >>= S3C2410_UFSTAT_TXSHIFT;
+
+			if (cpuid == S3C2410_GSTATUS1_2440) {
+				level &= S3C2440_UFSTAT_TXMASK;
+				level >>= S3C2440_UFSTAT_TXSHIFT;
+			} else {
+				level &= S3C2410_UFSTAT_TXMASK;
+				level >>= S3C2410_UFSTAT_TXSHIFT;
+			}
 
 			if (level < FIFO_MAX)
 				break;
@@ -92,7 +110,7 @@
 	} else {
 		/* not using fifos */
 
-		while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXFE) != S3C2410_UTRSTAT_TXFE);
+		while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE);
 	}
 
 	/* write byte to transmission register */
diff -Nru a/include/asm-arm/io.h b/include/asm-arm/io.h
--- a/include/asm-arm/io.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-arm/io.h	2004-10-28 22:25:57 -07:00
@@ -136,6 +136,8 @@
 extern void _memcpy_toio(void __iomem *, const void *, size_t);
 extern void _memset_io(void __iomem *, int, size_t);
 
+#define mmiowb()
+
 /*
  *  Memory access primitives
  *  ------------------------
diff -Nru a/include/asm-arm/posix_types.h b/include/asm-arm/posix_types.h
--- a/include/asm-arm/posix_types.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-arm/posix_types.h	2004-10-28 22:25:56 -07:00
@@ -62,19 +62,19 @@
 
 #undef	__FD_SET
 #define __FD_SET(fd, fdsetp) \
-		(((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
+		(((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] |= (1<<((fd) & 31)))
 
 #undef	__FD_CLR
 #define __FD_CLR(fd, fdsetp) \
-		(((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31)))
+		(((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] &= ~(1<<((fd) & 31)))
 
 #undef	__FD_ISSET
 #define __FD_ISSET(fd, fdsetp) \
-		((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0)
+		((((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] & (1<<((fd) & 31))) != 0)
 
 #undef	__FD_ZERO
 #define __FD_ZERO(fdsetp) \
-		(memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp)))
+		(memset (fdsetp, 0, sizeof (*(fd_set *)(fdsetp))))
 
 #endif
 
diff -Nru a/include/asm-arm26/io.h b/include/asm-arm26/io.h
--- a/include/asm-arm26/io.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-arm26/io.h	2004-10-28 22:25:58 -07:00
@@ -320,6 +320,8 @@
 #define writesw(p,d,l)                        __readwrite_bug("writesw")
 #define writesl(p,d,l)                        __readwrite_bug("writesl")
 
+#define mmiowb()
+
 /* the following macro is depreciated */
 #define ioaddr(port)                    __ioaddr((port))
 
diff -Nru a/include/asm-cris/io.h b/include/asm-cris/io.h
--- a/include/asm-cris/io.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-cris/io.h	2004-10-28 22:25:59 -07:00
@@ -56,6 +56,8 @@
 #define __raw_writew writew
 #define __raw_writel writel
 
+#define mmiowb()
+
 #define memset_io(a,b,c)	memset((void *)(a),(b),(c))
 #define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
 #define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
diff -Nru a/include/asm-generic/errno.h b/include/asm-generic/errno.h
--- a/include/asm-generic/errno.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-generic/errno.h	2004-10-28 22:25:57 -07:00
@@ -96,9 +96,10 @@
 
 #define	ENOMEDIUM	123	/* No medium found */
 #define	EMEDIUMTYPE	124	/* Wrong medium type */
-#define	ENOKEY		125	/* Required key not available */
-#define	EKEYEXPIRED	126	/* Key has expired */
-#define	EKEYREVOKED	127	/* Key has been revoked */
-#define	EKEYREJECTED	128	/* Key was rejected by service */
+#define	ECANCELED	125	/* Operation Canceled */
+#define	ENOKEY		126	/* Required key not available */
+#define	EKEYEXPIRED	127	/* Key has expired */
+#define	EKEYREVOKED	128	/* Key has been revoked */
+#define	EKEYREJECTED	129	/* Key was rejected by service */
 
 #endif
diff -Nru a/include/asm-generic/pci.h b/include/asm-generic/pci.h
--- a/include/asm-generic/pci.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-generic/pci.h	2004-10-28 22:25:58 -07:00
@@ -24,4 +24,11 @@
 
 #define pcibios_scan_all_fns(a, b)	0
 
+#ifndef HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	return channel ? 15 : 14;
+}
+#endif /* HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ */
+
 #endif
diff -Nru a/include/asm-h8300/io.h b/include/asm-h8300/io.h
--- a/include/asm-h8300/io.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-h8300/io.h	2004-10-28 22:25:58 -07:00
@@ -200,6 +200,8 @@
 #define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
 #define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
 
+#define mmiowb()
+
 #define inb(addr)    ((h8300_buswidth(addr))?readw((addr) & ~1) & 0xff:readb(addr))
 #define inw(addr)    _swapw(readw(addr))
 #define inl(addr)    _swapl(readl(addr))
diff -Nru a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
--- a/include/asm-i386/hpet.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-i386/hpet.h	2004-10-28 22:25:58 -07:00
@@ -96,6 +96,7 @@
 
 extern int hpet_rtc_timer_init(void);
 extern int hpet_enable(void);
+extern int hpet_reenable(void);
 extern int is_hpet_enabled(void);
 extern int is_hpet_capable(void);
 extern int hpet_readl(unsigned long a);
diff -Nru a/include/asm-i386/i387.h b/include/asm-i386/i387.h
--- a/include/asm-i386/i387.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-i386/i387.h	2004-10-28 22:25:59 -07:00
@@ -117,7 +117,5 @@
  */
 extern int dump_fpu( struct pt_regs *regs,
 		     struct user_i387_struct *fpu );
-extern int dump_extended_fpu( struct pt_regs *regs,
-			      struct user_fxsr_struct *fpu );
 
 #endif /* __ASM_I386_I387_H */
diff -Nru a/include/asm-i386/io.h b/include/asm-i386/io.h
--- a/include/asm-i386/io.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-i386/io.h	2004-10-28 22:25:59 -07:00
@@ -178,6 +178,8 @@
 #define __raw_writew writew
 #define __raw_writel writel
 
+#define mmiowb()
+
 static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
 {
 	memset((void __force *) addr, val, count);
diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h
--- a/include/asm-i386/page.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-i386/page.h	2004-10-28 22:25:57 -07:00
@@ -63,6 +63,7 @@
 #define HPAGE_SIZE	((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 #endif
 
 
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-i386/unistd.h	2004-10-28 22:25:58 -07:00
@@ -290,7 +290,7 @@
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
 #define __NR_sys_kexec_load	283
 #define __NR_waitid		284
-#define __NR_sys_setaltroot	285
+/* #define __NR_sys_setaltroot	285 */
 #define __NR_add_key		286
 #define __NR_request_key	287
 #define __NR_keyctl		288
diff -Nru a/include/asm-ia64/io.h b/include/asm-ia64/io.h
--- a/include/asm-ia64/io.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-ia64/io.h	2004-10-28 22:25:56 -07:00
@@ -32,7 +32,8 @@
  */
 #define IO_SPACE_LIMIT		0xffffffffffffffffUL
 
-#define MAX_IO_SPACES			16
+#define MAX_IO_SPACES_BITS		4
+#define MAX_IO_SPACES			(1UL << MAX_IO_SPACES_BITS)
 #define IO_SPACE_BITS			24
 #define IO_SPACE_SIZE			(1UL << IO_SPACE_BITS)
 
@@ -52,10 +53,24 @@
 
 # ifdef __KERNEL__
 
+/*
+ * All MMIO iomem cookies are in region 6; anything less is a PIO cookie:
+ *	0xCxxxxxxxxxxxxxxx	MMIO cookie (return from ioremap)
+ *	0x000000001SPPPPPP	PIO cookie (S=space number, P..P=port)
+ *
+ * ioread/writeX() uses the leading 1 in PIO cookies (PIO_OFFSET) to catch
+ * code that uses bare port numbers without the prerequisite pci_iomap().
+ */
+#define PIO_OFFSET		(1UL << (MAX_IO_SPACES_BITS + IO_SPACE_BITS))
+#define PIO_MASK		(PIO_OFFSET - 1)
+#define PIO_RESERVED		__IA64_UNCACHED_OFFSET
+#define HAVE_ARCH_PIO_SIZE
+
 #include <asm/intrinsics.h>
 #include <asm/machvec.h>
 #include <asm/page.h>
 #include <asm/system.h>
+#include <asm-generic/iomap.h>
 
 /*
  * Change virtual addresses to physical addresses and vv.
@@ -91,6 +106,20 @@
  */
 #define __ia64_mf_a()	ia64_mfa()
 
+/**
+ * ___ia64_mmiowb - I/O write barrier
+ *
+ * Ensure ordering of I/O space writes.  This will make sure that writes
+ * following the barrier will arrive after all previous writes.  For most
+ * ia64 platforms, this is a simple 'mf.a' instruction.
+ *
+ * See Documentation/DocBook/deviceiobook.tmpl for more information.
+ */
+static inline void ___ia64_mmiowb(void)
+{
+	ia64_mfa();
+}
+
 static inline const unsigned long
 __ia64_get_io_port_base (void)
 {
@@ -133,6 +162,7 @@
 #define __ia64_writew	___ia64_writew
 #define __ia64_writel	___ia64_writel
 #define __ia64_writeq	___ia64_writeq
+#define __ia64_mmiowb	___ia64_mmiowb
 
 /*
  * For the in/out routines, we need to do "mf.a" _after_ doing the I/O access to ensure
@@ -267,6 +297,7 @@
 #define __outb		platform_outb
 #define __outw		platform_outw
 #define __outl		platform_outl
+#define __mmiowb	platform_mmiowb
 
 #define inb(p)		__inb(p)
 #define inw(p)		__inw(p)
@@ -280,6 +311,7 @@
 #define outsb(p,s,c)	__outsb(p,s,c)
 #define outsw(p,s,c)	__outsw(p,s,c)
 #define outsl(p,s,c)	__outsl(p,s,c)
+#define mmiowb()	__mmiowb()
 
 /*
  * The address passed to these functions are ioremap()ped already.
diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
--- a/include/asm-ia64/machvec.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-ia64/machvec.h	2004-10-28 22:25:58 -07:00
@@ -62,6 +62,7 @@
 typedef void ia64_mv_outb_t (unsigned char, unsigned long);
 typedef void ia64_mv_outw_t (unsigned short, unsigned long);
 typedef void ia64_mv_outl_t (unsigned int, unsigned long);
+typedef void ia64_mv_mmiowb_t (void);
 typedef unsigned char ia64_mv_readb_t (const volatile void __iomem *);
 typedef unsigned short ia64_mv_readw_t (const volatile void __iomem *);
 typedef unsigned int ia64_mv_readl_t (const volatile void __iomem *);
@@ -130,6 +131,7 @@
 #  define platform_outb		ia64_mv.outb
 #  define platform_outw		ia64_mv.outw
 #  define platform_outl		ia64_mv.outl
+#  define platform_mmiowb	ia64_mv.mmiowb
 #  define platform_readb        ia64_mv.readb
 #  define platform_readw        ia64_mv.readw
 #  define platform_readl        ia64_mv.readl
@@ -176,6 +178,7 @@
 	ia64_mv_outb_t *outb;
 	ia64_mv_outw_t *outw;
 	ia64_mv_outl_t *outl;
+	ia64_mv_mmiowb_t *mmiowb;
 	ia64_mv_readb_t *readb;
 	ia64_mv_readw_t *readw;
 	ia64_mv_readl_t *readl;
@@ -218,6 +221,7 @@
 	platform_outb,				\
 	platform_outw,				\
 	platform_outl,				\
+	platform_mmiowb,			\
 	platform_readb,				\
 	platform_readw,				\
 	platform_readl,				\
@@ -343,6 +347,9 @@
 #endif
 #ifndef platform_outl
 # define platform_outl		__ia64_outl
+#endif
+#ifndef platform_mmiowb
+# define platform_mmiowb	__ia64_mmiowb
 #endif
 #ifndef platform_readb
 # define platform_readb		__ia64_readb
diff -Nru a/include/asm-ia64/machvec_init.h b/include/asm-ia64/machvec_init.h
--- a/include/asm-ia64/machvec_init.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ia64/machvec_init.h	2004-10-28 22:25:59 -07:00
@@ -12,6 +12,7 @@
 extern ia64_mv_outb_t __ia64_outb;
 extern ia64_mv_outw_t __ia64_outw;
 extern ia64_mv_outl_t __ia64_outl;
+extern ia64_mv_mmiowb_t __ia64_mmiowb;
 extern ia64_mv_readb_t __ia64_readb;
 extern ia64_mv_readw_t __ia64_readw;
 extern ia64_mv_readl_t __ia64_readl;
diff -Nru a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
--- a/include/asm-ia64/machvec_sn2.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ia64/machvec_sn2.h	2004-10-28 22:25:57 -07:00
@@ -49,6 +49,7 @@
 extern ia64_mv_outb_t __sn_outb;
 extern ia64_mv_outw_t __sn_outw;
 extern ia64_mv_outl_t __sn_outl;
+extern ia64_mv_mmiowb_t __sn_mmiowb;
 extern ia64_mv_readb_t __sn_readb;
 extern ia64_mv_readw_t __sn_readw;
 extern ia64_mv_readl_t __sn_readl;
@@ -92,6 +93,7 @@
 #define platform_outb			__sn_outb
 #define platform_outw			__sn_outw
 #define platform_outl			__sn_outl
+#define platform_mmiowb			__sn_mmiowb
 #define platform_readb			__sn_readb
 #define platform_readw			__sn_readw
 #define platform_readl			__sn_readl
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
--- a/include/asm-ia64/pgtable.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ia64/pgtable.h	2004-10-28 22:25:57 -07:00
@@ -6,7 +6,7 @@
  * the IA-64 page table tree.
  *
  * This hopefully works with any (fixed) IA-64 page-size, as defined
- * in <asm/page.h> (currently 8192).
+ * in <asm/page.h>.
  *
  * Copyright (C) 1998-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
@@ -309,15 +309,15 @@
 }
 
 /* The offset in the 1-level directory is given by the 3 region bits
-   (61..63) and the seven level-1 bits (33-39).  */
+   (61..63) and the level-1 bits.  */
 static inline pgd_t*
 pgd_offset (struct mm_struct *mm, unsigned long address)
 {
 	return mm->pgd + pgd_index(address);
 }
 
-/* In the kernel's mapped region we have a full 43 bit space available and completely
-   ignore the region number (since we know its in region number 5). */
+/* In the kernel's mapped region we completely ignore the region number
+   (since we know it's in region number 5). */
 #define pgd_offset_k(addr) \
 	(init_mm.pgd + (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)))
 
diff -Nru a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h
--- a/include/asm-ia64/sn/intr.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ia64/sn/intr.h	2004-10-28 22:25:57 -07:00
@@ -43,7 +43,7 @@
 	int		irq_share_cnt;	/* num devices sharing IRQ   */
 };
 
-extern void sn_send_IPI_phys(long, int, int);
+extern void sn_send_IPI_phys(int, long, int, int);
 
 #define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector)
 
diff -Nru a/include/asm-ia64/sn/io.h b/include/asm-ia64/sn/io.h
--- a/include/asm-ia64/sn/io.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-ia64/sn/io.h	2004-10-28 22:25:56 -07:00
@@ -12,7 +12,7 @@
 #include <asm/intrinsics.h>
 
 extern void * sn_io_addr(unsigned long port) __attribute_const__; /* Forward definition */
-extern void sn_mmiob(void); /* Forward definition */
+extern void __sn_mmiowb(void); /* Forward definition */
 
 extern int numionodes;
 
@@ -93,7 +93,7 @@
 
 	if ((addr = sn_io_addr(port))) {
 		*addr = val;
-		sn_mmiob();
+		__sn_mmiowb();
 	}
 }
 
@@ -104,7 +104,7 @@
 
 	if ((addr = sn_io_addr(port))) {
 		*addr = val;
-		sn_mmiob();
+		__sn_mmiowb();
 	}
 }
 
@@ -115,7 +115,7 @@
 
 	if ((addr = sn_io_addr(port))) {
 		*addr = val;
-		sn_mmiob();
+		__sn_mmiowb();
 	}
 }
 
diff -Nru a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h
--- a/include/asm-ia64/sn/nodepda.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ia64/sn/nodepda.h	2004-10-28 22:25:57 -07:00
@@ -30,6 +30,12 @@
  * This structure provides a convenient way of keeping together 
  * all per-node data structures. 
  */
+struct phys_cpuid {
+	short			nasid;
+	char			subnode;
+	char			slice;
+};
+
 struct nodepda_s {
 	void 		*pdinfo;	/* Platform-dependent per-node info */
 	spinlock_t		bist_lock;
@@ -46,6 +52,10 @@
 	 */
 	struct nodepda_s	*pernode_pdaindr[MAX_COMPACT_NODES]; 
 
+	/*
+	 * Array of physical cpu identifiers. Indexed by cpuid.
+	 */
+	struct phys_cpuid	phys_cpuid[NR_CPUS];
 };
 
 typedef struct nodepda_s nodepda_t;
diff -Nru a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h
--- a/include/asm-ia64/sn/sn2/sn_hwperf.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ia64/sn/sn2/sn_hwperf.h	2004-10-28 22:25:59 -07:00
@@ -41,7 +41,15 @@
 #define sn_hwp_is_shared	f.fields.is_shared
 #define sn_hwp_flags		f.b.flags
 
-#define SN_HWPERF_FOREIGN(x)	(!(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
+/* macros for object classification */
+#define SN_HWPERF_IS_NODE(x)		((x) && strstr((x)->name, "SHub"))
+#define SN_HWPERF_IS_IONODE(x)		((x) && strstr((x)->name, "TIO"))
+#define SN_HWPERF_IS_ROUTER(x)		((x) && strstr((x)->name, "Router"))
+#define SN_HWPERF_IS_NL3ROUTER(x)	((x) && strstr((x)->name, "NL3Router"))
+#define SN_HWPERF_FOREIGN(x)		((x) && !(x)->sn_hwp_this_part && !(x)->sn_hwp_is_shared)
+#define SN_HWPERF_SAME_OBJTYPE(x,y)	((SN_HWPERF_IS_NODE(x) && SN_HWPERF_IS_NODE(y)) ||\
+					(SN_HWPERF_IS_IONODE(x) && SN_HWPERF_IS_IONODE(y)) ||\
+					(SN_HWPERF_IS_ROUTER(x) && SN_HWPERF_IS_ROUTER(y)))
 
 /* numa port structure, SN_HWPERF_ENUM_PORTS returns an array of these */
 struct sn_hwperf_port_info {
diff -Nru a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
--- a/include/asm-ia64/sn/sn_cpuid.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ia64/sn/sn_cpuid.h	2004-10-28 22:25:57 -07:00
@@ -7,6 +7,7 @@
  * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
  */
 
+
 #ifndef _ASM_IA64_SN_SN_CPUID_H
 #define _ASM_IA64_SN_SN_CPUID_H
 
@@ -35,9 +36,6 @@
  *		the boot cpu is 0.
  *			smp_processor_id() returns the cpuid of the current cpu.
  *
- *	   CPUNUM - On IA64, a cpunum and cpuid are the same. This is NOT true
- *		on other architectures like IA32.
- *
  * 	   CPU_PHYSICAL_ID (also known as HARD_PROCESSOR_ID)
  *		This is the same as 31:24 of the processor LID register
  *			hard_smp_processor_id()- cpu_physical_id of current processor
@@ -45,16 +43,16 @@
  *			cpu_logical_id(phy_id) - convert a <physical_cpuid> to a <cpuid> 
  *				* not real efficient - don't use in perf critical code
  *
- *         LID - processor defined register (see PRM V2).
+ *         SLICE - a number in the range of 0 - 3 (typically) that represents the
+ *		cpu number on a brick.
  *
- *           On SN2
- *		31:28 - id   Contains 0-3 to identify the cpu on the node
- *		27:16 - eid  Contains the NASID
+ *	   SUBNODE - (almost obsolete) the number of the FSB that a cpu is
+ *		connected to. This is also the same as the PI number. Usually 0 or 1.
  *
+ *	NOTE!!!: the value of the bits in the cpu physical id (SAPICid or LID) of a cpu has no 
+ *	significance. The SAPIC id (LID) is a 16-bit cookie that has meaning only to the PROM.
  *
  *
- * The following assumes the following mappings for LID register values:
- *
  * The macros convert between cpu physical ids & slice/nasid/cnodeid.
  * These terms are described below:
  *
@@ -83,19 +81,11 @@
  */
 
 #ifndef CONFIG_SMP
-#define cpu_logical_id(cpu)				0
+#define cpu_logical_id(cpu)			0
 #define cpu_physical_id(cpuid)			((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
 #endif
 
-/*
- * macros for some of these exist in sn/addrs.h & sn/arch.h, etc. However, 
- * trying #include these files here causes circular dependencies.
- */
-#define cpu_physical_id_to_nasid(cpi)		((cpi) &0xfff)
-#define cpu_physical_id_to_slice(cpi)		((cpi>>12) & 3)
-#define cpu_physical_id_to_coherence_id(cpi)	(((cpi) & 0x600) >> 9)
-#define get_nasid()				((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xfff)
-#define get_slice()				((ia64_getreg(_IA64_REG_CR_LID) >> 28) & 0xf)
+
 #define get_node_number(addr)			(((unsigned long)(addr)>>38) & 0x7ff)
 
 /*
@@ -103,43 +93,35 @@
  * 
  * NOTE: on non-MP systems, only cpuid 0 exists
  */
-#define id_eid_to_cpu_physical_id(id,eid)	 	(((id)<<8) | (eid))
-
-#define nasid_slice_to_cpuid(nasid,slice)		(cpu_logical_id(nasid_slice_to_cpu_physical_id((nasid),(slice))))
-
-#define nasid_slice_to_cpu_physical_id(nasid, slice)	(((slice)<<12) | (nasid))
 
-/*
- * The following table/struct  is used for managing PTC coherency domains.
- */
-typedef struct {
-	u8	domain;
-	u8	reserved;
-	u16	sapicid;
-} sn_sapicid_info_t;
-
-extern sn_sapicid_info_t	sn_sapicid_info[];	/* indexed by cpuid */
 extern short physical_node_map[];			/* indexed by nasid to get cnode */
 
-
 /*
- * cpuid_to_slice  - convert a cpuid to the slice that it resides on
- *  There are 4 cpus per node. This function returns 0 .. 3)
+ * Macros for retrieving info about current cpu
  */
-#define cpuid_to_slice(cpuid)		(cpu_physical_id_to_slice(cpu_physical_id(cpuid)))
-
+#define get_nasid()			(nodepda->phys_cpuid[smp_processor_id()].nasid)
+#define get_subnode()			(nodepda->phys_cpuid[smp_processor_id()].subnode)
+#define get_slice()			(nodepda->phys_cpuid[smp_processor_id()].slice)
+#define get_cnode()			(nodepda->phys_cpuid[smp_processor_id()].cnode)
+#define get_sapicid()			((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xffff)
 
 /*
- * cpuid_to_nasid  - convert a cpuid to the NASID that it resides on
+ * Macros for retrieving info about an arbitrary cpu
+ *	cpuid - logical cpu id
  */
-#define cpuid_to_nasid(cpuid)		(cpu_physical_id_to_nasid(cpu_physical_id(cpuid)))
+#define cpuid_to_nasid(cpuid)		(nodepda->phys_cpuid[cpuid].nasid)
+#define cpuid_to_subnode(cpuid)		(nodepda->phys_cpuid[cpuid].subnode)
+#define cpuid_to_slice(cpuid)		(nodepda->phys_cpuid[cpuid].slice)
+#define cpuid_to_cnodeid(cpuid)		(physical_node_map[cpuid_to_nasid(cpuid)])
 
 
 /*
- * cpuid_to_cnodeid  - convert a cpuid to the cnode that it resides on
+ * Dont use the following in performance critical code. They require scans
+ * of potentially large tables.
  */
-#define cpuid_to_cnodeid(cpuid)		(physical_node_map[cpuid_to_nasid(cpuid)])
-
+extern int nasid_slice_to_cpuid(int, int);
+#define nasid_slice_to_cpu_physical_id(nasid, slice)			\
+	cpu_physical_id(nasid_slice_to_cpuid(nasid, slice))
 
 /*
  * cnodeid_to_nasid - convert a cnodeid to a NASID
@@ -149,36 +131,15 @@
  */
 #define cnodeid_to_nasid(cnodeid)	pda->cnodeid_to_nasid_table[cnodeid]
  
-
 /*
  * nasid_to_cnodeid - convert a NASID to a cnodeid
  */
 #define nasid_to_cnodeid(nasid)		(physical_node_map[nasid])
 
-
-/*
- * cnode_slice_to_cpuid - convert a codeid & slice to a cpuid
- */
-
-#define cnode_slice_to_cpuid(cnodeid,slice) (nasid_slice_to_cpuid(cnodeid_to_nasid(cnodeid),(slice)))
- 
-
 /*
- * cpuid_to_subnode - convert a cpuid to the subnode it resides on.
- *   slice 0 & 1 are on subnode 0
- *   slice 2 & 3 are on subnode 1.
+ * partition_coherence_id - cget the coherence ID of the current partition
  */
-#define cpuid_to_subnode(cpuid)		((cpuid_to_slice(cpuid)<2) ? 0 : 1)
- 
-
-#define smp_physical_node_id()			(cpuid_to_nasid(smp_processor_id()))
-
-/*
- * cpuid_to_coherence_id - convert a cpuid to the coherence domain id it
- * resides on
- */
-#define cpuid_to_coherence_id(cpuid)    cpu_physical_id_to_coherence_id(cpu_physical_id(cpuid))
-
+#define partition_coherence_id()	(get_nasid() >> 9)
 
 #endif /* _ASM_IA64_SN_SN_CPUID_H */
 
diff -Nru a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
--- a/include/asm-ia64/sn/sn_sal.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ia64/sn/sn_sal.h	2004-10-28 22:25:59 -07:00
@@ -31,6 +31,7 @@
 #define  SN_SAL_NO_FAULT_ZONE_VIRTUAL		   0x02000010
 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL		   0x02000011
 #define  SN_SAL_PRINT_ERROR			   0x02000012
+#define  SN_SAL_GET_SAPIC_INFO                     0x02009999	//ZZZZ fix
 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES	   0x0200001a	// reentrant
 #define  SN_SAL_GET_FIT_COMPT			   0x0200001b	// reentrant
 #define  SN_SAL_CONSOLE_PUTC                       0x02000021
@@ -843,6 +844,37 @@
 	return (int) rv.status;
 }
 
+/*
+ * Returns the nasid, subnode & slice corresponding to a SAPIC ID
+ */
+static inline u64
+ia64_sn_get_sapic_info(int sapicid, int *nasid, int *subnode, int *slice)
+{
+	struct ia64_sal_retval ret_stuff;
+
+	ret_stuff.status = 0;
+	ret_stuff.v0 = 0;
+	ret_stuff.v1 = 0;
+	ret_stuff.v2 = 0;
+	SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SAPIC_INFO, sapicid, 0, 0, 0, 0, 0, 0);
+
+/***** BEGIN HACK - temp til new proms available ********/
+	if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
+		if (nasid) *nasid = sapicid & 0xfff;
+		if (subnode) *subnode = (sapicid >> 13) & 1;
+		if (slice) *slice = (sapicid >> 12) & 3;
+		return 0;
+	}
+/***** END HACK *******/
+
+	if (ret_stuff.status < 0)
+		return ret_stuff.status;
+
+	if (nasid) *nasid = (int) ret_stuff.v0;
+	if (subnode) *subnode = (int) ret_stuff.v1;
+	if (slice) *slice = (int) ret_stuff.v2;
+	return 0;
+}
 /*
  * This is the access point to the Altix PROM hardware performance
  * and status monitoring interface. For info on using this, see
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ia64/unistd.h	2004-10-28 22:25:57 -07:00
@@ -259,7 +259,6 @@
 #define __NR_mq_getsetattr		1267
 #define __NR_kexec_load			1268
 #define __NR_vserver			1269
-#define __NR_setaltroot			1270
 
 #ifdef __KERNEL__
 
diff -Nru a/include/asm-m32r/io.h b/include/asm-m32r/io.h
--- a/include/asm-m32r/io.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-m32r/io.h	2004-10-28 22:25:58 -07:00
@@ -151,6 +151,9 @@
 #define __raw_readb readb
 #define __raw_readw readw
 #define __raw_readl readl
+#define readb_relaxed readb
+#define readw_relaxed readw
+#define readl_relaxed readl
 
 #define writeb(val, addr)  _writeb((val), (unsigned long)(addr))
 #define writew(val, addr)  _writew((val), (unsigned long)(addr))
@@ -158,6 +161,8 @@
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
+
+#define mmiowb()
 
 #define flush_write_buffers() do { } while (0)  /* M32R_FIXME */
 
diff -Nru a/include/asm-m68k/io.h b/include/asm-m68k/io.h
--- a/include/asm-m68k/io.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-m68k/io.h	2004-10-28 22:25:58 -07:00
@@ -306,6 +306,7 @@
 #endif
 #endif /* CONFIG_PCI */
 
+#define mmiowb()
 
 static inline void *ioremap(unsigned long physaddr, unsigned long size)
 {
diff -Nru a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
--- a/include/asm-m68knommu/io.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-m68knommu/io.h	2004-10-28 22:25:57 -07:00
@@ -102,6 +102,8 @@
 		*bp++ = _swapl(*ap);
 }
 
+#define mmiowb()
+
 /*
  *	make the short names macros so specific devices
  *	can override them as required
diff -Nru a/include/asm-m68knommu/page_offset.h b/include/asm-m68knommu/page_offset.h
--- a/include/asm-m68knommu/page_offset.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-m68knommu/page_offset.h	2004-10-28 22:25:56 -07:00
@@ -1,6 +1,5 @@
 
 #include <linux/config.h>
-#include <asm/shglcore.h>
 
 /* This handles the memory map.. */
 
@@ -44,8 +43,5 @@
 #endif
 #ifdef CONFIG_M68EN302
 #define PAGE_OFFSET_RAW		0x00000000
-#endif
-#ifdef CONFIG_SHGLCORE
-#define PAGE_OFFSET_RAW		SHGLCORE_RAM_BANK_0_ADDR 
 #endif
 
diff -Nru a/include/asm-m68knommu/param.h b/include/asm-m68knommu/param.h
--- a/include/asm-m68knommu/param.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-m68knommu/param.h	2004-10-28 22:25:58 -07:00
@@ -3,38 +3,11 @@
 
 #include <linux/config.h>
 
-#ifndef HZ
-#ifdef CONFIG_COLDFIRE
 #if defined(CONFIG_CLEOPATRA)
-#define HZ 1000
-#else
-#define HZ 100
-#endif
-#endif
-#ifdef CONFIG_M68EN302
-#define HZ 100
-#endif
-#ifdef CONFIG_M68328
-#define HZ 100
-#endif
-#ifdef CONFIG_M68EZ328
-#define HZ 100
+#define	HZ 1000
 #endif
-#ifdef CONFIG_UCSIMM
-#define HZ 100
-#endif
-
-#ifdef CONFIG_M68VZ328
-#define HZ 100
-#endif
-
-#ifdef CONFIG_SHGLCORE
-#define HZ 50
-#endif
-#ifdef CONFIG_M68360
-#define HZ 100
-#endif
-
+#ifndef HZ
+#define	HZ 100
 #endif
 
 #ifdef __KERNEL__
diff -Nru a/include/asm-m68knommu/shglcore.h b/include/asm-m68knommu/shglcore.h
--- a/include/asm-m68knommu/shglcore.h	2004-10-28 22:25:59 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,65 +0,0 @@
-
-/* Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
- */
-
-#ifndef _M68K_SHGLCORE_H
-#define _M68K_SHGLCORE_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_SHGLCORE
-
-#include <asm/MC68332.h>
-
-#ifdef CONFIG_SHGLCORE_2MEG
-
-#define SHGLCORE_ROM_BANK_0_ADDR	0x000000
-#define SHGLCORE_ROM_BANK_1_ADDR	0x100000
-#define SHGLCORE_RAM_BANK_0_ADDR	0x200000
-#define SHGLCORE_RAM_BANK_1_ADDR	0x300000
-#define SHGLCORE_FLASH_BANK_0_ADDR	0x400000
-
-#define SHGLCORE_ROM_BANK_0_LENGTH	0x100000
-#define SHGLCORE_ROM_BANK_1_LENGTH	0x100000
-#define SHGLCORE_RAM_BANK_0_LENGTH	0x100000
-#define SHGLCORE_RAM_BANK_1_LENGTH	0x100000
-#define SHGLCORE_FLASH_BANK_0_LENGTH	0x80000
-
-#define SHGLCORE_ACC_ADDR		0x600000
-#define SHGLCORE_LANCE_ADDR		0x700000
-
-#else
-
-#define SHGLCORE_ROM_BANK_0_ADDR	0x000000
-#define SHGLCORE_RAM_BANK_0_ADDR	0x100000
-#define SHGLCORE_FLASH_BANK_0_ADDR	0x300000
-
-#define SHGLCORE_ROM_BANK_0_LENGTH	0x100000
-#define SHGLCORE_RAM_BANK_0_LENGTH	0x100000
-#define SHGLCORE_FLASH_BANK_0_LENGTH	0x80000
-
-#define SHGLCORE_ACC_ADDR		0x400000
-#define SHGLCORE_LANCE_ADDR		0x500000
-
-#endif
-
-#define MAX_DMA_ADDRESS			SHGLCORE_RAM_BANK_0_ADDR + SHGLCORE_RAM_BANK_0_LENGTH
-
-#define SHGLCORE_LATCH_ADDR	(SHGLCORE_ACC_ADDR+0x100)
-#define SHGLCORE_1865_0_ADDR	(SHGLCORE_ACC_ADDR+0x600)
-#define SHGLCORE_1865_1_ADDR	(SHGLCORE_ACC_ADDR+0x700)
-
-#define SHGLCORE_LATCH_BIT(x)	BYTE_REF(SHGLCORE_LATCH_ADDR+x)
-
-#define SHGLCORE_LATCH_STATUS_LED	0
-#define SHGLCORE_LATCH_ERROR_LED	1
-#define SHGLCORE_LATCH_ALARM_LED	2
-
-#define SHGLCORE_LATCH_1865		4
-
-#define SHGLCORE_LATCH_RELAY_1		6
-#define SHGLCORE_LATCH_RELAY_2		7
-
-#endif /* SHGLCORE */
-
-#endif /* _M68K_SHGLCORE_H */
diff -Nru a/include/asm-m68knommu/shglports.h b/include/asm-m68knommu/shglports.h
--- a/include/asm-m68knommu/shglports.h	2004-10-28 22:25:58 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,76 +0,0 @@
-
-/* Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>,
- *         1997, 1998  D. Jeff Dionne <jeff@lineo.ca>,
- */
-
-#ifndef _M68K_SHGLPORTS_H
-#define _M68K_SHGLPORTS_H
-
-#include <linux/config.h>
-#include <linux/sched.h>
-
-#ifdef CONFIG_SHGLCORE
-
-extern struct semaphore porte_interlock;
-
-struct SHGLCORE_PORT_QS { 
-  unsigned char
-  nullqs:1, /* COM1TX */ 
-  sbin:1,   /* PQS6 (PCS3) */
-  sbclk:1,  /* PQS5 (PCS2) */
-  sbout:1,  /* PQS4 (PCS1) */
-  null4:4;  /* MISO, MOSI, SCLK, /SS=PCS0 */
-};
-
-#define PORT_QS ((volatile struct SHGLCORE_PORT_QS*)PORTQS_ADDR)
-
-struct SHGLCORE_PORT_E {
-  unsigned char
-  dead:1,       /* LED */
-  sbirigb:1,    /* PE6 */
-  ds:1,         /* /DS */
-  nulle1:1,     /* na */ 
-  sbpll:1,      /* PE3 */
-  avec:1,       /* /AVEC */
-  sbsrom:1,     /* PE1 */
-  sbpanel:1;    /* PE0 */
-};
-
-#define PORT_E ((volatile struct SHGLCORE_PORT_E*)PORTE_ADDR)
-
-struct SHGLCORE_PORT_F {
-  unsigned char
-  nullf1:4,
-  nullf2:4;
-};
-
-#define PORT_F ((volatile struct SHGLCORE_PORT_F*)PORTF_ADDR)
-
-extern int comm_status_led, comm_error_led, alarm_led;
-
-static inline void SET_COMM_STATUS_LED(int value) {
-	BYTE_REF(SHGLCORE_ACC_ADDR+0x100+0) = comm_status_led = value;
-}
-static inline int GET_COMM_STATUS_LED(void) {
-	return comm_status_led;
-}
-
-
-static inline void SET_COMM_ERROR_LED(int value) {
-	BYTE_REF(SHGLCORE_ACC_ADDR+0x100+1) = comm_error_led = value;
-}
-static inline int GET_COMM_ERROR_LED(void) {
-	return comm_error_led;
-}
-
-
-static inline void SET_ALARM_LED(int value) {
-	BYTE_REF(SHGLCORE_ACC_ADDR+0x100+2) = alarm_led = value;
-}
-static inline int GET_ALARM_LED(void) {
-	return alarm_led;
-}
-
-#endif
-
-#endif /* _M68K_SHGLPORTS_H */
diff -Nru a/include/asm-mips/io.h b/include/asm-mips/io.h
--- a/include/asm-mips/io.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-mips/io.h	2004-10-28 22:25:57 -07:00
@@ -290,6 +290,10 @@
 #define __raw_writeb(b,addr)	((*(volatile unsigned char *)(addr)) = (b))
 #define __raw_writew(w,addr)	((*(volatile unsigned short *)(addr)) = (w))
 #define __raw_writel(l,addr)	((*(volatile unsigned int *)(addr)) = (l))
+
+/* Depends on MIPS III instruction set */
+#define mmiowb() asm volatile ("sync" ::: "memory")
+
 #ifdef CONFIG_MIPS32
 #define ____raw_writeq(val,addr)						\
 ({									\
diff -Nru a/include/asm-parisc/io.h b/include/asm-parisc/io.h
--- a/include/asm-parisc/io.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-parisc/io.h	2004-10-28 22:25:57 -07:00
@@ -177,6 +177,8 @@
 #define readl_relaxed(addr) readl(addr)
 #define readq_relaxed(addr) readq(addr)
 
+#define mmiowb()
+
 extern void __memcpy_fromio(unsigned long dest, unsigned long src, int count);
 extern void __memcpy_toio(unsigned long dest, unsigned long src, int count);
 extern void __memset_io(unsigned long dest, char fill, int count);
diff -Nru a/include/asm-ppc/io.h b/include/asm-ppc/io.h
--- a/include/asm-ppc/io.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ppc/io.h	2004-10-28 22:25:59 -07:00
@@ -207,6 +207,8 @@
 	*(__force volatile __u32 *)(addr) = b;
 }
 
+#define mmiowb()
+
 /*
  * The insw/outsw/insl/outsl macros don't do byte-swapping.
  * They are only used in practice for transferring buffers which
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ppc/unistd.h	2004-10-28 22:25:57 -07:00
@@ -273,8 +273,11 @@
 #define __NR_mq_notify		266
 #define __NR_mq_getsetattr	267
 #define __NR_kexec_load		268
+#define __NR_add_key		269
+#define __NR_request_key	270
+#define __NR_keyctl		271
 
-#define __NR_syscalls		269
+#define __NR_syscalls		272
 
 #define __NR(n)	#n
 
diff -Nru a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
--- a/include/asm-ppc64/eeh.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ppc64/eeh.h	2004-10-28 22:25:59 -07:00
@@ -20,8 +20,10 @@
 #ifndef _PPC64_EEH_H
 #define _PPC64_EEH_H
 
-#include <linux/string.h>
 #include <linux/init.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
 
 struct pci_dev;
 struct device_node;
@@ -29,6 +31,7 @@
 /* Values for eeh_mode bits in device_node */
 #define EEH_MODE_SUPPORTED	(1<<0)
 #define EEH_MODE_NOCHECK	(1<<1)
+#define EEH_MODE_ISOLATED	(1<<2)
 
 #ifdef CONFIG_PPC_PSERIES
 extern void __init eeh_init(void);
@@ -68,7 +71,28 @@
 #define EEH_RELEASE_DMA		3
 int eeh_set_option(struct pci_dev *dev, int options);
 
-/*
+
+/**
+ * Notifier event flags.
+ */
+#define EEH_NOTIFY_FREEZE  1
+
+/** EEH event -- structure holding pci slot data that describes
+ *  a change in the isolation status of a PCI slot.  A pointer
+ *  to this struct is passed as the data pointer in a notify callback.
+ */
+struct eeh_event {
+	struct list_head     list;
+	struct pci_dev       *dev;
+	struct device_node   *dn;
+	int                  reset_state;
+};
+
+/** Register to find out about EEH events. */
+int eeh_register_notifier(struct notifier_block *nb);
+int eeh_unregister_notifier(struct notifier_block *nb);
+
+/**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
  *
  * If this macro yields TRUE, the caller relays to eeh_check_failure()
@@ -86,114 +110,116 @@
 /* 
  * MMIO read/write operations with EEH support.
  */
-static inline u8 eeh_readb(const volatile void __iomem *addr) {
-	volatile u8 *vaddr = (volatile u8 __force *) addr;
-	u8 val = in_8(vaddr);
+static inline u8 eeh_readb(const volatile void __iomem *addr)
+{
+	u8 val = in_8(addr);
 	if (EEH_POSSIBLE_ERROR(val, u8))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writeb(u8 val, volatile void __iomem *addr) {
-	volatile u8 *vaddr = (volatile u8 __force *) addr;
-	out_8(vaddr, val);
+static inline void eeh_writeb(u8 val, volatile void __iomem *addr)
+{
+	out_8(addr, val);
 }
 
-static inline u16 eeh_readw(const volatile void __iomem *addr) {
-	volatile u16 *vaddr = (volatile u16 __force *) addr;
-	u16 val = in_le16(vaddr);
+static inline u16 eeh_readw(const volatile void __iomem *addr)
+{
+	u16 val = in_le16(addr);
 	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writew(u16 val, volatile void __iomem *addr) {
-	volatile u16 *vaddr = (volatile u16 __force *) addr;
-	out_le16(vaddr, val);
-}
-static inline u16 eeh_raw_readw(const volatile void __iomem *addr) {
-	volatile u16 *vaddr = (volatile u16 __force *) addr;
-	u16 val = in_be16(vaddr);
+static inline void eeh_writew(u16 val, volatile void __iomem *addr)
+{
+	out_le16(addr, val);
+}
+static inline u16 eeh_raw_readw(const volatile void __iomem *addr)
+{
+	u16 val = in_be16(addr);
 	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure(addr, val);
 	return val;
 }
 static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) {
-	volatile u16 *vaddr = (volatile u16 __force *) addr;
+	volatile u16 __iomem *vaddr = (volatile u16 __iomem *) addr;
 	out_be16(vaddr, val);
 }
 
-static inline u32 eeh_readl(const volatile void __iomem *addr) {
-	volatile u32 *vaddr = (volatile u32 __force *) addr;
-	u32 val = in_le32(vaddr);
+static inline u32 eeh_readl(const volatile void __iomem *addr)
+{
+	u32 val = in_le32(addr);
 	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writel(u32 val, volatile void __iomem *addr) {
-	volatile u32 *vaddr = (volatile u32 __force *) addr;
-	out_le32(vaddr, val);
-}
-static inline u32 eeh_raw_readl(const volatile void __iomem *addr) {
-	volatile u32 *vaddr = (volatile u32 __force *) addr;
-	u32 val = in_be32(vaddr);
+static inline void eeh_writel(u32 val, volatile void __iomem *addr)
+{
+	out_le32(addr, val);
+}
+static inline u32 eeh_raw_readl(const volatile void __iomem *addr)
+{
+	u32 val = in_be32(addr);
 	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr) {
-	volatile u32 *vaddr = (volatile u32 __force *) addr;
-	out_be32(vaddr, val);
+static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr)
+{
+	out_be32(addr, val);
 }
 
-static inline u64 eeh_readq(const volatile void __iomem *addr) {
-	volatile u64 *vaddr = (volatile u64 __force *) addr;
-	u64 val = in_le64(vaddr);
+static inline u64 eeh_readq(const volatile void __iomem *addr)
+{
+	u64 val = in_le64(addr);
 	if (EEH_POSSIBLE_ERROR(val, u64))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writeq(u64 val, volatile void __iomem *addr) {
-	volatile u64 *vaddr = (volatile u64 __force *) addr;
-	out_le64(vaddr, val);
-}
-static inline u64 eeh_raw_readq(const volatile void __iomem *addr) {
-	volatile u64 *vaddr = (volatile u64 __force *) addr;
-	u64 val = in_be64(vaddr);
+static inline void eeh_writeq(u64 val, volatile void __iomem *addr)
+{
+	out_le64(addr, val);
+}
+static inline u64 eeh_raw_readq(const volatile void __iomem *addr)
+{
+	u64 val = in_be64(addr);
 	if (EEH_POSSIBLE_ERROR(val, u64))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr) {
-	volatile u64 *vaddr = (volatile u64 __force *) addr;
-	out_be64(vaddr, val);
+static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr)
+{
+	out_be64(addr, val);
 }
 
 #define EEH_CHECK_ALIGN(v,a) \
 	((((unsigned long)(v)) & ((a) - 1)) == 0)
 
-static inline void eeh_memset_io(volatile void __iomem *addr, int c, unsigned long n) {
-	void *vaddr = (void __force *) addr;
+static inline void eeh_memset_io(volatile void __iomem *addr, int c, unsigned long n)
+{
 	u32 lc = c;
 	lc |= lc << 8;
 	lc |= lc << 16;
 
-	while(n && !EEH_CHECK_ALIGN(vaddr, 4)) {
-		*((volatile u8 *)vaddr) = c;
-		vaddr = (void *)((unsigned long)vaddr + 1);
+	while(n && !EEH_CHECK_ALIGN(addr, 4)) {
+		*((volatile u8 *)addr) = c;
+		addr = (void *)((unsigned long)addr + 1);
 		n--;
 	}
 	while(n >= 4) {
-		*((volatile u32 *)vaddr) = lc;
-		vaddr = (void *)((unsigned long)vaddr + 4);
+		*((volatile u32 *)addr) = lc;
+		addr = (void *)((unsigned long)addr + 4);
 		n -= 4;
 	}
 	while(n) {
-		*((volatile u8 *)vaddr) = c;
-		vaddr = (void *)((unsigned long)vaddr + 1);
+		*((volatile u8 *)addr) = c;
+		addr = (void *)((unsigned long)addr + 1);
 		n--;
 	}
 	__asm__ __volatile__ ("sync" : : : "memory");
 }
-static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src, unsigned long n) {
+static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src,
+				     unsigned long n)
+{
 	void *vsrc = (void __force *) src;
 	void *destsave = dest;
 	unsigned long nsave = n;
@@ -230,7 +256,9 @@
 	}
 }
 
-static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) {
+static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src,
+				   unsigned long n)
+{
 	void *vdest = (void __force *) dest;
 
 	while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) {
@@ -256,66 +284,75 @@
 
 #undef EEH_CHECK_ALIGN
 
-static inline u8 eeh_inb(unsigned long port) {
+static inline u8 eeh_inb(unsigned long port)
+{
 	u8 val;
 	if (!_IO_IS_VALID(port))
 		return ~0;
-	val = in_8((u8 *)(port+pci_io_base));
+	val = in_8((u8 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u8))
 		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
-static inline void eeh_outb(u8 val, unsigned long port) {
+static inline void eeh_outb(u8 val, unsigned long port)
+{
 	if (_IO_IS_VALID(port))
-		out_8((u8 *)(port+pci_io_base), val);
+		out_8((u8 __iomem *)(port+pci_io_base), val);
 }
 
-static inline u16 eeh_inw(unsigned long port) {
+static inline u16 eeh_inw(unsigned long port)
+{
 	u16 val;
 	if (!_IO_IS_VALID(port))
 		return ~0;
-	val = in_le16((u16 *)(port+pci_io_base));
+	val = in_le16((u16 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
-static inline void eeh_outw(u16 val, unsigned long port) {
+static inline void eeh_outw(u16 val, unsigned long port)
+{
 	if (_IO_IS_VALID(port))
-		out_le16((u16 *)(port+pci_io_base), val);
+		out_le16((u16 __iomem *)(port+pci_io_base), val);
 }
 
-static inline u32 eeh_inl(unsigned long port) {
+static inline u32 eeh_inl(unsigned long port)
+{
 	u32 val;
 	if (!_IO_IS_VALID(port))
 		return ~0;
-	val = in_le32((u32 *)(port+pci_io_base));
+	val = in_le32((u32 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
-static inline void eeh_outl(u32 val, unsigned long port) {
+static inline void eeh_outl(u32 val, unsigned long port)
+{
 	if (_IO_IS_VALID(port))
-		out_le32((u32 *)(port+pci_io_base), val);
+		out_le32((u32 __iomem *)(port+pci_io_base), val);
 }
 
 /* in-string eeh macros */
-static inline void eeh_insb(unsigned long port, void * buf, int ns) {
-	_insb((u8 *)(port+pci_io_base), buf, ns);
+static inline void eeh_insb(unsigned long port, void * buf, int ns)
+{
+	_insb((u8 __iomem *)(port+pci_io_base), buf, ns);
 	if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
 		eeh_check_failure((void __iomem *)(port), *(u8*)buf);
 }
 
-static inline void eeh_insw_ns(unsigned long port, void * buf, int ns) {
-	_insw_ns((u16 *)(port+pci_io_base), buf, ns);
+static inline void eeh_insw_ns(unsigned long port, void * buf, int ns)
+{
+	_insw_ns((u16 __iomem *)(port+pci_io_base), buf, ns);
 	if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
 		eeh_check_failure((void __iomem *)(port), *(u16*)buf);
 }
 
-static inline void eeh_insl_ns(unsigned long port, void * buf, int nl) {
-	_insl_ns((u32 *)(port+pci_io_base), buf, nl);
+static inline void eeh_insl_ns(unsigned long port, void * buf, int nl)
+{
+	_insl_ns((u32 __iomem *)(port+pci_io_base), buf, nl);
 	if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
 		eeh_check_failure((void __iomem *)(port), *(u32*)buf);
 }
diff -Nru a/include/asm-ppc64/floppy.h b/include/asm-ppc64/floppy.h
--- a/include/asm-ppc64/floppy.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-ppc64/floppy.h	2004-10-28 22:25:58 -07:00
@@ -11,6 +11,7 @@
 #define __ASM_PPC64_FLOPPY_H
 
 #include <linux/config.h>
+#include <asm/machdep.h>
 
 #define fd_inb(port)			inb_p(port)
 #define fd_outb(value,port)		outb_p(value,port)
diff -Nru a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
--- a/include/asm-ppc64/io.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ppc64/io.h	2004-10-28 22:25:59 -07:00
@@ -1,4 +1,4 @@
-#ifndef _PPC64_IO_H
+ #ifndef _PPC64_IO_H
 #define _PPC64_IO_H
 
 /* 
@@ -158,6 +158,8 @@
 extern void _insl_ns(volatile u32 *port, void *buf, int nl);
 extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
 
+#define mmiowb()
+
 /*
  * output pause versions need a delay at least for the
  * w83c105 ide controller in a p610.
@@ -203,7 +205,7 @@
 #define ioremap_nocache(addr, size)	ioremap((addr), (size))
 extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size);
 extern void iounmap(volatile void __iomem *addr);
-extern void * reserve_phb_iospace(unsigned long size);
+extern void __iomem * reserve_phb_iospace(unsigned long size);
 
 /**
  *	virt_to_phys	-	map virtual addresses to physical
@@ -271,7 +273,7 @@
  * and should not be used directly by device drivers.  Use inb/readb
  * instead.
  */
-static inline int in_8(volatile unsigned char *addr)
+static inline int in_8(const volatile unsigned char __iomem *addr)
 {
 	int ret;
 
@@ -280,13 +282,13 @@
 	return ret;
 }
 
-static inline void out_8(volatile unsigned char *addr, int val)
+static inline void out_8(volatile unsigned char __iomem *addr, int val)
 {
 	__asm__ __volatile__("stb%U0%X0 %1,%0; sync"
 			     : "=m" (*addr) : "r" (val));
 }
 
-static inline int in_le16(volatile unsigned short *addr)
+static inline int in_le16(const volatile unsigned short __iomem *addr)
 {
 	int ret;
 
@@ -295,7 +297,7 @@
 	return ret;
 }
 
-static inline int in_be16(volatile unsigned short *addr)
+static inline int in_be16(const volatile unsigned short __iomem *addr)
 {
 	int ret;
 
@@ -304,19 +306,19 @@
 	return ret;
 }
 
-static inline void out_le16(volatile unsigned short *addr, int val)
+static inline void out_le16(volatile unsigned short __iomem *addr, int val)
 {
 	__asm__ __volatile__("sthbrx %1,0,%2; sync"
 			     : "=m" (*addr) : "r" (val), "r" (addr));
 }
 
-static inline void out_be16(volatile unsigned short *addr, int val)
+static inline void out_be16(volatile unsigned short __iomem *addr, int val)
 {
 	__asm__ __volatile__("sth%U0%X0 %1,%0; sync"
 			     : "=m" (*addr) : "r" (val));
 }
 
-static inline unsigned in_le32(volatile unsigned *addr)
+static inline unsigned in_le32(const volatile unsigned __iomem *addr)
 {
 	unsigned ret;
 
@@ -325,7 +327,7 @@
 	return ret;
 }
 
-static inline unsigned in_be32(volatile unsigned *addr)
+static inline unsigned in_be32(const volatile unsigned __iomem *addr)
 {
 	unsigned ret;
 
@@ -334,19 +336,19 @@
 	return ret;
 }
 
-static inline void out_le32(volatile unsigned *addr, int val)
+static inline void out_le32(volatile unsigned __iomem *addr, int val)
 {
 	__asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
 			     : "r" (val), "r" (addr));
 }
 
-static inline void out_be32(volatile unsigned *addr, int val)
+static inline void out_be32(volatile unsigned __iomem *addr, int val)
 {
 	__asm__ __volatile__("stw%U0%X0 %1,%0; sync"
 			     : "=m" (*addr) : "r" (val));
 }
 
-static inline unsigned long in_le64(volatile unsigned long *addr)
+static inline unsigned long in_le64(const volatile unsigned long __iomem *addr)
 {
 	unsigned long tmp, ret;
 
@@ -365,7 +367,7 @@
 	return ret;
 }
 
-static inline unsigned long in_be64(volatile unsigned long *addr)
+static inline unsigned long in_be64(const volatile unsigned long __iomem *addr)
 {
 	unsigned long ret;
 
@@ -374,7 +376,7 @@
 	return ret;
 }
 
-static inline void out_le64(volatile unsigned long *addr, unsigned long val)
+static inline void out_le64(volatile unsigned long __iomem *addr, unsigned long val)
 {
 	unsigned long tmp;
 
@@ -391,7 +393,7 @@
 			     : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr));
 }
 
-static inline void out_be64(volatile unsigned long *addr, unsigned long val)
+static inline void out_be64(volatile unsigned long __iomem *addr, unsigned long val)
 {
 	__asm__ __volatile__("std%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val));
 }
@@ -435,6 +437,10 @@
 #define dma_cache_inv(_start,_size)		do { } while (0)
 #define dma_cache_wback(_start,_size)		do { } while (0)
 #define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
+/* Check of existence of legacy devices */
+extern int check_legacy_ioport(unsigned long base_port);
+
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
--- a/include/asm-ppc64/iommu.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-ppc64/iommu.h	2004-10-28 22:25:58 -07:00
@@ -111,7 +111,18 @@
 extern void iommu_setup_u3(void);
 
 /* Creates table for an individual device node */
+/* XXX: This isn't generic, please name it accordingly or add
+ * some ppc_md. hooks for iommu implementations to do what they
+ * need to do. --BenH.
+ */
 extern void iommu_devnode_init(struct device_node *dn);
+
+/* Frees table for an individual device node */
+/* XXX: This isn't generic, please name it accordingly or add
+ * some ppc_md. hooks for iommu implementations to do what they
+ * need to do. --BenH.
+ */
+extern void iommu_free_table(struct device_node *dn);
 
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 
diff -Nru a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h
--- a/include/asm-ppc64/irq.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ppc64/irq.h	2004-10-28 22:25:59 -07:00
@@ -20,6 +20,19 @@
 /* this number is used when no interrupt has been assigned */
 #define NO_IRQ			(-1)
 
+/*
+ * These constants are used for passing information about interrupt
+ * signal polarity and level/edge sensing to the low-level PIC chip
+ * drivers.
+ */
+#define IRQ_SENSE_MASK		0x1
+#define IRQ_SENSE_LEVEL		0x1	/* interrupt on active level */
+#define IRQ_SENSE_EDGE		0x0	/* interrupt triggered by edge */
+
+#define IRQ_POLARITY_MASK	0x2
+#define IRQ_POLARITY_POSITIVE	0x2	/* high level or low->high edge */
+#define IRQ_POLARITY_NEGATIVE	0x0	/* low level or high->low edge */
+
 #define get_irq_desc(irq) (&irq_desc[(irq)])
 
 /* Define a way to iterate across irqs. */
diff -Nru a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
--- a/include/asm-ppc64/machdep.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ppc64/machdep.h	2004-10-28 22:25:57 -07:00
@@ -28,6 +28,7 @@
 	int   (*probe)(void);
 	void  (*kick_cpu)(int nr);
 	void  (*setup_cpu)(int nr);
+	void  (*late_setup_cpu)(int nr);
 	void  (*take_timebase)(void);
 	void  (*give_timebase)(void);
 };
@@ -86,6 +87,7 @@
 	void		(*power_off)(void);
 	void		(*halt)(void);
 	void		(*panic)(char *str);
+	void		(*cpu_die)(void);
 
 	int		(*set_rtc_time)(struct rtc_time *);
 	void		(*get_rtc_time)(struct rtc_time *);
@@ -114,6 +116,12 @@
 	 */
 	long	 	(*feature_call)(unsigned int feature, ...);
 
+	/* Check availability of legacy devices like i8042 */
+	int 		(*check_legacy_ioport)(unsigned int baseport);
+
+	/* Get legacy PCI/IDE interrupt mapping */ 
+	int		(*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel);
+	
 };
 
 extern struct machdep_calls ppc_md;
diff -Nru a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
--- a/include/asm-ppc64/mmu.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-ppc64/mmu.h	2004-10-28 22:25:58 -07:00
@@ -24,6 +24,7 @@
 typedef struct {
 	mm_context_id_t id;
 #ifdef CONFIG_HUGETLB_PAGE
+	pgd_t *huge_pgdir;
 	u16 htlb_segs; /* bitmask */
 #endif
 } mm_context_t;
diff -Nru a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
--- a/include/asm-ppc64/page.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-ppc64/page.h	2004-10-28 22:25:56 -07:00
@@ -64,7 +64,6 @@
 #define is_hugepage_only_range(addr, len) \
 	(touches_hugepage_high_range((addr), (len)) || \
 	  touches_hugepage_low_range((addr), (len)))
-#define hugetlb_free_pgtables free_pgtables
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #define in_hugepage_area(context, addr) \
diff -Nru a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
--- a/include/asm-ppc64/pci-bridge.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-ppc64/pci-bridge.h	2004-10-28 22:25:56 -07:00
@@ -41,7 +41,7 @@
 	int first_busno;
 	int last_busno;
 
-	void *io_base_virt;
+	void __iomem *io_base_virt;
 	unsigned long io_base_phys;
 
 	/* Some machines have a non 1:1 mapping of
@@ -51,8 +51,8 @@
 	unsigned long pci_io_size;
 
 	struct pci_ops *ops;
-	volatile unsigned int *cfg_addr;
-	volatile unsigned char *cfg_data;
+	volatile unsigned int __iomem *cfg_addr;
+	volatile unsigned char __iomem *cfg_data;
 
 	/* Currently, we limit ourselves to 1 IO range and 3 mem
 	 * ranges since the common pci_bus structure can't handle more
@@ -98,6 +98,25 @@
  * is known that sysdata is correct.
  */
 #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
+
+extern void phbs_remap_io(void);
+
+static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
+{
+	struct device_node *busdn;
+
+	busdn = bus->sysdata;
+	if (busdn == 0) {
+		struct pci_bus *b;
+		for (b = bus->parent; b && bus->sysdata == 0; b = b->parent)
+			;
+		busdn = b->sysdata;
+	}
+	if (busdn == NULL)
+		return NULL;
+	return busdn->phb;
+}
+
 
 #endif
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h
--- a/include/asm-ppc64/pci.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ppc64/pci.h	2004-10-28 22:25:57 -07:00
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/dma-mapping.h>
+#include <asm/machdep.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -20,6 +21,8 @@
 #define PCIBIOS_MIN_IO		0x1000
 #define PCIBIOS_MIN_MEM		0x10000000
 
+struct pci_dev;
+
 #ifdef CONFIG_PPC_ISERIES
 #define pcibios_scan_all_fns(a, b)	0
 #else
@@ -36,7 +39,13 @@
 	/* We don't do dynamic PCI IRQ allocation */
 }
 
-struct pci_dev;
+#define HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+	if (ppc_md.pci_get_legacy_ide_irq)
+		return ppc_md.pci_get_legacy_ide_irq(dev, channel);
+	return channel ? 15 : 14;
+}
 
 #define HAVE_ARCH_PCI_MWI 1
 static inline int pcibios_prep_mwi(struct pci_dev *dev)
diff -Nru a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
--- a/include/asm-ppc64/pgtable.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ppc64/pgtable.h	2004-10-28 22:25:59 -07:00
@@ -98,6 +98,7 @@
 #define _PAGE_BUSY	0x0800 /* software: PTE & hash are busy */ 
 #define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */
 #define _PAGE_GROUP_IX  0x7000 /* software: HPTE index within group */
+#define _PAGE_HUGE	0x10000 /* 16MB page */
 /* Bits 0x7000 identify the index within an HPT Group */
 #define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_SECONDARY | _PAGE_GROUP_IX)
 /* PAGE_MASK gives the right answer below, but only by accident */
@@ -157,19 +158,19 @@
 #endif /* __ASSEMBLY__ */
 
 /* shift to put page number into pte */
-#define PTE_SHIFT (16)
+#define PTE_SHIFT (17)
 
 /* We allow 2^41 bytes of real memory, so we need 29 bits in the PMD
  * to give the PTE page number.  The bottom two bits are for flags. */
 #define PMD_TO_PTEPAGE_SHIFT (2)
 
 #ifdef CONFIG_HUGETLB_PAGE
-#define _PMD_HUGEPAGE	0x00000001U
-#define HUGEPTE_BATCH_SIZE (1<<(HPAGE_SHIFT-PMD_SHIFT))
 
 #ifndef __ASSEMBLY__
 int hash_huge_page(struct mm_struct *mm, unsigned long access,
 		   unsigned long ea, unsigned long vsid, int local);
+
+void hugetlb_mm_free_pgd(struct mm_struct *mm);
 #endif /* __ASSEMBLY__ */
 
 #define HAVE_ARCH_UNMAPPED_AREA
@@ -177,7 +178,7 @@
 #else
 
 #define hash_huge_page(mm,a,ea,vsid,local)	-1
-#define _PMD_HUGEPAGE	0
+#define hugetlb_mm_free_pgd(mm)			do {} while (0)
 
 #endif
 
@@ -213,10 +214,8 @@
 #define pmd_set(pmdp, ptep) 	\
 	(pmd_val(*(pmdp)) = (__ba_to_bpn(ptep) << PMD_TO_PTEPAGE_SHIFT))
 #define pmd_none(pmd)		(!pmd_val(pmd))
-#define	pmd_hugepage(pmd)	(!!(pmd_val(pmd) & _PMD_HUGEPAGE))
-#define	pmd_bad(pmd)		(((pmd_val(pmd)) == 0) || pmd_hugepage(pmd))
-#define	pmd_present(pmd)	((!pmd_hugepage(pmd)) \
-				 && (pmd_val(pmd) & ~_PMD_HUGEPAGE) != 0)
+#define	pmd_bad(pmd)		(pmd_val(pmd) == 0)
+#define	pmd_present(pmd)	(pmd_val(pmd) != 0)
 #define	pmd_clear(pmdp)		(pmd_val(*(pmdp)) = 0)
 #define pmd_page_kernel(pmd)	\
 	(__bpn_to_ba(pmd_val(pmd) >> PMD_TO_PTEPAGE_SHIFT))
@@ -269,6 +268,7 @@
 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;}
 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;}
 static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;}
+static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE;}
 
 static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -294,6 +294,8 @@
 	pte_val(pte) |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte) {
 	pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) {
+	pte_val(pte) |= _PAGE_HUGE; return pte; }
 
 /* Atomic PTE updates */
 static inline unsigned long pte_update(pte_t *p, unsigned long clr)
@@ -463,6 +465,10 @@
 extern pgd_t ioremap_dir[1024];
 
 extern void paging_init(void);
+
+struct mmu_gather;
+void hugetlb_free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *prev,
+			   unsigned long start, unsigned long end);
 
 /*
  * This gets called at the end of handling a page fault, when
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-ppc64/processor.h	2004-10-28 22:25:56 -07:00
@@ -389,6 +389,7 @@
 #define PLATFORM_ISERIES_LPAR 0x0201
 #define PLATFORM_LPAR         0x0001
 #define PLATFORM_POWERMAC     0x0400
+#define PLATFORM_MAPLE        0x0500
 
 /* Compatibility with drivers coming from PPC32 world */
 #define _machine	(systemcfg->platform)
diff -Nru a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
--- a/include/asm-ppc64/prom.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ppc64/prom.h	2004-10-28 22:25:59 -07:00
@@ -93,33 +93,6 @@
 	unsigned int size;
 };
 
-struct pci_range32 {
-	struct pci_address child_addr;
-	unsigned int  parent_addr;
-  	unsigned long size; 
-};
-
-struct pci_range64 {
-	struct pci_address child_addr;
-  	unsigned long parent_addr;
-        unsigned long size; 
-};
-
-union pci_range {
-	struct {
-		struct pci_address addr;
-		u32 phys;
-		u32 size_hi;
-	} pci32;
-	struct {
-		struct pci_address addr;
-		u32 phys_hi;
-		u32 phys_lo;
-		u32 size_hi;
-		u32 size_lo;
-	} pci64;
-};
-
 struct of_tce_table {
 	phandle node;
 	unsigned long base;
diff -Nru a/include/asm-ppc64/serial.h b/include/asm-ppc64/serial.h
--- a/include/asm-ppc64/serial.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-ppc64/serial.h	2004-10-28 22:25:59 -07:00
@@ -18,113 +18,13 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#define BASE_BAUD ( 1843200 / 16 )
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE  64
-#else
-#define RS_TABLE_SIZE  4
-#endif
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define FOURPORT_FLAGS ASYNC_FOURPORT
-#define ACCENT_FLAGS 0
-#define BOCA_FLAGS 0
-#define HUB6_FLAGS 0
-#endif
-	
-/*
- * The following define the access methods for the HUB6 card. All
- * access is through two ports for all 24 possible chips. The card is
- * selected through the high 2 bits, the port on that card with the
- * "middle" 3 bits, and the register on that port with the bottom
- * 3 bits.
- *
- * While the access port and interrupt is configurable, the default
- * port locations are 0x302 for the port control register, and 0x303
- * for the data read/write register. Normally, the interrupt is at irq3
- * but can be anything from 3 to 7 inclusive. Note that using 3 will
- * require disabling com2.
- */
-
-#define C_P(card,port) (((card)<<6|(port)<<3) + 1)
 
-#define STD_SERIAL_PORT_DEFNS			\
-	/* UART CLK   PORT IRQ     FLAGS        */			\
-	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
-	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
-	{ 0, BASE_BAUD, 0x890, 0xf, STD_COM_FLAGS },	/* ttyS2 */	\
-	{ 0, BASE_BAUD, 0x898, 0xe, STD_COM_FLAGS },	/* ttyS3 */
-
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define EXTRA_SERIAL_PORT_DEFNS			\
-	{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, 	/* ttyS4 */	\
-	{ 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS },	/* ttyS5 */	\
-	{ 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS },	/* ttyS6 */	\
-	{ 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS },	/* ttyS7 */	\
-	{ 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS },	/* ttyS8 */	\
-	{ 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS },	/* ttyS9 */	\
-	{ 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS },	/* ttyS10 */	\
-	{ 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS },	/* ttyS11 */	\
-	{ 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS },	/* ttyS12 */	\
-	{ 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS },	/* ttyS13 */	\
-	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS14 (spare) */		\
-	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS15 (spare) */		\
-	{ 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS },	/* ttyS16 */	\
-	{ 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS },	/* ttyS17 */	\
-	{ 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS },	/* ttyS18 */	\
-	{ 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS },	/* ttyS19 */	\
-	{ 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS },	/* ttyS20 */	\
-	{ 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS },	/* ttyS21 */	\
-	{ 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS },	/* ttyS22 */	\
-	{ 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS },	/* ttyS23 */	\
-	{ 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS },	/* ttyS24 */	\
-	{ 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS },	/* ttyS25 */	\
-	{ 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS },	/* ttyS26 */	\
-	{ 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS },	/* ttyS27 */	\
-	{ 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS },	/* ttyS28 */	\
-	{ 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS },	/* ttyS29 */	\
-	{ 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS },	/* ttyS30 */	\
-	{ 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS },	/* ttyS31 */
-#else
-#define EXTRA_SERIAL_PORT_DEFNS
-#endif
-
-/* You can have up to four HUB6's in the system, but I've only
- * included two cards here for a total of twelve ports.
- */
-#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS))
-#define HUB6_SERIAL_PORT_DFNS		\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) },  /* ttyS32 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) },  /* ttyS33 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) },  /* ttyS34 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) },  /* ttyS35 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) },  /* ttyS36 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) },  /* ttyS37 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) },  /* ttyS38 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) },  /* ttyS39 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) },  /* ttyS40 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) },  /* ttyS41 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) },  /* ttyS42 */	\
-	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) },  /* ttyS43 */
-#else
-#define HUB6_SERIAL_PORT_DFNS
-#endif
-
-#define MCA_SERIAL_PORT_DFNS
+/* Default baud base if not found in device-tree */
+#define BASE_BAUD ( 1843200 / 16 )
 
-#define SERIAL_PORT_DFNS		\
-	STD_SERIAL_PORT_DEFNS		\
-	EXTRA_SERIAL_PORT_DEFNS		\
-	HUB6_SERIAL_PORT_DFNS		\
-	MCA_SERIAL_PORT_DFNS
+#define ARCH_HAS_GET_LEGACY_SERIAL_PORTS
+struct old_serial_port;
+extern struct old_serial_port *get_legacy_serial_ports(unsigned int *count);
+#define UART_NR	(8 + CONFIG_SERIAL_8250_NR_UARTS)
 
 #endif /* _PPC64_SERIAL_H */
diff -Nru a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
--- a/include/asm-ppc64/smp.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-ppc64/smp.h	2004-10-28 22:25:56 -07:00
@@ -28,6 +28,8 @@
 
 extern int boot_cpuid;
 
+extern void cpu_die(void) __attribute__((noreturn));
+
 #ifdef CONFIG_SMP
 
 extern void smp_send_debugger_break(int cpu);
@@ -57,15 +59,23 @@
 
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
-extern void cpu_die(void) __attribute__((noreturn));
-extern int query_cpu_stopped(unsigned int pcpu);
-#endif /* !(CONFIG_SMP) */
+#endif /* CONFIG_SMP */
 
 #define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id)
 #define set_hard_smp_processor_id(CPU, VAL) \
 	do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0)
 
 extern int smt_enabled_at_boot;
+
+extern int smp_mpic_probe(void);
+extern void smp_mpic_setup_cpu(int cpu);
+extern void smp_mpic_message_pass(int target, int msg);
+extern void smp_generic_kick_cpu(int nr);
+
+extern void smp_generic_give_timebase(void);
+extern void smp_generic_take_timebase(void);
+
+extern struct smp_ops_t *smp_ops;
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-ppc64/udbg.h b/include/asm-ppc64/udbg.h
--- a/include/asm-ppc64/udbg.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-ppc64/udbg.h	2004-10-28 22:25:57 -07:00
@@ -1,6 +1,8 @@
 #ifndef __UDBG_HDR
 #define __UDBG_HDR
 
+#include <linux/compiler.h>
+
 /*
  * c 2001 PPC 64 Team, IBM Corp
  *
@@ -10,7 +12,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-void udbg_init_uart(void *comport);
+void udbg_init_uart(void __iomem *comport, unsigned int speed);
 void udbg_putc(unsigned char c);
 unsigned char udbg_getc(void);
 int udbg_getc_poll(void);
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-ppc64/unistd.h	2004-10-28 22:25:56 -07:00
@@ -279,8 +279,11 @@
 #define __NR_mq_notify		266
 #define __NR_mq_getsetattr	267
 #define __NR_kexec_load		268
+#define __NR_add_key		269
+#define __NR_request_key	270
+#define __NR_keyctl		271
 
-#define __NR_syscalls		269
+#define __NR_syscalls		272
 #ifdef __KERNEL__
 #define NR_syscalls	__NR_syscalls
 #endif
diff -Nru a/include/asm-s390/debug.h b/include/asm-s390/debug.h
--- a/include/asm-s390/debug.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-s390/debug.h	2004-10-28 22:25:58 -07:00
@@ -127,6 +127,8 @@
 
 void debug_set_level(debug_info_t* id, int new_level);
 
+void debug_stop_all(void);
+
 extern inline debug_entry_t* 
 debug_event(debug_info_t* id, int level, void* data, int length)
 {
diff -Nru a/include/asm-s390/extmem.h b/include/asm-s390/extmem.h
--- a/include/asm-s390/extmem.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-s390/extmem.h	2004-10-28 22:25:58 -07:00
@@ -8,12 +8,23 @@
 #ifndef _ASM_S390X_DCSS_H
 #define _ASM_S390X_DCSS_H
 #ifndef __ASSEMBLY__
-#define SEGMENT_SHARED_RW       0
-#define SEGMENT_SHARED_RO       1
-#define SEGMENT_EXCLUSIVE_RW    2
-#define SEGMENT_EXCLUSIVE_RO    3
+
+/* possible values for segment type as returned by segment_info */
+#define SEG_TYPE_SW 0
+#define SEG_TYPE_EW 1
+#define SEG_TYPE_SR 2
+#define SEG_TYPE_ER 3
+#define SEG_TYPE_SN 4
+#define SEG_TYPE_EN 5
+#define SEG_TYPE_SC 6
+
+#define SEGMENT_SHARED 0
+#define SEGMENT_EXCLUSIVE 1
+
 extern int segment_load (char *name,int segtype,unsigned long *addr,unsigned long *length);
 extern void segment_unload(char *name);
-extern void segment_replace(char *name);
+extern void segment_save(char *name);
+extern int segment_info (char* name);
+
 #endif
 #endif
diff -Nru a/include/asm-s390/io.h b/include/asm-s390/io.h
--- a/include/asm-s390/io.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-s390/io.h	2004-10-28 22:25:58 -07:00
@@ -105,6 +105,8 @@
 #define outb(x,addr) ((void) writeb(x,addr))
 #define outb_p(x,addr) outb(x,addr)
 
+#define mmiowb()
+
 #endif /* __KERNEL__ */
 
 #endif
diff -Nru a/include/asm-sh/bitops.h b/include/asm-sh/bitops.h
--- a/include/asm-sh/bitops.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-sh/bitops.h	2004-10-28 22:25:56 -07:00
@@ -344,7 +344,7 @@
 #define ext2_test_bit(nr, addr) test_bit((nr), (addr))
 #define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
 #define ext2_find_next_zero_bit(addr, size, offset) \
-                find_next_zero_bit((addr), (size), (offset))
+                find_next_zero_bit((unsigned long *)(addr), (size), (offset))
 #else
 static __inline__ int ext2_set_bit(int nr, volatile void * addr)
 {
diff -Nru a/include/asm-sh/io.h b/include/asm-sh/io.h
--- a/include/asm-sh/io.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-sh/io.h	2004-10-28 22:25:58 -07:00
@@ -134,6 +134,8 @@
 #define readw_relaxed(a) readw(a)
 #define readl_relaxed(a) readl(a)
 
+#define mmiowb()
+
 /*
  * If the platform has PC-like I/O, this function converts the offset into
  * an address.
diff -Nru a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
--- a/include/asm-sh/pgtable.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-sh/pgtable.h	2004-10-28 22:25:59 -07:00
@@ -288,7 +288,7 @@
 
 #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-extern inline pte_t ptep_get_and_clear(pte_t *ptep);
+extern pte_t ptep_get_and_clear(pte_t *ptep);
 #endif
 
 #include <asm-generic/pgtable.h>
diff -Nru a/include/asm-sh/system.h b/include/asm-sh/system.h
--- a/include/asm-sh/system.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-sh/system.h	2004-10-28 22:25:59 -07:00
@@ -7,7 +7,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/kernel.h>
 
 /*
  *	switch_to() should switch tasks to task nr n, first
diff -Nru a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
--- a/include/asm-sh/unistd.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-sh/unistd.h	2004-10-28 22:25:59 -07:00
@@ -290,8 +290,13 @@
 #define __NR_mq_timedreceive    (__NR_mq_open+3)
 #define __NR_mq_notify          (__NR_mq_open+4)
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
+#define __NR_sys_kexec_load	283
+#define __NR_waitid		284
+#define __NR_add_key		285
+#define __NR_request_key	286
+#define __NR_keyctl		287
 
-#define NR_syscalls 283
+#define NR_syscalls 288
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
 
diff -Nru a/include/asm-sh64/io.h b/include/asm-sh64/io.h
--- a/include/asm-sh64/io.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-sh64/io.h	2004-10-28 22:25:57 -07:00
@@ -86,6 +86,9 @@
 #define readb(addr)		sh64_in8(addr)
 #define readw(addr)		sh64_in16(addr)
 #define readl(addr)		sh64_in32(addr)
+#define readb_relaxed(addr)		sh64_in8(addr)
+#define readw_relaxed(addr)		sh64_in16(addr)
+#define readl_relaxed(addr)		sh64_in32(addr)
 
 #define writeb(b, addr)		sh64_out8(b, addr)
 #define writew(b, addr)		sh64_out16(b, addr)
@@ -105,6 +108,8 @@
 void outb(unsigned long value, unsigned long port);
 void outw(unsigned long value, unsigned long port);
 void outl(unsigned long value, unsigned long port);
+
+#define mmiowb()
 
 #ifdef __KERNEL__
 
diff -Nru a/include/asm-sparc/errno.h b/include/asm-sparc/errno.h
--- a/include/asm-sparc/errno.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-sparc/errno.h	2004-10-28 22:25:59 -07:00
@@ -101,9 +101,10 @@
 
 #define	ENOMEDIUM	125	/* No medium found */
 #define	EMEDIUMTYPE	126	/* Wrong medium type */
-#define	ENOKEY		127	/* Required key not available */
-#define	EKEYEXPIRED	128	/* Key has expired */
-#define	EKEYREVOKED	129	/* Key has been revoked */
-#define	EKEYREJECTED	130	/* Key was rejected by service */
+#define	ECANCELED	127	/* Operation Cancelled */
+#define	ENOKEY		128	/* Required key not available */
+#define	EKEYEXPIRED	129	/* Key has expired */
+#define	EKEYREVOKED	130	/* Key has been revoked */
+#define	EKEYREJECTED	131	/* Key was rejected by service */
 
 #endif
diff -Nru a/include/asm-sparc/io.h b/include/asm-sparc/io.h
--- a/include/asm-sparc/io.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-sparc/io.h	2004-10-28 22:25:56 -07:00
@@ -23,6 +23,8 @@
 	return ((w&0xff) << 8) | ((w>>8)&0xff);
 }
 
+#define mmiowb()
+
 /*
  * Memory mapped I/O to PCI
  *
diff -Nru a/include/asm-sparc64/errno.h b/include/asm-sparc64/errno.h
--- a/include/asm-sparc64/errno.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-sparc64/errno.h	2004-10-28 22:25:56 -07:00
@@ -101,9 +101,10 @@
 
 #define ENOMEDIUM       125     /* No medium found */
 #define EMEDIUMTYPE     126     /* Wrong medium type */
-#define	ENOKEY		127	/* Required key not available */
-#define	EKEYEXPIRED	128	/* Key has expired */
-#define	EKEYREVOKED	129	/* Key has been revoked */
-#define	EKEYREJECTED	130	/* Key was rejected by service */
+#define	ECANCELED	127	/* Operation Cancelled */
+#define	ENOKEY		128	/* Required key not available */
+#define	EKEYEXPIRED	129	/* Key has expired */
+#define	EKEYREVOKED	130	/* Key has been revoked */
+#define	EKEYREJECTED	131	/* Key was rejected by service */
 
 #endif /* !(_SPARC64_ERRNO_H) */
diff -Nru a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
--- a/include/asm-sparc64/io.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-sparc64/io.h	2004-10-28 22:25:59 -07:00
@@ -439,6 +439,8 @@
 	return retval;
 }
 
+#define mmiowb()
+
 #ifdef __KERNEL__
 
 /* On sparc64 we have the whole physical IO address space accessible
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-sparc64/unistd.h	2004-10-28 22:25:57 -07:00
@@ -298,7 +298,7 @@
 #define __NR_mq_notify		277
 #define __NR_mq_getsetattr	278
 #define __NR_waitid		279
-#define __NR_sys_setaltroot	280
+/*#define __NR_sys_setaltroot	280 available (was setaltroot) */
 #define __NR_add_key		281
 #define __NR_request_key	282
 #define __NR_keyctl		283
diff -Nru a/include/asm-um/hardirq.h b/include/asm-um/hardirq.h
--- a/include/asm-um/hardirq.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-um/hardirq.h	2004-10-28 22:25:56 -07:00
@@ -1,6 +1,26 @@
-#ifndef __UM_HARDIRQ_H
-#define __UM_HARDIRQ_H
+/* (c) 2004 cw@f00f.org, GPLv2 blah blah */
 
-#include "asm/arch/hardirq.h"
+#ifndef __ASM_UM_HARDIRQ_H
+#define __ASM_UM_HARDIRQ_H
 
-#endif
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+/* NOTE: When SMP works again we might want to make this
+ * ____cacheline_aligned or maybe use per_cpu state? --cw */
+typedef struct {
+	unsigned int __softirq_pending;
+} irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>
+
+/* As this would be very strange for UML to get we BUG() after the
+ * printk. */
+static inline void ack_bad_irq(unsigned int irq)
+{
+	printk(KERN_ERR "unexpected IRQ %02x\n", irq);
+	BUG();
+}
+
+#endif /* __ASM_UM_HARDIRQ_H */
diff -Nru a/include/asm-v850/io.h b/include/asm-v850/io.h
--- a/include/asm-v850/io.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-v850/io.h	2004-10-28 22:25:57 -07:00
@@ -102,6 +102,8 @@
 #define ioremap_writethrough(physaddr, size)	(physaddr)
 #define ioremap_fullcache(physaddr, size)	(physaddr)
 
+#define mmiowb()
+
 #define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
 #if 0
 /* This is really stupid; don't define it.  */
diff -Nru a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
--- a/include/asm-x86_64/apic.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-x86_64/apic.h	2004-10-28 22:25:59 -07:00
@@ -97,6 +97,7 @@
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
+extern void clustered_apic_check(void);
 
 extern int check_nmi_watchdog(void);
 extern void nmi_watchdog_default(void);
@@ -111,7 +112,6 @@
 
 #endif /* CONFIG_X86_LOCAL_APIC */
 
-#define clustered_apic_mode 0
 #define esr_disable 0
 extern unsigned boot_cpu_id;
 
diff -Nru a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
--- a/include/asm-x86_64/apicdef.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-x86_64/apicdef.h	2004-10-28 22:25:57 -07:00
@@ -11,27 +11,29 @@
 #define		APIC_DEFAULT_PHYS_BASE	0xfee00000
  
 #define		APIC_ID		0x20
-#define			APIC_ID_MASK		(0x0F<<24)
-#define			GET_APIC_ID(x)		(((x)>>24)&0x0F)
+#define			APIC_ID_MASK		(0xFFu<<24)
+#define			GET_APIC_ID(x)		(((x)>>24)&0xFFu)
 #define		APIC_LVR	0x30
 #define			APIC_LVR_MASK		0xFF00FF
-#define			GET_APIC_VERSION(x)	((x)&0xFF)
-#define			GET_APIC_MAXLVT(x)	(((x)>>16)&0xFF)
-#define			APIC_INTEGRATED(x)	((x)&0xF0)
+#define			GET_APIC_VERSION(x)	((x)&0xFFu)
+#define			GET_APIC_MAXLVT(x)	(((x)>>16)&0xFFu)
+#define			APIC_INTEGRATED(x)	((x)&0xF0u)
 #define		APIC_TASKPRI	0x80
-#define			APIC_TPRI_MASK		0xFF
+#define			APIC_TPRI_MASK		0xFFu
 #define		APIC_ARBPRI	0x90
-#define			APIC_ARBPRI_MASK	0xFF
+#define			APIC_ARBPRI_MASK	0xFFu
 #define		APIC_PROCPRI	0xA0
 #define		APIC_EOI	0xB0
 #define			APIC_EIO_ACK		0x0		/* Write this to the EOI register */
 #define		APIC_RRR	0xC0
 #define		APIC_LDR	0xD0
-#define			APIC_LDR_MASK		(0xFF<<24)
-#define			GET_APIC_LOGICAL_ID(x)	(((x)>>24)&0xFF)
+#define			APIC_LDR_MASK		(0xFFu<<24)
+#define			GET_APIC_LOGICAL_ID(x)	(((x)>>24)&0xFFu)
 #define			SET_APIC_LOGICAL_ID(x)	(((x)<<24))
-#define			APIC_ALL_CPUS		0xFF
+#define			APIC_ALL_CPUS		0xFFu
 #define		APIC_DFR	0xE0
+#define			APIC_DFR_CLUSTER		0x0FFFFFFFul
+#define			APIC_DFR_FLAT			0xFFFFFFFFul
 #define		APIC_SPIV	0xF0
 #define			APIC_SPIV_FOCUS_DISABLED	(1<<9)
 #define			APIC_SPIV_APIC_ENABLED		(1<<8)
@@ -58,6 +60,7 @@
 #define			APIC_INT_ASSERT		0x04000
 #define			APIC_ICR_BUSY		0x01000
 #define			APIC_DEST_LOGICAL	0x00800
+#define			APIC_DEST_PHYSICAL	0x00000
 #define			APIC_DM_FIXED		0x00000
 #define			APIC_DM_LOWEST		0x00100
 #define			APIC_DM_SMI		0x00200
@@ -86,6 +89,7 @@
 #define			APIC_LVT_REMOTE_IRR		(1<<14)
 #define			APIC_INPUT_POLARITY		(1<<13)
 #define			APIC_SEND_PENDING		(1<<12)
+#define			APIC_MODE_MASK			0x700
 #define			GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
 #define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
 #define				APIC_MODE_FIXED		0x0
@@ -109,6 +113,18 @@
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
 #define MAX_IO_APICS 32
+
+/*
+ * All x86-64 systems are xAPIC compatible.
+ * In the following, "apicid" is a physical APIC ID.
+ */
+#define XAPIC_DEST_CPUS_SHIFT	4
+#define XAPIC_DEST_CPUS_MASK	((1u << XAPIC_DEST_CPUS_SHIFT) - 1)
+#define XAPIC_DEST_CLUSTER_MASK	(XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT)
+#define APIC_CLUSTER(apicid)	((apicid) & XAPIC_DEST_CLUSTER_MASK)
+#define APIC_CLUSTERID(apicid)	(APIC_CLUSTER(apicid) >> XAPIC_DEST_CPUS_SHIFT)
+#define APIC_CPUID(apicid)	((apicid) & XAPIC_DEST_CPUS_MASK)
+#define NUM_APIC_CLUSTERS	((BAD_APICID + 1) >> XAPIC_DEST_CPUS_SHIFT)
 
 /*
  * the local APIC register structure, memory mapped. Not terribly well
diff -Nru a/include/asm-x86_64/genapic.h b/include/asm-x86_64/genapic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-x86_64/genapic.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,34 @@
+#ifndef _ASM_GENAPIC_H
+#define _ASM_GENAPIC_H 1
+
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Generic APIC sub-arch data struct.
+ *
+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+ * James Cleverdon.
+ */
+
+struct genapic {
+	char *name;
+	u32 int_delivery_mode;
+	u32 int_dest_mode;
+	u32 int_delivery_dest;	/* for quick IPIs */
+	int (*apic_id_registered)(void);
+	cpumask_t (*target_cpus)(void);
+	void (*init_apic_ldr)(void);
+	/* ipi */
+	void (*send_IPI_mask)(cpumask_t mask, int vector);
+	void (*send_IPI_allbutself)(int vector);
+	void (*send_IPI_all)(int vector);
+	/* */
+	unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
+};
+
+
+extern struct genapic *genapic;
+
+#endif
diff -Nru a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
--- a/include/asm-x86_64/io.h	2004-10-28 22:25:57 -07:00
+++ b/include/asm-x86_64/io.h	2004-10-28 22:25:57 -07:00
@@ -204,6 +204,8 @@
 #define __raw_readl readl
 #define __raw_readq readq
 
+#define mmiowb()
+
 #ifdef CONFIG_UNORDERED_IO
 static inline void __writel(__u32 val, volatile void __iomem *addr)
 {
diff -Nru a/include/asm-x86_64/ipi.h b/include/asm-x86_64/ipi.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-x86_64/ipi.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,113 @@
+#ifndef __ASM_IPI_H
+#define __ASM_IPI_H
+
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Generic APIC InterProcessor Interrupt code.
+ *
+ * Moved to include file by James Cleverdon from
+ * arch/x86-64/kernel/smp.c
+ *
+ * Copyrights from kernel/smp.c:
+ *
+ * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
+ * (c) 2002,2003 Andi Kleen, SuSE Labs.
+ * Subject to the GNU Public License, v.2
+ */
+
+#include <asm/fixmap.h>
+#include <asm/hw_irq.h>
+#include <asm/apicdef.h>
+#include <asm/genapic.h>
+
+/*
+ * the following functions deal with sending IPIs between CPUs.
+ *
+ * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
+ */
+
+static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
+{
+	unsigned int icr =  APIC_DM_FIXED | shortcut | vector | dest;
+	if (vector == KDB_VECTOR)
+		icr = (icr & (~APIC_VECTOR_MASK)) | APIC_DM_NMI;
+	return icr;
+}
+
+static inline int __prepare_ICR2 (unsigned int mask)
+{
+	return SET_APIC_DEST_FIELD(mask);
+}
+
+static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
+{
+	/*
+	 * Subtle. In the case of the 'never do double writes' workaround
+	 * we have to lock out interrupts to be safe.  As we don't care
+	 * of the value read we use an atomic rmw access to avoid costly
+	 * cli/sti.  Otherwise we use an even cheaper single atomic write
+	 * to the APIC.
+	 */
+	unsigned int cfg;
+
+	/*
+	 * Wait for idle.
+	 */
+	apic_wait_icr_idle();
+
+	/*
+	 * No need to touch the target chip field
+	 */
+	cfg = __prepare_ICR(shortcut, vector, dest);
+
+	/*
+	 * Send the IPI. The write to APIC_ICR fires this off.
+	 */
+	apic_write_around(APIC_ICR, cfg);
+}
+
+
+static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
+{
+	unsigned long cfg, flags;
+	unsigned long query_cpu;
+
+	/*
+	 * Hack. The clustered APIC addressing mode doesn't allow us to send
+	 * to an arbitrary mask, so I do a unicast to each CPU instead.
+	 * - mbligh
+	 */
+	local_irq_save(flags);
+
+	for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) {
+		if (cpu_isset(query_cpu, mask)) {
+
+			/*
+			 * Wait for idle.
+			 */
+			apic_wait_icr_idle();
+
+			/*
+			 * prepare target chip field
+			 */
+			cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]);
+			apic_write_around(APIC_ICR2, cfg);
+
+			/*
+			 * program the ICR
+			 */
+			cfg = __prepare_ICR(0, vector, APIC_DEST_PHYSICAL);
+
+			/*
+			 * Send the IPI. The write to APIC_ICR fires this off.
+			 */
+			apic_write_around(APIC_ICR, cfg);
+		}
+	}
+	local_irq_restore(flags);
+}
+
+#endif /* __ASM_IPI_H */
diff -Nru a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h
--- a/include/asm-x86_64/irq.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-x86_64/irq.h	2004-10-28 22:25:56 -07:00
@@ -36,7 +36,7 @@
 #define NR_IRQ_VECTORS NR_IRQS
 #else
 #define NR_IRQS 224
-#define NR_IRQ_VECTORS NR_IRQS
+#define NR_IRQ_VECTORS 1024
 #endif
 
 static __inline__ int irq_canonicalize(int irq)
diff -Nru a/include/asm-x86_64/mach_apic.h b/include/asm-x86_64/mach_apic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-x86_64/mach_apic.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,28 @@
+#ifndef __ASM_MACH_APIC_H
+#define __ASM_MACH_APIC_H
+
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Generic APIC sub-arch defines.
+ *
+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+ * James Cleverdon.
+ */
+
+#include <asm/genapic.h>
+
+#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
+#define INT_DEST_MODE (genapic->int_dest_mode)
+#define INT_DELIVERY_DEST (genapic->int_delivery_dest)
+#define TARGET_CPUS	  (genapic->target_cpus())
+#define apic_id_registered (genapic->apic_id_registered)
+#define init_apic_ldr (genapic->init_apic_ldr)
+#define send_IPI_mask (genapic->send_IPI_mask)
+#define send_IPI_allbutself (genapic->send_IPI_allbutself)
+#define send_IPI_all (genapic->send_IPI_all)
+#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
+
+#endif /* __ASM_MACH_APIC_H */
diff -Nru a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
--- a/include/asm-x86_64/mpspec.h	2004-10-28 22:25:58 -07:00
+++ b/include/asm-x86_64/mpspec.h	2004-10-28 22:25:58 -07:00
@@ -14,9 +14,9 @@
 #define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')
 
 /*
- * a maximum of 16 APICs with the current APIC ID architecture.
+ * A maximum of 255 APICs with the current APIC ID architecture.
  */
-#define MAX_APICS 16
+#define MAX_APICS 128
 
 struct intel_mp_floating
 {
diff -Nru a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h
--- a/include/asm-x86_64/msi.h	2004-10-28 22:25:59 -07:00
+++ b/include/asm-x86_64/msi.h	2004-10-28 22:25:59 -07:00
@@ -7,6 +7,7 @@
 #define ASM_MSI_H
 
 #include <asm/desc.h>
+#include <asm/mach_apic.h>
 #include <asm/smp.h>
 
 #define LAST_DEVICE_VECTOR		232
diff -Nru a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
--- a/include/asm-x86_64/smp.h	2004-10-28 22:25:56 -07:00
+++ b/include/asm-x86_64/smp.h	2004-10-28 22:25:56 -07:00
@@ -48,7 +48,7 @@
 extern void zap_low_mappings(void);
 void smp_stop_cpu(void);
 extern cpumask_t cpu_sibling_map[NR_CPUS];
-extern char phys_proc_id[NR_CPUS];
+extern u8 phys_proc_id[NR_CPUS];
 
 #define SMP_TRAMPOLINE_BASE 0x6000
 
@@ -74,14 +74,29 @@
 	return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
 }
 
+#define safe_smp_processor_id() (disable_apic ? 0 : x86_apicid_to_cpu(hard_smp_processor_id()))
+
+#endif /* !ASSEMBLY */
+
+#define NO_PROC_ID		0xFF		/* No processor magic marker */
+
+#endif
+
+#ifndef ASSEMBLY
 /*
  * Some lowlevel functions might want to know about
  * the real APIC ID <-> CPU # mapping.
- * AK: why is this volatile?
  */
-extern volatile char x86_cpu_to_apicid[NR_CPUS];
+extern u8 x86_cpu_to_apicid[NR_CPUS];	/* physical ID */
+extern u8 x86_cpu_to_log_apicid[NR_CPUS];
+extern u8 bios_cpu_apicid[];
+
+static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+{
+	return cpus_addr(cpumask)[0];
+}
 
-static inline char x86_apicid_to_cpu(char apicid)
+static inline int x86_apicid_to_cpu(u8 apicid)
 {
 	int i;
 
@@ -92,10 +107,6 @@
 	return -1;
 }
 
-#define safe_smp_processor_id() (disable_apic ? 0 : x86_apicid_to_cpu(hard_smp_processor_id()))
-
-extern u8 bios_cpu_apicid[];
-
 static inline int cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < NR_CPUS)
@@ -105,23 +116,6 @@
 }
 
 #endif /* !ASSEMBLY */
-
-#define NO_PROC_ID		0xFF		/* No processor magic marker */
-
-#endif
-#define INT_DELIVERY_MODE 1     /* logical delivery */
-
-#ifndef ASSEMBLY
-#ifdef CONFIG_SMP
-#define TARGET_CPUS cpu_online_map
-#else
-#define TARGET_CPUS cpumask_of_cpu(0)
-#endif
-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
-{
-	return cpus_addr(cpumask)[0];
-}
-#endif
 
 #ifndef CONFIG_SMP
 #define stack_smp_processor_id() 0
diff -Nru a/include/linux/8250.h b/include/linux/8250.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/8250.h	2004-10-28 22:25:56 -07:00
@@ -0,0 +1,75 @@
+/*
+ *  linux/drivers/char/8250.h
+ *
+ *  Driver for 8250/16550-type serial ports
+ *
+ *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ *  Copyright (C) 2001 Russell King.
+ *
+ * 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.
+ *
+ *  $Id: 8250.h,v 1.8 2002/07/21 21:32:30 rmk Exp $
+ */
+
+#include <linux/config.h>
+
+int serial8250_register_port(struct uart_port *);
+void serial8250_unregister_port(int line);
+void serial8250_get_irq_map(unsigned int *map);
+void serial8250_suspend_port(int line);
+void serial8250_resume_port(int line);
+
+struct old_serial_port {
+	unsigned int uart;
+	unsigned int baud_base;
+	unsigned int port;
+	unsigned int irq;
+	unsigned int flags;
+	unsigned char hub6;
+	unsigned char io_type;
+	unsigned char *iomem_base;
+	unsigned short iomem_reg_shift;
+};
+
+/*
+ * This replaces serial_uart_config in include/linux/serial.h
+ */
+struct serial8250_config {
+	const char	*name;
+	unsigned short	fifo_size;
+	unsigned short	tx_loadsz;
+	unsigned char	fcr;
+	unsigned int	flags;
+};
+
+#define UART_CAP_FIFO	(1 << 8)	/* UART has FIFO */
+#define UART_CAP_EFR	(1 << 9)	/* UART has EFR */
+#define UART_CAP_SLEEP	(1 << 10)	/* UART has IER sleep */
+#define UART_CAP_AFE	(1 << 11)	/* MCR-based hw flow control */
+
+#undef SERIAL_DEBUG_PCI
+
+#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
+#define SERIAL_INLINE
+#endif
+  
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#else
+#define _INLINE_
+#endif
+
+#define PROBE_RSA	(1 << 0)
+#define PROBE_ANY	(~0)
+
+#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
+
+#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
+#define SERIAL8250_SHARE_IRQS 1
+#else
+#define SERIAL8250_SHARE_IRQS 0
+#endif
diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h
--- a/include/linux/atmdev.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/atmdev.h	2004-10-28 22:25:59 -07:00
@@ -395,7 +395,6 @@
 void atm_dev_deregister(struct atm_dev *dev);
 void shutdown_atm_dev(struct atm_dev *dev);
 void vcc_insert_socket(struct sock *sk);
-void vcc_remove_socket(struct sock *sk);
 
 
 /*
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/blkdev.h	2004-10-28 22:25:57 -07:00
@@ -377,6 +377,8 @@
 	 */
 	unsigned int		sg_timeout;
 	unsigned int		sg_reserved_size;
+
+	struct list_head	drain_list;
 };
 
 #define RQ_INACTIVE		(-1)
@@ -604,7 +606,7 @@
 extern void generic_unplug_device(request_queue_t *);
 extern void __generic_unplug_device(request_queue_t *);
 extern long nr_blockdev_pages(void);
-extern void blk_wait_queue_drained(request_queue_t *);
+extern void blk_wait_queue_drained(request_queue_t *, int);
 extern void blk_finish_queue_drain(request_queue_t *);
 
 int blk_get_queue(request_queue_t *);
diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h
--- a/include/linux/buffer_head.h	2004-10-28 22:25:56 -07:00
+++ b/include/linux/buffer_head.h	2004-10-28 22:25:56 -07:00
@@ -76,7 +76,7 @@
 {									\
 	clear_bit(BH_##bit, &(bh)->b_state);				\
 }									\
-static inline int buffer_##name(struct buffer_head *bh)			\
+static inline int buffer_##name(const struct buffer_head *bh)		\
 {									\
 	return test_bit(BH_##bit, &(bh)->b_state);			\
 }
diff -Nru a/include/linux/compat.h b/include/linux/compat.h
--- a/include/linux/compat.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/compat.h	2004-10-28 22:25:58 -07:00
@@ -119,6 +119,8 @@
 long compat_sys_shmctl(int first, int second, void __user *uptr);
 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
 		unsigned nsems, const struct compat_timespec __user *timeout);
+asmlinkage long compat_sys_keyctl(u32 option,
+			      u32 arg2, u32 arg3, u32 arg4, u32 arg5);
 
 asmlinkage ssize_t compat_sys_readv(unsigned long fd,
 		const struct compat_iovec __user *vec, unsigned long vlen);
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/compiler.h	2004-10-28 22:25:58 -07:00
@@ -9,6 +9,10 @@
 # define __safe		__attribute__((safe))
 # define __force	__attribute__((force))
 # define __iomem	__attribute__((noderef, address_space(2)))
+# define __acquires(x)	__attribute__((context(0,1)))
+# define __releases(x)	__attribute__((context(1,0)))
+# define __acquire(x)	__context__(1)
+# define __release(x)	__context__(-1)
 extern void __chk_user_ptr(void __user *);
 extern void __chk_io_ptr(void __iomem *);
 #else
@@ -20,6 +24,10 @@
 # define __chk_user_ptr(x) (void)0
 # define __chk_io_ptr(x) (void)0
 # define __builtin_warning(x, y...) (1)
+# define __acquires(x)
+# define __releases(x)
+# define __acquire(x) (void)0
+# define __release(x) (void)0
 #endif
 
 #ifdef __KERNEL__
diff -Nru a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h
--- a/include/linux/dvb/frontend.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/dvb/frontend.h	2004-10-28 22:25:58 -07:00
@@ -258,6 +258,8 @@
 #define FE_GET_FRONTEND            _IOR('o', 77, struct dvb_frontend_parameters)
 #define FE_GET_EVENT               _IOR('o', 78, struct dvb_frontend_event)
 
+#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
+
 
 #endif /*_DVBFRONTEND_H_*/
 
diff -Nru a/include/linux/fb.h b/include/linux/fb.h
--- a/include/linux/fb.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/fb.h	2004-10-28 22:25:57 -07:00
@@ -102,6 +102,7 @@
 #define FB_ACCEL_I810           39      /* Intel 810/815                */
 #define FB_ACCEL_SIS_GLAMOUR_2  40	/* SiS 315, 650, 740		*/
 #define FB_ACCEL_SIS_XABRE      41	/* SiS 330 ("Xabre")		*/
+#define FB_ACCEL_I830           42      /* Intel 830M/845G/85x/865G     */
 
 #define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
@@ -113,6 +114,21 @@
 #define FB_ACCEL_NEOMAGIC_NM2360 97	/* NeoMagic NM2360              */
 #define FB_ACCEL_NEOMAGIC_NM2380 98	/* NeoMagic NM2380              */
 
+#define FB_ACCEL_SAVAGE4        0x80	/* S3 Savage4                   */
+#define FB_ACCEL_SAVAGE3D       0x81	/* S3 Savage3D                  */
+#define FB_ACCEL_SAVAGE3D_MV    0x82	/* S3 Savage3D-MV               */
+#define FB_ACCEL_SAVAGE2000     0x83	/* S3 Savage2000                */
+#define FB_ACCEL_SAVAGE_MX_MV   0x84	/* S3 Savage/MX-MV              */
+#define FB_ACCEL_SAVAGE_MX      0x85	/* S3 Savage/MX                 */
+#define FB_ACCEL_SAVAGE_IX_MV   0x86	/* S3 Savage/IX-MV              */
+#define FB_ACCEL_SAVAGE_IX      0x87	/* S3 Savage/IX                 */
+#define FB_ACCEL_PROSAVAGE_PM   0x88	/* S3 ProSavage PM133           */
+#define FB_ACCEL_PROSAVAGE_KM   0x89	/* S3 ProSavage KM133           */
+#define FB_ACCEL_S3TWISTER_P    0x8a	/* S3 Twister                   */
+#define FB_ACCEL_S3TWISTER_K    0x8b	/* S3 TwisterK                  */
+#define FB_ACCEL_SUPERSAVAGE    0x8c    /* S3 Supersavage               */
+#define FB_ACCEL_PROSAVAGE_DDR  0x8d	/* S3 ProSavage DDR             */
+#define FB_ACCEL_PROSAVAGE_DDRK 0x8e	/* S3 ProSavage DDR-K           */
 
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
@@ -298,7 +314,7 @@
  * hardware cursor control
  */
 
-#define FB_CUR_SETCUR   0x01
+#define FB_CUR_SETIMAGE 0x01
 #define FB_CUR_SETPOS   0x02
 #define FB_CUR_SETHOT   0x04
 #define FB_CUR_SETCMAP  0x08
@@ -317,9 +333,6 @@
 	const char *mask;	/* cursor mask bits */
 	struct fbcurpos hot;	/* cursor hot spot */
 	struct fb_image	image;	/* Cursor image */
-/* all fields below are for fbcon use only */
-	int   flash;            /* cursor blink */
-	char  *data;             /* copy of bitmap */
 };
 
 #ifdef __KERNEL__
@@ -671,7 +684,6 @@
 	struct fb_var_screeninfo var;	/* Current var */
 	struct fb_fix_screeninfo fix;	/* Current fix */
 	struct fb_monspecs monspecs;	/* Current Monitor specs */
-	struct fb_cursor cursor;	/* Current cursor */	
 	struct work_struct queue;	/* Framebuffer event queue */
 	struct timer_list cursor_timer; /* Cursor timer */
 	struct fb_pixmap pixmap;	/* Image hardware mapper */
@@ -787,7 +799,6 @@
 extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
 				u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
 				u32 height);
-extern void fb_load_cursor_image(struct fb_info *);
 extern void fb_set_suspend(struct fb_info *info, int state);
 extern int fb_get_color_depth(struct fb_info *info);
 extern int fb_get_options(char *name, char **option);
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/fs.h	2004-10-28 22:25:57 -07:00
@@ -348,7 +348,12 @@
 	spinlock_t		private_lock;	/* for use by the address_space */
 	struct list_head	private_list;	/* ditto */
 	struct address_space	*assoc_mapping;	/* ditto */
-};
+} __attribute__((aligned(sizeof(long))));
+	/*
+	 * On most architectures that alignment is already the case; but
+	 * must be enforced here for CRIS, to let the least signficant bit
+	 * of struct page's "mapping" pointer be used for PAGE_MAPPING_ANON.
+	 */
 
 struct block_device {
 	dev_t			bd_dev;  /* not a kdev_t - it's a search key */
@@ -1524,7 +1529,6 @@
 extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
 extern int vfs_follow_link(struct nameidata *, const char *);
 extern int page_readlink(struct dentry *, char __user *, int);
-extern int page_follow_link(struct dentry *, struct nameidata *);
 extern int page_follow_link_light(struct dentry *, struct nameidata *);
 extern void page_put_link(struct dentry *, struct nameidata *);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
@@ -1571,6 +1575,7 @@
 extern struct file_operations simple_dir_operations;
 extern struct inode_operations simple_dir_inode_operations;
 struct tree_descr { char *name; struct file_operations *ops; int mode; };
+struct dentry *d_alloc_name(struct dentry *, const char *);
 extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
 extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
 extern void simple_release_fs(struct vfsmount **mount, int *count);
diff -Nru a/include/linux/hdlc.h b/include/linux/hdlc.h
--- a/include/linux/hdlc.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/hdlc.h	2004-10-28 22:25:59 -07:00
@@ -243,11 +243,15 @@
 static __inline__ unsigned short hdlc_type_trans(struct sk_buff *skb,
 						 struct net_device *dev)
 {
-	hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+	hdlc_device *hdlc = dev_to_hdlc(dev);
+
+	skb->mac.raw  = skb->data;
+	skb->dev      = dev;
+
 	if (hdlc->proto.type_trans)
 		return hdlc->proto.type_trans(skb, dev);
 	else
-		return __constant_htons(ETH_P_HDLC);
+		return htons(ETH_P_HDLC);
 }
 
 #endif /* __KERNEL */
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/ide.h	2004-10-28 22:25:57 -07:00
@@ -874,7 +874,6 @@
 	int (*ide_dma_test_irq)(ide_drive_t *drive);
 	int (*ide_dma_host_on)(ide_drive_t *drive);
 	int (*ide_dma_host_off)(ide_drive_t *drive);
-	int (*ide_dma_verbose)(ide_drive_t *drive);
 	int (*ide_dma_lostirq)(ide_drive_t *drive);
 	int (*ide_dma_timeout)(ide_drive_t *drive);
 
@@ -938,6 +937,7 @@
 	unsigned	no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
 	unsigned	no_dsc     : 1;	/* 0 default, 1 dsc_overlap disabled */
 	unsigned	auto_poll  : 1; /* supports nop auto-poll */
+	unsigned	sg_mapped  : 1;	/* sg_table and sg_nents are ready */
 
 	struct device	gendev;
 	struct semaphore gendev_rel_sem; /* To deal with device release() */
@@ -1302,9 +1302,6 @@
  */
 extern int ide_wait_cmd(ide_drive_t *, u8, u8, u8, u8, u8 *);
 
-/* (ide_drive_t *drive, u8 *buf) */
-extern int ide_wait_cmd_task(ide_drive_t *, u8 *);
-
 typedef struct ide_task_s {
 /*
  *	struct hd_drive_task_hdr	tf;
@@ -1349,8 +1346,6 @@
 extern void ata_output_data(ide_drive_t *, void *, u32);
 extern void atapi_input_bytes(ide_drive_t *, void *, u32);
 extern void atapi_output_bytes(ide_drive_t *, void *, u32);
-extern void taskfile_input_data(ide_drive_t *, void *, u32);
-extern void taskfile_output_data(ide_drive_t *, void *, u32);
 
 extern int drive_is_ready(ide_drive_t *);
 extern int wait_for_ready(ide_drive_t *, int /* timeout */);
@@ -1491,11 +1486,12 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 int __ide_dma_bad_drive(ide_drive_t *);
 int __ide_dma_good_drive(ide_drive_t *);
+int ide_use_dma(ide_drive_t *);
 int __ide_dma_off(ide_drive_t *);
+void ide_dma_verbose(ide_drive_t *);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
 extern int ide_build_sglist(ide_drive_t *, struct request *);
-extern int ide_raw_build_sglist(ide_drive_t *, struct request *);
 extern int ide_build_dmatable(ide_drive_t *, struct request *);
 extern void ide_destroy_dmatable(ide_drive_t *);
 extern ide_startstop_t ide_dma_intr(ide_drive_t *);
@@ -1511,13 +1507,14 @@
 extern void ide_dma_start(ide_drive_t *);
 extern int __ide_dma_end(ide_drive_t *);
 extern int __ide_dma_test_irq(ide_drive_t *);
-extern int __ide_dma_verbose(ide_drive_t *);
 extern int __ide_dma_lostirq(ide_drive_t *);
 extern int __ide_dma_timeout(ide_drive_t *);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
 
 #else
+static inline int ide_use_dma(ide_drive_t *drive) { return 0; }
 static inline int __ide_dma_off(ide_drive_t *drive) { return 0; }
+static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 #ifndef CONFIG_BLK_DEV_IDEDMA_PCI
diff -Nru a/include/linux/if_vlan.h b/include/linux/if_vlan.h
--- a/include/linux/if_vlan.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/if_vlan.h	2004-10-28 22:25:57 -07:00
@@ -366,7 +366,9 @@
 	GET_VLAN_INGRESS_PRIORITY_CMD,
 	GET_VLAN_EGRESS_PRIORITY_CMD,
 	SET_VLAN_NAME_TYPE_CMD,
-	SET_VLAN_FLAG_CMD
+	SET_VLAN_FLAG_CMD,
+	GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
+	GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
 };
 
 enum vlan_name_types {
diff -Nru a/include/linux/input.h b/include/linux/input.h
--- a/include/linux/input.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/input.h	2004-10-28 22:25:57 -07:00
@@ -473,6 +473,28 @@
 #define KEY_INS_LINE		0x1c2
 #define KEY_DEL_LINE		0x1c3
 
+#define KEY_FN			0x1d0
+#define KEY_FN_ESC		0x1d1
+#define KEY_FN_F1		0x1d2
+#define KEY_FN_F2		0x1d3
+#define KEY_FN_F3		0x1d4
+#define KEY_FN_F4		0x1d5
+#define KEY_FN_F5		0x1d6
+#define KEY_FN_F6		0x1d7
+#define KEY_FN_F7		0x1d8
+#define KEY_FN_F8		0x1d9
+#define KEY_FN_F9		0x1da
+#define KEY_FN_F10		0x1db
+#define KEY_FN_F11		0x1dc
+#define KEY_FN_F12		0x1dd
+#define KEY_FN_1		0x1de
+#define KEY_FN_2		0x1df
+#define KEY_FN_D		0x1e0
+#define KEY_FN_E		0x1e1
+#define KEY_FN_F		0x1e2
+#define KEY_FN_S		0x1e3
+#define KEY_FN_B		0x1e4
+
 #define KEY_MAX			0x1ff
 
 /*
diff -Nru a/include/linux/interrupt.h b/include/linux/interrupt.h
--- a/include/linux/interrupt.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/interrupt.h	2004-10-28 22:25:58 -07:00
@@ -109,10 +109,6 @@
 extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
 extern void FASTCALL(raise_softirq(unsigned int nr));
 
-#ifndef invoke_softirq
-#define invoke_softirq() do_softirq()
-#endif
-
 
 /* Tasklets --- multithreaded analogue of BHs.
 
diff -Nru a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h
--- a/include/linux/ipv6_route.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/ipv6_route.h	2004-10-28 22:25:57 -07:00
@@ -14,7 +14,8 @@
 #define _LINUX_IPV6_ROUTE_H
 
 #define RTF_DEFAULT	0x00010000	/* default - learned via ND	*/
-#define RTF_ALLONLINK	0x00020000	/* fallback, no routers on link	*/
+#define RTF_ALLONLINK	0x00020000	/* (deprecated and will be removed)
+					   fallback, no routers on link */
 #define RTF_ADDRCONF	0x00040000	/* addrconf route - RA		*/
 #define RTF_PREFIX_RT	0x00080000	/* A prefix only route - RA	*/
 
diff -Nru a/include/linux/kobject_uevent.h b/include/linux/kobject_uevent.h
--- a/include/linux/kobject_uevent.h	2004-10-28 22:25:56 -07:00
+++ b/include/linux/kobject_uevent.h	2004-10-28 22:25:56 -07:00
@@ -22,6 +22,7 @@
 	KOBJ_CHANGE	= (__force kobject_action_t) 0x03,	/* a sysfs attribute file has changed */
 	KOBJ_MOUNT	= (__force kobject_action_t) 0x04,	/* mount event for block devices */
 	KOBJ_UMOUNT	= (__force kobject_action_t) 0x05,	/* umount event for block devices */
+	KOBJ_OFFLINE	= (__force kobject_action_t) 0x06,	/* offline event for hotplug devices */
 };
 
 
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/list.h	2004-10-28 22:25:58 -07:00
@@ -568,8 +568,6 @@
 	}
 }
 
-#define hlist_del_rcu_init hlist_del_init
-
 static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
 {
 	struct hlist_node *first = h->first;
diff -Nru a/include/linux/mempolicy.h b/include/linux/mempolicy.h
--- a/include/linux/mempolicy.h	2004-10-28 22:25:56 -07:00
+++ b/include/linux/mempolicy.h	2004-10-28 22:25:56 -07:00
@@ -30,7 +30,7 @@
 #include <linux/bitmap.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
-#include <asm/semaphore.h>
+#include <linux/spinlock.h>
 
 struct vm_area_struct;
 
@@ -134,13 +134,13 @@
 
 struct shared_policy {
 	struct rb_root root;
-	struct semaphore sem;
+	spinlock_t lock;
 };
 
 static inline void mpol_shared_policy_init(struct shared_policy *info)
 {
 	info->root = RB_ROOT;
-	init_MUTEX(&info->sem);
+	spin_lock_init(&info->lock);
 }
 
 int mpol_set_shared_policy(struct shared_policy *info,
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	2004-10-28 22:25:56 -07:00
+++ b/include/linux/mm.h	2004-10-28 22:25:56 -07:00
@@ -41,6 +41,8 @@
 #define MM_VM_SIZE(mm)	TASK_SIZE
 #endif
 
+#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + n)
+
 /*
  * Linux kernel virtual memory manager primitives.
  * The idea being to have a "virtual" mm in the same way
@@ -756,6 +758,7 @@
 extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr);
 
 extern struct page * vmalloc_to_page(void *addr);
+extern unsigned long vmalloc_to_pfn(void *addr);
 extern struct page * follow_page(struct mm_struct *mm, unsigned long address,
 		int write);
 int remap_pfn_range(struct vm_area_struct *, unsigned long,
diff -Nru a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
--- a/include/linux/mmc/mmc.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/mmc/mmc.h	2004-10-28 22:25:58 -07:00
@@ -57,7 +57,7 @@
 	unsigned int		timeout_clks;	/* data timeout (in clocks) */
 	unsigned int		blksz_bits;	/* data block size */
 	unsigned int		blocks;		/* number of blocks */
-	struct request		*req;		/* request structure */
+	struct request		*req __attribute__((deprecated));/* request structure (use the sg list instead) */
 	unsigned int		error;		/* data error */
 	unsigned int		flags;
 
@@ -69,6 +69,9 @@
 
 	struct mmc_command	*stop;		/* stop command */
 	struct mmc_request	*mrq;		/* assoicated request */
+
+	unsigned int		sg_len;		/* size of scatter list */
+	struct scatterlist	*sg;		/* I/O scatter list */
 };
 
 struct mmc_request {
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/mmzone.h	2004-10-28 22:25:58 -07:00
@@ -35,7 +35,7 @@
  */
 #if defined(CONFIG_SMP)
 struct zone_padding {
-	int x;
+	char x[0];
 } ____cacheline_maxaligned_in_smp;
 #define ZONE_PADDING(name)	struct zone_padding name;
 #else
@@ -108,10 +108,7 @@
  */
 
 struct zone {
-	/*
-	 * Commonly accessed fields:
-	 */
-	spinlock_t		lock;
+	/* Fields commonly accessed by the page allocator */
 	unsigned long		free_pages;
 	unsigned long		pages_min, pages_low, pages_high;
 	/*
@@ -128,8 +125,18 @@
 	 */
 	unsigned long		protection[MAX_NR_ZONES];
 
+	struct per_cpu_pageset	pageset[NR_CPUS];
+
+	/*
+	 * free areas of different sizes
+	 */
+	spinlock_t		lock;
+	struct free_area	free_area[MAX_ORDER];
+
+
 	ZONE_PADDING(_pad1_)
 
+	/* Fields commonly accessed by the page reclaim scanner */
 	spinlock_t		lru_lock;	
 	struct list_head	active_list;
 	struct list_head	inactive_list;
@@ -137,10 +144,8 @@
 	unsigned long		nr_scan_inactive;
 	unsigned long		nr_active;
 	unsigned long		nr_inactive;
-	int			all_unreclaimable; /* All pages pinned */
 	unsigned long		pages_scanned;	   /* since last reclaim */
-
-	ZONE_PADDING(_pad2_)
+	int			all_unreclaimable; /* All pages pinned */
 
 	/*
 	 * prev_priority holds the scanning priority for this zone.  It is
@@ -161,10 +166,9 @@
 	int temp_priority;
 	int prev_priority;
 
-	/*
-	 * free areas of different sizes
-	 */
-	struct free_area	free_area[MAX_ORDER];
+
+	ZONE_PADDING(_pad2_)
+	/* Rarely used or read-mostly fields */
 
 	/*
 	 * wait_table		-- the array holding the hash table
@@ -194,10 +198,6 @@
 	unsigned long		wait_table_size;
 	unsigned long		wait_table_bits;
 
-	ZONE_PADDING(_pad3_)
-
-	struct per_cpu_pageset	pageset[NR_CPUS];
-
 	/*
 	 * Discontig memory support fields.
 	 */
@@ -206,12 +206,13 @@
 	/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
 	unsigned long		zone_start_pfn;
 
+	unsigned long		spanned_pages;	/* total size, including holes */
+	unsigned long		present_pages;	/* amount of memory (excluding holes) */
+
 	/*
 	 * rarely used fields:
 	 */
 	char			*name;
-	unsigned long		spanned_pages;	/* total size, including holes */
-	unsigned long		present_pages;	/* amount of memory (excluding holes) */
 } ____cacheline_maxaligned_in_smp;
 
 
diff -Nru a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/module.h	2004-10-28 22:25:59 -07:00
@@ -44,6 +44,20 @@
 	char name[MODULE_NAME_LEN];
 };
 
+struct module;
+
+struct module_attribute {
+        struct attribute attr;
+        ssize_t (*show)(struct module *, char *);
+        ssize_t (*store)(struct module *, const char *, size_t count);
+};
+
+struct module_kobject
+{
+	struct kobject kobj;
+	struct module *mod;
+};
+
 /* These are either module local, or the kernel's dummy ones. */
 extern int init_module(void);
 extern void cleanup_module(void);
@@ -59,6 +73,8 @@
 		  struct exception_table_entry *finish);
 void sort_main_extable(void);
 
+extern struct subsystem module_subsys;
+
 #ifdef MODULE
 #define ___module_cat(a,b) __mod_ ## a ## b
 #define __module_cat(a,b) ___module_cat(a,b)
@@ -206,23 +222,6 @@
 	MODULE_STATE_GOING,
 };
 
-/* sysfs stuff */
-struct module_attribute
-{
-	struct attribute attr;
-	struct kernel_param *param;
-};
-
-struct module_kobject
-{
-	/* Everyone should have one of these. */
-	struct kobject kobj;
-
-	/* We always have refcnt, we may have others from module_param(). */
-	unsigned int num_attributes;
-	struct module_attribute attr[0];
-};
-
 /* Similar stuff for section attributes. */
 #define MODULE_SECT_NAME_LEN 32
 struct module_sect_attr
@@ -238,6 +237,7 @@
 	struct module_sect_attr attrs[0];
 };
 
+struct param_kobject;
 
 struct module
 {
@@ -251,6 +251,7 @@
 
 	/* Sysfs stuff. */
 	struct module_kobject *mkobj;
+	struct param_kobject *params_kobject;
 
 	/* Exported symbols */
 	const struct kernel_symbol *syms;
@@ -302,9 +303,6 @@
 
 	/* Destruction function. */
 	void (*exit)(void);
-
-	/* Fake kernel param for refcnt. */
-	struct kernel_param refcnt_param;
 #endif
 
 #ifdef CONFIG_KALLSYMS
@@ -560,13 +558,15 @@
 	char type[64-sizeof(void *)];
 	void *addr;
 };
+
+static inline void __deprecated MODULE_PARM_(void) { }
 #ifdef MODULE
 /* DEPRECATED: Do not use. */
 #define MODULE_PARM(var,type)						    \
 struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \
-{ __stringify(var), type };
+{ __stringify(var), type, &MODULE_PARM_ };
 #else
-#define MODULE_PARM(var,type)
+#define MODULE_PARM(var,type) static void __attribute__((__unused__)) *__parm_##var = &MODULE_PARM_;
 #endif
 
 #define __MODULE_STRING(x) __stringify(x)
diff -Nru a/include/linux/moduleparam.h b/include/linux/moduleparam.h
--- a/include/linux/moduleparam.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/moduleparam.h	2004-10-28 22:25:58 -07:00
@@ -152,4 +152,15 @@
 		void *elem, int elemsize,
 		int (*set)(const char *, struct kernel_param *kp),
 		int *num);
+
+/* for exporting parameters in /sys/parameters */
+
+struct module;
+
+extern int module_param_sysfs_setup(struct module *mod,
+				    struct kernel_param *kparam,
+				    unsigned int num_params);
+
+extern void module_param_sysfs_remove(struct module *mod);
+
 #endif /* _LINUX_MODULE_PARAMS_H */
diff -Nru a/include/linux/net.h b/include/linux/net.h
--- a/include/linux/net.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/net.h	2004-10-28 22:25:57 -07:00
@@ -176,7 +176,6 @@
 extern int	     sock_wake_async(struct socket *sk, int how, int band);
 extern int	     sock_register(struct net_proto_family *fam);
 extern int	     sock_unregister(int family);
-extern struct socket *sock_alloc(void);
 extern int	     sock_create(int family, int type, int proto,
 				 struct socket **res);
 extern int	     sock_create_kern(int family, int type, int proto,
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/netdevice.h	2004-10-28 22:25:59 -07:00
@@ -930,14 +930,12 @@
 /* Load a device via the kmod */
 extern void		dev_load(const char *name);
 extern void		dev_mcast_init(void);
-extern int		netdev_register_fc(struct net_device *dev, void (*stimul)(struct net_device *dev));
-extern void		netdev_unregister_fc(int bit);
 extern int		netdev_max_backlog;
 extern int		weight_p;
 extern unsigned long	netdev_fc_xoff;
 extern atomic_t netdev_dropping;
 extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
-extern int skb_checksum_help(struct sk_buff **pskb, int inward);
+extern int skb_checksum_help(struct sk_buff *skb, int inward);
 
 #ifdef CONFIG_SYSCTL
 extern char *net_sysctl_strdup(const char *s);
diff -Nru a/include/linux/netfilter.h b/include/linux/netfilter.h
--- a/include/linux/netfilter.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/netfilter.h	2004-10-28 22:25:58 -07:00
@@ -172,12 +172,6 @@
 			struct nf_info *info,
 			unsigned int verdict);
 
-extern inline struct ipt_target *
-ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern inline struct ip6t_target *
-ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern inline struct arpt_target *
-arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
 extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
 
 #ifdef CONFIG_NETFILTER_DEBUG
diff -Nru a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
--- a/include/linux/netfilter_ipv4/ip_tables.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/netfilter_ipv4/ip_tables.h	2004-10-28 22:25:58 -07:00
@@ -407,11 +407,6 @@
 	struct module *me;
 };
 
-extern struct ipt_target *
-ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern struct arpt_target *
-arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-
 extern int ipt_register_target(struct ipt_target *target);
 extern void ipt_unregister_target(struct ipt_target *target);
 
diff -Nru a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
--- a/include/linux/netfilter_ipv6/ip6_tables.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/netfilter_ipv6/ip6_tables.h	2004-10-28 22:25:59 -07:00
@@ -355,13 +355,15 @@
 
 	/* Return true or false: return FALSE and set *hotdrop = 1 to
            force immediate packet drop. */
+	/* Arguments changed since 2.6.9, as this must now handle
+	   non-linear skb, using skb_header_pointer and
+	   skb_ip_make_writable. */
 	int (*match)(const struct sk_buff *skb,
 		     const struct net_device *in,
 		     const struct net_device *out,
 		     const void *matchinfo,
 		     int offset,
-		     const void *hdr,
-		     u_int16_t datalen,
+		     unsigned int protoff,
 		     int *hotdrop);
 
 	/* Called when user tries to insert an entry of this type. */
@@ -386,11 +388,13 @@
 
 	const char name[IP6T_FUNCTION_MAXNAMELEN];
 
-	/* Returns verdict. */
+	/* Returns verdict. Argument order changed since 2.6.9, as this
+	   must now handle non-linear skbs, using skb_copy_bits and
+	   skb_ip_make_writable. */
 	unsigned int (*target)(struct sk_buff **pskb,
-			       unsigned int hooknum,
 			       const struct net_device *in,
 			       const struct net_device *out,
+			       unsigned int hooknum,
 			       const void *targinfo,
 			       void *userdata);
 
diff -Nru a/include/linux/pagevec.h b/include/linux/pagevec.h
--- a/include/linux/pagevec.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/pagevec.h	2004-10-28 22:25:59 -07:00
@@ -5,14 +5,15 @@
  * pages.  A pagevec is a multipage container which is used for that.
  */
 
-#define PAGEVEC_SIZE	15
+/* 14 pointers + two long's align the pagevec structure to a power of two */
+#define PAGEVEC_SIZE	14
 
 struct page;
 struct address_space;
 
 struct pagevec {
-	unsigned short nr;
-	unsigned short cold;
+	unsigned long nr;
+	unsigned long cold;
 	struct page *pages[PAGEVEC_SIZE];
 };
 
diff -Nru a/include/linux/parport.h b/include/linux/parport.h
--- a/include/linux/parport.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/parport.h	2004-10-28 22:25:59 -07:00
@@ -466,7 +466,6 @@
 				    int usec);
 
 /* For architectural drivers */
-extern void parport_ieee1284_wakeup (struct parport *port);
 extern size_t parport_ieee1284_write_compat (struct parport *,
 					     const void *, size_t, int);
 extern size_t parport_ieee1284_read_nibble (struct parport *,
@@ -500,20 +499,8 @@
 extern void parport_close (struct pardevice *dev);
 extern ssize_t parport_device_id (int devnum, char *buffer, size_t len);
 extern int parport_device_num (int parport, int mux, int daisy);
-extern int parport_device_coords (int devnum, int *parport, int *mux,
-				  int *daisy);
 extern void parport_daisy_deselect_all (struct parport *port);
 extern int parport_daisy_select (struct parport *port, int daisy, int mode);
-
-/* For finding devices based on their device ID.  Example usage:
-   int devnum = -1;
-   while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM, devnum)) != -1) {
-       struct pardevice *dev = parport_open (devnum, ...);
-       ...
-   }
-*/
-extern int parport_find_device (const char *mfg, const char *mdl, int from);
-extern int parport_find_class (parport_device_class cls, int from);
 
 /* Lowlevel drivers _can_ call this support function to handle irqs.  */
 static __inline__ void parport_generic_irq(int irq, struct parport *port,
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/pci.h	2004-10-28 22:25:58 -07:00
@@ -547,6 +547,7 @@
 #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list)
 #define pci_dev_b(n) list_entry(n, struct pci_dev, bus_list)
 #define	to_pci_dev(n) container_of(n, struct pci_dev, dev)
+#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
 
 /*
  *  For PCI devices, the region numbers are assigned this way:
diff -Nru a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
--- a/include/linux/pkt_cls.h	2004-10-28 22:25:56 -07:00
+++ b/include/linux/pkt_cls.h	2004-10-28 22:25:56 -07:00
@@ -1,6 +1,8 @@
 #ifndef __LINUX_PKT_CLS_H
 #define __LINUX_PKT_CLS_H
 
+#include <linux/pkt_sched.h>
+
 /* I think i could have done better macros ; for now this is stolen from
  * some arch/mips code - jhs
 */
diff -Nru a/include/linux/posix-timers.h b/include/linux/posix-timers.h
--- a/include/linux/posix-timers.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/posix-timers.h	2004-10-28 22:25:58 -07:00
@@ -33,8 +33,7 @@
 	struct k_clock_abs *abs_struct;
 	int (*clock_set) (struct timespec * tp);
 	int (*clock_get) (struct timespec * tp);
-	int (*timer_create) (int which_clock, struct sigevent __user *timer_event_spec,
-			timer_t __user * created_timer_id);
+	int (*timer_create) (struct k_itimer *timer);
 	int (*nsleep) (int which_clock, int flags,
 		       struct timespec * t);
 	int (*timer_set) (struct k_itimer * timr, int flags,
@@ -48,12 +47,12 @@
 void register_posix_clock(int clock_id, struct k_clock *new_clock);
 
 /* Error handlers for timer_create, nanosleep and settime */
-int do_posix_clock_notimer_create(int which_clock,
-                struct sigevent __user *time_event_spec,
-                timer_t __user *created_timer_id);
-
+int do_posix_clock_notimer_create(struct k_itimer *timer);
 int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);
 int do_posix_clock_nosettime(struct timespec *tp);
+
+/* function to call to trigger timer event */
+int posix_timer_event(struct k_itimer *timr, int si_private);
 
 struct now_struct {
 	unsigned long jiffies;
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/proc_fs.h	2004-10-28 22:25:59 -07:00
@@ -193,6 +193,7 @@
 
 #define proc_root_driver NULL
 #define proc_net NULL
+#define proc_bus NULL
 
 #define proc_net_fops_create(name, mode, fops)  ({ (void)(mode), NULL; })
 #define proc_net_create(name, mode, info)	({ (void)(mode), NULL; })
diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h
--- a/include/linux/raid/md.h	2004-10-28 22:25:56 -07:00
+++ b/include/linux/raid/md.h	2004-10-28 22:25:56 -07:00
@@ -60,7 +60,7 @@
  */
 #define MD_MAJOR_VERSION                0
 #define MD_MINOR_VERSION                90
-#define MD_PATCHLEVEL_VERSION           0
+#define MD_PATCHLEVEL_VERSION           1
 
 extern int register_md_personality (int p_num, mdk_personality_t *p);
 extern int unregister_md_personality (int p_num);
diff -Nru a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
--- a/include/linux/raid/md_p.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/raid/md_p.h	2004-10-28 22:25:57 -07:00
@@ -197,7 +197,7 @@
 
 	__u32	chunksize;	/* in 512byte sectors */
 	__u32	raid_disks;
-	__u8	pad1[128-92];	/* set to 0 when written */
+	__u8	pad1[128-96];	/* set to 0 when written */
 
 	/* constant this-device information - 64 bytes */
 	__u64	data_offset;	/* sector start of data, often 0 */
@@ -215,7 +215,7 @@
 	__u64	resync_offset;	/* data before this offset (from data_offset) known to be in sync */
 	__u32	sb_csum;	/* checksum upto devs[max_dev] */
 	__u32	max_dev;	/* size of devs[] array to consider */
-	__u8	pad3[64-40];	/* set to 0 when writing */
+	__u8	pad3[64-32];	/* set to 0 when writing */
 
 	/* device state information. Indexed by dev_number.
 	 * 2 bytes per device
diff -Nru a/include/linux/raid/multipath.h b/include/linux/raid/multipath.h
--- a/include/linux/raid/multipath.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/raid/multipath.h	2004-10-28 22:25:59 -07:00
@@ -13,6 +13,7 @@
 	int			raid_disks;
 	int			working_disks;
 	spinlock_t		device_lock;
+	struct list_head	retry_list;
 
 	mempool_t		*pool;
 };
@@ -36,6 +37,6 @@
 	struct bio		*master_bio;
 	struct bio		bio;
 	int			path;
-	struct multipath_bh	*next_mp; /* next for retry */
+	struct list_head	retry_list;
 };
 #endif
diff -Nru a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
--- a/include/linux/raid/raid1.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/raid/raid1.h	2004-10-28 22:25:58 -07:00
@@ -35,6 +35,7 @@
 	sector_t		next_seq_sect;
 	spinlock_t		device_lock;
 
+	struct list_head	retry_list;
 	/* for use when syncing mirrors: */
 
 	spinlock_t		resync_lock;
diff -Nru a/include/linux/rcupdate.h b/include/linux/rcupdate.h
--- a/include/linux/rcupdate.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/rcupdate.h	2004-10-28 22:25:57 -07:00
@@ -238,6 +238,24 @@
 				(_________p1); \
 				})
 
+/**
+ * rcu_assign_pointer - assign (publicize) a pointer to a newly
+ * initialized structure that will be dereferenced by RCU read-side
+ * critical sections.  Returns the value assigned.
+ *
+ * Inserts memory barriers on architectures that require them
+ * (pretty much all of them other than x86), and also prevents
+ * the compiler from reordering the code that initializes the
+ * structure after the pointer assignment.  More importantly, this
+ * call documents which pointers will be dereferenced by RCU read-side
+ * code.
+ */
+
+#define rcu_assign_pointer(p, v)	({ \
+						smp_wmb(); \
+						(p) = (v); \
+					})
+
 extern void rcu_init(void);
 extern void rcu_check_callbacks(int cpu, int user);
 extern void rcu_restart_cpu(int cpu);
diff -Nru a/include/linux/rmap.h b/include/linux/rmap.h
--- a/include/linux/rmap.h	2004-10-28 22:25:56 -07:00
+++ b/include/linux/rmap.h	2004-10-28 22:25:56 -07:00
@@ -7,6 +7,7 @@
 #include <linux/config.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/spinlock.h>
 
 /*
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/sched.h	2004-10-28 22:25:57 -07:00
@@ -216,7 +216,7 @@
 	atomic_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
 	int map_count;				/* number of VMAs */
 	struct rw_semaphore mmap_sem;
-	spinlock_t page_table_lock;		/* Protects task page tables and mm->rss */
+	spinlock_t page_table_lock;		/* Protects page tables, mm->rss, mm->anon_rss */
 
 	struct list_head mmlist;		/* List of maybe swapped mm's.  These are globally strung
 						 * together off init_mm.mmlist, and are protected
@@ -226,7 +226,7 @@
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
-	unsigned long rss, total_vm, locked_vm, shared_vm;
+	unsigned long rss, anon_rss, total_vm, locked_vm, shared_vm;
 	unsigned long exec_vm, stack_vm, reserved_vm, def_flags, nr_ptes;
 
 	unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
@@ -267,6 +267,7 @@
  */
 struct signal_struct {
 	atomic_t		count;
+	atomic_t		live;
 
 	/* current thread group signal load-balancing target: */
 	task_t			*curr_target;
@@ -771,8 +772,6 @@
 
 #include <asm/current.h>
 
-extern unsigned long itimer_ticks;
-extern unsigned long itimer_next;
 extern void do_timer(struct pt_regs *);
 
 extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state));
diff -Nru a/include/linux/sctp.h b/include/linux/sctp.h
--- a/include/linux/sctp.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/sctp.h	2004-10-28 22:25:58 -07:00
@@ -281,7 +281,11 @@
 	sctp_paramhdr_t param_hdr;
 } __attribute__((packed)) sctp_ecn_capable_param_t;
 
-
+/* ADDIP Section 3.2.6 Adaption Layer Indication */
+typedef struct sctp_adaption_ind_param {
+	struct sctp_paramhdr param_hdr;
+	__u32 adaption_ind;
+} __attribute__((packed)) sctp_adaption_ind_param_t;
 
 /* RFC 2960.  Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2):
  *   The INIT ACK chunk is used to acknowledge the initiation of an SCTP
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/security.h	2004-10-28 22:25:58 -07:00
@@ -30,8 +30,6 @@
 #include <linux/shm.h>
 #include <linux/msg.h>
 #include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
 
 struct ctl_table;
 
@@ -55,18 +53,14 @@
 extern int cap_syslog (int type);
 extern int cap_vm_enough_memory (long pages);
 
-static inline int cap_netlink_send (struct sock *sk, struct sk_buff *skb)
-{
-	NETLINK_CB (skb).eff_cap = current->cap_effective;
-	return 0;
-}
+struct msghdr;
+struct sk_buff;
+struct sock;
+struct sockaddr;
+struct socket;
 
-static inline int cap_netlink_recv (struct sk_buff *skb)
-{
-	if (!cap_raised (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN))
-		return -EPERM;
-	return 0;
-}
+extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
+extern int cap_netlink_recv(struct sk_buff *skb);
 
 /*
  * Values used in the task_security_ops calls
@@ -488,16 +482,15 @@
  *	@file contains the file structure to update.
  *	Return 0 on success.
  * @file_send_sigiotask:
- *	Check permission for the file owner @fown to send SIGIO to the process
- *	@tsk.  Note that this hook is always called from interrupt.  Note that
- *	the fown_struct, @fown, is never outside the context of a struct file,
- *	so the file structure (and associated security information) can always
- *	be obtained:
+ *	Check permission for the file owner @fown to send SIGIO or SIGURG to the
+ *	process @tsk.  Note that this hook is sometimes called from interrupt.
+ *	Note that the fown_struct, @fown, is never outside the context of a
+ *	struct file, so the file structure (and associated security information)
+ *	can always be obtained:
  *		(struct file *)((long)fown - offsetof(struct file,f_owner));
  * 	@tsk contains the structure of task receiving signal.
  *	@fown contains the file owner information.
- *	@fd contains the file descriptor.
- *	@reason contains the operational flags.
+ *	@sig is the signal that will be sent.  When 0, kernel sends SIGIO.
  *	Return 0 if permission is granted.
  * @file_receive:
  *	This hook allows security modules to control the ability of a process
@@ -1135,8 +1128,7 @@
 			   unsigned long arg);
 	int (*file_set_fowner) (struct file * file);
 	int (*file_send_sigiotask) (struct task_struct * tsk,
-				    struct fown_struct * fown,
-				    int fd, int reason);
+				    struct fown_struct * fown, int sig);
 	int (*file_receive) (struct file * file);
 
 	int (*task_create) (unsigned long clone_flags);
@@ -1657,9 +1649,9 @@
 
 static inline int security_file_send_sigiotask (struct task_struct *tsk,
 						struct fown_struct *fown,
-						int fd, int reason)
+						int sig)
 {
-	return security_ops->file_send_sigiotask (tsk, fown, fd, reason);
+	return security_ops->file_send_sigiotask (tsk, fown, sig);
 }
 
 static inline int security_file_receive (struct file *file)
@@ -2299,7 +2291,7 @@
 
 static inline int security_file_send_sigiotask (struct task_struct *tsk,
 						struct fown_struct *fown,
-						int fd, int reason)
+						int sig)
 {
 	return 0;
 }
@@ -2520,11 +2512,6 @@
 	return -EINVAL;
 }
 
-/*
- * The netlink capability defaults need to be used inline by default
- * (rather than hooking into the capability module) to reduce overhead
- * in the networking code.
- */
 static inline int security_netlink_send (struct sock *sk, struct sk_buff *skb)
 {
 	return cap_netlink_send (sk, skb);
diff -Nru a/include/linux/smp_lock.h b/include/linux/smp_lock.h
--- a/include/linux/smp_lock.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/smp_lock.h	2004-10-28 22:25:59 -07:00
@@ -5,62 +5,50 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-
-extern spinlock_t kernel_flag;
+#ifdef CONFIG_LOCK_KERNEL
 
 #define kernel_locked()		(current->lock_depth >= 0)
 
-#define get_kernel_lock()	spin_lock(&kernel_flag)
-#define put_kernel_lock()	spin_unlock(&kernel_flag)
+extern int __lockfunc get_kernel_lock(void);
+extern void __lockfunc put_kernel_lock(void);
 
 /*
- * Release global kernel lock.
+ * Release/re-acquire global kernel lock for the scheduler
  */
-static inline void release_kernel_lock(struct task_struct *task)
-{
-	if (unlikely(task->lock_depth >= 0))
-		put_kernel_lock();
-}
+#define release_kernel_lock(tsk) do { 		\
+	if (unlikely((tsk)->lock_depth >= 0))	\
+		put_kernel_lock();		\
+} while (0)
 
 /*
- * Re-acquire the kernel lock
+ * Non-SMP kernels will never block on the kernel lock,
+ * so we are better off returning a constant zero from
+ * reacquire_kernel_lock() so that the compiler can see
+ * it at compile-time.
  */
-static inline void reacquire_kernel_lock(struct task_struct *task)
-{
-	if (unlikely(task->lock_depth >= 0))
-		get_kernel_lock();
-}
+#ifdef CONFIG_SMP
+#define return_value_on_smp return
+#else
+#define return_value_on_smp
+#endif
 
-/*
- * Getting the big kernel lock.
- *
- * This cannot happen asynchronously,
- * so we only need to worry about other
- * CPU's.
- */
-static inline void lock_kernel(void)
+static inline int reacquire_kernel_lock(struct task_struct *task)
 {
-	int depth = current->lock_depth+1;
-	if (likely(!depth))
-		get_kernel_lock();
-	current->lock_depth = depth;
+	if (unlikely(task->lock_depth >= 0))
+		return_value_on_smp get_kernel_lock();
+	return 0;
 }
 
-static inline void unlock_kernel(void)
-{
-	BUG_ON(current->lock_depth < 0);
-	if (likely(--current->lock_depth < 0))
-		put_kernel_lock();
-}
+extern void __lockfunc lock_kernel(void)	__acquires(kernel_lock);
+extern void __lockfunc unlock_kernel(void)	__releases(kernel_lock);
 
 #else
 
 #define lock_kernel()				do { } while(0)
 #define unlock_kernel()				do { } while(0)
 #define release_kernel_lock(task)		do { } while(0)
-#define reacquire_kernel_lock(task)		do { } while(0)
+#define reacquire_kernel_lock(task)		0
 #define kernel_locked()				1
 
-#endif /* CONFIG_SMP || CONFIG_PREEMPT */
+#endif /* CONFIG_LOCK_KERNEL */
 #endif /* __LINUX_SMPLOCK_H */
diff -Nru a/include/linux/sonypi.h b/include/linux/sonypi.h
--- a/include/linux/sonypi.h	2004-10-28 22:25:57 -07:00
+++ b/include/linux/sonypi.h	2004-10-28 22:25:57 -07:00
@@ -1,7 +1,7 @@
-/* 
+/*
  * Sony Programmable I/O Control Device driver for VAIO
  *
- * Copyright (C) 2001-2003 Stelian Pop <stelian@popies.net>
+ * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
  *
  * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
  *
@@ -14,24 +14,24 @@
  * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
  *
  * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
- * 
+ *
  * 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.
  *
  */
 
-#ifndef _SONYPI_H_ 
+#ifndef _SONYPI_H_
 #define _SONYPI_H_
 
 #include <linux/types.h>
@@ -96,6 +96,7 @@
 #define SONYPI_EVENT_ANYBUTTON_RELEASED		56
 #define SONYPI_EVENT_BATTERY_INSERT		57
 #define SONYPI_EVENT_BATTERY_REMOVE		58
+#define SONYPI_EVENT_FNKEY_RELEASED		59
 
 /* get/set brightness */
 #define SONYPI_IOCGBRT		_IOR('v', 0, __u8)
@@ -143,6 +144,6 @@
 
 u8 sonypi_camera_command(int command, u8 value);
 
-#endif /* __KERNEL__ */
+#endif				/* __KERNEL__ */
 
-#endif /* _SONYPI_H_ */
+#endif				/* _SONYPI_H_ */
diff -Nru a/include/linux/spinlock.h b/include/linux/spinlock.h
--- a/include/linux/spinlock.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/spinlock.h	2004-10-28 22:25:58 -07:00
@@ -32,43 +32,49 @@
 #define LOCK_SECTION_END                        \
         ".previous\n\t"
 
+#define __lockfunc fastcall __attribute__((section(".spinlock.text")))
+
 /*
  * If CONFIG_SMP is set, pull in the _raw_* definitions
  */
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
 
-#define __lockfunc fastcall __attribute__((section(".spinlock.text")))
-
 int __lockfunc _spin_trylock(spinlock_t *lock);
 int __lockfunc _write_trylock(rwlock_t *lock);
-void __lockfunc _spin_lock(spinlock_t *lock);
-void __lockfunc _write_lock(rwlock_t *lock);
-void __lockfunc _spin_lock(spinlock_t *lock);
-void __lockfunc _read_lock(rwlock_t *lock);
-void __lockfunc _spin_unlock(spinlock_t *lock);
-void __lockfunc _write_unlock(rwlock_t *lock);
-void __lockfunc _read_unlock(rwlock_t *lock);
-unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock);
-unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock);
-unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock);
-void __lockfunc _spin_lock_irq(spinlock_t *lock);
-void __lockfunc _spin_lock_bh(spinlock_t *lock);
-void __lockfunc _read_lock_irq(rwlock_t *lock);
-void __lockfunc _read_lock_bh(rwlock_t *lock);
-void __lockfunc _write_lock_irq(rwlock_t *lock);
-void __lockfunc _write_lock_bh(rwlock_t *lock);
-void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
-void __lockfunc _spin_unlock_irq(spinlock_t *lock);
-void __lockfunc _spin_unlock_bh(spinlock_t *lock);
-void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
-void __lockfunc _read_unlock_irq(rwlock_t *lock);
-void __lockfunc _read_unlock_bh(rwlock_t *lock);
-void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
-void __lockfunc _write_unlock_irq(rwlock_t *lock);
-void __lockfunc _write_unlock_bh(rwlock_t *lock);
+
+void __lockfunc _spin_lock(spinlock_t *lock)	__acquires(spinlock_t);
+void __lockfunc _read_lock(rwlock_t *lock)	__acquires(rwlock_t);
+void __lockfunc _write_lock(rwlock_t *lock)	__acquires(rwlock_t);
+
+void __lockfunc _spin_unlock(spinlock_t *lock)	__releases(spinlock_t);
+void __lockfunc _read_unlock(rwlock_t *lock)	__releases(rwlock_t);
+void __lockfunc _write_unlock(rwlock_t *lock)	__releases(rwlock_t);
+
+unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)	__acquires(spinlock_t);
+unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock)	__acquires(rwlock_t);
+unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock)	__acquires(rwlock_t);
+
+void __lockfunc _spin_lock_irq(spinlock_t *lock)	__acquires(spinlock_t);
+void __lockfunc _spin_lock_bh(spinlock_t *lock)		__acquires(spinlock_t);
+void __lockfunc _read_lock_irq(rwlock_t *lock)		__acquires(rwlock_t);
+void __lockfunc _read_lock_bh(rwlock_t *lock)		__acquires(rwlock_t);
+void __lockfunc _write_lock_irq(rwlock_t *lock)		__acquires(rwlock_t);
+void __lockfunc _write_lock_bh(rwlock_t *lock)		__acquires(rwlock_t);
+
+void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)	__releases(spinlock_t);
+void __lockfunc _spin_unlock_irq(spinlock_t *lock)				__releases(spinlock_t);
+void __lockfunc _spin_unlock_bh(spinlock_t *lock)				__releases(spinlock_t);
+void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)	__releases(rwlock_t);
+void __lockfunc _read_unlock_irq(rwlock_t *lock)				__releases(rwlock_t);
+void __lockfunc _read_unlock_bh(rwlock_t *lock)					__releases(rwlock_t);
+void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)	__releases(rwlock_t);
+void __lockfunc _write_unlock_irq(rwlock_t *lock)				__releases(rwlock_t);
+void __lockfunc _write_unlock_bh(rwlock_t *lock)				__releases(rwlock_t);
+
 int __lockfunc _spin_trylock_bh(spinlock_t *lock);
 int in_lock_functions(unsigned long addr);
+
 #else
 
 #define in_lock_functions(ADDR) 0
diff -Nru a/include/linux/syscalls.h b/include/linux/syscalls.h
--- a/include/linux/syscalls.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/syscalls.h	2004-10-28 22:25:59 -07:00
@@ -490,7 +490,6 @@
 				void __user *res);
 asmlinkage long sys_syslog(int type, char __user *buf, int len);
 asmlinkage long sys_uselib(const char __user *library);
-asmlinkage long sys_setaltroot(const char __user *altroot);
 asmlinkage long sys_ni_syscall(void);
 
 asmlinkage long sys_add_key(const char __user *_type,
diff -Nru a/include/linux/tc_act/tc_pedit.h b/include/linux/tc_act/tc_pedit.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/tc_act/tc_pedit.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,36 @@
+#ifndef __LINUX_TC_PED_H
+#define __LINUX_TC_PED_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_PEDIT 7
+
+enum
+{
+	TCA_PEDIT_UNSPEC,
+	TCA_PEDIT_TM,
+	TCA_PEDIT_PARMS,
+	__TCA_PEDIT_MAX
+};
+#define TCA_PEDIT_MAX (__TCA_PEDIT_MAX - 1)
+                                                                                
+struct tc_pedit_key
+{
+	__u32           mask;  /* AND */
+	__u32           val;   /*XOR */
+	__u32           off;  /*offset */
+	__u32           at;
+	__u32           offmask;
+	__u32           shift;
+};
+                                                                                
+struct tc_pedit_sel
+{
+	tc_gen;
+	unsigned char           nkeys;
+	unsigned char           flags;
+	struct tc_pedit_key     keys[0];
+};
+#define tc_pedit tc_pedit_sel
+
+#endif
diff -Nru a/include/linux/ticable.h b/include/linux/ticable.h
--- a/include/linux/ticable.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/ticable.h	2004-10-28 22:25:59 -07:00
@@ -38,5 +38,7 @@
 #define IOCTL_TIUSB_TIMEOUT        _IOW('N', 0x20, int) /* set timeout */
 #define IOCTL_TIUSB_RESET_DEVICE   _IOW('N', 0x21, int) /* reset device */
 #define IOCTL_TIUSB_RESET_PIPES    _IOW('N', 0x22, int) /* reset both pipes*/
+#define IOCTL_TIUSB_GET_MAXPS      _IOR('N', 0x23, int) /* max packet size */
+#define IOCTL_TIUSB_GET_DEVID      _IOR('N', 0x24, int) /* get device type */
 
 #endif /* TICABLE_H */
diff -Nru a/include/linux/videodev.h b/include/linux/videodev.h
--- a/include/linux/videodev.h	2004-10-28 22:25:59 -07:00
+++ b/include/linux/videodev.h	2004-10-28 22:25:59 -07:00
@@ -133,7 +133,7 @@
 #define VIDEO_VC_AUDIO		2	/* Channel has audio */
 	__u16  type;
 #define VIDEO_TYPE_TV		1
-#define VIDEO_TYPE_CAMERA	2	
+#define VIDEO_TYPE_CAMERA	2
 	__u16 norm;			/* Norm set by channel */
 };
 
@@ -172,7 +172,7 @@
 #define VIDEO_PALETTE_HI240	2	/* High 240 cube (BT848) */
 #define VIDEO_PALETTE_RGB565	3	/* 565 16 bit RGB */
 #define VIDEO_PALETTE_RGB24	4	/* 24bit RGB */
-#define VIDEO_PALETTE_RGB32	5	/* 32bit RGB */	
+#define VIDEO_PALETTE_RGB32	5	/* 32bit RGB */
 #define VIDEO_PALETTE_RGB555	6	/* 555 15bit RGB */
 #define VIDEO_PALETTE_YUV422	7	/* YUV422 capture */
 #define VIDEO_PALETTE_YUYV	8
@@ -198,7 +198,7 @@
 #define VIDEO_AUDIO_MUTABLE	2
 #define VIDEO_AUDIO_VOLUME	4
 #define VIDEO_AUDIO_BASS	8
-#define VIDEO_AUDIO_TREBLE	16	
+#define VIDEO_AUDIO_TREBLE	16
 #define VIDEO_AUDIO_BALANCE	32
 	char    name[16];
 #define VIDEO_SOUND_MONO	1
@@ -272,11 +272,11 @@
 	int	frames;		/* Frames */
 	int	offsets[VIDEO_MAX_FRAME];
 };
-	
+
 
 #define 	VIDEO_NO_UNIT	(-1)
 
-	
+
 struct video_unit
 {
 	int 	video;		/* Video minor */
@@ -373,7 +373,7 @@
 	/* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
 #define VID_PLAY_GENLOCK		1
 	/* p1: 0 = OFF, 1 = ON */
-	/* p2: GENLOCK FINE DELAY value */ 
+	/* p2: GENLOCK FINE DELAY value */
 #define VID_PLAY_NORMAL			2
 #define VID_PLAY_PAUSE			3
 #define VID_PLAY_SINGLE_FRAME		4
@@ -421,7 +421,7 @@
 #define VID_HARDWARE_CPIA	24
 #define VID_HARDWARE_ZR36120	25	/* Zoran ZR36120/ZR36125 */
 #define VID_HARDWARE_ZR36067	26	/* Zoran ZR36067/36060 */
-#define VID_HARDWARE_OV511	27	
+#define VID_HARDWARE_OV511	27
 #define VID_HARDWARE_ZR356700	28	/* Zoran 36700 series */
 #define VID_HARDWARE_W9966	29
 #define VID_HARDWARE_SE401	30	/* SE401 USB webcams */
diff -Nru a/include/linux/videodev2.h b/include/linux/videodev2.h
--- a/include/linux/videodev2.h	2004-10-28 22:25:58 -07:00
+++ b/include/linux/videodev2.h	2004-10-28 22:25:58 -07:00
@@ -95,20 +95,20 @@
 
 	/* HD and modern captures. */
 	V4L2_COLORSPACE_REC709        = 3,
-	
+
 	/* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
 	V4L2_COLORSPACE_BT878         = 4,
-	
+
 	/* These should be useful.  Assume 601 extents. */
 	V4L2_COLORSPACE_470_SYSTEM_M  = 5,
 	V4L2_COLORSPACE_470_SYSTEM_BG = 6,
-	
+
 	/* I know there will be cameras that send this.  So, this is
 	 * unspecified chromaticities and full 0-255 on each of the
 	 * Y'CbCr components
 	 */
 	V4L2_COLORSPACE_JPEG          = 7,
-	
+
 	/* For RGB colourspaces, this is probably a good start. */
 	V4L2_COLORSPACE_SRGB          = 8,
 };
@@ -334,10 +334,10 @@
 				 * must be 0..15 */
 	int  APP_len;           /* Length of data in JPEG APPn segment */
 	char APP_data[60];      /* Data in the JPEG APPn segment. */
-	
+
 	int  COM_len;           /* Length of data in JPEG COM segment */
 	char COM_data[60];      /* Data in JPEG COM segment */
-	
+
 	__u32 jpeg_markers;     /* Which markers should go into the JPEG
 				 * output. Unless you exactly know what
 				 * you do, leave them untouched.
@@ -347,7 +347,7 @@
 				 * The presence of the APP and COM marker
 				 * is influenced by APP_len and COM_len
 				 * ONLY, not by this property! */
-	
+
 #define V4L2_JPEG_MARKER_DHT (1<<3)    /* Define Huffman Tables */
 #define V4L2_JPEG_MARKER_DQT (1<<4)    /* Define Quantization Tables */
 #define V4L2_JPEG_MARKER_DRI (1<<5)    /* Define Restart Interval */
@@ -470,7 +470,7 @@
  */
 
 struct v4l2_cropcap {
-	enum v4l2_buf_type      type;	
+	enum v4l2_buf_type      type;
         struct v4l2_rect        bounds;
         struct v4l2_rect        defrect;
         struct v4l2_fract       pixelaspect;
diff -Nru a/include/media/audiochip.h b/include/media/audiochip.h
--- a/include/media/audiochip.h	2004-10-28 22:25:57 -07:00
+++ b/include/media/audiochip.h	2004-10-28 22:25:57 -07:00
@@ -13,7 +13,7 @@
 #define AUDIO_RADIO        0x01
 #define AUDIO_EXTERN       0x02
 #define AUDIO_INTERN       0x03
-#define AUDIO_OFF          0x04 
+#define AUDIO_OFF          0x04
 #define AUDIO_ON           0x05
 #define AUDIO_EXTERN_1     AUDIO_EXTERN
 #define AUDIO_EXTERN_2     0x06
diff -Nru a/include/media/ir-common.h b/include/media/ir-common.h
--- a/include/media/ir-common.h	2004-10-28 22:25:59 -07:00
+++ b/include/media/ir-common.h	2004-10-28 22:25:59 -07:00
@@ -1,4 +1,6 @@
 /*
+ * $Id: ir-common.h,v 1.6 2004/09/15 16:15:24 kraxel Exp $
+ *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
  *
diff -Nru a/include/media/tuner.h b/include/media/tuner.h
--- a/include/media/tuner.h	2004-10-28 22:25:58 -07:00
+++ b/include/media/tuner.h	2004-10-28 22:25:58 -07:00
@@ -1,5 +1,5 @@
 
-/* 
+/*
     tuner.h - definition for different tuners
 
     Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de)
diff -Nru a/include/media/video-buf.h b/include/media/video-buf.h
--- a/include/media/video-buf.h	2004-10-28 22:25:58 -07:00
+++ b/include/media/video-buf.h	2004-10-28 22:25:58 -07:00
@@ -1,5 +1,5 @@
 /*
- * $Id: video-buf.h,v 1.7 2004/10/11 14:53:13 kraxel Exp $
+ * $Id: video-buf.h,v 1.8 2004/10/13 10:39:00 kraxel Exp $
  *
  * generic helper functions for video4linux capture buffers, to handle
  * memory management and PCI DMA.  Right now bttv + saa7134 use it.
@@ -9,7 +9,7 @@
  * into PAGE_SIZE chunks).  They also assume the driver does not need
  * to touch the video data (thus it is probably not useful for USB as
  * data often must be uncompressed by the drivers).
- * 
+ *
  * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -102,7 +102,7 @@
  * functions, additionally some commonly used fields for v4l buffers
  * (width, height, lists, waitqueue) are in there.  That struct should
  * be used as first element in the drivers buffer struct.
- * 
+ *
  * about the mmap helpers (videobuf_mmap_*):
  *
  * The mmaper function allows to map any subset of contingous buffers.
diff -Nru a/include/net/act_api.h b/include/net/act_api.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/net/act_api.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,122 @@
+#ifndef __NET_ACT_API_H
+#define __NET_ACT_API_H
+
+/*
+ * Public police action API for classifiers/qdiscs
+ */
+
+#include <net/sch_generic.h>
+#include <net/pkt_sched.h>
+
+struct tcf_police
+{
+	struct tcf_police *next;
+	int		refcnt;
+#ifdef CONFIG_NET_CLS_ACT
+	int		bindcnt;
+#endif
+	u32		index;
+	int		action;
+	int		result;
+	u32		ewma_rate;
+	u32		burst;
+	u32		mtu;
+	u32		toks;
+	u32		ptoks;
+	psched_time_t	t_c;
+	spinlock_t	lock;
+	struct qdisc_rate_table *R_tab;
+	struct qdisc_rate_table *P_tab;
+
+	struct tc_stats	stats;
+	spinlock_t	*stats_lock;
+};
+
+#ifdef CONFIG_NET_CLS_ACT
+
+#define ACT_P_CREATED 1
+#define ACT_P_DELETED 1
+#define tca_gen(name) \
+struct tcf_##name *next; \
+	u32 index; \
+	int refcnt; \
+	int bindcnt; \
+	u32 capab; \
+	int action; \
+	struct tcf_t tm; \
+	struct tc_stats stats; \
+	spinlock_t *stats_lock; \
+	spinlock_t lock
+
+
+struct tc_action
+{
+	void *priv;
+	struct tc_action_ops *ops;
+	__u32   type;   /* for backward compat(TCA_OLD_COMPAT) */
+	__u32   order; 
+	struct tc_action *next;
+};
+
+#define TCA_CAP_NONE 0
+struct tc_action_ops
+{
+	struct tc_action_ops *next;
+	char    kind[IFNAMSIZ];
+	__u32   type; /* TBD to match kind */
+	__u32 	capab;  /* capabilities includes 4 bit version */
+	struct module		*owner;
+	int     (*act)(struct sk_buff **, struct tc_action *);
+	int     (*get_stats)(struct sk_buff *, struct tc_action *);
+	int     (*dump)(struct sk_buff *, struct tc_action *,int , int);
+	int     (*cleanup)(struct tc_action *, int bind);
+	int     (*lookup)(struct tc_action *, u32 );
+	int     (*init)(struct rtattr *,struct rtattr *,struct tc_action *, int , int );
+	int     (*walk)(struct sk_buff *, struct netlink_callback *, int , struct tc_action *);
+};
+
+extern int tcf_register_action(struct tc_action_ops *a);
+extern int tcf_unregister_action(struct tc_action_ops *a);
+extern void tcf_action_destroy(struct tc_action *a, int bind);
+extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res);
+extern int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
+extern int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
+extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
+extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *);
+extern int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,struct tc_action *,int , int );
+extern int tcf_act_police_dump(struct sk_buff *, struct tc_action *, int, int);
+extern int tcf_act_police(struct sk_buff **skb, struct tc_action *a);
+#endif /* CONFIG_NET_CLS_ACT */
+
+extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
+extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st, spinlock_t *lock);
+extern void tcf_police_destroy(struct tcf_police *p);
+extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
+extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
+
+static inline int
+tcf_police_release(struct tcf_police *p, int bind)
+{
+	int ret = 0;
+#ifdef CONFIG_NET_CLS_ACT
+	if (p) {
+		if (bind) {
+			 p->bindcnt--;
+		}
+		p->refcnt--;
+		if (p->refcnt <= 0 && !p->bindcnt) {
+			tcf_police_destroy(p);
+			ret = 1;
+		}
+	}
+#else
+	if (p && --p->refcnt == 0)
+		tcf_police_destroy(p);
+
+#endif /* CONFIG_NET_CLS_ACT */
+	return ret;
+}
+
+#endif
diff -Nru a/include/net/addrconf.h b/include/net/addrconf.h
--- a/include/net/addrconf.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/addrconf.h	2004-10-28 22:25:59 -07:00
@@ -67,8 +67,7 @@
 					       struct in6_addr *saddr);
 extern int			ipv6_dev_get_saddr(struct net_device *dev, 
 					       struct in6_addr *daddr,
-					       struct in6_addr *saddr,
-					       int onlink);
+					       struct in6_addr *saddr);
 extern int			ipv6_get_lladdr(struct net_device *dev, struct in6_addr *);
 extern int			ipv6_rcv_saddr_equal(const struct sock *sk, 
 						      const struct sock *sk2);
diff -Nru a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
--- a/include/net/bluetooth/hci.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/bluetooth/hci.h	2004-10-28 22:25:59 -07:00
@@ -108,7 +108,7 @@
 #define HCI_ACLDATA_PKT		0x02
 #define HCI_SCODATA_PKT		0x03
 #define HCI_EVENT_PKT		0x04
-#define HCI_UNKNOWN_PKT		0xff
+#define HCI_VENDOR_PKT		0xff
 
 /* HCI Packet types */
 #define HCI_DM1		0x0008
diff -Nru a/include/net/dst.h b/include/net/dst.h
--- a/include/net/dst.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/dst.h	2004-10-28 22:25:59 -07:00
@@ -67,7 +67,7 @@
 	struct xfrm_state	*xfrm;
 
 	int			(*input)(struct sk_buff*);
-	int			(*output)(struct sk_buff**);
+	int			(*output)(struct sk_buff*);
 
 #ifdef CONFIG_NET_CLS_ROUTE
 	__u32			tclassid;
@@ -222,7 +222,7 @@
 	int err;
 
 	for (;;) {
-		err = skb->dst->output(&skb);
+		err = skb->dst->output(skb);
 
 		if (likely(err == 0))
 			return err;
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h	2004-10-28 22:25:58 -07:00
+++ b/include/net/ip.h	2004-10-28 22:25:58 -07:00
@@ -89,8 +89,8 @@
 			       struct packet_type *pt);
 extern int		ip_local_deliver(struct sk_buff *skb);
 extern int		ip_mr_input(struct sk_buff *skb);
-extern int		ip_output(struct sk_buff **pskb);
-extern int		ip_mc_output(struct sk_buff **pskb);
+extern int		ip_output(struct sk_buff *skb);
+extern int		ip_mc_output(struct sk_buff *skb);
 extern int		ip_fragment(struct sk_buff *skb, int (*out)(struct sk_buff*));
 extern int		ip_do_nat(struct sk_buff *skb);
 extern void		ip_send_check(struct iphdr *ip);
diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h
--- a/include/net/ip6_route.h	2004-10-28 22:25:57 -07:00
+++ b/include/net/ip6_route.h	2004-10-28 22:25:57 -07:00
@@ -70,7 +70,7 @@
 extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
 					 struct neighbour *neigh,
 					 struct in6_addr *addr,
-					 int (*output)(struct sk_buff **));
+					 int (*output)(struct sk_buff *));
 extern int ndisc_dst_gc(int *more);
 extern void fib6_force_start_gc(void);
 
@@ -87,7 +87,7 @@
 extern struct rt6_info *	rt6_add_dflt_router(struct in6_addr *gwaddr,
 						    struct net_device *dev);
 
-extern void			rt6_purge_dflt_routers(int lst_resort);
+extern void			rt6_purge_dflt_routers(void);
 
 extern void			rt6_reset_dflt_pointer(struct rt6_info *rt);
 
diff -Nru a/include/net/ipv6.h b/include/net/ipv6.h
--- a/include/net/ipv6.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/ipv6.h	2004-10-28 22:25:59 -07:00
@@ -355,7 +355,7 @@
  *	skb processing functions
  */
 
-extern int			ip6_output(struct sk_buff **pskb);
+extern int			ip6_output(struct sk_buff *skb);
 extern int			ip6_forward(struct sk_buff *skb);
 extern int			ip6_input(struct sk_buff *skb);
 extern int			ip6_mc_input(struct sk_buff *skb);
diff -Nru a/include/net/ndisc.h b/include/net/ndisc.h
--- a/include/net/ndisc.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/ndisc.h	2004-10-28 22:25:59 -07:00
@@ -45,6 +45,11 @@
 	__u8		opt[0];
 };
 
+struct rs_msg {
+	struct icmp6hdr	icmph;
+	__u8		opt[0];
+};
+
 struct ra_msg {
         struct icmp6hdr		icmph;
 	__u32			reachable_time;
diff -Nru a/include/net/pkt_cls.h b/include/net/pkt_cls.h
--- a/include/net/pkt_cls.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/pkt_cls.h	2004-10-28 22:25:59 -07:00
@@ -1,36 +1,11 @@
 #ifndef __NET_PKT_CLS_H
 #define __NET_PKT_CLS_H
 
-
 #include <linux/pkt_cls.h>
-
-struct rtattr;
-struct tcmsg;
+#include <net/sch_generic.h>
 
 /* Basic packet classifier frontend definitions. */
 
-struct tcf_result
-{
-	unsigned long	class;
-	u32		classid;
-};
-
-struct tcf_proto
-{
-	/* Fast access part */
-	struct tcf_proto	*next;
-	void			*root;
-	int			(*classify)(struct sk_buff*, struct tcf_proto*, struct tcf_result *);
-	u32			protocol;
-
-	/* All the rest */
-	u32			prio;
-	u32			classid;
-	struct Qdisc		*q;
-	void			*data;
-	struct tcf_proto_ops	*ops;
-};
-
 struct tcf_walker
 {
 	int	stop;
@@ -39,86 +14,31 @@
 	int	(*fn)(struct tcf_proto *, unsigned long node, struct tcf_walker *);
 };
 
-struct module;
-
-struct tcf_proto_ops
-{
-	struct tcf_proto_ops	*next;
-	char			kind[IFNAMSIZ];
-
-	int			(*classify)(struct sk_buff*, struct tcf_proto*, struct tcf_result *);
-	int			(*init)(struct tcf_proto*);
-	void			(*destroy)(struct tcf_proto*);
-
-	unsigned long		(*get)(struct tcf_proto*, u32 handle);
-	void			(*put)(struct tcf_proto*, unsigned long);
-	int			(*change)(struct tcf_proto*, unsigned long, u32 handle, struct rtattr **, unsigned long *);
-	int			(*delete)(struct tcf_proto*, unsigned long);
-	void			(*walk)(struct tcf_proto*, struct tcf_walker *arg);
-
-	/* rtnetlink specific */
-	int			(*dump)(struct tcf_proto*, unsigned long, struct sk_buff *skb, struct tcmsg*);
-
-	struct module		*owner;
-};
-
-/* Main classifier routine: scans classifier chain attached
-   to this qdisc, (optionally) tests for protocol and asks
-   specific classifiers.
- */
-
-static inline int tc_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res)
-{
-	int err = 0;
-	u32 protocol = skb->protocol;
-#ifdef CONFIG_NET_CLS_ACT
-	struct tcf_proto *otp = tp;
-reclassify:
-#endif
-	protocol = skb->protocol;
-
-	for ( ; tp; tp = tp->next) {
-		if ((tp->protocol == protocol ||
-			tp->protocol == __constant_htons(ETH_P_ALL)) &&
-			(err = tp->classify(skb, tp, res)) >= 0) {
-#ifdef CONFIG_NET_CLS_ACT
-			if ( TC_ACT_RECLASSIFY == err) {
-				__u32 verd = (__u32) G_TC_VERD(skb->tc_verd);
-				tp = otp;
-
-				if (MAX_REC_LOOP < verd++) {
-					printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n",tp->prio&0xffff, ntohs(tp->protocol));
-					return TC_ACT_SHOT;
-				}
-				skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd);
-				goto reclassify;
-			} else {
-				if (skb->tc_verd) 
-					skb->tc_verd = SET_TC_VERD(skb->tc_verd,0);
-				return err;
-			}
-#else
-
-			return err;
-#endif
-            }
-
-	}
-	return -1;
-}
-
-static inline void tcf_destroy(struct tcf_proto *tp)
-{
-	tp->ops->destroy(tp);
-	module_put(tp->ops->owner);
-	kfree(tp);
-}
-
 extern int register_tcf_proto_ops(struct tcf_proto_ops *ops);
 extern int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
 extern int ing_filter(struct sk_buff *skb);
 
+static inline unsigned long
+__cls_set_class(unsigned long *clp, unsigned long cl)
+{
+	unsigned long old_cl;
+ 
+	old_cl = *clp;
+	*clp = cl;
+	return old_cl;
+}
 
-
+static inline unsigned long
+cls_set_class(struct tcf_proto *tp, unsigned long *clp, 
+	unsigned long cl)
+{
+	unsigned long old_cl;
+	
+	tcf_tree_lock(tp);
+	old_cl = __cls_set_class(clp, cl);
+	tcf_tree_unlock(tp);
+ 
+	return old_cl;
+}
 
 #endif
diff -Nru a/include/net/pkt_sched.h b/include/net/pkt_sched.h
--- a/include/net/pkt_sched.h	2004-10-28 22:25:57 -07:00
+++ b/include/net/pkt_sched.h	2004-10-28 22:25:57 -07:00
@@ -1,18 +1,7 @@
 #ifndef __NET_PKT_SCHED_H
 #define __NET_PKT_SCHED_H
 
-#include <linux/config.h>
-#include <linux/netdevice.h>
-#include <linux/types.h>
-#include <linux/pkt_sched.h>
-#include <linux/rcupdate.h>
-#include <net/pkt_cls.h>
-#include <linux/module.h>
-#include <linux/rtnetlink.h>
-#include <net/gen_stats.h>
-
-struct rtattr;
-struct Qdisc;
+#include <net/sch_generic.h>
 
 struct qdisc_walker
 {
@@ -22,86 +11,8 @@
 	int	(*fn)(struct Qdisc *, unsigned long cl, struct qdisc_walker *);
 };
 
-struct Qdisc_class_ops
-{
-	/* Child qdisc manipulation */
-	int			(*graft)(struct Qdisc *, unsigned long cl, struct Qdisc *, struct Qdisc **);
-	struct Qdisc *		(*leaf)(struct Qdisc *, unsigned long cl);
-
-	/* Class manipulation routines */
-	unsigned long		(*get)(struct Qdisc *, u32 classid);
-	void			(*put)(struct Qdisc *, unsigned long);
-	int			(*change)(struct Qdisc *, u32, u32, struct rtattr **, unsigned long *);
-	int			(*delete)(struct Qdisc *, unsigned long);
-	void			(*walk)(struct Qdisc *, struct qdisc_walker * arg);
-
-	/* Filter manipulation */
-	struct tcf_proto **	(*tcf_chain)(struct Qdisc *, unsigned long);
-	unsigned long		(*bind_tcf)(struct Qdisc *, unsigned long, u32 classid);
-	void			(*unbind_tcf)(struct Qdisc *, unsigned long);
-
-	/* rtnetlink specific */
-	int			(*dump)(struct Qdisc *, unsigned long, struct sk_buff *skb, struct tcmsg*);
-	int			(*dump_stats)(struct Qdisc *, unsigned long, struct gnet_dump *);
-};
-
-struct module;
-
-struct Qdisc_ops
-{
-	struct Qdisc_ops	*next;
-	struct Qdisc_class_ops	*cl_ops;
-	char			id[IFNAMSIZ];
-	int			priv_size;
-
-	int 			(*enqueue)(struct sk_buff *, struct Qdisc *);
-	struct sk_buff *	(*dequeue)(struct Qdisc *);
-	int 			(*requeue)(struct sk_buff *, struct Qdisc *);
-	unsigned int		(*drop)(struct Qdisc *);
-
-	int			(*init)(struct Qdisc *, struct rtattr *arg);
-	void			(*reset)(struct Qdisc *);
-	void			(*destroy)(struct Qdisc *);
-	int			(*change)(struct Qdisc *, struct rtattr *arg);
-
-	int			(*dump)(struct Qdisc *, struct sk_buff *);
-	int			(*dump_stats)(struct Qdisc *, struct gnet_dump *);
-
-	struct module		*owner;
-};
-
 extern rwlock_t qdisc_tree_lock;
 
-struct Qdisc
-{
-	int 			(*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
-	struct sk_buff *	(*dequeue)(struct Qdisc *dev);
-	unsigned		flags;
-#define TCQ_F_BUILTIN	1
-#define TCQ_F_THROTTLED	2
-#define TCQ_F_INGRES	4
-	int			padded;
-	struct Qdisc_ops	*ops;
-	u32			handle;
-	u32			parent;
-	atomic_t		refcnt;
-	struct sk_buff_head	q;
-	struct net_device	*dev;
-	struct list_head	list;
-
-	struct gnet_stats_basic	bstats;
-	struct gnet_stats_queue	qstats;
-	struct gnet_stats_rate_est	rate_est;
-	spinlock_t		*stats_lock;
-	struct rcu_head 	q_rcu;
-	int			(*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
-
-	/* This field is deprecated, but it is still used by CBQ
-	 * and it will live until better solution will be invented.
-	 */
-	struct Qdisc		*__parent;
-};
-
 #define	QDISC_ALIGN		32
 #define	QDISC_ALIGN_CONST	(QDISC_ALIGN - 1)
 
@@ -111,34 +22,6 @@
 			      & ~QDISC_ALIGN_CONST);
 }
 
-struct qdisc_rate_table
-{
-	struct tc_ratespec rate;
-	u32		data[256];
-	struct qdisc_rate_table *next;
-	int		refcnt;
-};
-
-extern void qdisc_lock_tree(struct net_device *dev);
-extern void qdisc_unlock_tree(struct net_device *dev);
-
-#define sch_tree_lock(q)	qdisc_lock_tree((q)->dev)
-#define sch_tree_unlock(q)	qdisc_unlock_tree((q)->dev)
-#define tcf_tree_lock(tp)	qdisc_lock_tree((tp)->q->dev)
-#define tcf_tree_unlock(tp)	qdisc_unlock_tree((tp)->q->dev)
-
-#define cls_set_class(tp, clp, cl) tcf_set_class(tp, clp, cl)
-static inline unsigned long
-__cls_set_class(unsigned long *clp, unsigned long cl)
-{
-	unsigned long old_cl;
-
-	old_cl = *clp;
-	*clp = cl;
-	return old_cl;
-}
-
-
 /* 
    Timer resolution MUST BE < 10% of min_schedulable_packet_size/bandwidth
    
@@ -249,7 +132,18 @@
 	   __delta; \
 })
 
-extern int psched_tod_diff(int delta_sec, int bound);
+static inline int
+psched_tod_diff(int delta_sec, int bound)
+{
+	int delta;
+
+	if (bound <= 1000000 || delta_sec > (0x7FFFFFFF/1000000)-1)
+		return bound;
+	delta = delta_sec * 1000000;
+	if (delta > bound)
+		delta = bound;
+	return delta;
+}
 
 #define PSCHED_TDIFF_SAFE(tv1, tv2, bound) \
 ({ \
@@ -311,140 +205,34 @@
 
 #endif /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */
 
-struct tcf_police
-{
-	struct tcf_police *next;
-	int		refcnt;
-#ifdef CONFIG_NET_CLS_ACT
-	int		bindcnt;
-#endif
-	u32		index;
-	int		action;
-	int		result;
-	u32		ewma_rate;
-	u32		burst;
-	u32		mtu;
-	u32		toks;
-	u32		ptoks;
-	psched_time_t	t_c;
-	spinlock_t	lock;
-	struct qdisc_rate_table *R_tab;
-	struct qdisc_rate_table *P_tab;
-
-	struct tc_stats	stats;
-	spinlock_t	*stats_lock;
-};
-
-#ifdef CONFIG_NET_CLS_ACT
-
-#define ACT_P_CREATED 1
-#define ACT_P_DELETED 1
-#define tca_gen(name) \
-struct tcf_##name *next; \
-	u32 index; \
-	int refcnt; \
-	int bindcnt; \
-	u32 capab; \
-	int action; \
-	struct tcf_t tm; \
-	struct tc_stats stats; \
-	spinlock_t *stats_lock; \
-	spinlock_t lock
-
-
-struct tc_action
-{
-	void *priv;
-	struct tc_action_ops *ops;
-	__u32   type;   /* for backward compat(TCA_OLD_COMPAT) */
-	__u32   order; 
-	struct tc_action *next;
-};
-
-#define TCA_CAP_NONE 0
-struct tc_action_ops
-{
-	struct tc_action_ops *next;
-	char    kind[IFNAMSIZ];
-	__u32   type; /* TBD to match kind */
-	__u32 	capab;  /* capabilities includes 4 bit version */
-	struct module		*owner;
-	int     (*act)(struct sk_buff **, struct tc_action *);
-	int     (*get_stats)(struct sk_buff *, struct tc_action *);
-	int     (*dump)(struct sk_buff *, struct tc_action *,int , int);
-	int     (*cleanup)(struct tc_action *, int bind);
-	int     (*lookup)(struct tc_action *, u32 );
-	int     (*init)(struct rtattr *,struct rtattr *,struct tc_action *, int , int );
-	int     (*walk)(struct sk_buff *, struct netlink_callback *, int , struct tc_action *);
-};
-
-extern int tcf_register_action(struct tc_action_ops *a);
-extern int tcf_unregister_action(struct tc_action_ops *a);
-extern void tcf_action_destroy(struct tc_action *a, int bind);
-extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res);
-extern int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
-extern int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
-extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
-extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
-extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
-extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *);
-extern int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,struct tc_action *,int , int );
-extern int tcf_act_police_dump(struct sk_buff *, struct tc_action *, int, int);
-extern int tcf_act_police(struct sk_buff **skb, struct tc_action *a);
-#endif
-
-extern unsigned long tcf_set_class(struct tcf_proto *tp, unsigned long *clp, 
-				   unsigned long cl);
-extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
-extern int qdisc_copy_stats(struct sk_buff *skb, struct tc_stats *st, spinlock_t *lock);
-extern void tcf_police_destroy(struct tcf_police *p);
-extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
-extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
-
-static inline int tcf_police_release(struct tcf_police *p, int bind)
-{
-	int ret = 0;
-#ifdef CONFIG_NET_CLS_ACT
-	if (p) {
-		if (bind) {
-			 p->bindcnt--;
-		}
-		p->refcnt--;
-		if (p->refcnt <= 0 && !p->bindcnt) {
-			tcf_police_destroy(p);
-			ret = 1;
-		}
-	}
-#else
-	if (p && --p->refcnt == 0)
-		tcf_police_destroy(p);
-
-#endif
-	return ret;
-}
-
 extern struct Qdisc noop_qdisc;
 extern struct Qdisc_ops noop_qdisc_ops;
 extern struct Qdisc_ops pfifo_qdisc_ops;
 extern struct Qdisc_ops bfifo_qdisc_ops;
 
-int register_qdisc(struct Qdisc_ops *qops);
-int unregister_qdisc(struct Qdisc_ops *qops);
-struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
-struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
-void dev_init_scheduler(struct net_device *dev);
-void dev_shutdown(struct net_device *dev);
-void dev_activate(struct net_device *dev);
-void dev_deactivate(struct net_device *dev);
-void qdisc_reset(struct Qdisc *qdisc);
-void qdisc_destroy(struct Qdisc *qdisc);
-struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops);
-int qdisc_new_estimator(struct tc_stats *stats, spinlock_t *stats_lock, struct rtattr *opt);
-void qdisc_kill_estimator(struct tc_stats *stats);
-struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct rtattr *tab);
-void qdisc_put_rtab(struct qdisc_rate_table *tab);
+extern int register_qdisc(struct Qdisc_ops *qops);
+extern int unregister_qdisc(struct Qdisc_ops *qops);
+extern struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
+extern struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
+extern void dev_init_scheduler(struct net_device *dev);
+extern void dev_shutdown(struct net_device *dev);
+extern void dev_activate(struct net_device *dev);
+extern void dev_deactivate(struct net_device *dev);
+extern void qdisc_reset(struct Qdisc *qdisc);
+extern void qdisc_destroy(struct Qdisc *qdisc);
+extern struct Qdisc * qdisc_create_dflt(struct net_device *dev,
+	struct Qdisc_ops *ops);
+extern int qdisc_new_estimator(struct tc_stats *stats, spinlock_t *stats_lock,
+	struct rtattr *opt);
+extern void qdisc_kill_estimator(struct tc_stats *stats);
+extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
+		struct rtattr *tab);
+extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
 
 extern int qdisc_restart(struct net_device *dev);
+
+extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
+	struct tcf_result *res);
 
 /* Calculate maximal size of packet seen by hard_start_xmit
    routine of this device.
diff -Nru a/include/net/sch_generic.h b/include/net/sch_generic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/net/sch_generic.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,175 @@
+#ifndef __NET_SCHED_GENERIC_H
+#define __NET_SCHED_GENERIC_H
+
+#include <linux/config.h>
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/module.h>
+#include <linux/rtnetlink.h>
+#include <linux/pkt_sched.h>
+#include <linux/pkt_cls.h>
+#include <net/gen_stats.h>
+
+struct Qdisc_ops;
+struct qdisc_walker;
+struct tcf_walker;
+struct module;
+
+struct qdisc_rate_table
+{
+	struct tc_ratespec rate;
+	u32		data[256];
+	struct qdisc_rate_table *next;
+	int		refcnt;
+};
+
+struct Qdisc
+{
+	int 			(*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
+	struct sk_buff *	(*dequeue)(struct Qdisc *dev);
+	unsigned		flags;
+#define TCQ_F_BUILTIN	1
+#define TCQ_F_THROTTLED	2
+#define TCQ_F_INGRESS	4
+	int			padded;
+	struct Qdisc_ops	*ops;
+	u32			handle;
+	u32			parent;
+	atomic_t		refcnt;
+	struct sk_buff_head	q;
+	struct net_device	*dev;
+	struct list_head	list;
+
+	struct gnet_stats_basic	bstats;
+	struct gnet_stats_queue	qstats;
+	struct gnet_stats_rate_est	rate_est;
+	spinlock_t		*stats_lock;
+	struct rcu_head 	q_rcu;
+	int			(*reshape_fail)(struct sk_buff *skb,
+					struct Qdisc *q);
+
+	/* This field is deprecated, but it is still used by CBQ
+	 * and it will live until better solution will be invented.
+	 */
+	struct Qdisc		*__parent;
+};
+
+struct Qdisc_class_ops
+{
+	/* Child qdisc manipulation */
+	int			(*graft)(struct Qdisc *, unsigned long cl,
+					struct Qdisc *, struct Qdisc **);
+	struct Qdisc *		(*leaf)(struct Qdisc *, unsigned long cl);
+
+	/* Class manipulation routines */
+	unsigned long		(*get)(struct Qdisc *, u32 classid);
+	void			(*put)(struct Qdisc *, unsigned long);
+	int			(*change)(struct Qdisc *, u32, u32,
+					struct rtattr **, unsigned long *);
+	int			(*delete)(struct Qdisc *, unsigned long);
+	void			(*walk)(struct Qdisc *, struct qdisc_walker * arg);
+
+	/* Filter manipulation */
+	struct tcf_proto **	(*tcf_chain)(struct Qdisc *, unsigned long);
+	unsigned long		(*bind_tcf)(struct Qdisc *, unsigned long,
+					u32 classid);
+	void			(*unbind_tcf)(struct Qdisc *, unsigned long);
+
+	/* rtnetlink specific */
+	int			(*dump)(struct Qdisc *, unsigned long,
+					struct sk_buff *skb, struct tcmsg*);
+	int			(*dump_stats)(struct Qdisc *, unsigned long,
+					struct gnet_dump *);
+};
+
+struct Qdisc_ops
+{
+	struct Qdisc_ops	*next;
+	struct Qdisc_class_ops	*cl_ops;
+	char			id[IFNAMSIZ];
+	int			priv_size;
+
+	int 			(*enqueue)(struct sk_buff *, struct Qdisc *);
+	struct sk_buff *	(*dequeue)(struct Qdisc *);
+	int 			(*requeue)(struct sk_buff *, struct Qdisc *);
+	unsigned int		(*drop)(struct Qdisc *);
+
+	int			(*init)(struct Qdisc *, struct rtattr *arg);
+	void			(*reset)(struct Qdisc *);
+	void			(*destroy)(struct Qdisc *);
+	int			(*change)(struct Qdisc *, struct rtattr *arg);
+
+	int			(*dump)(struct Qdisc *, struct sk_buff *);
+	int			(*dump_stats)(struct Qdisc *, struct gnet_dump *);
+
+	struct module		*owner;
+};
+
+
+struct tcf_result
+{
+	unsigned long	class;
+	u32		classid;
+};
+
+struct tcf_proto_ops
+{
+	struct tcf_proto_ops	*next;
+	char			kind[IFNAMSIZ];
+
+	int			(*classify)(struct sk_buff*, struct tcf_proto*,
+					struct tcf_result *);
+	int			(*init)(struct tcf_proto*);
+	void			(*destroy)(struct tcf_proto*);
+
+	unsigned long		(*get)(struct tcf_proto*, u32 handle);
+	void			(*put)(struct tcf_proto*, unsigned long);
+	int			(*change)(struct tcf_proto*, unsigned long,
+					u32 handle, struct rtattr **,
+					unsigned long *);
+	int			(*delete)(struct tcf_proto*, unsigned long);
+	void			(*walk)(struct tcf_proto*, struct tcf_walker *arg);
+
+	/* rtnetlink specific */
+	int			(*dump)(struct tcf_proto*, unsigned long,
+					struct sk_buff *skb, struct tcmsg*);
+
+	struct module		*owner;
+};
+
+struct tcf_proto
+{
+	/* Fast access part */
+	struct tcf_proto	*next;
+	void			*root;
+	int			(*classify)(struct sk_buff*, struct tcf_proto*,
+					struct tcf_result *);
+	u32			protocol;
+
+	/* All the rest */
+	u32			prio;
+	u32			classid;
+	struct Qdisc		*q;
+	void			*data;
+	struct tcf_proto_ops	*ops;
+};
+
+
+extern void qdisc_lock_tree(struct net_device *dev);
+extern void qdisc_unlock_tree(struct net_device *dev);
+
+#define sch_tree_lock(q)	qdisc_lock_tree((q)->dev)
+#define sch_tree_unlock(q)	qdisc_unlock_tree((q)->dev)
+#define tcf_tree_lock(tp)	qdisc_lock_tree((tp)->q->dev)
+#define tcf_tree_unlock(tp)	qdisc_unlock_tree((tp)->q->dev)
+
+static inline void
+tcf_destroy(struct tcf_proto *tp)
+{
+	tp->ops->destroy(tp);
+	module_put(tp->ops->owner);
+	kfree(tp);
+}
+
+#endif
diff -Nru a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
--- a/include/net/sctp/sctp.h	2004-10-28 22:25:57 -07:00
+++ b/include/net/sctp/sctp.h	2004-10-28 22:25:57 -07:00
@@ -335,7 +335,7 @@
 /* Map an association to an assoc_id. */
 static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
 {
-	return (asoc?asoc->assoc_id:NULL);
+	return (asoc?asoc->assoc_id:0);
 }
 
 /* Look up the association by its id.  */
diff -Nru a/include/net/sctp/structs.h b/include/net/sctp/structs.h
--- a/include/net/sctp/structs.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/sctp/structs.h	2004-10-28 22:25:59 -07:00
@@ -266,6 +266,7 @@
 	__u8 disable_fragments;
 	__u8 pd_mode;
 	__u8 v4mapped;
+	__u32 adaption_ind;
 
 	/* Receive to here while partial delivery is in effect. */
 	struct sk_buff_head pd_lobby;
@@ -323,6 +324,8 @@
 
 	__u8 prsctp_capable;
 
+	__u32 adaption_ind;	
+
 	/* This is a shim for my peer's INIT packet, followed by
 	 * a copy of the raw address list of the association.
 	 * The length of the raw address list is saved in the
@@ -362,6 +365,7 @@
 	struct sctp_ipv4addr_param *v4;
 	struct sctp_ipv6addr_param *v6;
 	union sctp_addr_param *addr;
+	struct sctp_adaption_ind_param *aind;
 };
 
 /* RFC 2960.  Section 3.3.5 Heartbeat.
@@ -1394,6 +1398,8 @@
 		__u8	hostname_address;/* Peer understands DNS addresses? */
 		__u8    asconf_capable;  /* Does peer support ADDIP? */
 		__u8    prsctp_capable;  /* Can peer do PR-SCTP? */
+
+		__u32   adaption_ind;	 /* Adaption Code point. */
 
 		/* This mask is used to disable sending the ASCONF chunk
 		 * with specified parameter to peer.
diff -Nru a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
--- a/include/net/sctp/ulpevent.h	2004-10-28 22:25:57 -07:00
+++ b/include/net/sctp/ulpevent.h	2004-10-28 22:25:57 -07:00
@@ -121,6 +121,9 @@
 	const struct sctp_association *asoc,
 	__u32 indication, int gfp);
 
+struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
+	const struct sctp_association *asoc, int gfp);
+
 struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
 	struct sctp_chunk *chunk,
 	int gfp);
diff -Nru a/include/net/sctp/user.h b/include/net/sctp/user.h
--- a/include/net/sctp/user.h	2004-10-28 22:25:56 -07:00
+++ b/include/net/sctp/user.h	2004-10-28 22:25:56 -07:00
@@ -55,7 +55,7 @@
 #include <linux/types.h>
 #include <linux/socket.h>
 
-typedef void * sctp_assoc_t;
+typedef __s32 sctp_assoc_t;
 
 /* The following symbols come from the Sockets API Extensions for
  * SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/sock.h	2004-10-28 22:25:59 -07:00
@@ -746,7 +746,6 @@
  * Functions to fill in entries in struct proto_ops when a protocol
  * does not implement a particular function.
  */
-extern int                      sock_no_release(struct socket *);
 extern int                      sock_no_bind(struct socket *, 
 					     struct sockaddr *, int);
 extern int                      sock_no_connect(struct socket *,
@@ -1275,7 +1274,6 @@
 
 extern atomic_t netstamp_needed;
 extern void sock_enable_timestamp(struct sock *sk);
-extern void sock_disable_timestamp(struct sock *sk);
 
 static inline void net_timestamp(struct timeval *stamp) 
 { 
diff -Nru a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
--- a/include/net/tc_act/tc_gact.h	2004-10-28 22:25:58 -07:00
+++ b/include/net/tc_act/tc_gact.h	2004-10-28 22:25:58 -07:00
@@ -1,7 +1,7 @@
 #ifndef __NET_TC_GACT_H
 #define __NET_TC_GACT_H
 
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
 
 struct tcf_gact
 {
diff -Nru a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
--- a/include/net/tc_act/tc_mirred.h	2004-10-28 22:25:58 -07:00
+++ b/include/net/tc_act/tc_mirred.h	2004-10-28 22:25:58 -07:00
@@ -1,7 +1,7 @@
 #ifndef __NET_TC_MIR_H
 #define __NET_TC_MIR_H
 
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
 
 struct tcf_mirred
 {
diff -Nru a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/net/tc_act/tc_pedit.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,14 @@
+#ifndef __NET_TC_PED_H
+#define __NET_TC_PED_H
+
+#include <net/act_api.h>
+
+struct tcf_pedit
+{
+	tca_gen(pedit);
+	unsigned char           nkeys;
+	unsigned char           flags;
+	struct tc_pedit_key     keys[0];
+};
+
+#endif
diff -Nru a/include/net/tcp.h b/include/net/tcp.h
--- a/include/net/tcp.h	2004-10-28 22:25:57 -07:00
+++ b/include/net/tcp.h	2004-10-28 22:25:57 -07:00
@@ -159,7 +159,6 @@
 extern void tcp_bucket_destroy(struct tcp_bind_bucket *tb);
 extern void tcp_bucket_unlock(struct sock *sk);
 extern int tcp_port_rover;
-extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
 
 /* These are AF independent. */
 static __inline__ int tcp_bhashfn(__u16 lport)
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	2004-10-28 22:25:59 -07:00
+++ b/include/net/xfrm.h	2004-10-28 22:25:59 -07:00
@@ -178,8 +178,6 @@
 
 extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
 extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
-extern struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
-extern void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
 
 #define XFRM_ACQ_EXPIRES	30
 
@@ -200,8 +198,6 @@
 
 extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
 extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
-extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
-extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
@@ -805,17 +801,15 @@
 extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
 extern int xfrm_state_update(struct xfrm_state *x);
-extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb);
 extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
 extern void xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
 extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
-extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
 extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm4_rcv(struct sk_buff *skb);
-extern int xfrm4_output(struct sk_buff **pskb);
+extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
 extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi);
@@ -825,7 +819,7 @@
 extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
 extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
 extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
-extern int xfrm6_output(struct sk_buff **pskb);
+extern int xfrm6_output(struct sk_buff *skb);
 
 #ifdef CONFIG_XFRM
 extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
@@ -863,7 +857,6 @@
 				  xfrm_address_t *daddr, xfrm_address_t *saddr, 
 				  int create, unsigned short family);
 extern void xfrm_policy_flush(void);
-extern void xfrm_policy_kill(struct xfrm_policy *);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl);
 extern int xfrm_flush_bundles(void);
diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
--- a/include/sound/ac97_codec.h	2004-10-28 22:25:58 -07:00
+++ b/include/sound/ac97_codec.h	2004-10-28 22:25:58 -07:00
@@ -26,6 +26,7 @@
  */
 
 #include <linux/bitops.h>
+#include "pcm.h"
 #include "control.h"
 #include "info.h"
 
@@ -133,6 +134,11 @@
 #define AC97_BC_20BIT_ADC	0x0200	/* 20-bit ADC resolution */
 #define AC97_BC_ADC_MASK	0x0300
 
+/* general purpose */
+#define AC97_GP_DRSS_MASK	0x0c00	/* double rate slot select */
+#define AC97_GP_DRSS_1011	0x0000	/* LR(C) 10+11(+12) */
+#define AC97_GP_DRSS_78		0x0400	/* LR 7+8 */
+
 /* extended audio ID bit defines */
 #define AC97_EI_VRA		0x0001	/* Variable bit rate supported */
 #define AC97_EI_DRA		0x0002	/* Double rate supported */
@@ -348,6 +354,8 @@
 #define AC97_SCAP_SKIP_AUDIO	(1<<4)	/* skip audio part of codec */
 #define AC97_SCAP_SKIP_MODEM	(1<<5)	/* skip modem part of codec */
 #define AC97_SCAP_INDEP_SDIN	(1<<6)	/* independent SDIN */
+#define AC97_SCAP_INV_EAPD	(1<<7)	/* inverted EAPD */
+#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
 
 /* ac97->flags */
 #define AC97_HAS_PC_BEEP	(1<<0)	/* force PC Speaker usage */
@@ -355,6 +363,7 @@
 #define AC97_CS_SPDIF		(1<<2)	/* Cirrus Logic uses funky SPDIF */
 #define AC97_CX_SPDIF		(1<<3)	/* Conexant's spdif interface */
 #define AC97_STEREO_MUTES	(1<<4)	/* has stereo mute bits */
+#define AC97_DOUBLE_RATE	(1<<5)	/* supports double rate playback */
 
 /* rates indexes */
 #define AC97_RATES_FRONT_DAC	0
@@ -369,6 +378,7 @@
 	AC97_SHARED_TYPE_NONE,
 	AC97_SHARED_TYPE_ICH,
 	AC97_SHARED_TYPE_ATIIXP,
+	AC97_SHARED_TYPE_VIA,
 	AC97_SHARED_TYPES
 };
 
@@ -432,6 +442,7 @@
 	snd_card_t *card;
 	unsigned short num;	/* bus number */
 	unsigned short no_vra: 1, /* bridge doesn't support VRA */
+		       dra: 1,	/* bridge supports double rate */
 		       isdin: 1;/* independent SDIN */
 	unsigned int clock;	/* AC'97 base clock (usually 48000Hz) */
 	spinlock_t bus_lock;	/* used mainly for slot allocation */
@@ -518,6 +529,7 @@
 /* functions */
 int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops, void *private_data, ac97_bus_t **rbus); /* create new AC97 bus */
 int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97);	/* create mixer controls */
+const char *snd_ac97_get_short_name(ac97_t *ac97);
 
 void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value);
 unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg);
@@ -538,18 +550,20 @@
 	AC97_TUNE_SWAP_SURROUND, /* swap master and surround controls */
 	AC97_TUNE_AD_SHARING,	/* for AD1985, turn on OMS bit and use headphone */
 	AC97_TUNE_ALC_JACK,	/* for Realtek, enable JACK detection */
+	AC97_TUNE_INV_EAPD,	/* inverted EAPD implementation */
 };
 
 struct ac97_quirk {
 	unsigned short vendor;	/* PCI vendor id */
 	unsigned short device;	/* PCI device id */
 	unsigned short mask;	/* device id bit mask, 0 = accept all */
+	unsigned int codec_id;	/* codec id (if any), 0 = accept all */
 	const char *name;	/* name shown as info */
 	int type;		/* quirk type above */
 };
 
 int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, int override);
-int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned short rate);
+int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned int rate);
 
 int snd_ac97_pcm_assign(ac97_bus_t *ac97,
 			unsigned short pcms_count,
@@ -557,5 +571,6 @@
 int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
 		      enum ac97_pcm_cfg cfg, unsigned short slots);
 int snd_ac97_pcm_close(struct ac97_pcm *pcm);
+int snd_ac97_pcm_double_rate_rules(snd_pcm_runtime_t *runtime);
 
 #endif /* __SOUND_AC97_CODEC_H */
diff -Nru a/include/sound/core.h b/include/sound/core.h
--- a/include/sound/core.h	2004-10-28 22:25:59 -07:00
+++ b/include/sound/core.h	2004-10-28 22:25:59 -07:00
@@ -307,8 +307,8 @@
 #define vfree_nocheck(obj) vfree(obj)
 #endif
 char *snd_kmalloc_strdup(const char *string, int flags);
-int copy_to_user_fromio(void __user *dst, unsigned long src, size_t count);
-int copy_from_user_toio(unsigned long dst, const void __user *src, size_t count);
+int copy_to_user_fromio(void __user *dst, const void __iomem *src, size_t count);
+int copy_from_user_toio(void __iomem *dst, const void __user *src, size_t count);
 
 /* init.c */
 
@@ -417,7 +417,7 @@
  */
 #define snd_assert(expr, args...) do {\
 	if (unlikely(!(expr))) {				\
-		snd_printk("BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
+		snd_printk(KERN_ERR "BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
 		args;\
 	}\
 } while (0)
@@ -433,7 +433,7 @@
  */
 #define snd_runtime_check(expr, args...) do {\
 	if (unlikely(!(expr))) {				\
-		snd_printk("ERROR (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
+		snd_printk(KERN_ERR "ERROR (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
 		args;\
 	}\
 } while (0)
diff -Nru a/include/sound/cs46xx.h b/include/sound/cs46xx.h
--- a/include/sound/cs46xx.h	2004-10-28 22:25:57 -07:00
+++ b/include/sound/cs46xx.h	2004-10-28 22:25:57 -07:00
@@ -1662,7 +1662,7 @@
 typedef struct {
 	char name[24];
 	unsigned long base;
-	unsigned long remap_addr;
+	void __iomem *remap_addr;
 	unsigned long size;
 	struct resource *resource;
 } snd_cs46xx_region_t;
diff -Nru a/include/sound/emu10k1.h b/include/sound/emu10k1.h
--- a/include/sound/emu10k1.h	2004-10-28 22:25:57 -07:00
+++ b/include/sound/emu10k1.h	2004-10-28 22:25:57 -07:00
@@ -737,6 +737,9 @@
 #define FXGPREGBASE		0x100		/* FX general purpose registers base       	*/
 #define A_FXGPREGBASE		0x400		/* Audigy GPRs, 0x400 to 0x5ff			*/
 
+#define A_TANKMEMCTLREGBASE	0x100		/* Tank memory control registers base - only for Audigy */
+#define A_TANKMEMCTLREG_MASK	0x1f		/* only 5 bits used - only for Audigy */
+
 /* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is	*/
 /* decompressed back to 20 bits on a read.  There are a total of 160 locations, the last 32	*/
 /* locations are for external TRAM. 								*/
@@ -857,7 +860,7 @@
 	struct list_head list;		/* list link container */
 	unsigned int vcount;
 	unsigned int count;		/* count of GPR (1..16) */
-	unsigned char gpr[32];		/* GPR number(s) */
+	unsigned short gpr[32];		/* GPR number(s) */
 	unsigned int value[32];
 	unsigned int min;		/* minimum range */
 	unsigned int max;		/* maximum range */
@@ -870,7 +873,7 @@
 typedef struct _snd_emu10k1_fx8010_irq {
 	struct _snd_emu10k1_fx8010_irq *next;
 	snd_fx8010_irq_handler_t *handler;
-	unsigned char gpr_running;
+	unsigned short gpr_running;
 	void *private_data;
 } snd_emu10k1_fx8010_irq_t;
 
@@ -881,12 +884,12 @@
 	unsigned int channels;		/* 16-bit channels count */
 	unsigned int tram_start;	/* initial ring buffer position in TRAM (in samples) */
 	unsigned int buffer_size;	/* count of buffered samples */
-	unsigned char gpr_size;		/* GPR containing size of ring buffer in samples (host) */
-	unsigned char gpr_ptr;		/* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
-	unsigned char gpr_count;	/* GPR containing count of samples between two interrupts (host) */
-	unsigned char gpr_tmpcount;	/* GPR containing current count of samples to interrupt (host = set, FX8010) */
-	unsigned char gpr_trigger;	/* GPR containing trigger (activate) information (host) */
-	unsigned char gpr_running;	/* GPR containing info if PCM is running (FX8010) */
+	unsigned short gpr_size;		/* GPR containing size of ring buffer in samples (host) */
+	unsigned short gpr_ptr;		/* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
+	unsigned short gpr_count;	/* GPR containing count of samples between two interrupts (host) */
+	unsigned short gpr_tmpcount;	/* GPR containing current count of samples to interrupt (host = set, FX8010) */
+	unsigned short gpr_trigger;	/* GPR containing trigger (activate) information (host) */
+	unsigned short gpr_running;	/* GPR containing info if PCM is running (FX8010) */
 	unsigned char etram[32];	/* external TRAM address & data */
 	snd_pcm_indirect_t pcm_rec;
 	unsigned int tram_pos;
@@ -1141,6 +1144,13 @@
 #define ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0x7f */
 #define ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x80 + (x)) /* x = 0x00 - 0x1f */
 
+#define A_ITRAM_DATA(x)	(TANKMEMDATAREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_DATA(x)	(TANKMEMDATAREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_ADDR(x)	(TANKMEMADDRREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+#define A_ITRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
+#define A_ETRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
+
 #define A_FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x3f? */
 #define A_EXTIN(x)	(0x40 + (x))	/* x = 0x00 - 0x1f? */
 #define A_EXTOUT(x)	(0x60 + (x))	/* x = 0x00 - 0x1f? */
@@ -1269,8 +1279,11 @@
 #define A_C_00100000	0xd5
 #define A_GPR_ACCU	0xd6		/* ACCUM, accumulator */
 #define A_GPR_COND	0xd7		/* CCR, condition register */
-/* 0xd8 = noise1 */
-/* 0xd9 = noise2 */
+#define A_GPR_NOISE0	0xd8		/* noise source */
+#define A_GPR_NOISE1	0xd9		/* noise source */
+#define A_GPR_IRQ	0xda		/* IRQ register */
+#define A_GPR_DBAC	0xdb		/* TRAM Delay Base Address Counter - internal */
+#define A_GPR_DBACE	0xde		/* TRAM Delay Base Address Counter - external */
 
 /* definitions for debug register */
 #define EMU10K1_DBG_ZC			0x80000000	/* zero tram counter */
@@ -1310,7 +1323,7 @@
 	snd_ctl_elem_id_t id;		/* full control ID definition */
 	unsigned int vcount;		/* visible count */
 	unsigned int count;		/* count of GPR (1..16) */
-	unsigned char gpr[32];		/* GPR number(s) */
+	unsigned short gpr[32];		/* GPR number(s) */
 	unsigned int value[32];		/* initial values */
 	unsigned int min;		/* minimum range */
 	unsigned int max;		/* maximum range */
@@ -1320,8 +1333,8 @@
 typedef struct {
 	char name[128];
 
-	unsigned long gpr_valid[0x100/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */
-	unsigned int gpr_map[0x100];	  /* initializers */
+	DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
+	unsigned int gpr_map[0x200];	  /* initializers */
 
 	unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
 	emu10k1_fx8010_control_gpr_t __user *gpr_add_controls; /* GPR controls to add/replace */
@@ -1333,12 +1346,12 @@
 	unsigned int gpr_list_control_total; /* total count of GPR controls */
 	emu10k1_fx8010_control_gpr_t __user *gpr_list_controls; /* listed GPR controls */
 
-	unsigned long tram_valid[0xa0/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */
-	unsigned int tram_data_map[0xa0]; /* data initializers */
-	unsigned int tram_addr_map[0xa0]; /* map initializers */
+	DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
+	unsigned int tram_data_map[0x100]; /* data initializers */
+	unsigned int tram_addr_map[0x100]; /* map initializers */
 
-	unsigned long code_valid[512/(sizeof(unsigned long)*8)];  /* bitmask of valid instructions */
-	unsigned int code[512][2];	  /* one instruction - 64 bits */
+	DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
+	unsigned int code[1024][2];	  /* one instruction - 64 bits */
 } emu10k1_fx8010_code_t;
 
 typedef struct {
@@ -1354,12 +1367,12 @@
 	unsigned int channels;		/* 16-bit channels count, zero = remove this substream */
 	unsigned int tram_start;	/* ring buffer position in TRAM (in samples) */
 	unsigned int buffer_size;	/* count of buffered samples */
-	unsigned char gpr_size;		/* GPR containing size of ringbuffer in samples (host) */
-	unsigned char gpr_ptr;		/* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
-	unsigned char gpr_count;	/* GPR containing count of samples between two interrupts (host) */
-	unsigned char gpr_tmpcount;	/* GPR containing current count of samples to interrupt (host = set, FX8010) */
-	unsigned char gpr_trigger;	/* GPR containing trigger (activate) information (host) */
-	unsigned char gpr_running;	/* GPR containing info if PCM is running (FX8010) */
+	unsigned short gpr_size;		/* GPR containing size of ringbuffer in samples (host) */
+	unsigned short gpr_ptr;		/* GPR containing current pointer in the ring buffer (host = reset, FX8010) */
+	unsigned short gpr_count;	/* GPR containing count of samples between two interrupts (host) */
+	unsigned short gpr_tmpcount;	/* GPR containing current count of samples to interrupt (host = set, FX8010) */
+	unsigned short gpr_trigger;	/* GPR containing trigger (activate) information (host) */
+	unsigned short gpr_running;	/* GPR containing info if PCM is running (FX8010) */
 	unsigned char pad;		/* reserved */
 	unsigned char etram[32];	/* external TRAM address & data (one per channel) */
 	unsigned int res2;		/* reserved */
diff -Nru a/include/sound/hdsp.h b/include/sound/hdsp.h
--- a/include/sound/hdsp.h	2004-10-28 22:25:59 -07:00
+++ b/include/sound/hdsp.h	2004-10-28 22:25:59 -07:00
@@ -32,13 +32,13 @@
 typedef struct _snd_hdsp_peak_rms hdsp_peak_rms_t;
 
 struct _snd_hdsp_peak_rms {
-	unsigned int input_peaks[26];
-	unsigned int playback_peaks[26];
-	unsigned int output_peaks[28];
-	unsigned long long input_rms[26];
-	unsigned long long playback_rms[26];
+	u32 input_peaks[26];
+	u32 playback_peaks[26];
+	u32 output_peaks[28];
+	u64 input_rms[26];
+	u64 playback_rms[26];
 	/* These are only used for H96xx cards */
-	unsigned long long output_rms[26];
+	u64 output_rms[26];
 };
 
 #define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, hdsp_peak_rms_t)
@@ -76,7 +76,7 @@
 typedef struct _snd_hdsp_firmware hdsp_firmware_t;
 
 struct _snd_hdsp_firmware {
-	unsigned long __user *firmware_data;	/* 24413 long words */
+	void __user *firmware_data;	/* 24413 x 4 bytes */
 };
 
 #define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, hdsp_firmware_t)
diff -Nru a/include/sound/opl3.h b/include/sound/opl3.h
--- a/include/sound/opl3.h	2004-10-28 22:25:57 -07:00
+++ b/include/sound/opl3.h	2004-10-28 22:25:57 -07:00
@@ -274,6 +274,9 @@
 	snd_timer_t *timer2;
 	spinlock_t timer_lock;
 
+	void *private_data;
+	void (*private_free)(opl3_t *);
+
 	spinlock_t reg_lock;
 	snd_card_t *card;		/* The card that this belongs to */
 	int used;			/* usage flag - exclusive */
@@ -314,6 +317,8 @@
 
 /* opl3.c */
 void snd_opl3_interrupt(snd_hwdep_t * hw);
+int snd_opl3_new(snd_card_t *card, unsigned short hardware, opl3_t **ropl3);
+int snd_opl3_init(opl3_t *opl3);
 int snd_opl3_create(snd_card_t * card,
 		    unsigned long l_port, unsigned long r_port,
 		    unsigned short hardware,
diff -Nru a/include/sound/pcm.h b/include/sound/pcm.h
--- a/include/sound/pcm.h	2004-10-28 22:25:58 -07:00
+++ b/include/sound/pcm.h	2004-10-28 22:25:58 -07:00
@@ -364,6 +364,7 @@
 typedef struct _snd_pcm_group {		/* keep linked substreams */
 	spinlock_t lock;
 	struct list_head substreams;
+	int count;
 } snd_pcm_group_t;
 
 struct _snd_pcm_substream {
@@ -405,6 +406,8 @@
 	snd_info_entry_t *proc_sw_params_entry;
 	snd_info_entry_t *proc_status_entry;
 	snd_info_entry_t *proc_prealloc_entry;
+	/* misc flags */
+	unsigned int no_mmap_ctrl: 1;
 };
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
@@ -486,6 +489,7 @@
 int snd_pcm_prepare(snd_pcm_substream_t *substream);
 int snd_pcm_start(snd_pcm_substream_t *substream);
 int snd_pcm_stop(snd_pcm_substream_t *substream, int status);
+int snd_pcm_drain_done(snd_pcm_substream_t *substream);
 #ifdef CONFIG_PM
 int snd_pcm_suspend(snd_pcm_substream_t *substream);
 int snd_pcm_suspend_all(snd_pcm_t *pcm);
diff -Nru a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
--- a/include/sound/seq_kernel.h	2004-10-28 22:25:59 -07:00
+++ b/include/sound/seq_kernel.h	2004-10-28 22:25:59 -07:00
@@ -180,4 +180,12 @@
 			      int cap, int type, int midi_channels, int midi_voices, char *portname);
 int snd_seq_event_port_detach(int client, int port);
 
+#ifdef CONFIG_KMOD
+void snd_seq_autoload_lock(void);
+void snd_seq_autoload_unlock(void);
+#else
+#define snd_seq_autoload_lock()
+#define snd_seq_autoload_unlock()
+#endif
+
 #endif /* __SOUND_SEQ_KERNEL_H */
diff -Nru a/include/sound/ymfpci.h b/include/sound/ymfpci.h
--- a/include/sound/ymfpci.h	2004-10-28 22:25:57 -07:00
+++ b/include/sound/ymfpci.h	2004-10-28 22:25:57 -07:00
@@ -305,7 +305,7 @@
 	unsigned int device_id;	/* PCI device ID */
 	unsigned int rev;	/* PCI revision */
 	unsigned long reg_area_phys;
-	unsigned long reg_area_virt;
+	void __iomem *reg_area_virt;
 	struct resource *res_reg_area;
 	struct resource *fm_res;
 	struct resource *mpu_res;
diff -Nru a/include/video/mach64.h b/include/video/mach64.h
--- a/include/video/mach64.h	2004-10-28 22:25:58 -07:00
+++ b/include/video/mach64.h	2004-10-28 22:25:58 -07:00
@@ -68,6 +68,8 @@
 
 #define I2C_CNTL_0		0x003C	/* Dword offset 0_0F */
 
+#define DSTN_CONTROL_LG		0x003C	/* Dword offset 0_0F (LG) */
+
 /* Overscan */
 #define OVR_CLR			0x0040	/* Dword offset 0_10 */
 #define OVR2_CLR		0x0040	/* Dword offset 0_10 */
@@ -101,7 +103,7 @@
 #define CUR_HORZ_VERT_OFF	0x0070	/* Dword offset 0_1C */
 #define CUR2_HORZ_VERT_OFF	0x0070	/* Dword offset 0_1C */
 
-#define CONFIG_PANEL_LG		0x0074	/* Dword offset 0_1D */
+#define CONFIG_PANEL_LG		0x0074	/* Dword offset 0_1D (LG) */
 
 /* General I/O Control */
 #define GP_IO			0x0078	/* Dword offset 0_1E */
@@ -116,7 +118,31 @@
 #define SCRATCH_REG3		0x008C	/* Dword offset 0_23 */
 
 /* Clock Control */
-#define CLOCK_CNTL		0x0090	/* Dword offset 0_24 */
+#define CLOCK_CNTL			0x0090	/* Dword offset 0_24 */
+/* CLOCK_CNTL register constants CT LAYOUT */
+#define CLOCK_SEL			0x0f
+#define CLOCK_SEL_INTERNAL		0x03
+#define CLOCK_SEL_EXTERNAL		0x0c
+#define CLOCK_DIV			0x30
+#define CLOCK_DIV1			0x00
+#define CLOCK_DIV2			0x10
+#define CLOCK_DIV4			0x20
+#define CLOCK_STROBE			0x40
+/*  ?					0x80 */
+/* CLOCK_CNTL register constants GX LAYOUT */
+#define CLOCK_BIT			0x04	/* For ICS2595 */
+#define CLOCK_PULSE			0x08	/* For ICS2595 */
+/*#define CLOCK_STROBE			0x40 dito as CT */
+#define CLOCK_DATA			0x80
+
+/* For internal PLL(CT) start */
+#define CLOCK_CNTL_ADDR			CLOCK_CNTL + 1
+#define PLL_WR_EN			0x02
+#define PLL_ADDR			0xfc
+#define CLOCK_CNTL_DATA			CLOCK_CNTL + 2
+#define PLL_DATA			0xff
+/* For internal PLL(CT) end */
+
 #define CLOCK_SEL_CNTL		0x0090	/* Dword offset 0_24 */
 
 /* Configuration */
@@ -129,6 +155,8 @@
 #define LCD_INDEX		0x00A4	/* Dword offset 0_29 */
 #define LCD_DATA		0x00A8	/* Dword offset 0_2A */
 
+#define HFB_PITCH_ADDR_LG	0x00A8	/* Dword offset 0_2A (LG) */
+
 /* Memory Control */
 #define EXT_MEM_CNTL		0x00AC	/* Dword offset 0_2B */
 #define MEM_CNTL		0x00B0	/* Dword offset 0_2C */
@@ -137,6 +165,8 @@
 
 #define I2C_CNTL_1		0x00BC	/* Dword offset 0_2F */
 
+#define LT_GIO_LG		0x00BC	/* Dword offset 0_2F (LG) */
+
 /* DAC Control */
 #define DAC_REGS		0x00C0	/* Dword offset 0_30 */
 #define DAC_W_INDEX		0x00C0	/* Dword offset 0_30 */
@@ -147,14 +177,16 @@
 
 #define EXT_DAC_REGS		0x00C8	/* Dword offset 0_32 */
 
+#define HORZ_STRETCHING_LG	0x00C8	/* Dword offset 0_32 (LG) */
+#define VERT_STRETCHING_LG	0x00CC	/* Dword offset 0_33 (LG) */
+
 /* Test and Debug */
 #define GEN_TEST_CNTL		0x00D0	/* Dword offset 0_34 */
 
 /* Custom Macros */
 #define CUSTOM_MACRO_CNTL	0x00D4	/* Dword offset 0_35 */
 
-#define LCD_GEN_CNTL_LG		0x00D4	/* Dword offset 0_35 */
-
+#define LCD_GEN_CNTL_LG		0x00D4	/* Dword offset 0_35 (LG) */
 #define POWER_MANAGEMENT_LG	0x00D8	/* Dword offset 0_36 (LG) */
 
 /* Configuration */
@@ -558,7 +590,7 @@
 #define CRTC_CSYNC_EN		0x00000010
 #define CRTC_PIX_BY_2_EN	0x00000020	/* unused on RAGE */
 #define CRTC_DISPLAY_DIS	0x00000040
-#define CRTC_VGA_XOVERSCAN	0x00000040
+#define CRTC_VGA_XOVERSCAN	0x00000080
 
 #define CRTC_PIX_WIDTH_MASK	0x00000700
 #define CRTC_PIX_WIDTH_4BPP	0x00000100
@@ -572,25 +604,95 @@
 #define CRTC_PIX_ORDER_MSN_LSN	0x00000000
 #define CRTC_PIX_ORDER_LSN_MSN	0x00000800
 
+#define CRTC_VSYNC_INT_EN	0x00001000ul	/* XC/XL */
+#define CRTC_VSYNC_INT		0x00002000ul	/* XC/XL */
+#define CRTC_FIFO_OVERFILL	0x0000c000ul	/* VT/GT */
+#define CRTC2_VSYNC_INT_EN	0x00004000ul	/* XC/XL */
+#define CRTC2_VSYNC_INT		0x00008000ul	/* XC/XL */
+
 #define CRTC_FIFO_LWM		0x000f0000
+#define CRTC_HVSYNC_IO_DRIVE	0x00010000	/* XC/XL */
+#define CRTC2_PIX_WIDTH		0x000e0000	/* LTPro */
 
-#define VGA_128KAP_PAGING	0x00100000
-#define VFC_SYNC_TRISTATE	0x00200000
+#define CRTC_VGA_128KAP_PAGING	0x00100000
+#define CRTC_VFC_SYNC_TRISTATE	0x00200000	/* VTB/GTB/LT */
+#define CRTC2_EN		0x00200000	/* LTPro */
 #define CRTC_LOCK_REGS		0x00400000
 #define CRTC_SYNC_TRISTATE	0x00800000
 
 #define CRTC_EXT_DISP_EN	0x01000000
-#define CRTC_ENABLE		0x02000000
-#define CRTC_DISP_REQ_ENB	0x04000000
-#define VGA_ATI_LINEAR		0x08000000
+#define CRTC_EN			0x02000000
+#define CRTC_DISP_REQ_EN	0x04000000
+#define CRTC_VGA_LINEAR		0x08000000
 #define CRTC_VSYNC_FALL_EDGE	0x10000000
-#define VGA_TEXT_132		0x20000000
-#define VGA_XCRT_CNT_EN		0x40000000
-#define VGA_CUR_B_TEST		0x80000000
+#define CRTC_VGA_TEXT_132	0x20000000
+#define CRTC_CNT_EN		0x40000000
+#define CRTC_CUR_B_TEST		0x80000000
 
 #define CRTC_CRNT_VLINE		0x07f00000
-#define CRTC_VBLANK		0x00000001
 
+#define CRTC_PRESERVED_MASK	0x0001f000
+
+#define CRTC_VBLANK		0x00000001
+#define CRTC_VBLANK_INT_EN	0x00000002
+#define CRTC_VBLANK_INT		0x00000004
+#define CRTC_VBLANK_INT_AK	CRTC_VBLANK_INT
+#define CRTC_VLINE_INT_EN	0x00000008
+#define CRTC_VLINE_INT		0x00000010
+#define CRTC_VLINE_INT_AK	CRTC_VLINE_INT
+#define CRTC_VLINE_SYNC		0x00000020
+#define CRTC_FRAME		0x00000040
+#define SNAPSHOT_INT_EN		0x00000080
+#define SNAPSHOT_INT		0x00000100
+#define SNAPSHOT_INT_AK		SNAPSHOT_INT
+#define I2C_INT_EN		0x00000200
+#define I2C_INT			0x00000400
+#define I2C_INT_AK		I2C_INT
+#define CRTC2_VBLANK		0x00000800
+#define CRTC2_VBLANK_INT_EN	0x00001000
+#define CRTC2_VBLANK_INT	0x00002000
+#define CRTC2_VBLANK_INT_AK	CRTC2_VBLANK_INT
+#define CRTC2_VLINE_INT_EN	0x00004000
+#define CRTC2_VLINE_INT		0x00008000
+#define CRTC2_VLINE_INT_AK	CRTC2_VLINE_INT
+#define CAPBUF0_INT_EN		0x00010000
+#define CAPBUF0_INT		0x00020000
+#define CAPBUF0_INT_AK		CAPBUF0_INT
+#define CAPBUF1_INT_EN		0x00040000
+#define CAPBUF1_INT		0x00080000
+#define CAPBUF1_INT_AK		CAPBUF1_INT
+#define OVERLAY_EOF_INT_EN	0x00100000
+#define OVERLAY_EOF_INT		0x00200000
+#define OVERLAY_EOF_INT_AK	OVERLAY_EOF_INT
+#define ONESHOT_CAP_INT_EN	0x00400000
+#define ONESHOT_CAP_INT		0x00800000
+#define ONESHOT_CAP_INT_AK	ONESHOT_CAP_INT
+#define BUSMASTER_EOL_INT_EN	0x01000000
+#define BUSMASTER_EOL_INT	0x02000000
+#define BUSMASTER_EOL_INT_AK	BUSMASTER_EOL_INT
+#define GP_INT_EN		0x04000000
+#define GP_INT			0x08000000
+#define GP_INT_AK		GP_INT
+#define CRTC2_VLINE_SYNC	0x10000000
+#define SNAPSHOT2_INT_EN	0x20000000
+#define SNAPSHOT2_INT		0x40000000
+#define SNAPSHOT2_INT_AK	SNAPSHOT2_INT
+#define VBLANK_BIT2_INT		0x80000000
+#define VBLANK_BIT2_INT_AK	VBLANK_BIT2_INT
+
+#define CRTC_INT_EN_MASK	(CRTC_VBLANK_INT_EN |	\
+				 CRTC_VLINE_INT_EN |	\
+				 SNAPSHOT_INT_EN |	\
+				 I2C_INT_EN |		\
+				 CRTC2_VBLANK_INT_EN |	\
+				 CRTC2_VLINE_INT_EN |	\
+				 CAPBUF0_INT_EN |	\
+				 CAPBUF1_INT_EN |	\
+				 OVERLAY_EOF_INT_EN |	\
+				 ONESHOT_CAP_INT_EN |	\
+				 BUSMASTER_EOL_INT_EN |	\
+				 GP_INT_EN |		\
+				 SNAPSHOT2_INT_EN)
 
 /* DAC control values */
 
@@ -606,6 +708,24 @@
 #define DAC_BLANK_ADJ_1		0x00000800
 #define DAC_BLANK_ADJ_2		0x00001000
 
+/* DAC control values (my source XL/XC Register reference) */
+#define DAC_OUTPUT_MASK         0x00000001  /* 0 - PAL, 1 - NTSC */
+#define DAC_MISTERY_BIT         0x00000002  /* PS2 ? RS343 ?, EXTRA_BRIGHT for GT */
+#define DAC_BLANKING            0x00000004
+#define DAC_CMP_DISABLE         0x00000008
+#define DAC1_CLK_SEL            0x00000010
+#define PALETTE_ACCESS_CNTL     0x00000020
+#define PALETTE2_SNOOP_EN       0x00000040
+#define DAC_CMP_OUTPUT          0x00000080 /* read only */
+/* #define DAC_8BIT_EN is ok */
+#define CRT_SENSE               0x00000800 /* read only */
+#define CRT_DETECTION_ON        0x00001000
+#define DAC_VGA_ADR_EN          0x00002000
+#define DAC_FEA_CON_EN          0x00004000
+#define DAC_PDWN                0x00008000
+#define DAC_TYPE_MASK           0x00070000 /* read only */
+
+
 
 /* Mix control values */
 
@@ -635,6 +755,7 @@
 /* Mach64 engine bit constants - these are typically ORed together */
 
 /* BUS_CNTL register constants */
+#define BUS_APER_REG_DIS	0x00000010
 #define BUS_FIFO_ERR_ACK	0x00200000
 #define BUS_HOST_ERR_ACK	0x00800000
 
@@ -652,29 +773,48 @@
 /* DSP_ON_OFF register constants */
 #define DSP_OFF			0x000007ff
 #define DSP_ON			0x07ff0000
+#define VGA_DSP_OFF		DSP_OFF
+#define VGA_DSP_ON		DSP_ON
+#define VGA_DSP_XCLKS_PER_QW	DSP_XCLKS_PER_QW
 
-/* CLOCK_CNTL register constants */
-#define CLOCK_SEL		0x0f
-#define CLOCK_DIV		0x30
-#define CLOCK_DIV1		0x00
-#define CLOCK_DIV2		0x10
-#define CLOCK_DIV4		0x20
-#define CLOCK_STROBE		0x40
-#define PLL_WR_EN		0x02
-
-/* PLL register indices */
+/* PLL register indices and fields */
 #define MPLL_CNTL		0x00
+#define PLL_PC_GAIN		0x07
+#define PLL_VC_GAIN		0x18
+#define PLL_DUTY_CYC		0xE0
 #define VPLL_CNTL		0x01
 #define PLL_REF_DIV		0x02
 #define PLL_GEN_CNTL		0x03
+#define PLL_OVERRIDE		0x01	/* PLL_SLEEP */
+#define PLL_MCLK_RST		0x02	/* PLL_MRESET */
+#define OSC_EN			0x04
+#define EXT_CLK_EN		0x08
+#define FORCE_DCLK_TRI_STATE	0x08    /* VT4 -> */
+#define MCLK_SRC_SEL		0x70
+#define EXT_CLK_CNTL		0x80
+#define DLL_PWDN		0x80    /* VT4 -> */
 #define MCLK_FB_DIV		0x04
 #define PLL_VCLK_CNTL		0x05
+#define PLL_VCLK_SRC_SEL	0x03
+#define PLL_VCLK_RST		0x04
+#define PLL_VCLK_INVERT		0x08
 #define VCLK_POST_DIV		0x06
+#define VCLK0_POST		0x03
+#define VCLK1_POST		0x0C
+#define VCLK2_POST		0x30
+#define VCLK3_POST		0xC0
 #define VCLK0_FB_DIV		0x07
 #define VCLK1_FB_DIV		0x08
 #define VCLK2_FB_DIV		0x09
 #define VCLK3_FB_DIV		0x0A
 #define PLL_EXT_CNTL		0x0B
+#define PLL_XCLK_MCLK_RATIO	0x03
+#define PLL_XCLK_SRC_SEL	0x07
+#define PLL_MFB_TIMES_4_2B	0x08
+#define PLL_VCLK0_XDIV		0x10
+#define PLL_VCLK1_XDIV		0x20
+#define PLL_VCLK2_XDIV		0x40
+#define PLL_VCLK3_XDIV		0x80
 #define DLL_CNTL		0x0C
 #define DLL1_CNTL		0x0C
 #define VFC_CNTL		0x0D
@@ -690,6 +830,9 @@
 #define SPLL_CNTL2		0x17
 #define APLL_STRAPS		0x18
 #define EXT_VPLL_CNTL		0x19
+#define EXT_VPLL_EN		0x04
+#define EXT_VPLL_VGA_EN		0x08
+#define EXT_VPLL_INSYNC		0x10
 #define EXT_VPLL_REF_DIV	0x1A
 #define EXT_VPLL_FB_DIV		0x1B
 #define EXT_VPLL_MSB		0x1C
@@ -708,24 +851,6 @@
 #define PLL_YCLK_CNTL		0x29
 #define PM_DYN_CLK_CNTL		0x2A
 
-/* Fields in PLL registers */
-#define PLL_PC_GAIN		0x07
-#define PLL_VC_GAIN		0x18
-#define PLL_DUTY_CYC		0xE0
-#define PLL_OVERRIDE		0x01
-#define PLL_MCLK_RST		0x02
-#define OSC_EN			0x04
-#define EXT_CLK_EN		0x08
-#define MCLK_SRC_SEL		0x70
-#define EXT_CLK_CNTL		0x80
-#define VCLK_SRC_SEL		0x03
-#define PLL_VCLK_RST		0x04
-#define VCLK_INVERT		0x08
-#define VCLK0_POST		0x03
-#define VCLK1_POST		0x0C
-#define VCLK2_POST		0x30
-#define VCLK3_POST		0xC0
-
 /* CONFIG_CNTL register constants */
 #define APERTURE_4M_ENABLE	1
 #define APERTURE_8M_ENABLE	2
@@ -811,6 +936,7 @@
 #define MEM_BNDRY_1M		0x00030000
 #define MEM_BNDRY_EN		0x00040000
 
+#define ONE_MB			0x100000
 /* ATI PCI constants */
 #define PCI_ATI_VENDOR_ID	0x1002
 
@@ -849,7 +975,19 @@
 #define LI_CHIP_ID	0x4c49	/* RAGE LT PRO */
 #define LP_CHIP_ID	0x4c50	/* RAGE LT PRO */
 #define LT_CHIP_ID	0x4c54	/* RAGE LT */
-#define XL_CHIP_ID	0x4752	/* RAGE (XL) */
+
+/* mach64CT family / (Rage XL) class */
+#define GR_CHIP_ID	0x4752	/* RAGE XL, BGA, PCI33 */
+#define GS_CHIP_ID	0x4753	/* RAGE XL, PQFP, PCI33 */
+#define GM_CHIP_ID	0x474d	/* RAGE XL, BGA, AGP 1x,2x */
+#define GN_CHIP_ID	0x474e	/* RAGE XL, PQFP,AGP 1x,2x */
+#define GO_CHIP_ID	0x474f	/* RAGE XL, BGA, PCI66 */
+#define GL_CHIP_ID	0x474c	/* RAGE XL, PQFP, PCI66 */
+
+#define IS_XL(id) ((id)==GR_CHIP_ID || (id)==GS_CHIP_ID || \
+		   (id)==GM_CHIP_ID || (id)==GN_CHIP_ID || \
+		   (id)==GO_CHIP_ID || (id)==GL_CHIP_ID)
+
 #define GT_CHIP_ID	0x4754	/* RAGE (GT) */
 #define GU_CHIP_ID	0x4755	/* RAGE II/II+ (GTB) */
 #define GV_CHIP_ID	0x4756	/* RAGE IIC, PCI */
@@ -860,10 +998,14 @@
 #define GI_CHIP_ID	0x4749	/* RAGE PRO, BGA, PCI33 only */
 #define GP_CHIP_ID	0x4750	/* RAGE PRO, PQFP, PCI33, full 3D */
 #define GQ_CHIP_ID	0x4751	/* RAGE PRO, PQFP, PCI33, limited 3D */
-#define LM_CHIP_ID	0x4c4d	/* RAGE Mobility PCI */
-#define LN_CHIP_ID	0x4c4e	/* RAGE Mobility AGP */
 
+#define LM_CHIP_ID	0x4c4d	/* RAGE Mobility AGP, full function */
+#define LN_CHIP_ID	0x4c4e	/* RAGE Mobility AGP */
+#define LR_CHIP_ID	0x4c52	/* RAGE Mobility PCI, full function */
+#define LS_CHIP_ID	0x4c53	/* RAGE Mobility PCI */
 
+#define IS_MOBILITY(id) ((id)==LM_CHIP_ID || (id)==LN_CHIP_ID || \
+			(id)==LR_CHIP_ID || (id)==LS_CHIP_ID)
 /* Mach64 major ASIC revisions */
 #define MACH64_ASIC_NEC_VT_A3		0x08
 #define MACH64_ASIC_NEC_VT_A4		0x48
@@ -889,7 +1031,7 @@
 #define MACH64_UNKNOWN		0
 #define MACH64_GX		1
 #define MACH64_CX		2
-#define MACH64_CT		3
+#define MACH64_CT		3Restore
 #define MACH64_ET		4
 #define MACH64_VT		5
 #define MACH64_GT		6
@@ -934,26 +1076,34 @@
 #define DP_CHAIN_32BPP		0x8080
 
 /* DP_PIX_WIDTH register constants */
-#define DST_1BPP		0
-#define DST_4BPP		1
-#define DST_8BPP		2
-#define DST_15BPP		3
-#define DST_16BPP		4
-#define DST_32BPP		6
-#define SRC_1BPP		0
+#define DST_1BPP		0x0
+#define DST_4BPP		0x1
+#define DST_8BPP		0x2
+#define DST_15BPP		0x3
+#define DST_16BPP		0x4
+#define DST_24BPP		0x5
+#define DST_32BPP		0x6
+#define DST_MASK		0xF
+#define SRC_1BPP		0x000
 #define SRC_4BPP		0x100
 #define SRC_8BPP		0x200
 #define SRC_15BPP		0x300
 #define SRC_16BPP		0x400
+#define SRC_24BPP		0x500
 #define SRC_32BPP		0x600
-#define HOST_1BPP		0
+#define SRC_MASK		0xF00
+#define DP_HOST_TRIPLE_EN	0x2000
+#define HOST_1BPP		0x00000
 #define HOST_4BPP		0x10000
 #define HOST_8BPP		0x20000
 #define HOST_15BPP		0x30000
 #define HOST_16BPP		0x40000
+#define HOST_24BPP		0x50000
 #define HOST_32BPP		0x60000
+#define HOST_MASK		0xF0000
 #define BYTE_ORDER_MSB_TO_LSB	0
 #define BYTE_ORDER_LSB_TO_MSB	0x1000000
+#define BYTE_ORDER_MASK		0x1000000
 
 /* DP_MIX register constants */
 #define BKGD_MIX_NOT_D			0
@@ -1027,12 +1177,12 @@
 #define CONTEXT_CMD_DISABLE		0x80000000
 
 /* GUI_STAT register constants */
-#define ENGINE_IDLE		0
-#define ENGINE_BUSY		1
-#define SCISSOR_LEFT_FLAG	0x10
-#define SCISSOR_RIGHT_FLAG	0x20
-#define SCISSOR_TOP_FLAG	0x40
-#define SCISSOR_BOTTOM_FLAG	0x80
+#define ENGINE_IDLE			0
+#define ENGINE_BUSY			1
+#define SCISSOR_LEFT_FLAG		0x10
+#define SCISSOR_RIGHT_FLAG		0x20
+#define SCISSOR_TOP_FLAG		0x40
+#define SCISSOR_BOTTOM_FLAG		0x80
 
 /* ATI VGA Extended Regsiters */
 #define sioATIEXT		0x1ce
@@ -1043,6 +1193,7 @@
 #define ATI36			0xb6
 
 /* VGA Graphics Controller Registers */
+#define R_GENMO			0x3cc
 #define VGAGRA			0x3ce
 #define GRA06			0x06
 
@@ -1103,7 +1254,7 @@
 
 /* LCD register indices */
 #define CONFIG_PANEL		0x00
-#define LCD_GEN_CTRL		0x01
+#define LCD_GEN_CNTL		0x01
 #define DSTN_CONTROL		0x02
 #define HFB_PITCH_ADDR		0x03
 #define HORZ_STRETCHING		0x04
@@ -1148,11 +1299,79 @@
 #define APC_LUT_MN		0x39
 #define APC_LUT_OP		0x3A
 
+/* Values in LCD_GEN_CTRL */
+#define CRT_ON                          0x00000001ul
+#define LCD_ON                          0x00000002ul
+#define HORZ_DIVBY2_EN                  0x00000004ul
+#define DONT_DS_ICON                    0x00000008ul
+#define LOCK_8DOT                       0x00000010ul
+#define ICON_ENABLE                     0x00000020ul
+#define DONT_SHADOW_VPAR                0x00000040ul
+#define V2CLK_PM_EN                     0x00000080ul
+#define RST_FM                          0x00000100ul
+#define DISABLE_PCLK_RESET              0x00000200ul	/* XC/XL */
+#define DIS_HOR_CRT_DIVBY2              0x00000400ul
+#define SCLK_SEL                        0x00000800ul
+#define SCLK_DELAY                      0x0000f000ul
+#define TVCLK_PM_EN                     0x00010000ul
+#define VCLK_DAC_PM_EN                  0x00020000ul
+#define VCLK_LCD_OFF                    0x00040000ul
+#define SELECT_WAIT_4MS                 0x00080000ul
+#define XTALIN_PM_EN                    0x00080000ul	/* XC/XL */
+#define V2CLK_DAC_PM_EN                 0x00100000ul
+#define LVDS_EN                         0x00200000ul
+#define LVDS_PLL_EN                     0x00400000ul
+#define LVDS_PLL_RESET                  0x00800000ul
+#define LVDS_RESERVED_BITS              0x07000000ul
+#define CRTC_RW_SELECT                  0x08000000ul	/* LTPro */
+#define USE_SHADOWED_VEND               0x10000000ul
+#define USE_SHADOWED_ROWCUR             0x20000000ul
+#define SHADOW_EN                       0x40000000ul
+#define SHADOW_RW_EN                  	0x80000000ul
+
+#define LCD_SET_PRIMARY_MASK            0x07FFFBFBul
+
+/* Values in HORZ_STRETCHING */
+#define HORZ_STRETCH_BLEND		0x00000ffful
+#define HORZ_STRETCH_RATIO		0x0000fffful
+#define HORZ_STRETCH_LOOP		0x00070000ul
+#define HORZ_STRETCH_LOOP09		0x00000000ul
+#define HORZ_STRETCH_LOOP11		0x00010000ul
+#define HORZ_STRETCH_LOOP12		0x00020000ul
+#define HORZ_STRETCH_LOOP14		0x00030000ul
+#define HORZ_STRETCH_LOOP15		0x00040000ul
+/*	?				0x00050000ul */
+/*	?				0x00060000ul */
+/*	?				0x00070000ul */
+/*	?				0x00080000ul */
+#define HORZ_PANEL_SIZE			0x0ff00000ul	/* XC/XL */
+/*	?				0x10000000ul */
+#define AUTO_HORZ_RATIO			0x20000000ul	/* XC/XL */
+#define HORZ_STRETCH_MODE		0x40000000ul
+#define HORZ_STRETCH_EN			0x80000000ul
+
+/* Values in VERT_STRETCHING */
+#define VERT_STRETCH_RATIO0		0x000003fful
+#define VERT_STRETCH_RATIO1		0x000ffc00ul
+#define VERT_STRETCH_RATIO2		0x3ff00000ul
+#define VERT_STRETCH_USE0		0x40000000ul
+#define VERT_STRETCH_EN			0x80000000ul
+
+/* Values in EXT_VERT_STRETCH */
+#define VERT_STRETCH_RATIO3		0x000003fful
+#define FORCE_DAC_DATA			0x000000fful
+#define FORCE_DAC_DATA_SEL		0x00000300ul
+#define VERT_STRETCH_MODE		0x00000400ul
+#define VERT_PANEL_SIZE			0x003ff800ul
+#define AUTO_VERT_RATIO			0x00400000ul
+#define USE_AUTO_FP_POS			0x00800000ul
+#define USE_AUTO_LCD_VSYNC		0x01000000ul
+/*	?				0xfe000000ul */
 
 /* Values in LCD_MISC_CNTL */
-#define BIAS_MOD_LEVEL_MASK	0x0000ff00
-#define BIAS_MOD_LEVEL_SHIFT	8
-#define BLMOD_EN		0x00010000
-#define BIASMOD_EN		0x00020000
+#define BIAS_MOD_LEVEL_MASK		0x0000ff00
+#define BIAS_MOD_LEVEL_SHIFT		8
+#define BLMOD_EN			0x00010000
+#define BIASMOD_EN			0x00020000
 
-#endif /* REGMACH64_H */
+#endif				/* REGMACH64_H */
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/init/Kconfig	2004-10-28 22:25:59 -07:00
@@ -50,6 +50,11 @@
 	depends on BROKEN || !SMP
 	default y
 
+config LOCK_KERNEL
+	bool
+	depends on SMP || PREEMPT
+	default y
+
 endmenu
 
 menu "General setup"
@@ -171,7 +176,7 @@
 
 config LOG_BUF_SHIFT
 	int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
-	range 12 20
+	range 12 21
 	default 17 if ARCH_S390
 	default 16 if X86_NUMAQ || IA64
 	default 15 if SMP
@@ -320,6 +325,43 @@
 	  option replaces shmem and tmpfs with the much simpler ramfs code,
 	  which may be appropriate on small systems without swap.
 
+config CC_ALIGN_FUNCTIONS
+	int "Function alignment" if EMBDEDDED
+	default 0
+	help
+	  Align the start of functions to the next power-of-two greater than n,
+	  skipping up to n bytes.  For instance, 32 aligns functions
+	  to the next 32-byte boundary, but 24 would align to the next
+	  32-byte boundary only if this can be done by skipping 23 bytes or less.
+	  Zero means use compiler's default.
+
+config CC_ALIGN_LABELS
+	int "Label alignment" if EMBEDDED
+	default 0
+	help
+	  Align all branch targets to a power-of-two boundary, skipping
+	  up to n bytes like ALIGN_FUNCTIONS.  This option can easily
+	  make code slower, because it must insert dummy operations for
+	  when the branch target is reached in the usual flow of the code.
+	  Zero means use compiler's default.
+
+config CC_ALIGN_LOOPS
+	int "Loop alignment" if EMBEDDED
+	default 0
+	help
+	  Align loops to a power-of-two boundary, skipping up to n bytes.
+	  Zero means use compiler's default.
+
+config CC_ALIGN_JUMPS
+	int "Jump alignment" if EMBEDDED
+	default 0
+	help
+	  Align branch targets to a power-of-two boundary, for branch
+	  targets where the targets can only be reached by jumping,
+	  skipping up to n bytes like ALIGN_FUNCTIONS.  In this case,
+	  no dummy operations need be executed.
+	  Zero means use compiler's default.
+
 endmenu		# General setup
 
 config TINY_SHMEM
@@ -392,7 +434,7 @@
 	depends on MODULES
 	help
 	  Modules which contain a MODULE_VERSION get an extra "srcversion"
-	  field inserting into their modinfo section, which contains a
+	  field inserted into their modinfo section, which contains a
     	  sum of the source files which made it.  This helps maintainers
 	  see exactly which source was used to build a module (since
 	  others sometimes change the module source without updating
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	2004-10-28 22:25:57 -07:00
+++ b/init/main.c	2004-10-28 22:25:57 -07:00
@@ -287,8 +287,15 @@
 {
 	/* Change NUL term back to "=", to make "param" the whole string. */
 	if (val) {
-		if (val[-1] == '"') val[-2] = '=';
-		else val[-1] = '=';
+		/* param=val or param="val"? */
+		if (val == param+strlen(param)+1)
+			val[-1] = '=';
+		else if (val == param+strlen(param)+2) {
+			val[-2] = '=';
+			memmove(val-1, val, strlen(val)+1);
+			val--;
+		} else
+			BUG();
 	}
 
 	/* Handle obsolete-style parameters */
diff -Nru a/ipc/mqueue.c b/ipc/mqueue.c
--- a/ipc/mqueue.c	2004-10-28 22:25:58 -07:00
+++ b/ipc/mqueue.c	2004-10-28 22:25:58 -07:00
@@ -1219,11 +1219,8 @@
 	if (mqueue_inode_cachep == NULL)
 		return -ENOMEM;
 
+	/* ignore failues - they are not fatal */
 	mq_sysctl_table = register_sysctl_table(mq_sysctl_root, 0);
-	if (!mq_sysctl_table) {
-		error = -ENOMEM;
-		goto out_cache;
-	}
 
 	error = register_filesystem(&mqueue_fs_type);
 	if (error)
@@ -1243,8 +1240,8 @@
 out_filesystem:
 	unregister_filesystem(&mqueue_fs_type);
 out_sysctl:
-	unregister_sysctl_table(mq_sysctl_table);
-out_cache:
+	if (mq_sysctl_table)
+		unregister_sysctl_table(mq_sysctl_table);
 	if (kmem_cache_destroy(mqueue_inode_cachep)) {
 		printk(KERN_INFO
 			"mqueue_inode_cache: not all structures were freed\n");
diff -Nru a/ipc/msg.c b/ipc/msg.c
--- a/ipc/msg.c	2004-10-28 22:25:56 -07:00
+++ b/ipc/msg.c	2004-10-28 22:25:56 -07:00
@@ -381,7 +381,7 @@
 		int success_return;
 		if (!buf)
 			return -EFAULT;
-		if(cmd == MSG_STAT && msqid >= msg_ids.size)
+		if(cmd == MSG_STAT && msqid >= msg_ids.entries->size)
 			return -EINVAL;
 
 		memset(&tbuf,0,sizeof(tbuf));
diff -Nru a/ipc/sem.c b/ipc/sem.c
--- a/ipc/sem.c	2004-10-28 22:25:57 -07:00
+++ b/ipc/sem.c	2004-10-28 22:25:57 -07:00
@@ -524,7 +524,7 @@
 		struct semid64_ds tbuf;
 		int id;
 
-		if(semid >= sem_ids.size)
+		if(semid >= sem_ids.entries->size)
 			return -EINVAL;
 
 		memset(&tbuf,0,sizeof(tbuf));
diff -Nru a/ipc/util.c b/ipc/util.c
--- a/ipc/util.c	2004-10-28 22:25:59 -07:00
+++ b/ipc/util.c	2004-10-28 22:25:59 -07:00
@@ -62,7 +62,6 @@
 
 	if(size > IPCMNI)
 		size = IPCMNI;
-	ids->size = size;
 	ids->in_use = 0;
 	ids->max_id = -1;
 	ids->seq = 0;
@@ -74,14 +73,17 @@
 		 	ids->seq_max = seq_limit;
 	}
 
-	ids->entries = ipc_rcu_alloc(sizeof(struct ipc_id)*size);
+	ids->entries = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*size +
+				     sizeof(struct ipc_id_ary));
 
 	if(ids->entries == NULL) {
 		printk(KERN_ERR "ipc_init_ids() failed, ipc service disabled.\n");
-		ids->size = 0;
+		size = 0;
+		ids->entries = &ids->nullentry;
 	}
-	for(i=0;i<ids->size;i++)
-		ids->entries[i].p = NULL;
+	ids->entries->size = size;
+	for(i=0;i<size;i++)
+		ids->entries->p[i] = NULL;
 }
 
 /**
@@ -104,7 +106,7 @@
 	 * since ipc_ids.sem is held
 	 */
 	for (id = 0; id <= max_id; id++) {
-		p = ids->entries[id].p;
+		p = ids->entries->p[id];
 		if(p==NULL)
 			continue;
 		if (key == p->key)
@@ -118,36 +120,36 @@
  */
 static int grow_ary(struct ipc_ids* ids, int newsize)
 {
-	struct ipc_id* new;
-	struct ipc_id* old;
+	struct ipc_id_ary* new;
+	struct ipc_id_ary* old;
 	int i;
+	int size = ids->entries->size;
 
 	if(newsize > IPCMNI)
 		newsize = IPCMNI;
-	if(newsize <= ids->size)
+	if(newsize <= size)
 		return newsize;
 
-	new = ipc_rcu_alloc(sizeof(struct ipc_id)*newsize);
+	new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize +
+			    sizeof(struct ipc_id_ary));
 	if(new == NULL)
-		return ids->size;
-	memcpy(new, ids->entries, sizeof(struct ipc_id)*ids->size);
-	for(i=ids->size;i<newsize;i++) {
-		new[i].p = NULL;
+		return size;
+	new->size = newsize;
+	memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size +
+					sizeof(struct ipc_id_ary));
+	for(i=size;i<newsize;i++) {
+		new->p[i] = NULL;
 	}
 	old = ids->entries;
 
 	/*
-	 * before setting the ids->entries to the new array, there must be a
-	 * smp_wmb() to make sure the memcpyed contents of the new array are
-	 * visible before the new array becomes visible.
+	 * Use rcu_assign_pointer() to make sure the memcpyed contents
+	 * of the new array are visible before the new array becomes visible.
 	 */
-	smp_wmb();	/* prevent seeing new array uninitialized. */
-	ids->entries = new;
-	smp_wmb();	/* prevent indexing into old array based on new size. */
-	ids->size = newsize;
+	rcu_assign_pointer(ids->entries, new);
 
 	ipc_rcu_putref(old);
-	return ids->size;
+	return newsize;
 }
 
 /**
@@ -175,7 +177,7 @@
 	 * ipc_ids.sem is held
 	 */
 	for (id = 0; id < size; id++) {
-		if(ids->entries[id].p == NULL)
+		if(ids->entries->p[id] == NULL)
 			goto found;
 	}
 	return -1;
@@ -191,11 +193,11 @@
 	if(ids->seq > ids->seq_max)
 		ids->seq = 0;
 
-	new->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&new->lock);
 	new->deleted = 0;
 	rcu_read_lock();
 	spin_lock(&new->lock);
-	ids->entries[id].p = new;
+	ids->entries->p[id] = new;
 	return id;
 }
 
@@ -216,15 +218,15 @@
 {
 	struct kern_ipc_perm* p;
 	int lid = id % SEQ_MULTIPLIER;
-	if(lid >= ids->size)
+	if(lid >= ids->entries->size)
 		BUG();
 
 	/* 
 	 * do not need a rcu_dereference()() here to force ordering
 	 * on Alpha, since the ipc_ids.sem is held.
 	 */	
-	p = ids->entries[lid].p;
-	ids->entries[lid].p = NULL;
+	p = ids->entries->p[lid];
+	ids->entries->p[lid] = NULL;
 	if(p==NULL)
 		BUG();
 	ids->in_use--;
@@ -234,7 +236,7 @@
 			lid--;
 			if(lid == -1)
 				break;
-		} while (ids->entries[lid].p == NULL);
+		} while (ids->entries->p[lid] == NULL);
 		ids->max_id = lid;
 	}
 	p->deleted = 1;
@@ -493,9 +495,9 @@
 {
 	struct kern_ipc_perm* out;
 	int lid = id % SEQ_MULTIPLIER;
-	if(lid >= ids->size)
+	if(lid >= ids->entries->size)
 		return NULL;
-	out = ids->entries[lid].p;
+	out = ids->entries->p[lid];
 	return out;
 }
 
@@ -503,25 +505,15 @@
 {
 	struct kern_ipc_perm* out;
 	int lid = id % SEQ_MULTIPLIER;
-	struct ipc_id* entries;
+	struct ipc_id_ary* entries;
 
 	rcu_read_lock();
-	if(lid >= ids->size) {
+	entries = rcu_dereference(ids->entries);
+	if(lid >= entries->size) {
 		rcu_read_unlock();
 		return NULL;
 	}
-
-	/* 
-	 * Note: The following two read barriers are corresponding
-	 * to the two write barriers in grow_ary(). They guarantee 
-	 * the writes are seen in the same order on the read side. 
-	 * smp_rmb() has effect on all CPUs.  rcu_dereference()
-	 * is used if there are data dependency between two reads, and 
-	 * has effect only on Alpha.
-	 */
-	smp_rmb(); /* prevent indexing old array with new size */
-	entries = rcu_dereference(ids->entries);
-	out = entries[lid].p;
+	out = entries->p[lid];
 	if(out == NULL) {
 		rcu_read_unlock();
 		return NULL;
diff -Nru a/ipc/util.h b/ipc/util.h
--- a/ipc/util.h	2004-10-28 22:25:58 -07:00
+++ b/ipc/util.h	2004-10-28 22:25:58 -07:00
@@ -15,18 +15,19 @@
 void msg_init (void);
 void shm_init (void);
 
-struct ipc_ids {
+struct ipc_id_ary {
 	int size;
+	struct kern_ipc_perm *p[0];
+};
+
+struct ipc_ids {
 	int in_use;
 	int max_id;
 	unsigned short seq;
 	unsigned short seq_max;
 	struct semaphore sem;	
-	struct ipc_id* entries;
-};
-
-struct ipc_id {
-	struct kern_ipc_perm* p;
+	struct ipc_id_ary nullentry;
+	struct ipc_id_ary* entries;
 };
 
 void __init ipc_init_ids(struct ipc_ids* ids, int size);
diff -Nru a/kernel/acct.c b/kernel/acct.c
--- a/kernel/acct.c	2004-10-28 22:25:58 -07:00
+++ b/kernel/acct.c	2004-10-28 22:25:58 -07:00
@@ -427,8 +427,12 @@
 #endif
 	do_div(elapsed, AHZ);
 	ac.ac_btime = xtime.tv_sec - elapsed;
-	ac.ac_utime = encode_comp_t(jiffies_to_AHZ(current->utime));
-	ac.ac_stime = encode_comp_t(jiffies_to_AHZ(current->stime));
+	ac.ac_utime = encode_comp_t(jiffies_to_AHZ(
+					    current->signal->utime +
+					    current->group_leader->utime));
+	ac.ac_stime = encode_comp_t(jiffies_to_AHZ(
+					    current->signal->stime +
+					    current->group_leader->stime));
 	/* we really need to bite the bullet and change layout */
 	ac.ac_uid = current->uid;
 	ac.ac_gid = current->gid;
@@ -441,8 +445,8 @@
 	ac.ac_gid16 = current->gid;
 #endif
 #if ACCT_VERSION==3
-	ac.ac_pid = current->pid;
-	ac.ac_ppid = current->parent->pid;
+	ac.ac_pid = current->tgid;
+	ac.ac_ppid = current->parent->tgid;
 #endif
 
 	read_lock(&tasklist_lock);	/* pin current->signal */
@@ -475,8 +479,10 @@
 	ac.ac_mem = encode_comp_t(vsize);
 	ac.ac_io = encode_comp_t(0 /* current->io_usage */);	/* %% */
 	ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
-	ac.ac_minflt = encode_comp_t(current->min_flt);
-	ac.ac_majflt = encode_comp_t(current->maj_flt);
+	ac.ac_minflt = encode_comp_t(current->signal->min_flt +
+				     current->group_leader->min_flt);
+	ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
+				     current->group_leader->maj_flt);
 	ac.ac_swaps = encode_comp_t(0);
 	ac.ac_exitcode = exitcode;
 
diff -Nru a/kernel/cpu.c b/kernel/cpu.c
--- a/kernel/cpu.c	2004-10-28 22:25:59 -07:00
+++ b/kernel/cpu.c	2004-10-28 22:25:59 -07:00
@@ -57,34 +57,6 @@
 	write_unlock_irq(&tasklist_lock);
 }
 
-/* Notify userspace when a cpu event occurs, by running '/sbin/hotplug
- * cpu' with certain environment variables set.  */
-static int cpu_run_sbin_hotplug(unsigned int cpu, const char *action)
-{
-	char *argv[3], *envp[6], cpu_str[12], action_str[32], devpath_str[40];
-	int i;
-
-	sprintf(cpu_str, "CPU=%d", cpu);
-	sprintf(action_str, "ACTION=%s", action);
-	sprintf(devpath_str, "DEVPATH=devices/system/cpu/cpu%d", cpu);
-	
-	i = 0;
-	argv[i++] = hotplug_path;
-	argv[i++] = "cpu";
-	argv[i] = NULL;
-
-	i = 0;
-	/* minimal command environment */
-	envp[i++] = "HOME=/";
-	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-	envp[i++] = cpu_str;
-	envp[i++] = action_str;
-	envp[i++] = devpath_str;
-	envp[i] = NULL;
-
-	return call_usermodehelper(argv[0], argv, envp, 0);
-}
-
 /* Take this CPU down. */
 static int take_cpu_down(void *unused)
 {
@@ -170,8 +142,6 @@
 
 	check_for_tasks(cpu);
 
-	cpu_run_sbin_hotplug(cpu, "offline");
-
 out_thread:
 	err = kthread_stop(p);
 out_allowed:
@@ -179,11 +149,6 @@
 out:
 	unlock_cpu_hotplug();
 	return err;
-}
-#else
-static inline int cpu_run_sbin_hotplug(unsigned int cpu, const char *action)
-{
-	return 0;
 }
 #endif /*CONFIG_HOTPLUG_CPU*/
 
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	2004-10-28 22:25:59 -07:00
+++ b/kernel/exit.c	2004-10-28 22:25:59 -07:00
@@ -783,6 +783,7 @@
 asmlinkage NORET_TYPE void do_exit(long code)
 {
 	struct task_struct *tsk = current;
+	int group_dead;
 
 	profile_task_exit(tsk);
 
@@ -807,7 +808,9 @@
 		ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
 	}
 
-	acct_process(code);
+	group_dead = atomic_dec_and_test(&tsk->signal->live);
+	if (group_dead)
+		acct_process(code);
 	__exit_mm(tsk);
 
 	exit_sem(tsk);
@@ -817,7 +820,7 @@
 	exit_thread();
 	exit_keys(tsk);
 
-	if (tsk->signal->leader)
+	if (group_dead && tsk->signal->leader)
 		disassociate_ctty(1);
 
 	module_put(tsk->thread_info->exec_domain->module);
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	2004-10-28 22:25:57 -07:00
+++ b/kernel/fork.c	2004-10-28 22:25:57 -07:00
@@ -173,6 +173,7 @@
 	mm->free_area_cache = oldmm->mmap_base;
 	mm->map_count = 0;
 	mm->rss = 0;
+	mm->anon_rss = 0;
 	cpus_clear(mm->cpu_vm_mask);
 	mm->mm_rb = RB_ROOT;
 	rb_link = &mm->mm_rb.rb_node;
@@ -292,8 +293,8 @@
 	INIT_LIST_HEAD(&mm->mmlist);
 	mm->core_waiters = 0;
 	mm->nr_ptes = 0;
-	mm->page_table_lock = SPIN_LOCK_UNLOCKED;
-	mm->ioctx_list_lock = RW_LOCK_UNLOCKED;
+	spin_lock_init(&mm->page_table_lock);
+	rwlock_init(&mm->ioctx_list_lock);
 	mm->ioctx_list = NULL;
 	mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
@@ -493,7 +494,7 @@
 	/* We don't need to lock fs - think why ;-) */
 	if (fs) {
 		atomic_set(&fs->count, 1);
-		fs->lock = RW_LOCK_UNLOCKED;
+		rwlock_init(&fs->lock);
 		fs->umask = old->umask;
 		read_lock(&old->lock);
 		fs->rootmnt = mntget(old->rootmnt);
@@ -575,7 +576,7 @@
 
 	atomic_set(&newf->count, 1);
 
-	newf->file_lock	    = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&newf->file_lock);
 	newf->next_fd	    = 0;
 	newf->max_fds	    = NR_OPEN_DEFAULT;
 	newf->max_fdset	    = __FD_SETSIZE;
@@ -718,6 +719,7 @@
 
 	if (clone_flags & CLONE_THREAD) {
 		atomic_inc(&current->signal->count);
+		atomic_inc(&current->signal->live);
 		return 0;
 	}
 	sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL);
@@ -725,6 +727,7 @@
 	if (!sig)
 		return -ENOMEM;
 	atomic_set(&sig->count, 1);
+	atomic_set(&sig->live, 1);
 	sig->group_exit = 0;
 	sig->group_exit_code = 0;
 	sig->group_exit_task = NULL;
diff -Nru a/kernel/futex.c b/kernel/futex.c
--- a/kernel/futex.c	2004-10-28 22:25:57 -07:00
+++ b/kernel/futex.c	2004-10-28 22:25:57 -07:00
@@ -732,7 +732,7 @@
 
 	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
 		INIT_LIST_HEAD(&futex_queues[i].chain);
-		futex_queues[i].lock = SPIN_LOCK_UNLOCKED;
+		spin_lock_init(&futex_queues[i].lock);
 	}
 	return 0;
 }
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	2004-10-28 22:25:58 -07:00
+++ b/kernel/module.c	2004-10-28 22:25:59 -07:00
@@ -369,22 +369,6 @@
 }
 #endif /* CONFIG_SMP */
 
-static int add_attribute(struct module *mod, struct kernel_param *kp)
-{
-	struct module_attribute *a;
-	int retval;
-
-	a = &mod->mkobj->attr[mod->mkobj->num_attributes];
-	a->attr.name = (char *)kp->name;
-	a->attr.owner = mod;
-	a->attr.mode = kp->perm;
-	a->param = kp;
-	retval = sysfs_create_file(&mod->mkobj->kobj, &a->attr);
-	if (!retval)
-		mod->mkobj->num_attributes++;
-	return retval;
-}
-
 #ifdef CONFIG_MODULE_UNLOAD
 /* Init the unload section of the module. */
 static void module_unload_init(struct module *mod)
@@ -665,22 +649,16 @@
 }
 EXPORT_SYMBOL_GPL(symbol_put_addr);
 
-static int refcnt_get_fn(char *buffer, struct kernel_param *kp)
+static ssize_t show_refcnt(struct module *mod, char *buffer)
 {
-	struct module *mod = container_of(kp, struct module, refcnt_param);
-
-	/* sysfs holds one reference. */
-	return sprintf(buffer, "%u", module_refcount(mod)-1);
+	/* sysfs holds a reference */
+	return sprintf(buffer, "%u\n", module_refcount(mod)-1);
 }
 
-static inline int sysfs_unload_setup(struct module *mod)
-{
-	mod->refcnt_param.name = "refcnt";
-	mod->refcnt_param.perm = 0444;
-	mod->refcnt_param.get = refcnt_get_fn;
-
-	return add_attribute(mod, &mod->refcnt_param);
-}
+static struct module_attribute refcnt = {
+	.attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },
+	.show = show_refcnt,
+};
 
 #else /* !CONFIG_MODULE_UNLOAD */
 static void print_unload_info(struct seq_file *m, struct module *mod)
@@ -708,10 +686,6 @@
 	return -ENOSYS;
 }
 
-static inline int sysfs_unload_setup(struct module *mod)
-{
-	return 0;
-}
 #endif /* CONFIG_MODULE_UNLOAD */
 
 #ifdef CONFIG_OBSOLETE_MODPARM
@@ -1050,101 +1024,57 @@
 #endif /* CONFIG_KALLSYMS */
 
 
-
-
-#define to_module_attr(n) container_of(n, struct module_attribute, attr);
-
-static ssize_t module_attr_show(struct kobject *kobj,
-				struct attribute *attr,
-				char *buf)
+#ifdef CONFIG_MODULE_UNLOAD
+static inline int module_add_refcnt_attr(struct module *mod)
 {
-	int count;
-	struct module_attribute *attribute = to_module_attr(attr);
-
-	if (!attribute->param->get)
-		return -EPERM;
-
-	count = attribute->param->get(buf, attribute->param);
-	if (count > 0) {
-		strcat(buf, "\n");
-		++count;
-	}
-	return count;
+	return sysfs_create_file(&mod->mkobj->kobj, &refcnt.attr);
 }
-
-/* sysfs always hands a nul-terminated string in buf.  We rely on that. */
-static ssize_t module_attr_store(struct kobject *kobj,
-				 struct attribute *attr,
-				 const char *buf, size_t len)
+static void module_remove_refcnt_attr(struct module *mod)
 {
-	int err;
-	struct module_attribute *attribute = to_module_attr(attr);
-
-	if (!attribute->param->set)
-		return -EPERM;
-
-	err = attribute->param->set(buf, attribute->param);
-	if (!err)
-		return len;
-	return err;
+	return sysfs_remove_file(&mod->mkobj->kobj, &refcnt.attr);
 }
-
-static struct sysfs_ops module_sysfs_ops = {
-	.show = module_attr_show,
-	.store = module_attr_store,
-};
-
-static void module_kobj_release(struct kobject *kobj)
+#else
+static inline int module_add_refcnt_attr(struct module *mod)
+{
+	return 0;
+}
+static void module_remove_refcnt_attr(struct module *mod)
 {
-	kfree(container_of(kobj, struct module_kobject, kobj));
 }
+#endif
 
-static struct kobj_type module_ktype = {
-	.sysfs_ops =	&module_sysfs_ops,
-	.release =	&module_kobj_release,
-};
-static decl_subsys(module, &module_ktype, NULL);
 
 static int mod_sysfs_setup(struct module *mod,
 			   struct kernel_param *kparam,
 			   unsigned int num_params)
 {
-	unsigned int i;
 	int err;
 
-	/* We overallocate: not every param is in sysfs, and maybe no refcnt */
-	mod->mkobj = kmalloc(sizeof(*mod->mkobj)
-			     + sizeof(mod->mkobj->attr[0]) * (num_params+1),
-			     GFP_KERNEL);
+	mod->mkobj = kmalloc(sizeof(struct module_kobject), GFP_KERNEL);
 	if (!mod->mkobj)
 		return -ENOMEM;
 
 	memset(&mod->mkobj->kobj, 0, sizeof(mod->mkobj->kobj));
-	err = kobject_set_name(&mod->mkobj->kobj, mod->name);
+	err = kobject_set_name(&mod->mkobj->kobj, "%s", mod->name);
 	if (err)
 		goto out;
 	kobj_set_kset_s(mod->mkobj, module_subsys);
+	mod->mkobj->mod = mod;
 	err = kobject_register(&mod->mkobj->kobj);
 	if (err)
 		goto out;
 
-	mod->mkobj->num_attributes = 0;
+	err = module_add_refcnt_attr(mod);
+	if (err)
+		goto out_unreg;
 
-	for (i = 0; i < num_params; i++) {
-		if (kparam[i].perm) {
-			err = add_attribute(mod, &kparam[i]);
-			if (err)
-				goto out_unreg;
-		}
-	}
-	err = sysfs_unload_setup(mod);
+	err = module_param_sysfs_setup(mod, kparam, num_params);
 	if (err)
 		goto out_unreg;
+
 	return 0;
 
 out_unreg:
-	for (i = 0; i < mod->mkobj->num_attributes; i++)
-		sysfs_remove_file(&mod->mkobj->kobj,&mod->mkobj->attr[i].attr);
 	/* Calls module_kobj_release */
 	kobject_unregister(&mod->mkobj->kobj);
 	return err;
@@ -1155,9 +1085,9 @@
 
 static void mod_kobject_remove(struct module *mod)
 {
-	unsigned int i;
-	for (i = 0; i < mod->mkobj->num_attributes; i++)
-		sysfs_remove_file(&mod->mkobj->kobj,&mod->mkobj->attr[i].attr);
+	module_remove_refcnt_attr(mod);
+	module_param_sysfs_remove(mod);
+
 	/* Calls module_kobj_release */
 	kobject_unregister(&mod->mkobj->kobj);
 }
@@ -1904,6 +1834,16 @@
 }
 
 #ifdef CONFIG_KALLSYMS
+/*
+ * This ignores the intensely annoying "mapping symbols" found
+ * in ARM ELF files: $a, $t and $d.
+ */
+static inline int is_arm_mapping_symbol(const char *str)
+{
+	return str[0] == '$' && strchr("atd", str[1]) 
+	       && (str[2] == '\0' || str[2] == '.');
+}
+
 static const char *get_ksymbol(struct module *mod,
 			       unsigned long addr,
 			       unsigned long *size,
@@ -1928,11 +1868,13 @@
 		 * and inserted at a whim. */
 		if (mod->symtab[i].st_value <= addr
 		    && mod->symtab[i].st_value > mod->symtab[best].st_value
-		    && *(mod->strtab + mod->symtab[i].st_name) != '\0' )
+		    && *(mod->strtab + mod->symtab[i].st_name) != '\0'
+		    && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
 			best = i;
 		if (mod->symtab[i].st_value > addr
 		    && mod->symtab[i].st_value < nextval
-		    && *(mod->strtab + mod->symtab[i].st_name) != '\0')
+		    && *(mod->strtab + mod->symtab[i].st_name) != '\0'
+		    && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
 			nextval = mod->symtab[i].st_value;
 	}
 
@@ -2166,9 +2108,3 @@
 void struct_module(struct module *mod) { return; }
 EXPORT_SYMBOL(struct_module);
 #endif
-
-static int __init modules_init(void)
-{
-	return subsystem_register(&module_subsys);
-}
-__initcall(modules_init);
diff -Nru a/kernel/params.c b/kernel/params.c
--- a/kernel/params.c	2004-10-28 22:25:59 -07:00
+++ b/kernel/params.c	2004-10-28 22:25:59 -07:00
@@ -15,11 +15,14 @@
     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/config.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
 
 #if 0
 #define DEBUGP printk
@@ -345,6 +348,394 @@
 	struct kparam_string *kps = kp->arg;
 	return strlcpy(buffer, kps->string, kps->maxlen);
 }
+
+/* sysfs output in /sys/modules/XYZ/parameters/ */
+
+extern struct kernel_param __start___param[], __stop___param[];
+
+#define MAX_KBUILD_MODNAME KOBJ_NAME_LEN
+
+struct param_attribute
+{
+	struct attribute attr;
+	struct kernel_param *param;
+};
+
+struct param_kobject
+{
+	struct kobject kobj;
+
+	unsigned int num_attributes;
+	struct param_attribute attr[0];
+};
+
+#define to_param_attr(n) container_of(n, struct param_attribute, attr);
+
+static ssize_t param_attr_show(struct kobject *kobj,
+			       struct attribute *attr,
+			       char *buf)
+{
+	int count;
+	struct param_attribute *attribute = to_param_attr(attr);
+
+	if (!attribute->param->get)
+		return -EPERM;
+
+	count = attribute->param->get(buf, attribute->param);
+	if (count > 0) {
+		strcat(buf, "\n");
+		++count;
+	}
+	return count;
+}
+
+/* sysfs always hands a nul-terminated string in buf.  We rely on that. */
+static ssize_t param_attr_store(struct kobject *kobj,
+				struct attribute *attr,
+				const char *buf, size_t len)
+{
+ 	int err;
+	struct param_attribute *attribute = to_param_attr(attr);
+
+	if (!attribute->param->set)
+		return -EPERM;
+
+	err = attribute->param->set(buf, attribute->param);
+	if (!err)
+		return len;
+	return err;
+}
+
+
+static struct sysfs_ops param_sysfs_ops = {
+	.show = param_attr_show,
+	.store = param_attr_store,
+};
+
+static void param_kobj_release(struct kobject *kobj)
+{
+	kfree(container_of(kobj, struct param_kobject, kobj));
+}
+
+static struct kobj_type param_ktype = {
+	.sysfs_ops =	&param_sysfs_ops,
+	.release =	&param_kobj_release,
+};
+
+static struct kset param_kset = {
+	.subsys =	&module_subsys,
+	.ktype =	&param_ktype,
+};
+
+#ifdef CONFIG_MODULES
+#define __modinit
+#else
+#define __modinit __init
+#endif
+
+/*
+ * param_add_attribute - actually adds an parameter to sysfs
+ * @mod: owner of parameter
+ * @pk: param_kobject the attribute shall be assigned to.
+ *      One per module, one per KBUILD_MODNAME.
+ * @kp: kernel_param to be added
+ * @skip: offset where the parameter name start in kp->name.
+ * Needed for built-in modules
+ *
+ * Fill in data into appropriate &pk->attr[], and create sysfs file.
+ */
+static __modinit int param_add_attribute(struct module *mod,
+					 struct param_kobject *pk,
+					 struct kernel_param *kp,
+					 unsigned int skip)
+{
+	struct param_attribute *a;
+	int err;
+
+	a = &pk->attr[pk->num_attributes];
+	a->attr.name = (char *) &kp->name[skip];
+	a->attr.owner = mod;
+	a->attr.mode = kp->perm;
+	a->param = kp;
+	err = sysfs_create_file(&pk->kobj, &a->attr);
+	if (!err)
+		pk->num_attributes++;
+	return err;
+}
+
+/*
+ * param_sysfs_remove - remove sysfs support for one module or KBUILD_MODNAME
+ * @pk: struct param_kobject which is to be removed
+ *
+ * Called when an error in registration occurs or a module is removed
+ * from the system.
+ */
+static __modinit void param_sysfs_remove(struct param_kobject *pk)
+{
+	unsigned int i;
+	for (i = 0; i < pk->num_attributes; i++)
+		sysfs_remove_file(&pk->kobj,&pk->attr[i].attr);
+
+	/* Calls param_kobj_release */
+	kobject_unregister(&pk->kobj);
+}
+
+
+/*
+ * param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME
+ * @mk: struct module_kobject (contains parent kobject)
+ * @kparam: array of struct kernel_param, the actual parameter definitions
+ * @num_params: number of entries in array
+ * @name_skip: offset where the parameter name start in kparam[].name. Needed for built-in "modules"
+ *
+ * Create a kobject for a (per-module) group of parameters, and create files
+ * in sysfs. A pointer to the param_kobject is returned on success,
+ * NULL if there's no parameter to export, or other ERR_PTR(err).
+ */
+static __modinit struct param_kobject *
+param_sysfs_setup(struct module_kobject *mk,
+		  struct kernel_param *kparam,
+		  unsigned int num_params,
+		  unsigned int name_skip)
+{
+	struct param_kobject *pk;
+	unsigned int valid_attrs = 0;
+	unsigned int i;
+	int err;
+
+	for (i=0; i<num_params; i++) {
+		if (kparam[i].perm)
+			valid_attrs++;
+	}
+
+	if (!valid_attrs)
+		return NULL;
+
+	pk = kmalloc(sizeof(struct param_kobject)
+		     + sizeof(struct param_attribute) * valid_attrs,
+		     GFP_KERNEL);
+	if (!pk)
+		return ERR_PTR(-ENOMEM);
+	memset(pk, 0, sizeof(struct param_kobject)
+	       + sizeof(struct param_attribute) * valid_attrs);
+
+	err = kobject_set_name(&pk->kobj, "parameters");
+	if (err)
+		goto out;
+
+	pk->kobj.kset = &param_kset;
+	pk->kobj.parent = &mk->kobj;
+	err = kobject_register(&pk->kobj);
+	if (err)
+		goto out;
+
+	for (i = 0; i < num_params; i++) {
+		if (kparam[i].perm) {
+			err = param_add_attribute(mk->mod, pk,
+						  &kparam[i], name_skip);
+			if (err)
+				goto out_unreg;
+		}
+	}
+
+	return pk;
+
+out_unreg:
+	param_sysfs_remove(pk);
+	return ERR_PTR(err);
+
+out:
+	kfree(pk);
+	return ERR_PTR(err);
+}
+
+
+#ifdef CONFIG_MODULES
+
+/*
+ * module_param_sysfs_setup - setup sysfs support for one module
+ * @mod: module
+ * @kparam: module parameters (array)
+ * @num_params: number of module parameters
+ *
+ * Adds sysfs entries for module parameters, and creates a link from
+ * /sys/module/[mod->name]/parameters to /sys/parameters/[mod->name]/
+ */
+int module_param_sysfs_setup(struct module *mod,
+			     struct kernel_param *kparam,
+			     unsigned int num_params)
+{
+	struct param_kobject *pk;
+
+	pk = param_sysfs_setup(mod->mkobj, kparam, num_params, 0);
+	if (IS_ERR(pk))
+		return PTR_ERR(pk);
+
+	mod->params_kobject = pk;
+	return 0;
+}
+
+/*
+ * module_param_sysfs_remove - remove sysfs support for one module
+ * @mod: module
+ *
+ * Remove sysfs entries for module parameters and the corresponding
+ * kobject.
+ */
+void module_param_sysfs_remove(struct module *mod)
+{
+	if (mod->params_kobject) {
+		param_sysfs_remove(mod->params_kobject);
+		mod->params_kobject = NULL;
+	}
+}
+#endif
+
+/*
+ * kernel_param_sysfs_setup - wrapper for built-in params support
+ */
+static void __init kernel_param_sysfs_setup(const char *name,
+					    struct kernel_param *kparam,
+					    unsigned int num_params,
+					    unsigned int name_skip)
+{
+	struct module_kobject *mk;
+
+	mk = kmalloc(sizeof(struct module_kobject), GFP_KERNEL);
+	memset(mk, 0, sizeof(struct module_kobject));
+
+	mk->mod = THIS_MODULE;
+	kobj_set_kset_s(mk, module_subsys);
+	kobject_set_name(&mk->kobj, name);
+	kobject_register(&mk->kobj);
+
+	/* no need to keep the kobject if no parameter is exported */
+	if (!param_sysfs_setup(mk, kparam, num_params, name_skip))
+		kobject_unregister(&mk->kobj);
+}
+
+/*
+ * param_sysfs_builtin - add contents in /sys/parameters for built-in modules
+ *
+ * Add module_parameters to sysfs for "modules" built into the kernel.
+ *
+ * The "module" name (KBUILD_MODNAME) is stored before a dot, the
+ * "parameter" name is stored behind a dot in kernel_param->name. So,
+ * extract the "module" name for all built-in kernel_param-eters,
+ * and for all who have the same, call kernel_param_sysfs_setup.
+ */
+static void __init param_sysfs_builtin(void)
+{
+	struct kernel_param *kp, *kp_begin = NULL;
+	unsigned int i, name_len, count = 0;
+	char modname[MAX_KBUILD_MODNAME + 1] = "";
+
+	for (i=0; i < __stop___param - __start___param; i++) {
+		char *dot;
+
+		kp = &__start___param[i];
+
+		/* We do not handle args without periods. */
+		dot = memchr(kp->name, '.', MAX_KBUILD_MODNAME);
+		if (!dot) {
+			DEBUGP("couldn't find period in %s\n", kp->name);
+			continue;
+		}
+		name_len = dot - kp->name;
+
+ 		/* new kbuild_modname? */
+		if (strlen(modname) != name_len
+		    || strncmp(modname, kp->name, name_len) != 0) {
+			/* add a new kobject for previous kernel_params. */
+			if (count)
+				kernel_param_sysfs_setup(modname,
+							 kp_begin,
+							 count,
+							 strlen(modname)+1);
+
+			strncpy(modname, kp->name, name_len);
+			modname[name_len] = '\0';
+			count = 0;
+			kp_begin = kp;
+		}
+		count++;
+	}
+
+	/* last kernel_params need to be registered as well */
+	if (count)
+		kernel_param_sysfs_setup(modname, kp_begin, count,
+					 strlen(modname)+1);
+}
+
+
+/* module-related sysfs stuff */
+#ifdef CONFIG_MODULES
+
+#define to_module_attr(n) container_of(n, struct module_attribute, attr);
+#define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
+
+static ssize_t module_attr_show(struct kobject *kobj,
+				struct attribute *attr,
+				char *buf)
+{
+	struct module_attribute *attribute;
+	struct module_kobject *mk;
+	int ret;
+
+	attribute = to_module_attr(attr);
+	mk = to_module_kobject(kobj);
+
+	if (!attribute->show)
+		return -EPERM;
+
+	if (!try_module_get(mk->mod))
+		return -ENODEV;
+
+	ret = attribute->show(mk->mod, buf);
+
+	module_put(mk->mod);
+
+	return ret;
+}
+
+static struct sysfs_ops module_sysfs_ops = {
+	.show = module_attr_show,
+	.store = NULL,
+};
+
+#else
+static struct sysfs_ops module_sysfs_ops = {
+	.show = NULL,
+	.store = NULL,
+};
+#endif
+
+static void module_kobj_release(struct kobject *kobj)
+{
+	kfree(container_of(kobj, struct module_kobject, kobj));
+}
+
+static struct kobj_type module_ktype = {
+	.sysfs_ops =	&module_sysfs_ops,
+	.release =	&module_kobj_release,
+};
+
+decl_subsys(module, &module_ktype, NULL);
+
+/*
+ * param_sysfs_init - wrapper for built-in params support
+ */
+static int __init param_sysfs_init(void)
+{
+	subsystem_register(&module_subsys);
+	kobject_set_name(&param_kset.kobj, "parameters");
+	kset_init(&param_kset);
+
+	param_sysfs_builtin();
+
+	return 0;
+}
+__initcall(param_sysfs_init);
 
 EXPORT_SYMBOL(param_set_byte);
 EXPORT_SYMBOL(param_get_byte);
diff -Nru a/kernel/posix-timers.c b/kernel/posix-timers.c
--- a/kernel/posix-timers.c	2004-10-28 22:25:58 -07:00
+++ b/kernel/posix-timers.c	2004-10-28 22:25:58 -07:00
@@ -384,32 +384,10 @@
 		unlock_timer(timr, flags);
 }
 
-/*
- * Notify the task and set up the timer for the next expiration (if
- * applicable).  This function requires that the k_itimer structure
- * it_lock is taken.  This code will requeue the timer only if we get
- * either an error return or a flag (ret > 0) from send_seg_info
- * indicating that the signal was either not queued or was queued
- * without an info block.  In this case, we will not get a call back to
- * do_schedule_next_timer() so we do it here.  This should be rare...
-
- * An interesting problem can occur if, while a signal, and thus a call
- * back is pending, the timer is rearmed, i.e. stopped and restarted.
- * We then need to sort out the call back and do the right thing.  What
- * we do is to put a counter in the info block and match it with the
- * timers copy on the call back.  If they don't match, we just ignore
- * the call back.  The counter is local to the timer and we use odd to
- * indicate a call back is pending.  Note that we do allow the timer to 
- * be deleted while a signal is pending.  The standard says we can
- * allow that signal to be delivered, and we do. 
- */
-
-static void timer_notify_task(struct k_itimer *timr)
+int posix_timer_event(struct k_itimer *timr,int si_private)
 {
-	int ret;
-
 	memset(&timr->sigq->info, 0, sizeof(siginfo_t));
-
+	timr->sigq->info.si_sys_private = si_private;
 	/*
 	 * Send signal to the process that owns this timer.
 
@@ -424,12 +402,6 @@
 	timr->sigq->info.si_code = SI_TIMER;
 	timr->sigq->info.si_tid = timr->it_id;
 	timr->sigq->info.si_value = timr->it_sigev_value;
-	if (timr->it_incr)
-		timr->sigq->info.si_sys_private = ++timr->it_requeue_pending;
-	else {
-		remove_from_abslist(timr);
-	}
-
 	if (timr->it_sigev_notify & SIGEV_THREAD_ID) {
 		if (unlikely(timr->it_process->flags & PF_EXITING)) {
 			timr->it_sigev_notify = SIGEV_SIGNAL;
@@ -437,28 +409,20 @@
 			timr->it_process = timr->it_process->group_leader;
 			goto group;
 		}
-		ret = send_sigqueue(timr->it_sigev_signo, timr->sigq,
+		return send_sigqueue(timr->it_sigev_signo, timr->sigq,
 			timr->it_process);
 	}
 	else {
 	group:
-		ret = send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
+		return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
 			timr->it_process);
 	}
-	if (ret) {
-		/*
-		 * signal was not sent because of sig_ignor
-		 * we will not get a call back to restart it AND
-		 * it should be restarted.
-		 */
-		schedule_next_timer(timr);
-	}
 }
 
 /*
  * This function gets called when a POSIX.1b interval timer expires.  It
  * is used as a callback from the kernel internal timer.  The
- * run_timer_list code ALWAYS calls with interrutps on.
+ * run_timer_list code ALWAYS calls with interrupts on.
 
  * This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
  */
@@ -501,8 +465,23 @@
 		spin_unlock(&abs_list.lock);
 
 	}
-	if (do_notify)
-		timer_notify_task(timr);
+	if (do_notify)  {
+		int si_private=0;
+
+		if (timr->it_incr)
+			si_private = ++timr->it_requeue_pending;
+		else {
+			remove_from_abslist(timr);
+		}
+
+		if (posix_timer_event(timr, si_private))
+			/*
+			 * signal was not sent because of sig_ignor
+			 * we will not get a call back to restart it AND
+			 * it should be restarted.
+			 */
+			schedule_next_timer(timr);
+	}
 	unlock_timer(timr, flags); /* hold thru abs lock to keep irq off */
 }
 
@@ -585,10 +564,6 @@
 				!posix_clocks[which_clock].res)
 		return -EINVAL;
 
-	if (posix_clocks[which_clock].timer_create)
-		return posix_clocks[which_clock].timer_create(which_clock,
-				timer_event_spec, created_timer_id);
-
 	new_timer = alloc_posix_timer();
 	if (unlikely(!new_timer))
 		return -EAGAIN;
@@ -620,11 +595,17 @@
 	new_timer->it_clock = which_clock;
 	new_timer->it_incr = 0;
 	new_timer->it_overrun = -1;
-	init_timer(&new_timer->it_timer);
-	new_timer->it_timer.expires = 0;
-	new_timer->it_timer.data = (unsigned long) new_timer;
-	new_timer->it_timer.function = posix_timer_fn;
-	set_timer_inactive(new_timer);
+	if (posix_clocks[which_clock].timer_create) {
+		error =  posix_clocks[which_clock].timer_create(new_timer);
+		if (error)
+			goto out;
+	} else {
+		init_timer(&new_timer->it_timer);
+		new_timer->it_timer.expires = 0;
+		new_timer->it_timer.data = (unsigned long) new_timer;
+		new_timer->it_timer.function = posix_timer_fn;
+		set_timer_inactive(new_timer);
+	}
 
 	/*
 	 * return the timer_id now.  The next step is hard to
@@ -1239,9 +1220,7 @@
 	return -EINVAL;
 }
 
-int do_posix_clock_notimer_create(int which_clock,
-		struct sigevent __user *timer_event_spec,
-		timer_t __user *created_timer_id) {
+int do_posix_clock_notimer_create(struct k_itimer *timer) {
 	return -EINVAL;
 }
 
diff -Nru a/kernel/power/Kconfig b/kernel/power/Kconfig
--- a/kernel/power/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/kernel/power/Kconfig	2004-10-28 22:25:59 -07:00
@@ -30,7 +30,8 @@
 	bool "Software Suspend (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && PM && SWAP
 	---help---
-	  Enable the possibilty of suspendig machine. It doesn't need APM.
+	  Enable the possibility of suspending the machine.
+	  It doesn't need APM.
 	  You may suspend your machine by 'swsusp' or 'shutdown -z <time>' 
 	  (patch for sysvinit needed). 
 
diff -Nru a/kernel/power/disk.c b/kernel/power/disk.c
--- a/kernel/power/disk.c	2004-10-28 22:25:56 -07:00
+++ b/kernel/power/disk.c	2004-10-28 22:25:56 -07:00
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2003 Patrick Mochel
  * Copyright (c) 2003 Open Source Development Lab
+ * Copyright (c) 2004 Pavel Machek <pavel@suse.cz>
  *
  * This file is released under the GPLv2.
  *
@@ -41,7 +42,7 @@
  *	there ain't no turning back.
  */
 
-static int power_down(u32 mode)
+static void power_down(u32 mode)
 {
 	unsigned long flags;
 	int error = 0;
@@ -67,7 +68,6 @@
 	   after resume. */
 	printk(KERN_CRIT "Please power me down manually\n");
 	while(1);
-	return 0;
 }
 
 
@@ -162,7 +162,7 @@
  *
  *	If we're going through the firmware, then get it over with quickly.
  *
- *	If not, then call pmdis to do it's thing, then figure out how
+ *	If not, then call swsusp to do it's thing, then figure out how
  *	to power down the system.
  */
 
@@ -184,18 +184,9 @@
 
 	if (in_suspend) {
 		pr_debug("PM: writing image.\n");
-
-		/*
-		 * FIXME: Leftover from swsusp. Are they necessary?
-		 */
-		mb();
-		barrier();
-
 		error = swsusp_write();
-		if (!error) {
-			error = power_down(pm_disk_mode);
-			pr_debug("PM: Power down failed.\n");
-		}
+		if (!error)
+			power_down(pm_disk_mode);
 	} else
 		pr_debug("PM: Image restored successfully.\n");
 	swsusp_free();
diff -Nru a/kernel/power/poweroff.c b/kernel/power/poweroff.c
--- a/kernel/power/poweroff.c	2004-10-28 22:25:58 -07:00
+++ b/kernel/power/poweroff.c	2004-10-28 22:25:58 -07:00
@@ -32,7 +32,7 @@
 static struct sysrq_key_op	sysrq_poweroff_op = {
 	.handler        = handle_poweroff,
 	.help_msg       = "powerOff",
-	.action_msg     = "Power Off\n"
+	.action_msg     = "Power Off"
 };
 
 static int pm_sysrq_init(void)
diff -Nru a/kernel/power/swsusp.c b/kernel/power/swsusp.c
--- a/kernel/power/swsusp.c	2004-10-28 22:25:57 -07:00
+++ b/kernel/power/swsusp.c	2004-10-28 22:25:57 -07:00
@@ -847,8 +847,11 @@
 {
 	int error = 0;
 
-	if ((error = swsusp_swap_check()))
+	if ((error = swsusp_swap_check())) {
+		printk(KERN_ERR "swsusp: FATAL: cannot find swap device, try "
+				"swapon -a!\n");
 		return error;
+	}
 	return suspend_prepare_image();
 }
 
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	2004-10-28 22:25:59 -07:00
+++ b/kernel/ptrace.c	2004-10-28 22:25:59 -07:00
@@ -38,6 +38,12 @@
 	SET_LINKS(child);
 }
  
+static inline int pending_resume_signal(struct sigpending *pending)
+{
+#define M(sig) (1UL << ((sig)-1))
+	return sigtestsetmask(&pending->signal, M(SIGCONT) | M(SIGKILL));
+}
+
 /*
  * unptrace a task: move it back to its original parent and
  * remove it from the ptrace list.
@@ -61,8 +67,16 @@
 		 * Turn a tracing stop into a normal stop now,
 		 * since with no tracer there would be no way
 		 * to wake it up with SIGCONT or SIGKILL.
+		 * If there was a signal sent that would resume the child,
+		 * but didn't because it was in TASK_TRACED, resume it now.
 		 */
+		spin_lock(&child->sighand->siglock);
 		child->state = TASK_STOPPED;
+		if (pending_resume_signal(&child->pending) ||
+		    pending_resume_signal(&child->signal->shared_pending)) {
+			signal_wake_up(child, 1);
+		}
+		spin_unlock(&child->sighand->siglock);
 	}
 }
 
@@ -132,7 +146,8 @@
 		goto bad;
 
 	/* Go */
-	task->ptrace |= PT_PTRACED | PT_ATTACHED;
+	task->ptrace |= PT_PTRACED | ((task->real_parent != current)
+				      ? PT_ATTACHED : 0);
 	if (capable(CAP_SYS_PTRACE))
 		task->ptrace |= PT_PTRACE_CAP;
 	task_unlock(task);
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	2004-10-28 22:25:59 -07:00
+++ b/kernel/sched.c	2004-10-28 22:25:59 -07:00
@@ -895,8 +895,6 @@
 	preempt_enable();
 }
 
-EXPORT_SYMBOL_GPL(kick_process);
-
 /*
  * Return a low guess at the load of a migration-source cpu.
  *
@@ -1973,11 +1971,19 @@
 			 */
 			sd->nr_balance_failed = sd->cache_nice_tries;
 		}
-	} else
-		sd->nr_balance_failed = 0;
 
-	/* We were unbalanced, so reset the balancing interval */
-	sd->balance_interval = sd->min_interval;
+		/*
+		 * We were unbalanced, but unsuccessful in move_tasks(),
+		 * so bump the balance_interval to lessen the lock contention.
+		 */
+		if (sd->balance_interval < sd->max_interval)
+			sd->balance_interval++;
+	} else {
+                sd->nr_balance_failed = 0;
+
+		/* We were unbalanced, so reset the balancing interval */
+		sd->balance_interval = sd->min_interval;
+	}
 
 	return nr_moved;
 
@@ -2052,70 +2058,85 @@
 	}
 }
 
+#ifdef CONFIG_SCHED_SMT
+static int cpu_and_siblings_are_idle(int cpu)
+{
+	int sib;
+	for_each_cpu_mask(sib, cpu_sibling_map[cpu]) {
+		if (idle_cpu(sib))
+			continue;
+		return 0;
+	}
+
+	return 1;
+}
+#else
+#define cpu_and_siblings_are_idle(A) idle_cpu(A)
+#endif
+
+
 /*
- * active_load_balance is run by migration threads. It pushes a running
- * task off the cpu. It can be required to correctly have at least 1 task
- * running on each physical CPU where possible, and not have a physical /
- * logical imbalance.
+ * active_load_balance is run by migration threads. It pushes running tasks
+ * off the busiest CPU onto idle CPUs. It requires at least 1 task to be
+ * running on each physical CPU where possible, and avoids physical /
+ * logical imbalances.
  *
- * Called with busiest locked.
+ * Called with busiest_rq locked.
  */
-static void active_load_balance(runqueue_t *busiest, int busiest_cpu)
+static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu)
 {
 	struct sched_domain *sd;
-	struct sched_group *group, *busy_group;
-	int i;
+	struct sched_group *cpu_group;
+	cpumask_t visited_cpus;
 
-	schedstat_inc(busiest, alb_cnt);
-	if (busiest->nr_running <= 1)
-		return;
-
-	for_each_domain(busiest_cpu, sd)
-		if (cpu_isset(busiest->push_cpu, sd->span))
-			break;
-	if (!sd)
-		return;
-
-	group = sd->groups;
-	while (!cpu_isset(busiest_cpu, group->cpumask))
-		group = group->next;
-	busy_group = group;
-
-	group = sd->groups;
-	do {
-		runqueue_t *rq;
-		int push_cpu = 0;
-
-		if (group == busy_group)
-			goto next_group;
+	schedstat_inc(busiest_rq, alb_cnt);
+	/*
+	 * Search for suitable CPUs to push tasks to in successively higher
+	 * domains with SD_LOAD_BALANCE set.
+	 */
+	visited_cpus = CPU_MASK_NONE;
+	for_each_domain(busiest_cpu, sd) {
+		if (!(sd->flags & SD_LOAD_BALANCE) || busiest_rq->nr_running <= 1)
+			break; /* no more domains to search or no more tasks to move */
+
+		cpu_group = sd->groups;
+		do { /* sched_groups should either use list_heads or be merged into the domains structure */
+			int cpu, target_cpu = -1;
+			runqueue_t *target_rq;
+
+			for_each_cpu_mask(cpu, cpu_group->cpumask) {
+				if (cpu_isset(cpu, visited_cpus) || cpu == busiest_cpu ||
+				    !cpu_and_siblings_are_idle(cpu)) {
+					cpu_set(cpu, visited_cpus);
+					continue;
+				}
+				target_cpu = cpu;
+				break;
+			}
+			if (target_cpu == -1)
+				goto next_group; /* failed to find a suitable target cpu in this domain */
 
-		for_each_cpu_mask(i, group->cpumask) {
-			if (!idle_cpu(i))
-				goto next_group;
-			push_cpu = i;
-		}
+			target_rq = cpu_rq(target_cpu);
 
-		rq = cpu_rq(push_cpu);
+			/*
+			 * This condition is "impossible", if it occurs we need to fix it
+			 * Reported by Bjorn Helgaas on a 128-cpu setup.
+			 */
+			BUG_ON(busiest_rq == target_rq);
 
-		/*
-		 * This condition is "impossible", but since load
-		 * balancing is inherently a bit racy and statistical,
-		 * it can trigger.. Reported by Bjorn Helgaas on a
-		 * 128-cpu setup.
-		 */
-		if (unlikely(busiest == rq))
-			goto next_group;
-		double_lock_balance(busiest, rq);
-		if (move_tasks(rq, push_cpu, busiest, 1, sd, SCHED_IDLE)) {
-			schedstat_inc(busiest, alb_lost);
-			schedstat_inc(rq, alb_gained);
-		} else {
-			schedstat_inc(busiest, alb_failed);
-		}
-		spin_unlock(&rq->lock);
+			/* move a task from busiest_rq to target_rq */
+			double_lock_balance(busiest_rq, target_rq);
+			if (move_tasks(target_rq, target_cpu, busiest_rq, 1, sd, SCHED_IDLE)) {
+				schedstat_inc(busiest_rq, alb_lost);
+				schedstat_inc(target_rq, alb_gained);
+			} else {
+				schedstat_inc(busiest_rq, alb_failed);
+			}
+			spin_unlock(&target_rq->lock);
 next_group:
-		group = group->next;
-	} while (group != sd->groups);
+			cpu_group = cpu_group->next;
+		} while (cpu_group != sd->groups && busiest_rq->nr_running > 1);
+	}
 }
 
 /*
@@ -2502,6 +2523,8 @@
 need_resched:
 	preempt_disable();
 	prev = current;
+	release_kernel_lock(prev);
+need_resched_nonpreemptible:
 	rq = this_rq();
 
 	/*
@@ -2513,7 +2536,6 @@
 		dump_stack();
 	}
 
-	release_kernel_lock(prev);
 	schedstat_inc(rq, sched_cnt);
 	now = sched_clock();
 	if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG))
@@ -2565,7 +2587,6 @@
 		}
 	} else {
 		if (dependent_sleeper(cpu, rq)) {
-			schedstat_inc(rq, sched_goidle);
 			next = rq->idle;
 			goto switch_tasks;
 		}
@@ -2609,6 +2630,8 @@
 	}
 	next->activated = 0;
 switch_tasks:
+	if (next == rq->idle)
+		schedstat_inc(rq, sched_goidle);
 	prefetch(next);
 	clear_tsk_need_resched(prev);
 	rcu_qsctr_inc(task_cpu(prev));
@@ -2636,7 +2659,9 @@
 	} else
 		spin_unlock_irq(&rq->lock);
 
-	reacquire_kernel_lock(current);
+	prev = current;
+	if (unlikely(reacquire_kernel_lock(prev) < 0))
+		goto need_resched_nonpreemptible;
 	preempt_enable_no_resched();
 	if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
 		goto need_resched;
@@ -3038,7 +3063,7 @@
 {
 	struct sched_param lp;
 	int retval = -EINVAL;
-	int oldprio;
+	int oldprio, oldpolicy = -1;
 	prio_array_t *array;
 	unsigned long flags;
 	runqueue_t *rq;
@@ -3060,23 +3085,17 @@
 
 	retval = -ESRCH;
 	if (!p)
-		goto out_unlock_tasklist;
-
-	/*
-	 * To be able to change p->policy safely, the apropriate
-	 * runqueue lock must be held.
-	 */
-	rq = task_rq_lock(p, &flags);
-
+		goto out_unlock;
+recheck:
+	/* double check policy once rq lock held */
 	if (policy < 0)
-		policy = p->policy;
+		policy = oldpolicy = p->policy;
 	else {
 		retval = -EINVAL;
 		if (policy != SCHED_FIFO && policy != SCHED_RR &&
 				policy != SCHED_NORMAL)
 			goto out_unlock;
 	}
-
 	/*
 	 * Valid priorities for SCHED_FIFO and SCHED_RR are
 	 * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0.
@@ -3098,7 +3117,17 @@
 	retval = security_task_setscheduler(p, policy, &lp);
 	if (retval)
 		goto out_unlock;
-
+	/*
+	 * To be able to change p->policy safely, the apropriate
+	 * runqueue lock must be held.
+	 */
+	rq = task_rq_lock(p, &flags);
+	/* recheck policy now with rq lock held */
+	if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
+		policy = oldpolicy = -1;
+		task_rq_unlock(rq, &flags);
+		goto recheck;
+	}
 	array = p->array;
 	if (array)
 		deactivate_task(p, task_rq(p));
@@ -3118,12 +3147,9 @@
 		} else if (TASK_PREEMPTS_CURR(p, rq))
 			resched_task(rq->curr);
 	}
-
-out_unlock:
 	task_rq_unlock(rq, &flags);
-out_unlock_tasklist:
+out_unlock:
 	read_unlock_irq(&tasklist_lock);
-
 out_nounlock:
 	return retval;
 }
@@ -4047,21 +4073,6 @@
 }
 #endif
 
-/*
- * The 'big kernel lock'
- *
- * This spinlock is taken and released recursively by lock_kernel()
- * and unlock_kernel().  It is transparently dropped and reaquired
- * over schedule().  It is used to protect legacy code that hasn't
- * been migrated to a proper locking design yet.
- *
- * Don't use in new code.
- *
- * Note: spinlock debugging needs this even on !CONFIG_SMP.
- */
-spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
-EXPORT_SYMBOL(kernel_flag);
-
 #ifdef CONFIG_SMP
 /*
  * Attach the domain 'sd' to 'cpu' as its base domain.  Callers must
@@ -4378,11 +4389,10 @@
 			printk("domain %d: ", level);
 
 			if (!(sd->flags & SD_LOAD_BALANCE)) {
-				printk("does not balance");
+				printk("does not load-balance");
 				if (sd->parent)
 					printk(" ERROR !SD_LOAD_BALANCE domain has parent");
 				printk("\n");
-				break;
 			}
 
 			printk("span %s\n", str);
@@ -4437,14 +4447,12 @@
 #define sched_domain_debug() {}
 #endif
 
-#ifdef CONFIG_SMP
 /*
  * Initial dummy domain for early boot and for hotplug cpu. Being static,
  * it is initialized to zero, so all balancing flags are cleared which is
  * what we want.
  */
 static struct sched_domain sched_domain_dummy;
-#endif
 
 #ifdef CONFIG_HOTPLUG_CPU
 /*
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	2004-10-28 22:25:57 -07:00
+++ b/kernel/signal.c	2004-10-28 22:25:57 -07:00
@@ -1109,7 +1109,7 @@
 
 int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
 {
-	struct task_struct *p;
+	struct task_struct *p = NULL;
 	int retval, success;
 
 	if (pgrp <= 0)
@@ -1903,22 +1903,16 @@
 		 * Anything else is fatal, maybe with a core dump.
 		 */
 		current->flags |= PF_SIGNALED;
-		if (sig_kernel_coredump(signr) &&
-		    do_coredump((long)signr, signr, regs)) {
+		if (sig_kernel_coredump(signr)) {
 			/*
-			 * That killed all other threads in the group and
-			 * synchronized with their demise, so there can't
-			 * be any more left to kill now.  The group_exit
-			 * flags are set by do_coredump.  Note that
-			 * thread_group_empty won't always be true yet,
-			 * because those threads were blocked in __exit_mm
-			 * and we just let them go to finish dying.
+			 * If it was able to dump core, this kills all
+			 * other threads in the group and synchronizes with
+			 * their demise.  If we lost the race with another
+			 * thread getting here, it set group_exit_code
+			 * first and our do_group_exit call below will use
+			 * that value and ignore the one we pass it.
 			 */
-			const int code = signr | 0x80;
-			BUG_ON(!current->signal->group_exit);
-			BUG_ON(current->signal->group_exit_code != code);
-			do_exit(code);
-			/* NOTREACHED */
+			do_coredump((long)signr, signr, regs);
 		}
 
 		/*
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	2004-10-28 22:25:57 -07:00
+++ b/kernel/softirq.c	2004-10-28 22:25:57 -07:00
@@ -145,7 +145,7 @@
 	preempt_count() -= SOFTIRQ_OFFSET - 1;
 
 	if (unlikely(!in_interrupt() && local_softirq_pending()))
-		invoke_softirq();
+		do_softirq();
 
 	dec_preempt_count();
 	preempt_check_resched();
@@ -182,8 +182,6 @@
 	raise_softirq_irqoff(nr);
 	local_irq_restore(flags);
 }
-
-EXPORT_SYMBOL(raise_softirq);
 
 void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
 {
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	2004-10-28 22:25:57 -07:00
+++ b/kernel/sys.c	2004-10-28 22:25:57 -07:00
@@ -286,6 +286,7 @@
 cond_syscall(sys_add_key)
 cond_syscall(sys_request_key)
 cond_syscall(sys_keyctl)
+cond_syscall(compat_sys_keyctl)
 cond_syscall(compat_sys_socketcall)
 
 /* arch-specific weak syscall entries */
diff -Nru a/kernel/time.c b/kernel/time.c
--- a/kernel/time.c	2004-10-28 22:25:57 -07:00
+++ b/kernel/time.c	2004-10-28 22:25:57 -07:00
@@ -528,8 +528,6 @@
 }
 #endif
 
-EXPORT_SYMBOL(getnstimeofday);
-
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void)
 {
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c	2004-10-28 22:25:59 -07:00
+++ b/kernel/timer.c	2004-10-28 22:25:59 -07:00
@@ -241,7 +241,6 @@
 	spin_unlock_irqrestore(&base->lock, flags);
 }
 
-EXPORT_SYMBOL(add_timer_on);
 
 /***
  * mod_timer - modify a timer's timeout
@@ -1605,7 +1604,7 @@
  */
 void msleep(unsigned int msecs)
 {
-	unsigned long timeout = msecs_to_jiffies(msecs);
+	unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
 	while (timeout) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
@@ -1621,7 +1620,7 @@
  */
 unsigned long msleep_interruptible(unsigned int msecs)
 {
-	unsigned long timeout = msecs_to_jiffies(msecs);
+	unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
 	while (timeout && !signal_pending(current)) {
 		set_current_state(TASK_INTERRUPTIBLE);
diff -Nru a/lib/Kconfig.debug b/lib/Kconfig.debug
--- a/lib/Kconfig.debug	2004-10-28 22:25:59 -07:00
+++ b/lib/Kconfig.debug	2004-10-28 22:25:59 -07:00
@@ -8,7 +8,7 @@
 
 config MAGIC_SYSRQ
 	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || X86_64)
+	depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || M68K || MIPS || PARISC || PPC32 || PPC64 || ARCH_S390 || SUPERH || SUPERH64 || SPARC32 || SPARC64 || X86_64 || USERMODE)
 	help
 	  If you say Y here, you will have some control over the system even
 	  if the system crashes for example during kernel debugging (e.g., you
@@ -46,11 +46,11 @@
 	help
 	  Say Y here to have the kernel do limited verification on memory
 	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
+	  memory. This can make kmalloc/kfree-intensive workloads much slower.
 
 config DEBUG_SPINLOCK
 	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || MIPS || PPC32 || (SUPERH && !SUPERH64) || SPARC32 || SPARC64 || USERMODE || X86_64)
+	depends on DEBUG_KERNEL && (ALPHA || ARM || X86 || IA64 || MIPS || PPC32 || (SUPERH && !SUPERH64) || SPARC32 || SPARC64 || USERMODE || X86_64 || USERMODE)
 	help
 	  Say Y here and build SMP to catch missing spinlock initialization
 	  and certain other kinds of spinlock errors commonly made.  This is
@@ -59,10 +59,17 @@
 
 config DEBUG_SPINLOCK_SLEEP
 	bool "Sleep-inside-spinlock checking"
-	depends on DEBUG_KERNEL && (X86 || IA64 || MIPS || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64)
+	depends on DEBUG_KERNEL && (X86 || IA64 || MIPS || PPC32 || PPC64 || ARCH_S390 || SPARC32 || SPARC64 || USERMODE)
 	help
 	  If you say Y here, various routines which may sleep will become very
 	  noisy if they are called with a spinlock held.
+
+config DEBUG_KOBJECT
+	bool "kobject debugging"
+	depends on DEBUG_KERNEL
+	help
+	  If you say Y here, some extra kobject debugging messages will be sent
+	  to the syslog. 
 
 config DEBUG_HIGHMEM
 	bool "Highmem debugging"
diff -Nru a/lib/Makefile b/lib/Makefile
--- a/lib/Makefile	2004-10-28 22:25:56 -07:00
+++ b/lib/Makefile	2004-10-28 22:25:56 -07:00
@@ -2,14 +2,19 @@
 # Makefile for some libs needed in the kernel.
 #
 
-
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
 	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
 	 bitmap.o extable.o kobject_uevent.o
 
+ifeq ($(CONFIG_DEBUG_KOBJECT),y)
+CFLAGS_kobject.o += -DDEBUG
+CFLAGS_kobject_uevent.o += -DDEBUG
+endif
+
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
+obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
   lib-y += dec_and_lock.o
diff -Nru a/lib/idr.c b/lib/idr.c
--- a/lib/idr.c	2004-10-28 22:25:59 -07:00
+++ b/lib/idr.c	2004-10-28 22:25:59 -07:00
@@ -275,24 +275,31 @@
 }
 EXPORT_SYMBOL(idr_get_new);
 
+static void idr_remove_warning(int id)
+{
+	printk("idr_remove called for id=%d which is not allocated.\n", id);
+	dump_stack();
+}
+
 static void sub_remove(struct idr *idp, int shift, int id)
 {
 	struct idr_layer *p = idp->top;
 	struct idr_layer **pa[MAX_LEVEL];
 	struct idr_layer ***paa = &pa[0];
+	int n;
 
 	*paa = NULL;
 	*++paa = &idp->top;
 
 	while ((shift > 0) && p) {
-		int n = (id >> shift) & IDR_MASK;
+		n = (id >> shift) & IDR_MASK;
 		__clear_bit(n, &p->bitmap);
 		*++paa = &p->ary[n];
 		p = p->ary[n];
 		shift -= IDR_BITS;
 	}
-	if (likely(p != NULL)){
-		int n = id & IDR_MASK;
+	n = id & IDR_MASK;
+	if (likely(p != NULL && test_bit(n, &p->bitmap))){
 		__clear_bit(n, &p->bitmap);
 		p->ary[n] = NULL;
 		while(*paa && ! --((**paa)->count)){
@@ -301,6 +308,8 @@
 		}
 		if ( ! *paa )
 			idp->layers = 0;
+	} else {
+		idr_remove_warning(id);
 	}
 }
 
diff -Nru a/lib/iomap.c b/lib/iomap.c
--- a/lib/iomap.c	2004-10-28 22:25:56 -07:00
+++ b/lib/iomap.c	2004-10-28 22:25:56 -07:00
@@ -19,7 +19,10 @@
  *
  * Architectures for which this is not true can't use this generic
  * implementation and should do their own copy.
- *
+ */
+
+#ifndef HAVE_ARCH_PIO_SIZE
+/*
  * We encode the physical PIO addresses (0-0xffff) into the
  * pointer by offsetting them with a constant (0x10000) and
  * assuming that all the low addresses are always PIO. That means
@@ -29,6 +32,7 @@
 #define PIO_OFFSET	0x10000UL
 #define PIO_MASK	0x0ffffUL
 #define PIO_RESERVED	0x40000UL
+#endif
 
 /*
  * Ugly macros are a way of life.
diff -Nru a/lib/kernel_lock.c b/lib/kernel_lock.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/lib/kernel_lock.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,126 @@
+/*
+ * lib/kernel_lock.c
+ *
+ * This is the traditional BKL - big kernel lock. Largely
+ * relegated to obsolescense, but used by various less
+ * important (or lazy) subsystems.
+ */
+#include <linux/smp_lock.h>
+#include <linux/module.h>
+
+/*
+ * The 'big kernel lock'
+ *
+ * This spinlock is taken and released recursively by lock_kernel()
+ * and unlock_kernel().  It is transparently dropped and reaquired
+ * over schedule().  It is used to protect legacy code that hasn't
+ * been migrated to a proper locking design yet.
+ *
+ * Don't use in new code.
+ */
+static spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * Acquire/release the underlying lock from the scheduler.
+ *
+ * This is called with preemption disabled, and should
+ * return an error value if it cannot get the lock and
+ * TIF_NEED_RESCHED gets set.
+ *
+ * If it successfully gets the lock, it should increment
+ * the preemption count like any spinlock does.
+ *
+ * (This works on UP too - _raw_spin_trylock will never
+ * return false in that case)
+ */
+int __lockfunc get_kernel_lock(void)
+{
+	while (!_raw_spin_trylock(&kernel_flag)) {
+		if (test_thread_flag(TIF_NEED_RESCHED))
+			return -EAGAIN;
+		cpu_relax();
+	}
+	preempt_disable();
+	return 0;
+}
+
+void __lockfunc put_kernel_lock(void)
+{
+	_raw_spin_unlock(&kernel_flag);
+	preempt_enable_no_resched();
+}
+
+/*
+ * These are the BKL spinlocks - we try to be polite about preemption. 
+ * If SMP is not on (ie UP preemption), this all goes away because the
+ * _raw_spin_trylock() will always succeed.
+ */
+#ifdef CONFIG_PREEMPT
+static inline void __lock_kernel(void)
+{
+	preempt_disable();
+	if (unlikely(!_raw_spin_trylock(&kernel_flag))) {
+		/*
+		 * If preemption was disabled even before this
+		 * was called, there's nothing we can be polite
+		 * about - just spin.
+		 */
+		if (preempt_count() > 1) {
+			_raw_spin_lock(&kernel_flag);
+			return;
+		}
+
+		/*
+		 * Otherwise, let's wait for the kernel lock
+		 * with preemption enabled..
+		 */
+		do {
+			preempt_enable();
+			while (spin_is_locked(&kernel_flag))
+				cpu_relax();
+			preempt_disable();
+		} while (!_raw_spin_trylock(&kernel_flag));
+	}
+}
+
+#else
+
+/*
+ * Non-preemption case - just get the spinlock
+ */
+static inline void __lock_kernel(void)
+{
+	_raw_spin_lock(&kernel_flag);
+}
+#endif
+
+static inline void __unlock_kernel(void)
+{
+	_raw_spin_unlock(&kernel_flag);
+	preempt_enable();
+}
+
+/*
+ * Getting the big kernel lock.
+ *
+ * This cannot happen asynchronously, so we only need to
+ * worry about other CPU's.
+ */
+void __lockfunc lock_kernel(void)
+{
+	int depth = current->lock_depth+1;
+	if (likely(!depth))
+		__lock_kernel();
+	current->lock_depth = depth;
+}
+
+void __lockfunc unlock_kernel(void)
+{
+	BUG_ON(current->lock_depth < 0);
+	if (likely(--current->lock_depth < 0))
+		__unlock_kernel();
+}
+
+EXPORT_SYMBOL(lock_kernel);
+EXPORT_SYMBOL(unlock_kernel);
diff -Nru a/lib/kobject.c b/lib/kobject.c
--- a/lib/kobject.c	2004-10-28 22:25:59 -07:00
+++ b/lib/kobject.c	2004-10-28 22:25:59 -07:00
@@ -10,8 +10,6 @@
  * about using the kobject interface.
  */
 
-#undef DEBUG
-
 #include <linux/kobject.h>
 #include <linux/string.h>
 #include <linux/module.h>
@@ -123,7 +121,7 @@
  */
 void kobject_init(struct kobject * kobj)
 {
- 	kref_init(&kobj->kref);
+	kref_init(&kobj->kref);
 	INIT_LIST_HEAD(&kobj->entry);
 	kobj->kset = kset_get(kobj->kset);
 }
diff -Nru a/lib/kobject_uevent.c b/lib/kobject_uevent.c
--- a/lib/kobject_uevent.c	2004-10-28 22:25:58 -07:00
+++ b/lib/kobject_uevent.c	2004-10-28 22:25:58 -07:00
@@ -23,6 +23,7 @@
 #include <linux/kobject.h>
 #include <net/sock.h>
 
+#if defined(CONFIG_KOBJECT_UEVENT) || defined(CONFIG_HOTPLUG)
 static char *action_to_string(enum kobject_action action)
 {
 	switch (action) {
@@ -36,10 +37,13 @@
 		return "mount";
 	case KOBJ_UMOUNT:
 		return "umount";
+	case KOBJ_OFFLINE:
+		return "offline";
 	default:
 		return NULL;
 	}
 }
+#endif
 
 #ifdef CONFIG_KOBJECT_UEVENT
 static struct sock *uevent_sock;
@@ -187,6 +191,8 @@
 	u64 seq;
 	struct kobject *top_kobj = kobj;
 	struct kset *kset;
+	static struct kset_hotplug_ops null_hotplug_ops;
+	struct kset_hotplug_ops *hotplug_ops = &null_hotplug_ops;
 
 	if (!top_kobj->kset && top_kobj->parent) {
 		do {
@@ -194,15 +200,18 @@
 		} while (!top_kobj->kset && top_kobj->parent);
 	}
 
-	if (top_kobj->kset && top_kobj->kset->hotplug_ops)
+	if (top_kobj->kset)
 		kset = top_kobj->kset;
 	else
 		return;
 
+	if (kset->hotplug_ops)
+		hotplug_ops = kset->hotplug_ops;
+
 	/* If the kset has a filter operation, call it.
 	   Skip the event, if the filter returns zero. */
-	if (kset->hotplug_ops->filter) {
-		if (!kset->hotplug_ops->filter(kset, kobj))
+	if (hotplug_ops->filter) {
+		if (!hotplug_ops->filter(kset, kobj))
 			return;
 	}
 
@@ -221,8 +230,8 @@
 	if (!buffer)
 		goto exit;
 
-	if (kset->hotplug_ops->name)
-		name = kset->hotplug_ops->name(kset, kobj);
+	if (hotplug_ops->name)
+		name = hotplug_ops->name(kset, kobj);
 	if (name == NULL)
 		name = kset->kobj.name;
 
@@ -246,19 +255,12 @@
 	envp [i++] = scratch;
 	scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
 
-	spin_lock(&sequence_lock);
-	seq = ++hotplug_seqnum;
-	spin_unlock(&sequence_lock);
-
-	envp [i++] = scratch;
-	scratch += sprintf(scratch, "SEQNUM=%lld", (long long)seq) + 1;
-
 	envp [i++] = scratch;
 	scratch += sprintf(scratch, "SUBSYSTEM=%s", name) + 1;
 
-	if (kset->hotplug_ops->hotplug) {
+	if (hotplug_ops->hotplug) {
 		/* have the kset specific function add its stuff */
-		retval = kset->hotplug_ops->hotplug (kset, kobj,
+		retval = hotplug_ops->hotplug (kset, kobj,
 				  &envp[i], NUM_ENVP - i, scratch,
 				  BUFFER_SIZE - (scratch - buffer));
 		if (retval) {
@@ -268,7 +270,15 @@
 		}
 	}
 
-	pr_debug ("%s: %s %s %s %s %s %s %s\n", __FUNCTION__, argv[0], argv[1],
+	spin_lock(&sequence_lock);
+	seq = ++hotplug_seqnum;
+	spin_unlock(&sequence_lock);
+
+	envp [i++] = scratch;
+	scratch += sprintf(scratch, "SEQNUM=%lld", (long long)seq) + 1;
+
+	pr_debug ("%s: %s %s seq=%lld %s %s %s %s %s\n",
+		  __FUNCTION__, argv[0], argv[1], (long long)seq,
 		  envp[0], envp[1], envp[2], envp[3], envp[4]);
 
 	send_uevent(action_string, kobj_path, buffer, scratch - buffer, GFP_KERNEL);
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	2004-10-28 22:25:59 -07:00
+++ b/mm/filemap.c	2004-10-28 22:25:59 -07:00
@@ -191,12 +191,11 @@
 }
 EXPORT_SYMBOL(filemap_fdatawrite);
 
-int filemap_fdatawrite_range(struct address_space *mapping,
+static int filemap_fdatawrite_range(struct address_space *mapping,
 	loff_t start, loff_t end)
 {
 	return __filemap_fdatawrite_range(mapping, start, end, WB_SYNC_ALL);
 }
-EXPORT_SYMBOL(filemap_fdatawrite_range);
 
 /*
  * This is a mostly non-blocking flush.  Not suitable for data-integrity
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	2004-10-28 22:25:58 -07:00
+++ b/mm/memory.c	2004-10-28 22:25:58 -07:00
@@ -334,6 +334,8 @@
 				pte = pte_mkold(pte);
 				get_page(page);
 				dst->rss++;
+				if (PageAnon(page))
+					dst->anon_rss++;
 				set_pte(dst_pte, pte);
 				page_dup_rmap(page);
 cont_copy_pte_range_noset:
@@ -424,7 +426,9 @@
 				set_pte(ptep, pgoff_to_pte(page->index));
 			if (pte_dirty(pte))
 				set_page_dirty(page);
-			if (pte_young(pte) && !PageAnon(page))
+			if (PageAnon(page))
+				tlb->mm->anon_rss--;
+			else if (pte_young(pte))
 				mark_page_accessed(page);
 			tlb->freed++;
 			page_remove_rmap(page);
@@ -1109,6 +1113,8 @@
 	spin_lock(&mm->page_table_lock);
 	page_table = pte_offset_map(pmd, address);
 	if (likely(pte_same(*page_table, pte))) {
+		if (PageAnon(old_page))
+			mm->anon_rss--;
 		if (PageReserved(old_page))
 			++mm->rss;
 		else
@@ -1798,6 +1804,16 @@
 }
 
 EXPORT_SYMBOL(vmalloc_to_page);
+
+/*
+ * Map a vmalloc()-space virtual address to the physical page frame number.
+ */
+unsigned long vmalloc_to_pfn(void * vmalloc_addr)
+{
+	return page_to_pfn(vmalloc_to_page(vmalloc_addr));
+}
+
+EXPORT_SYMBOL(vmalloc_to_pfn);
 
 #if !defined(CONFIG_ARCH_GATE_AREA)
 
diff -Nru a/mm/mempolicy.c b/mm/mempolicy.c
--- a/mm/mempolicy.c	2004-10-28 22:25:59 -07:00
+++ b/mm/mempolicy.c	2004-10-28 22:25:59 -07:00
@@ -887,12 +887,12 @@
  *
  * Remember policies even when nobody has shared memory mapped.
  * The policies are kept in Red-Black tree linked from the inode.
- * They are protected by the sp->sem semaphore, which should be held
+ * They are protected by the sp->lock spinlock, which should be held
  * for any accesses to the tree.
  */
 
 /* lookup first element intersecting start-end */
-/* Caller holds sp->sem */
+/* Caller holds sp->lock */
 static struct sp_node *
 sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end)
 {
@@ -924,7 +924,7 @@
 }
 
 /* Insert a new shared policy into the list. */
-/* Caller holds sp->sem */
+/* Caller holds sp->lock */
 static void sp_insert(struct shared_policy *sp, struct sp_node *new)
 {
 	struct rb_node **p = &sp->root.rb_node;
@@ -954,13 +954,15 @@
 	struct mempolicy *pol = NULL;
 	struct sp_node *sn;
 
-	down(&sp->sem);
+	if (!sp->root.rb_node)
+		return NULL;
+	spin_lock(&sp->lock);
 	sn = sp_lookup(sp, idx, idx+1);
 	if (sn) {
 		mpol_get(sn->policy);
 		pol = sn->policy;
 	}
-	up(&sp->sem);
+	spin_unlock(&sp->lock);
 	return pol;
 }
 
@@ -990,9 +992,10 @@
 static int shared_policy_replace(struct shared_policy *sp, unsigned long start,
 				 unsigned long end, struct sp_node *new)
 {
-	struct sp_node *n, *new2;
+	struct sp_node *n, *new2 = NULL;
 
-	down(&sp->sem);
+restart:
+	spin_lock(&sp->lock);
 	n = sp_lookup(sp, start, end);
 	/* Take care of old policies in the same range. */
 	while (n && n->start < end) {
@@ -1005,13 +1008,16 @@
 		} else {
 			/* Old policy spanning whole new range. */
 			if (n->end > end) {
-				new2 = sp_alloc(end, n->end, n->policy);
 				if (!new2) {
-					up(&sp->sem);
-					return -ENOMEM;
+					spin_unlock(&sp->lock);
+					new2 = sp_alloc(end, n->end, n->policy);
+					if (!new2)
+						return -ENOMEM;
+					goto restart;
 				}
 				n->end = end;
 				sp_insert(sp, new2);
+				new2 = NULL;
 			}
 			/* Old crossing beginning, but not end (easy) */
 			if (n->start < start && n->end > start)
@@ -1023,7 +1029,11 @@
 	}
 	if (new)
 		sp_insert(sp, new);
-	up(&sp->sem);
+	spin_unlock(&sp->lock);
+	if (new2) {
+		mpol_free(new2->policy);
+		kmem_cache_free(sn_cache, new2);
+	}
 	return 0;
 }
 
@@ -1056,7 +1066,9 @@
 	struct sp_node *n;
 	struct rb_node *next;
 
-	down(&p->sem);
+	if (!p->root.rb_node)
+		return;
+	spin_lock(&p->lock);
 	next = rb_first(&p->root);
 	while (next) {
 		n = rb_entry(next, struct sp_node, nd);
@@ -1065,7 +1077,7 @@
 		mpol_free(n->policy);
 		kmem_cache_free(sn_cache, n);
 	}
-	up(&p->sem);
+	spin_unlock(&p->lock);
 }
 
 /* assumes fs == KERNEL_DS */
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	2004-10-28 22:25:58 -07:00
+++ b/mm/mmap.c	2004-10-28 22:25:58 -07:00
@@ -988,9 +988,12 @@
 	 *         f_op->mmap method. -DaveM
 	 */
 	addr = vma->vm_start;
+	pgoff = vma->vm_pgoff;
+	vm_flags = vma->vm_flags;
 
 	if (!file || !vma_merge(mm, prev, addr, vma->vm_end,
 			vma->vm_flags, NULL, file, pgoff, vma_policy(vma))) {
+		file = vma->vm_file;
 		vma_link(mm, vma, prev, rb_link, rb_parent);
 		if (correct_wcount)
 			atomic_inc(&inode->i_writecount);
@@ -1005,6 +1008,7 @@
 	}
 out:	
 	mm->total_vm += len >> PAGE_SHIFT;
+	__vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
 	if (vm_flags & VM_LOCKED) {
 		mm->locked_vm += len >> PAGE_SHIFT;
 		make_pages_present(addr, addr + len);
@@ -1015,7 +1019,6 @@
 					pgoff, flags & MAP_NONBLOCK);
 		down_write(&mm->mmap_sem);
 	}
-	__vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
 	return addr;
 
 unmap_and_free_vma:
diff -Nru a/mm/nommu.c b/mm/nommu.c
--- a/mm/nommu.c	2004-10-28 22:25:59 -07:00
+++ b/mm/nommu.c	2004-10-28 22:25:59 -07:00
@@ -33,9 +33,10 @@
 atomic_t vm_committed_space = ATOMIC_INIT(0);
 int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
 int sysctl_overcommit_ratio = 50; /* default is 50% */
-
 int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
+
 EXPORT_SYMBOL(sysctl_max_map_count);
+EXPORT_SYMBOL(mem_map);
 
 /*
  * Handle all mappings that got truncated by a "truncate()"
@@ -75,6 +76,8 @@
 	return -EFBIG;
 }
 
+EXPORT_SYMBOL(vmtruncate);
+
 /*
  * Return the total memory allocated for this pointer, not
  * just what the caller asked for.
@@ -141,6 +144,12 @@
 	return virt_to_page(addr);
 }
 
+unsigned long vmalloc_to_pfn(void *addr)
+{
+	return page_to_pfn(virt_to_page(addr));
+}
+
+
 long vread(char *buf, char *addr, unsigned long count)
 {
 	memcpy(buf, addr, count);
@@ -431,6 +440,7 @@
 
 	tblock->next = current->mm->context.tblock.next;
 	current->mm->context.tblock.next = tblock;
+	current->mm->total_vm += len >> PAGE_SHIFT;
 
 #ifdef DEBUG
 	printk("do_mmap:\n");
@@ -484,6 +494,7 @@
 	realalloc -= kobjsize(tblock);
 	askedalloc -= sizeof(struct mm_tblock_struct);
 	kfree(tblock);
+	mm->total_vm -= len >> PAGE_SHIFT;
 
 #ifdef DEBUG
 	show_process_blocks();
@@ -496,6 +507,7 @@
 void exit_mmap(struct mm_struct * mm)
 {
 	struct mm_tblock_struct *tmp;
+	mm->total_vm = 0;
 
 	if (!mm)
 		return;
@@ -575,3 +587,14 @@
 void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
 {
 }
+
+unsigned long arch_get_unmapped_area(struct file *file, unsigned long addr,
+	unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	return -ENOMEM;
+}
+
+void arch_unmap_area(struct vm_area_struct *area)
+{
+}
+
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	2004-10-28 22:25:56 -07:00
+++ b/mm/page_alloc.c	2004-10-28 22:25:56 -07:00
@@ -1103,6 +1103,8 @@
 			" active:%lukB"
 			" inactive:%lukB"
 			" present:%lukB"
+			" pages_scanned:%lu"
+			" all_unreclaimable? %s"
 			"\n",
 			zone->name,
 			K(zone->free_pages),
@@ -1111,7 +1113,9 @@
 			K(zone->pages_high),
 			K(zone->nr_active),
 			K(zone->nr_inactive),
-			K(zone->present_pages)
+			K(zone->present_pages),
+			zone->pages_scanned,
+			(zone->all_unreclaimable ? "yes" : "no")
 			);
 		printk("protections[]:");
 		for (i = 0; i < MAX_NR_ZONES; i++)
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	2004-10-28 22:25:59 -07:00
+++ b/mm/rmap.c	2004-10-28 22:25:59 -07:00
@@ -432,6 +432,8 @@
 	BUG_ON(PageReserved(page));
 	BUG_ON(!anon_vma);
 
+	vma->vm_mm->anon_rss++;
+
 	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
 	index = (address - vma->vm_start) >> PAGE_SHIFT;
 	index += vma->vm_pgoff;
@@ -584,6 +586,7 @@
 		}
 		set_pte(pte, swp_entry_to_pte(entry));
 		BUG_ON(pte_file(*pte));
+		mm->anon_rss--;
 	}
 
 	mm->rss--;
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	2004-10-28 22:25:57 -07:00
+++ b/mm/shmem.c	2004-10-28 22:25:57 -07:00
@@ -66,6 +66,9 @@
 #define SHMEM_PAGEIN	 VM_READ
 #define SHMEM_TRUNCATE	 VM_WRITE
 
+/* Definition to limit shmem_truncate's steps between cond_rescheds */
+#define LATENCY_LIMIT	 64
+
 /* Pretend that each entry is of this size in directory's i_size */
 #define BOGO_DIRENT_SIZE 20
 
@@ -188,13 +191,13 @@
 static LIST_HEAD(shmem_swaplist);
 static spinlock_t shmem_swaplist_lock = SPIN_LOCK_UNLOCKED;
 
-static void shmem_free_block(struct inode *inode)
+static void shmem_free_blocks(struct inode *inode, long pages)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 	if (sbinfo) {
 		spin_lock(&sbinfo->stat_lock);
-		sbinfo->free_blocks++;
-		inode->i_blocks -= BLOCKS_PER_PAGE;
+		sbinfo->free_blocks += pages;
+		inode->i_blocks -= pages*BLOCKS_PER_PAGE;
 		spin_unlock(&sbinfo->stat_lock);
 	}
 }
@@ -219,15 +222,9 @@
 
 	freed = info->alloced - info->swapped - inode->i_mapping->nrpages;
 	if (freed > 0) {
-		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 		info->alloced -= freed;
 		shmem_unacct_blocks(info->flags, freed);
-		if (sbinfo) {
-			spin_lock(&sbinfo->stat_lock);
-			sbinfo->free_blocks += freed;
-			inode->i_blocks -= freed*BLOCKS_PER_PAGE;
-			spin_unlock(&sbinfo->stat_lock);
-		}
+		shmem_free_blocks(inode, freed);
 	}
 }
 
@@ -380,7 +377,7 @@
 		spin_lock(&info->lock);
 
 		if (!page) {
-			shmem_free_block(inode);
+			shmem_free_blocks(inode, 1);
 			return ERR_PTR(-ENOMEM);
 		}
 		if (sgp != SGP_WRITE &&
@@ -393,7 +390,7 @@
 	}
 	if (page) {
 		/* another task gave its page, or truncated the file */
-		shmem_free_block(inode);
+		shmem_free_blocks(inode, 1);
 		shmem_dir_free(page);
 	}
 	if (info->next_index <= index && !IS_ERR(entry))
@@ -422,6 +419,49 @@
 	return freed;
 }
 
+static int shmem_map_and_free_swp(struct page *subdir,
+		int offset, int limit, struct page ***dir)
+{
+	swp_entry_t *ptr;
+	int freed = 0;
+
+	ptr = shmem_swp_map(subdir);
+	for (; offset < limit; offset += LATENCY_LIMIT) {
+		int size = limit - offset;
+		if (size > LATENCY_LIMIT)
+			size = LATENCY_LIMIT;
+		freed += shmem_free_swp(ptr+offset, ptr+offset+size);
+		if (need_resched()) {
+			shmem_swp_unmap(ptr);
+			if (*dir) {
+				shmem_dir_unmap(*dir);
+				*dir = NULL;
+			}
+			cond_resched();
+			ptr = shmem_swp_map(subdir);
+		}
+	}
+	shmem_swp_unmap(ptr);
+	return freed;
+}
+
+static void shmem_free_pages(struct list_head *next)
+{
+	struct page *page;
+	int freed = 0;
+
+	do {
+		page = container_of(next, struct page, lru);
+		next = next->next;
+		shmem_dir_free(page);
+		freed++;
+		if (freed >= LATENCY_LIMIT) {
+			cond_resched();
+			freed = 0;
+		}
+	} while (next);
+}
+
 static void shmem_truncate(struct inode *inode)
 {
 	struct shmem_inode_info *info = SHMEM_I(inode);
@@ -429,10 +469,15 @@
 	unsigned long size;
 	unsigned long limit;
 	unsigned long stage;
+	unsigned long diroff;
 	struct page **dir;
+	struct page *topdir;
+	struct page *middir;
 	struct page *subdir;
-	struct page *empty;
 	swp_entry_t *ptr;
+	LIST_HEAD(pages_to_free);
+	long nr_pages_to_free = 0;
+	long nr_swaps_freed = 0;
 	int offset;
 	int freed;
 
@@ -445,14 +490,22 @@
 	info->flags |= SHMEM_TRUNCATE;
 	limit = info->next_index;
 	info->next_index = idx;
+	topdir = info->i_indirect;
+	if (topdir && idx <= SHMEM_NR_DIRECT) {
+		info->i_indirect = NULL;
+		nr_pages_to_free++;
+		list_add(&topdir->lru, &pages_to_free);
+	}
+	spin_unlock(&info->lock);
+
 	if (info->swapped && idx < SHMEM_NR_DIRECT) {
 		ptr = info->i_direct;
 		size = limit;
 		if (size > SHMEM_NR_DIRECT)
 			size = SHMEM_NR_DIRECT;
-		info->swapped -= shmem_free_swp(ptr+idx, ptr+size);
+		nr_swaps_freed = shmem_free_swp(ptr+idx, ptr+size);
 	}
-	if (!info->i_indirect)
+	if (!topdir)
 		goto done2;
 
 	BUG_ON(limit <= SHMEM_NR_DIRECT);
@@ -461,36 +514,38 @@
 	offset = idx % ENTRIES_PER_PAGE;
 	idx -= offset;
 
-	empty = NULL;
-	dir = shmem_dir_map(info->i_indirect);
+	dir = shmem_dir_map(topdir);
 	stage = ENTRIES_PER_PAGEPAGE/2;
-	if (idx < ENTRIES_PER_PAGEPAGE/2)
-		dir += idx/ENTRIES_PER_PAGE;
-	else {
+	if (idx < ENTRIES_PER_PAGEPAGE/2) {
+		middir = topdir;
+		diroff = idx/ENTRIES_PER_PAGE;
+	} else {
 		dir += ENTRIES_PER_PAGE/2;
 		dir += (idx - ENTRIES_PER_PAGEPAGE/2)/ENTRIES_PER_PAGEPAGE;
 		while (stage <= idx)
 			stage += ENTRIES_PER_PAGEPAGE;
+		middir = *dir;
 		if (*dir) {
-			subdir = *dir;
-			size = ((idx - ENTRIES_PER_PAGEPAGE/2) %
+			diroff = ((idx - ENTRIES_PER_PAGEPAGE/2) %
 				ENTRIES_PER_PAGEPAGE) / ENTRIES_PER_PAGE;
-			if (!size && !offset) {
-				empty = subdir;
+			if (!diroff && !offset) {
 				*dir = NULL;
+				nr_pages_to_free++;
+				list_add(&middir->lru, &pages_to_free);
 			}
 			shmem_dir_unmap(dir);
-			dir = shmem_dir_map(subdir) + size;
+			dir = shmem_dir_map(middir);
 		} else {
+			diroff = 0;
 			offset = 0;
 			idx = stage;
 		}
 	}
 
-	for (; idx < limit; idx += ENTRIES_PER_PAGE, dir++) {
+	for (; idx < limit; idx += ENTRIES_PER_PAGE, diroff++) {
 		if (unlikely(idx == stage)) {
-			shmem_dir_unmap(dir-1);
-			dir = shmem_dir_map(info->i_indirect) +
+			shmem_dir_unmap(dir);
+			dir = shmem_dir_map(topdir) +
 			    ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
 			while (!*dir) {
 				dir++;
@@ -499,50 +554,43 @@
 					goto done1;
 			}
 			stage = idx + ENTRIES_PER_PAGEPAGE;
-			subdir = *dir;
+			middir = *dir;
 			*dir = NULL;
+			nr_pages_to_free++;
+			list_add(&middir->lru, &pages_to_free);
 			shmem_dir_unmap(dir);
-			if (empty) {
-				shmem_dir_free(empty);
-				shmem_free_block(inode);
-			}
-			empty = subdir;
-			cond_resched_lock(&info->lock);
-			dir = shmem_dir_map(subdir);
+			cond_resched();
+			dir = shmem_dir_map(middir);
+			diroff = 0;
 		}
-		subdir = *dir;
+		subdir = dir[diroff];
 		if (subdir && subdir->nr_swapped) {
-			ptr = shmem_swp_map(subdir);
 			size = limit - idx;
 			if (size > ENTRIES_PER_PAGE)
 				size = ENTRIES_PER_PAGE;
-			freed = shmem_free_swp(ptr+offset, ptr+size);
-			shmem_swp_unmap(ptr);
-			info->swapped -= freed;
+			freed = shmem_map_and_free_swp(subdir,
+						offset, size, &dir);
+			if (!dir)
+				dir = shmem_dir_map(middir);
+			nr_swaps_freed += freed;
+			if (offset)
+				spin_lock(&info->lock);
 			subdir->nr_swapped -= freed;
+			if (offset)
+				spin_unlock(&info->lock);
 			BUG_ON(subdir->nr_swapped > offset);
 		}
 		if (offset)
 			offset = 0;
 		else if (subdir) {
-			*dir = NULL;
-			shmem_dir_free(subdir);
-			shmem_free_block(inode);
+			dir[diroff] = NULL;
+			nr_pages_to_free++;
+			list_add(&subdir->lru, &pages_to_free);
 		}
 	}
 done1:
-	shmem_dir_unmap(dir-1);
-	if (empty) {
-		shmem_dir_free(empty);
-		shmem_free_block(inode);
-	}
-	if (info->next_index <= SHMEM_NR_DIRECT) {
-		shmem_dir_free(info->i_indirect);
-		info->i_indirect = NULL;
-		shmem_free_block(inode);
-	}
+	shmem_dir_unmap(dir);
 done2:
-	BUG_ON(info->swapped > info->next_index);
 	if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) {
 		/*
 		 * Call truncate_inode_pages again: racing shmem_unuse_inode
@@ -551,13 +599,24 @@
 		 * Also, though shmem_getpage checks i_size before adding to
 		 * cache, no recheck after: so fix the narrow window there too.
 		 */
-		spin_unlock(&info->lock);
 		truncate_inode_pages(inode->i_mapping, inode->i_size);
-		spin_lock(&info->lock);
 	}
+
+	spin_lock(&info->lock);
 	info->flags &= ~SHMEM_TRUNCATE;
+	info->swapped -= nr_swaps_freed;
+	if (nr_pages_to_free)
+		shmem_free_blocks(inode, nr_pages_to_free);
 	shmem_recalc_inode(inode);
 	spin_unlock(&info->lock);
+
+	/*
+	 * Empty swap vector directory pages to be freed?
+	 */
+	if (!list_empty(&pages_to_free)) {
+		pages_to_free.prev->next = NULL;
+		shmem_free_pages(pages_to_free.next);
+	}
 }
 
 static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
@@ -665,9 +724,6 @@
 	}
 	if (!info->i_indirect)
 		goto lost2;
-	/* we might be racing with shmem_truncate */
-	if (limit <= SHMEM_NR_DIRECT)
-		goto lost2;
 
 	dir = shmem_dir_map(info->i_indirect);
 	stage = SHMEM_NR_DIRECT + ENTRIES_PER_PAGEPAGE/2;
@@ -1050,7 +1106,7 @@
 						    idx);
 			if (!filepage) {
 				shmem_unacct_blocks(info->flags, 1);
-				shmem_free_block(inode);
+				shmem_free_blocks(inode, 1);
 				error = -ENOMEM;
 				goto failed;
 			}
@@ -1068,7 +1124,7 @@
 				spin_unlock(&info->lock);
 				page_cache_release(filepage);
 				shmem_unacct_blocks(info->flags, 1);
-				shmem_free_block(inode);
+				shmem_free_blocks(inode, 1);
 				filepage = NULL;
 				if (error)
 					goto failed;
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	2004-10-28 22:25:57 -07:00
+++ b/mm/swapfile.c	2004-10-28 22:25:57 -07:00
@@ -1374,7 +1374,7 @@
 	p->highest_bit = 0;
 	p->cluster_nr = 0;
 	p->inuse_pages = 0;
-	p->sdev_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&p->sdev_lock);
 	p->next = -1;
 	if (swap_flags & SWAP_FLAG_PREFER) {
 		p->prio =
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	2004-10-28 22:25:57 -07:00
+++ b/mm/vmscan.c	2004-10-28 22:25:57 -07:00
@@ -574,7 +574,6 @@
 			nr_taken++;
 		}
 		zone->nr_inactive -= nr_taken;
-		zone->pages_scanned += nr_taken;
 		spin_unlock_irq(&zone->lru_lock);
 
 		if (nr_taken == 0)
@@ -675,6 +674,7 @@
 		}
 		pgscanned++;
 	}
+	zone->pages_scanned += pgscanned;
 	zone->nr_active -= pgmoved;
 	spin_unlock_irq(&zone->lru_lock);
 
diff -Nru a/net/8021q/vlan.c b/net/8021q/vlan.c
--- a/net/8021q/vlan.c	2004-10-28 22:25:59 -07:00
+++ b/net/8021q/vlan.c	2004-10-28 22:25:59 -07:00
@@ -35,6 +35,8 @@
 #include "vlan.h"
 #include "vlanproc.h"
 
+#define DRV_VERSION "1.8"
+
 /* Global VLAN variables */
 
 /* Our listing of VLAN group(s) */
@@ -42,8 +44,7 @@
 #define vlan_grp_hashfn(IDX)	((((IDX) >> VLAN_GRP_HASH_SHIFT) ^ (IDX)) & VLAN_GRP_HASH_MASK)
 
 static char vlan_fullname[] = "802.1Q VLAN Support";
-static unsigned int vlan_version = 1;
-static unsigned int vlan_release = 8;
+static char vlan_version[] = DRV_VERSION;
 static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
 static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
 
@@ -84,8 +85,8 @@
 {
 	int err;
 
-	printk(VLAN_INF "%s v%u.%u %s\n",
-	       vlan_fullname, vlan_version, vlan_release, vlan_copyright);
+	printk(VLAN_INF "%s v%s %s\n",
+	       vlan_fullname, vlan_version, vlan_copyright);
 	printk(VLAN_INF "All bugs added by %s\n",
 	       vlan_buggyright);
 
@@ -646,15 +647,9 @@
 static int vlan_ioctl_handler(void __user *arg)
 {
 	int err = 0;
+	unsigned short vid = 0;
 	struct vlan_ioctl_args args;
 
-	/* everything here needs root permissions, except aguably the
-	 * hack ioctls for sending packets.  However, I know _I_ don't
-	 * want users running that on my network! --BLG
-	 */
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
 	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
 		return -EFAULT;
 
@@ -668,24 +663,32 @@
 
 	switch (args.cmd) {
 	case SET_VLAN_INGRESS_PRIORITY_CMD:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		err = vlan_dev_set_ingress_priority(args.device1,
 						    args.u.skb_priority,
 						    args.vlan_qos);
 		break;
 
 	case SET_VLAN_EGRESS_PRIORITY_CMD:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		err = vlan_dev_set_egress_priority(args.device1,
 						   args.u.skb_priority,
 						   args.vlan_qos);
 		break;
 
 	case SET_VLAN_FLAG_CMD:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		err = vlan_dev_set_vlan_flag(args.device1,
 					     args.u.flag,
 					     args.vlan_qos);
 		break;
 
 	case SET_VLAN_NAME_TYPE_CMD:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		if ((args.u.name_type >= 0) &&
 		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
 			vlan_name_type = args.u.name_type;
@@ -695,17 +698,9 @@
 		}
 		break;
 
-		/* TODO:  Figure out how to pass info back...
-		   case GET_VLAN_INGRESS_PRIORITY_IOCTL:
-		   err = vlan_dev_get_ingress_priority(args);
-		   break;
-
-		   case GET_VLAN_EGRESS_PRIORITY_IOCTL:
-		   err = vlan_dev_get_egress_priority(args);
-		   break;
-		*/
-
 	case ADD_VLAN_CMD:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		/* we have been given the name of the Ethernet Device we want to
 		 * talk to:  args.dev1	 We also have the
 		 * VLAN ID:  args.u.VID
@@ -718,12 +713,51 @@
 		break;
 
 	case DEL_VLAN_CMD:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		/* Here, the args.dev1 is the actual VLAN we want
 		 * to get rid of.
 		 */
 		err = unregister_vlan_device(args.device1);
 		break;
 
+	case GET_VLAN_INGRESS_PRIORITY_CMD:
+		/* TODO:  Implement
+		   err = vlan_dev_get_ingress_priority(args);
+		   if (copy_to_user((void*)arg, &args,
+		        sizeof(struct vlan_ioctl_args))) {
+		        err = -EFAULT;
+		   }
+		*/
+		err = -EINVAL;
+		break;
+	case GET_VLAN_EGRESS_PRIORITY_CMD:
+		/* TODO:  Implement
+		   err = vlan_dev_get_egress_priority(args.device1, &(args.args);
+		   if (copy_to_user((void*)arg, &args,
+		        sizeof(struct vlan_ioctl_args))) {
+		        err = -EFAULT;
+		   }
+		*/
+		err = -EINVAL;
+		break;
+	case GET_VLAN_REALDEV_NAME_CMD:
+		err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
+		if (copy_to_user((void*)arg, &args,
+				 sizeof(struct vlan_ioctl_args))) {
+			err = -EFAULT;
+		}
+		break;
+
+	case GET_VLAN_VID_CMD:
+		err = vlan_dev_get_vid(args.device1, &vid);
+		args.u.VID = vid;
+		if (copy_to_user((void*)arg, &args,
+				 sizeof(struct vlan_ioctl_args))) {
+                      err = -EFAULT;
+		}
+		break;
+
 	default:
 		/* pass on to underlying device instead?? */
 		printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
@@ -735,3 +769,4 @@
 }
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff -Nru a/net/8021q/vlan.h b/net/8021q/vlan.h
--- a/net/8021q/vlan.h	2004-10-28 22:25:58 -07:00
+++ b/net/8021q/vlan.h	2004-10-28 22:25:58 -07:00
@@ -66,6 +66,8 @@
 int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
 int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
 int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
+int vlan_dev_get_realdev_name(const char* dev_name, char* result);
+int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
 void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
 
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
diff -Nru a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
--- a/net/8021q/vlan_dev.c	2004-10-28 22:25:59 -07:00
+++ b/net/8021q/vlan_dev.c	2004-10-28 22:25:59 -07:00
@@ -1,4 +1,4 @@
-/*
+/* -*- linux-c -*-
  * INET		802.1Q VLAN
  *		Ethernet-type device handling.
  *
@@ -484,13 +484,26 @@
 	       veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto);
 #endif
 
-	stats->tx_packets++; /* for statics only */
-	stats->tx_bytes += skb->len;
-
 	skb->dev = VLAN_DEV_INFO(dev)->real_dev;
-	dev_queue_xmit(skb);
 
-	return 0;
+	{
+		/* Please note, dev_queue_xmit consumes the pkt regardless of the
+		 * error value.  So, will copy the skb first and free if successful.
+		 */
+		struct sk_buff* skb2 = skb_get(skb);
+		int rv = dev_queue_xmit(skb2);
+		if (rv == 0) {
+			/* Was success, need to free the skb reference since we bumped up the
+			 * user count above.
+			 */
+
+			stats->tx_packets++; /* for statics only */
+			stats->tx_bytes += skb->len;
+
+			kfree_skb(skb);
+		}
+		return rv;
+	}
 }
 
 int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -621,6 +634,44 @@
 
 	return -EINVAL;
 }
+
+
+int vlan_dev_get_realdev_name(const char *dev_name, char* result)
+{
+	struct net_device *dev = dev_get_by_name(dev_name);
+	int rv = 0;
+	if (dev) {
+		if (dev->priv_flags & IFF_802_1Q_VLAN) {
+			strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
+			rv = 0;
+		} else {
+			rv = -EINVAL;
+		}
+		dev_put(dev);
+	} else {
+		rv = -ENODEV;
+	}
+	return rv;
+}
+
+int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
+{
+	struct net_device *dev = dev_get_by_name(dev_name);
+	int rv = 0;
+	if (dev) {
+		if (dev->priv_flags & IFF_802_1Q_VLAN) {
+			*result = VLAN_DEV_INFO(dev)->vlan_id;
+			rv = 0;
+		} else {
+			rv = -EINVAL;
+		}
+		dev_put(dev);
+	} else {
+		rv = -ENODEV;
+	}
+	return rv;
+}
+
 
 int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
 {
diff -Nru a/net/Kconfig b/net/Kconfig
--- a/net/Kconfig	2004-10-28 22:25:56 -07:00
+++ b/net/Kconfig	2004-10-28 22:25:56 -07:00
@@ -564,24 +564,6 @@
 
 	  If unsure, say N.
 
-config NET_HW_FLOWCONTROL
-	bool "Forwarding between high speed interfaces"
-	depends on EXPERIMENTAL
-	---help---
-	  This option enables NIC (Network Interface Card) hardware throttling
-	  during periods of extreme congestion. At the moment only a couple
-	  of device drivers support it (really only one -- tulip, a modified
-	  8390 driver can be found at
-	  <ftp://ftp.tux.org/pub/net/ip-routing/fastroute/fastroute-8390.tar.gz>).
-
-	  Really, this option is applicable to any machine attached to a fast
-	  enough network, and even a 10 Mb NIC is able to kill a not very slow
-	  box, such as a 120MHz Pentium.
-
-	  However, do not say Y here if you did not experience any serious
-	  problems.
-
-
 menu "QoS and/or fair queueing"
 
 config NET_SCHED
diff -Nru a/net/atm/common.c b/net/atm/common.c
--- a/net/atm/common.c	2004-10-28 22:25:59 -07:00
+++ b/net/atm/common.c	2004-10-28 22:25:59 -07:00
@@ -57,7 +57,7 @@
 	write_unlock_irq(&vcc_sklist_lock);
 }
 
-void vcc_remove_socket(struct sock *sk)
+static void vcc_remove_socket(struct sock *sk)
 {
 	write_lock_irq(&vcc_sklist_lock);
 	sk_del_node_init(sk);
@@ -86,7 +86,6 @@
 EXPORT_SYMBOL(vcc_hash);
 EXPORT_SYMBOL(vcc_sklist_lock);
 EXPORT_SYMBOL(vcc_insert_socket);
-EXPORT_SYMBOL(vcc_remove_socket);
 
 static void vcc_sock_destruct(struct sock *sk)
 {
diff -Nru a/net/atm/signaling.c b/net/atm/signaling.c
--- a/net/atm/signaling.c	2004-10-28 22:25:59 -07:00
+++ b/net/atm/signaling.c	2004-10-28 22:25:59 -07:00
@@ -136,6 +136,7 @@
 			if (vcc->sk->sk_ack_backlog ==
 			    vcc->sk->sk_max_ack_backlog) {
 				sigd_enq(NULL,as_reject,vcc,NULL,NULL);
+				dev_kfree_skb(skb);
 				goto as_indicate_complete;
 			}
 			vcc->sk->sk_ack_backlog++;
@@ -148,7 +149,7 @@
 		case as_close:
 			set_bit(ATM_VF_RELEASED,&vcc->flags);
 			vcc_release_async(vcc, msg->reply);
-			break;
+			goto out;
 		case as_modify:
 			modify_qos(vcc,msg);
 			break;
@@ -163,6 +164,7 @@
 			return -EINVAL;
 	}
 	vcc->sk->sk_state_change(vcc->sk);
+out:
 	dev_kfree_skb(skb);
 	return 0;
 }
diff -Nru a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
--- a/net/bluetooth/hci_sock.c	2004-10-28 22:25:58 -07:00
+++ b/net/bluetooth/hci_sock.c	2004-10-28 22:25:58 -07:00
@@ -111,7 +111,8 @@
 		/* Apply filter */
 		flt = &hci_pi(sk)->filter;
 
-		if (!test_bit((skb->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
+		if (!test_bit((skb->pkt_type == HCI_VENDOR_PKT) ?
+				0 : (skb->pkt_type & HCI_FLT_TYPE_BITS), &flt->type_mask))
 			continue;
 
 		if (skb->pkt_type == HCI_EVENT_PKT) {
diff -Nru a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
--- a/net/bridge/br_netfilter.c	2004-10-28 22:25:59 -07:00
+++ b/net/bridge/br_netfilter.c	2004-10-28 22:25:59 -07:00
@@ -197,7 +197,7 @@
 		skb_pull(skb, VLAN_HLEN);
 		skb->nh.raw += VLAN_HLEN;
 	}
-	skb->dst->output(&skb);
+	skb->dst->output(skb);
 	return 0;
 }
 
diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
--- a/net/bridge/netfilter/ebtables.c	2004-10-28 22:25:57 -07:00
+++ b/net/bridge/netfilter/ebtables.c	2004-10-28 22:25:57 -07:00
@@ -109,11 +109,17 @@
 
 static inline int ebt_dev_check(char *entry, const struct net_device *device)
 {
+	int i = 0;
+	char *devname = device->name;
+
 	if (*entry == '\0')
 		return 0;
 	if (!device)
 		return 1;
-	return !!strcmp(entry, device->name);
+	/* 1 is the wildcard token */
+	while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
+		i++;
+	return (devname[i] != entry[i] && entry[i] != 1);
 }
 
 #define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	2004-10-28 22:25:58 -07:00
+++ b/net/core/dev.c	2004-10-28 22:25:58 -07:00
@@ -1106,34 +1106,34 @@
  * Invalidate hardware checksum when packet is to be mangled, and
  * complete checksum manually on outgoing path.
  */
-int skb_checksum_help(struct sk_buff **pskb, int inward)
+int skb_checksum_help(struct sk_buff *skb, int inward)
 {
 	unsigned int csum;
-	int ret = 0, offset = (*pskb)->h.raw - (*pskb)->data;
+	int ret = 0, offset = skb->h.raw - skb->data;
 
 	if (inward) {
-		(*pskb)->ip_summed = CHECKSUM_NONE;
+		skb->ip_summed = CHECKSUM_NONE;
 		goto out;
 	}
 
-	if (skb_cloned(*pskb)) {
-		ret = pskb_expand_head(*pskb, 0, 0, GFP_ATOMIC);
+	if (skb_cloned(skb)) {
+		ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 		if (ret)
 			goto out;
 	}
 
-	if (offset > (int)(*pskb)->len)
+	if (offset > (int)skb->len)
 		BUG();
-	csum = skb_checksum(*pskb, offset, (*pskb)->len-offset, 0);
+	csum = skb_checksum(skb, offset, skb->len-offset, 0);
 
-	offset = (*pskb)->tail - (*pskb)->h.raw;
+	offset = skb->tail - skb->h.raw;
 	if (offset <= 0)
 		BUG();
-	if ((*pskb)->csum + 2 > offset)
+	if (skb->csum + 2 > offset)
 		BUG();
 
-	*(u16*)((*pskb)->h.raw + (*pskb)->csum) = csum_fold(csum);
-	(*pskb)->ip_summed = CHECKSUM_NONE;
+	*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
+	skb->ip_summed = CHECKSUM_NONE;
 out:	
 	return ret;
 }
@@ -1282,7 +1282,7 @@
 	    (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
 	     (!(dev->features & NETIF_F_IP_CSUM) ||
 	      skb->protocol != htons(ETH_P_IP))))
-	      	if (skb_checksum_help(&skb, 0))
+	      	if (skb_checksum_help(skb, 0))
 	      		goto out_kfree_skb;
 
 
@@ -1390,66 +1390,6 @@
 DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
 
 
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-atomic_t netdev_dropping = ATOMIC_INIT(0);
-static unsigned long netdev_fc_mask = 1;
-unsigned long netdev_fc_xoff;
-spinlock_t netdev_fc_lock = SPIN_LOCK_UNLOCKED;
-
-static struct
-{
-	void (*stimul)(struct net_device *);
-	struct net_device *dev;
-} netdev_fc_slots[BITS_PER_LONG];
-
-int netdev_register_fc(struct net_device *dev,
-		       void (*stimul)(struct net_device *dev))
-{
-	int bit = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&netdev_fc_lock, flags);
-	if (netdev_fc_mask != ~0UL) {
-		bit = ffz(netdev_fc_mask);
-		netdev_fc_slots[bit].stimul = stimul;
-		netdev_fc_slots[bit].dev = dev;
-		set_bit(bit, &netdev_fc_mask);
-		clear_bit(bit, &netdev_fc_xoff);
-	}
-	spin_unlock_irqrestore(&netdev_fc_lock, flags);
-	return bit;
-}
-
-void netdev_unregister_fc(int bit)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&netdev_fc_lock, flags);
-	if (bit > 0) {
-		netdev_fc_slots[bit].stimul = NULL;
-		netdev_fc_slots[bit].dev = NULL;
-		clear_bit(bit, &netdev_fc_mask);
-		clear_bit(bit, &netdev_fc_xoff);
-	}
-	spin_unlock_irqrestore(&netdev_fc_lock, flags);
-}
-
-static void netdev_wakeup(void)
-{
-	unsigned long xoff;
-
-	spin_lock(&netdev_fc_lock);
-	xoff = netdev_fc_xoff;
-	netdev_fc_xoff = 0;
-	while (xoff) {
-		int i = ffz(~xoff);
-		xoff &= ~(1 << i);
-		netdev_fc_slots[i].stimul(netdev_fc_slots[i].dev);
-	}
-	spin_unlock(&netdev_fc_lock);
-}
-#endif
-
 static void get_sample_stats(int cpu)
 {
 #ifdef RAND_LIE
@@ -1559,13 +1499,8 @@
 			return queue->cng_level;
 		}
 
-		if (queue->throttle) {
+		if (queue->throttle)
 			queue->throttle = 0;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-			if (atomic_dec_and_test(&netdev_dropping))
-				netdev_wakeup();
-#endif
-		}
 
 		netif_rx_schedule(&queue->backlog_dev);
 		goto enqueue;
@@ -1574,9 +1509,6 @@
 	if (!queue->throttle) {
 		queue->throttle = 1;
 		__get_cpu_var(netdev_rx_stat).throttled++;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-		atomic_inc(&netdev_dropping);
-#endif
 	}
 
 drop:
@@ -1848,16 +1780,6 @@
 		if (work >= quota || jiffies - start_time > 1)
 			break;
 
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-		if (queue->throttle &&
-		    queue->input_pkt_queue.qlen < no_cong_thresh ) {
-			queue->throttle = 0;
-			if (atomic_dec_and_test(&netdev_dropping)) {
-				netdev_wakeup();
-				break;
-			}
-		}
-#endif
 	}
 
 	backlog_dev->quota -= work;
@@ -1872,13 +1794,8 @@
 	smp_mb__before_clear_bit();
 	netif_poll_enable(backlog_dev);
 
-	if (queue->throttle) {
+	if (queue->throttle)
 		queue->throttle = 0;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-		if (atomic_dec_and_test(&netdev_dropping))
-			netdev_wakeup();
-#endif
-	}
 	local_irq_enable();
 	return 0;
 }
@@ -3364,12 +3281,6 @@
 
 #ifdef CONFIG_KMOD
 EXPORT_SYMBOL(dev_load);
-#endif
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-EXPORT_SYMBOL(netdev_dropping);
-EXPORT_SYMBOL(netdev_fc_xoff);
-EXPORT_SYMBOL(netdev_register_fc);
-EXPORT_SYMBOL(netdev_unregister_fc);
 #endif
 
 #ifdef CONFIG_NET_CLS_ACT
diff -Nru a/net/core/dst.c b/net/core/dst.c
--- a/net/core/dst.c	2004-10-28 22:25:58 -07:00
+++ b/net/core/dst.c	2004-10-28 22:25:58 -07:00
@@ -106,9 +106,9 @@
 	return 0;
 }
 
-static int dst_discard_out(struct sk_buff **pskb)
+static int dst_discard_out(struct sk_buff *skb)
 {
-	kfree_skb(*pskb);
+	kfree_skb(skb);
 	return 0;
 }
 
diff -Nru a/net/core/ethtool.c b/net/core/ethtool.c
--- a/net/core/ethtool.c	2004-10-28 22:25:59 -07:00
+++ b/net/core/ethtool.c	2004-10-28 22:25:59 -07:00
@@ -452,9 +452,23 @@
 	return 0;
 }
 
+static int __ethtool_set_sg(struct net_device *dev, u32 data)
+{
+	int err;
+
+	if (!data && dev->ethtool_ops->set_tso) {
+		err = dev->ethtool_ops->set_tso(dev, 0);
+		if (err)
+			return err;
+	}
+
+	return dev->ethtool_ops->set_sg(dev, data);
+}
+
 static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_value edata;
+	int err;
 
 	if (!dev->ethtool_ops->set_tx_csum)
 		return -EOPNOTSUPP;
@@ -462,6 +476,12 @@
 	if (copy_from_user(&edata, useraddr, sizeof(edata)))
 		return -EFAULT;
 
+	if (!edata.data && dev->ethtool_ops->set_sg) {
+		err = __ethtool_set_sg(dev, 0);
+		if (err)
+			return err;
+	}
+
 	return dev->ethtool_ops->set_tx_csum(dev, edata.data);
 }
 
@@ -489,7 +509,13 @@
 	if (copy_from_user(&edata, useraddr, sizeof(edata)))
 		return -EFAULT;
 
-	return dev->ethtool_ops->set_sg(dev, edata.data);
+	if (edata.data && 
+	    !(dev->features & (NETIF_F_IP_CSUM |
+			       NETIF_F_NO_CSUM |
+			       NETIF_F_HW_CSUM)))
+		return -EINVAL;
+
+	return __ethtool_set_sg(dev, edata.data);
 }
 
 static int ethtool_get_tso(struct net_device *dev, char __user *useraddr)
@@ -515,6 +541,9 @@
 
 	if (copy_from_user(&edata, useraddr, sizeof(edata)))
 		return -EFAULT;
+
+	if (edata.data && !(dev->features & NETIF_F_SG))
+		return -EINVAL;
 
 	return dev->ethtool_ops->set_tso(dev, edata.data);
 }
diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c
--- a/net/core/netfilter.c	2004-10-28 22:25:58 -07:00
+++ b/net/core/netfilter.c	2004-10-28 22:25:58 -07:00
@@ -751,10 +751,9 @@
 
 	/* Any setup of logging members must be done before
 	 * substituting pointer. */
-	smp_wmb();
 	spin_lock(&nf_log_lock);
 	if (!nf_logging[pf]) {
-		nf_logging[pf] = logfn;
+		rcu_assign_pointer(nf_logging[pf], logfn);
 		ret = 0;
 	}
 	spin_unlock(&nf_log_lock);
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	2004-10-28 22:25:59 -07:00
+++ b/net/core/sock.c	2004-10-28 22:25:59 -07:00
@@ -175,6 +175,15 @@
 	}
 }
 
+static void sock_disable_timestamp(struct sock *sk)
+{	
+	if (sock_flag(sk, SOCK_TIMESTAMP)) { 
+		sock_reset_flag(sk, SOCK_TIMESTAMP);
+		atomic_dec(&netstamp_needed);
+	}
+}
+
+
 /*
  *	This is meant for all protocols to use and covers goings on
  *	at the socket level. Everything here is generic.
@@ -972,11 +981,6 @@
  * function, some default processing is provided.
  */
 
-int sock_no_release(struct socket *sock)
-{
-	return 0;
-}
-
 int sock_no_bind(struct socket *sock, struct sockaddr *saddr, int len)
 {
 	return -EOPNOTSUPP;
@@ -1247,15 +1251,6 @@
 }
 EXPORT_SYMBOL(sock_enable_timestamp); 
 
-void sock_disable_timestamp(struct sock *sk)
-{	
-	if (sock_flag(sk, SOCK_TIMESTAMP)) { 
-		sock_reset_flag(sk, SOCK_TIMESTAMP);
-		atomic_dec(&netstamp_needed);
-	}
-}
-EXPORT_SYMBOL(sock_disable_timestamp);
-
 /*
  *	Get a socket option on an socket.
  *
@@ -1371,7 +1366,6 @@
 EXPORT_SYMBOL(sk_send_sigurg);
 EXPORT_SYMBOL(sock_alloc_send_pskb);
 EXPORT_SYMBOL(sock_alloc_send_skb);
-EXPORT_SYMBOL(sock_getsockopt);
 EXPORT_SYMBOL(sock_init_data);
 EXPORT_SYMBOL(sock_kfree_s);
 EXPORT_SYMBOL(sock_kmalloc);
@@ -1385,14 +1379,12 @@
 EXPORT_SYMBOL(sock_no_mmap);
 EXPORT_SYMBOL(sock_no_poll);
 EXPORT_SYMBOL(sock_no_recvmsg);
-EXPORT_SYMBOL(sock_no_release);
 EXPORT_SYMBOL(sock_no_sendmsg);
 EXPORT_SYMBOL(sock_no_sendpage);
 EXPORT_SYMBOL(sock_no_setsockopt);
 EXPORT_SYMBOL(sock_no_shutdown);
 EXPORT_SYMBOL(sock_no_socketpair);
 EXPORT_SYMBOL(sock_rfree);
-EXPORT_SYMBOL(sock_rmalloc);
 EXPORT_SYMBOL(sock_setsockopt);
 EXPORT_SYMBOL(sock_wfree);
 EXPORT_SYMBOL(sock_wmalloc);
diff -Nru a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
--- a/net/decnet/dn_nsp_in.c	2004-10-28 22:25:57 -07:00
+++ b/net/decnet/dn_nsp_in.c	2004-10-28 22:25:57 -07:00
@@ -419,6 +419,7 @@
 		case DN_CI:
 		case DN_CD:
 			scp->state = DN_RJ;
+			sk->sk_err = ECONNREFUSED;
 			break;
 		case DN_RUN:
 			sk->sk_shutdown |= SHUTDOWN_MASK;
diff -Nru a/net/decnet/dn_route.c b/net/decnet/dn_route.c
--- a/net/decnet/dn_route.c	2004-10-28 22:25:59 -07:00
+++ b/net/decnet/dn_route.c	2004-10-28 22:25:59 -07:00
@@ -287,10 +287,9 @@
 		if (compare_keys(&rth->fl, &rt->fl)) {
 			/* Put it first */
 			*rthp = rth->u.rt_next;
-			smp_wmb();
-			rth->u.rt_next = dn_rt_hash_table[hash].chain;
-			smp_wmb();
-			dn_rt_hash_table[hash].chain = rth;
+			rcu_assign_pointer(rth->u.rt_next,
+					   dn_rt_hash_table[hash].chain);
+			rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
 
 			rth->u.dst.__use++;
 			dst_hold(&rth->u.dst);
@@ -304,10 +303,8 @@
 		rthp = &rth->u.rt_next;
 	}
 
-	smp_wmb();
-	rt->u.rt_next = dn_rt_hash_table[hash].chain;
-	smp_wmb();
-	dn_rt_hash_table[hash].chain = rt;
+	rcu_assign_pointer(rt->u.rt_next, dn_rt_hash_table[hash].chain);
+	rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
 	
 	dst_hold(&rt->u.dst);
 	rt->u.dst.__use++;
@@ -683,9 +680,8 @@
 	return NET_RX_DROP;
 }
 
-static int dn_output(struct sk_buff **pskb)
+static int dn_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct dst_entry *dst = skb->dst;
 	struct dn_route *rt = (struct dn_route *)dst;
 	struct net_device *dev = dst->dev;
@@ -796,11 +792,6 @@
 	return NET_RX_BAD;
 }
 
-static int dn_rt_bug_out(struct sk_buff **pskb)
-{
-	return dn_rt_bug(*pskb);
-}
-
 static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
 {
 	struct dn_fib_info *fi = res->fi;
@@ -1392,7 +1383,7 @@
 	rt->u.dst.neighbour = neigh;
 	rt->u.dst.dev = out_dev;
 	rt->u.dst.lastuse = jiffies;
-	rt->u.dst.output = dn_rt_bug_out;
+	rt->u.dst.output = dn_rt_bug;
 	switch(res.type) {
 		case RTN_UNICAST:
 			rt->u.dst.input = dn_forward;
diff -Nru a/net/ipv4/Kconfig b/net/ipv4/Kconfig
--- a/net/ipv4/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/net/ipv4/Kconfig	2004-10-28 22:25:59 -07:00
@@ -331,8 +331,8 @@
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
-	  Support for IP Paylod Compression (RFC3173), typically needed
-	  for IPsec.
+	  Support for IP Payload Compression Protocol (IPComp) (RFC3173),
+	  typically needed for IPsec.
 	  
 	  If unsure, say Y.
 
diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
--- a/net/ipv4/af_inet.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/af_inet.c	2004-10-28 22:25:57 -07:00
@@ -1165,8 +1165,6 @@
 EXPORT_SYMBOL(inet_stream_ops);
 EXPORT_SYMBOL(inet_unregister_protosw);
 EXPORT_SYMBOL(net_statistics);
-EXPORT_SYMBOL(tcp_protocol);
-EXPORT_SYMBOL(udp_protocol);
 
 #ifdef INET_REFCNT_DEBUG
 EXPORT_SYMBOL(inet_sock_nr);
diff -Nru a/net/ipv4/devinet.c b/net/ipv4/devinet.c
--- a/net/ipv4/devinet.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/devinet.c	2004-10-28 22:25:57 -07:00
@@ -158,8 +158,7 @@
 
 	/* Account for reference dev->ip_ptr */
 	in_dev_hold(in_dev);
-	smp_wmb();
-	dev->ip_ptr = in_dev;
+	rcu_assign_pointer(dev->ip_ptr, in_dev);
 
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl_register(in_dev, &in_dev->cnf);
diff -Nru a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
--- a/net/ipv4/fib_semantics.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/fib_semantics.c	2004-10-28 22:25:57 -07:00
@@ -163,6 +163,8 @@
 		if (fi->fib_prefsrc)
 			hlist_del(&fi->fib_lhash);
 		change_nexthops(fi) {
+			if (!nh->nh_dev)
+				continue;
 			hlist_del(&nh->nh_hash);
 		} endfor_nexthops(fi)
 		fi->fib_dead = 1;
diff -Nru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
--- a/net/ipv4/ip_output.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv4/ip_output.c	2004-10-28 22:25:59 -07:00
@@ -224,9 +224,8 @@
 		       ip_finish_output2);
 }
 
-int ip_mc_output(struct sk_buff **pskb)
+int ip_mc_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct sock *sk = skb->sk;
 	struct rtable *rt = (struct rtable*)skb->dst;
 	struct net_device *dev = rt->u.dst.dev;
@@ -285,10 +284,8 @@
 		return ip_finish_output(skb);
 }
 
-int ip_output(struct sk_buff **pskb)
+int ip_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
-
 	IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
 
 	if ((skb->len > dst_pmtu(skb->dst) || skb_shinfo(skb)->frag_list) &&
diff -Nru a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
--- a/net/ipv4/netfilter/arp_tables.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv4/netfilter/arp_tables.c	2004-10-28 22:25:59 -07:00
@@ -395,7 +395,7 @@
 	return find_inlist_lock(&arpt_tables, name, "arptable_", error, mutex);
 }
 
-struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
+static struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&arpt_target, name, "arpt_", error, mutex);
 }
@@ -1325,7 +1325,6 @@
 EXPORT_SYMBOL(arpt_register_table);
 EXPORT_SYMBOL(arpt_unregister_table);
 EXPORT_SYMBOL(arpt_do_table);
-EXPORT_SYMBOL(arpt_find_target_lock);
 EXPORT_SYMBOL(arpt_register_target);
 EXPORT_SYMBOL(arpt_unregister_target);
 
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c	2004-10-28 22:25:56 -07:00
+++ b/net/ipv4/netfilter/ip_conntrack_core.c	2004-10-28 22:25:56 -07:00
@@ -352,16 +352,14 @@
 {
 	struct ip_conntrack_tuple_hash *h;
 	unsigned int hash = hash_conntrack(tuple);
-	/* use per_cpu() to avoid multiple calls to smp_processor_id() */
-	unsigned int cpu = smp_processor_id();
 
 	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
 	list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
 		if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) {
-			per_cpu(ip_conntrack_stat, cpu).found++;
+			CONNTRACK_STAT_INC(found);
 			return h;
 		}
-		per_cpu(ip_conntrack_stat, cpu).searched++;
+		CONNTRACK_STAT_INC(searched);
 	}
 
 	return NULL;
@@ -436,13 +434,14 @@
 		add_timer(&ct->timeout);
 		atomic_inc(&ct->ct_general.use);
 		set_bit(IPS_CONFIRMED_BIT, &ct->status);
-		WRITE_UNLOCK(&ip_conntrack_lock);
 		CONNTRACK_STAT_INC(insert);
+		WRITE_UNLOCK(&ip_conntrack_lock);
 		return NF_ACCEPT;
 	}
 
-	WRITE_UNLOCK(&ip_conntrack_lock);
 	CONNTRACK_STAT_INC(insert_failed);
+	WRITE_UNLOCK(&ip_conntrack_lock);
+
 	return NF_DROP;
 }
 
diff -Nru a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
--- a/net/ipv4/netfilter/ip_fw_compat.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/netfilter/ip_fw_compat.c	2004-10-28 22:25:57 -07:00
@@ -69,7 +69,7 @@
 	/* Assume worse case: any hook could change packet */
 	(*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
 	if ((*pskb)->ip_summed == CHECKSUM_HW)
-		if (skb_checksum_help(pskb, (out == NULL)))
+		if (skb_checksum_help(*pskb, (out == NULL)))
 			return NF_DROP;
 
 	switch (hooknum) {
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv4/netfilter/ip_nat_standalone.c	2004-10-28 22:25:59 -07:00
@@ -86,7 +86,7 @@
 
 	/* If we had a hardware checksum before, it's now invalid */
 	if ((*pskb)->ip_summed == CHECKSUM_HW)
-		if (skb_checksum_help(pskb, (out == NULL)))
+		if (skb_checksum_help(*pskb, (out == NULL)))
 			return NF_DROP;
 
 	ct = ip_conntrack_get(*pskb, &ctinfo);
diff -Nru a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
--- a/net/ipv4/netfilter/ip_tables.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/netfilter/ip_tables.c	2004-10-28 22:25:57 -07:00
@@ -471,7 +471,7 @@
 	return find_inlist_lock(&ipt_match, name, "ipt_", error, mutex);
 }
 
-struct ipt_target *
+static struct ipt_target *
 ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
@@ -1877,7 +1877,6 @@
 EXPORT_SYMBOL(ipt_do_table);
 EXPORT_SYMBOL(ipt_register_target);
 EXPORT_SYMBOL(ipt_unregister_target);
-EXPORT_SYMBOL(ipt_find_target_lock);
 
 module_init(init);
 module_exit(fini);
diff -Nru a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/ipv4/netfilter/ipt_CONNMARK.c
--- a/net/ipv4/netfilter/ipt_CONNMARK.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/netfilter/ipt_CONNMARK.c	2004-10-28 22:25:57 -07:00
@@ -60,7 +60,7 @@
 		break;
 	    case IPT_CONNMARK_RESTORE:
 		nfmark = (*pskb)->nfmark;
-		diff = (ct->mark ^ nfmark & markinfo->mask);
+		diff = (ct->mark ^ nfmark) & markinfo->mask;
 		if (diff != 0) {
 		    (*pskb)->nfmark = nfmark ^ diff;
 		    (*pskb)->nfcache |= NFC_ALTERED;
diff -Nru a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
--- a/net/ipv4/netfilter/ipt_ECN.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv4/netfilter/ipt_ECN.c	2004-10-28 22:25:59 -07:00
@@ -86,7 +86,7 @@
 		memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4,
 		       &_tcph, sizeof(_tcph));
 		if ((*pskb)->ip_summed == CHECKSUM_HW)
-			if (skb_checksum_help(pskb, inward))
+			if (skb_checksum_help(*pskb, inward))
 				return 0;
 		(*pskb)->nfcache |= NFC_ALTERED;
 	}
diff -Nru a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-10-28 22:25:58 -07:00
@@ -81,8 +81,8 @@
 	enum ip_conntrack_info ctinfo;
 	const struct ip_nat_multi_range *mr;
 	struct ip_nat_multi_range newrange;
-	u_int32_t newsrc;
 	struct rtable *rt;
+	u_int32_t newsrc;
 
 	IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
 
@@ -96,36 +96,13 @@
 	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 
 	mr = targinfo;
-
-	{
-		struct flowi fl = { .nl_u = { .ip4_u =
-					      { .daddr = (*pskb)->nh.iph->daddr,
-						.tos = (RT_TOS((*pskb)->nh.iph->tos) |
-							RTO_CONN),
-#ifdef CONFIG_IP_ROUTE_FWMARK
-						.fwmark = (*pskb)->nfmark
-#endif
-					      } } };
-		if (ip_route_output_key(&rt, &fl) != 0) {
-			/* Funky routing can do this. */
-			if (net_ratelimit())
-				printk("MASQUERADE:"
-				       " No route: Rusty's brain broke!\n");
-			return NF_DROP;
-		}
-		if (rt->u.dst.dev != out) {
-			if (net_ratelimit())
-				printk("MASQUERADE:"
-				       " Route sent us somewhere else.\n");
-			ip_rt_put(rt);
-			return NF_DROP;
-		}
+	rt = (struct rtable *)(*pskb)->dst;
+	newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+	if (!newsrc) {
+		printk("MASQUERADE: %s ate my IP address\n", out->name);
+		return NF_DROP;
 	}
 
-	newsrc = rt->rt_src;
-	DEBUGP("newsrc = %u.%u.%u.%u\n", NIPQUAD(newsrc));
-	ip_rt_put(rt);
-
 	WRITE_LOCK(&masq_lock);
 	ct->nat.masq_index = out->ifindex;
 	WRITE_UNLOCK(&masq_lock);
@@ -157,6 +134,18 @@
 	return ret;
 }
 
+static inline int
+connect_unassure(const struct ip_conntrack *i, void *_ina)
+{
+	struct in_ifaddr *ina = _ina;
+
+	/* We reset the ASSURED bit on all connections, so they will
+	 * get reaped under memory pressure. */
+	if (i->nat.masq_index == ina->ifa_dev->dev->ifindex)
+		clear_bit(IPS_ASSURED_BIT, (unsigned long *)&i->status);
+	return 0;
+}
+
 static int masq_inet_event(struct notifier_block *this,
 			   unsigned long event,
 			   void *ptr)
@@ -166,6 +155,8 @@
 	 * entries. */
 	if (event == NETDEV_UP)
 		ip_ct_selective_cleanup(device_cmp, ptr);
+	else if (event == NETDEV_DOWN)
+		ip_ct_selective_cleanup(connect_unassure, ptr);
 
 	return NOTIFY_DONE;
 }
diff -Nru a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
--- a/net/ipv4/netfilter/ipt_ULOG.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/netfilter/ipt_ULOG.c	2004-10-28 22:25:57 -07:00
@@ -1,7 +1,7 @@
 /*
  * netfilter module for userspace packet logging daemons
  *
- * (C) 2000-2002 by Harald Welte <laforge@netfilter.org>
+ * (C) 2000-2004 by Harald Welte <laforge@netfilter.org>
  *
  * 2000/09/22 ulog-cprange feature added
  * 2001/01/04 in-kernel queue as proposed by Sebastian Zander 
@@ -13,6 +13,8 @@
  * 2002/07/07 remove broken nflog_rcv() function -HW
  * 2002/08/29 fix shifted/unshifted nlgroup bug -HW
  * 2002/10/30 fix uninitialized mac_len field - <Anders K. Pedersen>
+ * 2004/10/25 fix erroneous calculation of 'len' parameter to NLMSG_PUT
+ *	      resulting in bogus 'error during NLMSG_PUT' messages.
  *
  * (C) 1999-2001 Paul `Rusty' Russell
  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
@@ -212,7 +214,7 @@
 
 	/* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
 	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, 
-			size - sizeof(*nlh));
+			sizeof(*pm)+copy_len);
 	ub->qlen++;
 
 	pm = NLMSG_DATA(nlh);
diff -Nru a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
--- a/net/ipv4/netfilter/ipt_hashlimit.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv4/netfilter/ipt_hashlimit.c	2004-10-28 22:25:58 -07:00
@@ -121,7 +121,6 @@
 {
 	struct dsthash_ent *ent;
 	u_int32_t hash = hash_dst(ht, dst);
-	MUST_BE_LOCKED(&ht->lock);
 	ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
 	return ent;
 }
@@ -170,8 +169,6 @@
 static inline void 
 __dsthash_free(struct ipt_hashlimit_htable *ht, struct dsthash_ent *ent)
 {
-	MUST_BE_LOCKED(&ht->lock);
-
 	list_del(&ent->list);
 	kmem_cache_free(hashlimit_cachep, ent);
 	atomic_dec(&ht->count);
@@ -258,7 +255,7 @@
 	IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
 
 	/* lock hash table and iterate over it */
-	LOCK_BH(&ht->lock);
+	spin_lock_bh(&ht->lock);
 	for (i = 0; i < ht->cfg.size; i++) {
 		struct dsthash_ent *dh, *n;
 		list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
@@ -266,7 +263,7 @@
 				__dsthash_free(ht, dh);
 		}
 	}
-	UNLOCK_BH(&ht->lock);
+	spin_unlock_bh(&ht->lock);
 }
 
 /* hash table garbage collector, run by timer */
@@ -457,7 +454,7 @@
 			dst.dst_port = ports[1];
 	} 
 
-	LOCK_BH(&hinfo->lock);
+	spin_lock_bh(&hinfo->lock);
 	dh = __dsthash_find(hinfo, &dst);
 	if (!dh) {
 		dh = __dsthash_alloc_init(hinfo, &dst);
@@ -466,7 +463,7 @@
 			/* enomem... don't match == DROP */
 			if (net_ratelimit())
 				printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
-			UNLOCK_BH(&hinfo->lock);
+			spin_unlock_bh(&hinfo->lock);
 			return 0;
 		}
 
@@ -479,7 +476,7 @@
 							hinfo->cfg.burst);
 		dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
 
-		UNLOCK_BH(&hinfo->lock);
+		spin_unlock_bh(&hinfo->lock);
 		return 1;
 	}
 
@@ -490,11 +487,11 @@
 	if (dh->rateinfo.credit >= dh->rateinfo.cost) {
 		/* We're underlimit. */
 		dh->rateinfo.credit -= dh->rateinfo.cost;
-		UNLOCK_BH(&hinfo->lock);
+		spin_unlock_bh(&hinfo->lock);
 		return 1;
 	}
 
-       	UNLOCK_BH(&hinfo->lock);
+       	spin_unlock_bh(&hinfo->lock);
 
 	/* default case: we're overlimit, thus don't match */
 	return 0;
@@ -569,7 +566,7 @@
 	struct ipt_hashlimit_htable *htable = pde->data;
 	unsigned int *bucket;
 
-	LOCK_BH(&htable->lock);
+	spin_lock_bh(&htable->lock);
 	if (*pos >= htable->cfg.size)
 		return NULL;
 
@@ -603,7 +600,7 @@
 
 	kfree(bucket);
 
-	UNLOCK_BH(&htable->lock);
+	spin_unlock_bh(&htable->lock);
 }
 
 static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv4/raw.c	2004-10-28 22:25:58 -07:00
@@ -407,7 +407,7 @@
 				printk(KERN_INFO "%s forgot to set AF_INET in "
 						 "raw sendmsg. Fix it!\n",
 						 current->comm);
-			err = -EINVAL;
+			err = -EAFNOSUPPORT;
 			if (usin->sin_family)
 				goto out;
 		}
diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c
--- a/net/ipv4/route.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv4/route.c	2004-10-28 22:25:59 -07:00
@@ -801,14 +801,13 @@
 			 * must be visible to another weakly ordered CPU before
 			 * the insertion at the start of the hash chain.
 			 */
-			smp_wmb();
-			rth->u.rt_next = rt_hash_table[hash].chain;
+			rcu_assign_pointer(rth->u.rt_next,
+					   rt_hash_table[hash].chain);
 			/*
 			 * Since lookup is lockfree, the update writes
 			 * must be ordered for consistency on SMP.
 			 */
-			smp_wmb();
-			rt_hash_table[hash].chain = rth;
+			rcu_assign_pointer(rt_hash_table[hash].chain, rth);
 
 			rth->u.dst.__use++;
 			dst_hold(&rth->u.dst);
@@ -1367,10 +1366,8 @@
 		dst_set_expires(&rt->u.dst, 0);
 }
 
-static int ip_rt_bug(struct sk_buff **pskb)
+static int ip_rt_bug(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
-
 	printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
 		NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr),
 		skb->dev ? skb->dev->name : "?");
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/tcp.c	2004-10-28 22:25:57 -07:00
@@ -2095,6 +2095,63 @@
 	return err;
 }
 
+/* Return information about state of tcp endpoint in API format. */
+void tcp_get_info(struct sock *sk, struct tcp_info *info)
+{
+	struct tcp_opt *tp = tcp_sk(sk);
+	u32 now = tcp_time_stamp;
+
+	memset(info, 0, sizeof(*info));
+
+	info->tcpi_state = sk->sk_state;
+	info->tcpi_ca_state = tp->ca_state;
+	info->tcpi_retransmits = tp->retransmits;
+	info->tcpi_probes = tp->probes_out;
+	info->tcpi_backoff = tp->backoff;
+
+	if (tp->tstamp_ok)
+		info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
+	if (tp->sack_ok)
+		info->tcpi_options |= TCPI_OPT_SACK;
+	if (tp->wscale_ok) {
+		info->tcpi_options |= TCPI_OPT_WSCALE;
+		info->tcpi_snd_wscale = tp->snd_wscale;
+		info->tcpi_rcv_wscale = tp->rcv_wscale;
+	} 
+
+	if (tp->ecn_flags&TCP_ECN_OK)
+		info->tcpi_options |= TCPI_OPT_ECN;
+
+	info->tcpi_rto = jiffies_to_usecs(tp->rto);
+	info->tcpi_ato = jiffies_to_usecs(tp->ack.ato);
+	info->tcpi_snd_mss = tp->mss_cache_std;
+	info->tcpi_rcv_mss = tp->ack.rcv_mss;
+
+	info->tcpi_unacked = tcp_get_pcount(&tp->packets_out);
+	info->tcpi_sacked = tcp_get_pcount(&tp->sacked_out);
+	info->tcpi_lost = tcp_get_pcount(&tp->lost_out);
+	info->tcpi_retrans = tcp_get_pcount(&tp->retrans_out);
+	info->tcpi_fackets = tcp_get_pcount(&tp->fackets_out);
+
+	info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
+	info->tcpi_last_data_recv = jiffies_to_msecs(now - tp->ack.lrcvtime);
+	info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
+
+	info->tcpi_pmtu = tp->pmtu_cookie;
+	info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
+	info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
+	info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
+	info->tcpi_snd_ssthresh = tp->snd_ssthresh;
+	info->tcpi_snd_cwnd = tp->snd_cwnd;
+	info->tcpi_advmss = tp->advmss;
+	info->tcpi_reordering = tp->reordering;
+
+	info->tcpi_rcv_rtt = jiffies_to_usecs(tp->rcv_rtt_est.rtt)>>3;
+	info->tcpi_rcv_space = tp->rcvq_space.space;
+
+	info->tcpi_total_retrans = tp->total_retrans;
+}
+
 int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
 		   int __user *optlen)
 {
@@ -2307,7 +2364,6 @@
 
 EXPORT_SYMBOL(tcp_accept);
 EXPORT_SYMBOL(tcp_close);
-EXPORT_SYMBOL(tcp_close_state);
 EXPORT_SYMBOL(tcp_destroy_sock);
 EXPORT_SYMBOL(tcp_disconnect);
 EXPORT_SYMBOL(tcp_getsockopt);
diff -Nru a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
--- a/net/ipv4/tcp_diag.c	2004-10-28 22:25:56 -07:00
+++ b/net/ipv4/tcp_diag.c	2004-10-28 22:25:56 -07:00
@@ -52,65 +52,8 @@
    rta->rta_len = rtalen;                   \
    RTA_DATA(rta); })
 
-/* Return information about state of tcp endpoint in API format. */
-void tcp_get_info(struct sock *sk, struct tcp_info *info)
-{
-	struct tcp_opt *tp = tcp_sk(sk);
-	u32 now = tcp_time_stamp;
-
-	memset(info, 0, sizeof(*info));
-
-	info->tcpi_state = sk->sk_state;
-	info->tcpi_ca_state = tp->ca_state;
-	info->tcpi_retransmits = tp->retransmits;
-	info->tcpi_probes = tp->probes_out;
-	info->tcpi_backoff = tp->backoff;
-
-	if (tp->tstamp_ok)
-		info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
-	if (tp->sack_ok)
-		info->tcpi_options |= TCPI_OPT_SACK;
-	if (tp->wscale_ok) {
-		info->tcpi_options |= TCPI_OPT_WSCALE;
-		info->tcpi_snd_wscale = tp->snd_wscale;
-		info->tcpi_rcv_wscale = tp->rcv_wscale;
-	} 
-
-	if (tp->ecn_flags&TCP_ECN_OK)
-		info->tcpi_options |= TCPI_OPT_ECN;
-
-	info->tcpi_rto = jiffies_to_usecs(tp->rto);
-	info->tcpi_ato = jiffies_to_usecs(tp->ack.ato);
-	info->tcpi_snd_mss = tp->mss_cache_std;
-	info->tcpi_rcv_mss = tp->ack.rcv_mss;
-
-	info->tcpi_unacked = tcp_get_pcount(&tp->packets_out);
-	info->tcpi_sacked = tcp_get_pcount(&tp->sacked_out);
-	info->tcpi_lost = tcp_get_pcount(&tp->lost_out);
-	info->tcpi_retrans = tcp_get_pcount(&tp->retrans_out);
-	info->tcpi_fackets = tcp_get_pcount(&tp->fackets_out);
-
-	info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
-	info->tcpi_last_data_recv = jiffies_to_msecs(now - tp->ack.lrcvtime);
-	info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
-
-	info->tcpi_pmtu = tp->pmtu_cookie;
-	info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
-	info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
-	info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
-	info->tcpi_snd_ssthresh = tp->snd_ssthresh;
-	info->tcpi_snd_cwnd = tp->snd_cwnd;
-	info->tcpi_advmss = tp->advmss;
-	info->tcpi_reordering = tp->reordering;
-
-	info->tcpi_rcv_rtt = jiffies_to_usecs(tp->rcv_rtt_est.rtt)>>3;
-	info->tcpi_rcv_space = tp->rcvq_space.space;
-
-	info->tcpi_total_retrans = tp->total_retrans;
-}
-
 static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
-			int ext, u32 pid, u32 seq)
+			int ext, u32 pid, u32 seq, u16 nlmsg_flags)
 {
 	struct inet_opt *inet = inet_sk(sk);
 	struct tcp_opt *tp = tcp_sk(sk);
@@ -122,6 +65,7 @@
 	unsigned char	 *b = skb->tail;
 
 	nlh = NLMSG_PUT(skb, pid, seq, TCPDIAG_GETSOCK, sizeof(*r));
+	nlh->nlmsg_flags = nlmsg_flags;
 	r = NLMSG_DATA(nlh);
 	if (sk->sk_state != TCP_TIME_WAIT) {
 		if (ext & (1<<(TCPDIAG_MEMINFO-1)))
@@ -293,7 +237,7 @@
 
 	if (tcpdiag_fill(rep, sk, req->tcpdiag_ext,
 			 NETLINK_CB(in_skb).pid,
-			 nlh->nlmsg_seq) <= 0)
+			 nlh->nlmsg_seq, 0) <= 0)
 		BUG();
 
 	err = netlink_unicast(tcpnl, rep, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
@@ -499,7 +443,7 @@
 	}
 
 	return tcpdiag_fill(skb, sk, r->tcpdiag_ext, NETLINK_CB(cb->skb).pid,
-			    cb->nlh->nlmsg_seq);
+			    cb->nlh->nlmsg_seq, NLM_F_MULTI);
 }
 
 static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
@@ -513,6 +457,7 @@
 	long tmo;
 
 	nlh = NLMSG_PUT(skb, pid, seq, TCPDIAG_GETSOCK, sizeof(*r));
+	nlh->nlmsg_flags = NLM_F_MULTI;
 	r = NLMSG_DATA(nlh);
 
 	r->tcpdiag_family = sk->sk_family;
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv4/tcp_input.c	2004-10-28 22:25:59 -07:00
@@ -2369,25 +2369,19 @@
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 	struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
-	__u32 mss = tcp_skb_mss(skb);
-	__u32 snd_una = tp->snd_una;
-	__u32 orig_seq, seq;
-	__u32 packets_acked = 0;
+	__u32 seq = tp->snd_una;
+	__u32 packets_acked;
 	int acked = 0;
 
 	/* If we get here, the whole TSO packet has not been
 	 * acked.
 	 */
-	BUG_ON(!after(scb->end_seq, snd_una));
+	BUG_ON(!after(scb->end_seq, seq));
 
-	seq = orig_seq = scb->seq;
-	while (!after(seq + mss, snd_una)) {
-		packets_acked++;
-		seq += mss;
-	}
-
-	if (tcp_trim_head(sk, skb, (seq - orig_seq)))
+	packets_acked = tcp_skb_pcount(skb);
+	if (tcp_trim_head(sk, skb, seq - scb->seq))
 		return 0;
+	packets_acked -= tcp_skb_pcount(skb);
 
 	if (packets_acked) {
 		__u8 sacked = scb->sacked;
@@ -4963,7 +4957,6 @@
 
 EXPORT_SYMBOL(sysctl_tcp_ecn);
 EXPORT_SYMBOL(sysctl_tcp_reordering);
-EXPORT_SYMBOL(tcp_cwnd_application_limited);
 EXPORT_SYMBOL(tcp_parse_options);
 EXPORT_SYMBOL(tcp_rcv_established);
 EXPORT_SYMBOL(tcp_rcv_state_process);
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/tcp_ipv4.c	2004-10-28 22:25:57 -07:00
@@ -448,8 +448,8 @@
 }
 
 /* Optimize the common listener case. */
-inline struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum,
-					   int dif)
+static inline struct sock *tcp_v4_lookup_listener(u32 daddr,
+		unsigned short hnum, int dif)
 {
 	struct sock *sk = NULL;
 	struct hlist_head *head;
@@ -2653,7 +2653,6 @@
 EXPORT_SYMBOL(tcp_v4_conn_request);
 EXPORT_SYMBOL(tcp_v4_connect);
 EXPORT_SYMBOL(tcp_v4_do_rcv);
-EXPORT_SYMBOL(tcp_v4_lookup_listener);
 EXPORT_SYMBOL(tcp_v4_rebuild_header);
 EXPORT_SYMBOL(tcp_v4_remember_stamp);
 EXPORT_SYMBOL(tcp_v4_send_check);
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv4/tcp_output.c	2004-10-28 22:25:58 -07:00
@@ -588,7 +588,8 @@
 	/* Any change of skb->len requires recalculation of tso
 	 * factor and mss.
 	 */
-	tcp_set_skb_tso_segs(skb, tcp_skb_mss(skb));
+	if (tcp_skb_pcount(skb) > 1)
+		tcp_set_skb_tso_segs(skb, tcp_skb_mss(skb));
 
 	return 0;
 }
@@ -1719,12 +1720,7 @@
 	}
 }
 
-EXPORT_SYMBOL(tcp_acceptable_seq);
 EXPORT_SYMBOL(tcp_connect);
-EXPORT_SYMBOL(tcp_connect_init);
 EXPORT_SYMBOL(tcp_make_synack);
-EXPORT_SYMBOL(tcp_send_synack);
 EXPORT_SYMBOL(tcp_simple_retransmit);
 EXPORT_SYMBOL(tcp_sync_mss);
-EXPORT_SYMBOL(tcp_write_wakeup);
-EXPORT_SYMBOL(tcp_write_xmit);
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/udp.c	2004-10-28 22:25:57 -07:00
@@ -531,7 +531,7 @@
 			return -EINVAL;
 		if (usin->sin_family != AF_INET) {
 			if (usin->sin_family != AF_UNSPEC)
-				return -EINVAL;
+				return -EAFNOSUPPORT;
 		}
 
 		daddr = usin->sin_addr.s_addr;
diff -Nru a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
--- a/net/ipv4/xfrm4_output.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv4/xfrm4_output.c	2004-10-28 22:25:57 -07:00
@@ -91,16 +91,14 @@
 	return ret;
 }
 
-int xfrm4_output(struct sk_buff **pskb)
+int xfrm4_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	int err;
 	
 	if (skb->ip_summed == CHECKSUM_HW) {
-		err = skb_checksum_help(pskb, 0);
-		skb = *pskb;
+		err = skb_checksum_help(skb, 0);
 		if (err)
 			goto error_nolock;
 	}
diff -Nru a/net/ipv6/Kconfig b/net/ipv6/Kconfig
--- a/net/ipv6/Kconfig	2004-10-28 22:25:58 -07:00
+++ b/net/ipv6/Kconfig	2004-10-28 22:25:58 -07:00
@@ -52,8 +52,8 @@
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
-	  Support for IP Paylod Compression (RFC3173), typically needed
-	  for IPsec.
+	  Support for IP Payload Compression Protocol (IPComp) (RFC3173),
+	  typically needed for IPsec.
 
 	  If unsure, say Y.
 
diff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
--- a/net/ipv6/addrconf.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/addrconf.c	2004-10-28 22:25:59 -07:00
@@ -404,6 +404,7 @@
 	return idev;
 }
 
+#ifdef CONFIG_SYSCTL
 static void dev_forward_change(struct inet6_dev *idev)
 {
 	struct net_device *dev;
@@ -449,7 +450,7 @@
 	}
 	read_unlock(&dev_base_lock);
 }
-
+#endif
 
 /* Nobody refers to this ifaddr, destroy it */
 
@@ -760,7 +761,7 @@
 #endif
 
 int ipv6_dev_get_saddr(struct net_device *dev,
-		   struct in6_addr *daddr, struct in6_addr *saddr, int onlink)
+		       struct in6_addr *daddr, struct in6_addr *saddr)
 {
 	struct inet6_ifaddr *ifp = NULL;
 	struct inet6_ifaddr *match = NULL;
@@ -769,10 +770,7 @@
 	int err;
 	int hiscore = -1, score;
 
-	if (!onlink)
-		scope = ipv6_addr_scope(daddr);
-	else
-		scope = IFA_LINK;
+	scope = ipv6_addr_scope(daddr);
 
 	/*
 	 *	known dev
@@ -877,17 +875,7 @@
 int ipv6_get_saddr(struct dst_entry *dst,
 		   struct in6_addr *daddr, struct in6_addr *saddr)
 {
-	struct rt6_info *rt;
-	struct net_device *dev = NULL;
-	int onlink;
-
-	rt = (struct rt6_info *) dst;
-	if (rt)
-		dev = rt->rt6i_dev;
-
-	onlink = (rt && (rt->rt6i_flags & RTF_ALLONLINK));
-
-	return ipv6_dev_get_saddr(dev, daddr, saddr, onlink);
+	return ipv6_dev_get_saddr(dst ? dst->dev : NULL, daddr, saddr);
 }
 
 
@@ -3042,7 +3030,7 @@
 			addrconf_forward_change();
 		}
 		if (*valp)
-			rt6_purge_dflt_routers(0);
+			rt6_purge_dflt_routers();
 	}
 
         return ret;
@@ -3096,7 +3084,7 @@
 		}
 
 		if (*valp)
-			rt6_purge_dflt_routers(0);
+			rt6_purge_dflt_routers();
 	} else
 		*valp = new;
 
diff -Nru a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
--- a/net/ipv6/ip6_fib.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/ip6_fib.c	2004-10-28 22:25:59 -07:00
@@ -433,7 +433,7 @@
 
 	if (fn->fn_flags&RTN_TL_ROOT &&
 	    fn->leaf == &ip6_null_entry &&
-	    !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF | RTF_ALLONLINK)) ){
+	    !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
 		fn->leaf = rt;
 		rt->u.next = NULL;
 		goto out;
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	2004-10-28 22:25:56 -07:00
+++ b/net/ipv6/ip6_output.c	2004-10-28 22:25:56 -07:00
@@ -56,7 +56,7 @@
 #include <net/xfrm.h>
 #include <net/checksum.h>
 
-static int ip6_fragment(struct sk_buff **pskb, int (*output)(struct sk_buff**));
+static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 
 static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
 {
@@ -108,9 +108,8 @@
 }
 
 
-static int ip6_output2(struct sk_buff **pskb)
+static int ip6_output2(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct dst_entry *dst = skb->dst;
 	struct net_device *dev = dst->dev;
 
@@ -146,14 +145,12 @@
 	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish);
 }
 
-int ip6_output(struct sk_buff **pskb)
+int ip6_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
-
 	if ((skb->len > dst_pmtu(skb->dst) || skb_shinfo(skb)->frag_list))
-		return ip6_fragment(pskb, ip6_output2);
+		return ip6_fragment(skb, ip6_output2);
 	else
-		return ip6_output2(pskb);
+		return ip6_output2(skb);
 }
 
 #ifdef CONFIG_NETFILTER
@@ -518,10 +515,10 @@
 	return offset;
 }
 
-static int ip6_fragment(struct sk_buff **pskb, int (*output)(struct sk_buff**))
+static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
 	struct net_device *dev;
-	struct sk_buff *frag, *skb = *pskb;
+	struct sk_buff *frag;
 	struct rt6_info *rt = (struct rt6_info*)skb->dst;
 	struct ipv6hdr *tmp_hdr;
 	struct frag_hdr *fh;
@@ -610,7 +607,7 @@
 				ip6_copy_metadata(frag, skb);
 			}
 			
-			err = output(&skb);
+			err = output(skb);
 			if (err || !frag)
 				break;
 
@@ -726,7 +723,7 @@
 
 		IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
 
-		err = output(&frag);
+		err = output(frag);
 		if (err)
 			goto fail;
 	}
diff -Nru a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
--- a/net/ipv6/ipv6_syms.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv6/ipv6_syms.c	2004-10-28 22:25:58 -07:00
@@ -35,13 +35,9 @@
 EXPORT_SYMBOL(in6addr_any);
 EXPORT_SYMBOL(in6addr_loopback);
 EXPORT_SYMBOL(in6_dev_finish_destroy);
-EXPORT_SYMBOL(ip6_find_1stfragopt);
 #ifdef CONFIG_XFRM
 EXPORT_SYMBOL(xfrm6_rcv);
 #endif
 EXPORT_SYMBOL(rt6_lookup);
 EXPORT_SYMBOL(fl6_sock_lookup);
-EXPORT_SYMBOL(ip6_append_data);
-EXPORT_SYMBOL(ip6_flush_pending_frames);
-EXPORT_SYMBOL(ip6_push_pending_frames);
 EXPORT_SYMBOL(ipv6_push_nfrag_opts);
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv6/ndisc.c	2004-10-28 22:25:58 -07:00
@@ -396,7 +396,7 @@
 		src_addr = solicited_addr;
 		in6_ifa_put(ifp);
 	} else {
-		if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0))
+		if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
 			return;
 		src_addr = &tmpaddr;
 	}
@@ -921,6 +921,64 @@
 	}
 }
 
+static void ndisc_recv_rs(struct sk_buff *skb)
+{
+	struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw;
+	unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
+	struct neighbour *neigh;
+	struct inet6_dev *idev;
+	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
+	struct ndisc_options ndopts;
+	u8 *lladdr = NULL;
+	int lladdrlen = 0;
+
+	if (skb->len < sizeof(*rs_msg))
+		return;
+
+	idev = in6_dev_get(skb->dev);
+	if (!idev) {
+		if (net_ratelimit())
+			ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
+		return;
+	}
+
+	/* Don't accept RS if we're not in router mode */
+	if (!idev->cnf.forwarding || idev->cnf.accept_ra)
+		goto out;
+
+	/*
+	 * Don't update NCE if src = ::;
+	 * this implies that the source node has no ip address assigned yet.
+	 */
+	if (ipv6_addr_any(saddr))
+		goto out;
+
+	/* Parse ND options */
+	if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
+		if (net_ratelimit())
+			ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n");
+		goto out;
+	}
+
+	if (ndopts.nd_opts_src_lladdr) {
+		lladdr = (u8 *)(ndopts.nd_opts_src_lladdr + 1);
+		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
+		if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len))
+			goto out;
+	}
+
+	neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
+	if (neigh) {
+		neigh_update(neigh, lladdr, NUD_STALE,
+			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
+		neigh_release(neigh);
+	}
+out:
+	in6_dev_put(idev);
+}
+
 static void ndisc_router_discovery(struct sk_buff *skb)
 {
         struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
@@ -1026,7 +1084,7 @@
 		 *	delete it
 		 */
 
-		rt6_purge_dflt_routers(RTF_ALLONLINK);
+		rt6_purge_dflt_routers();
 	}
 
 	if (rt)
@@ -1393,6 +1451,10 @@
 
 	case NDISC_NEIGHBOUR_ADVERTISEMENT:
 		ndisc_recv_na(skb);
+		break;
+
+	case NDISC_ROUTER_SOLICITATION:
+		ndisc_recv_rs(skb);
 		break;
 
 	case NDISC_ROUTER_ADVERTISEMENT:
diff -Nru a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
--- a/net/ipv6/netfilter/ip6_tables.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6_tables.c	2004-10-28 22:25:59 -07:00
@@ -158,14 +158,15 @@
 /* Returns whether matches rule or not. */
 static inline int
 ip6_packet_match(const struct sk_buff *skb,
-		 const struct ipv6hdr *ipv6,
 		 const char *indev,
 		 const char *outdev,
 		 const struct ip6t_ip6 *ip6info,
-		 int isfrag)
+		 unsigned int *protoff,
+		 int *fragoff)
 {
 	size_t i;
 	unsigned long ret;
+	const struct ipv6hdr *ipv6 = skb->nh.ipv6h;
 
 #define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
 
@@ -216,9 +217,10 @@
 	/* look for the desired protocol header */
 	if((ip6info->flags & IP6T_F_PROTO)) {
 		u_int8_t currenthdr = ipv6->nexthdr;
-		struct ipv6_opt_hdr *hdrptr;
+		struct ipv6_opt_hdr _hdr, *hp;
 		u_int16_t ptr;		/* Header offset in skb */
 		u_int16_t hdrlen;	/* Header */
+		u_int16_t _fragoff = 0, *fp = NULL;
 
 		ptr = IPV6_HDR_LEN;
 
@@ -234,23 +236,41 @@
 				(currenthdr == IPPROTO_ESP))
 				return 0;
 
-	                hdrptr = (struct ipv6_opt_hdr *)(skb->data + ptr);
+			hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+			BUG_ON(hp == NULL);
 
 			/* Size calculation */
 	                if (currenthdr == IPPROTO_FRAGMENT) {
+				fp = skb_header_pointer(skb,
+						   ptr+offsetof(struct frag_hdr,
+								frag_off),
+						   sizeof(_fragoff),
+						   &_fragoff);
+				if (fp == NULL)
+					return 0;
+
+				_fragoff = ntohs(*fp) & ~0x7;
 	                        hdrlen = 8;
 	                } else if (currenthdr == IPPROTO_AH)
-	                        hdrlen = (hdrptr->hdrlen+2)<<2;
+	                        hdrlen = (hp->hdrlen+2)<<2;
 	                else
-	                        hdrlen = ipv6_optlen(hdrptr);
+	                        hdrlen = ipv6_optlen(hp);
 
-			currenthdr = hdrptr->nexthdr;
+			currenthdr = hp->nexthdr;
 	                ptr += hdrlen;
 			/* ptr is too large */
 	                if ( ptr > skb->len ) 
 				return 0;
+			if (_fragoff) {
+				if (ip6t_ext_hdr(currenthdr))
+					return 0;
+				break;
+			}
 		}
 
+		*protoff = ptr;
+		*fragoff = _fragoff;
+
 		/* currenthdr contains the protocol header */
 
 		dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -292,9 +312,9 @@
 
 static unsigned int
 ip6t_error(struct sk_buff **pskb,
-	  unsigned int hooknum,
 	  const struct net_device *in,
 	  const struct net_device *out,
+	  unsigned int hooknum,
 	  const void *targinfo,
 	  void *userinfo)
 {
@@ -310,13 +330,12 @@
 	     const struct net_device *in,
 	     const struct net_device *out,
 	     int offset,
-	     const void *hdr,
-	     u_int16_t datalen,
+	     unsigned int protoff,
 	     int *hotdrop)
 {
 	/* Stop iteration if it doesn't match */
 	if (!m->u.kernel.match->match(skb, in, out, m->data,
-				      offset, hdr, datalen, hotdrop))
+				      offset, protoff, hotdrop))
 		return 1;
 	else
 		return 0;
@@ -338,10 +357,8 @@
 	      void *userdata)
 {
 	static const char nulldevname[IFNAMSIZ];
-	u_int16_t offset = 0;
-	struct ipv6hdr *ipv6;
-	void *protohdr;
-	u_int16_t datalen;
+	int offset = 0;
+	unsigned int protoff = 0;
 	int hotdrop = 0;
 	/* Initializing verdict to NF_DROP keeps gcc happy. */
 	unsigned int verdict = NF_DROP;
@@ -354,9 +371,6 @@
 		return NF_DROP;
 
 	/* Initialization */
-	ipv6 = (*pskb)->nh.ipv6h;
-	protohdr = (u_int32_t *)((char *)ipv6 + IPV6_HDR_LEN);
-	datalen = (*pskb)->len - IPV6_HDR_LEN;
 	indev = in ? in->name : nulldevname;
 	outdev = out ? out->name : nulldevname;
 
@@ -393,17 +407,19 @@
 		IP_NF_ASSERT(e);
 		IP_NF_ASSERT(back);
 		(*pskb)->nfcache |= e->nfcache;
-		if (ip6_packet_match(*pskb, ipv6, indev, outdev, 
-			&e->ipv6, offset)) {
+		if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
+			&protoff, &offset)) {
 			struct ip6t_entry_target *t;
 
 			if (IP6T_MATCH_ITERATE(e, do_match,
 					       *pskb, in, out,
-					       offset, protohdr,
-					       datalen, &hotdrop) != 0)
+					       offset, protoff, &hotdrop) != 0)
 				goto no_match;
 
-			ADD_COUNTER(e->counters, ntohs(ipv6->payload_len) + IPV6_HDR_LEN, 1);
+			ADD_COUNTER(e->counters,
+				    ntohs((*pskb)->nh.ipv6h->payload_len)
+				    + IPV6_HDR_LEN,
+				    1);
 
 			t = ip6t_get_target(e);
 			IP_NF_ASSERT(t->u.kernel.target);
@@ -443,8 +459,8 @@
 					= 0xeeeeeeec;
 #endif
 				verdict = t->u.kernel.target->target(pskb,
-								     hook,
 								     in, out,
+								     hook,
 								     t->data,
 								     userdata);
 
@@ -459,11 +475,6 @@
 				((struct ip6t_entry *)table_base)->comefrom
 					= 0x57acc001;
 #endif
-				/* Target might have changed stuff. */
-				ipv6 = (*pskb)->nh.ipv6h;
-				protohdr = (u_int32_t *)((void *)ipv6 + IPV6_HDR_LEN);
-				datalen = (*pskb)->len - IPV6_HDR_LEN;
-
 				if (verdict == IP6T_CONTINUE)
 					e = (void *)e + e->next_offset;
 				else
@@ -554,7 +565,7 @@
 	return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex);
 }
 
-struct ip6t_target *
+static struct ip6t_target *
 ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex)
 {
 	return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
@@ -1535,26 +1546,31 @@
 
 static int
 tcp_find_option(u_int8_t option,
-		const struct tcphdr *tcp,
-		u_int16_t datalen,
+		const struct sk_buff *skb,
+		unsigned int tcpoff,
+		unsigned int optlen,
 		int invert,
 		int *hotdrop)
 {
-	unsigned int i = sizeof(struct tcphdr);
-	const u_int8_t *opt = (u_int8_t *)tcp;
+	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+	u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
+	unsigned int i;
 
 	duprintf("tcp_match: finding option\n");
+	if (!optlen)
+		return invert;
 	/* If we don't have the whole header, drop packet. */
-	if (tcp->doff * 4 < sizeof(struct tcphdr) ||
-	    tcp->doff * 4 > datalen) {
+	op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
+				_opt);
+	if (op == NULL) {
 		*hotdrop = 1;
 		return 0;
 	}
 
-	while (i < tcp->doff * 4) {
-		if (opt[i] == option) return !invert;
-		if (opt[i] < 2) i++;
-		else i += opt[i+1]?:1;
+	for (i = 0; i < optlen; ) {
+		if (op[i] == option) return !invert;
+		if (op[i] < 2) i++;
+		else i += op[i+1]?:1;
 	}
 
 	return invert;
@@ -1566,27 +1582,31 @@
 	  const struct net_device *out,
 	  const void *matchinfo,
 	  int offset,
-	  const void *hdr,
-	  u_int16_t datalen,
+	  unsigned int protoff,
 	  int *hotdrop)
 {
-	const struct tcphdr *tcp;
+	struct tcphdr _tcph, *th;
 	const struct ip6t_tcp *tcpinfo = matchinfo;
-	int tcpoff;
-	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
-	/* To quote Alan:
+	if (offset) {
+		/* To quote Alan:
 
-	   Don't allow a fragment of TCP 8 bytes in. Nobody normal
-	   causes this. Its a cracker trying to break in by doing a
-	   flag overwrite to pass the direction checks.
-	*/
-
-	if (offset == 1) {
-		duprintf("Dropping evil TCP offset=1 frag.\n");
-		*hotdrop = 1;
+		   Don't allow a fragment of TCP 8 bytes in. Nobody normal
+		   causes this. Its a cracker trying to break in by doing a
+		   flag overwrite to pass the direction checks.
+		*/
+		if (offset == 1) {
+			duprintf("Dropping evil TCP offset=1 frag.\n");
+			*hotdrop = 1;
+		}
+		/* Must not be a fragment. */
 		return 0;
-	} else if (offset == 0 && datalen < sizeof(struct tcphdr)) {
+	}
+
+#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+
+	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+	if (th == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
@@ -1594,45 +1614,30 @@
 		return 0;
 	}
 
-	tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
-	tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff);
-	if (tcpoff < 0 || tcpoff > skb->len) {
-		duprintf("tcp_match: cannot skip exthdr. Dropping.\n");
-		*hotdrop = 1;
-		return 0;
-	} else if (nexthdr == IPPROTO_FRAGMENT)
-		return 0;
-	else if (nexthdr != IPPROTO_TCP ||
-		 skb->len - tcpoff < sizeof(struct tcphdr)) {
-		/* cannot be occured */
-		duprintf("tcp_match: cannot get TCP header. Dropping.\n");
-		*hotdrop = 1;
-		return 0;
+	if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
+			ntohs(th->source),
+			!!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
+		return 0;
+	if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
+			ntohs(th->dest),
+			!!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
+		return 0;
+	if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
+		      == tcpinfo->flg_cmp,
+		      IP6T_TCP_INV_FLAGS))
+		return 0;
+	if (tcpinfo->option) {
+		if (th->doff * 4 < sizeof(_tcph)) {
+			*hotdrop = 1;
+			return 0;
+		}
+		if (!tcp_find_option(tcpinfo->option, skb, protoff,
+				     th->doff*4 - sizeof(*th),
+				     tcpinfo->invflags & IP6T_TCP_INV_OPTION,
+				     hotdrop))
+			return 0;
 	}
-
-	tcp = (struct tcphdr *)(skb->data + tcpoff);
-
-	/* FIXME: Try tcp doff >> packet len against various stacks --RR */
-
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
-
-	/* Must not be a fragment. */
-	return !offset
-		&& port_match(tcpinfo->spts[0], tcpinfo->spts[1],
-			      ntohs(tcp->source),
-			      !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))
-		&& port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
-			      ntohs(tcp->dest),
-			      !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))
-		&& FWINVTCP((((unsigned char *)tcp)[13]
-			     & tcpinfo->flg_mask)
-			    == tcpinfo->flg_cmp,
-			    IP6T_TCP_INV_FLAGS)
-		&& (!tcpinfo->option
-		    || tcp_find_option(tcpinfo->option, tcp, datalen,
-				       tcpinfo->invflags
-				       & IP6T_TCP_INV_OPTION,
-				       hotdrop));
+	return 1;
 }
 
 /* Called when user tries to insert an entry of this type. */
@@ -1658,16 +1663,18 @@
 	  const struct net_device *out,
 	  const void *matchinfo,
 	  int offset,
-	  const void *hdr,
-	  u_int16_t datalen,
+	  unsigned int protoff,
 	  int *hotdrop)
 {
-	const struct udphdr *udp;
+	struct udphdr _udph, *uh;
 	const struct ip6t_udp *udpinfo = matchinfo;
-	int udpoff;
-	u8 nexthdr = skb->nh.ipv6h->nexthdr;
 
-	if (offset == 0 && datalen < sizeof(struct udphdr)) {
+	/* Must not be a fragment. */
+	if (offset)
+		return 0;
+
+	uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
+	if (uh == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil UDP tinygram.\n");
@@ -1675,30 +1682,11 @@
 		return 0;
 	}
 
-	udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
-	udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff);
-	if (udpoff < 0 || udpoff > skb->len) {
-		duprintf("udp_match: cannot skip exthdr. Dropping.\n");
-		*hotdrop = 1;
-		return 0;
-	} else if (nexthdr == IPPROTO_FRAGMENT)
-		return 0;
-	else if (nexthdr != IPPROTO_UDP ||
-		 skb->len - udpoff < sizeof(struct udphdr)) {
-		duprintf("udp_match: cannot get UDP header. Dropping.\n");
-		*hotdrop = 1;
-		return 0;
-	}
-
-	udp = (struct udphdr *)(skb->data + udpoff);
-
-	/* Must not be a fragment. */
-	return !offset
-		&& port_match(udpinfo->spts[0], udpinfo->spts[1],
-			      ntohs(udp->source),
-			      !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
+	return port_match(udpinfo->spts[0], udpinfo->spts[1],
+			  ntohs(uh->source),
+			  !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
 		&& port_match(udpinfo->dpts[0], udpinfo->dpts[1],
-			      ntohs(udp->dest),
+			      ntohs(uh->dest),
 			      !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
 }
 
@@ -1748,14 +1736,18 @@
 	   const struct net_device *out,
 	   const void *matchinfo,
 	   int offset,
-	   const void *hdr,
-	   u_int16_t datalen,
+	   unsigned int protoff,
 	   int *hotdrop)
 {
-	const struct icmp6hdr *icmp = hdr;
+	struct icmp6hdr _icmp, *ic;
 	const struct ip6t_icmp *icmpinfo = matchinfo;
 
-	if (offset == 0 && datalen < 2) {
+	/* Must not be a fragment. */
+	if (offset)
+		return 0;
+
+	ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
+	if (ic == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil ICMP tinygram.\n");
@@ -1763,13 +1755,11 @@
 		return 0;
 	}
 
-	/* Must not be a fragment. */
-	return !offset
-		&& icmp6_type_code_match(icmpinfo->type,
-					icmpinfo->code[0],
-					icmpinfo->code[1],
-					icmp->icmp6_type, icmp->icmp6_code,
-					!!(icmpinfo->invflags&IP6T_ICMP_INV));
+	return icmp6_type_code_match(icmpinfo->type,
+				     icmpinfo->code[0],
+				     icmpinfo->code[1],
+				     ic->icmp6_type, ic->icmp6_code,
+				     !!(icmpinfo->invflags&IP6T_ICMP_INV));
 }
 
 /* Called when user tries to insert an entry of this type. */
@@ -1972,7 +1962,6 @@
 EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
 EXPORT_SYMBOL(ip6t_do_table);
-EXPORT_SYMBOL(ip6t_find_target_lock);
 EXPORT_SYMBOL(ip6t_register_match);
 EXPORT_SYMBOL(ip6t_unregister_match);
 EXPORT_SYMBOL(ip6t_register_target);
diff -Nru a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
--- a/net/ipv6/netfilter/ip6t_LOG.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv6/netfilter/ip6t_LOG.c	2004-10-28 22:25:57 -07:00
@@ -40,120 +40,166 @@
 #define DEBUGP(format, args...)
 #endif
 
-struct esphdr {
-	__u32   spi;
-}; /* FIXME evil kludge */
-        
 /* Use lock to serialize, so printks don't overlap */
 static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
 
-/* takes in current header and pointer to the header */
-/* if another header exists, sets hdrptr to the next header
-   and returns the new header value, else returns IPPROTO_NONE */
-static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t **hdrptr)
-{
-	u_int8_t hdrlen, nexthdr = IPPROTO_NONE;
-
-	switch(currenthdr){
-		case IPPROTO_AH:
-		/* whoever decided to do the length of AUTH for ipv6
-		in 32bit units unlike other headers should be beaten...
-		repeatedly...with a large stick...no, an even LARGER
-		stick...no, you're still not thinking big enough */
-			nexthdr = **hdrptr;
-			hdrlen = (*hdrptr)[1] * 4 + 8;
-			*hdrptr = *hdrptr + hdrlen;
-			break;
-		/*stupid rfc2402 */
-		case IPPROTO_DSTOPTS:
-		case IPPROTO_ROUTING:
-		case IPPROTO_HOPOPTS:
-			nexthdr = **hdrptr;
-			hdrlen = (*hdrptr)[1] * 8 + 8;
-			*hdrptr = *hdrptr + hdrlen;
-			break;
-		case IPPROTO_FRAGMENT:
-			nexthdr = **hdrptr;
-			*hdrptr = *hdrptr + 8;
-			break;
-	}	
-	return nexthdr;
-}
-
 /* One level of recursion won't kill us */
 static void dump_packet(const struct ip6t_log_info *info,
-			struct ipv6hdr *ipv6h, int recurse)
+			const struct sk_buff *skb, unsigned int ip6hoff,
+			int recurse)
 {
-	u_int8_t currenthdr = ipv6h->nexthdr;
-	u_int8_t *hdrptr;
+	u_int8_t currenthdr;
 	int fragment;
+	struct ipv6hdr _ip6h, *ih;
+	unsigned int ptr;
+	unsigned int hdrlen = 0;
+
+	ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
+	if (ih == NULL) {
+		printk("TRUNCATED");
+		return;
+	}
 
 	/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */
-	printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->saddr));
-	printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
+	printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr));
+	printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr));
 
 	/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
 	printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
-	       ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr),
-	       (ntohl(*(u_int32_t *)ipv6h) & 0x0ff00000) >> 20,
-	       ipv6h->hop_limit,
-	       (ntohl(*(u_int32_t *)ipv6h) & 0x000fffff));
+	       ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
+	       (ntohl(*(u_int32_t *)ih) & 0x0ff00000) >> 20,
+	       ih->hop_limit,
+	       (ntohl(*(u_int32_t *)ih) & 0x000fffff));
 
 	fragment = 0;
-	hdrptr = (u_int8_t *)(ipv6h + 1);
-	while (currenthdr != IPPROTO_NONE) {
-		if ((currenthdr == IPPROTO_TCP) ||
-		    (currenthdr == IPPROTO_UDP) ||
-		    (currenthdr == IPPROTO_ICMPV6))
-			break;
+	ptr = ip6hoff + sizeof(struct ipv6hdr);
+	currenthdr = ih->nexthdr;
+	while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
+		struct ipv6_opt_hdr _hdr, *hp;
+
+		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+		if (hp == NULL) {
+			printk("TRUNCATED");
+			return;
+		}
+
 		/* Max length: 48 "OPT (...) " */
-		printk("OPT ( ");
+		if (info->logflags & IP6T_LOG_IPOPT)
+			printk("OPT ( ");
+
 		switch (currenthdr) {
 		case IPPROTO_FRAGMENT: {
-			struct frag_hdr *fhdr = (struct frag_hdr *)hdrptr;
+			struct frag_hdr _fhdr, *fh;
 
-			/* Max length: 11 "FRAG:65535 " */
-			printk("FRAG:%u ", ntohs(fhdr->frag_off) & 0xFFF8);
+			printk("FRAG:");
+			fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
+						&_fhdr);
+			if (fh == NULL) {
+				printk("TRUNCATED ");
+				return;
+			}
+
+			/* Max length: 6 "65535 " */
+			printk("%u ", ntohs(fh->frag_off) & 0xFFF8);
 
 			/* Max length: 11 "INCOMPLETE " */
-			if (fhdr->frag_off & htons(0x0001))
+			if (fh->frag_off & htons(0x0001))
 				printk("INCOMPLETE ");
 
-			printk("ID:%08x ", fhdr->identification);
+			printk("ID:%08x ", ntohl(fh->identification));
 
-			if (ntohs(fhdr->frag_off) & 0xFFF8)
+			if (ntohs(fh->frag_off) & 0xFFF8)
 				fragment = 1;
 
+			hdrlen = 8;
+
 			break;
 		}
 		case IPPROTO_DSTOPTS:
 		case IPPROTO_ROUTING:
 		case IPPROTO_HOPOPTS:
+			if (fragment) {
+				if (info->logflags & IP6T_LOG_IPOPT)
+					printk(")");
+				return;
+			}
+			hdrlen = ipv6_optlen(hp);
 			break;
 		/* Max Length */
 		case IPPROTO_AH:
+			if (info->logflags & IP6T_LOG_IPOPT) {
+				struct ip_auth_hdr _ahdr, *ah;
+
+				/* Max length: 3 "AH " */
+				printk("AH ");
+
+				if (fragment) {
+					printk(")");
+					return;
+				}
+
+				ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
+							&_ahdr);
+				if (ah == NULL) {
+					/*
+					 * Max length: 26 "INCOMPLETE [65535 	
+					 *  bytes] )"
+					 */
+					printk("INCOMPLETE [%u bytes] )",
+					       skb->len - ptr);
+					return;
+				}
+
+				/* Length: 15 "SPI=0xF1234567 */
+				printk("SPI=0x%x ", ntohl(ah->spi));
+
+			}
+
+			hdrlen = (hp->hdrlen+2)<<2;
+			break;
 		case IPPROTO_ESP:
 			if (info->logflags & IP6T_LOG_IPOPT) {
-				struct esphdr *esph = (struct esphdr *)hdrptr;
-				int esp = (currenthdr == IPPROTO_ESP);
+				struct ip_esp_hdr _esph, *eh;
 
 				/* Max length: 4 "ESP " */
-				printk("%s ",esp ? "ESP" : "AH");
+				printk("ESP ");
+
+				if (fragment) {
+					printk(")");
+					return;
+				}
+
+				/*
+				 * Max length: 26 "INCOMPLETE [65535 bytes] )"
+				 */
+				eh = skb_header_pointer(skb, ptr, sizeof(_esph),
+							&_esph);
+				if (eh == NULL) {
+					printk("INCOMPLETE [%u bytes] )",
+					       skb->len - ptr);
+					return;
+				}
+
+				/* Length: 16 "SPI=0xF1234567 )" */
+				printk("SPI=0x%x )", ntohl(eh->spi) );
 
-				/* Length: 15 "SPI=0xF1234567 " */
-				printk("SPI=0x%x ", ntohl(esph->spi) );
-				break;
 			}
+			return;
 		default:
-			break;
+			/* Max length: 20 "Unknown Ext Hdr 255" */
+			printk("Unknown Ext Hdr %u", currenthdr);
+			return;
 		}
-		printk(") ");
-		currenthdr = ip6_nexthdr(currenthdr, &hdrptr);
+		if (info->logflags & IP6T_LOG_IPOPT)
+			printk(") ");
+
+		currenthdr = hp->nexthdr;
+		ptr += hdrlen;
 	}
 
 	switch (currenthdr) {
 	case IPPROTO_TCP: {
-		struct tcphdr *tcph = (struct tcphdr *)hdrptr;
+		struct tcphdr _tcph, *th;
 
 		/* Max length: 10 "PROTO=TCP " */
 		printk("PROTO=TCP ");
@@ -161,51 +207,69 @@
 		if (fragment)
 			break;
 
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph);
+		if (th == NULL) {
+			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			return;
+		}
+
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
 		printk("SPT=%u DPT=%u ",
-		       ntohs(tcph->source), ntohs(tcph->dest));
+		       ntohs(th->source), ntohs(th->dest));
 		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
 		if (info->logflags & IP6T_LOG_TCPSEQ)
 			printk("SEQ=%u ACK=%u ",
-			       ntohl(tcph->seq), ntohl(tcph->ack_seq));
+			       ntohl(th->seq), ntohl(th->ack_seq));
 		/* Max length: 13 "WINDOW=65535 " */
-		printk("WINDOW=%u ", ntohs(tcph->window));
-		/* Max length: 9 "RES=0x3F " */
-		printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
+		printk("WINDOW=%u ", ntohs(th->window));
+		/* Max length: 9 "RES=0x3C " */
+		printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
 		/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
-		if (tcph->cwr)
+		if (th->cwr)
 			printk("CWR ");
-		if (tcph->ece)
+		if (th->ece)
 			printk("ECE ");
-		if (tcph->urg)
+		if (th->urg)
 			printk("URG ");
-		if (tcph->ack)
+		if (th->ack)
 			printk("ACK ");
-		if (tcph->psh)
+		if (th->psh)
 			printk("PSH ");
-		if (tcph->rst)
+		if (th->rst)
 			printk("RST ");
-		if (tcph->syn)
+		if (th->syn)
 			printk("SYN ");
-		if (tcph->fin)
+		if (th->fin)
 			printk("FIN ");
 		/* Max length: 11 "URGP=65535 " */
-		printk("URGP=%u ", ntohs(tcph->urg_ptr));
+		printk("URGP=%u ", ntohs(th->urg_ptr));
 
 		if ((info->logflags & IP6T_LOG_TCPOPT)
-		    && tcph->doff * 4 != sizeof(struct tcphdr)) {
+		    && th->doff * 4 > sizeof(struct tcphdr)) {
+			u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
 			unsigned int i;
+			unsigned int optsize = th->doff * 4
+					       - sizeof(struct tcphdr);
+
+			op = skb_header_pointer(skb,
+						ptr + sizeof(struct tcphdr),
+						optsize, _opt);
+			if (op == NULL) {
+				printk("OPT (TRUNCATED)");
+				return;
+			}
 
 			/* Max length: 127 "OPT (" 15*4*2chars ") " */
 			printk("OPT (");
-			for (i =sizeof(struct tcphdr); i < tcph->doff * 4; i++)
-				printk("%02X", ((u_int8_t *)tcph)[i]);
+			for (i =0; i < optsize; i++)
+				printk("%02X", op[i]);
 			printk(") ");
 		}
 		break;
 	}
 	case IPPROTO_UDP: {
-		struct udphdr *udph = (struct udphdr *)hdrptr;
+		struct udphdr _udph, *uh;
 
 		/* Max length: 10 "PROTO=UDP " */
 		printk("PROTO=UDP ");
@@ -213,14 +277,21 @@
 		if (fragment)
 			break;
 
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph);
+		if (uh == NULL) {
+			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			return;
+		}
+
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
 		printk("SPT=%u DPT=%u LEN=%u ",
-		       ntohs(udph->source), ntohs(udph->dest),
-		       ntohs(udph->len));
+		       ntohs(uh->source), ntohs(uh->dest),
+		       ntohs(uh->len));
 		break;
 	}
 	case IPPROTO_ICMPV6: {
-		struct icmp6hdr *icmp6h = (struct icmp6hdr *)hdrptr;
+		struct icmp6hdr _icmp6h, *ic;
 
 		/* Max length: 13 "PROTO=ICMPv6 " */
 		printk("PROTO=ICMPv6 ");
@@ -228,16 +299,23 @@
 		if (fragment)
 			break;
 
+		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
+		ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
+		if (ic == NULL) {
+			printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+			return;
+		}
+
 		/* Max length: 18 "TYPE=255 CODE=255 " */
-		printk("TYPE=%u CODE=%u ", icmp6h->icmp6_type, icmp6h->icmp6_code);
+		printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
 
-		switch (icmp6h->icmp6_type) {
+		switch (ic->icmp6_type) {
 		case ICMPV6_ECHO_REQUEST:
 		case ICMPV6_ECHO_REPLY:
 			/* Max length: 19 "ID=65535 SEQ=65535 " */
 			printk("ID=%u SEQ=%u ",
-				ntohs(icmp6h->icmp6_identifier),
-				ntohs(icmp6h->icmp6_sequence));
+				ntohs(ic->icmp6_identifier),
+				ntohs(ic->icmp6_sequence));
 			break;
 		case ICMPV6_MGM_QUERY:
 		case ICMPV6_MGM_REPORT:
@@ -246,7 +324,7 @@
 
 		case ICMPV6_PARAMPROB:
 			/* Max length: 17 "POINTER=ffffffff " */
-			printk("POINTER=%08x ", ntohl(icmp6h->icmp6_pointer));
+			printk("POINTER=%08x ", ntohl(ic->icmp6_pointer));
 			/* Fall through */
 		case ICMPV6_DEST_UNREACH:
 		case ICMPV6_PKT_TOOBIG:
@@ -254,13 +332,14 @@
 			/* Max length: 3+maxlen */
 			if (recurse) {
 				printk("[");
-				dump_packet(info, (struct ipv6hdr *)(icmp6h + 1), 0);
+				dump_packet(info, skb, ptr + sizeof(_icmp6h),
+					    0);
 				printk("] ");
 			}
 
 			/* Max length: 10 "MTU=65535 " */
-			if (icmp6h->icmp6_type == ICMPV6_PKT_TOOBIG)
-				printk("MTU=%u ", ntohl(icmp6h->icmp6_mtu));
+			if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
+				printk("MTU=%u ", ntohl(ic->icmp6_mtu));
 		}
 		break;
 	}
@@ -328,16 +407,16 @@
 			printk(" ");
 	}
 
-	dump_packet(loginfo, ipv6h, 1);
+	dump_packet(loginfo, skb, (u8*)skb->nh.ipv6h - skb->data, 1);
 	printk("\n");
 	spin_unlock_bh(&log_lock);
 }
 
 static unsigned int
 ip6t_log_target(struct sk_buff **pskb,
-		unsigned int hooknum,
 		const struct net_device *in,
 		const struct net_device *out,
+		unsigned int hooknum,
 		const void *targinfo,
 		void *userinfo)
 {
diff -Nru a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
--- a/net/ipv6/netfilter/ip6t_MARK.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_MARK.c	2004-10-28 22:25:59 -07:00
@@ -20,9 +20,9 @@
 
 static unsigned int
 target(struct sk_buff **pskb,
-       unsigned int hooknum,
        const struct net_device *in,
        const struct net_device *out,
+       unsigned int hooknum,
        const void *targinfo,
        void *userinfo)
 {
diff -Nru a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
--- a/net/ipv6/netfilter/ip6t_ah.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv6/netfilter/ip6t_ah.c	2004-10-28 22:25:57 -07:00
@@ -31,12 +31,12 @@
 static inline int
 spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
 {
-       int r=0;
-       DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-              min,spi,max);
-       r=(spi >= min && spi <= max) ^ invert;
-       DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
-       return r;
+	int r=0;
+	DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
+	       min,spi,max);
+	r = (spi >= min && spi <= max) ^ invert;
+	DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
+	return r;
 }
 
 static int
@@ -45,125 +45,124 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *protohdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
-       struct ip_auth_hdr *ah = NULL;
-       const struct ip6t_ah *ahinfo = matchinfo;
-       unsigned int temp;
-       int len;
-       u8 nexthdr;
-       unsigned int ptr;
-       unsigned int hdrlen = 0;
-
-       /*DEBUGP("IPv6 AH entered\n");*/
-       /* if (opt->auth == 0) return 0;
-       * It does not filled on output */
-
-       /* type of the 1st exthdr */
-       nexthdr = skb->nh.ipv6h->nexthdr;
-       /* pointer to the 1st exthdr */
-       ptr = sizeof(struct ipv6hdr);
-       /* available length */
-       len = skb->len - ptr;
-       temp = 0;
-
-        while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr *hdr;
-
-              DEBUGP("ipv6_ah header iteration \n");
-
-              /* Is there enough space for the next ext header? */
-                if (len < (int)sizeof(struct ipv6_opt_hdr))
-                        return 0;
-              /* No more exthdr -> evaluate */
-                if (nexthdr == NEXTHDR_NONE) {
-                     break;
-              }
-              /* ESP -> evaluate */
-                if (nexthdr == NEXTHDR_ESP) {
-                     break;
-              }
-
-              hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
-
-              /* Calculate the header length */
-                if (nexthdr == NEXTHDR_FRAGMENT) {
-                        hdrlen = 8;
-                } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hdr->hdrlen+2)<<2;
-                else
-                        hdrlen = ipv6_optlen(hdr);
-
-              /* AH -> evaluate */
-                if (nexthdr == NEXTHDR_AUTH) {
-                     temp |= MASK_AH;
-                     break;
-              }
-
-
-              /* set the flag */
-              switch (nexthdr){
-                     case NEXTHDR_HOP:
-                     case NEXTHDR_ROUTING:
-                     case NEXTHDR_FRAGMENT:
-                     case NEXTHDR_AUTH:
-                     case NEXTHDR_DEST:
-                            break;
-                     default:
-                            DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
-                            return 0;
-                            break;
-              }
-
-                nexthdr = hdr->nexthdr;
-                len -= hdrlen;
-                ptr += hdrlen;
-		if ( ptr > skb->len ) {
-			DEBUGP("ipv6_ah: new pointer too large! \n");
+	struct ip_auth_hdr *ah = NULL, _ah;
+	const struct ip6t_ah *ahinfo = matchinfo;
+	unsigned int temp;
+	int len;
+	u8 nexthdr;
+	unsigned int ptr;
+	unsigned int hdrlen = 0;
+
+	/*DEBUGP("IPv6 AH entered\n");*/
+	/* if (opt->auth == 0) return 0;
+	* It does not filled on output */
+
+	/* type of the 1st exthdr */
+	nexthdr = skb->nh.ipv6h->nexthdr;
+	/* pointer to the 1st exthdr */
+	ptr = sizeof(struct ipv6hdr);
+	/* available length */
+	len = skb->len - ptr;
+	temp = 0;
+
+	while (ip6t_ext_hdr(nexthdr)) {
+		struct ipv6_opt_hdr _hdr, *hp;
+
+		DEBUGP("ipv6_ah header iteration \n");
+
+		/* Is there enough space for the next ext header? */
+		if (len < sizeof(struct ipv6_opt_hdr))
+			return 0;
+		/* No more exthdr -> evaluate */
+		if (nexthdr == NEXTHDR_NONE)
+			break;
+		/* ESP -> evaluate */
+		if (nexthdr == NEXTHDR_ESP)
+			break;
+
+		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+		BUG_ON(hp == NULL);
+
+		/* Calculate the header length */
+		if (nexthdr == NEXTHDR_FRAGMENT)
+			hdrlen = 8;
+		else if (nexthdr == NEXTHDR_AUTH)
+			hdrlen = (hp->hdrlen+2)<<2;
+		else
+			hdrlen = ipv6_optlen(hp);
+
+		/* AH -> evaluate */
+		if (nexthdr == NEXTHDR_AUTH) {
+			temp |= MASK_AH;
+			break;
+		}
+
+		
+		/* set the flag */
+		switch (nexthdr) {
+		case NEXTHDR_HOP:
+		case NEXTHDR_ROUTING:
+		case NEXTHDR_FRAGMENT:
+		case NEXTHDR_AUTH:
+		case NEXTHDR_DEST:
 			break;
+		default:
+			DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
+			return 0;
 		}
-        }
 
-       /* AH header not found */
-       if ( temp != MASK_AH ) return 0;
+		nexthdr = hp->nexthdr;
+		len -= hdrlen;
+		ptr += hdrlen;
+		if (ptr > skb->len) {
+			DEBUGP("ipv6_ah: new pointer too large! \n");
+			break;
+		}
+	}
 
-       if (len < (int)sizeof(struct ip_auth_hdr)){
-	       *hotdrop = 1;
-       		return 0;
-       }
-
-       ah = (struct ip_auth_hdr *) (skb->data + ptr);
-
-       DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
-       DEBUGP("RES %04X ", ah->reserved);
-       DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
-
-       DEBUGP("IPv6 AH spi %02X ",
-       		(spi_match(ahinfo->spis[0], ahinfo->spis[1],
-                           ntohl(ah->spi),
-                           !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
-       DEBUGP("len %02X %04X %02X ",
-       		ahinfo->hdrlen, hdrlen,
-       		(!ahinfo->hdrlen ||
-                           (ahinfo->hdrlen == hdrlen) ^
-                           !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
-       DEBUGP("res %02X %04X %02X\n", 
-       		ahinfo->hdrres, ah->reserved,
-       		!(ahinfo->hdrres && ah->reserved));
-
-       return (ah != NULL)
-              &&
-              (spi_match(ahinfo->spis[0], ahinfo->spis[1],
-                           ntohl(ah->spi),
-                           !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
-              &&
-              (!ahinfo->hdrlen ||
-                           (ahinfo->hdrlen == hdrlen) ^
-                           !!(ahinfo->invflags & IP6T_AH_INV_LEN))
-              &&
-              !(ahinfo->hdrres && ah->reserved);
+	/* AH header not found */
+	if (temp != MASK_AH)
+		return 0;
+
+	if (len < sizeof(struct ip_auth_hdr)){
+		*hotdrop = 1;
+		return 0;
+	}
+
+	ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
+	BUG_ON(ah == NULL);
+
+	DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
+	DEBUGP("RES %04X ", ah->reserved);
+	DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
+
+	DEBUGP("IPv6 AH spi %02X ",
+	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
+	                  ntohl(ah->spi),
+	                  !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
+	DEBUGP("len %02X %04X %02X ",
+	       ahinfo->hdrlen, hdrlen,
+	       (!ahinfo->hdrlen ||
+	        (ahinfo->hdrlen == hdrlen) ^
+	        !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
+	DEBUGP("res %02X %04X %02X\n",
+	       ahinfo->hdrres, ah->reserved,
+	       !(ahinfo->hdrres && ah->reserved));
+
+	return (ah != NULL)
+	       &&
+	       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
+	                  ntohl(ah->spi),
+	                  !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
+	       &&
+	       (!ahinfo->hdrlen ||
+	        (ahinfo->hdrlen == hdrlen) ^
+	        !!(ahinfo->invflags & IP6T_AH_INV_LEN))
+	       &&
+	       !(ahinfo->hdrres && ah->reserved);
 }
 
 /* Called when user tries to insert an entry of this type. */
@@ -174,20 +173,18 @@
           unsigned int matchinfosize,
           unsigned int hook_mask)
 {
-       const struct ip6t_ah *ahinfo = matchinfo;
-
-       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
-              DEBUGP("ip6t_ah: matchsize %u != %u\n",
-                      matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
-              return 0;
-       }
-       if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
-              DEBUGP("ip6t_ah: unknown flags %X\n",
-                      ahinfo->invflags);
-              return 0;
-       }
+	const struct ip6t_ah *ahinfo = matchinfo;
 
-       return 1;
+	if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
+		DEBUGP("ip6t_ah: matchsize %u != %u\n",
+		       matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
+		return 0;
+	}
+	if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
+		DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
+		return 0;
+	}
+	return 1;
 }
 
 static struct ip6t_match ah_match = {
@@ -199,12 +196,12 @@
 
 static int __init init(void)
 {
-       return ip6t_register_match(&ah_match);
+	return ip6t_register_match(&ah_match);
 }
 
 static void __exit cleanup(void)
 {
-       ip6t_unregister_match(&ah_match);
+	ip6t_unregister_match(&ah_match);
 }
 
 module_init(init);
diff -Nru a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
--- a/net/ipv6/netfilter/ip6t_dst.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_dst.c	2004-10-28 22:25:59 -07:00
@@ -7,7 +7,6 @@
  * published by the Free Software Foundation.
  */
 
-
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ipv6.h>
@@ -20,8 +19,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_opts.h>
 
-#define LOW(n)		(n & 0x00FF)
-
 #define HOPBYHOP	0
 
 MODULE_LICENSE("GPL");
@@ -48,8 +45,8 @@
  *  	0	-> invariant
  *  	1	-> can change the routing
  *  (Type & 0x1F) Type
- *      0	-> PAD0 (only 1 byte!)
- *      1	-> PAD1 LENGTH info (total length = length + 2)
+ *      0	-> Pad1 (only 1 byte!)
+ *      1	-> PadN LENGTH info (total length = length + 2)
  *      C0 | 2	-> JUMBO 4 x x x x ( xxxx > 64k )
  *      5	-> RTALERT 2 x x
  */
@@ -60,11 +57,10 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *protohdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
-       struct ipv6_opt_hdr *optsh = NULL;
+       struct ipv6_opt_hdr _optsh, *oh;
        const struct ip6t_opts *optinfo = matchinfo;
        unsigned int temp;
        unsigned int len;
@@ -72,7 +68,9 @@
        unsigned int ptr;
        unsigned int hdrlen = 0;
        unsigned int ret = 0;
-       u_int16_t *optdesc = NULL;
+       u8 _opttype, *tp = NULL;
+       u8 _optlen, *lp = NULL;
+       unsigned int optlen;
        
        /* type of the 1st exthdr */
        nexthdr = skb->nh.ipv6h->nexthdr;
@@ -83,7 +81,7 @@
        temp = 0;
 
         while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr *hdr;
+               struct ipv6_opt_hdr _hdr, *hp;
 
               DEBUGP("ipv6_opts header iteration \n");
 
@@ -99,15 +97,16 @@
                      break;
               }
 
-              hdr=(void *)(skb->data)+ptr;
+	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+	      BUG_ON(hp == NULL);
 
               /* Calculate the header length */
                 if (nexthdr == NEXTHDR_FRAGMENT) {
                         hdrlen = 8;
                 } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hdr->hdrlen+2)<<2;
+                        hdrlen = (hp->hdrlen+2)<<2;
                 else
-                        hdrlen = ipv6_optlen(hdr);
+                        hdrlen = ipv6_optlen(hp);
 
               /* OPTS -> evaluate */
 #if HOPBYHOP
@@ -135,7 +134,7 @@
                             break;
               }
 
-                nexthdr = hdr->nexthdr;
+                nexthdr = hp->nexthdr;
                 len -= hdrlen;
                 ptr += hdrlen;
 		if ( ptr > skb->len ) {
@@ -161,9 +160,10 @@
        		return 0;
        }
 
-       optsh=(void *)(skb->data)+ptr;
+       oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+       BUG_ON(oh == NULL);
 
-       DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
+       DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
 
        DEBUGP("len %02X %04X %02X ",
        		optinfo->hdrlen, hdrlen,
@@ -171,13 +171,12 @@
                            ((optinfo->hdrlen == hdrlen) ^
                            !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
 
-       ret = (optsh != NULL)
+       ret = (oh != NULL)
        		&&
 	      	(!(optinfo->flags & IP6T_OPTS_LEN) ||
                            ((optinfo->hdrlen == hdrlen) ^
                            !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
 
-       temp = len = 0;
        ptr += 2;
        hdrlen -= 2;
        if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
@@ -188,48 +187,59 @@
 		DEBUGP("Strict ");
 		DEBUGP("#%d ",optinfo->optsnr);
 		for(temp=0; temp<optinfo->optsnr; temp++){
-			optdesc = (void *)(skb->data)+ptr;
+			/* type field exists ? */
+			if (hdrlen < 1)
+				break;
+			tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
+						&_opttype);
+			if (tp == NULL)
+				break;
+
 			/* Type check */
-			if ( (unsigned char)*optdesc != 
-				(optinfo->opts[temp] & 0xFF00)>>8 ){
+			if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){
 				DEBUGP("Tbad %02X %02X\n",
-						(unsigned char)*optdesc,
-						(optinfo->opts[temp] &
-						 0xFF00)>>8);
+				       *tp,
+				       (optinfo->opts[temp] & 0xFF00)>>8);
 				return 0;
 			} else {
 				DEBUGP("Tok ");
 			}
 			/* Length check */
-			if (((optinfo->opts[temp] & 0x00FF) != 0xFF) &&
-				(unsigned char)*optdesc != 0){
-				if ( ntohs((u16)*optdesc) != 
-						optinfo->opts[temp] ){
-					DEBUGP("Lbad %02X %04X %04X\n",
-							(unsigned char)*optdesc,
-							ntohs((u16)*optdesc),
-							optinfo->opts[temp]);
+			if (*tp) {
+				u16 spec_len;
+
+				/* length field exists ? */
+				if (hdrlen < 2)
+					break;
+				lp = skb_header_pointer(skb, ptr + 1,
+							sizeof(_optlen),
+							&_optlen);
+				if (lp == NULL)
+					break;
+				spec_len = optinfo->opts[temp] & 0x00FF;
+
+				if (spec_len != 0x00FF && spec_len != *lp) {
+					DEBUGP("Lbad %02X %04X\n", *lp,
+					       spec_len);
 					return 0;
-				} else {
-					DEBUGP("Lok ");
 				}
-			}
-			/* Step to the next */
-			if ((unsigned char)*optdesc == 0){
-				DEBUGP("PAD0 \n");
-				ptr++;
-				hdrlen--;
+				DEBUGP("Lok ");
+				optlen = *lp + 2;
 			} else {
-				ptr += LOW(ntohs(*optdesc));
-				hdrlen -= LOW(ntohs(*optdesc));
-				DEBUGP("len%04X \n", 
-					LOW(ntohs(*optdesc)));
+				DEBUGP("Pad1\n");
+				optlen = 1;
 			}
-			if (ptr > skb->len || ( !hdrlen && 
-				(temp != optinfo->optsnr - 1))) {
+
+			/* Step to the next */
+			DEBUGP("len%04X \n", optlen);
+
+			if ((ptr > skb->len - optlen || hdrlen < optlen) &&
+			    (temp < optinfo->optsnr - 1)) {
 				DEBUGP("new pointer is too large! \n");
 				break;
 			}
+			ptr += optlen;
+			hdrlen -= optlen;
 		}
 		if (temp == optinfo->optsnr)
 			return ret;
@@ -271,6 +281,7 @@
 #endif
 	.match		= &match,
 	.checkentry	= &checkentry,
+	.me		= THIS_MODULE,
 };
 
 static int __init init(void)
diff -Nru a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
--- a/net/ipv6/netfilter/ip6t_esp.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv6/netfilter/ip6t_esp.c	2004-10-28 22:25:58 -07:00
@@ -32,8 +32,8 @@
 spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
 {
 	int r=0;
-        DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
-        	min,spi,max);
+	DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
+	       min,spi,max);
 	r=(spi >= min && spi <= max) ^ invert;
 	DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
 	return r;
@@ -45,11 +45,10 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *protohdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
-	struct ip_esp_hdr *esp = NULL;
+	struct ip_esp_hdr _esp, *eh = NULL;
 	const struct ip6t_esp *espinfo = matchinfo;
 	unsigned int temp;
 	int len;
@@ -67,73 +66,74 @@
 	len = skb->len - ptr;
 	temp = 0;
 
-        while (ip6t_ext_hdr(nexthdr)) {
-        	struct ipv6_opt_hdr *hdr;
-        	int hdrlen;
+	while (ip6t_ext_hdr(nexthdr)) {
+		struct ipv6_opt_hdr _hdr, *hp;
+		int hdrlen;
 
 		DEBUGP("ipv6_esp header iteration \n");
 
 		/* Is there enough space for the next ext header? */
-                if (len < (int)sizeof(struct ipv6_opt_hdr))
-                        return 0;
+		if (len < sizeof(struct ipv6_opt_hdr))
+			return 0;
 		/* No more exthdr -> evaluate */
-                if (nexthdr == NEXTHDR_NONE) {
+		if (nexthdr == NEXTHDR_NONE)
 			break;
-		}
 		/* ESP -> evaluate */
-                if (nexthdr == NEXTHDR_ESP) {
+		if (nexthdr == NEXTHDR_ESP) {
 			temp |= MASK_ESP;
 			break;
 		}
 
-		hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
+		hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+		BUG_ON(hp == NULL);
 
 		/* Calculate the header length */
-                if (nexthdr == NEXTHDR_FRAGMENT) {
-                        hdrlen = 8;
-                } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hdr->hdrlen+2)<<2;
-                else
-                        hdrlen = ipv6_optlen(hdr);
+		if (nexthdr == NEXTHDR_FRAGMENT)
+			hdrlen = 8;
+		else if (nexthdr == NEXTHDR_AUTH)
+			hdrlen = (hp->hdrlen+2)<<2;
+		else
+			hdrlen = ipv6_optlen(hp);
 
 		/* set the flag */
-		switch (nexthdr){
-			case NEXTHDR_HOP:
-			case NEXTHDR_ROUTING:
-			case NEXTHDR_FRAGMENT:
-			case NEXTHDR_AUTH:
-			case NEXTHDR_DEST:
-				break;
-			default:
-				DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
-				return 0;
-				break;
+		switch (nexthdr) {
+		case NEXTHDR_HOP:
+		case NEXTHDR_ROUTING:
+		case NEXTHDR_FRAGMENT:
+		case NEXTHDR_AUTH:
+		case NEXTHDR_DEST:
+			break;
+		default:
+			DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
+			return 0;
 		}
 
-                nexthdr = hdr->nexthdr;
-                len -= hdrlen;
-                ptr += hdrlen;
-		if ( ptr > skb->len ) {
+		nexthdr = hp->nexthdr;
+		len -= hdrlen;
+		ptr += hdrlen;
+		if (ptr > skb->len) {
 			DEBUGP("ipv6_esp: new pointer too large! \n");
 			break;
 		}
-        }
+	}
 
 	/* ESP header not found */
-	if ( temp != MASK_ESP ) return 0;
+	if (temp != MASK_ESP)
+		return 0;
 
-       if (len < (int)sizeof(struct ip_esp_hdr)){
-	       *hotdrop = 1;
-       		return 0;
-       }
+	if (len < sizeof(struct ip_esp_hdr)) {
+		*hotdrop = 1;
+		return 0;
+	}
 
-	esp = (struct ip_esp_hdr *) (skb->data + ptr);
+	eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
+	BUG_ON(eh == NULL);
 
-	DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi));
+	DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
 
-	return (esp != NULL)
+	return (eh != NULL)
 		&& spi_match(espinfo->spis[0], espinfo->spis[1],
-			      ntohl(esp->spi),
+			      ntohl(eh->spi),
 			      !!(espinfo->invflags & IP6T_ESP_INV_SPI));
 }
 
@@ -157,7 +157,6 @@
 			 espinfo->invflags);
 		return 0;
 	}
-
 	return 1;
 }
 
diff -Nru a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
--- a/net/ipv6/netfilter/ip6t_eui64.c	2004-10-28 22:25:56 -07:00
+++ b/net/ipv6/netfilter/ip6t_eui64.c	2004-10-28 22:25:56 -07:00
@@ -24,8 +24,7 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *hdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
 
diff -Nru a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
--- a/net/ipv6/netfilter/ip6t_frag.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv6/netfilter/ip6t_frag.c	2004-10-28 22:25:57 -07:00
@@ -45,11 +45,10 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *protohdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
-       struct frag_hdr *frag = NULL;
+       struct frag_hdr _frag, *fh = NULL;
        const struct ip6t_frag *fraginfo = matchinfo;
        unsigned int temp;
        int len;
@@ -66,7 +65,7 @@
        temp = 0;
 
         while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr *hdr;
+               struct ipv6_opt_hdr _hdr, *hp;
 
               DEBUGP("ipv6_frag header iteration \n");
 
@@ -82,15 +81,16 @@
                      break;
               }
 
-              hdr=(struct ipv6_opt_hdr *)(skb->data+ptr);
+	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+	      BUG_ON(hp == NULL);
 
               /* Calculate the header length */
                 if (nexthdr == NEXTHDR_FRAGMENT) {
                         hdrlen = 8;
                 } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hdr->hdrlen+2)<<2;
+                        hdrlen = (hp->hdrlen+2)<<2;
                 else
-                        hdrlen = ipv6_optlen(hdr);
+                        hdrlen = ipv6_optlen(hp);
 
               /* FRAG -> evaluate */
                 if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -113,7 +113,7 @@
                             break;
               }
 
-                nexthdr = hdr->nexthdr;
+                nexthdr = hp->nexthdr;
                 len -= hdrlen;
                 ptr += hdrlen;
 		if ( ptr > skb->len ) {
@@ -130,57 +130,58 @@
        		return 0;
        }
 
-       frag = (struct frag_hdr *) (skb->data + ptr);
+       fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
+       BUG_ON(fh == NULL);
 
-       DEBUGP("INFO %04X ", frag->frag_off);
-       DEBUGP("OFFSET %04X ", ntohs(frag->frag_off) & ~0x7);
-       DEBUGP("RES %02X %04X", frag->reserved, ntohs(frag->frag_off) & 0x6);
-       DEBUGP("MF %04X ", frag->frag_off & htons(IP6_MF));
-       DEBUGP("ID %u %08X\n", ntohl(frag->identification),
-	      ntohl(frag->identification));
+       DEBUGP("INFO %04X ", fh->frag_off);
+       DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
+       DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
+       DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF));
+       DEBUGP("ID %u %08X\n", ntohl(fh->identification),
+	      ntohl(fh->identification));
 
        DEBUGP("IPv6 FRAG id %02X ",
        		(id_match(fraginfo->ids[0], fraginfo->ids[1],
-                           ntohl(frag->identification),
+                           ntohl(fh->identification),
                            !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
        DEBUGP("res %02X %02X%04X %02X ", 
-       		(fraginfo->flags & IP6T_FRAG_RES), frag->reserved,
-		ntohs(frag->frag_off) & 0x6,
+       		(fraginfo->flags & IP6T_FRAG_RES), fh->reserved,
+		ntohs(fh->frag_off) & 0x6,
        		!((fraginfo->flags & IP6T_FRAG_RES)
-			&& (frag->reserved || (ntohs(frag->frag_off) & 0x6))));
+			&& (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
        DEBUGP("first %02X %02X %02X ", 
        		(fraginfo->flags & IP6T_FRAG_FST),
-		ntohs(frag->frag_off) & ~0x7,
+		ntohs(fh->frag_off) & ~0x7,
        		!((fraginfo->flags & IP6T_FRAG_FST)
-			&& (ntohs(frag->frag_off) & ~0x7)));
+			&& (ntohs(fh->frag_off) & ~0x7)));
        DEBUGP("mf %02X %02X %02X ", 
        		(fraginfo->flags & IP6T_FRAG_MF),
-		ntohs(frag->frag_off) & IP6_MF,
+		ntohs(fh->frag_off) & IP6_MF,
        		!((fraginfo->flags & IP6T_FRAG_MF)
-			&& !((ntohs(frag->frag_off) & IP6_MF))));
+			&& !((ntohs(fh->frag_off) & IP6_MF))));
        DEBUGP("last %02X %02X %02X\n", 
        		(fraginfo->flags & IP6T_FRAG_NMF),
-		ntohs(frag->frag_off) & IP6_MF,
+		ntohs(fh->frag_off) & IP6_MF,
        		!((fraginfo->flags & IP6T_FRAG_NMF)
-			&& (ntohs(frag->frag_off) & IP6_MF)));
+			&& (ntohs(fh->frag_off) & IP6_MF)));
 
-       return (frag != NULL)
+       return (fh != NULL)
        		&&
        		(id_match(fraginfo->ids[0], fraginfo->ids[1],
-			  ntohl(frag->identification),
+			  ntohl(fh->identification),
                            !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
 		&&
 		!((fraginfo->flags & IP6T_FRAG_RES)
-			&& (frag->reserved || (ntohs(frag->frag_off) & 0x6)))
+			&& (fh->reserved || (ntohs(fh->frag_off) & 0x6)))
 		&&
 		!((fraginfo->flags & IP6T_FRAG_FST)
-			&& (ntohs(frag->frag_off) & ~0x7))
+			&& (ntohs(fh->frag_off) & ~0x7))
 		&&
 		!((fraginfo->flags & IP6T_FRAG_MF)
-			&& !(ntohs(frag->frag_off) & IP6_MF))
+			&& !(ntohs(fh->frag_off) & IP6_MF))
 		&&
 		!((fraginfo->flags & IP6T_FRAG_NMF)
-			&& (ntohs(frag->frag_off) & IP6_MF));
+			&& (ntohs(fh->frag_off) & IP6_MF));
 }
 
 /* Called when user tries to insert an entry of this type. */
diff -Nru a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
--- a/net/ipv6/netfilter/ip6t_hbh.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_hbh.c	2004-10-28 22:25:59 -07:00
@@ -19,8 +19,6 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/netfilter_ipv6/ip6t_opts.h>
 
-#define LOW(n)		(n & 0x00FF)
-
 #define HOPBYHOP	1
 
 MODULE_LICENSE("GPL");
@@ -47,8 +45,8 @@
  *  	0	-> invariant
  *  	1	-> can change the routing
  *  (Type & 0x1F) Type
- *      0	-> PAD0 (only 1 byte!)
- *      1	-> PAD1 LENGTH info (total length = length + 2)
+ *      0	-> Pad1 (only 1 byte!)
+ *      1	-> PadN LENGTH info (total length = length + 2)
  *      C0 | 2	-> JUMBO 4 x x x x ( xxxx > 64k )
  *      5	-> RTALERT 2 x x
  */
@@ -59,11 +57,10 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *protohdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
-       struct ipv6_opt_hdr *optsh = NULL;
+       struct ipv6_opt_hdr _optsh, *oh;
        const struct ip6t_opts *optinfo = matchinfo;
        unsigned int temp;
        unsigned int len;
@@ -71,7 +68,9 @@
        unsigned int ptr;
        unsigned int hdrlen = 0;
        unsigned int ret = 0;
-       u_int16_t *optdesc = NULL;
+       u8 _opttype, *tp = NULL;
+       u8 _optlen, *lp = NULL;
+       unsigned int optlen;
        
        /* type of the 1st exthdr */
        nexthdr = skb->nh.ipv6h->nexthdr;
@@ -82,7 +81,7 @@
        temp = 0;
 
         while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr *hdr;
+               struct ipv6_opt_hdr _hdr, *hp;
 
               DEBUGP("ipv6_opts header iteration \n");
 
@@ -98,15 +97,16 @@
                      break;
               }
 
-              hdr=(void *)(skb->data)+ptr;
+	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+	      BUG_ON(hp == NULL);
 
               /* Calculate the header length */
                 if (nexthdr == NEXTHDR_FRAGMENT) {
                         hdrlen = 8;
                 } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hdr->hdrlen+2)<<2;
+                        hdrlen = (hp->hdrlen+2)<<2;
                 else
-                        hdrlen = ipv6_optlen(hdr);
+                        hdrlen = ipv6_optlen(hp);
 
               /* OPTS -> evaluate */
 #if HOPBYHOP
@@ -134,7 +134,7 @@
                             break;
               }
 
-                nexthdr = hdr->nexthdr;
+                nexthdr = hp->nexthdr;
                 len -= hdrlen;
                 ptr += hdrlen;
 		if ( ptr > skb->len ) {
@@ -160,9 +160,10 @@
        		return 0;
        }
 
-       optsh=(void *)(skb->data)+ptr;
+       oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+       BUG_ON(oh == NULL);
 
-       DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
+       DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
 
        DEBUGP("len %02X %04X %02X ",
        		optinfo->hdrlen, hdrlen,
@@ -170,13 +171,12 @@
                            ((optinfo->hdrlen == hdrlen) ^
                            !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
 
-       ret = (optsh != NULL)
+       ret = (oh != NULL)
        		&&
 	      	(!(optinfo->flags & IP6T_OPTS_LEN) ||
                            ((optinfo->hdrlen == hdrlen) ^
                            !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
 
-       temp = len = 0;
        ptr += 2;
        hdrlen -= 2;
        if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
@@ -187,48 +187,59 @@
 		DEBUGP("Strict ");
 		DEBUGP("#%d ",optinfo->optsnr);
 		for(temp=0; temp<optinfo->optsnr; temp++){
-			optdesc = (void *)(skb->data)+ptr;
+			/* type field exists ? */
+			if (hdrlen < 1)
+				break;
+			tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
+						&_opttype);
+			if (tp == NULL)
+				break;
+
 			/* Type check */
-			if ( (unsigned char)*optdesc != 
-				(optinfo->opts[temp] & 0xFF00)>>8 ){
+			if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){
 				DEBUGP("Tbad %02X %02X\n",
-						(unsigned char)*optdesc,
-						(optinfo->opts[temp] &
-						 0xFF00)>>8);
+				       *tp,
+				       (optinfo->opts[temp] & 0xFF00)>>8);
 				return 0;
 			} else {
 				DEBUGP("Tok ");
 			}
 			/* Length check */
-			if (((optinfo->opts[temp] & 0x00FF) != 0xFF) &&
-				(unsigned char)*optdesc != 0){
-				if ( ntohs((u16)*optdesc) != 
-						optinfo->opts[temp] ){
-					DEBUGP("Lbad %02X %04X %04X\n",
-							(unsigned char)*optdesc,
-							ntohs((u16)*optdesc),
-							optinfo->opts[temp]);
+			if (*tp) {
+				u16 spec_len;
+
+				/* length field exists ? */
+				if (hdrlen < 2)
+					break;
+				lp = skb_header_pointer(skb, ptr + 1,
+							sizeof(_optlen),
+							&_optlen);
+				if (lp == NULL)
+					break;
+				spec_len = optinfo->opts[temp] & 0x00FF;
+
+				if (spec_len != 0x00FF && spec_len != *lp) {
+					DEBUGP("Lbad %02X %04X\n", *lp,
+					       spec_len);
 					return 0;
-				} else {
-					DEBUGP("Lok ");
 				}
-			}
-			/* Step to the next */
-			if ((unsigned char)*optdesc == 0){
-				DEBUGP("PAD0 \n");
-				ptr++;
-				hdrlen--;
+				DEBUGP("Lok ");
+				optlen = *lp + 2;
 			} else {
-				ptr += LOW(ntohs(*optdesc));
-				hdrlen -= LOW(ntohs(*optdesc));
-				DEBUGP("len%04X \n", 
-					LOW(ntohs(*optdesc)));
+				DEBUGP("Pad1\n");
+				optlen = 1;
 			}
-			if (ptr > skb->len || ( !hdrlen && 
-				(temp != optinfo->optsnr - 1))) {
+
+			/* Step to the next */
+			DEBUGP("len%04X \n", optlen);
+
+			if ((ptr > skb->len - optlen || hdrlen < optlen) &&
+			    (temp < optinfo->optsnr - 1)) {
 				DEBUGP("new pointer is too large! \n");
 				break;
 			}
+			ptr += optlen;
+			hdrlen -= optlen;
 		}
 		if (temp == optinfo->optsnr)
 			return ret;
diff -Nru a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
--- a/net/ipv6/netfilter/ip6t_hl.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv6/netfilter/ip6t_hl.c	2004-10-28 22:25:58 -07:00
@@ -20,7 +20,7 @@
 
 static int match(const struct sk_buff *skb, const struct net_device *in,
 		 const struct net_device *out, const void *matchinfo,
-		 int offset, const void *hdr, u_int16_t datalen,
+		 int offset, unsigned int protoff,
 		 int *hotdrop)
 {
 	const struct ip6t_hl_info *info = matchinfo;
diff -Nru a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
--- a/net/ipv6/netfilter/ip6t_ipv6header.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c	2004-10-28 22:25:59 -07:00
@@ -31,8 +31,7 @@
 		 const struct net_device *out,
 		 const void *matchinfo,
 		 int offset,
-		 const void *protohdr,
-		 u_int16_t datalen,
+		 unsigned int protoff,
 		 int *hotdrop)
 {
 	const struct ip6t_ipv6header_info *info = matchinfo;
diff -Nru a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c
--- a/net/ipv6/netfilter/ip6t_length.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_length.c	2004-10-28 22:25:59 -07:00
@@ -23,8 +23,7 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *hdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
 	const struct ip6t_length_info *info = matchinfo;
diff -Nru a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c
--- a/net/ipv6/netfilter/ip6t_limit.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv6/netfilter/ip6t_limit.c	2004-10-28 22:25:57 -07:00
@@ -57,8 +57,7 @@
 		const struct net_device *out,
 		const void *matchinfo,
 		int offset,
-		const void *hdr,
-		u_int16_t datalen,
+		unsigned int protoff,
 		int *hotdrop)
 {
 	struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master;
diff -Nru a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
--- a/net/ipv6/netfilter/ip6t_mac.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_mac.c	2004-10-28 22:25:59 -07:00
@@ -25,8 +25,7 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *hdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
     const struct ip6t_mac_info *info = matchinfo;
diff -Nru a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c
--- a/net/ipv6/netfilter/ip6t_mark.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_mark.c	2004-10-28 22:25:59 -07:00
@@ -24,8 +24,7 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *hdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
 	const struct ip6t_mark_info *info = matchinfo;
diff -Nru a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
--- a/net/ipv6/netfilter/ip6t_multiport.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_multiport.c	2004-10-28 22:25:59 -07:00
@@ -53,28 +53,32 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *hdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
-	const struct udphdr *udp = hdr;
+	u16 _ports[2], *pptr;
 	const struct ip6t_multiport *multiinfo = matchinfo;
 
-	/* Must be big enough to read ports. */
-	if (offset == 0 && datalen < sizeof(struct udphdr)) {
+	/* Must not be a fragment. */
+	if (offset)
+		return 0;
+
+	/* Must be big enough to read ports (both UDP and TCP have
+	   them at the start). */
+	pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
+	if (pptr == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
-			duprintf("ip6t_multiport:"
-				 " Dropping evil offset=0 tinygram.\n");
-			*hotdrop = 1;
-			return 0;
+		 * can't.  Hence, no choice but to drop.
+		 */
+		duprintf("ip6t_multiport:"
+			 " Dropping evil offset=0 tinygram.\n");
+		*hotdrop = 1;
+		return 0;
 	}
 
-	/* Must not be a fragment. */
-	return !offset
-		&& ports_match(multiinfo->ports,
-			       multiinfo->flags, multiinfo->count,
-			       ntohs(udp->source), ntohs(udp->dest));
+	return ports_match(multiinfo->ports,
+			   multiinfo->flags, multiinfo->count,
+			   ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
 /* Called when user tries to insert an entry of this type. */
diff -Nru a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
--- a/net/ipv6/netfilter/ip6t_owner.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_owner.c	2004-10-28 22:25:59 -07:00
@@ -92,8 +92,7 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *hdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
 	const struct ip6t_owner_info *info = matchinfo;
diff -Nru a/net/ipv6/netfilter/ip6t_physdev.c b/net/ipv6/netfilter/ip6t_physdev.c
--- a/net/ipv6/netfilter/ip6t_physdev.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/netfilter/ip6t_physdev.c	2004-10-28 22:25:59 -07:00
@@ -26,8 +26,7 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *hdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
 	int i;
diff -Nru a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
--- a/net/ipv6/netfilter/ip6t_rt.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv6/netfilter/ip6t_rt.c	2004-10-28 22:25:57 -07:00
@@ -47,11 +47,10 @@
       const struct net_device *out,
       const void *matchinfo,
       int offset,
-      const void *protohdr,
-      u_int16_t datalen,
+      unsigned int protoff,
       int *hotdrop)
 {
-       struct ipv6_rt_hdr *route = NULL;
+       struct ipv6_rt_hdr _route, *rh = NULL;
        const struct ip6t_rt *rtinfo = matchinfo;
        unsigned int temp;
        unsigned int len;
@@ -59,6 +58,7 @@
        unsigned int ptr;
        unsigned int hdrlen = 0;
        unsigned int ret = 0;
+       struct in6_addr *ap, _addr;
 
        /* type of the 1st exthdr */
        nexthdr = skb->nh.ipv6h->nexthdr;
@@ -69,7 +69,7 @@
        temp = 0;
 
         while (ip6t_ext_hdr(nexthdr)) {
-               struct ipv6_opt_hdr *hdr;
+               struct ipv6_opt_hdr _hdr, *hp;
 
               DEBUGP("ipv6_rt header iteration \n");
 
@@ -85,15 +85,16 @@
                      break;
               }
 
-              hdr=(struct ipv6_opt_hdr *)(skb->data+ptr);
+	      hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+	      BUG_ON(hp == NULL);
 
               /* Calculate the header length */
                 if (nexthdr == NEXTHDR_FRAGMENT) {
                         hdrlen = 8;
                 } else if (nexthdr == NEXTHDR_AUTH)
-                        hdrlen = (hdr->hdrlen+2)<<2;
+                        hdrlen = (hp->hdrlen+2)<<2;
                 else
-                        hdrlen = ipv6_optlen(hdr);
+                        hdrlen = ipv6_optlen(hp);
 
               /* ROUTING -> evaluate */
                 if (nexthdr == NEXTHDR_ROUTING) {
@@ -116,7 +117,7 @@
                             break;
               }
 
-                nexthdr = hdr->nexthdr;
+                nexthdr = hp->nexthdr;
                 len -= hdrlen;
                 ptr += hdrlen;
 		if ( ptr > skb->len ) {
@@ -138,20 +139,21 @@
        		return 0;
        }
 
-       route = (struct ipv6_rt_hdr *) (skb->data + ptr);
+       rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
+       BUG_ON(rh == NULL);
 
-       DEBUGP("IPv6 RT LEN %u %u ", hdrlen, route->hdrlen);
-       DEBUGP("TYPE %04X ", route->type);
-       DEBUGP("SGS_LEFT %u %02X\n", route->segments_left, route->segments_left);
+       DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
+       DEBUGP("TYPE %04X ", rh->type);
+       DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
 
        DEBUGP("IPv6 RT segsleft %02X ",
        		(segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
-                           route->segments_left,
+                           rh->segments_left,
                            !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
        DEBUGP("type %02X %02X %02X ",
-       		rtinfo->rt_type, route->type, 
+       		rtinfo->rt_type, rh->type, 
        		(!(rtinfo->flags & IP6T_RT_TYP) ||
-                           ((rtinfo->rt_type == route->type) ^
+                           ((rtinfo->rt_type == rh->type) ^
                            !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
        DEBUGP("len %02X %04X %02X ",
        		rtinfo->hdrlen, hdrlen,
@@ -159,13 +161,13 @@
                            ((rtinfo->hdrlen == hdrlen) ^
                            !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
        DEBUGP("res %02X %02X %02X ", 
-       		(rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)route)->bitmap,
-       		!((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap)));
+       		(rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->bitmap,
+       		!((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->bitmap)));
 
-       ret = (route != NULL)
+       ret = (rh != NULL)
        		&&
        		(segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
-                           route->segments_left,
+                           rh->segments_left,
                            !!(rtinfo->invflags & IP6T_RT_INV_SGS)))
 		&&
 	      	(!(rtinfo->flags & IP6T_RT_LEN) ||
@@ -173,13 +175,19 @@
                            !!(rtinfo->invflags & IP6T_RT_INV_LEN)))
 		&&
        		(!(rtinfo->flags & IP6T_RT_TYP) ||
-                           ((rtinfo->rt_type == route->type) ^
-                           !!(rtinfo->invflags & IP6T_RT_INV_TYP)))
-		&&
-       		!((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap));
+                           ((rtinfo->rt_type == rh->type) ^
+                           !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
+
+	if (ret && (rtinfo->flags & IP6T_RT_RES)) {
+		u_int32_t *bp, _bitmap;
+		bp = skb_header_pointer(skb,
+					ptr + offsetof(struct rt0_hdr, bitmap),
+					sizeof(_bitmap), &_bitmap);
+
+		ret = (*bp == 0);
+	}
 
 	DEBUGP("#%d ",rtinfo->addrnr);
-       temp = len = ptr = 0;
        if ( !(rtinfo->flags & IP6T_RT_FST) ){
 	       return ret;
 	} else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
@@ -188,32 +196,27 @@
 			DEBUGP("There isn't enough space\n");
 			return 0;
 		} else {
+			unsigned int i = 0;
+
 			DEBUGP("#%d ",rtinfo->addrnr);
-			ptr = 0;
 			for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){
-				len = 0;
-				while ((u8)(((struct rt0_hdr *)route)->
-						addr[temp].s6_addr[len]) ==
-					(u8)(rtinfo->addrs[ptr].s6_addr[len])){
-					DEBUGP("%02X?%02X ",
-		(u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
-					(u8)(rtinfo->addrs[ptr].s6_addr[len]));
-					len++;
-					if ( len == 16 ) break;
+				ap = skb_header_pointer(skb,
+							ptr
+							+ sizeof(struct rt0_hdr)
+							+ temp * sizeof(_addr),
+							sizeof(_addr),
+							&_addr);
+
+				BUG_ON(ap == NULL);
+
+				if (!ipv6_addr_cmp(ap, &rtinfo->addrs[i])) {
+					DEBUGP("i=%d temp=%d;\n",i,temp);
+					i++;
 				}
-				if (len==16) {
-					DEBUGP("ptr=%d temp=%d;\n",ptr,temp);
-					ptr++;
-				} else {
-					DEBUGP("%02X?%02X ",
-		(u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
-					(u8)(rtinfo->addrs[ptr].s6_addr[len]));
-					DEBUGP("!ptr=%d temp=%d;\n",ptr,temp);
-				}
-				if (ptr==rtinfo->addrnr) break;
+				if (i==rtinfo->addrnr) break;
 			}
-			DEBUGP("ptr=%d len=%d #%d\n",ptr,len, rtinfo->addrnr);
-			if ( (len == 16) && (ptr == rtinfo->addrnr))
+			DEBUGP("i=%d #%d\n", i, rtinfo->addrnr);
+			if (i == rtinfo->addrnr)
 				return ret;
 			else return 0;
 		}
@@ -225,26 +228,19 @@
 		} else {
 			DEBUGP("#%d ",rtinfo->addrnr);
 			for(temp=0; temp<rtinfo->addrnr; temp++){
-				len = 0;
-				while ((u8)(((struct rt0_hdr *)route)->
-						addr[temp].s6_addr[len]) ==
-					(u8)(rtinfo->addrs[temp].s6_addr[len])){
-					DEBUGP("%02X?%02X ",
-		(u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
-					(u8)(rtinfo->addrs[temp].s6_addr[len]));
-					len++;
-					if ( len == 16 ) break;
-				}
-				if (len!=16) {
-					DEBUGP("%02X?%02X ",
-		(u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
-					(u8)(rtinfo->addrs[temp].s6_addr[len]));
-					DEBUGP("!len=%d temp=%d;\n",len,temp);
+				ap = skb_header_pointer(skb,
+							ptr
+							+ sizeof(struct rt0_hdr)
+							+ temp * sizeof(_addr),
+							sizeof(_addr),
+							&_addr);
+				BUG_ON(ap == NULL);
+
+				if (ipv6_addr_cmp(ap, &rtinfo->addrs[temp]))
 					break;
-				}
 			}
-			DEBUGP("temp=%d len=%d #%d\n",temp,len,rtinfo->addrnr);
-			if ( (len == 16) && (temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16)))
+			DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr);
+			if ((temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16)))
 				return ret;
 			else return 0;
 		}
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	2004-10-28 22:25:57 -07:00
+++ b/net/ipv6/raw.c	2004-10-28 22:25:57 -07:00
@@ -639,7 +639,7 @@
 			return -EINVAL;
 
 		if (sin6->sin6_family && sin6->sin6_family != AF_INET6) 
-			return(-EINVAL);
+			return(-EAFNOSUPPORT);
 
 		/* port is the proto value [0..255] carried in nexthdr */
 		proto = ntohs(sin6->sin6_port);
diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c
--- a/net/ipv6/route.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/route.c	2004-10-28 22:25:59 -07:00
@@ -88,7 +88,7 @@
 static int		 ip6_dst_gc(void);
 
 static int		ip6_pkt_discard(struct sk_buff *skb);
-static int		ip6_pkt_discard_out(struct sk_buff **pskb);
+static int		ip6_pkt_discard_out(struct sk_buff *skb);
 static void		ip6_link_failure(struct sk_buff *skb);
 static void		ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
 
@@ -638,7 +638,7 @@
 struct dst_entry *ndisc_dst_alloc(struct net_device *dev, 
 				  struct neighbour *neigh,
 				  struct in6_addr *addr,
-				  int (*output)(struct sk_buff **))
+				  int (*output)(struct sk_buff *))
 {
 	struct rt6_info *rt;
 	struct inet6_dev *idev = in6_dev_get(dev);
@@ -1288,20 +1288,14 @@
 	return rt6_get_dflt_router(gwaddr, dev);
 }
 
-void rt6_purge_dflt_routers(int last_resort)
+void rt6_purge_dflt_routers(void)
 {
 	struct rt6_info *rt;
-	u32 flags;
-
-	if (last_resort)
-		flags = RTF_ALLONLINK;
-	else
-		flags = RTF_DEFAULT | RTF_ADDRCONF;	
 
 restart:
 	read_lock_bh(&rt6_lock);
 	for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) {
-		if (rt->rt6i_flags & flags) {
+		if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
 			dst_hold(&rt->u.dst);
 
 			rt6_reset_dflt_pointer(NULL);
@@ -1362,11 +1356,10 @@
 	return 0;
 }
 
-int ip6_pkt_discard_out(struct sk_buff **pskb)
+int ip6_pkt_discard_out(struct sk_buff *skb)
 {
-	(*pskb)->dev = (*pskb)->dst->dev;
-	BUG_ON(!(*pskb)->dev);
-	return ip6_pkt_discard(*pskb);
+	skb->dev = skb->dst->dev;
+	return ip6_pkt_discard(skb);
 }
 
 /*
@@ -1592,7 +1585,7 @@
 	rtm->rtm_protocol = rt->rt6i_protocol;
 	if (rt->rt6i_flags&RTF_DYNAMIC)
 		rtm->rtm_protocol = RTPROT_REDIRECT;
-	else if (rt->rt6i_flags&(RTF_ADDRCONF|RTF_ALLONLINK))
+	else if (rt->rt6i_flags & RTF_ADDRCONF)
 		rtm->rtm_protocol = RTPROT_KERNEL;
 	else if (rt->rt6i_flags&RTF_DEFAULT)
 		rtm->rtm_protocol = RTPROT_RA;
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	2004-10-28 22:25:58 -07:00
+++ b/net/ipv6/tcp_ipv6.c	2004-10-28 22:25:58 -07:00
@@ -1802,6 +1802,7 @@
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct flowi fl;
 	struct dst_entry *dst;
+	struct in6_addr *final_p = NULL, final;
 
 	memset(&fl, 0, sizeof(fl));
 	fl.proto = IPPROTO_TCP;
@@ -1815,7 +1816,9 @@
 
 	if (np->opt && np->opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
+		ipv6_addr_copy(&final, &fl.fl6_dst);
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	dst = __sk_dst_check(sk, np->dst_cookie);
@@ -1827,6 +1830,9 @@
 			sk->sk_err_soft = -err;
 			return err;
 		}
+
+		if (final_p)
+			ipv6_addr_copy(&fl.fl6_dst, final_p);
 
 		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
 			sk->sk_route_caps = 0;
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/udp.c	2004-10-28 22:25:59 -07:00
@@ -699,7 +699,7 @@
 		if (likely(up->pending)) {
 			if (unlikely(up->pending != AF_INET6)) {
 				release_sock(sk);
-				return -EINVAL;
+				return -EAFNOSUPPORT;
 			}
 			dst = NULL;
 			goto do_append_data;
diff -Nru a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
--- a/net/ipv6/xfrm6_output.c	2004-10-28 22:25:59 -07:00
+++ b/net/ipv6/xfrm6_output.c	2004-10-28 22:25:59 -07:00
@@ -91,16 +91,14 @@
 	return ret;
 }
 
-int xfrm6_output(struct sk_buff **pskb)
+int xfrm6_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	int err;
 	
 	if (skb->ip_summed == CHECKSUM_HW) {
-		err = skb_checksum_help(pskb, 0);
-		skb = *pskb;
+		err = skb_checksum_help(skb, 0);
 		if (err)
 			goto error_nolock;
 	}
diff -Nru a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
--- a/net/irda/irlan/irlan_client.c	2004-10-28 22:25:58 -07:00
+++ b/net/irda/irlan/irlan_client.c	2004-10-28 22:25:58 -07:00
@@ -234,7 +234,7 @@
 	ASSERT(tsap == self->client.tsap_ctrl, return;);
 
        	/* Remove frames queued on the control channel */
-	while ((skb = skb_dequeue(&self->client.txq))) {
+	while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
 		dev_kfree_skb(skb);
 	}
 	self->client.tx_busy = FALSE;
diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c	2004-10-28 22:25:58 -07:00
+++ b/net/netlink/af_netlink.c	2004-10-28 22:25:58 -07:00
@@ -80,8 +80,6 @@
 static int netlink_dump(struct sock *sk);
 static void netlink_destroy_callback(struct netlink_callback *cb);
 
-atomic_t netlink_sock_nr;
-
 static rwlock_t nl_table_lock = RW_LOCK_UNLOCKED;
 static atomic_t nl_table_users = ATOMIC_INIT(0);
 
@@ -100,11 +98,6 @@
 	BUG_TRAP(!nlk_sk(sk)->cb);
 
 	kfree(nlk_sk(sk));
-
-	atomic_dec(&netlink_sock_nr);
-#ifdef NETLINK_REFCNT_DEBUG
-	printk(KERN_DEBUG "NETLINK %p released, %d are still alive\n", sk, atomic_read(&netlink_sock_nr));
-#endif
 }
 
 /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on SMP.
@@ -240,7 +233,6 @@
 	spin_lock_init(&nlk->cb_lock);
 	init_waitqueue_head(&nlk->wait);
 	sk->sk_destruct = netlink_sock_destruct;
-	atomic_inc(&netlink_sock_nr);
 
 	sk->sk_protocol = protocol;
 	return 0;
@@ -876,7 +868,10 @@
 	if (input)
 		nlk_sk(sk)->data_ready = input;
 
-	netlink_insert(sk, 0);
+	if (netlink_insert(sk, 0)) {
+		sock_release(sock);
+		return NULL;
+	}
 	return sk;
 }
 
diff -Nru a/net/rxrpc/rxrpc_syms.c b/net/rxrpc/rxrpc_syms.c
--- a/net/rxrpc/rxrpc_syms.c	2004-10-28 22:25:57 -07:00
+++ b/net/rxrpc/rxrpc_syms.c	2004-10-28 22:25:57 -07:00
@@ -18,15 +18,7 @@
 #include <rxrpc/krxiod.h>
 
 /* call.c */
-EXPORT_SYMBOL(rxrpc_call_rcv_timeout);
-EXPORT_SYMBOL(rxrpc_call_acks_timeout);
-EXPORT_SYMBOL(rxrpc_call_dfr_ack_timeout);
-EXPORT_SYMBOL(rxrpc_call_max_resend);
-EXPORT_SYMBOL(rxrpc_call_states);
-EXPORT_SYMBOL(rxrpc_call_error_states);
-
 EXPORT_SYMBOL(rxrpc_create_call);
-EXPORT_SYMBOL(rxrpc_incoming_call);
 EXPORT_SYMBOL(rxrpc_put_call);
 EXPORT_SYMBOL(rxrpc_call_abort);
 EXPORT_SYMBOL(rxrpc_call_read_data);
@@ -37,15 +29,8 @@
 EXPORT_SYMBOL(rxrpc_create_connection);
 EXPORT_SYMBOL(rxrpc_put_connection);
 
-/* sysctl.c */
-EXPORT_SYMBOL(rxrpc_ktrace);
-EXPORT_SYMBOL(rxrpc_kdebug);
-EXPORT_SYMBOL(rxrpc_kproto);
-EXPORT_SYMBOL(rxrpc_knet);
-
 /* transport.c */
 EXPORT_SYMBOL(rxrpc_create_transport);
-EXPORT_SYMBOL(rxrpc_clear_transport);
 EXPORT_SYMBOL(rxrpc_put_transport);
 EXPORT_SYMBOL(rxrpc_add_service);
 EXPORT_SYMBOL(rxrpc_del_service);
diff -Nru a/net/sched/Kconfig b/net/sched/Kconfig
--- a/net/sched/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/net/sched/Kconfig	2004-10-28 22:25:59 -07:00
@@ -406,3 +406,10 @@
         ---help---
         requires new iproute2
         This allows packets to be mirrored or redirected to netdevices
+
+config NET_ACT_PEDIT
+        tristate "Generic Packet Editor Actions"
+        depends on NET_CLS_ACT
+        ---help---
+        requires new iproute2
+        This allows for packets to be generically edited
diff -Nru a/net/sched/Makefile b/net/sched/Makefile
--- a/net/sched/Makefile	2004-10-28 22:25:58 -07:00
+++ b/net/sched/Makefile	2004-10-28 22:25:58 -07:00
@@ -12,6 +12,7 @@
 obj-$(CONFIG_NET_CLS_POLICE)	+= police.o
 obj-$(CONFIG_NET_ACT_GACT)      += gact.o
 obj-$(CONFIG_NET_ACT_MIRRED)    += mirred.o
+obj-$(CONFIG_NET_ACT_PEDIT)     += pedit.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 obj-$(CONFIG_NET_SCH_HPFQ)	+= sch_hpfq.o
diff -Nru a/net/sched/act_api.c b/net/sched/act_api.c
--- a/net/sched/act_api.c	2004-10-28 22:25:59 -07:00
+++ b/net/sched/act_api.c	2004-10-28 22:25:59 -07:00
@@ -31,7 +31,8 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <net/sock.h>
-#include <net/pkt_sched.h>
+#include <net/sch_generic.h>
+#include <net/act_api.h>
 
 #if 1 /* control */
 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
diff -Nru a/net/sched/cls_api.c b/net/sched/cls_api.c
--- a/net/sched/cls_api.c	2004-10-28 22:25:57 -07:00
+++ b/net/sched/cls_api.c	2004-10-28 22:25:57 -07:00
@@ -36,6 +36,7 @@
 #include <linux/kmod.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
+#include <net/pkt_cls.h>
 
 #if 0 /* control */
 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
@@ -297,19 +298,6 @@
 	return err;
 }
 
-unsigned long tcf_set_class(struct tcf_proto *tp, unsigned long *clp, 
-			    unsigned long cl)
-{
-	unsigned long old_cl;
-
-	tcf_tree_lock(tp);
-	old_cl = __cls_set_class(clp, cl);
-	tcf_tree_unlock(tp);
-
-	return old_cl;
-}
-
-
 static int
 tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh,
 	      u32 pid, u32 seq, unsigned flags, int event)
@@ -475,4 +463,3 @@
 
 EXPORT_SYMBOL(register_tcf_proto_ops);
 EXPORT_SYMBOL(unregister_tcf_proto_ops);
-EXPORT_SYMBOL(tcf_set_class);
diff -Nru a/net/sched/cls_fw.c b/net/sched/cls_fw.c
--- a/net/sched/cls_fw.c	2004-10-28 22:25:57 -07:00
+++ b/net/sched/cls_fw.c	2004-10-28 22:25:57 -07:00
@@ -43,7 +43,8 @@
 #include <net/route.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
 
 struct fw_head
 {
diff -Nru a/net/sched/cls_route.c b/net/sched/cls_route.c
--- a/net/sched/cls_route.c	2004-10-28 22:25:57 -07:00
+++ b/net/sched/cls_route.c	2004-10-28 22:25:57 -07:00
@@ -33,7 +33,8 @@
 #include <net/route.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
 
 /*
    1. For now we assume that route tags < 256.
diff -Nru a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c
--- a/net/sched/cls_rsvp.c	2004-10-28 22:25:57 -07:00
+++ b/net/sched/cls_rsvp.c	2004-10-28 22:25:57 -07:00
@@ -32,7 +32,8 @@
 #include <net/route.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
 
 #define RSVP_DST_LEN	1
 #define RSVP_ID		"rsvp"
diff -Nru a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c
--- a/net/sched/cls_rsvp6.c	2004-10-28 22:25:58 -07:00
+++ b/net/sched/cls_rsvp6.c	2004-10-28 22:25:58 -07:00
@@ -33,7 +33,8 @@
 #include <net/route.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
 
 #define RSVP_DST_LEN	4
 #define RSVP_ID		"rsvp6"
diff -Nru a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
--- a/net/sched/cls_tcindex.c	2004-10-28 22:25:57 -07:00
+++ b/net/sched/cls_tcindex.c	2004-10-28 22:25:57 -07:00
@@ -12,7 +12,8 @@
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <net/ip.h>
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
 #include <net/route.h>
 
 
diff -Nru a/net/sched/cls_u32.c b/net/sched/cls_u32.c
--- a/net/sched/cls_u32.c	2004-10-28 22:25:57 -07:00
+++ b/net/sched/cls_u32.c	2004-10-28 22:25:57 -07:00
@@ -54,7 +54,8 @@
 #include <net/route.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
 
 
 struct tc_u_knode
@@ -88,7 +89,6 @@
 	struct tc_u_common	*tp_c;
 	int			refcnt;
 	unsigned		divisor;
-	u32			hgenerator;
 	struct tc_u_knode	*ht[1];
 };
 
diff -Nru a/net/sched/pedit.c b/net/sched/pedit.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/pedit.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,302 @@
+/*
+ * net/sched/pedit.c	Generic packet editor
+ *
+ *		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.
+ *
+ * Authors:	Jamal Hadi Salim (2002-4)
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/tc_act/tc_pedit.h>
+#include <net/tc_act/tc_pedit.h>
+
+
+#define PEDIT_DEB 1
+
+/* use generic hash table */
+#define MY_TAB_SIZE     16
+#define MY_TAB_MASK     15
+static u32 idx_gen;
+static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE];
+static rwlock_t pedit_lock = RW_LOCK_UNLOCKED;
+
+#define tcf_st  tcf_pedit
+#define tc_st  tc_pedit
+#define tcf_t_lock   pedit_lock
+#define tcf_ht tcf_pedit_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+
+
+int
+tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,int ovr, int bind)
+{
+	struct rtattr *tb[TCA_PEDIT_MAX];
+	struct tc_pedit *parm;
+	int size = 0;
+	int ret = 0;
+	struct tcf_pedit *p = NULL;
+
+	if (rtattr_parse(tb, TCA_PEDIT_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
+		return -1;
+
+	if (NULL == a || NULL == tb[TCA_PEDIT_PARMS - 1]) {
+		printk("BUG: tcf_pedit_init called with NULL params\n");
+		return -1;
+	}
+
+	parm = RTA_DATA(tb[TCA_PEDIT_PARMS - 1]);
+
+	p = tcf_hash_check(parm, a, ovr, bind);
+
+	if (NULL == p) { /* new */
+
+		if (!parm->nkeys)
+			return -1;
+
+		size = sizeof (*p)+ (parm->nkeys*sizeof(struct tc_pedit_key));
+
+		p = tcf_hash_create(parm,est,a,size,ovr,bind);
+
+		if (NULL == p)
+			return -1;
+		ret = 1;
+		goto override;
+	} 
+
+	if (ovr) {
+override:
+		p->flags = parm->flags;
+		p->nkeys = parm->nkeys;
+		p->action = parm->action;
+		memcpy(p->keys,parm->keys,parm->nkeys*(sizeof(struct tc_pedit_key)));
+	}
+
+	return ret;
+}
+
+int
+tcf_pedit_cleanup(struct tc_action *a, int bind)
+{
+	struct tcf_pedit *p;
+	p = PRIV(a,pedit);
+	if (NULL != p)
+		return	tcf_hash_release(p, bind);
+	return 0;
+}
+
+/*
+**
+*/
+int
+tcf_pedit(struct sk_buff **pskb, struct tc_action *a)
+{
+	struct tcf_pedit *p;
+	struct sk_buff *skb = *pskb;
+	int i, munged = 0;
+	u8 *pptr;
+
+	p = PRIV(a,pedit);
+
+	if (NULL == p) {
+		printk("BUG: tcf_pedit called with NULL params\n");
+		return -1; /* change to something symbolic */
+	}
+
+	if (!(skb->tc_verd & TC_OK2MUNGE)) {
+		/* should we set skb->cloned? */
+		if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+			return p->action;
+		}
+	}
+
+	pptr = skb->nh.raw;
+
+	spin_lock(&p->lock);
+
+	p->tm.lastuse = jiffies;
+
+	if (0 < p->nkeys) {
+		struct tc_pedit_key *tkey = p->keys;
+
+		for (i = p->nkeys; i > 0; i--, tkey++) {
+			u32 *ptr ;
+
+			int offset = tkey->off;
+			if (tkey->offmask) {
+				if (skb->len > tkey->at) {
+					 char *j = pptr+tkey->at;
+					 offset +=((*j&tkey->offmask)>>tkey->shift);
+				} else {
+					goto bad;
+				}
+			}
+
+			if (offset % 4) {
+				printk("offset must be on 32 bit boundaries\n");
+				goto bad;
+			}
+
+			if (skb->len < 0 || (offset > 0 && offset > skb->len)) {
+				printk("offset %d cant exceed pkt length %d\n",
+						offset, skb->len);
+				goto bad;
+			}
+
+
+			ptr = (u32 *)(pptr+offset);
+			/* just do it, baby */
+			*ptr = ((*ptr & tkey->mask) ^ tkey->val);
+			munged++;
+		}
+		
+		if (munged)
+			skb->tc_verd = SET_TC_MUNGED(skb->tc_verd);
+		goto done;
+	} else {
+		printk("pedit BUG: index %d\n",p->index);
+	}
+
+bad:
+	p->stats.overlimits++;
+done:
+	p->stats.bytes += skb->len;
+	p->stats.packets++;
+	spin_unlock(&p->lock);
+	return p->action;
+}
+
+int
+tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
+{
+	unsigned char *b = skb->tail;
+	struct tc_pedit *opt;
+	struct tcf_pedit *p;
+	struct tcf_t t;
+	int s; 
+		
+
+	p = PRIV(a,pedit);
+
+	if (NULL == p) {
+		printk("BUG: tcf_pedit_dump called with NULL params\n");
+		goto rtattr_failure;
+	}
+
+	s = sizeof (*opt)+(p->nkeys*sizeof(struct tc_pedit_key));
+
+	/* netlink spinlocks held above us - must use ATOMIC
+	 * */
+	opt = kmalloc(s, GFP_ATOMIC);
+	if (opt == NULL)
+		return -ENOBUFS;
+
+	memset(opt, 0, s);
+
+	memcpy(opt->keys,p->keys,p->nkeys*(sizeof(struct tc_pedit_key)));
+	opt->index = p->index;
+	opt->nkeys = p->nkeys;
+	opt->flags = p->flags;
+	opt->action = p->action;
+	opt->refcnt = p->refcnt - ref;
+	opt->bindcnt = p->bindcnt - bind;
+
+
+#ifdef PEDIT_DEB
+	{                
+		/* Debug - get rid of later */
+		int i;
+		struct tc_pedit_key *key = opt->keys;
+
+		for (i=0; i<opt->nkeys; i++, key++) {
+			printk( "\n key #%d",i);
+			printk( "  at %d: val %08x mask %08x",
+			(unsigned int)key->off,
+			(unsigned int)key->val,
+			(unsigned int)key->mask);
+												}
+											}
+#endif
+
+	RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
+	t.install = jiffies - p->tm.install;
+	t.lastuse = jiffies - p->tm.lastuse;
+	t.expires = p->tm.expires;
+	RTA_PUT(skb, TCA_PEDIT_TM, sizeof (t), &t);
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+int
+tcf_pedit_stats(struct sk_buff *skb, struct tc_action *a)
+{
+	struct tcf_pedit *p;
+	p = PRIV(a,pedit);
+	if (NULL != p)
+		return qdisc_copy_stats(skb, &p->stats, p->stats_lock);
+
+	return 1;
+}
+
+static
+struct tc_action_ops act_pedit_ops = {
+	.kind		=	"pedit",
+	.type		=	TCA_ACT_PEDIT,
+	.capab		=	TCA_CAP_NONE,
+	.owner		=	THIS_MODULE,
+	.act		=	tcf_pedit,
+	.get_stats	=	tcf_pedit_stats,
+	.dump		=	tcf_pedit_dump,
+	.cleanup	=	tcf_pedit_cleanup,
+	.lookup		=	tcf_hash_search,
+	.init		=	tcf_pedit_init,
+	.walk		=	tcf_generic_walker
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
+MODULE_DESCRIPTION("Generic Packet Editor actions");
+MODULE_LICENSE("GPL");
+
+static int __init
+pedit_init_module(void)
+{
+	return tcf_register_action(&act_pedit_ops);
+}
+
+static void __exit
+pedit_cleanup_module(void)
+{
+	tcf_unregister_action(&act_pedit_ops);
+}
+
+module_init(pedit_init_module);
+module_exit(pedit_cleanup_module);
+
diff -Nru a/net/sched/police.c b/net/sched/police.c
--- a/net/sched/police.c	2004-10-28 22:25:59 -07:00
+++ b/net/sched/police.c	2004-10-28 22:25:59 -07:00
@@ -31,7 +31,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/init.h>
 #include <net/sock.h>
-#include <net/pkt_sched.h>
+#include <net/act_api.h>
 
 #define L2T(p,L)   ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log])
 #define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log])
diff -Nru a/net/sched/sch_api.c b/net/sched/sch_api.c
--- a/net/sched/sch_api.c	2004-10-28 22:25:57 -07:00
+++ b/net/sched/sch_api.c	2004-10-28 22:25:57 -07:00
@@ -308,7 +308,7 @@
 		dev_deactivate(dev);
 
 	qdisc_lock_tree(dev);
-	if (qdisc && qdisc->flags&TCQ_F_INGRES) {
+	if (qdisc && qdisc->flags&TCQ_F_INGRESS) {
 		oqdisc = dev->qdisc_ingress;
 		/* Prune old scheduler */
 		if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) {
@@ -357,7 +357,7 @@
 
 
 	if (parent == NULL) { 
-		if (q && q->flags&TCQ_F_INGRES) {
+		if (q && q->flags&TCQ_F_INGRESS) {
 			*old = dev_graft_qdisc(dev, q);
 		} else {
 			*old = dev_graft_qdisc(dev, new);
@@ -430,7 +430,7 @@
 	skb_queue_head_init(&sch->q);
 
 	if (handle == TC_H_INGRESS)
-		sch->flags |= TCQ_F_INGRES;
+		sch->flags |= TCQ_F_INGRESS;
 
 	sch->ops = ops;
 	sch->enqueue = ops->enqueue;
@@ -453,10 +453,9 @@
 
 	/* enqueue is accessed locklessly - make sure it's visible
 	 * before we set a netdevice's qdisc pointer to sch */
-	smp_wmb();
 	if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
 		qdisc_lock_tree(dev);
-		list_add_tail(&sch->list, &dev->qdisc_list);
+		list_add_tail_rcu(&sch->list, &dev->qdisc_list);
 		qdisc_unlock_tree(dev);
 
 #ifdef CONFIG_NET_ESTIMATOR
@@ -1099,8 +1098,54 @@
 	return skb->len;
 }
 
-int psched_us_per_tick = 1;
-int psched_tick_per_us = 1;
+/* Main classifier routine: scans classifier chain attached
+   to this qdisc, (optionally) tests for protocol and asks
+   specific classifiers.
+ */
+int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
+	struct tcf_result *res)
+{
+	int err = 0;
+	u32 protocol = skb->protocol;
+#ifdef CONFIG_NET_CLS_ACT
+	struct tcf_proto *otp = tp;
+reclassify:
+#endif
+	protocol = skb->protocol;
+
+	for ( ; tp; tp = tp->next) {
+		if ((tp->protocol == protocol ||
+			tp->protocol == __constant_htons(ETH_P_ALL)) &&
+			(err = tp->classify(skb, tp, res)) >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+			if ( TC_ACT_RECLASSIFY == err) {
+				__u32 verd = (__u32) G_TC_VERD(skb->tc_verd);
+				tp = otp;
+
+				if (MAX_REC_LOOP < verd++) {
+					printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n",
+						tp->prio&0xffff, ntohs(tp->protocol));
+					return TC_ACT_SHOT;
+				}
+				skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd);
+				goto reclassify;
+			} else {
+				if (skb->tc_verd) 
+					skb->tc_verd = SET_TC_VERD(skb->tc_verd,0);
+				return err;
+			}
+#else
+
+			return err;
+#endif
+		}
+
+	}
+	return -1;
+}
+
+static int psched_us_per_tick = 1;
+static int psched_tick_per_us = 1;
 
 #ifdef CONFIG_PROC_FS
 static int psched_show(struct seq_file *seq, void *v)
@@ -1126,21 +1171,6 @@
 };	
 #endif
 
-#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY
-int psched_tod_diff(int delta_sec, int bound)
-{
-	int delta;
-
-	if (bound <= 1000000 || delta_sec > (0x7FFFFFFF/1000000)-1)
-		return bound;
-	delta = delta_sec * 1000000;
-	if (delta > bound)
-		delta = bound;
-	return delta;
-}
-EXPORT_SYMBOL(psched_tod_diff);
-#endif
-
 #ifdef CONFIG_NET_SCH_CLK_CPU
 psched_tdiff_t psched_clock_per_hz;
 int psched_clock_scale;
@@ -1246,3 +1276,4 @@
 EXPORT_SYMBOL(qdisc_put_rtab);
 EXPORT_SYMBOL(register_qdisc);
 EXPORT_SYMBOL(unregister_qdisc);
+EXPORT_SYMBOL(tc_classify);
diff -Nru a/net/sched/sch_netem.c b/net/sched/sch_netem.c
--- a/net/sched/sch_netem.c	2004-10-28 22:25:59 -07:00
+++ b/net/sched/sch_netem.c	2004-10-28 22:25:59 -07:00
@@ -142,19 +142,23 @@
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
+	psched_tdiff_t td;
 	psched_time_t now;
 	
 	PSCHED_GET_TIME(now);
-	PSCHED_TADD2(now, tabledist(q->latency, q->jitter, 
-				    &q->delay_cor, q->delay_dist),
-		     cb->time_to_send);
+	td = tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist);
+	PSCHED_TADD2(now, td, cb->time_to_send);
 	
 	/* Always queue at tail to keep packets in order */
 	if (likely(q->delayed.qlen < q->limit)) {
 		__skb_queue_tail(&q->delayed, skb);
-		sch->q.qlen++;
 		sch->bstats.bytes += skb->len;
 		sch->bstats.packets++;
+
+		if (!timer_pending(&q->timer)) {
+			q->timer.expires = jiffies + PSCHED_US2JIFFIE(td);
+			add_timer(&q->timer);
+		}
 		return NET_XMIT_SUCCESS;
 	}
 
@@ -243,15 +247,31 @@
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
+
+	skb = q->qdisc->dequeue(q->qdisc);
+	if (skb) 
+		sch->q.qlen--;
+	return skb;
+}
+
+static void netem_watchdog(unsigned long arg)
+{
+	struct Qdisc *sch = (struct Qdisc *)arg;
+	struct netem_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb;
 	psched_time_t now;
 
+	pr_debug("netem_watchdog: fired @%lu\n", jiffies);
+
+	spin_lock_bh(&sch->dev->queue_lock);
 	PSCHED_GET_TIME(now);
+
 	while ((skb = skb_peek(&q->delayed)) != NULL) {
 		const struct netem_skb_cb *cb
 			= (const struct netem_skb_cb *)skb->cb;
 		long delay 
 			= PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
-		pr_debug("netem_dequeue: delay queue %p@%lu %ld\n",
+		pr_debug("netem_watchdog: skb %p@%lu %ld\n",
 			 skb, jiffies, delay);
 
 		/* if more time remaining? */
@@ -263,20 +283,10 @@
 
 		if (q->qdisc->enqueue(skb, q->qdisc))
 			sch->qstats.drops++;
+		else
+			sch->q.qlen++;
 	}
-
-	skb = q->qdisc->dequeue(q->qdisc);
-	if (skb) 
-		sch->q.qlen--;
-	return skb;
-}
-
-static void netem_watchdog(unsigned long arg)
-{
-	struct Qdisc *sch = (struct Qdisc *)arg;
-
-	pr_debug("netem_watchdog: fired @%lu\n", jiffies);
-	netif_schedule(sch->dev);
+	spin_unlock_bh(&sch->dev->queue_lock);
 }
 
 static void netem_reset(struct Qdisc *sch)
@@ -493,7 +503,7 @@
 	sch_tree_lock(sch);
 	*old = xchg(&q->qdisc, new);
 	qdisc_reset(*old);
-	sch->q.qlen = q->delayed.qlen;
+	sch->q.qlen = 0;
 	sch_tree_unlock(sch);
 
 	return 0;
diff -Nru a/net/sctp/associola.c b/net/sctp/associola.c
--- a/net/sctp/associola.c	2004-10-28 22:25:56 -07:00
+++ b/net/sctp/associola.c	2004-10-28 22:25:56 -07:00
@@ -271,7 +271,7 @@
 
 	asoc->need_ecne = 0;
 
-	asoc->assoc_id = (sctp_assoc_t)-1L;
+	asoc->assoc_id = 0;
 
 	/* Assume that peer would support both address types unless we are
 	 * told otherwise.
@@ -374,9 +374,9 @@
 	sctp_endpoint_put(asoc->ep);
 	sock_put(asoc->base.sk);
 
-	if ((long)asoc->assoc_id != -1L) {
+	if (asoc->assoc_id != 0) {
 		spin_lock_bh(&sctp_assocs_id_lock);
-		idr_remove(&sctp_assocs_id, (long)asoc->assoc_id);
+		idr_remove(&sctp_assocs_id, asoc->assoc_id);
 		spin_unlock_bh(&sctp_assocs_id_lock);
 	}
 
@@ -482,14 +482,15 @@
 
 	/* 7.2.1 Slow-Start
 	 *
-	 * o The initial cwnd before data transmission or after a
-	 *   sufficiently long idle period MUST be <= 2*MTU.
+	 * o The initial cwnd before DATA transmission or after a sufficiently
+	 *   long idle period MUST be set to
+	 *      min(4*MTU, max(2*MTU, 4380 bytes))
 	 *
 	 * o The initial value of ssthresh MAY be arbitrarily high
 	 *   (for example, implementations MAY use the size of the
 	 *   receiver advertised window).
 	 */
-	peer->cwnd = asoc->pmtu * 2;
+	peer->cwnd = min(4*asoc->pmtu, max_t(__u32, 2*asoc->pmtu, 4380));
 
 	/* At this point, we may not have the receiver's advertised window,
 	 * so initialize ssthresh to the default value and it will be set
diff -Nru a/net/sctp/outqueue.c b/net/sctp/outqueue.c
--- a/net/sctp/outqueue.c	2004-10-28 22:25:57 -07:00
+++ b/net/sctp/outqueue.c	2004-10-28 22:25:57 -07:00
@@ -706,10 +706,19 @@
 		if (!new_transport) {
 			new_transport = asoc->peer.active_path;
 		} else if (!new_transport->active) {
-			/* If the chunk is Heartbeat, send it to
-			 * chunk->transport, even it's inactive.
+			/* If the chunk is Heartbeat or Heartbeat Ack, 
+			 * send it to chunk->transport, even if it's 
+			 * inactive.
+			 *
+			 * 3.3.6 Heartbeat Acknowledgement:
+			 * ...  
+			 * A HEARTBEAT ACK is always sent to the source IP
+			 * address of the IP datagram containing the
+			 * HEARTBEAT chunk to which this ack is responding.
+			 * ...  
 			 */
-			if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT)
+			if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT &&
+			    chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT_ACK)
 				new_transport = asoc->peer.active_path;
 		}
 
diff -Nru a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
--- a/net/sctp/sm_make_chunk.c	2004-10-28 22:25:57 -07:00
+++ b/net/sctp/sm_make_chunk.c	2004-10-28 22:25:57 -07:00
@@ -171,6 +171,7 @@
 	struct sctp_opt *sp;
 	sctp_supported_addrs_param_t sat;
 	__u16 types[2];
+	sctp_adaption_ind_param_t aiparam;
 
 	/* RFC 2960 3.3.2 Initiation (INIT) (1)
 	 *
@@ -196,6 +197,7 @@
 	chunksize += sizeof(ecap_param);
 	if (sctp_prsctp_enable)
 		chunksize += sizeof(prsctp_param);
+	chunksize += sizeof(aiparam);
 	chunksize += vparam_len;
 
 	/* RFC 2960 3.3.2 Initiation (INIT) (1)
@@ -234,6 +236,10 @@
 	sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
 	if (sctp_prsctp_enable)
 		sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
+	aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+	aiparam.param_hdr.length = htons(sizeof(aiparam));
+	aiparam.adaption_ind = htonl(sp->adaption_ind);
+	sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
 nodata:
 	if (addrs.v)
 		kfree(addrs.v);
@@ -251,6 +257,7 @@
 	sctp_cookie_param_t *cookie;
 	int cookie_len;
 	size_t chunksize;
+	sctp_adaption_ind_param_t aiparam;
 
 	retval = NULL;
 
@@ -284,6 +291,8 @@
 	if (asoc->peer.prsctp_capable)
 		chunksize += sizeof(prsctp_param);
 
+	chunksize += sizeof(aiparam);
+
 	/* Now allocate and fill out the chunk.  */
 	retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
 	if (!retval)
@@ -302,6 +311,11 @@
 	if (asoc->peer.prsctp_capable)
 		sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
 
+	aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+	aiparam.param_hdr.length = htons(sizeof(aiparam));
+	aiparam.adaption_ind = htonl(sctp_sk(asoc->base.sk)->adaption_ind);
+	sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
+
 	/* We need to remove the const qualifier at this point.  */
 	retval->asoc = (struct sctp_association *) asoc;
 
@@ -1297,6 +1311,9 @@
 	/* Remember PR-SCTP capability. */
 	cookie->c.prsctp_capable = asoc->peer.prsctp_capable;
 
+	/* Save adaption indication in the cookie. */
+	cookie->c.adaption_ind = asoc->peer.adaption_ind;
+
 	/* Set an expiration time for the cookie.  */
 	do_gettimeofday(&cookie->c.expiration);
 	TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration);
@@ -1455,6 +1472,7 @@
 	retval->addip_serial = retval->c.initial_tsn;
 	retval->adv_peer_ack_point = retval->ctsn_ack_point;
 	retval->peer.prsctp_capable = retval->c.prsctp_capable;
+	retval->peer.adaption_ind = retval->c.adaption_ind;
 
 	/* The INIT stuff will be done by the side effects.  */
 	return retval;
@@ -1661,6 +1679,7 @@
 	case SCTP_PARAM_HEARTBEAT_INFO:
 	case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
 	case SCTP_PARAM_ECN_CAPABLE:
+	case SCTP_PARAM_ADAPTION_LAYER_IND:
 		break;
 
 	case SCTP_PARAM_HOST_NAME_ADDRESS:
@@ -1989,6 +2008,10 @@
 		asoc->peer.ecn_capable = 1;
 		break;
 
+	case SCTP_PARAM_ADAPTION_LAYER_IND:
+		asoc->peer.adaption_ind = param.aind->adaption_ind;
+		break;
+
 	case SCTP_PARAM_FWD_TSN_SUPPORT:
 		if (sctp_prsctp_enable) {
 			asoc->peer.prsctp_capable = 1;
@@ -2459,6 +2482,8 @@
 	union sctp_addr	addr;
 	struct sctp_bind_addr *bp = &asoc->base.bind_addr;
 	union sctp_addr_param *addr_param;
+	struct list_head *pos;
+	struct sctp_transport *transport;
 	int retval = 0;
 
 	addr_param = (union sctp_addr_param *)
@@ -2482,6 +2507,12 @@
 		retval = sctp_del_bind_addr(bp, &addr);
 		sctp_write_unlock(&asoc->base.addr_lock);
 		sctp_local_bh_enable();
+		list_for_each(pos, &asoc->peer.transport_addr_list) {
+			transport = list_entry(pos, struct sctp_transport,
+						 transports);
+			sctp_transport_route(transport, NULL,
+					     sctp_sk(asoc->base.sk));
+		}
 		break;
 	default:
 		break;
diff -Nru a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
--- a/net/sctp/sm_statefuns.c	2004-10-28 22:25:56 -07:00
+++ b/net/sctp/sm_statefuns.c	2004-10-28 22:25:56 -07:00
@@ -629,6 +629,21 @@
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
 
+	/* Sockets API Draft Section 5.3.1.6 	
+	 * When a peer sends a Adaption Layer Indication parameter , SCTP
+	 * delivers this notification to inform the application that of the
+	 * peers requested adaption layer.
+	 */
+	if (new_asoc->peer.adaption_ind) {
+		ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+							    GFP_ATOMIC);
+		if (!ev)
+			goto nomem_ev;
+
+		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+				SCTP_ULPEVENT(ev));
+	}
+
 	return SCTP_DISPOSITION_CONSUME;
 
 nomem_ev:
@@ -713,6 +728,20 @@
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
 
+	/* Sockets API Draft Section 5.3.1.6
+	 * When a peer sends a Adaption Layer Indication parameter , SCTP
+	 * delivers this notification to inform the application that of the
+	 * peers requested adaption layer.
+	 */
+	if (asoc->peer.adaption_ind) {
+		ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+		if (!ev)
+			goto nomem;
+
+		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+				SCTP_ULPEVENT(ev));
+	}
+
 	return SCTP_DISPOSITION_CONSUME;
 nomem:
 	return SCTP_DISPOSITION_NOMEM;
@@ -1532,6 +1561,21 @@
 		goto nomem_ev;
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+
+	/* Sockets API Draft Section 5.3.1.6
+	 * When a peer sends a Adaption Layer Indication parameter , SCTP
+	 * delivers this notification to inform the application that of the
+	 * peers requested adaption layer.
+	 */
+	if (asoc->peer.adaption_ind) {
+		ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+		if (!ev)
+			goto nomem_ev;
+
+		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+				SCTP_ULPEVENT(ev));
+	}
+
 	return SCTP_DISPOSITION_CONSUME;
 
 nomem_ev:
@@ -1612,6 +1656,21 @@
 			goto nomem;
 		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
 				SCTP_ULPEVENT(ev));
+
+		/* Sockets API Draft Section 5.3.1.6
+		 * When a peer sends a Adaption Layer Indication parameter,
+		 * SCTP delivers this notification to inform the application
+		 * that of the peers requested adaption layer.
+		 */
+		if (new_asoc->peer.adaption_ind) {
+			ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+								 GFP_ATOMIC);
+			if (!ev)
+				goto nomem;
+
+			sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+					SCTP_ULPEVENT(ev));
+		}
 	}
 	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
 
diff -Nru a/net/sctp/socket.c b/net/sctp/socket.c
--- a/net/sctp/socket.c	2004-10-28 22:25:59 -07:00
+++ b/net/sctp/socket.c	2004-10-28 22:25:59 -07:00
@@ -1063,7 +1063,7 @@
 	struct sctp_sndrcvinfo default_sinfo = { 0 };
 	struct sctp_sndrcvinfo *sinfo;
 	struct sctp_initmsg *sinit;
-	sctp_assoc_t associd = NULL;
+	sctp_assoc_t associd = 0;
 	sctp_cmsgs_t cmsgs = { NULL };
 	int err;
 	sctp_scope_t scope;
@@ -2120,6 +2120,20 @@
 	return err;
 }
 
+static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
+					  int optlen)
+{
+	__u32 val;
+
+	if (optlen < sizeof(__u32))
+		return -EINVAL;
+	if (copy_from_user(&val, optval, sizeof(__u32)))
+		return -EFAULT;
+
+	sctp_sk(sk)->adaption_ind = val;
+
+	return 0;
+}
 
 /* API 6.2 setsockopt(), getsockopt()
  *
@@ -2219,6 +2233,10 @@
 	case SCTP_MAXSEG:
 		retval = sctp_setsockopt_maxseg(sk, optval, optlen);
 		break;
+	case SCTP_ADAPTION_LAYER:
+		retval = sctp_setsockopt_adaption_layer(sk, optval, optlen);
+		break;
+
 	default:
 		retval = -ENOPROTOOPT;
 		break;
@@ -2518,6 +2536,8 @@
 	/* User specified fragmentation limit. */
 	sp->user_frag         = 0;
 
+	sp->adaption_ind = 0;
+
 	sp->pf = sctp_get_pf_specific(sk->sk_family);
 
 	/* Control variables for partial data delivery. */
@@ -3160,6 +3180,29 @@
 }
 
 /*
+ * 7.1.11  Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
+ *
+ * Requests that the local endpoint set the specified Adaption Layer
+ * Indication parameter for all future INIT and INIT-ACK exchanges.
+ */
+static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
+				  char __user *optval, int __user *optlen)
+{
+	__u32 val;
+
+	if (len < sizeof(__u32))
+		return -EINVAL;
+
+	len = sizeof(__u32);
+	val = sctp_sk(sk)->adaption_ind;
+	if (put_user(len, optlen))
+		return -EFAULT;
+	if (copy_to_user(optval, &val, len))
+		return -EFAULT;
+	return 0;
+}
+
+/*
  *
  * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM)
  *
@@ -3513,6 +3556,10 @@
 		break;
 	case SCTP_GET_PEER_ADDR_INFO:
 		retval = sctp_getsockopt_peer_addr_info(sk, len, optval,
+							optlen);
+		break;
+	case SCTP_ADAPTION_LAYER:
+		retval = sctp_getsockopt_adaption_layer(sk, len, optval,
 							optlen);
 		break;
 	default:
diff -Nru a/net/sctp/transport.c b/net/sctp/transport.c
--- a/net/sctp/transport.c	2004-10-28 22:25:57 -07:00
+++ b/net/sctp/transport.c	2004-10-28 22:25:57 -07:00
@@ -421,15 +421,15 @@
 {
 	switch (reason) {
 	case SCTP_LOWER_CWND_T3_RTX:
-		/* RFC 2960 Section 7.2.3, sctpimpguide-05 Section 2.9.2
+		/* RFC 2960 Section 7.2.3, sctpimpguide
 		 * When the T3-rtx timer expires on an address, SCTP should
 		 * perform slow start by:
-		 *      ssthresh = max(cwnd/2, 2*MTU)
+		 *      ssthresh = max(cwnd/2, 4*MTU)
 		 *      cwnd = 1*MTU
 		 *      partial_bytes_acked = 0
 		 */
 		transport->ssthresh = max(transport->cwnd/2,
-					  2*transport->asoc->pmtu);
+					  4*transport->asoc->pmtu);
 		transport->cwnd = transport->asoc->pmtu;
 		break;
 
@@ -439,15 +439,15 @@
 		 * were last sent, according to the formula described in
 		 * Section 7.2.3.
 	 	 *
-	 	 * RFC 2960 7.2.3, sctpimpguide-05 2.9.2 Upon detection of
-		 * packet losses from SACK (see Section 7.2.4), An endpoint
+	 	 * RFC 2960 7.2.3, sctpimpguide Upon detection of packet
+		 * losses from SACK (see Section 7.2.4), An endpoint
 		 * should do the following:
-		 *      ssthresh = max(cwnd/2, 2*MTU)
+		 *      ssthresh = max(cwnd/2, 4*MTU)
 		 *      cwnd = ssthresh
 		 *      partial_bytes_acked = 0
 		 */
 		transport->ssthresh = max(transport->cwnd/2,
-					  2*transport->asoc->pmtu);
+					  4*transport->asoc->pmtu);
 		transport->cwnd = transport->ssthresh;
 		break;
 
@@ -467,23 +467,24 @@
 		if ((jiffies - transport->last_time_ecne_reduced) >
 		    transport->rtt) {
 			transport->ssthresh = max(transport->cwnd/2,
-					  	  2*transport->asoc->pmtu);
+					  	  4*transport->asoc->pmtu);
 			transport->cwnd = transport->ssthresh;
 			transport->last_time_ecne_reduced = jiffies;
 		}
 		break;
 
 	case SCTP_LOWER_CWND_INACTIVE:
-		/* RFC 2960 Section 7.2.1, sctpimpguide-05 Section 2.14.2
-		 * When the association does not transmit data on a given
-		 * transport address within an RTO, the cwnd of the transport
-		 * address should be adjusted to 2*MTU.
+		/* RFC 2960 Section 7.2.1, sctpimpguide
+		 * When the endpoint does not transmit data on a given
+		 * transport address, the cwnd of the transport address
+		 * should be adjusted to max(cwnd/2, 4*MTU) per RTO.
 		 * NOTE: Although the draft recommends that this check needs
 		 * to be done every RTO interval, we do it every hearbeat
 		 * interval.
 		 */
 		if ((jiffies - transport->last_time_used) > transport->rto)
-			transport->cwnd = 2*transport->asoc->pmtu;
+			transport->cwnd = max(transport->cwnd/2,
+						 4*transport->asoc->pmtu);
 		break;
 	};
 
diff -Nru a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
--- a/net/sctp/ulpevent.c	2004-10-28 22:25:57 -07:00
+++ b/net/sctp/ulpevent.c	2004-10-28 22:25:57 -07:00
@@ -562,7 +562,7 @@
 	struct sctp_shutdown_event *sse;
 	struct sk_buff *skb;
 
-	event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
+	event = sctp_ulpevent_new(sizeof(struct sctp_shutdown_event),
 				  MSG_NOTIFICATION, gfp);
 	if (!event)
 		goto fail;
@@ -613,6 +613,40 @@
 	return NULL;
 }
 
+/* Create and initialize a SCTP_ADAPTION_INDICATION notification.
+ *
+ * Socket Extensions for SCTP
+ * 5.3.1.6 SCTP_ADAPTION_INDICATION
+ */
+struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
+	const struct sctp_association *asoc, int gfp)
+{
+	struct sctp_ulpevent *event;
+	struct sctp_adaption_event *sai;
+	struct sk_buff *skb;
+
+	event = sctp_ulpevent_new(sizeof(struct sctp_adaption_event),
+				  MSG_NOTIFICATION, gfp);
+	if (!event)
+		goto fail;
+
+	skb = sctp_event2skb(event);
+	sai = (struct sctp_adaption_event *)
+		skb_put(skb, sizeof(struct sctp_adaption_event));
+
+	sai->sai_type = SCTP_ADAPTION_INDICATION;
+	sai->sai_flags = 0;
+	sai->sai_length = sizeof(struct sctp_adaption_event);
+	sai->sai_adaption_ind = asoc->peer.adaption_ind;
+	sctp_ulpevent_set_owner(event, asoc);
+	sai->sai_assoc_id = sctp_assoc2id(asoc);
+
+	return event;
+
+fail:
+	return NULL;
+}
+
 /* A message has been received.  Package this message as a notification
  * to pass it to the upper layers.  Go ahead and calculate the sndrcvinfo
  * even if filtered out later.
@@ -689,7 +723,7 @@
 	struct sctp_pdapi_event *pd;
 	struct sk_buff *skb;
 
-	event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
+	event = sctp_ulpevent_new(sizeof(struct sctp_pdapi_event),
 				  MSG_NOTIFICATION, gfp);
 	if (!event)
 		goto fail;
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	2004-10-28 22:25:57 -07:00
+++ b/net/socket.c	2004-10-28 22:25:57 -07:00
@@ -459,7 +459,7 @@
  *	NULL is returned.
  */
 
-struct socket *sock_alloc(void)
+static struct socket *sock_alloc(void)
 {
 	struct inode * inode;
 	struct socket * sock;
@@ -1354,7 +1354,7 @@
 	if (!sock)
 		goto out;
 
-	err = -EMFILE;
+	err = -ENFILE;
 	if (!(newsock = sock_alloc())) 
 		goto out_put;
 
@@ -2089,8 +2089,6 @@
 /* ABI emulation layers need these two */
 EXPORT_SYMBOL(move_addr_to_kernel);
 EXPORT_SYMBOL(move_addr_to_user);
-EXPORT_SYMBOL(sock_alloc);
-EXPORT_SYMBOL(sock_alloc_inode);
 EXPORT_SYMBOL(sock_create);
 EXPORT_SYMBOL(sock_create_kern);
 EXPORT_SYMBOL(sock_create_lite);
diff -Nru a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
--- a/net/sunrpc/rpc_pipe.c	2004-10-28 22:25:57 -07:00
+++ b/net/sunrpc/rpc_pipe.c	2004-10-28 22:25:57 -07:00
@@ -523,16 +523,12 @@
 {
 	struct inode *inode, *dir = parent->d_inode;
 	void *private = RPC_I(dir)->private;
-	struct qstr name;
 	struct dentry *dentry;
 	int mode, i;
 
 	down(&dir->i_sem);
 	for (i = start; i < eof; i++) {
-		name.name = files[i].name;
-		name.len = strlen(name.name);
-		name.hash = full_name_hash(name.name, name.len);
-		dentry = d_alloc(parent, &name);
+		dentry = d_alloc_name(parent, files[i].name);
 		if (!dentry)
 			goto out_bad;
 		mode = files[i].mode;
diff -Nru a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c
--- a/net/xfrm/xfrm_export.c	2004-10-28 22:25:58 -07:00
+++ b/net/xfrm/xfrm_export.c	2004-10-28 22:25:58 -07:00
@@ -12,22 +12,17 @@
 EXPORT_SYMBOL(__xfrm_route_forward);
 EXPORT_SYMBOL(xfrm_state_alloc);
 EXPORT_SYMBOL(__xfrm_state_destroy);
-EXPORT_SYMBOL(xfrm_state_find);
 EXPORT_SYMBOL(xfrm_state_insert);
 EXPORT_SYMBOL(xfrm_state_add);
 EXPORT_SYMBOL(xfrm_state_update);
 EXPORT_SYMBOL(xfrm_state_check_expire);
-EXPORT_SYMBOL(xfrm_state_check_space);
 EXPORT_SYMBOL(xfrm_state_check);
 EXPORT_SYMBOL(xfrm_state_lookup);
 EXPORT_SYMBOL(xfrm_state_register_afinfo);
 EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
-EXPORT_SYMBOL(xfrm_state_get_afinfo);
-EXPORT_SYMBOL(xfrm_state_put_afinfo);
 EXPORT_SYMBOL(xfrm_state_delete_tunnel);
 EXPORT_SYMBOL(xfrm_replay_check);
 EXPORT_SYMBOL(xfrm_replay_advance);
-EXPORT_SYMBOL(xfrm_check_selectors);
 EXPORT_SYMBOL(__secpath_destroy);
 EXPORT_SYMBOL(secpath_dup);
 EXPORT_SYMBOL(xfrm_get_acqseq);
@@ -44,7 +39,6 @@
 EXPORT_SYMBOL(xfrm_find_acq);
 EXPORT_SYMBOL(xfrm_alloc_spi);
 EXPORT_SYMBOL(xfrm_state_flush);
-EXPORT_SYMBOL(xfrm_policy_kill);
 EXPORT_SYMBOL(xfrm_policy_bysel);
 EXPORT_SYMBOL(xfrm_policy_insert);
 EXPORT_SYMBOL(xfrm_policy_walk);
@@ -54,8 +48,6 @@
 EXPORT_SYMBOL(xfrm_dst_lookup);
 EXPORT_SYMBOL(xfrm_policy_register_afinfo);
 EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
-EXPORT_SYMBOL(xfrm_policy_get_afinfo);
-EXPORT_SYMBOL(xfrm_policy_put_afinfo);
 
 EXPORT_SYMBOL_GPL(xfrm_probe_algs);
 EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
--- a/net/xfrm/xfrm_policy.c	2004-10-28 22:25:58 -07:00
+++ b/net/xfrm/xfrm_policy.c	2004-10-28 22:25:58 -07:00
@@ -40,6 +40,9 @@
 	LIST_HEAD_INIT(xfrm_policy_gc_list);
 static spinlock_t xfrm_policy_gc_lock = SPIN_LOCK_UNLOCKED;
 
+static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
+static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+
 int xfrm_register_type(struct xfrm_type *type, unsigned short family)
 {
 	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
@@ -286,7 +289,7 @@
  * entry dead. The rule must be unlinked from lists to the moment.
  */
 
-void xfrm_policy_kill(struct xfrm_policy *policy)
+static void xfrm_policy_kill(struct xfrm_policy *policy)
 {
 	write_lock_bh(&policy->lock);
 	if (policy->dead)
@@ -1187,7 +1190,7 @@
 	return err;
 }
 
-struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
+static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
 {
 	struct xfrm_policy_afinfo *afinfo;
 	if (unlikely(family >= NPROTO))
@@ -1200,7 +1203,7 @@
 	return afinfo;
 }
 
-void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
+static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
 	if (unlikely(afinfo == NULL))
 		return;
diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
--- a/net/xfrm/xfrm_state.c	2004-10-28 22:25:58 -07:00
+++ b/net/xfrm/xfrm_state.c	2004-10-28 22:25:58 -07:00
@@ -48,6 +48,9 @@
 
 static void __xfrm_state_delete(struct xfrm_state *x);
 
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
+
 static void xfrm_state_gc_destroy(struct xfrm_state *x)
 {
 	if (del_timer(&x->timer))
@@ -526,7 +529,7 @@
 	return 0;
 }
 
-int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
+static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int nhead = x->props.header_len + LL_RESERVED_SPACE(skb->dst->dev)
 		- skb_headroom(skb);
@@ -740,19 +743,6 @@
 	}
 }
 
-int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl)
-{
-	int i;
-
-	for (i=0; i<n; i++) {
-		int match;
-		match = xfrm_selector_match(&x[i]->sel, fl, x[i]->props.family);
-		if (!match)
-			return -EINVAL;
-	}
-	return 0;
-}
-
 static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
 static rwlock_t		xfrm_km_lock = RW_LOCK_UNLOCKED;
 
@@ -914,7 +904,7 @@
 	return err;
 }
 
-struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
 {
 	struct xfrm_state_afinfo *afinfo;
 	if (unlikely(family >= NPROTO))
@@ -927,7 +917,7 @@
 	return afinfo;
 }
 
-void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
 {
 	if (unlikely(afinfo == NULL))
 		return;
diff -Nru a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
--- a/net/xfrm/xfrm_user.c	2004-10-28 22:25:58 -07:00
+++ b/net/xfrm/xfrm_user.c	2004-10-28 22:25:58 -07:00
@@ -332,6 +332,7 @@
 	struct sk_buff *in_skb;
 	struct sk_buff *out_skb;
 	u32 nlmsg_seq;
+	u16 nlmsg_flags;
 	int start_idx;
 	int this_idx;
 };
@@ -351,7 +352,7 @@
 	nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid,
 			sp->nlmsg_seq,
 			XFRM_MSG_NEWSA, sizeof(*p));
-	nlh->nlmsg_flags = 0;
+	nlh->nlmsg_flags = sp->nlmsg_flags;
 
 	p = NLMSG_DATA(nlh);
 	copy_to_user_state(x, p);
@@ -386,6 +387,7 @@
 	info.in_skb = cb->skb;
 	info.out_skb = skb;
 	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+	info.nlmsg_flags = NLM_F_MULTI;
 	info.this_idx = 0;
 	info.start_idx = cb->args[0];
 	(void) xfrm_state_walk(IPSEC_PROTO_ANY, dump_one_state, &info);
@@ -408,6 +410,7 @@
 	info.in_skb = in_skb;
 	info.out_skb = skb;
 	info.nlmsg_seq = seq;
+	info.nlmsg_flags = 0;
 	info.this_idx = info.start_idx = 0;
 
 	if (dump_one_state(x, 0, &info)) {
@@ -743,7 +746,7 @@
 			sp->nlmsg_seq,
 			XFRM_MSG_NEWPOLICY, sizeof(*p));
 	p = NLMSG_DATA(nlh);
-	nlh->nlmsg_flags = 0;
+	nlh->nlmsg_flags = sp->nlmsg_flags;
 
 	copy_to_user_policy(xp, p, dir);
 	if (copy_to_user_tmpl(xp, skb) < 0)
@@ -766,6 +769,7 @@
 	info.in_skb = cb->skb;
 	info.out_skb = skb;
 	info.nlmsg_seq = cb->nlh->nlmsg_seq;
+	info.nlmsg_flags = NLM_F_MULTI;
 	info.this_idx = 0;
 	info.start_idx = cb->args[0];
 	(void) xfrm_policy_walk(dump_one_policy, &info);
@@ -789,6 +793,7 @@
 	info.in_skb = in_skb;
 	info.out_skb = skb;
 	info.nlmsg_seq = seq;
+	info.nlmsg_flags = 0;
 	info.this_idx = info.start_idx = 0;
 
 	if (dump_one_policy(xp, dir, 0, &info) < 0) {
@@ -1232,8 +1237,7 @@
 
 	xfrm_nl = netlink_kernel_create(NETLINK_XFRM, xfrm_netlink_rcv);
 	if (xfrm_nl == NULL)
-		panic("xfrm_user_init: cannot initialize xfrm_nl\n");
-
+		return -ENOMEM;
 
 	xfrm_register_km(&netlink_mgr);
 
diff -Nru a/scripts/Makefile.lib b/scripts/Makefile.lib
--- a/scripts/Makefile.lib	2004-10-28 22:25:58 -07:00
+++ b/scripts/Makefile.lib	2004-10-28 22:25:58 -07:00
@@ -232,3 +232,30 @@
 # Usage:
 # $(Q)$(MAKE) $(build)=dir
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
+
+# filechk is used to check if the content of a generated file is updated.
+# Sample usage:
+# define filechk_sample
+#	echo $KERNELRELEASE
+# endef
+# version.h : Makefile
+#	$(call filechk,sample)
+# The rule defined shall write to stdout the content of the new file.
+# The existing file will be compared with the new one.
+# - If no file exist it is created
+# - If the content differ the new file is used
+# - If they are equal no change, and no timestamp update
+
+define filechk
+	$(Q)set -e;				\
+	echo '  CHK     $@';			\
+	mkdir -p $(dir $@);			\
+	$(filechk_$(1)) $(2) > $@.tmp;		\
+	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
+		rm -f $@.tmp;			\
+	else					\
+		echo '  UPD     $@';		\
+		mv -f $@.tmp $@;		\
+	fi
+endef
+
diff -Nru a/scripts/Makefile.modinst b/scripts/Makefile.modinst
--- a/scripts/Makefile.modinst	2004-10-28 22:25:58 -07:00
+++ b/scripts/Makefile.modinst	2004-10-28 22:25:58 -07:00
@@ -19,7 +19,10 @@
 quiet_cmd_modules_install = INSTALL $@
       cmd_modules_install = mkdir -p $(2); cp $@ $(2)
 
-modinst_dir = $(MODLIB)/$(if $(filter ../% /%,$@),extra/,kernel/$(@D))
+# Modules built outside the kernel source tree go into extra by default
+INSTALL_MOD_DIR ?= extra
+
+modinst_dir = $(MODLIB)/$(if $(filter ../% /%,$@),$(INSTALL_MOD_DIR)/,kernel/$(@D))
 
 $(modules):
 	$(call cmd,modules_install,$(modinst_dir))
diff -Nru a/scripts/basic/docproc.c b/scripts/basic/docproc.c
--- a/scripts/basic/docproc.c	2004-10-28 22:25:57 -07:00
+++ b/scripts/basic/docproc.c	2004-10-28 22:25:57 -07:00
@@ -52,7 +52,7 @@
 FILEONLY *externalfunctions;
 FILEONLY *symbolsonly;
 
-typedef void FILELINE(char * file, char * line);
+typedef void FILELINE(char * file, signed char * line);
 FILELINE * singlefunctions;
 FILELINE * entity_system;
 
@@ -79,6 +79,7 @@
 {
 	pid_t pid;
 	int ret;
+	char real_filename[PATH_MAX + 1];
 	/* Make sure output generated so far are flushed */
 	fflush(stdout);
 	switch(pid=fork()) {
@@ -86,8 +87,13 @@
 			perror("fork");
 			exit(1);
 		case  0:
-			execvp(KERNELDOCPATH KERNELDOC, svec);
-			perror("exec " KERNELDOCPATH KERNELDOC);
+			memset(real_filename, 0, sizeof(real_filename));
+			strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
+			strncat(real_filename, KERNELDOCPATH KERNELDOC,
+					PATH_MAX - strlen(real_filename));
+			execvp(real_filename, svec);
+			fprintf(stderr, "exec ");
+			perror(real_filename);
 			exit(1);
 		default:
 			waitpid(pid, &ret ,0);
@@ -142,9 +148,9 @@
  * Files are separated by tabs.
  */
 void adddep(char * file)		   { printf("\t%s", file); }
-void adddep2(char * file, char * line)     { line = line; adddep(file); }
+void adddep2(char * file, signed char * line)     { line = line; adddep(file); }
 void noaction(char * line)		   { line = line; }
-void noaction2(char * file, char * line)   { file = file; line = line; }
+void noaction2(char * file, signed char * line)   { file = file; line = line; }
 
 /* Echo the line without further action */
 void printline(char * line)               { printf("%s", line); }
@@ -160,16 +166,21 @@
 	struct symfile *sym;
 	char line[MAXLINESZ];
 	if (filename_exist(filename) == NULL) {
+		char real_filename[PATH_MAX + 1];
+		memset(real_filename, 0, sizeof(real_filename));
+		strncat(real_filename, getenv("SRCTREE"), PATH_MAX);
+		strncat(real_filename, filename,
+				PATH_MAX - strlen(real_filename));
 		sym = add_new_file(filename);
-		fp = fopen(filename, "r");
+		fp = fopen(real_filename, "r");
 		if (fp == NULL)
 		{
 			fprintf(stderr, "docproc: ");
-			perror(filename);
+			perror(real_filename);
 		}
 		while(fgets(line, MAXLINESZ, fp)) {
-			char *p;
-			char *e;
+			signed char *p;
+			signed char *e;
 			if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
                             ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
 				/* Skip EXPORT_SYMBOL{_GPL} */
@@ -242,7 +253,7 @@
  * Call kernel-doc with the following parameters:
  * kernel-doc -docbook -function function1 [-function function2]
  */
-void singfunc(char * filename, char * line)
+void singfunc(char * filename, signed char * line)
 {
 	char *vec[200]; /* Enough for specific functions */
         int i, idx = 0;
@@ -279,7 +290,7 @@
 void parse_file(FILE *infile)
 {
 	char line[MAXLINESZ];
-	char * s;
+	signed char * s;
 	while(fgets(line, MAXLINESZ, infile)) {
 		if (line[0] == '!') {
 			s = line + 2;
diff -Nru a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
--- a/scripts/basic/fixdep.c	2004-10-28 22:25:58 -07:00
+++ b/scripts/basic/fixdep.c	2004-10-28 22:25:58 -07:00
@@ -217,12 +217,12 @@
 	printf("    $(wildcard include/config/%s.h) \\\n", s);
 }
 
-void parse_config_file(char *map, size_t len)
+void parse_config_file(signed 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;
+	signed char *p, *q;
 
 	for (; m < end; m++) {
 		if (*m == INT_CONF) { p = (char *) m  ; goto conf; }
@@ -291,9 +291,9 @@
 
 void parse_dep_file(void *map, size_t len)
 {
-	char *m = map;
-	char *end = m + len;
-	char *p;
+	signed char *m = map;
+	signed char *end = m + len;
+	signed char *p;
 	char s[PATH_MAX];
 
 	p = strchr(m, ':');
diff -Nru a/scripts/basic/split-include.c b/scripts/basic/split-include.c
--- a/scripts/basic/split-include.c	2004-10-28 22:25:57 -07:00
+++ b/scripts/basic/split-include.c	2004-10-28 22:25:57 -07:00
@@ -104,7 +104,7 @@
     /* Read config lines. */
     while (fgets(line, buffer_size, fp_config))
     {
-	const char * str_config;
+	const signed char * str_config;
 	int is_same;
 	int itarget;
 
diff -Nru a/scripts/checkstack.pl b/scripts/checkstack.pl
--- a/scripts/checkstack.pl	2004-10-28 22:25:57 -07:00
+++ b/scripts/checkstack.pl	2004-10-28 22:25:57 -07:00
@@ -39,6 +39,9 @@
 	} elsif ($arch =~ /^i[3456]86$/) {
 		#c0105234:       81 ec ac 05 00 00       sub    $0x5ac,%esp
 		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%esp$/o;
+	} elsif ($arch eq 'x86_64') {
+		#    2f60:	48 81 ec e8 05 00 00 	sub    $0x5e8,%rsp
+		$re = qr/^.*[as][du][db]    \$(0x$x{1,8}),\%rsp$/o;
 	} elsif ($arch eq 'ia64') {
 		#e0000000044011fc:       01 0f fc 8c     adds r12=-384,r12
 		$re = qr/.*adds.*r12=-(([0-9]{2}|[3-9])[0-9]{2}),r12/o;
diff -Nru a/scripts/conmakehash.c b/scripts/conmakehash.c
--- a/scripts/conmakehash.c	2004-10-28 22:25:56 -07:00
+++ b/scripts/conmakehash.c	2004-10-28 22:25:56 -07:00
@@ -33,7 +33,7 @@
 
 int getunicode(char **p0)
 {
-  char *p = *p0;
+  unsigned char *p = *p0;
 
   while (*p == ' ' || *p == '\t')
     p++;
diff -Nru a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
--- a/scripts/gen_initramfs_list.sh	2004-10-28 22:25:58 -07:00
+++ b/scripts/gen_initramfs_list.sh	2004-10-28 22:25:58 -07:00
@@ -2,25 +2,26 @@
 # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
 # Released under the terms of the GNU GPL
 #
-# A script to generate newline separated entries (to stdout) from a directory's
-# contents suitable for use as a cpio_list for gen_init_cpio.
+# Generate a newline separated list of entries from the file/directory pointed
+# out by the environment variable: CONFIG_INITRAMFS_SOURCE
 #
-# Arguements: $1 -- the source directory
+# If CONFIG_INITRAMFS_SOURCE is non-existing then generate a small dummy file.
+#
+# The output is suitable for gen_init_cpio as found in usr/Makefile.
 #
 # TODO:  Add support for symlinks, sockets and pipes when gen_init_cpio
 #        supports them.
 
-usage() {
-	echo "Usage: $0 initramfs-source-dir"
-	exit 1
+simple_initramfs() {
+	cat <<-EOF
+		# This is a very simple initramfs
+
+		dir /dev 0755 0 0
+		nod /dev/console 0600 0 0 c 5 1
+		dir /root 0700 0 0
+	EOF
 }
 
-srcdir=$(echo "$1" | sed -e 's://*:/:g')
-
-if [ "$#" -gt 1 -o ! -d "${srcdir}" ]; then
-	usage
-fi
-
 filetype() {
 	local argv1="$1"
 
@@ -76,9 +77,27 @@
 	return 0
 }
 
-find "${srcdir}" -printf "%p %m %U %G\n" | \
-while read x; do
-	parse ${x}
-done
+if [ -z $1 ]; then
+	simple_initramfs
+elif [ -f $1 ]; then
+	cat $1
+elif [ -d $1 ]; then
+	srcdir=$(echo "$1" | sed -e 's://*:/:g')
+	dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null)
+
+	# If $dirlist is only one line, then the directory is empty
+	if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
+		echo "${dirlist}" | \
+		while read x; do
+			parse ${x}
+		done
+	else
+		# Failsafe in case directory is empty
+		simple_initramfs
+	fi
+else
+	echo "  $0: Cannot open '$1' (CONFIG_INITRAMFS_SOURCE)" >&2
+	exit 1
+fi
 
 exit 0
diff -Nru a/scripts/kallsyms.c b/scripts/kallsyms.c
--- a/scripts/kallsyms.c	2004-10-28 22:25:59 -07:00
+++ b/scripts/kallsyms.c	2004-10-28 22:25:59 -07:00
@@ -97,6 +97,17 @@
 	exit(1);
 }
 
+/*
+ * This ignores the intensely annoying "mapping symbols" found
+ * in ARM ELF files: $a, $t and $d.
+ */
+static inline int
+is_arm_mapping_symbol(const char *str)
+{
+	return str[0] == '$' && strchr("atd", str[1])
+	       && (str[2] == '\0' || str[2] == '.');
+}
+
 static int
 read_symbol(FILE *in, struct sym_entry *s)
 {
@@ -121,7 +132,8 @@
 		_sinittext = s->addr;
 	else if (strcmp(str, "_einittext") == 0)
 		_einittext = s->addr;
-	else if (toupper(s->type) == 'A' || toupper(s->type) == 'U')
+	else if (toupper(s->type) == 'A' || toupper(s->type) == 'U' ||
+		 is_arm_mapping_symbol(str))
 		return -1;
 
 	/* include the type field in the symbol name, so that it gets
diff -Nru a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
--- a/scripts/kconfig/conf.c	2004-10-28 22:25:59 -07:00
+++ b/scripts/kconfig/conf.c	2004-10-28 22:25:59 -07:00
@@ -31,14 +31,14 @@
 static int indent = 1;
 static int valid_stdin = 1;
 static int conf_cnt;
-static char line[128];
+static signed char line[128];
 static struct menu *rootEntry;
 
 static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
 
-static void strip(char *str)
+static void strip(signed char *str)
 {
-	char *p = str;
+	signed char *p = str;
 	int l;
 
 	while ((isspace(*p)))
diff -Nru a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
--- a/scripts/kconfig/confdata.c	2004-10-28 22:25:59 -07:00
+++ b/scripts/kconfig/confdata.c	2004-10-28 22:25:59 -07:00
@@ -27,10 +27,10 @@
 	NULL,
 };
 
-static char *conf_expand_value(const char *in)
+static char *conf_expand_value(const signed char *in)
 {
 	struct symbol *sym;
-	const char *src;
+	const signed char *src;
 	static char res_value[SYMBOL_MAXLENGTH];
 	char *dst, name[SYMBOL_MAXLENGTH];
 
@@ -270,6 +270,8 @@
 	int type, l;
 	const char *str;
 	time_t now;
+	int use_timestamp = 1;
+	char *env;
 
 	dirname[0] = 0;
 	if (name && name[0]) {
@@ -293,7 +295,7 @@
 	} else
 		basename = conf_def_filename;
 
-	sprintf(newname, "%s.tmpconfig.%d", dirname, getpid());
+	sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
 	out = fopen(newname, "w");
 	if (!out)
 		return 1;
@@ -306,22 +308,28 @@
 	sym = sym_lookup("KERNELRELEASE", 0);
 	sym_calc_value(sym);
 	time(&now);
+	env = getenv("KCONFIG_NOTIMESTAMP");
+	if (env && *env)
+		use_timestamp = 0;
+
 	fprintf(out, "#\n"
 		     "# Automatically generated make config: don't edit\n"
 		     "# Linux kernel version: %s\n"
-		     "# %s"
+		     "%s%s"
 		     "#\n",
 		     sym_get_string_value(sym),
-		     ctime(&now));
+		     use_timestamp ? "# " : "",
+		     use_timestamp ? ctime(&now) : "");
 	if (out_h)
 		fprintf(out_h, "/*\n"
 			       " * Automatically generated C config: don't edit\n"
 			       " * Linux kernel version: %s\n"
-			       " * %s"
+			       "%s%s"
 			       " */\n"
 			       "#define AUTOCONF_INCLUDED\n",
 			       sym_get_string_value(sym),
-			       ctime(&now));
+			       use_timestamp ? " * " : "",
+			       use_timestamp ? ctime(&now) : "");
 
 	if (!sym_change_count)
 		sym_clear_all_valid();
diff -Nru a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
--- a/scripts/kconfig/mconf.c	2004-10-28 22:25:57 -07:00
+++ b/scripts/kconfig/mconf.c	2004-10-28 22:25:57 -07:00
@@ -82,8 +82,8 @@
 	"leave this blank.\n"
 ;
 
-static char buf[4096], *bufptr = buf;
-static char input_buf[4096];
+static signed char buf[4096], *bufptr = buf;
+static signed char input_buf[4096];
 static char filename[PATH_MAX+1] = ".config";
 static char *args[1024], **argptr = args;
 static int indent;
diff -Nru a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
--- a/scripts/kconfig/symbol.c	2004-10-28 22:25:57 -07:00
+++ b/scripts/kconfig/symbol.c	2004-10-28 22:25:57 -07:00
@@ -421,7 +421,7 @@
 
 bool sym_string_valid(struct symbol *sym, const char *str)
 {
-	char ch;
+	signed char ch;
 
 	switch (sym->type) {
 	case S_STRING:
diff -Nru a/scripts/kernel-doc b/scripts/kernel-doc
--- a/scripts/kernel-doc	2004-10-28 22:25:58 -07:00
+++ b/scripts/kernel-doc	2004-10-28 22:25:58 -07:00
@@ -1531,7 +1531,7 @@
 }
 
 sub process_file($) {
-    my ($file) = @_;
+    my ($file) = "$ENV{'SRCTREE'}@_";
     my $identifier;
     my $func;
     my $initial_section_counter = $section_counter;
diff -Nru a/scripts/mksysmap b/scripts/mksysmap
--- a/scripts/mksysmap	2004-10-28 22:25:59 -07:00
+++ b/scripts/mksysmap	2004-10-28 22:25:59 -07:00
@@ -40,5 +40,5 @@
 # so we just ignore them to let readprofile continue to work.
 # (At least sparc64 has __crc_ in the middle).
 
-$NM -n $1 | grep -v '\( [aUw] \)\|\(__crc_\)' > $2
+$NM -n $1 | grep -v '\( [aUw] \)\|\(__crc_\)\|\( \$[adt]\)' > $2
 
diff -Nru a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
--- a/scripts/mod/file2alias.c	2004-10-28 22:25:58 -07:00
+++ b/scripts/mod/file2alias.c	2004-10-28 22:25:58 -07:00
@@ -12,17 +12,22 @@
 
 #include "modpost.h"
 
-/* We use the ELF typedefs, since we can't rely on stdint.h being present. */
-
+/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
+ * use either stdint.h or inttypes.h for the rest. */
 #if KERNEL_ELFCLASS == ELFCLASS32
-typedef Elf32_Addr     kernel_ulong_t;
+typedef Elf32_Addr	kernel_ulong_t;
+#else
+typedef Elf64_Addr	kernel_ulong_t;
+#endif
+#ifdef __sun__
+#include <inttypes.h>
 #else
-typedef Elf64_Addr     kernel_ulong_t;
+#include <stdint.h>
 #endif
 
-typedef Elf32_Word     __u32;
-typedef Elf32_Half     __u16;
-typedef unsigned char  __u8;
+typedef uint32_t	__u32;
+typedef uint16_t	__u16;
+typedef unsigned char	__u8;
 
 /* Big exception to the "don't include kernel headers into userspace, which
  * even potentially has different endianness and word sizes, since 
diff -Nru a/scripts/mod/modpost.c b/scripts/mod/modpost.c
--- a/scripts/mod/modpost.c	2004-10-28 22:25:57 -07:00
+++ b/scripts/mod/modpost.c	2004-10-28 22:25:57 -07:00
@@ -104,6 +104,7 @@
 	struct module *module;
 	unsigned int crc;
 	int crc_valid;
+	unsigned int weak:1;
 	char name[0];
 };
 
@@ -126,12 +127,13 @@
  * the list of unresolved symbols per module */
 
 struct symbol *
-alloc_symbol(const char *name, struct symbol *next)
+alloc_symbol(const char *name, unsigned int weak, struct symbol *next)
 {
 	struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1));
 
 	memset(s, 0, sizeof(*s));
 	strcpy(s->name, name);
+	s->weak = weak;
 	s->next = next;
 	return s;
 }
@@ -145,7 +147,7 @@
 	struct symbol *new;
 
 	hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
-	new = symbolhash[hash] = alloc_symbol(name, symbolhash[hash]);
+	new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
 	new->module = module;
 	if (crc) {
 		new->crc = *crc;
@@ -217,7 +219,7 @@
 	static char line[4096];
 	int skip = 1;
 	size_t len = 0;
-	char *p = (char *)file + *pos;
+	signed char *p = (char *)file + *pos;
 	char *s = line;
 
 	for (; *pos < size ; (*pos)++)
@@ -349,7 +351,8 @@
 		break;
 	case SHN_UNDEF:
 		/* undefined symbol */
-		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
+		if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
+		    ELF_ST_BIND(sym->st_info) != STB_WEAK)
 			break;
 		/* ignore global offset table */
 		if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0)
@@ -370,6 +373,7 @@
 			   strlen(MODULE_SYMBOL_PREFIX)) == 0)
 			mod->unres = alloc_symbol(symname +
 						  strlen(MODULE_SYMBOL_PREFIX),
+						  ELF_ST_BIND(sym->st_info) == STB_WEAK,
 						  mod->unres);
 		break;
 	default:
@@ -476,7 +480,7 @@
 	 * the automatic versioning doesn't pick it up, but it's really
 	 * important anyhow */
 	if (modversions)
-		mod->unres = alloc_symbol("struct_module", mod->unres);
+		mod->unres = alloc_symbol("struct_module", 0, mod->unres);
 }
 
 #define SZ 500
@@ -548,7 +552,7 @@
 	for (s = mod->unres; s; s = s->next) {
 		exp = find_symbol(s->name);
 		if (!exp || exp->module == mod) {
-			if (have_vmlinux)
+			if (have_vmlinux && !s->weak)
 				fprintf(stderr, "*** Warning: \"%s\" [%s.ko] "
 				"undefined!\n",	s->name, mod->name);
 			continue;
diff -Nru a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
--- a/scripts/mod/sumversion.c	2004-10-28 22:25:58 -07:00
+++ b/scripts/mod/sumversion.c	2004-10-28 22:25:58 -07:00
@@ -252,9 +252,9 @@
 }
 
 /* FIXME: Handle .s files differently (eg. # starts comments) --RR */
-static int parse_file(const char *fname, struct md4_ctx *md)
+static int parse_file(const signed char *fname, struct md4_ctx *md)
 {
-	char *file;
+	signed char *file;
 	unsigned long i, len;
 
 	file = grab_file(fname, &len);
@@ -332,7 +332,7 @@
 	   Sum all files in the same dir or subdirs.
 	*/
 	while ((line = get_next_line(&pos, file, flen)) != NULL) {
-		char* p = line;
+		signed char* p = line;
 		if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
 			check_files = 1;
 			continue;
@@ -456,7 +456,7 @@
 	close(fd);
 }
 
-static int strip_rcs_crap(char *version)
+static int strip_rcs_crap(signed char *version)
 {
 	unsigned int len, full_len;
 
diff -Nru a/scripts/reference_init.pl b/scripts/reference_init.pl
--- a/scripts/reference_init.pl	2004-10-28 22:25:59 -07:00
+++ b/scripts/reference_init.pl	2004-10-28 22:25:59 -07:00
@@ -95,6 +95,7 @@
 		     $from !~ /\.text\.lock$/ &&
 		     $from !~ /\.pci_fixup_header$/ &&
 		     $from !~ /\.pci_fixup_final$/ &&
+		     $from !~ /\__param$/ &&
 		     $from !~ /\.debug_/)) {
 			printf("Error: %s %s refers to %s\n", $object, $from, $line);
 		}
diff -Nru a/security/commoncap.c b/security/commoncap.c
--- a/security/commoncap.c	2004-10-28 22:25:57 -07:00
+++ b/security/commoncap.c	2004-10-28 22:25:57 -07:00
@@ -24,6 +24,23 @@
 #include <linux/xattr.h>
 #include <linux/hugetlb.h>
 
+int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+	NETLINK_CB(skb).eff_cap = current->cap_effective;
+	return 0;
+}
+
+EXPORT_SYMBOL(cap_netlink_send);
+
+int cap_netlink_recv(struct sk_buff *skb)
+{
+	if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
+		return -EPERM;
+	return 0;
+}
+
+EXPORT_SYMBOL(cap_netlink_recv);
+
 int cap_capable (struct task_struct *tsk, int cap)
 {
 	/* Derived from include/linux/sched.h:capable. */
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	2004-10-28 22:25:57 -07:00
+++ b/security/dummy.c	2004-10-28 22:25:57 -07:00
@@ -518,8 +518,7 @@
 }
 
 static int dummy_file_send_sigiotask (struct task_struct *tsk,
-				      struct fown_struct *fown, int fd,
-				      int reason)
+				      struct fown_struct *fown, int sig)
 {
 	return 0;
 }
diff -Nru a/security/keys/Makefile b/security/keys/Makefile
--- a/security/keys/Makefile	2004-10-28 22:25:58 -07:00
+++ b/security/keys/Makefile	2004-10-28 22:25:58 -07:00
@@ -10,4 +10,5 @@
 	user_defined.o \
 	request_key.o
 
+obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
diff -Nru a/security/keys/compat.c b/security/keys/compat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/security/keys/compat.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,78 @@
+/* compat.c: 32-bit compatibility syscall for 64-bit systems
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/keyctl.h>
+#include <linux/compat.h>
+#include "internal.h"
+
+/*****************************************************************************/
+/*
+ * the key control system call, 32-bit compatibility version for 64-bit archs
+ * - this should only be called if the 64-bit arch uses weird pointers in
+ *   32-bit mode or doesn't guarantee that the top 32-bits of the argument
+ *   registers on taking a 32-bit syscall are zero
+ * - if you can, you should call sys_keyctl directly
+ */
+asmlinkage long compat_sys_keyctl(u32 option,
+			      u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+{
+	switch (option) {
+	case KEYCTL_GET_KEYRING_ID:
+		return keyctl_get_keyring_ID(arg2, arg3);
+
+	case KEYCTL_JOIN_SESSION_KEYRING:
+		return keyctl_join_session_keyring(compat_ptr(arg3));
+
+	case KEYCTL_UPDATE:
+		return keyctl_update_key(arg2, compat_ptr(arg3), arg4);
+
+	case KEYCTL_REVOKE:
+		return keyctl_revoke_key(arg2);
+
+	case KEYCTL_DESCRIBE:
+		return keyctl_describe_key(arg2, compat_ptr(arg3), arg4);
+
+	case KEYCTL_CLEAR:
+		return keyctl_keyring_clear(arg2);
+
+	case KEYCTL_LINK:
+		return keyctl_keyring_link(arg2, arg3);
+
+	case KEYCTL_UNLINK:
+		return keyctl_keyring_unlink(arg2, arg3);
+
+	case KEYCTL_SEARCH:
+		return keyctl_keyring_search(arg2, compat_ptr(arg3),
+					     compat_ptr(arg4), arg5);
+
+	case KEYCTL_READ:
+		return keyctl_read_key(arg2, compat_ptr(arg3), arg4);
+
+	case KEYCTL_CHOWN:
+		return keyctl_chown_key(arg2, arg3, arg4);
+
+	case KEYCTL_SETPERM:
+		return keyctl_setperm_key(arg2, arg3);
+
+	case KEYCTL_INSTANTIATE:
+		return keyctl_instantiate_key(arg2, compat_ptr(arg3), arg4,
+					      arg5);
+
+	case KEYCTL_NEGATE:
+		return keyctl_negate_key(arg2, arg3, arg4);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+} /* end compat_sys_keyctl() */
diff -Nru a/security/keys/internal.h b/security/keys/internal.h
--- a/security/keys/internal.h	2004-10-28 22:25:56 -07:00
+++ b/security/keys/internal.h	2004-10-28 22:25:56 -07:00
@@ -81,6 +81,26 @@
 
 extern int install_thread_keyring(struct task_struct *tsk);
 
+/*
+ * keyctl functions
+ */
+extern long keyctl_get_keyring_ID(key_serial_t, int);
+extern long keyctl_join_session_keyring(const char __user *);
+extern long keyctl_update_key(key_serial_t, const void __user *, size_t);
+extern long keyctl_revoke_key(key_serial_t);
+extern long keyctl_keyring_clear(key_serial_t);
+extern long keyctl_keyring_link(key_serial_t, key_serial_t);
+extern long keyctl_keyring_unlink(key_serial_t, key_serial_t);
+extern long keyctl_describe_key(key_serial_t, char __user *, size_t);
+extern long keyctl_keyring_search(key_serial_t, const char __user *,
+				  const char __user *, key_serial_t);
+extern long keyctl_read_key(key_serial_t, char __user *, size_t);
+extern long keyctl_chown_key(key_serial_t, uid_t, gid_t);
+extern long keyctl_setperm_key(key_serial_t, key_perm_t);
+extern long keyctl_instantiate_key(key_serial_t, const void __user *,
+				   size_t, key_serial_t);
+extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
+
 
 /*
  * debugging key validation
diff -Nru a/security/keys/key.c b/security/keys/key.c
--- a/security/keys/key.c	2004-10-28 22:25:59 -07:00
+++ b/security/keys/key.c	2004-10-28 22:25:59 -07:00
@@ -1036,4 +1036,4 @@
 
 } /* end key_init() */
 
-subsys_initcall(key_init);
+security_initcall(key_init);
diff -Nru a/security/keys/keyctl.c b/security/keys/keyctl.c
--- a/security/keys/keyctl.c	2004-10-28 22:25:57 -07:00
+++ b/security/keys/keyctl.c	2004-10-28 22:25:57 -07:00
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/syscalls.h>
 #include <linux/keyctl.h>
 #include <linux/fs.h>
 #include <linux/err.h>
@@ -231,7 +232,7 @@
  * - the keyring must have search permission to be found
  * - implements keyctl(KEYCTL_GET_KEYRING_ID)
  */
-static long keyctl_get_keyring_ID(key_serial_t id, int create)
+long keyctl_get_keyring_ID(key_serial_t id, int create)
 {
 	struct key *key;
 	long ret;
@@ -254,7 +255,7 @@
  * join the session keyring
  * - implements keyctl(KEYCTL_JOIN_SESSION_KEYRING)
  */
-static long keyctl_join_session_keyring(const char __user *_name)
+long keyctl_join_session_keyring(const char __user *_name)
 {
 	char *name;
 	long nlen, ret;
@@ -297,9 +298,9 @@
  * - the key must be writable
  * - implements keyctl(KEYCTL_UPDATE)
  */
-static long keyctl_update_key(key_serial_t id,
-			      const void __user *_payload,
-			      size_t plen)
+long keyctl_update_key(key_serial_t id,
+		       const void __user *_payload,
+		       size_t plen)
 {
 	struct key *key;
 	void *payload;
@@ -346,7 +347,7 @@
  * - the key must be writable
  * - implements keyctl(KEYCTL_REVOKE)
  */
-static long keyctl_revoke_key(key_serial_t id)
+long keyctl_revoke_key(key_serial_t id)
 {
 	struct key *key;
 	long ret;
@@ -372,7 +373,7 @@
  * - the keyring must be writable
  * - implements keyctl(KEYCTL_CLEAR)
  */
-static long keyctl_keyring_clear(key_serial_t ringid)
+long keyctl_keyring_clear(key_serial_t ringid)
 {
 	struct key *keyring;
 	long ret;
@@ -398,7 +399,7 @@
  * - the key must be linkable
  * - implements keyctl(KEYCTL_LINK)
  */
-static long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
+long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
 {
 	struct key *keyring, *key;
 	long ret;
@@ -432,7 +433,7 @@
  * - we don't need any permissions on the key
  * - implements keyctl(KEYCTL_UNLINK)
  */
-static long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
+long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
 {
 	struct key *keyring, *key;
 	long ret;
@@ -470,9 +471,9 @@
  *	type;uid;gid;perm;description<NUL>
  * - implements keyctl(KEYCTL_DESCRIBE)
  */
-static long keyctl_describe_key(key_serial_t keyid,
-				char __user *buffer,
-				size_t buflen)
+long keyctl_describe_key(key_serial_t keyid,
+			 char __user *buffer,
+			 size_t buflen)
 {
 	struct key *key;
 	char *tmpbuf;
@@ -532,10 +533,10 @@
  *   there's one specified
  * - implements keyctl(KEYCTL_SEARCH)
  */
-static long keyctl_keyring_search(key_serial_t ringid,
-				  const char __user *_type,
-				  const char __user *_description,
-				  key_serial_t destringid)
+long keyctl_keyring_search(key_serial_t ringid,
+			   const char __user *_type,
+			   const char __user *_description,
+			   key_serial_t destringid)
 {
 	struct key_type *ktype;
 	struct key *keyring, *key, *dest;
@@ -649,9 +650,7 @@
  *   irrespective of how much we may have copied
  * - implements keyctl(KEYCTL_READ)
  */
-static long keyctl_read_key(key_serial_t keyid,
-			    char __user *buffer,
-			    size_t buflen)
+long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
 {
 	struct key *key, *skey;
 	long ret;
@@ -711,7 +710,7 @@
  * - if the uid or gid is -1, then that parameter is not changed
  * - implements keyctl(KEYCTL_CHOWN)
  */
-static long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
+long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 {
 	struct key *key;
 	long ret;
@@ -770,7 +769,7 @@
  * - the keyring owned by the changer
  * - implements keyctl(KEYCTL_SETPERM)
  */
-static long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
+long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
 {
 	struct key *key;
 	long ret;
@@ -814,10 +813,10 @@
  * instantiate the key with the specified payload, and, if one is given, link
  * the key into the keyring
  */
-static long keyctl_instantiate_key(key_serial_t id,
-				   const void __user *_payload,
-				   size_t plen,
-				   key_serial_t ringid)
+long keyctl_instantiate_key(key_serial_t id,
+			    const void __user *_payload,
+			    size_t plen,
+			    key_serial_t ringid)
 {
 	struct key *key, *keyring;
 	void *payload;
@@ -877,9 +876,7 @@
  * negatively instantiate the key with the given timeout (in seconds), and, if
  * one is given, link the key into the keyring
  */
-static long keyctl_negate_key(key_serial_t id,
-			      unsigned timeout,
-			      key_serial_t ringid)
+long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 {
 	struct key *key, *keyring;
 	long ret;
@@ -916,7 +913,6 @@
 /*****************************************************************************/
 /*
  * the key control system call
- * - currently invoked through prctl()
  */
 asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
 			   unsigned long arg4, unsigned long arg5)
diff -Nru a/security/selinux/hooks.c b/security/selinux/hooks.c
--- a/security/selinux/hooks.c	2004-10-28 22:25:59 -07:00
+++ b/security/selinux/hooks.c	2004-10-28 22:25:59 -07:00
@@ -2237,6 +2237,9 @@
 	if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
 		return -EOPNOTSUPP;
 
+	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		return -EPERM;
+
 	AVC_AUDIT_DATA_INIT(&ad,FS);
 	ad.u.fs.dentry = dentry;
 
@@ -2562,8 +2565,7 @@
 }
 
 static int selinux_file_send_sigiotask(struct task_struct *tsk,
-				       struct fown_struct *fown,
-				       int fd, int reason)
+				       struct fown_struct *fown, int signum)
 {
         struct file *file;
 	u32 perm;
@@ -2576,10 +2578,10 @@
 	tsec = tsk->security;
 	fsec = file->f_security;
 
-	if (!fown->signum)
+	if (!signum)
 		perm = signal_to_av(SIGIO); /* as per send_sigio_to_task */
 	else
-		perm = signal_to_av(fown->signum);
+		perm = signal_to_av(signum);
 
 	return avc_has_perm(fsec->fown_sid, tsec->sid,
 			    SECCLASS_PROCESS, perm, NULL, NULL);
@@ -3241,13 +3243,11 @@
 	u16 family;
 	char *addrp;
 	int len, err = 0;
-	u32 netif_perm, node_perm, node_sid, recv_perm = 0;
+	u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
 	u32 sock_sid = 0;
 	u16 sock_class = 0;
 	struct socket *sock;
 	struct net_device *dev;
-	struct sel_netif *netif;
-	struct netif_security_struct *nsec;
 	struct avc_audit_data ad;
 
 	family = sk->sk_family;
@@ -3278,13 +3278,9 @@
 	if (!dev)
 		goto out;
 
-	netif = sel_netif_lookup(dev);
-	if (IS_ERR(netif)) {
-		err = PTR_ERR(netif);
+	err = sel_netif_sids(dev, &if_sid, NULL);
+	if (err)
 		goto out;
-	}
-	
-	nsec = &netif->nsec;
 
 	switch (sock_class) {
 	case SECCLASS_UDP_SOCKET:
@@ -3310,14 +3306,11 @@
 	ad.u.net.family = family;
 
 	err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
-	if (err) {
-		sel_netif_put(netif);
+	if (err)
 		goto out;
-	}
 
-	err = avc_has_perm(sock_sid, nsec->if_sid, SECCLASS_NETIF,
-	                   netif_perm, &nsec->avcr, &ad);
-	sel_netif_put(netif);
+	err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF,
+	                   netif_perm, NULL, &ad);
 	if (err)
 		goto out;
 	
@@ -3433,13 +3426,11 @@
 {
 	char *addrp;
 	int len, err = NF_ACCEPT;
-	u32 netif_perm, node_perm, node_sid, send_perm = 0;
+	u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
 	struct sock *sk;
 	struct socket *sock;
 	struct inode *inode;
-	struct sel_netif *netif;
 	struct sk_buff *skb = *pskb;
-	struct netif_security_struct *nsec;
 	struct inode_security_struct *isec;
 	struct avc_audit_data ad;
 	struct net_device *dev = (struct net_device *)out;
@@ -3456,13 +3447,10 @@
 	if (!inode)
 		goto out;
 
-	netif = sel_netif_lookup(dev);
-	if (IS_ERR(netif)) {
-		err = NF_DROP;
+	err = sel_netif_sids(dev, &if_sid, NULL);
+	if (err)
 		goto out;
-	}
-	
-	nsec = &netif->nsec;
+
 	isec = inode->i_security;
 	
 	switch (isec->sclass) {
@@ -3491,14 +3479,11 @@
 
 	err = selinux_parse_skb(skb, &ad, &addrp,
 				&len, 0) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT) {
-		sel_netif_put(netif);
+	if (err != NF_ACCEPT)
 		goto out;
-	}
 
-	err = avc_has_perm(isec->sid, nsec->if_sid, SECCLASS_NETIF,
-	                   netif_perm, &nsec->avcr, &ad) ? NF_DROP : NF_ACCEPT;
-	sel_netif_put(netif);
+	err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
+	                   netif_perm, NULL, &ad) ? NF_DROP : NF_ACCEPT;
 	if (err != NF_ACCEPT)
 		goto out;
 		
diff -Nru a/security/selinux/include/netif.h b/security/selinux/include/netif.h
--- a/security/selinux/include/netif.h	2004-10-28 22:25:58 -07:00
+++ b/security/selinux/include/netif.h	2004-10-28 22:25:58 -07:00
@@ -15,16 +15,7 @@
 #ifndef _SELINUX_NETIF_H_
 #define _SELINUX_NETIF_H_
 
-struct sel_netif
-{
-	struct list_head list;
-	atomic_t users;
-	struct netif_security_struct nsec;
-	struct rcu_head rcu_head;
-};
-
-struct sel_netif *sel_netif_lookup(struct net_device *dev);
-void sel_netif_put(struct sel_netif *netif);
+int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid);
 
 #endif	/* _SELINUX_NETIF_H_ */
 
diff -Nru a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
--- a/security/selinux/include/objsec.h	2004-10-28 22:25:57 -07:00
+++ b/security/selinux/include/objsec.h	2004-10-28 22:25:57 -07:00
@@ -99,7 +99,6 @@
 	struct net_device *dev;		/* back pointer */
 	u32 if_sid;			/* SID for this interface */
 	u32 msg_sid;			/* default SID for messages received on this interface */
-	struct avc_entry_ref avcr;	/* reference to permissions */
 };
 
 struct sk_security_struct {
diff -Nru a/security/selinux/netif.c b/security/selinux/netif.c
--- a/security/selinux/netif.c	2004-10-28 22:25:58 -07:00
+++ b/security/selinux/netif.c	2004-10-28 22:25:58 -07:00
@@ -36,10 +36,17 @@
 #define DEBUGP(format, args...)
 #endif
 
+struct sel_netif
+{
+	struct list_head list;
+	struct netif_security_struct nsec;
+	struct rcu_head rcu_head;
+};
+
 static u32 sel_netif_total;
 static LIST_HEAD(sel_netif_list);
 static spinlock_t sel_netif_lock = SPIN_LOCK_UNLOCKED;
-static struct sel_netif sel_netif_hash[SEL_NETIF_HASH_SIZE];
+static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE];
 
 static inline u32 sel_netif_hasfn(struct net_device *dev)
 {
@@ -50,12 +57,12 @@
  * All of the devices should normally fit in the hash, so we optimize
  * for that case.
  */
-static struct sel_netif *sel_netif_find(struct net_device *dev)
+static inline struct sel_netif *sel_netif_find(struct net_device *dev)
 {
 	struct list_head *pos;
 	int idx = sel_netif_hasfn(dev);
 
-	__list_for_each_rcu(pos, &sel_netif_hash[idx].list) {
+	__list_for_each_rcu(pos, &sel_netif_hash[idx]) {
 		struct sel_netif *netif = list_entry(pos,
 		                                     struct sel_netif, list);
 		if (likely(netif->nsec.dev == dev))
@@ -74,25 +81,38 @@
 	}
 	
 	idx = sel_netif_hasfn(netif->nsec.dev);
-	list_add_rcu(&netif->list, &sel_netif_hash[idx].list);
-	atomic_set(&netif->users, 1);
+	list_add_rcu(&netif->list, &sel_netif_hash[idx]);
 	sel_netif_total++;
 out:
 	return ret;
 }
 
-struct sel_netif *sel_netif_lookup(struct net_device *dev)
+static void sel_netif_free(struct rcu_head *p)
+{
+	struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head);
+
+	DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
+	kfree(netif);
+}
+
+static void sel_netif_destroy(struct sel_netif *netif)
+{
+	DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
+
+	list_del_rcu(&netif->list);
+	sel_netif_total--;
+	call_rcu(&netif->rcu_head, sel_netif_free);
+}
+
+static struct sel_netif *sel_netif_lookup(struct net_device *dev)
 {
 	int ret;
 	struct sel_netif *netif, *new;
 	struct netif_security_struct *nsec;
 
-	rcu_read_lock();
 	netif = sel_netif_find(dev);
-	rcu_read_unlock();
-	
 	if (likely(netif != NULL))
-		goto out_hold;
+		goto out;
 	
 	new = kmalloc(sizeof(*new), GFP_ATOMIC);
 	if (!new) {
@@ -118,76 +138,86 @@
 	if (netif) {
 		spin_unlock_bh(&sel_netif_lock);
 		kfree(new);
-		goto out_hold;
+		goto out;
 	}
 	
-	sel_netif_insert(new);
+	ret = sel_netif_insert(new);
 	spin_unlock_bh(&sel_netif_lock);
 	
+	if (ret) {
+		kfree(new);
+		netif = ERR_PTR(ret);
+		goto out;
+	}
+
 	netif = new;
 	
 	DEBUGP("new: ifindex=%u name=%s if_sid=%u msg_sid=%u\n", dev->ifindex, dev->name,
 	        nsec->if_sid, nsec->msg_sid);
-out_hold:
-	atomic_inc(&netif->users);
 out:
 	return netif;
 }
 
-static void sel_netif_free(struct rcu_head *p)
+static void sel_netif_assign_sids(u32 if_sid_in, u32 msg_sid_in, u32 *if_sid_out, u32 *msg_sid_out)
 {
-	struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head);
-	
-	DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
-	kfree(netif);
+	if (if_sid_out)
+		*if_sid_out = if_sid_in;
+	if (msg_sid_out)
+		*msg_sid_out = msg_sid_in;
 }
 
-static void sel_netif_destroy(struct sel_netif *netif)
+static int sel_netif_sids_slow(struct net_device *dev, u32 *if_sid, u32 *msg_sid)
 {
-	DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
+	int ret = 0;
+	u32 tmp_if_sid, tmp_msg_sid;
 	
-	spin_lock_bh(&sel_netif_lock);
-	list_del_rcu(&netif->list);
-	sel_netif_total--;
-	spin_unlock_bh(&sel_netif_lock);
-
-	call_rcu(&netif->rcu_head, sel_netif_free);
+	ret = security_netif_sid(dev->name, &tmp_if_sid, &tmp_msg_sid);
+	if (!ret)
+		sel_netif_assign_sids(tmp_if_sid, tmp_msg_sid, if_sid, msg_sid);
+	return ret;
 }
 
-void sel_netif_put(struct sel_netif *netif)
+int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid)
 {
-	if (atomic_dec_and_test(&netif->users))
-		sel_netif_destroy(netif);
+	int ret = 0;
+	struct sel_netif *netif;
+
+	rcu_read_lock();
+	netif = sel_netif_lookup(dev);
+	if (IS_ERR(netif)) {
+		rcu_read_unlock();
+		ret = sel_netif_sids_slow(dev, if_sid, msg_sid);
+		goto out;
+	}
+	sel_netif_assign_sids(netif->nsec.if_sid, netif->nsec.msg_sid, if_sid, msg_sid);
+	rcu_read_unlock();
+out:
+	return ret;
 }
 
 static void sel_netif_kill(struct net_device *dev)
 {
 	struct sel_netif *netif;
-	
-	rcu_read_lock();
-	netif = sel_netif_find(dev);
-	rcu_read_unlock();
 
-	/* Drop internal reference */
+	spin_lock_bh(&sel_netif_lock);
+	netif = sel_netif_find(dev);
 	if (netif)
-		sel_netif_put(netif);
+		sel_netif_destroy(netif);
+	spin_unlock_bh(&sel_netif_lock);
 }
 
 static void sel_netif_flush(void)
 {
 	int idx;
 
+	spin_lock_bh(&sel_netif_lock);
 	for (idx = 0; idx < SEL_NETIF_HASH_SIZE; idx++) {
-		struct list_head *pos;
+		struct sel_netif *netif;
 		
-		list_for_each_rcu(pos, &sel_netif_hash[idx].list) {
-			struct sel_netif *netif;
-			
-			netif = list_entry(pos, struct sel_netif, list);
-			if (netif)
-				sel_netif_put(netif);
-		}
+		list_for_each_entry(netif, &sel_netif_hash[idx], list)
+			sel_netif_destroy(netif);
 	}
+	spin_unlock_bh(&sel_netif_lock);
 }
 
 static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid,
@@ -223,7 +253,7 @@
 		goto out;
 
 	for (i = 0; i < SEL_NETIF_HASH_SIZE; i++)
-		INIT_LIST_HEAD(&sel_netif_hash[i].list);
+		INIT_LIST_HEAD(&sel_netif_hash[i]);
 
 	register_netdevice_notifier(&sel_netif_netdev_notifier);
 	
diff -Nru a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
--- a/security/selinux/selinuxfs.c	2004-10-28 22:25:59 -07:00
+++ b/security/selinux/selinuxfs.c	2004-10-28 22:25:59 -07:00
@@ -818,7 +818,6 @@
 	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;
@@ -838,10 +837,7 @@
 		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);
+		dentry = d_alloc_name(dir, names[i]);
 		if (!dentry) {
 			ret = -ENOMEM;
 			goto err;
@@ -896,7 +892,6 @@
 	int ret;
 	struct dentry *dentry;
 	struct inode *inode;
-	struct qstr qname;
 	struct inode_security_struct *isec;
 
 	static struct tree_descr selinux_files[] = {
@@ -917,10 +912,7 @@
 	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);
+	dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME);
 	if (!dentry)
 		return -ENOMEM;
 
@@ -935,10 +927,7 @@
 	if (ret)
 		goto out;
 
-	qname.name = NULL_FILE_NAME;
-	qname.len = strlen(qname.name);
-	qname.hash = full_name_hash(qname.name, qname.len);
-	dentry = d_alloc(sb->s_root, &qname);
+	dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
 	if (!dentry)
 		return -ENOMEM;
 
diff -Nru a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
--- a/security/selinux/ss/sidtab.c	2004-10-28 22:25:58 -07:00
+++ b/security/selinux/ss/sidtab.c	2004-10-28 22:25:58 -07:00
@@ -16,8 +16,8 @@
 (sid & SIDTAB_HASH_MASK)
 
 #define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)
-#define SIDTAB_LOCK(s) spin_lock_irq(&s->lock)
-#define SIDTAB_UNLOCK(s) spin_unlock_irq(&s->lock)
+#define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)
+#define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)
 
 int sidtab_init(struct sidtab *s)
 {
@@ -237,12 +237,13 @@
 {
 	u32 sid;
 	int ret = 0;
+	unsigned long flags;
 
 	*out_sid = SECSID_NULL;
 
 	sid = sidtab_search_context(s, context);
 	if (!sid) {
-		SIDTAB_LOCK(s);
+		SIDTAB_LOCK(s, flags);
 		/* Rescan now that we hold the lock. */
 		sid = sidtab_search_context(s, context);
 		if (sid)
@@ -257,7 +258,7 @@
 		if (ret)
 			s->next_sid--;
 unlock_out:
-		SIDTAB_UNLOCK(s);
+		SIDTAB_UNLOCK(s, flags);
 	}
 
 	if (ret)
@@ -320,17 +321,21 @@
 
 void sidtab_set(struct sidtab *dst, struct sidtab *src)
 {
-	SIDTAB_LOCK(src);
+	unsigned long flags;
+
+	SIDTAB_LOCK(src, flags);
 	dst->htable = src->htable;
 	dst->nel = src->nel;
 	dst->next_sid = src->next_sid;
 	dst->shutdown = 0;
-	SIDTAB_UNLOCK(src);
+	SIDTAB_UNLOCK(src, flags);
 }
 
 void sidtab_shutdown(struct sidtab *s)
 {
-	SIDTAB_LOCK(s);
+	unsigned long flags;
+
+	SIDTAB_LOCK(s, flags);
 	s->shutdown = 1;
-	SIDTAB_UNLOCK(s);
+	SIDTAB_UNLOCK(s, flags);
 }
diff -Nru a/sound/arm/Kconfig b/sound/arm/Kconfig
--- a/sound/arm/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/sound/arm/Kconfig	2004-10-28 22:25:59 -07:00
@@ -4,12 +4,15 @@
 	depends on SND!=n && ARM
 
 config SND_SA11XX_UDA1341
-	tristate "SA11xx UDA1341TS driver (H3600)"
+	tristate "SA11xx UDA1341TS driver (iPaq H3600)"
 	depends on ARCH_SA1100 && SND && L3
 	select SND_PCM
 	help
-	  Say Y or M if you have a Compaq iPaq H3x00 handheld computer and want
-	  to use its Philips UDA 1341 audio chip.
+	  Say Y here if you have a Compaq iPaq H3x00 handheld computer
+	  and want to use its Philips UDA 1341 audio chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sa11xx-uda1341.
 
 endmenu
 
diff -Nru a/sound/core/Kconfig b/sound/core/Kconfig
--- a/sound/core/Kconfig	2004-10-28 22:25:58 -07:00
+++ b/sound/core/Kconfig	2004-10-28 22:25:58 -07:00
@@ -17,17 +17,26 @@
 	depends on SND
 	select SND_TIMER
 	help
-	  Say 'Y' or 'M' to enable MIDI sequencer and router support. This feature
-	  allows routing and enqueing MIDI events. Events can be processed at given
-	  time.
+	  Say Y or M to enable MIDI sequencer and router support.  This
+	  feature allows routing and enqueueing of MIDI events.  Events
+	  can be processed at a given time.
+
+	  Many programs require this feature, so you should enable it
+	  unless you know what you're doing.
 
 config SND_SEQ_DUMMY
 	tristate "Sequencer dummy client"
 	depends on SND_SEQUENCER
 	help
-	  Say 'Y' or 'M' to enable dummy sequencer client. This client is a simple
-	  midi-through client. All normal input events are redirected to output port
-	  immediately.
+	  Say Y here to enable the dummy sequencer client.  This client
+	  is a simple MIDI-through client: all normal input events are
+	  redirected to the output port immediately.
+
+	  You don't need this unless you want to connect many MIDI
+	  devices or applications together.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-seq-dummy.
 
 config SND_OSSEMUL
 	bool
@@ -37,7 +46,13 @@
 	depends on SND
 	select SND_OSSEMUL
 	help
-	  Say 'Y' or 'M' to enable mixer OSS API emulation (/dev/mixer*).
+	  To enable OSS mixer API emulation (/dev/mixer*), say Y here
+	  and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
+
+	  Many programs still use the OSS API, so say Y.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-mixer-oss.
 
 config SND_PCM_OSS
 	tristate "OSS PCM (digital audio) API"
@@ -45,15 +60,26 @@
 	select SND_OSSEMUL
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to enable digital audio (PCM) OSS API emulation (/dev/dsp*).
+	  To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y
+	  here and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
+
+	  Many programs still use the OSS API, so say Y.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-pcm-oss.
 
 config SND_SEQUENCER_OSS
 	bool "OSS Sequencer API"
 	depends on SND_SEQUENCER
 	select SND_OSSEMUL
 	help
-	  Say 'Y' to enable OSS sequencer emulation (both /dev/sequencer and
-	  /dev/music interfaces).
+	  Say Y here to enable OSS sequencer emulation (both
+	  /dev/sequencer and /dev/music interfaces).
+
+	  Many programs still use the OSS API, so say Y.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-seq-oss.
 
 config SND_BIT32_EMUL
 	tristate "Emulation for 32-bit applications"
@@ -63,38 +89,51 @@
 	select SND_TIMER
 	select SND_HWDEP
 	help
-	  Say 'Y' or 'M' to enable the emulation for 32-bit ALSA-native
+	  Say Y here to enable the emulation for 32-bit ALSA-native
 	  applications.
 
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ioctl32.
+
 config SND_RTCTIMER
 	tristate "RTC Timer support"
 	depends on SND && RTC
 	select SND_TIMER
 	help
-	  Say 'Y' or 'M' to enable RTC timer support for ALSA. ALSA code uses RTC
-	  timer as precise timing source and maps the RTC timer to the ALSA's timer
-	  interface. ALSA sequencer code can also use this timing source.
+	  Say Y here to enable RTC timer support for ALSA.  ALSA uses
+	  the RTC timer as a precise timing source and maps the RTC
+	  timer to ALSA's timer interface.  The ALSA sequencer code also
+	  can use this timing source.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-rtctimer.
 
 config SND_VERBOSE_PRINTK
 	bool "Verbose printk"
 	depends on SND
 	help
-	  Say 'Y' to enable verbose log messages. These messages will help to
-	  identify source file and position containing printed messages.
+	  Say Y here to enable verbose log messages.  These messages
+	  will help to identify source file and position containing
+	  printed messages.
+
+	  You don't need this unless you're debugging ALSA.
 
 config SND_DEBUG
 	bool "Debug"
 	depends on SND
 	help
-	  Say 'Y' to enable ALSA debug code.
+	  Say Y here to enable ALSA debug code.
 
 config SND_DEBUG_MEMORY
 	bool "Debug memory"
 	depends on SND_DEBUG
 	help
-	  Say 'Y' to enable debugging of memory allocation.
+	  Say Y here to enable debugging of memory allocations.
 
 config SND_DEBUG_DETECT
 	bool "Debug detection"
 	depends on SND_DEBUG
+	help
+	  Say Y here to enable extra-verbose log messages printed when
+	  detecting devices.
 
diff -Nru a/sound/core/ioctl32/hwdep32.c b/sound/core/ioctl32/hwdep32.c
--- a/sound/core/ioctl32/hwdep32.c	2004-10-28 22:25:59 -07:00
+++ b/sound/core/ioctl32/hwdep32.c	2004-10-28 22:25:59 -07:00
@@ -34,7 +34,7 @@
 	u32 driver_data;
 } /* don't set packed attribute here */;
 
-static int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
 {
 	struct sndrv_hwdep_dsp_image data;
 	struct sndrv_hwdep_dsp_image32 data32;
diff -Nru a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c
--- a/sound/core/ioctl32/ioctl32.c	2004-10-28 22:25:57 -07:00
+++ b/sound/core/ioctl32/ioctl32.c	2004-10-28 22:25:57 -07:00
@@ -102,7 +102,7 @@
 	CPTR(pids);\
 }
 
-static int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
 {
 	struct sndrv_ctl_elem_list32 data32;
 	struct sndrv_ctl_elem_list data;
@@ -168,7 +168,7 @@
 	unsigned char reserved[64];
 } __attribute__((packed));
 
-static int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
 {
 	struct sndrv_ctl_elem_info data;
 	struct sndrv_ctl_elem_info32 data32;
@@ -246,7 +246,7 @@
 		struct sndrv_aes_iec958 iec958;
         } value;
         unsigned char reserved[128];
-} __attribute__((packed));
+};
 
 
 /* hmm, it's so hard to retrieve the value type from the control id.. */
@@ -274,7 +274,7 @@
 }
 
 
-static int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
 {
 	struct sndrv_ctl_elem_value *data;
 	struct sndrv_ctl_elem_value32 *data32;
diff -Nru a/sound/core/ioctl32/ioctl32.h b/sound/core/ioctl32/ioctl32.h
--- a/sound/core/ioctl32/ioctl32.h	2004-10-28 22:25:57 -07:00
+++ b/sound/core/ioctl32/ioctl32.h	2004-10-28 22:25:57 -07:00
@@ -18,7 +18,7 @@
  *
  *
  * This file registers the converters from 32-bit ioctls to 64-bit ones.
- * The converter assumes that a 32-bit user-pointer can be casted by A(x)
+ * The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x)
  * macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
  *
  */
@@ -47,7 +47,7 @@
 
 
 #define DEFINE_ALSA_IOCTL(type) \
-static int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
+static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
 {\
 	struct sndrv_##type##32 data32;\
 	struct sndrv_##type data;\
@@ -72,7 +72,7 @@
 }
 
 #define DEFINE_ALSA_IOCTL_BIG(type) \
-static int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
+static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
 {\
 	struct sndrv_##type##32 *data32;\
 	struct sndrv_##type *data;\
diff -Nru a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c
--- a/sound/core/ioctl32/pcm32.c	2004-10-28 22:25:58 -07:00
+++ b/sound/core/ioctl32/pcm32.c	2004-10-28 22:25:58 -07:00
@@ -169,11 +169,69 @@
 
 DEFINE_ALSA_IOCTL(pcm_uframes_str);
 DEFINE_ALSA_IOCTL(pcm_sframes_str);
-DEFINE_ALSA_IOCTL_BIG(pcm_hw_params);
 DEFINE_ALSA_IOCTL(pcm_sw_params);
 DEFINE_ALSA_IOCTL(pcm_channel_info);
 DEFINE_ALSA_IOCTL(pcm_status);
 
+/* recalcuate the boundary within 32bit */
+static void recalculate_boundary(struct file *file)
+{
+	snd_pcm_file_t *pcm_file;
+	snd_pcm_substream_t *substream;
+	snd_pcm_runtime_t *runtime;
+
+	/* FIXME: need to check whether fop->ioctl is sane */
+	if (! (pcm_file = file->private_data))
+		return;
+	if (! (substream = pcm_file->substream))
+		return;
+	if (! (runtime = substream->runtime))
+		return;
+	runtime->boundary = runtime->buffer_size;
+	while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+		runtime->boundary *= 2;
+}
+
+static inline int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+{
+	struct sndrv_pcm_hw_params32 *data32;
+	struct sndrv_pcm_hw_params *data;
+	mm_segment_t oldseg;
+	int err;
+
+	data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (data32 == NULL || data == NULL) {
+		err = -ENOMEM;
+		goto __end;
+	}
+	if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
+		err = -EFAULT;
+		goto __end;
+	}
+	memset(data, 0, sizeof(*data));
+	convert_from_32(pcm_hw_params, data, data32);
+	oldseg = get_fs();
+	set_fs(KERNEL_DS);
+	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+	set_fs(oldseg);
+	if (err < 0)
+		goto __end;
+	err = 0;
+	convert_to_32(pcm_hw_params, data32, data);
+	if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+		err = -EFAULT;
+	else
+		recalculate_boundary(file);
+      __end:
+      	if (data)
+      		kfree(data);
+      	if (data32)
+      		kfree(data32);
+	return err;
+}
+
+
 /*
  */
 struct sndrv_xferi32 {
@@ -182,7 +240,7 @@
 	u32 frames;
 } __attribute__((packed));
 
-static int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static inline int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
 {
 	struct sndrv_xferi32 data32;
 	struct sndrv_xferi data;
@@ -222,7 +280,7 @@
  * handler there expands again the same 128 pointers on stack, so it is better
  * to handle the function (calling pcm_readv/writev) directly in this handler.
  */
-static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static inline int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
 {
 	snd_pcm_file_t *pcm_file;
 	snd_pcm_substream_t *substream;
@@ -343,7 +401,7 @@
 	oparams->fifo_size = params->fifo_size;
 }
 
-static int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static inline int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
 {
 	struct sndrv_pcm_hw_params_old32 *data32;
 	struct sndrv_pcm_hw_params *data;
@@ -371,6 +429,8 @@
 	err = 0;
 	if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
 		err = -EFAULT;
+	else
+		recalculate_boundary(file);
       __end:
       	if (data)
       		kfree(data);
@@ -439,6 +499,30 @@
 
 
 /*
+ * When PCM is used on 32bit mode, we need to disable
+ * mmap of PCM status/control records because of the size
+ * incompatibility.
+ * 
+ * Since INFO ioctl is always called at first, we mark the
+ * mmap-disabling in this ioctl wrapper.
+ */
+static int snd_pcm_info_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
+{
+	snd_pcm_file_t *pcm_file;
+	snd_pcm_substream_t *substream;
+	if (! filp->f_op || ! filp->f_op->ioctl)
+		return -ENOTTY;
+	pcm_file = filp->private_data;
+	if (! pcm_file)
+		return -ENOTTY;
+	substream = pcm_file->substream;
+	if (! substream)
+		return -ENOTTY;
+	substream->no_mmap_ctrl = 1;
+	return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+}
+
+/*
  */
 #define AP(x) snd_ioctl32_##x
 
@@ -456,13 +540,14 @@
 	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
 	SNDRV_PCM_IOCTL_HW_REFINE_OLD32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old32),
 	SNDRV_PCM_IOCTL_HW_PARAMS_OLD32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old32),
-	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr),
+	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32),
 
 };
 
 struct ioctl32_mapper pcm_mappers[] = {
 	MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_INFO),
+	/* MAP_COMPAT(SNDRV_PCM_IOCTL_INFO), */
+	{ SNDRV_PCM_IOCTL_INFO, snd_pcm_info_ioctl32 },
 	MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
 	{ SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
 	{ SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
diff -Nru a/sound/core/memalloc.c b/sound/core/memalloc.c
--- a/sound/core/memalloc.c	2004-10-28 22:25:59 -07:00
+++ b/sound/core/memalloc.c	2004-10-28 22:25:59 -07:00
@@ -245,9 +245,9 @@
 	snd_assert(size > 0, return NULL);
 	snd_assert(dma != NULL, return NULL);
 	pg = get_order(size);
-	gfp_flags = GFP_KERNEL;
-	if (pg > 0)
-		gfp_flags |= __GFP_NOWARN;
+	gfp_flags = GFP_KERNEL
+		| __GFP_NORETRY /* don't trigger OOM-killer */
+		| __GFP_NOWARN; /* no stack trace print - this call is non-critical */
 	res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
 	if (res != NULL) {
 #ifdef NEED_RESERVE_PAGES
diff -Nru a/sound/core/memory.c b/sound/core/memory.c
--- a/sound/core/memory.c	2004-10-28 22:25:56 -07:00
+++ b/sound/core/memory.c	2004-10-28 22:25:56 -07:00
@@ -257,7 +257,7 @@
  *
  * Returns zero if successful, or non-zero on failure.
  */
-int copy_to_user_fromio(void __user *dst, unsigned long src, size_t count)
+int copy_to_user_fromio(void __user *dst, const void __iomem *src, size_t count)
 {
 #if defined(__i386__) || defined(CONFIG_SPARC32)
 	return copy_to_user(dst, (const void*)src, count) ? -EFAULT : 0;
@@ -267,7 +267,7 @@
 		size_t c = count;
 		if (c > sizeof(buf))
 			c = sizeof(buf);
-		memcpy_fromio(buf, (void*)src, c);
+		memcpy_fromio(buf, src, c);
 		if (copy_to_user(dst, buf, c))
 			return -EFAULT;
 		count -= c;
@@ -288,7 +288,7 @@
  *
  * Returns zero if successful, or non-zero on failure.
  */
-int copy_from_user_toio(unsigned long dst, const void __user *src, size_t count)
+int copy_from_user_toio(void __iomem *dst, const void __user *src, size_t count)
 {
 #if defined(__i386__) || defined(CONFIG_SPARC32)
 	return copy_from_user((void*)dst, src, count) ? -EFAULT : 0;
@@ -300,7 +300,7 @@
 			c = sizeof(buf);
 		if (copy_from_user(buf, src, c))
 			return -EFAULT;
-		memcpy_toio((void*)dst, buf, c);
+		memcpy_toio(dst, buf, c);
 		count -= c;
 		dst += c;
 		src += c;
diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
--- a/sound/core/oss/pcm_oss.c	2004-10-28 22:25:59 -07:00
+++ b/sound/core/oss/pcm_oss.c	2004-10-28 22:25:59 -07:00
@@ -829,13 +829,18 @@
 			xfer += tmp;
 			if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) ||
 			    runtime->oss.buffer_used == runtime->oss.period_bytes) {
-				tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.buffer_used, 1);
+				tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, 
+							 runtime->oss.buffer_used - runtime->oss.period_ptr, 1);
 				if (tmp <= 0)
 					return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
 				runtime->oss.bytes += tmp;
-				runtime->oss.buffer_used = 0;
 				runtime->oss.period_ptr += tmp;
 				runtime->oss.period_ptr %= runtime->oss.period_bytes;
+				if (runtime->oss.period_ptr == 0 ||
+				    runtime->oss.period_ptr == runtime->oss.buffer_used)
+					runtime->oss.buffer_used = 0;
+				else if ((substream->ffile->f_flags & O_NONBLOCK) != 0)
+					return xfer > 0 ? xfer : -EAGAIN;
 			}
 		} else {
 			tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0);
@@ -845,6 +850,9 @@
 			buf += tmp;
 			bytes -= tmp;
 			xfer += tmp;
+			if ((substream->ffile->f_flags & O_NONBLOCK) != 0 &&
+			    tmp != runtime->oss.period_bytes)
+				break;
 		}
 	}
 	return xfer;
diff -Nru a/sound/core/pcm.c b/sound/core/pcm.c
--- a/sound/core/pcm.c	2004-10-28 22:25:59 -07:00
+++ b/sound/core/pcm.c	2004-10-28 22:25:59 -07:00
@@ -267,7 +267,7 @@
 }
 #endif
 
-
+#ifdef CONFIG_PROC_FS
 static void snd_pcm_proc_info_read(snd_pcm_substream_t *substream, snd_info_buffer_t *buffer)
 {
 	snd_pcm_info_t info;
@@ -391,6 +391,7 @@
 	snd_iprintf(buffer, "hw_ptr      : %ld\n", runtime->status->hw_ptr);
 	snd_iprintf(buffer, "appl_ptr    : %ld\n", runtime->control->appl_ptr);
 }
+#endif
 
 #ifdef CONFIG_SND_DEBUG
 static void snd_pcm_xrun_debug_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
diff -Nru a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
--- a/sound/core/pcm_lib.c	2004-10-28 22:25:57 -07:00
+++ b/sound/core/pcm_lib.c	2004-10-28 22:25:57 -07:00
@@ -176,7 +176,7 @@
 		runtime->avail_max = avail;
 	if (avail >= runtime->stop_threshold) {
 		if (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING)
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
+			snd_pcm_drain_done(substream);
 		else
 			xrun(substream);
 		return -EPIPE;
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	2004-10-28 22:25:57 -07:00
+++ b/sound/core/pcm_native.c	2004-10-28 22:25:57 -07:00
@@ -451,7 +451,7 @@
 static int snd_pcm_hw_free(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime;
-	int result;
+	int result = 0;
 
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
@@ -468,11 +468,8 @@
 	snd_pcm_stream_unlock_irq(substream);
 	if (atomic_read(&runtime->mmap_count))
 		return -EBADFD;
-	if (substream->ops->hw_free == NULL) {
-		runtime->status->state = SNDRV_PCM_STATE_OPEN;
-		return 0;
-	}
-	result = substream->ops->hw_free(substream);
+	if (substream->ops->hw_free)
+		result = substream->ops->hw_free(substream);
 	runtime->status->state = SNDRV_PCM_STATE_OPEN;
 	return result;
 }
@@ -652,6 +649,7 @@
 struct action_ops {
 	int (*pre_action)(snd_pcm_substream_t *substream, int state);
 	int (*do_action)(snd_pcm_substream_t *substream, int state);
+	void (*undo_action)(snd_pcm_substream_t *substream, int state);
 	void (*post_action)(snd_pcm_substream_t *substream, int state);
 };
 
@@ -666,7 +664,8 @@
 {
 	struct list_head *pos;
 	snd_pcm_substream_t *s = NULL;
-	int err, res = 0;
+	snd_pcm_substream_t *s1;
+	int res = 0;
 
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
@@ -674,24 +673,31 @@
 			spin_lock(&s->self_group.lock);
 		res = ops->pre_action(s, state);
 		if (res < 0)
-			break;
+			goto _unlock;
 	}
-	if (res >= 0) {
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
-			err = ops->do_action(s, state);
-			if (err < 0) {
-				if (res == 0)
-					res = err;
-			} else {
-				ops->post_action(s, state);
+	snd_pcm_group_for_each(pos, substream) {
+		s = snd_pcm_group_substream_entry(pos);
+		res = ops->do_action(s, state);
+		if (res < 0) {
+			if (ops->undo_action) {
+				snd_pcm_group_for_each(pos, substream) {
+					s1 = snd_pcm_group_substream_entry(pos);
+					if (s1 == s) /* failed stream */
+						break;
+					ops->undo_action(s1, state);
+				}
 			}
-			if (do_lock && s != substream)
-				spin_unlock(&s->self_group.lock);
+			s = NULL; /* unlock all */
+			goto _unlock;
 		}
-	} else if (do_lock) {
-		snd_pcm_substream_t *s1;
-		/* unlock all streams */
+	}
+	snd_pcm_group_for_each(pos, substream) {
+		s = snd_pcm_group_substream_entry(pos);
+		ops->post_action(s, state);
+	}
+ _unlock:
+	if (do_lock) {
+		/* unlock streams */
 		snd_pcm_group_for_each(pos, substream) {
 			s1 = snd_pcm_group_substream_entry(pos);
 			if (s1 != substream)
@@ -716,9 +722,10 @@
 	if (res < 0)
 		return res;
 	res = ops->do_action(substream, state);
-	if (res == 0) {
+	if (res == 0)
 		ops->post_action(substream, state);
-	}
+	else if (ops->undo_action)
+		ops->undo_action(substream, state);
 	return res;
 }
 
@@ -787,6 +794,9 @@
 	return res;
 }
 
+/*
+ * start callbacks
+ */
 static int snd_pcm_pre_start(snd_pcm_substream_t *substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -803,14 +813,20 @@
 {
 	if (substream->runtime->trigger_master != substream)
 		return 0;
-        return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
+	return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
+}
+
+static void snd_pcm_undo_start(snd_pcm_substream_t *substream, int state)
+{
+	if (substream->runtime->trigger_master == substream)
+		substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
 }
 
 static void snd_pcm_post_start(snd_pcm_substream_t *substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	snd_pcm_trigger_tstamp(substream);
-	runtime->status->state = SNDRV_PCM_STATE_RUNNING;
+	runtime->status->state = state;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    runtime->silence_size > 0)
 		snd_pcm_playback_silence(substream, ULONG_MAX);
@@ -823,22 +839,27 @@
 static struct action_ops snd_pcm_action_start = {
 	.pre_action = snd_pcm_pre_start,
 	.do_action = snd_pcm_do_start,
+	.undo_action = snd_pcm_undo_start,
 	.post_action = snd_pcm_post_start
 };
 
 /**
  * snd_pcm_start
+ *
+ * Start all linked streams.
  */
 int snd_pcm_start(snd_pcm_substream_t *substream)
 {
-	return snd_pcm_action(&snd_pcm_action_start, substream, 0);
+	return snd_pcm_action(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
 }
 
+/*
+ * stop callbacks
+ */
 static int snd_pcm_pre_stop(snd_pcm_substream_t *substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	if (substream->runtime->status->state != SNDRV_PCM_STATE_RUNNING &&
-	    substream->runtime->status->state != SNDRV_PCM_STATE_DRAINING)
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 	runtime->trigger_master = substream;
 	return 0;
@@ -846,19 +867,22 @@
 
 static int snd_pcm_do_stop(snd_pcm_substream_t *substream, int state)
 {
-	if (substream->runtime->trigger_master != substream)
-		return 0;
-	return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+	if (substream->runtime->trigger_master == substream &&
+	    snd_pcm_running(substream))
+		substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+	return 0; /* unconditonally stop all substreams */
 }
 
 static void snd_pcm_post_stop(snd_pcm_substream_t *substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_trigger_tstamp(substream);
-	if (substream->timer)
-		snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP, &runtime->trigger_tstamp);
-	runtime->status->state = state;
-	snd_pcm_tick_set(substream, 0);
+	if (runtime->status->state != state) {
+		snd_pcm_trigger_tstamp(substream);
+		if (substream->timer)
+			snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP, &runtime->trigger_tstamp);
+		runtime->status->state = state;
+		snd_pcm_tick_set(substream, 0);
+	}
 	wake_up(&runtime->sleep);
 }
 
@@ -870,12 +894,30 @@
 
 /**
  * snd_pcm_stop
+ *
+ * Try to stop all running streams in the substream group.
+ * The state of each stream is changed to the given value after that unconditionally.
  */
 int snd_pcm_stop(snd_pcm_substream_t *substream, int state)
 {
 	return snd_pcm_action(&snd_pcm_action_stop, substream, state);
 }
 
+/**
+ * snd_pcm_drain_done
+ *
+ * Stop the DMA only when the given stream is playback.
+ * The state is changed to SETUP.
+ * Unlike snd_pcm_stop(), this affects only the given stream.
+ */
+int snd_pcm_drain_done(snd_pcm_substream_t *substream)
+{
+	return snd_pcm_action_single(&snd_pcm_action_stop, substream, SNDRV_PCM_STATE_SETUP);
+}
+
+/*
+ * pause callbacks
+ */
 static int snd_pcm_pre_pause(snd_pcm_substream_t *substream, int push)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -899,6 +941,14 @@
 					      SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
 }
 
+static void snd_pcm_undo_pause(snd_pcm_substream_t *substream, int push)
+{
+	if (substream->runtime->trigger_master == substream)
+		substream->ops->trigger(substream,
+					push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
+					SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+}
+
 static void snd_pcm_post_pause(snd_pcm_substream_t *substream, int push)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -921,9 +971,13 @@
 static struct action_ops snd_pcm_action_pause = {
 	.pre_action = snd_pcm_pre_pause,
 	.do_action = snd_pcm_do_pause,
+	.undo_action = snd_pcm_undo_pause,
 	.post_action = snd_pcm_post_pause
 };
 
+/*
+ * Push/release the pause for all linked streams.
+ */
 static int snd_pcm_pause(snd_pcm_substream_t *substream, int push)
 {
 	return snd_pcm_action(&snd_pcm_action_pause, substream, push);
@@ -937,7 +991,6 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
 		return -EBUSY;
-	runtime->status->suspended_state = runtime->status->state;
 	runtime->trigger_master = substream;
 	return 0;
 }
@@ -947,10 +1000,10 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	if (runtime->trigger_master != substream)
 		return 0;
-	if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING &&
-	    runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING)
+	if (! snd_pcm_running(substream))
 		return 0;
-	return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
+	substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
+	return 0; /* suspend unconditionally */
 }
 
 static void snd_pcm_post_suspend(snd_pcm_substream_t *substream, int state)
@@ -959,6 +1012,7 @@
 	snd_pcm_trigger_tstamp(substream);
 	if (substream->timer)
 		snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MPAUSE, &runtime->trigger_tstamp);
+	runtime->status->suspended_state = runtime->status->state;
 	runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
 	snd_pcm_tick_set(substream, 0);
 	wake_up(&runtime->sleep);
@@ -972,6 +1026,9 @@
 
 /**
  * snd_pcm_suspend
+ *
+ * Trigger SUSPEND to all linked streams.
+ * After this call, all streams are changed to SUSPENDED state.
  */
 int snd_pcm_suspend(snd_pcm_substream_t *substream)
 {
@@ -980,11 +1037,14 @@
 
 /**
  * snd_pcm_suspend_all
+ *
+ * Trigger SUSPEND to all substreams in the given pcm.
+ * After this call, all streams are changed to SUSPENDED state.
  */
 int snd_pcm_suspend_all(snd_pcm_t *pcm)
 {
 	snd_pcm_substream_t *substream;
-	int stream, err;
+	int stream, err = 0;
 
 	for (stream = 0; stream < 2; stream++) {
 		for (substream = pcm->streams[stream].substream; substream; substream = substream->next) {
@@ -992,15 +1052,11 @@
 			if (substream->runtime == NULL)
 				continue;
 			snd_pcm_stream_lock(substream);
-			if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
-				snd_pcm_stream_unlock(substream);
-				continue;
-			}
-			if ((err = snd_pcm_suspend(substream)) < 0) {
-				snd_pcm_stream_unlock(substream);
-				return err;
-			}
+			if (substream->runtime->status->state != SNDRV_PCM_STATE_SUSPENDED)
+				err = snd_pcm_suspend(substream);
 			snd_pcm_stream_unlock(substream);
+			if (err < 0)
+				return err;
 		}
 	}
 	return 0;
@@ -1022,12 +1078,21 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	if (runtime->trigger_master != substream)
 		return 0;
+	/* DMA not running previously? */
 	if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING &&
-	    runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING)
+	    (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING ||
+	     substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
 		return 0;
 	return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
 }
 
+static void snd_pcm_undo_resume(snd_pcm_substream_t *substream, int state)
+{
+	if (substream->runtime->trigger_master == substream &&
+	    snd_pcm_running(substream))
+		substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
+}
+
 static void snd_pcm_post_resume(snd_pcm_substream_t *substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1042,6 +1107,7 @@
 static struct action_ops snd_pcm_action_resume = {
 	.pre_action = snd_pcm_pre_resume,
 	.do_action = snd_pcm_do_resume,
+	.undo_action = snd_pcm_undo_resume,
 	.post_action = snd_pcm_post_resume
 };
 
@@ -1066,6 +1132,11 @@
 
 #endif /* CONFIG_PM */
 
+/*
+ * xrun ioctl
+ *
+ * Change the RUNNING stream(s) to XRUN state.
+ */
 static int snd_pcm_xrun(snd_pcm_substream_t *substream)
 {
 	snd_card_t *card = substream->pcm->card;
@@ -1073,8 +1144,13 @@
 	int result;
 
 	snd_power_lock(card);
+	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+		if (result < 0)
+			goto _unlock;
+	}
+
 	snd_pcm_stream_lock_irq(substream);
-       _xrun_recovery:
 	switch (runtime->status->state) {
 	case SNDRV_PCM_STATE_XRUN:
 		result = 0;	/* already there */
@@ -1082,21 +1158,18 @@
 	case SNDRV_PCM_STATE_RUNNING:
 		result = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
 		break;
-	case SNDRV_PCM_STATE_SUSPENDED:
-		snd_pcm_stream_unlock_irq(substream);
-		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
-		snd_pcm_stream_lock_irq(substream);
-		if (result >= 0)
-			goto _xrun_recovery;
-		break;
 	default:
 		result = -EBADFD;
 	}
 	snd_pcm_stream_unlock_irq(substream);
+ _unlock:
 	snd_power_unlock(card);
 	return result;
 }
 
+/*
+ * reset ioctl
+ */
 static int snd_pcm_pre_reset(snd_pcm_substream_t * substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1145,17 +1218,17 @@
 	return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
 }
 
+/*
+ * prepare ioctl
+ */
 static int snd_pcm_pre_prepare(snd_pcm_substream_t * substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	switch (runtime->status->state) {
-	case SNDRV_PCM_STATE_OPEN:
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
-	case SNDRV_PCM_STATE_RUNNING:
+	if (snd_pcm_running(substream))
 		return -EBUSY;
-	default:
-		return 0;
-	}
+	return 0;
 }
 
 static int snd_pcm_do_prepare(snd_pcm_substream_t * substream, int state)
@@ -1195,111 +1268,147 @@
 	return res;
 }
 
-static void snd_pcm_change_state(snd_pcm_substream_t *substream, int state)
+/*
+ * drain ioctl
+ */
+
+static int snd_pcm_pre_drain_init(snd_pcm_substream_t * substream, int state)
 {
-	struct list_head *pos;
-	snd_pcm_substream_t *s;
+	if (substream->ffile->f_flags & O_NONBLOCK)
+		return -EAGAIN;
+	substream->runtime->trigger_master = substream;
+	return 0;
+}
 
-	if (snd_pcm_stream_linked(substream)) {
-		if (!spin_trylock(&substream->group->lock)) {
-			spin_unlock(&substream->self_group.lock);
-			spin_lock(&substream->group->lock);
-			spin_lock(&substream->self_group.lock);
-		}
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
-			if (s != substream)
-				spin_lock(&s->self_group.lock);
-			s->runtime->status->state = state;
-			if (s != substream)
-				spin_unlock(&s->self_group.lock);
+static int snd_pcm_do_drain_init(snd_pcm_substream_t * substream, int state)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (runtime->status->state) {
+		case SNDRV_PCM_STATE_PREPARED:
+			/* start playback stream if possible */
+			if (! snd_pcm_playback_empty(substream)) {
+				snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
+				snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
+			}
+			break;
+		case SNDRV_PCM_STATE_RUNNING:
+			runtime->status->state = SNDRV_PCM_STATE_DRAINING;
+			break;
+		default:
+			break;
 		}
-		spin_unlock(&substream->group->lock);
 	} else {
-		substream->runtime->status->state = state;
+		/* stop running stream */
+		if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
+			int state = snd_pcm_capture_avail(runtime) > 0 ?
+				SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
+			snd_pcm_do_stop(substream, state);
+			snd_pcm_post_stop(substream, state);
+		}
 	}
+	return 0;
+}
+
+static void snd_pcm_post_drain_init(snd_pcm_substream_t * substream, int state)
+{
 }
 
-static int snd_pcm_playback_drop(snd_pcm_substream_t *substream);
+static struct action_ops snd_pcm_action_drain_init = {
+	.pre_action = snd_pcm_pre_drain_init,
+	.do_action = snd_pcm_do_drain_init,
+	.post_action = snd_pcm_post_drain_init
+};
 
-static int snd_pcm_playback_drain(snd_pcm_substream_t * substream)
+struct drain_rec {
+	snd_pcm_substream_t *substream;
+	wait_queue_t wait;
+	snd_pcm_uframes_t stop_threshold;
+};
+
+static int snd_pcm_drop(snd_pcm_substream_t *substream);
+
+/*
+ * Drain the stream(s).
+ * When the substream is linked, sync until the draining of all playback streams
+ * is finished.
+ * After this call, all streams are supposed to be either SETUP or DRAINING
+ * (capture only) state.
+ */
+static int snd_pcm_drain(snd_pcm_substream_t *substream)
 {
 	snd_card_t *card;
 	snd_pcm_runtime_t *runtime;
-	int err, result = 0;
-	wait_queue_t wait;
-	enum { READY, EXPIRED, SUSPENDED, SIGNALED } state = READY;
-	snd_pcm_uframes_t stop_threshold;
+	struct list_head *pos;
+	int result = 0;
+	int i, num_drecs;
+	struct drain_rec *drec, drec_tmp, *d;
 
 	snd_assert(substream != NULL, return -ENXIO);
-	snd_assert(substream->stream == SNDRV_PCM_STREAM_PLAYBACK, return -EINVAL);
-	runtime = substream->runtime;
 	card = substream->pcm->card;
+	runtime = substream->runtime;
 
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+		return -EBADFD;
+
+	down_read(&snd_pcm_link_rwsem);
 	snd_power_lock(card);
-	snd_pcm_stream_lock_irq(substream);
+	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+		if (result < 0)
+			goto _unlock;
+	}
 
-	/* stop_threshold fixup to avoid endless loop when */
-	/* stop_threshold > buffer_size */
-	stop_threshold = runtime->stop_threshold;
-	if (runtime->stop_threshold > runtime->buffer_size)
-		runtime->stop_threshold = runtime->buffer_size;
+	/* allocate temporary record for drain sync */
+	if (snd_pcm_stream_linked(substream)) {
+		drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL);
+		if (! drec) {
+			result = -ENOMEM;
+			goto _unlock;
+		}
+	} else
+		drec = &drec_tmp;
 
-	switch (runtime->status->state) {
-	case SNDRV_PCM_STATE_PAUSED:
+	snd_pcm_stream_lock_irq(substream);
+	/* resume pause */
+	if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
 		snd_pcm_pause(substream, 0);
-		/* Fall through */
-	case SNDRV_PCM_STATE_RUNNING:
-	case SNDRV_PCM_STATE_DRAINING:
-		break;
-	case SNDRV_PCM_STATE_SUSPENDED:
-		snd_pcm_stream_unlock_irq(substream);
-		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
-		snd_pcm_stream_lock_irq(substream);
-		if (result >= 0)
-			snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
-		goto _end;
-	case SNDRV_PCM_STATE_OPEN:
-		result = -EBADFD;
-		goto _end;
-	case SNDRV_PCM_STATE_PREPARED:
-		if (!snd_pcm_playback_empty(substream)) {
-			err = snd_pcm_start(substream);
-			if (err < 0) {
-				result = err;
-				goto _end;
-			}
-			break;
-		}
-		/* Fall through */
-	case SNDRV_PCM_STATE_XRUN:
-		snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
-		/* Fall through */
-	case SNDRV_PCM_STATE_SETUP:
+
+	/* pre-start/stop - all running streams are changed to DRAINING state */
+	result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
+	if (result < 0)
 		goto _end;
-	default: 
-		break; 
-	}
 
-	if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
-		if (snd_pcm_playback_empty(substream)) {
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
-			goto _end;
+	/* check streams with PLAYBACK & DRAINING */
+	num_drecs = 0;
+	snd_pcm_group_for_each(pos, substream) {
+		snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos);
+		runtime = s->runtime;
+		if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) {
+			runtime->status->state = SNDRV_PCM_STATE_SETUP;
+			continue;
+		}
+		if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			d = &drec[num_drecs++];
+			d->substream = s;
+			init_waitqueue_entry(&d->wait, current);
+			add_wait_queue(&runtime->sleep, &d->wait);
+			/* stop_threshold fixup to avoid endless loop when
+			 * stop_threshold > buffer_size
+			 */
+			d->stop_threshold = runtime->stop_threshold;
+			if (runtime->stop_threshold > runtime->buffer_size)
+				runtime->stop_threshold = runtime->buffer_size;
 		}
-		snd_pcm_change_state(substream, SNDRV_PCM_STATE_DRAINING);
 	}
 
-	if (substream->ffile->f_flags & O_NONBLOCK) {
-		result = -EAGAIN;
+	if (! num_drecs)
 		goto _end;
-	}
 
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&runtime->sleep, &wait);
-	while (1) {
+	for (;;) {
 		long tout;
 		if (signal_pending(current)) {
-			state = SIGNALED;
+			result = -ERESTARTSYS;
 			break;
 		}
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1309,177 +1418,81 @@
 		snd_power_lock(card);
 		snd_pcm_stream_lock_irq(substream);
 		if (tout == 0) {
-			state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
+			if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
+				result = -ESTRPIPE;
+			else {
+				snd_printd("playback drain error (DMA or IRQ trouble?)\n");
+				snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
+				result = -EIO;
+			}
 			break;
 		}
-		if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) {
-			state = READY;
-			break;
+		/* all finished? */
+		for (i = 0; i < num_drecs; i++) {
+			runtime = drec[i].substream->runtime;
+			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+				break;
 		}
+		if (i == num_drecs)
+			break;
 	}
-	remove_wait_queue(&runtime->sleep, &wait);
-
-	switch (state) {
-	case SIGNALED:
-		result = -ERESTARTSYS;
-		goto _end;
-	case SUSPENDED:
-		result = -ESTRPIPE;
-		goto _end;
-	case EXPIRED:
-		snd_printd("playback drain error (DMA or IRQ trouble?)\n");
-		result = -EIO;
-		goto _end;
-	default:
-		break;
+	for (i = 0; i < num_drecs; i++) {
+		d = &drec[i];
+		runtime = d->substream->runtime;
+		remove_wait_queue(&runtime->sleep, &d->wait);
+		runtime->stop_threshold = d->stop_threshold;
 	}
 
-      _end:
-	runtime->stop_threshold = stop_threshold;
+ _end:
 	snd_pcm_stream_unlock_irq(substream);
+	if (drec && drec != &drec_tmp)
+		kfree(drec);
+ _unlock:
 	snd_power_unlock(card);
-	if (state == EXPIRED)
-		snd_pcm_playback_drop(substream);
+	up_read(&snd_pcm_link_rwsem);
 
 	return result;
 }
 
-static int snd_pcm_playback_drop(snd_pcm_substream_t *substream)
+/*
+ * drop ioctl
+ *
+ * Immediately put all linked substreams into SETUP state.
+ */
+static int snd_pcm_drop(snd_pcm_substream_t *substream)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_t *card = substream->pcm->card;
-	int res = 0;
+	snd_pcm_runtime_t *runtime;
+	snd_card_t *card;
+	int result = 0;
 	
-	snd_power_lock(card);
-	snd_pcm_stream_lock_irq(substream);
-	switch (runtime->status->state) {
-	case SNDRV_PCM_STATE_OPEN:
-		res = -EBADFD;
-		break;
-	case SNDRV_PCM_STATE_SETUP:
-		break;
-	case SNDRV_PCM_STATE_PAUSED:
-		snd_pcm_pause(substream, 0);
-		/* Fall through */
-	case SNDRV_PCM_STATE_RUNNING:
-	case SNDRV_PCM_STATE_DRAINING:
-		if (snd_pcm_update_hw_ptr(substream) >= 0) {
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
-			break;
-		}
-		/* Fall through */
-	case SNDRV_PCM_STATE_PREPARED:
-	case SNDRV_PCM_STATE_XRUN:
-		snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
-		break;
-	case SNDRV_PCM_STATE_SUSPENDED:
-		snd_pcm_stream_unlock_irq(substream);
-		res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
-		snd_pcm_stream_lock_irq(substream);
-		if (res >= 0)
-			snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
-		break;
-	default:
-		break; 
-	}
-	runtime->control->appl_ptr = runtime->status->hw_ptr;
-	snd_pcm_stream_unlock_irq(substream);
-	snd_power_unlock(card);
-	return res;
-}
+	snd_assert(substream != NULL, return -ENXIO);
+	runtime = substream->runtime;
+	card = substream->pcm->card;
 
-static int snd_pcm_capture_drain(snd_pcm_substream_t * substream)
-{
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_t *card = substream->pcm->card;
-	int res = 0;
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+		return -EBADFD;
 
 	snd_power_lock(card);
-	snd_pcm_stream_lock_irq(substream);
-	switch (runtime->status->state) {
-	case SNDRV_PCM_STATE_OPEN:
-		res = -EBADFD;
-		break;
-	case SNDRV_PCM_STATE_PREPARED:
-		snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
-		break;
-	case SNDRV_PCM_STATE_SETUP:
-	case SNDRV_PCM_STATE_DRAINING:
-		break;
-	case SNDRV_PCM_STATE_PAUSED:
-		snd_pcm_pause(substream, 0);
-		/* Fall through */
-	case SNDRV_PCM_STATE_RUNNING:
-		if (snd_pcm_update_hw_ptr(substream) >= 0) {
-			snd_pcm_stop(substream, 
-				     snd_pcm_capture_avail(runtime) > 0 ?
-				     SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP);
-			break;
-		}
-		/* Fall through */
-	case SNDRV_PCM_STATE_XRUN:
-	       _xrun_recovery:
-		snd_pcm_change_state(substream, 
-				     snd_pcm_capture_avail(runtime) > 0 ?
-				     SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP);
-		break;
-	case SNDRV_PCM_STATE_SUSPENDED:
-		snd_pcm_stream_unlock_irq(substream);
-		res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
-		snd_pcm_stream_lock_irq(substream);
-		if (res >= 0)
-			goto _xrun_recovery;
-		break;
-	default: 
-		break; 
+	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
+		if (result < 0)
+			goto _unlock;
 	}
-	snd_pcm_stream_unlock_irq(substream);
-	snd_power_unlock(card);
-	return res;
-}
 
-static int snd_pcm_capture_drop(snd_pcm_substream_t * substream)
-{
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_t *card = substream->pcm->card;
-	int res = 0;
-
-	snd_power_lock(card);
 	snd_pcm_stream_lock_irq(substream);
-	switch (runtime->status->state) {
-	case SNDRV_PCM_STATE_OPEN:
-		res = -EBADFD;
-		break;
-	case SNDRV_PCM_STATE_SETUP:
-		break;
-	case SNDRV_PCM_STATE_PAUSED:
+	/* resume pause */
+	if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
 		snd_pcm_pause(substream, 0);
-		/* Fall through */
-	case SNDRV_PCM_STATE_RUNNING:
-		snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
-		break;
-	case SNDRV_PCM_STATE_SUSPENDED:
-		snd_pcm_stream_unlock_irq(substream);
-		res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
-		snd_pcm_stream_lock_irq(substream);
-		if (res < 0)
-			goto _end;
-		/* Fall through */
-	case SNDRV_PCM_STATE_PREPARED:
-	case SNDRV_PCM_STATE_DRAINING:
-	case SNDRV_PCM_STATE_XRUN:
-		snd_pcm_change_state(substream, SNDRV_PCM_STATE_SETUP);
-		break;
-	default: 
-		break; 
-	}
-	runtime->control->appl_ptr = runtime->status->hw_ptr;
-       _end:
+
+	snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
+	/* runtime->control->appl_ptr = runtime->status->hw_ptr; */
 	snd_pcm_stream_unlock_irq(substream);
+ _unlock:
 	snd_power_unlock(card);
-	return res;
+	return result;
 }
 
+
 /* WARNING: Don't forget to fput back the file */
 extern int snd_major;
 static struct file *snd_pcm_file_fd(int fd)
@@ -1505,6 +1518,9 @@
 	return file;
 }
 
+/*
+ * PCM link handling
+ */
 static int snd_pcm_link(snd_pcm_substream_t *substream, int fd)
 {
 	int res = 0;
@@ -1512,12 +1528,6 @@
 	snd_pcm_file_t *pcm_file;
 	snd_pcm_substream_t *substream1;
 
-	snd_pcm_stream_lock_irq(substream);
-	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
-		snd_pcm_stream_unlock_irq(substream);
-		return -EBADFD;
-	}
-	snd_pcm_stream_unlock_irq(substream);
 	file = snd_pcm_file_fd(fd);
 	if (!file)
 		return -EBADFD;
@@ -1525,7 +1535,8 @@
 	substream1 = pcm_file->substream;
 	down_write(&snd_pcm_link_rwsem);
 	write_lock_irq(&snd_pcm_link_rwlock);
-	if (substream->runtime->status->state != substream1->runtime->status->state) {
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
+	    substream->runtime->status->state != substream1->runtime->status->state) {
 		res = -EBADFD;
 		goto _end;
 	}
@@ -1542,8 +1553,10 @@
 		spin_lock_init(&substream->group->lock);
 		INIT_LIST_HEAD(&substream->group->substreams);
 		list_add_tail(&substream->link_list, &substream->group->substreams);
+		substream->group->count = 1;
 	}
 	list_add_tail(&substream1->link_list, &substream->group->substreams);
+	substream->group->count++;
 	substream1->group = substream->group;
  _end:
 	write_unlock_irq(&snd_pcm_link_rwlock);
@@ -1562,7 +1575,7 @@
 static int snd_pcm_unlink(snd_pcm_substream_t *substream)
 {
 	struct list_head *pos;
-	int res = 0, count = 0;
+	int res = 0;
 
 	down_write(&snd_pcm_link_rwsem);
 	write_lock_irq(&snd_pcm_link_rwlock);
@@ -1571,11 +1584,8 @@
 		goto _end;
 	}
 	list_del(&substream->link_list);
-	snd_pcm_group_for_each(pos, substream) {
-		if (++count > 1)
-			break;
-	}
-	if (count == 1) {	/* detach the last stream, too */
+	substream->group->count--;
+	if (substream->group->count == 1) {	/* detach the last stream, too */
 		snd_pcm_group_for_each(pos, substream) {
 			relink_to_local(snd_pcm_group_substream_entry(pos));
 			break;
@@ -1589,6 +1599,9 @@
 	return res;
 }
 
+/*
+ * hw configurator
+ */
 static int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params,
 			       snd_pcm_hw_rule_t *rule)
 {
@@ -1973,6 +1986,7 @@
 
 	str = substream->pstr;
 	substream->file = pcm_file;
+	substream->no_mmap_ctrl = 0;
 
 	pcm_file->substream = substream;
 
@@ -2076,10 +2090,7 @@
 	snd_assert(substream != NULL, return -ENXIO);
 	snd_assert(!atomic_read(&substream->runtime->mmap_count), );
 	pcm = substream->pcm;
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		snd_pcm_playback_drop(substream);
-	else
-		snd_pcm_capture_drop(substream);
+	snd_pcm_drop(substream);
 	fasync_helper(-1, file, 0, &substream->runtime->fasync);
 	down(&pcm->open_mutex);
 	snd_pcm_release_file(pcm_file);
@@ -2435,7 +2446,7 @@
 	case SNDRV_PCM_IOCTL_RESET:
 		return snd_pcm_reset(substream);
 	case SNDRV_PCM_IOCTL_START:
-		return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, 0);
+		return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
 	case SNDRV_PCM_IOCTL_LINK:
 		return snd_pcm_link(substream, (int)(unsigned long) arg);
 	case SNDRV_PCM_IOCTL_UNLINK:
@@ -2454,6 +2465,10 @@
 		return snd_pcm_hw_refine_old_user(substream, arg);
 	case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
 		return snd_pcm_hw_params_old_user(substream, arg);
+	case SNDRV_PCM_IOCTL_DRAIN:
+		return snd_pcm_drain(substream);
+	case SNDRV_PCM_IOCTL_DROP:
+		return snd_pcm_drop(substream);
 	}
 	snd_printd("unknown ioctl = 0x%x\n", cmd);
 	return -ENOTTY;
@@ -2542,10 +2557,6 @@
 		snd_pcm_stream_unlock_irq(substream);
 		return res;
 	}
-	case SNDRV_PCM_IOCTL_DRAIN:
-		return snd_pcm_playback_drain(substream);
-	case SNDRV_PCM_IOCTL_DROP:
-		return snd_pcm_playback_drop(substream);
 	}
 	return snd_pcm_common_ioctl1(substream, cmd, arg);
 }
@@ -2625,10 +2636,6 @@
 		__put_user(result, _frames);
 		return result < 0 ? result : 0;
 	}
-	case SNDRV_PCM_IOCTL_DRAIN:
-		return snd_pcm_capture_drain(substream);
-	case SNDRV_PCM_IOCTL_DROP:
-		return snd_pcm_capture_drop(substream);
 	}
 	return snd_pcm_common_ioctl1(substream, cmd, arg);
 }
@@ -3158,8 +3165,12 @@
 	offset = area->vm_pgoff << PAGE_SHIFT;
 	switch (offset) {
 	case SNDRV_PCM_MMAP_OFFSET_STATUS:
+		if (substream->no_mmap_ctrl)
+			return -ENXIO;
 		return snd_pcm_mmap_status(substream, file, area);
 	case SNDRV_PCM_MMAP_OFFSET_CONTROL:
+		if (substream->no_mmap_ctrl)
+			return -ENXIO;
 		return snd_pcm_mmap_control(substream, file, area);
 	default:
 		return snd_pcm_mmap_data(substream, file, area);
diff -Nru a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
--- a/sound/core/seq/oss/seq_oss.c	2004-10-28 22:25:59 -07:00
+++ b/sound/core/seq/oss/seq_oss.c	2004-10-28 22:25:59 -07:00
@@ -78,16 +78,17 @@
 		snd_seq_oss_synth_unregister,
 	};
 
+	snd_seq_autoload_lock();
 	if ((rc = register_device()) < 0)
-		return rc;
+		goto error;
 	if ((rc = register_proc()) < 0) {
 		unregister_device();
-		return rc;
+		goto error;
 	}
 	if ((rc = snd_seq_oss_create_client()) < 0) {
 		unregister_proc();
 		unregister_device();
-		return rc;
+		goto error;
 	}
 
 	if ((rc = snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OSS, &ops,
@@ -95,12 +96,15 @@
 		snd_seq_oss_delete_client();
 		unregister_proc();
 		unregister_device();
-		return rc;
+		goto error;
 	}
 
 	/* success */
 	snd_seq_oss_synth_init();
-	return 0;
+
+ error:
+	snd_seq_autoload_unlock();
+	return rc;
 }
 
 static void __exit alsa_seq_oss_exit(void)
diff -Nru a/sound/core/seq/seq.c b/sound/core/seq/seq.c
--- a/sound/core/seq/seq.c	2004-10-28 22:25:59 -07:00
+++ b/sound/core/seq/seq.c	2004-10-28 22:25:59 -07:00
@@ -70,35 +70,37 @@
  *  INIT PART
  */
 
-
 static int __init alsa_seq_init(void)
 {
 	int err;
 
+	snd_seq_autoload_lock();
 	if ((err = client_init_data()) < 0)
-		return err;
+		goto error;
 
 	/* init memory, room for selected events */
 	if ((err = snd_sequencer_memory_init()) < 0)
-		return err;
+		goto error;
 
 	/* init event queues */
 	if ((err = snd_seq_queues_init()) < 0)
-		return err;
+		goto error;
 
 	/* register sequencer device */
 	if ((err = snd_sequencer_device_init()) < 0)
-		return err;
+		goto error;
 
 	/* register proc interface */
 	if ((err = snd_seq_info_init()) < 0)
-		return err;
+		goto error;
 
 	/* register our internal client */
 	if ((err = snd_seq_system_client_init()) < 0)
-		return err;
+		goto error;
 
-	return 0;
+ error:
+	snd_seq_autoload_unlock();
+	return err;
 }
 
 static void __exit alsa_seq_exit(void)
diff -Nru a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
--- a/sound/core/seq/seq_clientmgr.c	2004-10-28 22:25:57 -07:00
+++ b/sound/core/seq/seq_clientmgr.c	2004-10-28 22:25:57 -07:00
@@ -420,7 +420,10 @@
 			count -= err;
 			buf += err;
 		} else {
-			copy_to_user(buf, &cell->event, sizeof(snd_seq_event_t));
+			if (copy_to_user(buf, &cell->event, sizeof(snd_seq_event_t))) {
+				err = -EFAULT;
+				break;
+			}
 			count -= sizeof(snd_seq_event_t);
 			buf += sizeof(snd_seq_event_t);
 		}
diff -Nru a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
--- a/sound/core/seq/seq_device.c	2004-10-28 22:25:57 -07:00
+++ b/sound/core/seq/seq_device.c	2004-10-28 22:25:57 -07:00
@@ -41,6 +41,7 @@
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/seq_device.h>
+#include <sound/seq_kernel.h>
 #include <sound/initval.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
@@ -125,11 +126,31 @@
  * load all registered drivers (called from seq_clientmgr.c)
  */
 
+#ifdef CONFIG_KMOD
+/* avoid auto-loading during module_init() */
+static int snd_seq_in_init;
+void snd_seq_autoload_lock(void)
+{
+	snd_seq_in_init++;
+}
+
+void snd_seq_autoload_unlock(void)
+{
+	snd_seq_in_init--;
+}
+#endif
+
 void snd_seq_device_load_drivers(void)
 {
 #ifdef CONFIG_KMOD
 	struct list_head *head;
 
+	/* Calling request_module during module_init()
+	 * may cause blocking.
+	 */
+	if (snd_seq_in_init)
+		return;
+
 	if (! current->fs->root)
 		return;
 
@@ -309,12 +330,16 @@
 	    entry->init_device == NULL || entry->free_device == NULL)
 		return -EINVAL;
 
+	snd_seq_autoload_lock();
 	ops = find_driver(id, 1);
-	if (ops == NULL)
+	if (ops == NULL) {
+		snd_seq_autoload_unlock();
 		return -ENOMEM;
+	}
 	if (ops->driver & DRIVER_LOADED) {
 		snd_printk(KERN_WARNING "driver_register: driver '%s' already exists\n", id);
 		unlock_driver(ops);
+		snd_seq_autoload_unlock();
 		return -EBUSY;
 	}
 
@@ -332,6 +357,7 @@
 	up(&ops->reg_mutex);
 
 	unlock_driver(ops);
+	snd_seq_autoload_unlock();
 
 	return 0;
 }
@@ -543,3 +569,7 @@
 EXPORT_SYMBOL(snd_seq_device_new);
 EXPORT_SYMBOL(snd_seq_device_register_driver);
 EXPORT_SYMBOL(snd_seq_device_unregister_driver);
+#ifdef CONFIG_KMOD
+EXPORT_SYMBOL(snd_seq_autoload_lock);
+EXPORT_SYMBOL(snd_seq_autoload_unlock);
+#endif
diff -Nru a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
--- a/sound/core/seq/seq_dummy.c	2004-10-28 22:25:58 -07:00
+++ b/sound/core/seq/seq_dummy.c	2004-10-28 22:25:58 -07:00
@@ -256,7 +256,11 @@
 
 static int __init alsa_seq_dummy_init(void)
 {
-	return register_client();
+	int err;
+	snd_seq_autoload_lock();
+	err = register_client();
+	snd_seq_autoload_unlock();
+	return err;
 }
 
 static void __exit alsa_seq_dummy_exit(void)
diff -Nru a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
--- a/sound/core/seq/seq_midi.c	2004-10-28 22:25:59 -07:00
+++ b/sound/core/seq/seq_midi.c	2004-10-28 22:25:59 -07:00
@@ -279,7 +279,7 @@
 	cinfo.client = client->seq_client;
 	cinfo.type = KERNEL_CLIENT;
 	name = rmidi->name[0] ? (const char *)rmidi->name : "External MIDI";
-	snprintf(cinfo.name, sizeof(cinfo.name), "%s - Rawmidi %d", name, card->number);
+	strlcpy(cinfo.name, name, sizeof(cinfo.name));
 	return snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
 }
 
@@ -464,7 +464,9 @@
 		snd_seq_midisynth_unregister_port,
 	};
 	memset(&synths, 0, sizeof(synths));
+	snd_seq_autoload_lock();
 	snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH, &ops, 0);
+	snd_seq_autoload_unlock();
 	return 0;
 }
 
diff -Nru a/sound/drivers/Kconfig b/sound/drivers/Kconfig
--- a/sound/drivers/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/sound/drivers/Kconfig	2004-10-28 22:25:59 -07:00
@@ -30,8 +30,14 @@
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include dummy driver. This driver does nothing, but
-	  emulates various mixer controls and PCM devices.
+	  Say Y here to include the dummy driver.  This driver does
+	  nothing, but emulates various mixer controls and PCM devices.
+
+	  You don't need this unless you're testing the hardware support
+	  of programs using the ALSA API.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-dummy.
 
 config SND_VIRMIDI
 	tristate "Virtual MIDI soundcard"
@@ -39,8 +45,14 @@
 	select SND_TIMER
 	select SND_RAWMIDI
 	help
-	  Say 'Y' or 'M' to include virtual MIDI driver. This driver allows to
-	  connect applications using raw MIDI devices to sequencer.
+	  Say Y here to include the virtual MIDI driver.  This driver
+	  allows to connect applications using raw MIDI devices to
+	  sequencer clients.
+
+	  If you don't know what MIDI is, say N here.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-virmidi.
 
 config SND_MTPAV
 	tristate "MOTU MidiTimePiece AV multiport MIDI"
@@ -48,23 +60,39 @@
 	select SND_TIMER
 	select SND_RAWMIDI
 	help
-	  Say 'Y' or 'M' to include support for MOTU MidiTimePiece AV multiport
-	  MIDI adapter.
+	  To use a MOTU MidiTimePiece AV multiport MIDI adapter
+	  connected to the parallel port, say Y here and make sure that
+	  the standard parallel port driver isn't used for the port.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-mtpav.
 
 config SND_SERIAL_U16550
-	tristate "UART16550 - MIDI only driver"
+	tristate "UART16550 serial MIDI driver"
 	depends on SND
 	select SND_TIMER
 	select SND_RAWMIDI
 	help
-	  Say 'Y' or 'M' to include support for MIDI serial port driver. It works
-	  with serial UARTs 16550 and better.
+	  To include support for MIDI serial port interfaces, say Y here
+	  and read <file:Documentation/sound/alsa/serial-u16550.txt>.
+	  This driver works with serial UARTs 16550 and better.
+
+	  This driver accesses the serial port hardware directly, so
+	  make sure that the standard serial driver isn't used or
+	  deactivated with setserial before loading this driver.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-serial-u16550.
 
 config SND_MPU401
 	tristate "Generic MPU-401 UART driver"
 	depends on SND
 	select SND_MPU401_UART
 	help
-	  Say 'Y' or 'M' to include support for MPU401 hardware using UART access.
+	  Say Y here to include support for MIDI ports compatible with
+	  the Roland MPU-401 interface in UART mode.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-mpu401.
 
 endmenu
diff -Nru a/sound/drivers/dummy.c b/sound/drivers/dummy.c
--- a/sound/drivers/dummy.c	2004-10-28 22:25:59 -07:00
+++ b/sound/drivers/dummy.c	2004-10-28 22:25:59 -07:00
@@ -556,7 +556,7 @@
 DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_MASTER)
 };
 
-int __init snd_card_dummy_new_mixer(snd_card_dummy_t * dummy)
+static int __init snd_card_dummy_new_mixer(snd_card_dummy_t * dummy)
 {
 	snd_card_t *card = dummy->card;
 	unsigned int idx;
diff -Nru a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
--- a/sound/drivers/mpu401/mpu401_uart.c	2004-10-28 22:25:57 -07:00
+++ b/sound/drivers/mpu401/mpu401_uart.c	2004-10-28 22:25:57 -07:00
@@ -70,12 +70,12 @@
 
 static void mpu401_write_mmio(mpu401_t *mpu, unsigned char data, unsigned long addr)
 {
-	writeb(data, (unsigned long*)addr);
+	writeb(data, (void __iomem *)addr);
 }
 
 static unsigned char mpu401_read_mmio(mpu401_t *mpu, unsigned long addr)
 {
-	return readb((unsigned long*)addr);
+	return readb((void __iomem *)addr);
 }
 /*  */
 
diff -Nru a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
--- a/sound/drivers/opl3/opl3_lib.c	2004-10-28 22:25:57 -07:00
+++ b/sound/drivers/opl3/opl3_lib.c	2004-10-28 22:25:57 -07:00
@@ -85,28 +85,6 @@
 	spin_unlock_irqrestore(&opl3->reg_lock, flags);
 }
 
-void snd_opl3_cs4281_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
-{
-	unsigned long flags;
-	unsigned long port;
-
-	/*
-	 * CS4281 requires a special access to I/O registers
-	 */
-
-	port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;
-
-	spin_lock_irqsave(&opl3->reg_lock, flags);
-
-	writel((unsigned int)cmd, port << 2);
-	udelay(10);
-
-	writel((unsigned int)val, (port + 1) << 2);
-	udelay(30);
-
-	spin_unlock_irqrestore(&opl3->reg_lock, flags);
-}
-
 static int snd_opl3_detect(opl3_t * opl3)
 {
 	/*
@@ -344,6 +322,9 @@
 
 static int snd_opl3_free(opl3_t *opl3)
 {
+	snd_assert(opl3 != NULL, return -ENXIO);
+	if (opl3->private_free)
+		opl3->private_free(opl3);
 	if (opl3->res_l_port) {
 		release_resource(opl3->res_l_port);
 		kfree_nocheck(opl3->res_l_port);
@@ -362,51 +343,89 @@
 	return snd_opl3_free(opl3);
 }
 
-int snd_opl3_create(snd_card_t * card,
-		    unsigned long l_port,
-		    unsigned long r_port,
-		    unsigned short hardware,
-		    int integrated,
-		    opl3_t ** ropl3)
+int snd_opl3_new(snd_card_t *card,
+		 unsigned short hardware,
+		 opl3_t **ropl3)
 {
-	opl3_t *opl3;
-	int err;
 	static snd_device_ops_t ops = {
 		.dev_free = snd_opl3_dev_free,
 	};
+	opl3_t *opl3;
+	int err;
 
 	*ropl3 = NULL;
-
 	opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
 	if (opl3 == NULL)
 		return -ENOMEM;
 
-	if (integrated)
-		goto __step1; /* ports are already reserved */
+	opl3->card = card;
+	opl3->hardware = hardware;
+	spin_lock_init(&opl3->reg_lock);
+	spin_lock_init(&opl3->timer_lock);
+	init_MUTEX(&opl3->access_mutex);
 
-	if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) {
-		snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl3, &ops)) < 0) {
 		snd_opl3_free(opl3);
-		return -EBUSY;
+		return err;
 	}
-	if (r_port != 0 &&
-	    (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) {
-		snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
-		snd_opl3_free(opl3);
-		return -EBUSY;
+
+	*ropl3 = opl3;
+	return 0;
+}
+
+int snd_opl3_init(opl3_t *opl3)
+{
+	if (! opl3->command) {
+		printk(KERN_ERR "snd_opl3_init: command not defined!\n");
+		return -EINVAL;
 	}
 
-      __step1:
+	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
+	/* Melodic mode */
+	opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);
 
-	opl3->card = card;
-	opl3->hardware = hardware;
+	switch (opl3->hardware & OPL3_HW_MASK) {
+	case OPL3_HW_OPL2:
+		opl3->max_voices = MAX_OPL2_VOICES;
+		break;
+	case OPL3_HW_OPL3:
+	case OPL3_HW_OPL4:
+		opl3->max_voices = MAX_OPL3_VOICES;
+		/* Enter OPL3 mode */
+		opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);
+	}
+	return 0;
+}
+
+int snd_opl3_create(snd_card_t * card,
+		    unsigned long l_port,
+		    unsigned long r_port,
+		    unsigned short hardware,
+		    int integrated,
+		    opl3_t ** ropl3)
+{
+	opl3_t *opl3;
+	int err;
+
+	*ropl3 = NULL;
+	if ((err = snd_opl3_new(card, hardware, &opl3)) < 0)
+		return err;
+	if (! integrated) {
+		if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) {
+			snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
+			snd_opl3_free(opl3);
+			return -EBUSY;
+		}
+		if (r_port != 0 &&
+		    (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) {
+			snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
+			snd_opl3_free(opl3);
+			return -EBUSY;
+		}
+	}
 	opl3->l_port = l_port;
 	opl3->r_port = r_port;
 
-	spin_lock_init(&opl3->reg_lock);
-	spin_lock_init(&opl3->timer_lock);
-	init_MUTEX(&opl3->access_mutex);
-
 	switch (opl3->hardware) {
 	/* some hardware doesn't support timers */
 	case OPL3_HW_OPL3_SV:
@@ -414,9 +433,6 @@
 	case OPL3_HW_OPL3_FM801:
 		opl3->command = &snd_opl3_command;
 		break;
-	case OPL3_HW_OPL3_CS4281:
-		opl3->command = &snd_opl3_cs4281_command;
-		break;
 	default:
 		opl3->command = &snd_opl2_command;
 		if ((err = snd_opl3_detect(opl3)) < 0) {
@@ -433,23 +449,7 @@
 		}
 	}
 
-	opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
-	opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);	/* Melodic mode */
-
-	switch (opl3->hardware & OPL3_HW_MASK) {
-	case OPL3_HW_OPL2:
-		opl3->max_voices = MAX_OPL2_VOICES;
-		break;
-	case OPL3_HW_OPL3:
-	case OPL3_HW_OPL4:
-		opl3->max_voices = MAX_OPL3_VOICES;
-		snd_assert(opl3->r_port != 0, snd_opl3_free(opl3); return -ENODEV);
-		opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);	/* Enter OPL3 mode */
-	}
-	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl3, &ops)) < 0) {
-		snd_opl3_free(opl3);
-		return err;
-	}
+	snd_opl3_init(opl3);
 
 	*ropl3 = opl3;
 	return 0;
@@ -531,6 +531,8 @@
 }
 
 EXPORT_SYMBOL(snd_opl3_interrupt);
+EXPORT_SYMBOL(snd_opl3_new);
+EXPORT_SYMBOL(snd_opl3_init);
 EXPORT_SYMBOL(snd_opl3_create);
 EXPORT_SYMBOL(snd_opl3_timer_new);
 EXPORT_SYMBOL(snd_opl3_hwdep_new);
diff -Nru a/sound/isa/Kconfig b/sound/isa/Kconfig
--- a/sound/isa/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/sound/isa/Kconfig	2004-10-28 22:25:59 -07:00
@@ -10,17 +10,25 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Analog Devices SoundPort AD1816A or
-	  compatible sound chips.
+	  Say Y here to include support for Analog Devices SoundPort
+	  AD1816A or compatible sound chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ad1816a.
 
 config SND_AD1848
 	tristate "Generic AD1848/CS4248 driver"
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for AD1848 (Analog Devices) or CS4248 
-	  (Cirrus Logic - Crystal Semiconductors) chips. Please, for newer chips
-	  from Cirrus Logic, use CS4231, CS4232 or CS4236+ driver.
+	  Say Y here to include support for AD1848 (Analog Devices) or
+	  CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
+	  
+	  For newer chips from Cirrus Logic, use the CS4231, CS4232 or
+	  CS4236+ drivers.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ad1848.
 
 config SND_CS4231
 	tristate "Generic Cirrus Logic CS4231 driver"
@@ -28,8 +36,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for CS4231 chips from Cirrus Logic -
-	  Crystal Semiconductors.
+	  Say Y here to include support for CS4231 chips from Cirrus
+	  Logic - Crystal Semiconductors.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-cs4231.
 
 config SND_CS4232
 	tristate "Generic Cirrus Logic CS4232 driver"
@@ -38,8 +49,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for CS4232 chips from Cirrus Logic -
-	  Crystal Semiconductors.
+	  Say Y here to include support for CS4232 chips from Cirrus
+	  Logic - Crystal Semiconductors.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-cs4232.
 
 config SND_CS4236
 	tristate "Generic Cirrus Logic CS4236+ driver"
@@ -48,8 +62,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for CS4235,CS4236,CS4237B,CS4238B,CS4239
-	  chips from Cirrus Logic - Crystal Semiconductors.
+	  Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
+	  CS4239 chips from Cirrus Logic - Crystal Semiconductors.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-cs4236.
 
 config SND_ES968
 	tristate "Generic ESS ES968 driver"
@@ -57,7 +74,10 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for ESS AudioDrive ES968 chip.
+	  Say Y here to include support for ESS AudioDrive ES968 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-es968.
 
 config SND_ES1688
 	tristate "Generic ESS ES688/ES1688 driver"
@@ -66,7 +86,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for ESS AudioDrive ES688 or ES1688 chips.
+	  Say Y here to include support for ESS AudioDrive ES688 or
+	  ES1688 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-es1688.
 
 config SND_ES18XX
 	tristate "Generic ESS ES18xx driver"
@@ -75,7 +99,10 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for ESS AudioDrive ES18xx chips.
+	  Say Y here to include support for ESS AudioDrive ES18xx chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-es18xx.
 
 config SND_GUS_SYNTH
 	tristate
@@ -87,7 +114,11 @@
 	select SND_PCM
 	select SND_GUS_SYNTH
 	help
-	  Say 'Y' or 'M' to include support for Gravis UltraSound Classic soundcard.
+	  Say Y here to include support for Gravis UltraSound Classic
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-gusclassic.
 
 config SND_GUSEXTREME
 	tristate "Gravis UltraSound Extreme"
@@ -97,7 +128,11 @@
 	select SND_PCM
 	select SND_GUS_SYNTH
 	help
-	  Say 'Y' or 'M' to include support for Gravis UltraSound Extreme soundcard.
+	  Say Y here to include support for Gravis UltraSound Extreme
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-gusextreme.
 
 config SND_GUSMAX
 	tristate "Gravis UltraSound MAX"
@@ -106,7 +141,11 @@
 	select SND_PCM
 	select SND_GUS_SYNTH
 	help
-	  Say 'Y' or 'M' to include support for Gravis UltraSound MAX soundcard.
+	  Say Y here to include support for Gravis UltraSound MAX
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-gusmax.
 
 config SND_INTERWAVE
 	tristate "AMD InterWave, Gravis UltraSound PnP"
@@ -115,9 +154,12 @@
 	select SND_PCM
 	select SND_GUS_SYNTH
 	help
-	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
-	  (Gravis UltraSound Plug & Play, STB SoundRage32, MED3210, Dynasonic Pro,
-	  Panasonic PCA761AW).
+	  Say Y here to include support for AMD InterWave based
+	  soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
+	  MED3210, Dynasonic Pro, Panasonic PCA761AW).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-interwave.
 
 config SND_INTERWAVE_STB
 	tristate "AMD InterWave + TEA6330T (UltraSound 32-Pro)"
@@ -126,8 +168,12 @@
 	select SND_PCM
 	select SND_GUS_SYNTH
 	help
-	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
-	  with TEA6330T bass and treble regulator (UltraSound 32-Pro).
+	  Say Y here to include support for AMD InterWave based
+	  soundcards with a TEA6330T bass and treble regulator
+	  (UltraSound 32-Pro).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-interwave-stb.
 
 config SND_OPTI92X_AD1848
 	tristate "OPTi 82C92x - AD1848"
@@ -137,8 +183,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Opti92x soundcards equiped with
-	  AD1848 codec.
+	  Say Y here to include support for soundcards based on Opti
+	  82C92x or OTI-601 chips and using an AD1848 codec.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-opti92x-ad1848.
 
 config SND_OPTI92X_CS4231
 	tristate "OPTi 82C92x - CS4231"
@@ -148,8 +197,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Opti92x soundcards equiped with
-	  CS4231 codec.
+	  Say Y here to include support for soundcards based on Opti
+	  82C92x chips and using a CS4231 codec.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-opti92x-cs4231.
 
 config SND_OPTI93X
 	tristate "OPTi 82C93x"
@@ -158,7 +210,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Opti93x soundcards.
+	  Say Y here to include support for soundcards based on Opti
+	  82C93x chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-opti93x.
 
 config SND_SB8
 	tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
@@ -167,8 +223,11 @@
 	select SND_RAWMIDI
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Sound Blaster 1.0/2.0/Pro (8-bit)
-	  soundcards or 100% compatible from Creative.
+	  Say Y here to include support for Creative Sound Blaster 1.0/
+	  2.0/Pro (8-bit) or 100% compatible soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sb8.
 
 config SND_SB16
 	tristate "Sound Blaster 16 (PnP)"
@@ -177,8 +236,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Sound Blaster 16 (including
-	  Plug and Play version).
+	  Say Y here to include support for Sound Blaster 16 soundcards
+	  (including the Plug and Play version).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sb16.
 
 config SND_SBAWE
 	tristate "Sound Blaster AWE (32,64) (PnP)"
@@ -187,16 +249,19 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Sound Blaster AWE (including
-	  Plug and Play version).
+	  Say Y here to include support for Sound Blaster AWE soundcards
+	  (including the Plug and Play version).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sbawe.
 
 config SND_SB16_CSP
 	bool "Sound Blaster 16/AWE CSP support"
 	depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
 	help
-	  Say 'Y' to include support for CSP core. This special coprocessor
-	  can do variable tasks like various compression and decompression
-	  algorithms.
+	  Say Y here to include support for the CSP core.  This special
+	  coprocessor can do variable tasks like various compression and
+	  decompression algorithms.
 
 config SND_WAVEFRONT
 	tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
@@ -205,8 +270,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Turtle Beach Maui, Tropez
-	  and Tropez+ soundcards based on Wavefront chip.
+	  Say Y here to include support for Turtle Beach Maui, Tropez
+	  and Tropez+ soundcards based on the Wavefront chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-wavefront.
 
 config SND_ALS100
 	tristate "Avance Logic ALS100/ALS120"
@@ -215,8 +283,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Avance Logic ALS100, ALS110,
-	  ALS120 and ALS200 soundcards.
+	  Say Y here to include support for soundcards based on Avance
+	  Logic ALS100, ALS110, ALS120 and ALS200 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-als100.
 
 config SND_AZT2320
 	tristate "Aztech Systems AZT2320"
@@ -225,14 +296,22 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Aztech Systems AZT2320 soundcard.
+	  Say Y here to include support for soundcards based on the
+	  Aztech Systems AZT2320 chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-azt2320.
 
 config SND_CMI8330
 	tristate "C-Media CMI8330"
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for C-Media CMI8330 based soundcards.
+	  Say Y here to include support for soundcards based on the
+	  C-Media CMI8330 chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-cmi8330.
 
 config SND_DT019X
 	tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
@@ -241,8 +320,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Diamond Technologies DT-019X and
-	  Avance Logic ALS-007 soundcards.
+	  Say Y here to include support for soundcards based on the
+	  Diamond Technologies DT-019X or Avance Logic ALS-007 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-dt019x.
 
 config SND_OPL3SA2
 	tristate "Yamaha OPL3-SA2/SA3"
@@ -251,14 +333,22 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Yamaha OPL3SA2 or OPL3SA3 chips.
+	  Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
+	  chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-opl3sa2.
 
 config SND_SGALAXY
 	tristate "Aztech Sound Galaxy"
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Aztech Sound Galaxy.
+	  Say Y here to include support for Aztech Sound Galaxy
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sgalaxy.
 
 config SND_SSCAPE
 	tristate "Ensoniq SoundScape PnP driver"
@@ -267,7 +357,10 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Ensoniq SoundScape PnP
-	  soundcard.
+	  Say Y here to include support for Ensoniq SoundScape PnP
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sscape.
 
 endmenu
diff -Nru a/sound/isa/es18xx.c b/sound/isa/es18xx.c
--- a/sound/isa/es18xx.c	2004-10-28 22:25:57 -07:00
+++ b/sound/isa/es18xx.c	2004-10-28 22:25:57 -07:00
@@ -419,6 +419,11 @@
 		
 	if ((chip->caps & ES18XX_PCM2) && mode == DAC2) {
 		snd_es18xx_mixer_write(chip, 0x70, bits);
+		/*
+		 * Comment from kernel oss driver:
+		 * FKS: fascinating: 0x72 doesn't seem to work.
+		 */
+		snd_es18xx_write(chip, 0xA2, div0);
 		snd_es18xx_mixer_write(chip, 0x72, div0);
 	} else {
 		snd_es18xx_write(chip, 0xA1, bits);
diff -Nru a/sound/oss/aci.c b/sound/oss/aci.c
--- a/sound/oss/aci.c	2004-10-28 22:25:58 -07:00
+++ b/sound/oss/aci.c	2004-10-28 22:25:58 -07:00
@@ -62,11 +62,10 @@
 #include "sound_config.h"
 
 int aci_port;	/* as determined by bit 4 in the OPTi 929 MC4 register */
-int aci_idcode[2];	/* manufacturer and product ID */
+static int aci_idcode[2];	/* manufacturer and product ID */
 int aci_version;	/* ACI firmware version	*/
 
 EXPORT_SYMBOL(aci_port);
-EXPORT_SYMBOL(aci_idcode);
 EXPORT_SYMBOL(aci_version);
 
 #include "aci.h"
diff -Nru a/sound/oss/aci.h b/sound/oss/aci.h
--- a/sound/oss/aci.h	2004-10-28 22:25:58 -07:00
+++ b/sound/oss/aci.h	2004-10-28 22:25:58 -07:00
@@ -2,7 +2,6 @@
 #define _ACI_H_
 
 extern int aci_port;
-extern int aci_idcode[2];	/* manufacturer and product ID */
 extern int aci_version;		/* ACI firmware version	*/
 extern int aci_rw_cmd(int write1, int write2, int write3);
 
diff -Nru a/sound/oss/audio.c b/sound/oss/audio.c
--- a/sound/oss/audio.c	2004-10-28 22:25:57 -07:00
+++ b/sound/oss/audio.c	2004-10-28 22:25:57 -07:00
@@ -38,7 +38,7 @@
 #define NEUTRAL16	0x00
 
 
-int             dma_ioctl(int dev, unsigned int cmd, void __user *arg);
+static int             dma_ioctl(int dev, unsigned int cmd, void __user *arg);
 
 static int set_format(int dev, int fmt)
 {
@@ -735,7 +735,7 @@
 	return bytes | ((count - 1) << 16);
 }
 
-int dma_ioctl(int dev, unsigned int cmd, void __user *arg)
+static int dma_ioctl(int dev, unsigned int cmd, void __user *arg)
 {
 	struct dma_buffparms *dmap_out = audio_devs[dev]->dmap_out;
 	struct dma_buffparms *dmap_in = audio_devs[dev]->dmap_in;
diff -Nru a/sound/oss/audio_syms.c b/sound/oss/audio_syms.c
--- a/sound/oss/audio_syms.c	2004-10-28 22:25:57 -07:00
+++ b/sound/oss/audio_syms.c	2004-10-28 22:25:57 -07:00
@@ -14,6 +14,3 @@
 EXPORT_SYMBOL(DMAbuf_close_dma);
 EXPORT_SYMBOL(DMAbuf_inputintr);
 EXPORT_SYMBOL(DMAbuf_outputintr);
-EXPORT_SYMBOL(dma_ioctl);
-EXPORT_SYMBOL(audio_open);
-EXPORT_SYMBOL(audio_release);
diff -Nru a/sound/oss/dev_table.c b/sound/oss/dev_table.c
--- a/sound/oss/dev_table.c	2004-10-28 22:25:59 -07:00
+++ b/sound/oss/dev_table.c	2004-10-28 22:25:59 -07:00
@@ -16,6 +16,8 @@
 #define _DEV_TABLE_C_
 #include "sound_config.h"
 
+static int sound_alloc_audiodev(void);
+
 int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
 			int driver_size, int flags, unsigned int format_mask,
 			void *devc, int dma1, int dma2)
@@ -121,7 +123,7 @@
 	}
 }
 
-int sound_alloc_audiodev(void)
+static int sound_alloc_audiodev(void)
 { 
 	int i = register_sound_dsp(&oss_sound_fops, -1);
 	if(i==-1)
diff -Nru a/sound/oss/dev_table.h b/sound/oss/dev_table.h
--- a/sound/oss/dev_table.h	2004-10-28 22:25:58 -07:00
+++ b/sound/oss/dev_table.h	2004-10-28 22:25:58 -07:00
@@ -397,7 +397,6 @@
 void sound_unload_mididev(int dev);
 void sound_unload_synthdev(int dev);
 void sound_unload_timerdev(int dev);
-int sound_alloc_audiodev(void);
 int sound_alloc_mixerdev(void);
 int sound_alloc_timerdev(void);
 int sound_alloc_synthdev(void);
diff -Nru a/sound/oss/msnd.c b/sound/oss/msnd.c
--- a/sound/oss/msnd.c	2004-10-28 22:25:57 -07:00
+++ b/sound/oss/msnd.c	2004-10-28 22:25:57 -07:00
@@ -33,6 +33,8 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/spinlock.h>
@@ -79,25 +81,6 @@
 	--num_devs;
 }
 
-int msnd_get_num_devs(void)
-{
-	return num_devs;
-}
-
-multisound_dev_t *msnd_get_dev(int j)
-{
-	int i;
-
-	for (i = 0; i < MSND_MAX_DEVS && j; ++i)
-		if (devs[i] != NULL)
-			--j;
-
-	if (i == MSND_MAX_DEVS || j != 0)
-		return NULL;
-
-	return devs[i];
-}
-
 void msnd_init_queue(unsigned long base, int start, int size)
 {
 	isa_writew(PCTODSP_BASED(start), base + JQS_wStart);
@@ -201,7 +184,7 @@
 	return count;
 }
 
-int msnd_wait_TXDE(multisound_dev_t *dev)
+static int msnd_wait_TXDE(multisound_dev_t *dev)
 {
 	register unsigned int io = dev->io;
 	register int timeout = 1000;
@@ -213,7 +196,7 @@
 	return -EIO;
 }
 
-int msnd_wait_HC0(multisound_dev_t *dev)
+static int msnd_wait_HC0(multisound_dev_t *dev)
 {
 	register unsigned int io = dev->io;
 	register int timeout = 1000;
@@ -337,8 +320,6 @@
 #ifndef LINUX20
 EXPORT_SYMBOL(msnd_register);
 EXPORT_SYMBOL(msnd_unregister);
-EXPORT_SYMBOL(msnd_get_num_devs);
-EXPORT_SYMBOL(msnd_get_dev);
 
 EXPORT_SYMBOL(msnd_init_queue);
 
@@ -349,8 +330,6 @@
 EXPORT_SYMBOL(msnd_fifo_write);
 EXPORT_SYMBOL(msnd_fifo_read);
 
-EXPORT_SYMBOL(msnd_wait_TXDE);
-EXPORT_SYMBOL(msnd_wait_HC0);
 EXPORT_SYMBOL(msnd_send_dsp_cmd);
 EXPORT_SYMBOL(msnd_send_word);
 EXPORT_SYMBOL(msnd_upload_host);
diff -Nru a/sound/oss/msnd.h b/sound/oss/msnd.h
--- a/sound/oss/msnd.h	2004-10-28 22:25:58 -07:00
+++ b/sound/oss/msnd.h	2004-10-28 22:25:58 -07:00
@@ -258,8 +258,6 @@
 
 int				msnd_register(multisound_dev_t *dev);
 void				msnd_unregister(multisound_dev_t *dev);
-int				msnd_get_num_devs(void);
-multisound_dev_t *		msnd_get_dev(int i);
 
 void				msnd_init_queue(unsigned long, int start, int size);
 
@@ -270,8 +268,6 @@
 int				msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len);
 int				msnd_fifo_read(msnd_fifo *f, char *buf, size_t len);
 
-int				msnd_wait_TXDE(multisound_dev_t *dev);
-int				msnd_wait_HC0(multisound_dev_t *dev);
 int				msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd);
 int				msnd_send_word(multisound_dev_t *dev, unsigned char high,
 					       unsigned char mid, unsigned char low);
diff -Nru a/sound/oss/sound_calls.h b/sound/oss/sound_calls.h
--- a/sound/oss/sound_calls.h	2004-10-28 22:25:58 -07:00
+++ b/sound/oss/sound_calls.h	2004-10-28 22:25:58 -07:00
@@ -39,7 +39,6 @@
 	   unsigned int cmd, void __user *arg);
 void audio_init_devices (void);
 void reorganize_buffers (int dev, struct dma_buffparms *dmap, int recording);
-int dma_ioctl (int dev, unsigned int cmd, void __user *arg);
 
 /*
  *	System calls for the /dev/sequencer
diff -Nru a/sound/oss/sound_syms.c b/sound/oss/sound_syms.c
--- a/sound/oss/sound_syms.c	2004-10-28 22:25:59 -07:00
+++ b/sound/oss/sound_syms.c	2004-10-28 22:25:59 -07:00
@@ -22,10 +22,8 @@
 EXPORT_SYMBOL(midi_devs);
 EXPORT_SYMBOL(num_midis);
 EXPORT_SYMBOL(synth_devs);
-EXPORT_SYMBOL(num_synths);
 
 EXPORT_SYMBOL(sound_timer_devs);
-EXPORT_SYMBOL(num_sound_timers);
 
 EXPORT_SYMBOL(sound_install_audiodrv);
 EXPORT_SYMBOL(sound_install_mixer);
@@ -33,7 +31,6 @@
 EXPORT_SYMBOL(sound_free_dma);
 EXPORT_SYMBOL(sound_open_dma);
 EXPORT_SYMBOL(sound_close_dma);
-EXPORT_SYMBOL(sound_alloc_audiodev);
 EXPORT_SYMBOL(sound_alloc_mididev);
 EXPORT_SYMBOL(sound_alloc_mixerdev);
 EXPORT_SYMBOL(sound_alloc_timerdev);
diff -Nru a/sound/pci/Kconfig b/sound/pci/Kconfig
--- a/sound/pci/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/Kconfig	2004-10-28 22:25:57 -07:00
@@ -8,27 +8,41 @@
 	select SND_PCM
 
 config SND_ALI5451
-	tristate "ALi PCI Audio M5451"
+	tristate "ALi M5451 PCI Audio Controller"
 	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ALI PCI Audio M5451 sound core.
+	  Say Y here to include support for the integrated AC97 sound
+	  device on motherboards using the ALi M5451 Audio Controller
+	  (M1535/M1535D/M1535+/M1535D+ south bridges).  Newer chipsets
+	  use the "Intel/SiS/nVidia/AMD/ALi AC97 Controller" driver.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ali5451.
 
 config SND_ATIIXP
-	tristate "ATI IXP 150/200/250/300"
+	tristate "ATI IXP AC97 Controller"
 	depends on SND
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ATI IXP 150/200/250/300 AC97 controller.
+	  Say Y here to include support for the integrated AC97 sound
+	  device on motherboards with ATI chipsets (ATI IXP 150/200/250/
+	  300/400).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-atiixp.
 
 config SND_ATIIXP_MODEM
-	tristate "ATI IXP 150/200/250 Modem"
+	tristate "ATI IXP Modem"
 	depends on SND
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ATI IXP 150/200/250 AC97 modem
-	  controller.
+	  Say Y here to include support for the integrated MC97 modem on
+	  motherboards with ATI chipsets (ATI IXP 150/200/250).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-atiixp-modem.
 
 config SND_AU8810
         tristate "Aureal Advantage"
@@ -36,10 +50,14 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
         help
-          Say 'Y' or 'M' to include support for Aureal Advantage soundcards.
-          Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
+	  Say Y here to include support for Aureal Advantage soundcards.
+
+	  Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
           3D support code is in place, but not yet useable. For more info, 
           email the ALSA developer list, or mjander@users.sourceforge.net.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-au8810.
  
 config SND_AU8820
         tristate "Aureal Vortex"
@@ -47,9 +65,13 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
         help
-          Say 'Y' or 'M' to include support for Aureal Vortex soundcards.
+	  Say Y here to include support for Aureal Vortex soundcards.
+
           Supported features: Hardware Mixer and SRC. For more info, email 
           the ALSA developer list, or mjander@users.sourceforge.net.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-au8820.
  
 config SND_AU8830
         tristate "Aureal Vortex 2"
@@ -57,10 +79,14 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
         help
-          Say 'Y' or 'M' to include support for Aureal Vortex 2 soundcards.
+	  Say Y here to include support for Aureal Vortex 2 soundcards.
+
           Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
           3D support code is in place, but not yet useable. For more info, 
           email the ALSA developer list, or mjander@users.sourceforge.net.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-au8830.
  
 config SND_AZT3328
 	tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
@@ -69,15 +95,32 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Aztech AZF3328 (PCI168) soundcards.
+	  Say Y here to include support for Aztech AZF3328 (PCI168)
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-azt3328.
 
 config SND_BT87X
         tristate "Bt87x Audio Capture"
         depends on SND
 	select SND_PCM
         help
-          Say 'Y' or 'M' to include support for recording audio from TV cards
-          based on Brooktree Bt878/Bt879 chips.
+	  Say Y here to include support for recording audio from TV
+	  cards based on Brooktree Bt878/Bt879 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-bt87x.
+
+config SND_BT87X_OVERCLOCK
+	bool "Bt87x Audio overclocking"
+	depends on SND_BT87X
+	help
+	  Say Y here if 448000 Hz isn't enough for you and you want to
+	  record from the analog input with up to 1792000 Hz.
+
+	  Higher sample rates won't hurt your hardware, but audio
+	  quality may suffer.
 
 config SND_CS46XX
 	tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
@@ -85,14 +128,19 @@
 	select SND_RAWMIDI
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Cirrus Logic CS4610 / CS4612 /
-	  CS4614 / CS4615 / CS4622 / CS4624 / CS4630 / CS4280 chips.
+	  Say Y here to include support for Cirrus Logic CS4610/CS4612/
+	  CS4614/CS4615/CS4622/CS4624/CS4630/CS4280 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-cs46xx.
 
 config SND_CS46XX_NEW_DSP
 	bool "Cirrus Logic (Sound Fusion) New DSP support (EXPERIMENTAL)"
 	depends on SND_CS46XX && EXPERIMENTAL
 	help
-	  Say 'Y' to use a new DSP image for SPDIF and dual codecs.
+	  Say Y here to use a new DSP image for SPDIF and dual codecs.
+
+	  This works better than the old code, so say Y.
 
 config SND_CS4281
 	tristate "Cirrus Logic (Sound Fusion) CS4281"
@@ -101,24 +149,37 @@
 	select SND_RAWMIDI
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Cirrus Logic CS4281.
+	  Say Y here to include support for Cirrus Logic CS4281 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-cs4281.
 
 config SND_EMU10K1
-	tristate "EMU10K1 (SB Live! & Audigy, E-mu APS)"
+	tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
 	depends on SND
 	select SND_HWDEP
 	select SND_RAWMIDI
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Sound Blaster PCI 512, Live!,
-	  Audigy and E-mu APS (partially supported).
+	  Say Y to include support for Sound Blaster PCI 512, Live!,
+	  Audigy and E-mu APS (partially supported) soundcards.
+
+	  The confusing multitude of mixer controls is documented in
+	  <file:Documentation/sound/alsa/SB-Live-mixer.txt> and
+	  <file:Documentation/sound/alsa/Audigy-mixer.txt>.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-emu10k1.
 
 config SND_KORG1212
 	tristate "Korg 1212 IO"
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Korg 1212IO.
+	  Say Y here to include support for Korg 1212IO soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-korg1212.
 
 config SND_MIXART
 	tristate "Digigram miXart"
@@ -126,38 +187,55 @@
 	select SND_HWDEP
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Digigram miXart soundcard.
+	  If you want to use Digigram miXart soundcards, say Y here and
+	  read <file:Documentation/sound/alsa/MIXART.txt>.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-mixart.
 
 config SND_NM256
 	tristate "NeoMagic NM256AV/ZX"
 	depends on SND
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for NeoMagic NM256AV/ZX chips.
+	  Say Y here to include support for NeoMagic NM256AV/ZX chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-nm256.
 
 config SND_RME32
 	tristate "RME Digi32, 32/8, 32 PRO"
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for RME Digi32, Digi32 PRO and
-	  Digi32/8 (Sek'd Prodif32, Prodif96 and Prodif Gold) audio devices.
+	  Say Y to include support for RME Digi32, Digi32 PRO and
+	  Digi32/8 (Sek'd Prodif32, Prodif96 and Prodif Gold) audio
+	  devices.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-rme32.
 
 config SND_RME96
 	tristate "RME Digi96, 96/8, 96/8 PRO"
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for RME Digi96, Digi96/8 and
-	  Digi96/8 PRO/PAD/PST.
+	  Say Y here to include support for RME Digi96, Digi96/8 and
+	  Digi96/8 PRO/PAD/PST soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-rme96.
 
 config SND_RME9652
 	tristate "RME Digi9652 (Hammerfall)"
 	depends on SND
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for RME Hammerfall (RME Digi9652 /
-	  Digi9636) soundcards.
+	  Say Y here to include support for RME Hammerfall (RME
+	  Digi9652/Digi9636) soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-rme9652.
 
 config SND_HDSP
 	tristate "RME Hammerfall DSP Audio"
@@ -166,17 +244,23 @@
 	select SND_RAWMIDI
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for RME Hammerfall DSP Audio
+	  Say Y here to include support for RME Hammerfall DSP Audio
 	  soundcards.
 
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-hdsp.
+
 config SND_TRIDENT
 	tristate "Trident 4D-Wave DX/NX; SiS 7018"
 	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Trident 4D-Wave DX/NX and
-	  SiS 7018 soundcards.
+	  Say Y here to include support for soundcards based on Trident
+	  4D-Wave DX/NX or SiS 7018 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-trident.
 
 config SND_YMFPCI
 	tristate "Yamaha YMF724/740/744/754"
@@ -185,9 +269,12 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Yamaha PCI audio chips - 
+	  Say Y here to include support for Yamaha PCI audio chips -
 	  YMF724, YMF724F, YMF740, YMF740C, YMF744, YMF754.
 
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ymfpci.
+
 config SND_ALS4000
 	tristate "Avance Logic ALS4000"
 	depends on SND
@@ -195,7 +282,11 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Avance Logic ALS4000.
+	  Say Y here to include support for soundcards based on Avance Logic
+	  ALS4000 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-als4000.
 
 config SND_CMIPCI
 	tristate "C-Media 8738, 8338"
@@ -204,8 +295,12 @@
 	select SND_MPU401_UART
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for C-Media CMI8338 and 8738 PCI
-	  soundcards.
+	  If you want to use soundcards based on C-Media CMI8338 or CMI8738
+	  chips, say Y here and read
+	  <file:Documentation/sound/alsa/CMIPCI.txt>.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-cmipci.
 
 config SND_ENS1370
 	tristate "(Creative) Ensoniq AudioPCI 1370"
@@ -213,7 +308,10 @@
 	select SND_RAWMIDI
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1370.
+	  Say Y here to include support for Ensoniq AudioPCI ES1370 chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ens1370.
 
 config SND_ENS1371
 	tristate "(Creative) Ensoniq AudioPCI 1371/1373"
@@ -221,9 +319,12 @@
 	select SND_RAWMIDI
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Ensoniq AudioPCI ES1371 and
+	  Say Y here to include support for Ensoniq AudioPCI ES1371 chips and
 	  Sound Blaster PCI 64 or 128 soundcards.
 
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ens1371.
+
 config SND_ES1938
 	tristate "ESS ES1938/1946/1969 (Solo-1)"
 	depends on SND
@@ -231,8 +332,11 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ESS Solo-1 (ES1938, ES1946, ES1969)
-	  soundcard.
+	  Say Y here to include support for soundcards based on ESS Solo-1
+	  (ES1938, ES1946, ES1969) chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-es1938.
 
 config SND_ES1968
 	tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
@@ -240,14 +344,22 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ESS Maestro 1/2/2E.
+	  Say Y here to include support for soundcards based on ESS Maestro
+	  1/2/2E chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-es1968.
 
 config SND_MAESTRO3
 	tristate "ESS Allegro/Maestro3"
 	depends on SND
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ESS Maestro 3 (Allegro) soundcard.
+	  Say Y here to include support for soundcards based on ESS Maestro 3
+	  (Allegro) chips.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-maestro3.
 
 config SND_FM801
 	tristate "ForteMedia FM801"
@@ -256,15 +368,23 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ForteMedia FM801 based soundcards.
+	  Say Y here to include support for soundcards based on the ForteMedia
+	  FM801 chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-fm801.
 
 config SND_FM801_TEA575X
 	tristate "ForteMedia FM801 + TEA5757 tuner"
 	depends on SND_FM801
         select VIDEO_DEV
 	help
-	  Say 'Y' or 'M' to include support for ForteMedia FM801 based soundcards
-          with TEA5757 tuner connected to GPIO1-3 pins (Media Forte SF256-PCS-02).
+	  Say Y here to include support for soundcards based on the ForteMedia
+	  FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media
+	  Forte SF256-PCS-02).
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-fm801-tea575x.
 
 config SND_ICE1712
 	tristate "ICEnsemble ICE1712 (Envy24)"
@@ -272,10 +392,16 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ICE1712 (Envy24) based soundcards.
-	  Currently supported hardware is: MidiMan M Audio - Delta 1010(LT), Dio 2496,
-	  Delta 66/44, Audiophile 24/96; Hoontech SoundTrack DSP 24 (Value);
-	  TerraTec - EWX 24/96, EWS 88MT, EWS 88D, DMX 6Fire.
+	  Say Y here to include support for soundcards based on the
+	  ICE1712 (Envy24) chip.
+
+	  Currently supported hardware is: M-Audio Delta 1010(LT),
+	  DiO 2496, 66, 44, 410, Audiophile 24/96; Digigram VX442;
+	  TerraTec EWX 24/96, EWS 88MT, 88D, DMX 6Fire, Phase 88;
+	  Hoontech SoundTrack DSP 24/Value/Media7.1; Event EZ8.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ice1712.
 
 config SND_ICE1724
 	tristate "ICE/VT1724/1720 (Envy24HT/PT)"
@@ -283,27 +409,40 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for ICE/VT1724/1720 (Envy24HT/PT) based
-	  soundcards.
-	  Currently supported hardware is: MidiMan M Audio - Revolution 7.1,
-	  AMP Ltd AUDIO2000, Terratec Aureon 5.1 Sky/7.1, AudioTrak Prodigy 7.1.
+	  Say Y here to include support for soundcards based on
+	  ICE/VT1724/1720 (Envy24HT/PT) chips.
+
+	  Currently supported hardware is: AMP AUDIO2000; M-Audio
+	  Revolution 7.1; TerraTec Aureon 5.1 Sky, 7.1 Space/Universe;
+	  AudioTrak Prodigy 7.1; Pontis MS300; Albatron K8X800 Pro II;
+	  Chaintech ZNF3-150/250.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-ice1724.
 
 config SND_INTEL8X0
-	tristate "Intel i8x0/MX440, SiS 7012; Ali 5455; NForce Audio; AMD768/8111"
+	tristate "Intel/SiS/nVidia/AMD/ALi AC97 Controller"
 	depends on SND
-	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Intel8x0 based soundcards,
-	  SiS 7012, AMD768/8111, NVidia NForce and ALi 5455 chips.
+	  Say Y here to include support for the integrated AC97 sound
+	  device on motherboards with Intel/SiS/nVidia/AMD chipsets, or
+	  ALi chipsets using the M5455 Audio Controller.  (There is a
+	  separate driver for ALi M5451 Audio Controllers.)
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-intel8x0.
 
 config SND_INTEL8X0M
-	tristate "Intel i8x0/MX440; SiS 7013; NForce; AMD768/8111 modems (EXPERIMENTAL)"
+	tristate "Intel/SiS/nVidia/AMD MC97 Modem (EXPERIMENTAL)"
 	depends on SND && EXPERIMENTAL
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Intel8x0, SiS 7013, NVidia NForce
-          and AMD768/8111 based modems.
+	  Say Y here to include support for the integrated MC97 modem on
+	  motherboards with Intel/SiS/nVidia/AMD chipsets.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-intel8x0m.
 
 config SND_SONICVIBES
 	tristate "S3 SonicVibes"
@@ -312,22 +451,33 @@
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for S3 SonicVibes based soundcards.
+	  Say Y here to include support for soundcards based on the S3
+	  SonicVibes chip.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-sonicvibes.
 
 config SND_VIA82XX
-	tristate "VIA 82C686A/B, 8233 South Bridge"
+	tristate "VIA 82C686A/B, 8233/8235 AC97 Controller"
 	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for VIA VT82C686A/B, VT8233 South Bridge.
+	  Say Y here to include support for the integrated AC97 sound
+	  device on motherboards with VIA chipsets.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-via82xx.
 
 config SND_VX222
 	tristate "Digigram VX222"
 	depends on SND
 	select SND_VX_LIB
 	help
-	  Say 'Y' or 'M' to include support for Digigram VX222 soundcards.
+	  Say Y here to include support for Digigram VX222 soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-vx222.
 
 endmenu
 
diff -Nru a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile
--- a/sound/pci/ac97/Makefile	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/ac97/Makefile	2004-10-28 22:25:58 -07:00
@@ -3,7 +3,12 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o ac97_proc.o ac97_patch.o
+snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o ac97_patch.o
+
+ifneq ($(CONFIG_PROC_FS),)
+snd-ac97-codec-objs += ac97_proc.o
+endif
+
 snd-ak4531-codec-objs := ak4531_codec.o
 
 # Toplevel Module Dependency
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/ac97/ac97_codec.c	2004-10-28 22:25:57 -07:00
@@ -118,9 +118,12 @@
 { 0x414c4770, 0xfffffff0, "ALC203",		NULL,		NULL },
 { 0x434d4941, 0xffffffff, "CMI9738",		patch_cm9738,	NULL },
 { 0x434d4961, 0xffffffff, "CMI9739",		patch_cm9739,	NULL },
+{ 0x434d4978, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
+{ 0x434d4982, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
+{ 0x434d4983, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
 { 0x43525900, 0xfffffff8, "CS4297",		NULL,		NULL },
 { 0x43525910, 0xfffffff8, "CS4297A",		patch_cirrus_spdif,	NULL },
-{ 0x43525920, 0xfffffff8, "CS4294/4298",	NULL,		NULL },
+{ 0x43525920, 0xfffffff8, "CS4298",		patch_cirrus_spdif,		NULL },
 { 0x43525928, 0xfffffff8, "CS4294",		NULL,		NULL },
 { 0x43525930, 0xfffffff8, "CS4299",		patch_cirrus_cs4299,	NULL },
 { 0x43525948, 0xfffffff8, "CS4201",		NULL,		NULL },
@@ -749,6 +752,14 @@
 static const snd_kcontrol_new_t snd_ac97_control_eapd =
 AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
 
+/* change the existing EAPD control as inverted */
+static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl)
+{
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_POWERDOWN, 15, 1, 0);
+	snd_ac97_update_bits(ac97, AC97_POWERDOWN, (1<<15), (1<<15)); /* EAPD up */
+	ac97->scaps |= AC97_SCAP_INV_EAPD;
+}
+
 static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -1559,7 +1570,7 @@
 			return err;
 	}
 
-	snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0x0000);
+	snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, ~AC97_GP_DRSS_MASK, 0x0000);
 
 	/* build 3D controls */
 	if (ac97->build_ops && ac97->build_ops->build_3d) {
@@ -1610,7 +1621,12 @@
 			return err;
 
 	if (snd_ac97_try_bit(ac97, AC97_POWERDOWN, 15)) {
-		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_eapd, ac97))) < 0)
+		kctl = snd_ac97_cnew(&snd_ac97_control_eapd, ac97);
+		if (! kctl)
+			return -ENOMEM;
+		if (ac97->scaps & AC97_SCAP_INV_EAPD)
+			set_inv_eapd(ac97, kctl);
+		if ((err = snd_ctl_add(card, kctl)) < 0)
 			return err;
 	}
 
@@ -1646,6 +1662,9 @@
 {
 	unsigned int result = 0;
 
+	if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE)
+		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
+				     AC97_EA_DRA, 0);
 	/* test a non-standard rate */
 	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 11000))
 		result |= SNDRV_PCM_RATE_CONTINUOUS;
@@ -1664,6 +1683,23 @@
 		result |= SNDRV_PCM_RATE_44100;
 	if (snd_ac97_test_rate(ac97, reg, shadow_reg, 48000))
 		result |= SNDRV_PCM_RATE_48000;
+	if ((ac97->flags & AC97_DOUBLE_RATE) &&
+	    reg == AC97_PCM_FRONT_DAC_RATE) {
+		/* test standard double rates */
+		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
+				     AC97_EA_DRA, AC97_EA_DRA);
+		if (snd_ac97_test_rate(ac97, reg, shadow_reg, 64000 / 2))
+			result |= SNDRV_PCM_RATE_64000;
+		if (snd_ac97_test_rate(ac97, reg, shadow_reg, 88200 / 2))
+			result |= SNDRV_PCM_RATE_88200;
+		if (snd_ac97_test_rate(ac97, reg, shadow_reg, 96000 / 2))
+			result |= SNDRV_PCM_RATE_96000;
+		/* some codecs don't support variable double rates */
+		if (!snd_ac97_test_rate(ac97, reg, shadow_reg, 76100 / 2))
+			result &= ~SNDRV_PCM_RATE_CONTINUOUS;
+		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
+				     AC97_EA_DRA, 0);
+	}
 	*r_result = result;
 }
 
@@ -1726,6 +1762,22 @@
 	sprintf(name + strlen(name), " id %x", id & 0xff);
 }
 
+/**
+ * snd_ac97_get_short_name - retrieve codec name
+ * @ac97: the codec instance
+ *
+ * Returns the short identifying name of the codec.
+ */
+const char *snd_ac97_get_short_name(ac97_t *ac97)
+{
+	const ac97_codec_id_t *pid;
+
+	for (pid = snd_ac97_codec_ids; pid->id; pid++)
+		if (pid->id == (ac97->id & pid->mask))
+			return pid->name;
+	return "unknown codec";
+}
+
 
 /* wait for a while until registers are accessible after RESET
  * return 0 if ok, negative not ready
@@ -1733,9 +1785,10 @@
 static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
 {
 	unsigned long end_time;
+	unsigned short val;
+
 	end_time = jiffies + timeout;
 	do {
-		unsigned short ext_mid;
 		
 		/* use preliminary reads to settle the communication */
 		snd_ac97_read(ac97, AC97_RESET);
@@ -1743,17 +1796,24 @@
 		snd_ac97_read(ac97, AC97_VENDOR_ID2);
 		/* modem? */
 		if (with_modem) {
-			ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
-			if (ext_mid != 0xffff && (ext_mid & 1) != 0)
+			val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+			if (val != 0xffff && (val & 1) != 0)
+				return 0;
+		}
+		if (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) {
+			/* probably only Xbox issue - all registers are read as zero */
+			val = snd_ac97_read(ac97, AC97_VENDOR_ID1);
+			if (val != 0 && val != 0xffff)
+				return 0;
+		} else {
+			/* because the PCM or MASTER volume registers can be modified,
+			 * the REC_GAIN register is used for tests
+			 */
+			/* test if we can write to the record gain volume register */
+			snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
+			if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05)
 				return 0;
 		}
-		/* because the PCM or MASTER volume registers can be modified,
-		 * the REC_GAIN register is used for tests
-		 */
-		/* test if we can write to the record gain volume register */
-		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
-		if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05)
-			return 0;
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(1);
 	} while (time_after_eq(end_time, jiffies));
@@ -2004,13 +2064,25 @@
 		ac97->addr = (ac97->ext_id & AC97_EI_ADDR_MASK) >> AC97_EI_ADDR_SHIFT;
 	else
 		ac97->addr = (ac97->ext_mid & AC97_MEI_ADDR_MASK) >> AC97_MEI_ADDR_SHIFT;
-	if (ac97->ext_id & 0x0189)	/* L/R, MIC, SDAC, LDAC VRA support */
-		snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, ac97->ext_id & 0x0189);
+	if (ac97->ext_id & 0x0189) {	/* L/R, MIC, SDAC, LDAC VRA support */
+		reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS);
+		reg |= ac97->ext_id & 0x0189;
+		snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, reg);
+	}
+	if ((ac97->ext_id & AC97_EI_DRA) && bus->dra) {
+		/* Intel controllers require double rate data to be put in
+		 * slots 7+8, so let's hope the codec supports it. */
+		snd_ac97_update_bits(ac97, AC97_GENERAL_PURPOSE, AC97_GP_DRSS_MASK, AC97_GP_DRSS_78);
+		if ((snd_ac97_read(ac97, AC97_GENERAL_PURPOSE) & AC97_GP_DRSS_MASK) == AC97_GP_DRSS_78)
+			ac97->flags |= AC97_DOUBLE_RATE;
+	}
 	if (ac97->ext_id & AC97_EI_VRA) {	/* VRA support */
 		snd_ac97_determine_rates(ac97, AC97_PCM_FRONT_DAC_RATE, 0, &ac97->rates[AC97_RATES_FRONT_DAC]);
 		snd_ac97_determine_rates(ac97, AC97_PCM_LR_ADC_RATE, 0, &ac97->rates[AC97_RATES_ADC]);
 	} else {
 		ac97->rates[AC97_RATES_FRONT_DAC] = SNDRV_PCM_RATE_48000;
+		if (ac97->flags & AC97_DOUBLE_RATE)
+			ac97->rates[AC97_RATES_FRONT_DAC] |= SNDRV_PCM_RATE_96000;
 		ac97->rates[AC97_RATES_ADC] = SNDRV_PCM_RATE_48000;
 	}
 	if (ac97->ext_id & AC97_EI_SPDIF) {
@@ -2317,9 +2389,9 @@
 
 static int swap_headphone(ac97_t *ac97, int remove_master)
 {
+	if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
+		return -ENOENT;
 	if (remove_master) {
-		if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
-			return 0;
 		snd_ac97_remove_ctl(ac97, "Master Playback", "Switch");
 		snd_ac97_remove_ctl(ac97, "Master Playback", "Volume");
 	} else
@@ -2330,9 +2402,9 @@
 
 static int swap_surround(ac97_t *ac97)
 {
-	/* FIXME: error checks.. */
-	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch");
-	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume");
+	if (snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch") ||
+	    snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume"))
+		return -ENOENT;
 	return 0;
 }
 
@@ -2363,6 +2435,15 @@
 	return snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_alc_jack_detect, ac97));
 }
 
+static int tune_inv_eapd(ac97_t *ac97)
+{
+	snd_kcontrol_t *kctl = ctl_find(ac97, "External Amplifier", NULL);
+	if (! kctl)
+		return -ENOENT;
+	set_inv_eapd(ac97, kctl);
+	return 0;
+}
+
 static int apply_quirk(ac97_t *ac97, int quirk)
 {
 	switch (quirk) {
@@ -2378,6 +2459,8 @@
 		return tune_ad_sharing(ac97);
 	case AC97_TUNE_ALC_JACK:
 		return tune_alc_jack(ac97);
+	case AC97_TUNE_INV_EAPD:
+		return tune_inv_eapd(ac97);
 	}
 	return -EINVAL;
 }
@@ -2413,6 +2496,8 @@
 			continue;
 		if ((! quirk->mask && quirk->device == ac97->subsystem_device) ||
 		    quirk->device == (quirk->mask & ac97->subsystem_device)) {
+			if (quirk->codec_id && quirk->codec_id != ac97->id)
+				continue;
 			snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device);
 			result = apply_quirk(ac97, quirk->type);
 			if (result < 0)
@@ -2433,11 +2518,13 @@
 EXPORT_SYMBOL(snd_ac97_write_cache);
 EXPORT_SYMBOL(snd_ac97_update);
 EXPORT_SYMBOL(snd_ac97_update_bits);
+EXPORT_SYMBOL(snd_ac97_get_short_name);
 EXPORT_SYMBOL(snd_ac97_bus);
 EXPORT_SYMBOL(snd_ac97_mixer);
 EXPORT_SYMBOL(snd_ac97_pcm_assign);
 EXPORT_SYMBOL(snd_ac97_pcm_open);
 EXPORT_SYMBOL(snd_ac97_pcm_close);
+EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules);
 EXPORT_SYMBOL(snd_ac97_tune_hardware);
 EXPORT_SYMBOL(snd_ac97_set_rate);
 #ifdef CONFIG_PM
diff -Nru a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
--- a/sound/pci/ac97/ac97_id.h	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/ac97/ac97_id.h	2004-10-28 22:25:59 -07:00
@@ -57,3 +57,6 @@
 #define AC97_ID_VT1616		0x49434551
 #define AC97_ID_CM9738		0x434d4941
 #define AC97_ID_CM9739		0x434d4961
+#define AC97_ID_CM9761_78	0x434d4978
+#define AC97_ID_CM9761_82	0x434d4982
+#define AC97_ID_CM9761_83	0x434d4983
diff -Nru a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
--- a/sound/pci/ac97/ac97_local.h	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/ac97/ac97_local.h	2004-10-28 22:25:57 -07:00
@@ -51,7 +51,14 @@
 void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
 
 /* ac97_proc.c */
+#ifdef CONFIG_PROC_FS
 void snd_ac97_bus_proc_init(ac97_bus_t * ac97);
 void snd_ac97_bus_proc_done(ac97_bus_t * ac97);
 void snd_ac97_proc_init(ac97_t * ac97);
 void snd_ac97_proc_done(ac97_t * ac97);
+#else
+#define snd_ac97_bus_proc_init(ac97_bus_t) do { } while (0)
+#define snd_ac97_bus_proc_done(ac97_bus_t) do { } while (0)
+#define snd_ac97_proc_init(ac97_t) do { } while (0)
+#define snd_ac97_proc_done(ac97_t) do { } while (0)
+#endif
diff -Nru a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
--- a/sound/pci/ac97/ac97_patch.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/ac97/ac97_patch.c	2004-10-28 22:25:59 -07:00
@@ -1779,6 +1779,140 @@
 	return 0;
 }
 
+#define AC97_CM9761_MULTI_CHAN	0x64
+#define AC97_CM9761_SPDIF_CTRL	0x6c
+
+static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400)
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+	return 0;
+}
+
+static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short vals[2][2] = {
+		{ 0x0008, 0x0400 }, /* off, on */
+		{ 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
+	};
+	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408,
+				    vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
+}
+
+static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+	if (ac97->spec.dev_flags) /* 9761-82 rev.B */
+		ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned short vals[2][2] = {
+		{ 0x2000, 0x1880 }, /* off, on */
+		{ 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
+	};
+	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880,
+				    vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
+}
+
+static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Line-In As Surround",
+		.info = snd_ac97_info_single,
+		.get = snd_ac97_cm9761_linein_rear_get,
+		.put = snd_ac97_cm9761_linein_rear_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Mic As Center/LFE",
+		.info = snd_ac97_info_single,
+		.get = snd_ac97_cm9761_center_mic_get,
+		.put = snd_ac97_cm9761_center_mic_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+};
+
+static int patch_cm9761_specific(ac97_t * ac97)
+{
+	return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
+}
+
+static struct snd_ac97_build_ops patch_cm9761_ops = {
+	.build_specific	= patch_cm9761_specific,
+	.build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */
+};
+
+int patch_cm9761(ac97_t *ac97)
+{
+	unsigned short val;
+
+	ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */
+	if (ac97->id == AC97_ID_CM9761_82) {
+		unsigned short tmp;
+		/* check page 1, reg 0x60 */
+		val = snd_ac97_read(ac97, AC97_INT_PAGING);
+		snd_ac97_write_cache(ac97, AC97_INT_PAGING, (val & ~0x0f) | 0x01);
+		tmp = snd_ac97_read(ac97, 0x60);
+		ac97->spec.dev_flags = tmp & 1; /* revision B? */
+		snd_ac97_write_cache(ac97, AC97_INT_PAGING, val);
+	}
+
+	ac97->build_ops = &patch_cm9761_ops;
+
+	/* enable spdif */
+	/* force the SPDIF bit in ext_id - codec doesn't set this bit! */
+        ac97->ext_id |= AC97_EI_SPDIF;
+	/* to be sure: we overwrite the ext status bits */
+	snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
+	snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0209);
+	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
+
+	/* set-up multi channel */
+	/* bit 15: pc master beep off
+	 * bit 14: ??
+	 * bit 13: vref ctl [= cm9739]
+	 * bit 12: center/mic [= cm9739] (reverted on rev B)
+	 * bit 11: ?? (mic/center/lfe) (reverted on rev B)
+	 * bit 10: suddound/line [= cm9739]
+	 * bit  9: mix 2 surround
+	 * bit  8: ?
+	 * bit  7: ?? (mic/center/lfe)
+	 * bit  4: ?? (front)
+	 * bit  3: ?? (line-in/rear share) (revereted with rev B)
+	 * bit  2: ?? (surround)
+	 * bit  1: front mic
+	 * bit  0: mic boost
+	 */
+
+#if 0
+	if (ac97->spec.dev_flags)
+		val = 0x0214;
+	else
+		val = 0x321c;
+	snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
+#endif
+
+	/* FIXME: set up GPIO */
+	snd_ac97_write_cache(ac97, 0x70, 0x0100);
+	snd_ac97_write_cache(ac97, 0x72, 0x0020);
+
+	return 0;
+}
+       
+
 /*
  * VIA VT1616 codec
  */
diff -Nru a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
--- a/sound/pci/ac97/ac97_patch.h	2004-10-28 22:25:56 -07:00
+++ b/sound/pci/ac97/ac97_patch.h	2004-10-28 22:25:56 -07:00
@@ -52,6 +52,7 @@
 int patch_alc850(ac97_t * ac97);
 int patch_cm9738(ac97_t * ac97);
 int patch_cm9739(ac97_t * ac97);
+int patch_cm9761(ac97_t * ac97);
 int patch_vt1616(ac97_t * ac97);
 int patch_it2646(ac97_t * ac97);
 int mpatch_si3036(ac97_t * ac97);
diff -Nru a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
--- a/sound/pci/ac97/ac97_pcm.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/ac97/ac97_pcm.c	2004-10-28 22:25:57 -07:00
@@ -93,54 +93,52 @@
   },
 },
 {
-  /* FIXME: double rates */
+  /* double rates */
   {
-  	/* 3&4 front, 7&8 rear, 6&9 center/lfe */
+  	/* 3&4 front, 7&8 front (t+1) */
 	AC97_PCM_FRONT_DAC_RATE,	/* slot 3 */
 	AC97_PCM_FRONT_DAC_RATE,	/* slot 4 */
 	0xff,				/* slot 5 */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 6 */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 7 */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 8 */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 9 */
+	0xff,				/* slot 6 */
+	AC97_PCM_FRONT_DAC_RATE,	/* slot 7 */
+	AC97_PCM_FRONT_DAC_RATE,	/* slot 8 */
+	0xff,				/* slot 9 */
 	0xff,				/* slot 10 */
 	0xff,				/* slot 11 */
   },
   {
-  	/* 7&8 front, 6&9 rear, 10&11 center/lfe */
+	/* not specified in the specification */
 	0xff,				/* slot 3 */
 	0xff,				/* slot 4 */
 	0xff,				/* slot 5 */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 6 */
-	AC97_PCM_FRONT_DAC_RATE,	/* slot 7 */
-	AC97_PCM_FRONT_DAC_RATE,	/* slot 8 */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 9 */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 10 */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 11 */
+	0xff,				/* slot 6 */
+	0xff,				/* slot 7 */
+	0xff,				/* slot 8 */
+	0xff,				/* slot 9 */
+	0xff,				/* slot 10 */
+	0xff,				/* slot 11 */
   },
   {
-  	/* 6&9 front, 10&11 rear, 3&4 center/lfe */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 3 */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 4 */
+	0xff,				/* slot 3 */
+	0xff,				/* slot 4 */
 	0xff,				/* slot 5 */
-	AC97_PCM_FRONT_DAC_RATE,	/* slot 6 */
+	0xff,				/* slot 6 */
 	0xff,				/* slot 7 */
 	0xff,				/* slot 8 */
-	AC97_PCM_FRONT_DAC_RATE,	/* slot 9 */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 10 */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 11 */
+	0xff,				/* slot 9 */
+	0xff,				/* slot 10 */
+	0xff,				/* slot 11 */
   },
   {
-  	/* 10&11 front, 3&4 rear, 7&8 center/lfe */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 3 */
-	AC97_PCM_SURR_DAC_RATE,		/* slot 4 */
+	0xff,				/* slot 3 */
+	0xff,				/* slot 4 */
 	0xff,				/* slot 5 */
 	0xff,				/* slot 6 */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 7 */
-	AC97_PCM_LFE_DAC_RATE,		/* slot 8 */
+	0xff,				/* slot 7 */
+	0xff,				/* slot 8 */
 	0xff,				/* slot 9 */
-	AC97_PCM_FRONT_DAC_RATE,	/* slot 10 */
-	AC97_PCM_FRONT_DAC_RATE,	/* slot 11 */
+	0xff,				/* slot 10 */
+	0xff,				/* slot 11 */
   }
 }};
 
@@ -180,6 +178,7 @@
 	if (! (ac97->ext_id & AC97_EI_SPDIF))
 		return -ENODEV;
 
+	/* TODO: double rate support */
 	if (ac97->flags & AC97_CS_SPDIF) {
 		switch (rate) {
 		case 48000: bits = 0; break;
@@ -257,10 +256,19 @@
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned short rate)
+int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned int rate)
 {
+	int dbl;
 	unsigned int tmp;
 	
+	dbl = rate > 48000;
+	if (dbl) {
+		if (!(ac97->flags & AC97_DOUBLE_RATE))
+			return -EINVAL;
+		if (reg != AC97_PCM_FRONT_DAC_RATE)
+			return -EINVAL;
+	}
+
 	switch (reg) {
 	case AC97_PCM_MIC_ADC_RATE:
 		if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0)	/* MIC VRA */
@@ -270,7 +278,7 @@
 	case AC97_PCM_FRONT_DAC_RATE:
 	case AC97_PCM_LR_ADC_RATE:
 		if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRA) == 0)	/* VRA */
-			if (rate != 48000)
+			if (rate != 48000 && rate != 96000)
 				return -EINVAL;
 		break;
 	case AC97_PCM_SURR_DAC_RATE:
@@ -287,9 +295,14 @@
 	default:
 		return -EINVAL;
 	}
-	tmp = ((unsigned int)rate * ac97->bus->clock) / 48000;
+	if (dbl)
+		rate /= 2;
+	tmp = (rate * ac97->bus->clock) / 48000;
 	if (tmp > 65535)
 		return -EINVAL;
+	if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE)
+		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
+				     AC97_EA_DRA, dbl ? AC97_EA_DRA : 0);
 	snd_ac97_update(ac97, reg, tmp & 0xffff);
 	snd_ac97_read(ac97, reg);
 	return 0;
@@ -304,13 +317,13 @@
 		if (ac97_is_rev22(ac97)) {
 			/* Note: it's simply emulation of AMAP behaviour */
 			u16 es;
-			es = ac97->regs[AC97_EXTENDED_STATUS] &= ~AC97_EI_DACS_SLOT_MASK;
+			es = ac97->regs[AC97_EXTENDED_ID] &= ~AC97_EI_DACS_SLOT_MASK;
 			switch (ac97->addr) {
 			case 1:
 			case 2: es |= (1<<AC97_EI_DACS_SLOT_SHIFT); break;
 			case 3: es |= (2<<AC97_EI_DACS_SLOT_SHIFT); break;
 			}
-			snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, es);
+			snd_ac97_write_cache(ac97, AC97_EXTENDED_ID, es);
 		}
 		switch (ac97->addr) {
 		case 0:
@@ -401,6 +414,9 @@
 		}
 		rates &= pcm->r[dbl].codec[cidx]->rates[idx];
 	}
+	if (!dbl)
+		rates &= ~(SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 |
+			   SNDRV_PCM_RATE_96000);
 	return rates;
 }
 
@@ -447,7 +463,6 @@
 			}
 		}
 	}
-	/* FIXME: add double rate allocation */
 	/* first step - exclusive devices */
 	for (i = 0; i < pcms_count; i++) {
 		pcm = &pcms[i];
@@ -498,6 +513,26 @@
 			rpcm->r[0].slots |= tmp;
 			rpcm->rates &= rates;
 		}
+		/* for double rate, we check the first codec only */
+		if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+		    bus->codec[0] && (bus->codec[0]->flags & AC97_DOUBLE_RATE) &&
+		    rate_table[pcm->stream][0] == 0) {
+			tmp = (1<<AC97_SLOT_PCM_LEFT) | (1<<AC97_SLOT_PCM_RIGHT) |
+			      (1<<AC97_SLOT_PCM_LEFT_0) | (1<<AC97_SLOT_PCM_RIGHT_0);
+			if ((tmp & pcm->r[1].slots) == tmp) {
+				rpcm->r[1].slots = tmp;
+				rpcm->r[1].rslots[0] = tmp;
+				rpcm->r[1].rate_table[0] = 0;
+				rpcm->r[1].codec[0] = bus->codec[0];
+				if (pcm->exclusive)
+					avail_slots[pcm->stream][0] &= ~tmp;
+				if (bus->no_vra)
+					rates = SNDRV_PCM_RATE_96000;
+				else
+					rates = get_rates(rpcm, 0, tmp, 1);
+				rpcm->rates |= rates;
+			}
+		}
 		if (rpcm->rates == ~0)
 			rpcm->rates = 0; /* not used */
 	}
@@ -519,13 +554,12 @@
 		      enum ac97_pcm_cfg cfg, unsigned short slots)
 {
 	ac97_bus_t *bus;
-	int i, cidx, r = 0, ok_flag;
+	int i, cidx, r, ok_flag;
 	unsigned int reg_ok = 0;
 	unsigned char reg;
 	int err = 0;
 
-	if (rate > 48000)	/* FIXME: add support for double rate */
-		return -EINVAL;
+	r = rate > 48000;
 	bus = pcm->bus;
 	if (cfg == AC97_PCM_CFG_SPDIF) {
 		int err;
@@ -613,4 +647,56 @@
 	pcm->aslots = 0;
 	spin_unlock_irq(&pcm->bus->bus_lock);
 	return 0;
+}
+
+static int double_rate_hw_constraint_rate(snd_pcm_hw_params_t *params,
+					  snd_pcm_hw_rule_t *rule)
+{
+	snd_interval_t *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	if (channels->min > 2) {
+		static const snd_interval_t single_rates = {
+			.min = 1,
+			.max = 48000,
+		};
+		snd_interval_t *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+		return snd_interval_refine(rate, &single_rates);
+	}
+	return 0;
+}
+
+static int double_rate_hw_constraint_channels(snd_pcm_hw_params_t *params,
+					      snd_pcm_hw_rule_t *rule)
+{
+	snd_interval_t *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	if (rate->min > 48000) {
+		static const snd_interval_t double_rate_channels = {
+			.min = 2,
+			.max = 2,
+		};
+		snd_interval_t *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+		return snd_interval_refine(channels, &double_rate_channels);
+	}
+	return 0;
+}
+
+/**
+ * snd_ac97_pcm_double_rate_rules - set double rate constraints
+ * @runtime: the runtime of the ac97 front playback pcm
+ *
+ * Installs the hardware constraint rules to prevent using double rates and
+ * more than two channels at the same time.
+ */
+int snd_ac97_pcm_double_rate_rules(snd_pcm_runtime_t *runtime)
+{
+	int err;
+
+	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				  double_rate_hw_constraint_rate, NULL,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (err < 0)
+		return err;
+	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  double_rate_hw_constraint_channels, NULL,
+				  SNDRV_PCM_HW_PARAM_RATE, -1);
+	return err;
 }
diff -Nru a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
--- a/sound/pci/ac97/ac97_proc.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/ac97/ac97_proc.c	2004-10-28 22:25:59 -07:00
@@ -72,9 +72,10 @@
 {
 	char name[64];
 	unsigned short val, tmp, ext, mext;
-	static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=res" };
+	static const char *spdif_slots[4] = { " SPDIF=3/4", " SPDIF=7/8", " SPDIF=6/9", " SPDIF=10/11" };
 	static const char *spdif_rates[4] = { " Rate=44.1kHz", " Rate=res", " Rate=48kHz", " Rate=32kHz" };
 	static const char *spdif_rates_cs4205[4] = { " Rate=48kHz", " Rate=44.1kHz", " Rate=res", " Rate=res" };
+	static const char *double_rate_slots[4] = { "10/11", "7/8", "reserved", "reserved" };
 
 	snd_ac97_get_name(NULL, ac97->id, name, 0);
 	snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
@@ -137,6 +138,9 @@
 		    val & 0x0200 ? "Mic" : "MIX",
 		    val & 0x0100 ? "Mic2" : "Mic1",
 		    val & 0x0080 ? "on" : "off");
+	if (ac97->ext_id & AC97_EI_DRA)
+		snd_iprintf(buffer, "Double rate slots: %s\n",
+			    double_rate_slots[(val >> 10) & 3]);
 
 	ext = snd_ac97_read(ac97, AC97_EXTENDED_ID);
 	if (ext == 0)
diff -Nru a/sound/pci/atiixp.c b/sound/pci/atiixp.c
--- a/sound/pci/atiixp.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/atiixp.c	2004-10-28 22:25:58 -07:00
@@ -1515,7 +1515,7 @@
 	}
 	chip->addr = pci_resource_start(pci, 0);
 	chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0));
-	if (chip->remap_addr == 0) {
+	if (chip->remap_addr == NULL) {
 		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
 		snd_atiixp_free(chip);
 		return -EIO;
@@ -1584,8 +1584,10 @@
 
 	snd_atiixp_chip_start(chip);
 
-	sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
-		card->shortname, revision, chip->addr, chip->irq);
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s rev %x with %s at %#lx, irq %i", card->shortname, revision,
+		 chip->ac97[0] ? snd_ac97_get_short_name(chip->ac97[0]) : "?",
+		 chip->addr, chip->irq);
 
 	snd_card_set_pm_callback(card, snd_atiixp_suspend, snd_atiixp_resume, chip);
 
diff -Nru a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
--- a/sound/pci/atiixp_modem.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/atiixp_modem.c	2004-10-28 22:25:59 -07:00
@@ -1237,7 +1237,7 @@
 	}
 	chip->addr = pci_resource_start(pci, 0);
 	chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0));
-	if (chip->remap_addr == 0) {
+	if (chip->remap_addr == NULL) {
 		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
 		snd_atiixp_free(chip);
 		return -EIO;
diff -Nru a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
--- a/sound/pci/au88x0/au88x0.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/au88x0/au88x0.c	2004-10-28 22:25:58 -07:00
@@ -215,7 +215,7 @@
 	vortex_core_shutdown(chip);
       core_out:
 	//FIXME: the type of chip->mmio might need to be changed??
-	iounmap((void *)chip->mmio);
+	iounmap(chip->mmio);
       ioremap_out:
 	pci_release_regions(chip->pci_dev);
       regions_out:
@@ -315,7 +315,7 @@
 #endif
 
 	// (5)
-	strcpy(card->driver, "Aureal Vortex");
+	strcpy(card->driver, CARD_NAME_SHORT);
 	strcpy(card->shortname, CARD_NAME_SHORT);
 	sprintf(card->longname, "%s at 0x%lx irq %i",
 		card->shortname, chip->io, chip->irq);
diff -Nru a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
--- a/sound/pci/au88x0/au88x0.h	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/au88x0/au88x0.h	2004-10-28 22:25:58 -07:00
@@ -169,7 +169,7 @@
 
 	/* PCI hardware resources */
 	unsigned long io;
-	unsigned long *mmio;
+	unsigned long __iomem *mmio;
 	unsigned int irq;
 	spinlock_t lock;
 
diff -Nru a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
--- a/sound/pci/au88x0/au88x0_eq.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/au88x0/au88x0_eq.c	2004-10-28 22:25:59 -07:00
@@ -52,37 +52,33 @@
 	hwwrite(vortex->mmio, 0x2b3c8, level);
 }
 
+static inline short sign_invert(short a)
+{
+	/* -(-32768) -> -32768 so we do -(-32768) -> 32767 to make the result positive */
+	if (a == -32768)
+		return 32767;
+	else
+		return -a;
+}
+
 static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int eax, i = 0, n /*esp2c */;
+	int i = 0, n /*esp2c */;
 
 	for (n = 0; n < eqhw->this04; n++) {
 		hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]);
 		hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]);
 
 		if (eqhw->this08 == 0) {
-			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]);
-			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]);
-			eax = coefs[i + 4];	//esp24;
+			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2] & 0xffff);
+			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3] & 0xffff);
+			hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4] & 0xffff);
 		} else {
-			if (coefs[2 + i] == 0x8000)
-				eax = 0x7fff;
-			else
-				eax = ~coefs[2 + i];
-			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, eax & 0xffff);
-			if (coefs[3 + i] == 0x8000)
-				eax = 0x7fff;
-			else
-				eax = ~coefs[3 + i];
-			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, eax & 0xffff);
-			if (coefs[4 + i] == 0x8000)
-				eax = 0x7fff;
-			else
-				eax = ~coefs[4 + i];
+			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i]) & 0xffff);
+			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i]) & 0xffff);
+		        hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i]) & 0xffff);
 		}
-		hwwrite(vortex->mmio, 0x2b010 + n * 0x30, eax);
-
 		i += 5;
 	}
 }
@@ -90,33 +86,21 @@
 static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int i = 0, n /*esp2c */, eax;
+	int i = 0, n /*esp2c */;
 
 	for (n = 0; n < eqhw->this04; n++) {
 		hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]);
 		hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]);
 
 		if (eqhw->this08 == 0) {
-			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]);
-			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]);
-			eax = coefs[4 + i];	//*esp24;
+			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i] & 0xffff);
+			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i] & 0xffff);
+			hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i] & 0xffff);
 		} else {
-			if (coefs[2 + i] == 0x8000)
-				eax = 0x7fff;
-			else
-				eax = ~(coefs[2 + i]);
-			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, eax & 0xffff);
-			if (coefs[3 + i] == 0x8000)
-				eax = 0x7fff;
-			else
-				eax = ~coefs[3 + i];
-			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, eax & 0xffff);
-			if (coefs[4 + i] == 0x8000)
-				eax = 0x7fff;
-			else
-				eax = ~coefs[4 + i];
+			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i]) & 0xffff);
+			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i]) & 0xffff);
+			hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i]) & 0xffff);
 		}
-		hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, eax);
 		i += 5;
 	}
 
@@ -188,22 +172,12 @@
 static void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b)
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int eax;
-
 	if (eqhw->this08 == 0) {
 		hwwrite(vortex->mmio, 0x2b3d4, a);
 		hwwrite(vortex->mmio, 0x2b3ec, b);
 	} else {
-		if (a == 0x8000)
-			eax = 0x7fff;
-		else
-			eax = ~a;
-		hwwrite(vortex->mmio, 0x2b3d4, eax & 0xffff);
-		if (b == 0x8000)
-			eax = 0x7fff;
-		else
-			eax = ~b;
-		hwwrite(vortex->mmio, 0x2b3ec, eax & 0xffff);
+		hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a) & 0xffff);
+		hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b) & 0xffff);
 	}
 }
 
diff -Nru a/sound/pci/bt87x.c b/sound/pci/bt87x.c
--- a/sound/pci/bt87x.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/bt87x.c	2004-10-28 22:25:58 -07:00
@@ -139,6 +139,14 @@
 #define RISC_SYNC_FM1	0x6
 #define RISC_SYNC_VRO	0xc
 
+#define ANALOG_CLOCK 1792000
+#ifdef CONFIG_SND_BT87X_OVERCLOCK
+#define CLOCK_DIV_MIN 1
+#else
+#define CLOCK_DIV_MIN 4
+#endif
+#define CLOCK_DIV_MAX 15
+
 #define ERROR_INTERRUPTS (INT_FBUS | INT_FTRGT | INT_PPERR | \
 			  INT_RIPERR | INT_PABORT | INT_OCERR)
 #define MY_INTERRUPTS (INT_RISCI | ERROR_INTERRUPTS)
@@ -264,7 +272,7 @@
 				   status, pci_status);
 		}
 	}
-	if (status & INT_RISCI) {
+	if ((status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) {
 		int current_block, irq_block;
 
 		/* assume that exactly one line has been recorded */
@@ -303,8 +311,8 @@
 		SNDRV_PCM_INFO_MMAP_VALID,
 	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
 	.rates = SNDRV_PCM_RATE_KNOT,
-	.rate_min = 119466,
-	.rate_max = 448000,
+	.rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX,
+	.rate_max = ANALOG_CLOCK / CLOCK_DIV_MIN,
 	.channels_min = 1,
 	.channels_max = 1,
 	.buffer_bytes_max = 255 * 4092,
@@ -346,9 +354,9 @@
 static int snd_bt87x_set_analog_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
 {
 	static ratnum_t analog_clock = {
-		.num = 1792000,
-		.den_min = 4,
-		.den_max = 15,
+		.num = ANALOG_CLOCK,
+		.den_min = CLOCK_DIV_MIN,
+		.den_max = CLOCK_DIV_MAX,
 		.den_step = 1
 	};
 	static snd_pcm_hw_constraint_ratnums_t constraint_rates = {
@@ -433,7 +441,7 @@
 
 	spin_lock_irq(&chip->reg_lock);
 	chip->reg_control &= ~(CTL_DA_SDR_MASK | CTL_DA_SBR);
-	decimation = (1792000 + runtime->rate / 4) / runtime->rate;
+	decimation = (ANALOG_CLOCK + runtime->rate / 4) / runtime->rate;
 	chip->reg_control |= decimation << CTL_DA_SDR_SHIFT;
 	if (runtime->format == SNDRV_PCM_FORMAT_S8)
 		chip->reg_control |= CTL_DA_SBR;
diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c
--- a/sound/pci/cs4281.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/cs4281.c	2004-10-28 22:25:59 -07:00
@@ -463,8 +463,8 @@
 struct snd_cs4281 {
 	int irq;
 
-	unsigned long ba0;		/* virtual (accessible) address */
-	unsigned long ba1;		/* virtual (accessible) address */
+	void __iomem *ba0;		/* virtual (accessible) address */
+	void __iomem *ba1;		/* virtual (accessible) address */
 	unsigned long ba0_addr;
 	unsigned long ba1_addr;
 
@@ -1358,9 +1358,9 @@
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
 	if (chip->ba0)
-		iounmap((void *) chip->ba0);
+		iounmap(chip->ba0);
 	if (chip->ba1)
-		iounmap((void *) chip->ba1);
+		iounmap(chip->ba1);
 	pci_release_regions(chip->pci);
 
 	kfree(chip);
@@ -1422,8 +1422,8 @@
 	}
 	chip->irq = pci->irq;
 
-	chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
-	chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
+	chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
+	chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
 	if (!chip->ba0 || !chip->ba1) {
 		snd_cs4281_free(chip);
 		return -ENOMEM;
@@ -1913,6 +1913,31 @@
 }
 
 
+/*
+ * OPL3 command
+ */
+static void snd_cs4281_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
+{
+	unsigned long flags;
+	cs4281_t *chip = opl3->private_data;
+	void __iomem *port;
+
+	if (cmd & OPL3_RIGHT)
+		port = chip->ba0 + BA0_B1AP; /* right port */
+	else
+		port = chip->ba0 + BA0_B0AP; /* left port */
+
+	spin_lock_irqsave(&opl3->reg_lock, flags);
+
+	writel((unsigned int)cmd, port);
+	udelay(10);
+
+	writel((unsigned int)val, port + 4);
+	udelay(30);
+
+	spin_unlock_irqrestore(&opl3->reg_lock, flags);
+}
+
 static int __devinit snd_cs4281_probe(struct pci_dev *pci,
 				      const struct pci_device_id *pci_id)
 {
@@ -1950,13 +1975,13 @@
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_opl3_create(card,
-				   (chip->ba0 + BA0_B0AP) >> 2,
-				   (chip->ba0 + BA0_B1AP) >> 2,
-				   OPL3_HW_OPL3_CS4281, 1, &opl3)) < 0) {
+	if ((err = snd_opl3_new(card, OPL3_HW_OPL3_CS4281, &opl3)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
+	opl3->private_data = chip;
+	opl3->command = snd_cs4281_opl3_command;
+	snd_opl3_init(opl3);
 	if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
 		snd_card_free(card);
 		return err;
diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
--- a/sound/pci/cs46xx/cs46xx_lib.c	2004-10-28 22:25:56 -07:00
+++ b/sound/pci/cs46xx/cs46xx_lib.c	2004-10-28 22:25:56 -07:00
@@ -203,12 +203,6 @@
 
 	val = snd_cs46xx_codec_read(chip, reg, codec_index);
 
-	/* HACK: voyetra uses EAPD bit in the reverse way.
-	 * we flip the bit to show the mixer status correctly
-	 */
-	if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
-		val ^= 0x8000;
-
 	return val;
 }
 
@@ -289,12 +283,6 @@
 		   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
 		   return);
 
-	/* HACK: voyetra uses EAPD bit in the reverse way.
-	 * we flip the bit to show the mixer status correctly
-	 */
-	if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
-		val ^= 0x8000;
-
 	snd_cs46xx_codec_write(chip, reg, val, codec_index);
 }
 
@@ -308,7 +296,7 @@
                         unsigned long offset,
                         unsigned long len)
 {
-	unsigned long dst;
+	void __iomem *dst;
 	unsigned int bank = offset >> 16;
 	offset = offset & 0xffff;
 
@@ -336,7 +324,7 @@
                          unsigned long offset,
                          unsigned long len) 
 {
-	unsigned long dst;
+	void __iomem *dst;
 	unsigned int bank = offset >> 16;
 	offset = offset & 0xffff;
 
@@ -2333,16 +2321,15 @@
 {
 	unsigned long end_time;
 	int err;
-	cs46xx_t * chip = ac97->private_data;
 
 	/* reset to defaults */
 	snd_ac97_write(ac97, AC97_RESET, 0);	
 
 	/* set the desired CODEC mode */
-	if (chip->nr_ac97_codecs == 0) {
+	if (ac97->num == CS46XX_PRIMARY_CODEC_INDEX) {
 		snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0);
 		snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0);
-	} else if (chip->nr_ac97_codecs == 1) {
+	} else if (ac97->num == CS46XX_SECONDARY_CODEC_INDEX) {
 		snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3);
 		snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
 	} else {
@@ -2380,10 +2367,43 @@
 }
 #endif
 
+static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec)
+{
+	int idx, err;
+	ac97_template_t ac97;
+
+	memset(&ac97, 0, sizeof(ac97));
+	ac97.private_data = chip;
+	ac97.private_free = snd_cs46xx_mixer_free_ac97;
+	ac97.num = codec;
+	if (chip->amplifier_ctrl == amp_voyetra)
+		ac97.scaps = AC97_SCAP_INV_EAPD;
+
+	if (codec == CS46XX_SECONDARY_CODEC_INDEX) {
+		snd_cs46xx_codec_write(chip, AC97_RESET, 0, codec);
+		udelay(10);
+		if (snd_cs46xx_codec_read(chip, AC97_RESET, codec) & 0x8000) {
+			snd_printdd("snd_cs46xx: seconadry codec not present\n");
+			return -ENXIO;
+		}
+	}
+
+	snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000, codec);
+	for (idx = 0; idx < 100; ++idx) {
+		if (snd_cs46xx_codec_read(chip, AC97_MASTER, codec) == 0x8000) {
+			err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[codec]);
+			return err;
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ/100);
+	}
+	snd_printdd("snd_cs46xx: codec %d detection timeout\n", codec);
+	return -ENXIO;
+}
+
 int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
 {
 	snd_card_t *card = chip->card;
-	ac97_template_t ac97;
 	snd_ctl_elem_id_t id;
 	int err;
 	unsigned int idx;
@@ -2402,70 +2422,15 @@
 		return err;
 	chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
 
-	memset(&ac97, 0, sizeof(ac97));
-	ac97.private_data = chip;
-	ac97.private_free = snd_cs46xx_mixer_free_ac97;
-
-	snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
-			       CS46XX_PRIMARY_CODEC_INDEX);
-	for (idx = 0; idx < 100; ++idx) {
-		if (snd_cs46xx_codec_read(chip, AC97_MASTER,
-					  CS46XX_PRIMARY_CODEC_INDEX) == 0x8000)
-			goto _ok;
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/100);
-	}
-	return -ENXIO;
-
- _ok:
-	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[CS46XX_PRIMARY_CODEC_INDEX])) < 0)
-		return err;
-	snd_printdd("snd_cs46xx: primary codec phase one\n");
+	if (cs46xx_detect_codec(chip, CS46XX_PRIMARY_CODEC_INDEX) < 0)
+		return -ENXIO;
 	chip->nr_ac97_codecs = 1;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	snd_printdd("snd_cs46xx: detecting seconadry codec\n");
 	/* try detect a secondary codec */
-	memset(&ac97, 0, sizeof(ac97));    
-	ac97.private_data = chip;
-	ac97.private_free = snd_cs46xx_mixer_free_ac97;
-	ac97.num = CS46XX_SECONDARY_CODEC_INDEX;
-
-	snd_cs46xx_codec_write(chip, AC97_RESET, 0,
-			       CS46XX_SECONDARY_CODEC_INDEX);
-	udelay(10);
-
-	if (snd_cs46xx_codec_read(chip, AC97_RESET,
-				  CS46XX_SECONDARY_CODEC_INDEX) & 0x8000) {
-		snd_printdd("snd_cs46xx: seconadry codec not present\n");
-		goto _no_sec_codec;
-	}
-
-	snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
-			       CS46XX_SECONDARY_CODEC_INDEX);
-	for (idx = 0; idx < 100; ++idx) {
-		if (snd_cs46xx_codec_read(chip, AC97_MASTER,
-					  CS46XX_SECONDARY_CODEC_INDEX) == 0x8000) {
-			goto _ok2;
-		}
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/100);
-	}
-
- _no_sec_codec:
-	snd_printdd("snd_cs46xx: secondary codec did not respond ...\n");
-
-	chip->nr_ac97_codecs = 1;
-    
-	/* well, one codec only ... */
-	goto _end;
- _ok2:
-	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])) < 0)
-		return err;
-	chip->nr_ac97_codecs = 2;
-
- _end:
-
+	if (! cs46xx_detect_codec(chip, CS46XX_SECONDARY_CODEC_INDEX))
+		chip->nr_ac97_codecs = 2;
 #endif /* CONFIG_SND_CS46XX_NEW_DSP */
 
 	/* add cs4630 mixer controls */
@@ -2483,15 +2448,14 @@
 	chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
     
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-	if (chip->nr_ac97_codecs == 1 && 
-	    (snd_cs46xx_codec_read(chip, AC97_VENDOR_ID2,
-				  CS46XX_PRIMARY_CODEC_INDEX) == 0x592b ||
-	     snd_cs46xx_codec_read(chip, AC97_VENDOR_ID2,
-				   CS46XX_PRIMARY_CODEC_INDEX) == 0x592d)) {
-		/* set primary cs4294 codec into Extended Audio Mode */
-		snd_printdd("setting EAM bit on cs4294 CODEC\n");
-		snd_cs46xx_codec_write(chip, AC97_CSR_ACMODE, 0x200,
-				       CS46XX_PRIMARY_CODEC_INDEX);
+	if (chip->nr_ac97_codecs == 1) {
+		unsigned int id2 = chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]->id & 0xffff;
+		if (id2 == 0x592b || id2 == 0x592d) {
+			/* set primary cs4294 codec into Extended Audio Mode */
+			snd_printdd("setting EAM bit on cs4294 CODEC\n");
+			snd_cs46xx_codec_write(chip, AC97_CSR_ACMODE, 0x200,
+					       CS46XX_PRIMARY_CODEC_INDEX);
+		}
 	}
 	/* do soundcard specific mixer setup */
 	if (chip->mixer_init) {
@@ -2902,7 +2866,7 @@
 	for (idx = 0; idx < 5; idx++) {
 		snd_cs46xx_region_t *region = &chip->region.idx[idx];
 		if (region->remap_addr)
-			iounmap((void *) region->remap_addr);
+			iounmap(region->remap_addr);
 		if (region->resource) {
 			release_resource(region->resource);
 			kfree_nocheck(region->resource);
@@ -3868,8 +3832,8 @@
 			snd_cs46xx_free(chip);
 			return -EBUSY;
 		}
-		region->remap_addr = (unsigned long) ioremap_nocache(region->base, region->size);
-		if (region->remap_addr == 0) {
+		region->remap_addr = ioremap_nocache(region->base, region->size);
+		if (region->remap_addr == NULL) {
 			snd_printk("%s ioremap problem\n", region->name);
 			snd_cs46xx_free(chip);
 			return -ENOMEM;
diff -Nru a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
--- a/sound/pci/cs46xx/dsp_spos.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/cs46xx/dsp_spos.c	2004-10-28 22:25:59 -07:00
@@ -514,7 +514,7 @@
 	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i,j,col;
-	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
+	void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
 
 	down(&chip->spos_mutex);
 	snd_iprintf(buffer, "TASK TREES:\n");
@@ -573,7 +573,7 @@
 	cs46xx_t *chip = entry->private_data;
 	/*dsp_spos_instance_t * ins = chip->dsp_spos_instance; */
 	unsigned int i,col = 0;
-	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
+	void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
 	symbol_entry_t * symbol; 
 
 	for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i += sizeof(u32),col ++) {
@@ -599,7 +599,7 @@
 {
 	cs46xx_t *chip = entry->private_data;
 	int i,col = 0;
-	unsigned long dst = chip->region.idx[2].remap_addr;
+	void __iomem *dst = chip->region.idx[2].remap_addr;
 
 	snd_iprintf(buffer,"PCMREADER:\n");
 	for (i = PCM_READER_BUF1;i < PCM_READER_BUF1 + 0x30; i += sizeof(u32),col ++) {
@@ -909,7 +909,7 @@
 static int debug_tree;
 static void _dsp_create_task_tree (cs46xx_t *chip,u32 * task_data, u32  dest, int size)
 {
-	unsigned long spdst = chip->region.idx[1].remap_addr + 
+	void __iomem *spdst = chip->region.idx[1].remap_addr + 
 		DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
 	int i;
 
@@ -923,7 +923,7 @@
 static int debug_scb;
 static void _dsp_create_scb (cs46xx_t *chip,u32 * scb_data, u32  dest)
 {
-	unsigned long spdst = chip->region.idx[1].remap_addr + 
+	void __iomem *spdst = chip->region.idx[1].remap_addr + 
 		DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
 	int i;
 
diff -Nru a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c	2004-10-28 22:25:59 -07:00
@@ -71,7 +71,7 @@
 	dsp_spos_instance_t * ins;
 	cs46xx_t *chip = scb_info->chip;
 	int j,col;
-	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
+	void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
 
 	ins = chip->dsp_spos_instance;
 
@@ -162,7 +162,7 @@
 
 static void _dsp_clear_sample_buffer (cs46xx_t *chip, u32 sample_buffer_addr, int dword_count) 
 {
-	unsigned long dst = chip->region.idx[2].remap_addr + sample_buffer_addr;
+	void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr;
 	int i;
   
 	for (i = 0; i < dword_count ; ++i ) {
diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
--- a/sound/pci/emu10k1/emufx.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/emu10k1/emufx.c	2004-10-28 22:25:58 -07:00
@@ -480,7 +480,7 @@
 static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
 					u32 op, u32 r, u32 a, u32 x, u32 y)
 {
-	snd_assert(*ptr < 512, return);
+	snd_assert(*ptr < 1024, return);
 	set_bit(*ptr, icode->code_valid);
 	icode->code[*ptr    ][0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
 	icode->code[(*ptr)++][1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
@@ -505,7 +505,7 @@
 {
 	int gpr;
 
-	for (gpr = 0; gpr < 0x100; gpr++) {
+	for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
 		if (!test_bit(gpr, icode->gpr_valid))
 			continue;
 		snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, icode->gpr_map[gpr]);
@@ -516,7 +516,7 @@
 {
 	int gpr;
 
-	for (gpr = 0; gpr < 0x100; gpr++) {
+	for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
 		set_bit(gpr, icode->gpr_valid);
 		icode->gpr_map[gpr] = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);
 	}
@@ -526,11 +526,16 @@
 {
 	int tram;
 
-	for (tram = 0; tram < 0xa0; tram++) {
+	for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
 		if (!test_bit(tram, icode->tram_valid))
 			continue;
 		snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, icode->tram_data_map[tram]);
-		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, icode->tram_addr_map[tram]);
+		if (!emu->audigy)
+			snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, icode->tram_addr_map[tram]);
+		else {
+			snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, icode->tram_addr_map[tram] << 12);
+			snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, icode->tram_addr_map[tram] >> 20);
+		}
 	}
 }
 
@@ -539,10 +544,15 @@
 	int tram;
 
 	memset(icode->tram_valid, 0, sizeof(icode->tram_valid));
-	for (tram = 0; tram < 0xa0; tram++) {
+	for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
 		set_bit(tram, icode->tram_valid);
 		icode->tram_data_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);
-		icode->tram_addr_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);
+		if (!emu->audigy)
+			icode->tram_addr_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);
+		else {
+			icode->tram_addr_map[tram] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;
+			icode->tram_addr_map[tram] |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;
+		}
 	}
 }
 
@@ -550,7 +560,7 @@
 {
 	u32 pc;
 
-	for (pc = 0; pc < 512; pc++) {
+	for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) {
 		if (!test_bit(pc, icode->code_valid))
 			continue;
 		snd_emu10k1_efx_write(emu, pc * 2, icode->code[pc][0]);
@@ -563,7 +573,7 @@
 	u32 pc;
 
 	memset(icode->code_valid, 0, sizeof(icode->code_valid));
-	for (pc = 0; pc < 512; pc++) {
+	for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) {
 		set_bit(pc, icode->code_valid);
 		icode->code[pc][0] = snd_emu10k1_efx_read(emu, pc * 2);
 		icode->code[pc][1] = snd_emu10k1_efx_read(emu, pc * 2 + 1);
@@ -962,8 +972,12 @@
 	}
 
 	/* clear free GPRs */
-	for (i = 0; i < 256; i++)
+	for (i = 0; i < 512; i++)
 		set_bit(i, icode->gpr_valid);
+		
+	/* clear TRAM data & address lines */
+	for (i = 0; i < 256; i++)
+		set_bit(i, icode->tram_valid);
 
 	strcpy(icode->name, "Audigy DSP code for ALSA");
 	ptr = 0;
@@ -1311,7 +1325,7 @@
 		goto __err;
 	}
 	/* clear remaining instruction memory */
-	while (ptr < 0x200)
+	while (ptr < 0x400)
 		A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
 
 	seg = snd_enter_user();
@@ -2067,8 +2081,6 @@
 		kfree(icode);
 		return res;
 	case SNDRV_EMU10K1_IOCTL_PCM_POKE:
-		if (emu->audigy)
-			return -EINVAL;
 		ipcm = (emu10k1_fx8010_pcm_t *)kmalloc(sizeof(*ipcm), GFP_KERNEL);
 		if (ipcm == NULL)
 			return -ENOMEM;
@@ -2080,8 +2092,6 @@
 		kfree(ipcm);
 		return res;
 	case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
-		if (emu->audigy)
-			return -EINVAL;
 		ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL);
 		if (ipcm == NULL)
 			return -ENOMEM;
@@ -2097,8 +2107,6 @@
 		kfree(ipcm);
 		return res;
 	case SNDRV_EMU10K1_IOCTL_TRAM_SETUP:
-		if (emu->audigy)
-			return -EINVAL;
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (get_user(addr, (unsigned int __user *)argp))
diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
--- a/sound/pci/emu10k1/emupcm.c	2004-10-28 22:25:56 -07:00
+++ b/sound/pci/emu10k1/emupcm.c	2004-10-28 22:25:56 -07:00
@@ -1092,6 +1092,7 @@
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
 	unsigned int nval[2], bits;
 	int nefx = emu->audigy ? 64 : 32;
+	int nefxb = emu->audigy ? 7 : 6;
 	int change, idx;
 	
 	nval[0] = nval[1] = 0;
@@ -1100,8 +1101,14 @@
 			nval[idx / 32] |= 1 << (idx % 32);
 			bits++;
 		}
-	if (bits != 1 && bits != 2 && bits != 4 && bits != 8)
+		
+	for (idx = 0; idx < nefxb; idx++)
+		if (1 << idx == bits)
+			break;
+	
+	if (idx >= nefxb)
 		return -EINVAL;
+
 	spin_lock_irq(&emu->reg_lock);
 	change = (nval[0] != emu->efx_voices_mask[0]) ||
 		(nval[1] != emu->efx_voices_mask[1]);
@@ -1185,7 +1192,7 @@
 	}
 	snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
 					       (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
-					       src, frames, tram_shift++);
+					       src, frames, tram_shift);
 	tram_pos -= frames;
 	pcm->tram_pos = tram_pos;
 	pcm->tram_shift = tram_shift;
diff -Nru a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
--- a/sound/pci/emu10k1/emuproc.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/emu10k1/emuproc.c	2004-10-28 22:25:57 -07:00
@@ -229,7 +229,7 @@
 
 	snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name);
 	snd_iprintf(buffer, "  Code dump      :\n");
-	for (pc = 0; pc < 512; pc++) {
+	for (pc = 0; pc < (emu->audigy ? 1024 : 512); pc++) {
 		u32 low, high;
 			
 		low = snd_emu10k1_efx_read(emu, pc * 2);
@@ -256,9 +256,13 @@
 }
 
 #define TOTAL_SIZE_GPR		(0x100*4)
+#define A_TOTAL_SIZE_GPR	(0x200*4)
 #define TOTAL_SIZE_TANKMEM_DATA	(0xa0*4)
 #define TOTAL_SIZE_TANKMEM_ADDR (0xa0*4)
+#define A_TOTAL_SIZE_TANKMEM_DATA (0x100*4)
+#define A_TOTAL_SIZE_TANKMEM_ADDR (0x100*4)
 #define TOTAL_SIZE_CODE		(0x200*8)
+#define A_TOTAL_SIZE_CODE	(0x400*8)
 
 static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_data,
 				    struct file *file, char __user *buf,
@@ -267,12 +271,12 @@
 	long size;
 	emu10k1_t *emu = entry->private_data;
 	unsigned int offset;
+	int tram_addr = 0;
 	
 	if (!strcmp(entry->name, "fx8010_tram_addr")) {
-		if (emu->audigy) return -EINVAL;
 		offset = TANKMEMADDRREGBASE;
+		tram_addr = 1;
 	} else if (!strcmp(entry->name, "fx8010_tram_data")) {
-		if (emu->audigy) return -EINVAL;
 		offset = TANKMEMDATAREGBASE;
 	} else if (!strcmp(entry->name, "fx8010_code")) {
 		offset = emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
@@ -289,7 +293,11 @@
 		if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL)
 			return -ENOMEM;
 		for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++)
-			tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
+			if (tram_addr && emu->audigy) {
+				tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0) >> 11;
+				tmp[idx] |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20;
+			} else 
+				tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
 		if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size))
 			res = -EFAULT;
 		else {
@@ -316,35 +324,35 @@
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
 		entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
-		entry->size = TOTAL_SIZE_GPR;
+		entry->size = emu->audigy ? A_TOTAL_SIZE_GPR : TOTAL_SIZE_GPR;
 		entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
 	}
-	if (!emu->audigy && ! snd_card_proc_new(emu->card, "fx8010_tram_data", &entry)) {
+	if (! snd_card_proc_new(emu->card, "fx8010_tram_data", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
 		entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
-		entry->size = TOTAL_SIZE_TANKMEM_DATA;
+		entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_DATA : TOTAL_SIZE_TANKMEM_DATA ;
 		entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
 	}
-	if (!emu->audigy && ! snd_card_proc_new(emu->card, "fx8010_tram_addr", &entry)) {
+	if (! snd_card_proc_new(emu->card, "fx8010_tram_addr", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
 		entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
-		entry->size = TOTAL_SIZE_TANKMEM_ADDR;
+		entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_ADDR : TOTAL_SIZE_TANKMEM_ADDR ;
 		entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
 	}
 	if (! snd_card_proc_new(emu->card, "fx8010_code", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;
 		entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
-		entry->size = TOTAL_SIZE_CODE;
+		entry->size = emu->audigy ? A_TOTAL_SIZE_CODE : TOTAL_SIZE_CODE;
 		entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
 	}
 	if (! snd_card_proc_new(emu->card, "fx8010_acode", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = emu;
 		entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
-		entry->c.text.read_size = 64*1024;
+		entry->c.text.read_size = 128*1024;
 		entry->c.text.read = snd_emu10k1_proc_acode_read;
 	}
 	return 0;
diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c
--- a/sound/pci/ens1370.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/ens1370.c	2004-10-28 22:25:59 -07:00
@@ -371,6 +371,7 @@
 
 struct _snd_ensoniq {
 	spinlock_t reg_lock;
+	struct semaphore src_mutex;
 
 	int irq;
 
@@ -512,6 +513,7 @@
 		r = inl(ES_REG(ensoniq, 1371_SMPRATE));
 		if ((r & ES_1371_SRC_RAM_BUSY) == 0)
 			return r;
+		cond_resched();
 	}
 	snd_printk("wait source ready timeout 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_SMPRATE), r);
 	return 0;
@@ -695,6 +697,7 @@
 {
 	unsigned int n, truncm, freq, result;
 
+	down(&ensoniq->src_mutex);
 	n = rate / 3000;
 	if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
 		n--;
@@ -718,12 +721,14 @@
 	snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
 	snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8);
 	snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8);
+	up(&ensoniq->src_mutex);
 }
 
 static void snd_es1371_dac1_rate(ensoniq_t * ensoniq, unsigned int rate)
 {
 	unsigned int freq, r;
 
+	down(&ensoniq->src_mutex);
 	freq = ((rate << 15) + 1500) / 3000;
 	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | ES_1371_DIS_P1;
 	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
@@ -733,12 +738,14 @@
 	snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
 	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1));
 	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
+	up(&ensoniq->src_mutex);
 }
 
 static void snd_es1371_dac2_rate(ensoniq_t * ensoniq, unsigned int rate)
 {
 	unsigned int freq, r;
 
+	down(&ensoniq->src_mutex);
 	freq = ((rate << 15) + 1500) / 3000;
 	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | ES_1371_DIS_P2;
 	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
@@ -748,6 +755,7 @@
 	snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
 	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1));
 	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
+	up(&ensoniq->src_mutex);
 }
 
 #endif /* CHIP1371 */
@@ -845,6 +853,13 @@
 		mode |= 0x01;
 	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->ctrl &= ~ES_DAC1_EN;
+#ifdef CHIP1371
+	/* 48k doesn't need SRC (it breaks AC3-passthru) */
+	if (runtime->rate == 48000)
+		ensoniq->ctrl |= ES_1373_BYPASS_P1;
+	else
+		ensoniq->ctrl &= ~ES_1373_BYPASS_P1;
+#endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
 	outl(runtime->dma_addr, ES_REG(ensoniq, DAC1_FRAME));
@@ -862,11 +877,12 @@
 	case 44100: ensoniq->ctrl |= ES_1370_WTSRSEL(3); break;
 	default: snd_BUG();
 	}
-#else
-	snd_es1371_dac1_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	spin_unlock_irq(&ensoniq->reg_lock);
+#ifndef CHIP1370
+	snd_es1371_dac1_rate(ensoniq, runtime->rate);
+#endif
 	return 0;
 }
 
@@ -900,11 +916,12 @@
 		ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate));
 		ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_PLAY2;
 	}
-#else
-	snd_es1371_dac2_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	spin_unlock_irq(&ensoniq->reg_lock);
+#ifndef CHIP1370
+	snd_es1371_dac2_rate(ensoniq, runtime->rate);
+#endif
 	return 0;
 }
 
@@ -936,11 +953,12 @@
 		ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate));
 		ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_CAPTURE;
 	}
-#else
-	snd_es1371_adc_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	spin_unlock_irq(&ensoniq->reg_lock);
+#ifndef CHIP1370
+	snd_es1371_adc_rate(ensoniq, runtime->rate);
+#endif
 	return 0;
 }
 
@@ -1878,6 +1896,7 @@
 	if (ensoniq == NULL)
 		return -ENOMEM;
 	spin_lock_init(&ensoniq->reg_lock);
+	init_MUTEX(&ensoniq->src_mutex);
 	ensoniq->card = card;
 	ensoniq->pci = pci;
 	ensoniq->irq = -1;
diff -Nru a/sound/pci/es1968.c b/sound/pci/es1968.c
--- a/sound/pci/es1968.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/es1968.c	2004-10-28 22:25:58 -07:00
@@ -555,6 +555,11 @@
 	int playback_streams, capture_streams;
 
 	unsigned int clock;		/* clock */
+	/* for clock measurement */
+	unsigned int in_measurement: 1;
+	unsigned int measure_apu;
+	unsigned int measure_lastpos;
+	unsigned int measure_count;
 
 	/* buffer */
 	struct snd_dma_buffer dma;
@@ -579,6 +584,7 @@
 	snd_rawmidi_t *rmidi;
 
 	spinlock_t reg_lock;
+	struct semaphore ac97_mutex;	/* ac97 lock */
 	struct tasklet_struct hwvol_tq;
 
 	/* Maestro Stuff */
@@ -671,6 +677,7 @@
 	while (timeout-- > 0) {
 		if (!(inb(chip->io_port + ESM_AC97_INDEX) & 1))
 			return 0;
+		cond_resched();
 	}
 	snd_printd("es1968: ac97 timeout\n");
 	return 1; /* timeout */
@@ -679,39 +686,35 @@
 static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
 	es1968_t *chip = ac97->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
 
+	down(&chip->ac97_mutex);
 	snd_es1968_ac97_wait(chip);
 
 	/* Write the bus */
 	outw(val, chip->io_port + ESM_AC97_DATA);
-	mdelay(1);
+	msleep(1);
 	outb(reg, chip->io_port + ESM_AC97_INDEX);
-	mdelay(1);
+	msleep(1);
 
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	up(&chip->ac97_mutex);
 }
 
 static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg)
 {
 	u16 data = 0;
 	es1968_t *chip = ac97->private_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
 
+	down(&chip->ac97_mutex);
 	snd_es1968_ac97_wait(chip);
 
 	outb(reg | 0x80, chip->io_port + ESM_AC97_INDEX);
-	mdelay(1);
+	msleep(1);
 
 	if (! snd_es1968_ac97_wait(chip)) {
 		data = inw(chip->io_port + ESM_AC97_DATA);
-		mdelay(1);
+		msleep(1);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	up(&chip->ac97_mutex);
 
 	return data;
 }
@@ -1803,30 +1806,28 @@
 
 	snd_es1968_apu_set_freq(chip, apu, ((unsigned int)48000 << 16) / chip->clock); /* 48000 Hz */
 
+	chip->in_measurement = 1;
+	chip->measure_apu = apu;
 	spin_lock_irq(&chip->reg_lock);
+	snd_es1968_bob_inc(chip, ESM_BOB_FREQ);
 	__apu_set_register(chip, apu, 5, pa & 0xffff);
 	snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR);
 	do_gettimeofday(&start_time);
 	spin_unlock_irq(&chip->reg_lock);
-#if 0
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ / 20); /* 50 msec */
-#else
-	/* FIXME:
-	 * schedule() above may be too inaccurate and the pointer can
-	 * overlap the boundary..
-	 */
-	mdelay(50);
-#endif
 	spin_lock_irq(&chip->reg_lock);
 	offset = __apu_get_register(chip, apu, 5);
 	do_gettimeofday(&stop_time);
 	snd_es1968_trigger_apu(chip, apu, 0); /* stop */
+	snd_es1968_bob_dec(chip);
+	chip->in_measurement = 0;
 	spin_unlock_irq(&chip->reg_lock);
 
 	/* check the current position */
 	offset -= (pa & 0xffff);
 	offset &= 0xfffe;
+	offset += chip->measure_count * (CLOCK_MEASURE_BUFSIZE/2);
 
 	t = stop_time.tv_sec - start_time.tv_sec;
 	t *= 1000000;
@@ -2004,6 +2005,12 @@
 				snd_es1968_update_pcm(chip, es);
 		}
 		spin_unlock(&chip->substream_lock);
+		if (chip->in_measurement) {
+			unsigned int curp = __apu_get_register(chip, chip->measure_apu, 5);
+			if (curp < chip->measure_lastpos)
+				chip->measure_count++;
+			chip->measure_lastpos = curp;
+		}
 	}
 
 	return IRQ_HANDLED;
@@ -2524,6 +2531,7 @@
 	spin_lock_init(&chip->substream_lock);
 	INIT_LIST_HEAD(&chip->buf_list);
 	INIT_LIST_HEAD(&chip->substream_list);
+	init_MUTEX(&chip->ac97_mutex);
 	init_MUTEX(&chip->memory_mutex);
 	tasklet_init(&chip->hwvol_tq, es1968_update_hw_volume, (unsigned long)chip);
 	chip->card = card;
diff -Nru a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
--- a/sound/pci/ice1712/Makefile	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/ice1712/Makefile	2004-10-28 22:25:57 -07:00
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff -Nru a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
--- a/sound/pci/ice1712/aureon.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/ice1712/aureon.c	2004-10-28 22:25:59 -07:00
@@ -89,6 +89,235 @@
 #define WM_OUT_MUX2		0x1e	/* output MUX */
 #define WM_RESET		0x1f	/* software reset */
 
+static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short val) {
+	unsigned int tmp;
+
+	/* Send address to XILINX chip */
+	tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	tmp |= AUREON_AC97_ADDR;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	tmp &= ~AUREON_AC97_ADDR;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);	
+
+	/* Send low-order byte to XILINX chip */
+	tmp &= ~AUREON_AC97_DATA_MASK;
+	tmp |= val & AUREON_AC97_DATA_MASK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	tmp |= AUREON_AC97_DATA_LOW;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	tmp &= ~AUREON_AC97_DATA_LOW;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	
+	/* Send high-order byte to XILINX chip */
+	tmp &= ~AUREON_AC97_DATA_MASK;
+	tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
+
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	tmp |= AUREON_AC97_DATA_HIGH;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	tmp &= ~AUREON_AC97_DATA_HIGH;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	
+	/* Instruct XILINX chip to parse the data to the STAC9744 chip */
+	tmp |= AUREON_AC97_COMMIT;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	tmp &= ~AUREON_AC97_COMMIT;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(10);
+	
+	/* Store the data in out private buffer */
+	ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
+}
+
+static unsigned short aureon_ac97_read(ice1712_t *ice, unsigned short reg)
+{
+       return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
+}
+
+/*
+ * Initialize STAC9744 chip
+ */
+static int aureon_ac97_init (ice1712_t *ice) {
+	int i;
+	static unsigned short ac97_defaults[] = {
+		0x00, 0x9640,
+		0x02, 0x8000,
+		0x04, 0x8000,
+		0x06, 0x8000,
+		0x0C, 0x8008,
+		0x0E, 0x8008,
+		0x10, 0x8808,
+		0x12, 0x8808,
+		0x14, 0x8808,
+		0x16, 0x8808,
+		0x18, 0x8808,
+		0x1C, 0x8000,
+		0x26, 0x000F,
+		0x28, 0x0201,
+		0x2C, 0xBB80,
+		0x32, 0xBB80,
+		0x7C, 0x8384,
+		0x7E, 0x7644,
+		(unsigned short)-1
+	};
+	unsigned int tmp;
+
+	/* Cold reset */
+	tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(3);
+	
+	tmp &= ~AUREON_AC97_RESET;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(3);
+	
+	tmp |= AUREON_AC97_RESET;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(3);
+	
+	memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
+	for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
+		ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
+		
+	aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
+
+	return 0;
+}
+
+#define AUREON_AC97_STEREO	0x80
+
+/*
+ * AC'97 volume controls
+ */
+static int aureon_ac97_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 31;
+	return 0;
+}
+
+static int aureon_ac97_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short vol;
+
+	down(&ice->gpio_mutex);
+
+	vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
+	ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
+	if (kcontrol->private_value & AUREON_AC97_STEREO)
+		ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
+
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int aureon_ac97_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int change;
+	
+	snd_ice1712_save_gpio_status(ice);
+
+	ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
+	nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
+	if (kcontrol->private_value & AUREON_AC97_STEREO)
+		nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
+	nvol |= ovol & ~0x1F1F;
+	
+	if ((change = (ovol != nvol)))
+		aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
+
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;		
+}
+
+/*
+ * AC'97 mute controls
+ */
+#define aureon_ac97_mute_info	aureon_mono_bool_info
+
+static int aureon_ac97_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	down(&ice->gpio_mutex);
+
+	ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
+
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int aureon_ac97_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int change;
+
+	snd_ice1712_save_gpio_status(ice);
+	
+	ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
+	nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~	0x8000);
+	
+	if ((change = (ovol != nvol)))
+		aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
+		
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
+
+/*
+ * AC'97 mute controls
+ */
+#define aureon_ac97_micboost_info	aureon_mono_bool_info
+
+static int aureon_ac97_micboost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	down(&ice->gpio_mutex);
+
+	ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
+
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int change;
+
+	snd_ice1712_save_gpio_status(ice);
+	
+	ovol = aureon_ac97_read(ice, AC97_MIC);
+	nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
+	
+	if ((change = (ovol != nvol)))
+		aureon_ac97_write(ice, AC97_MIC, nvol);
+		
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
 
 /*
  * write data in the SPI mode
@@ -179,78 +408,177 @@
 }
 
 /*
+ * AC'97 master playback mute controls (Mute on WM8770 chip)
+ */
+#define aureon_ac97_mmute_info	aureon_mono_bool_info
+
+static int aureon_ac97_mmute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	down(&ice->gpio_mutex);
+
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
+
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int aureon_ac97_mmute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int change;
+	
+	snd_ice1712_save_gpio_status(ice);
+	
+	ovol = wm_get(ice, WM_OUT_MUX1);
+	nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
+	if ((change = (ovol != nvol)))
+		wm_put(ice, WM_OUT_MUX1, nvol);
+		
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
+
+/*
+ * Logarithmic volume values for WM8770
+ * Computed as 20 * Log10(255 / x)
+ */
+static unsigned char wm_vol[256] = {
+	127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
+	23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
+	17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
+	13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+	11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0
+};
+
+#define WM_VOL_MAX	(sizeof(wm_vol) - 1)
+#define WM_VOL_MUTE	0x8000
+
+static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
+{
+	unsigned char nvol;
+	
+	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
+		nvol = 0;
+	else
+		nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
+	
+	wm_put(ice, index, nvol);
+	wm_put_nocache(ice, index, 0x180 | nvol);
+}
+
+/*
  * DAC mute control
  */
-#define wm_dac_mute_info	aureon_mono_bool_info
+#define wm_pcm_mute_info	aureon_mono_bool_info
 
-static int wm_dac_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	unsigned short val;
 
 	down(&ice->gpio_mutex);
-	val = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_MUTE);
-	ucontrol->value.integer.value[0] = ~val>>4 & 0x1;
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
 	up(&ice->gpio_mutex);
 	return 0;
 }
 
-static int wm_dac_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	unsigned short new, old;
+	unsigned short nval, oval;
 	int change;
 
 	snd_ice1712_save_gpio_status(ice);
-	old = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_MUTE);
-	new = (~ucontrol->value.integer.value[0]<<4&0x10) | (old&~0x10);
-	change = (new != old);
-	if (change)
-		wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_MUTE, new);
+	oval = wm_get(ice, WM_MUTE);
+	nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
+	if ((change = (nval != oval)))
+		wm_put(ice, WM_MUTE, nval);
 	snd_ice1712_restore_gpio_status(ice);
 
 	return change;
 }
 
 /*
+ * Master volume attenuation mixer control
+ */
+static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = WM_VOL_MAX;
+	return 0;
+}
+
+static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int i;
+	for (i=0; i<2; i++)
+		ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
+	return 0;
+}
+
+static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int ch, change = 0;
+
+	snd_ice1712_save_gpio_status(ice);
+	for (ch = 0; ch < 2; ch++) {
+		if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
+			int dac;
+			ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
+			ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
+			for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+				wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
+					   ice->spec.aureon.vol[dac + ch],
+					   ice->spec.aureon.master[ch]);
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+	return change;
+}
+
+/*
  * DAC volume attenuation mixer control
  */
-static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	int voices = kcontrol->private_value >> 8;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = voices;
 	uinfo->value.integer.min = 0;		/* mute (-101dB) */
-	uinfo->value.integer.max = 101;		/* 0dB */
+	uinfo->value.integer.max = 0x7F;	/* 0dB */
 	return 0;
 }
 
-static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int i, idx, ofs, voices;
-	unsigned short vol;
+	int i, ofs, voices;
 
 	voices = kcontrol->private_value >> 8;
 	ofs = kcontrol->private_value & 0xff;
-	down(&ice->gpio_mutex);
-	for (i = 0; i < voices; i++) {
-		idx  = WM_DAC_ATTEN + ofs + i;
-		vol = wm_get(ice, idx) & 0x7f;
-		if (vol <= 0x1a)
-			ucontrol->value.integer.value[i] = 0;
-		else
-			ucontrol->value.integer.value[i] = vol - 0x1a;
-	}
-	up(&ice->gpio_mutex);
+	for (i = 0; i < voices; i++)
+		ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
 	return 0;
 }
 
-static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	int i, idx, ofs, voices;
-	unsigned short ovol, nvol;
 	int change = 0;
 
 	voices = kcontrol->private_value >> 8;
@@ -258,13 +586,11 @@
 	snd_ice1712_save_gpio_status(ice);
 	for (i = 0; i < voices; i++) {
 		idx  = WM_DAC_ATTEN + ofs + i;
-		nvol = ucontrol->value.integer.value[i] + 0x1a;
-		ovol = wm_get(ice, idx) & 0x7f;
-		if (ovol != nvol) {
-			if (nvol <= 0x1a && ovol <= 0x1a)
-				continue;
-			wm_put(ice, idx, nvol | 0x80); /* zero-detect, prelatch */
-			wm_put_nocache(ice, idx, nvol | 0x180); /* update */
+		if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
+			ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
+			ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
+			wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
+				   ice->spec.aureon.master[i]);
 			change = 1;
 		}
 	}
@@ -272,33 +598,127 @@
 	return change;
 }
 
+/*
+ * WM8770 mute control
+ */
+static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = kcontrol->private_value >> 8;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int voices, ofs, i;
+	
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xFF;
+
+	for (i = 0; i < voices; i++)
+		ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
+	return 0;
+}
+
+static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int change = 0, voices, ofs, i;
+
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xFF;
+
+	snd_ice1712_save_gpio_status(ice);
+	for (i = 0; i < voices; i++) {
+		int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
+		if (ucontrol->value.integer.value[i] != val) {
+			ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
+			ice->spec.aureon.vol[ofs + i] |=
+				ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+			wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
+				   ice->spec.aureon.master[i]);
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
+
+/*
+ * WM8770 master mute control
+ */
+static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	
+	ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
+	ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
+	return 0;
+}
+
+static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int change = 0, i;
+
+	snd_ice1712_save_gpio_status(ice);
+	for (i = 0; i < 2; i++) {
+		int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
+		if (ucontrol->value.integer.value[i] != val) {
+			int dac;
+			ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
+			ice->spec.aureon.master[i] |=
+				ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+			for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+				wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
+					   ice->spec.aureon.vol[dac + i],
+					   ice->spec.aureon.master[i]);
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
+
 /* digital master volume */
-#define MASTER_0dB 0xff
-#define MASTER_RES 128	/* -64dB */
-#define MASTER_MIN (MASTER_0dB - MASTER_RES)
-static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+#define PCM_0dB 0xff
+#define PCM_RES 128	/* -64dB */
+#define PCM_MIN (PCM_0dB - PCM_RES)
+static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 1;
 	uinfo->value.integer.min = 0;		/* mute (-64dB) */
-	uinfo->value.integer.max = MASTER_RES;	/* 0dB */
+	uinfo->value.integer.max = PCM_RES;	/* 0dB */
 	return 0;
 }
 
-static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned short val;
 
 	down(&ice->gpio_mutex);
 	val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
-	val = val > MASTER_MIN ? (val - MASTER_MIN) : 0;
+	val = val > PCM_MIN ? (val - PCM_MIN) : 0;
 	ucontrol->value.integer.value[0] = val;
 	up(&ice->gpio_mutex);
 	return 0;
 }
 
-static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned short ovol, nvol;
@@ -306,7 +726,7 @@
 
 	snd_ice1712_save_gpio_status(ice);
 	nvol = ucontrol->value.integer.value[0];
-	nvol = (nvol ? (nvol + MASTER_MIN) : 0) & 0xff;
+	nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
 	ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
 	if (ovol != nvol) {
 		wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
@@ -355,7 +775,7 @@
 		old = wm_get(ice, WM_ADC_GAIN + i);
 		new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
 		if (new != old) {
-			wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN, new);
+			wm_put(ice, WM_ADC_GAIN + i, new);
 			change = 1;
 		}
 	}
@@ -589,42 +1009,96 @@
 static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = wm_master_mute_info,
+		.get = wm_master_mute_get,
+		.put = wm_master_mute_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = wm_master_vol_info,
+		.get = wm_master_vol_get,
+		.put = wm_master_vol_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Front Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (2 << 8) | 0
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Front Playback Volume",
-		.info = wm_dac_vol_info,
-		.get = wm_dac_vol_get,
-		.put = wm_dac_vol_put,
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
 		.private_value = (2 << 8) | 0
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Rear Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (2 << 8) | 2
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Rear Playback Volume",
-		.info = wm_dac_vol_info,
-		.get = wm_dac_vol_get,
-		.put = wm_dac_vol_put,
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
 		.private_value = (2 << 8) | 2
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Center Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (1 << 8) | 4
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Center Playback Volume",
-		.info = wm_dac_vol_info,
-		.get = wm_dac_vol_get,
-		.put = wm_dac_vol_put,
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
 		.private_value = (1 << 8) | 4
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "LFE Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (1 << 8) | 5
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "LFE Playback Volume",
-		.info = wm_dac_vol_info,
-		.get = wm_dac_vol_get,
-		.put = wm_dac_vol_put,
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
 		.private_value = (1 << 8) | 5
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Side Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (2 << 8) | 6
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Side Playback Volume",
-		.info = wm_dac_vol_info,
-		.get = wm_dac_vol_get,
-		.put = wm_dac_vol_put,
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
 		.private_value = (2 << 8) | 6
 	}
 };
@@ -632,17 +1106,17 @@
 static snd_kcontrol_new_t wm_controls[] __devinitdata = {
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = wm_dac_mute_info,
-		.get = wm_dac_mute_get,
-		.put = wm_dac_mute_put,
+		.name = "PCM Playback Switch",
+		.info = wm_pcm_mute_info,
+		.get = wm_pcm_mute_get,
+		.put = wm_pcm_mute_put
  	},
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Volume",
-		.info = wm_master_vol_info,
-		.get = wm_master_vol_get,
-		.put = wm_master_vol_put,
+		.name = "PCM Playback Volume",
+		.info = wm_pcm_vol_info,
+		.get = wm_pcm_vol_get,
+		.put = wm_pcm_vol_put
  	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -650,14 +1124,13 @@
 		.info = wm_adc_mute_info,
 		.get = wm_adc_mute_get,
 		.put = wm_adc_mute_put,
-
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Capture Volume",
 		.info = wm_adc_vol_info,
 		.get = wm_adc_vol_get,
-		.put = wm_adc_vol_put,
+		.put = wm_adc_vol_put
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -665,6 +1138,7 @@
 		.info = wm_adc_mux_info,
 		.get = wm_adc_mux_get,
 		.put = wm_adc_mux_put,
+		.private_value = 5
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -689,7 +1163,96 @@
 	},
 };
 
-
+static snd_kcontrol_new_t ac97_controls[] __devinitdata = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "AC97 Playback Switch",
+		.info = aureon_ac97_mmute_info,
+		.get = aureon_ac97_mmute_get,
+		.put = aureon_ac97_mmute_put,
+		.private_value = AC97_MASTER
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "AC97 Playback Volume",
+ 		.info = aureon_ac97_vol_info,
+ 		.get = aureon_ac97_vol_get,
+ 		.put = aureon_ac97_vol_put,
+ 		.private_value = AC97_MASTER|AUREON_AC97_STEREO
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "CD Playback Switch",
+ 		.info = aureon_ac97_mute_info,
+ 		.get = aureon_ac97_mute_get,
+ 		.put = aureon_ac97_mute_put,
+ 		.private_value = AC97_CD
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "CD Playback Volume",
+ 		.info = aureon_ac97_vol_info,
+ 		.get = aureon_ac97_vol_get,
+ 		.put = aureon_ac97_vol_put,
+ 		.private_value = AC97_CD|AUREON_AC97_STEREO
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Aux Playback Switch",
+ 		.info = aureon_ac97_mute_info,
+ 		.get = aureon_ac97_mute_get,
+ 		.put = aureon_ac97_mute_put,
+ 		.private_value = AC97_AUX,
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Aux Playback Volume",
+ 		.info = aureon_ac97_vol_info,
+ 		.get = aureon_ac97_vol_get,
+ 		.put = aureon_ac97_vol_put,
+ 		.private_value = AC97_AUX|AUREON_AC97_STEREO
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Line Playback Switch",
+ 		.info = aureon_ac97_mute_info,
+ 		.get = aureon_ac97_mute_get,
+ 		.put = aureon_ac97_mute_put,
+ 		.private_value = AC97_LINE
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Line Playback Volume",
+ 		.info = aureon_ac97_vol_info,
+ 		.get = aureon_ac97_vol_get,
+ 		.put = aureon_ac97_vol_put,
+ 		.private_value = AC97_LINE|AUREON_AC97_STEREO
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Mic Playback Switch",
+ 		.info = aureon_ac97_mute_info,
+ 		.get = aureon_ac97_mute_get,
+ 		.put = aureon_ac97_mute_put,
+ 		.private_value = AC97_MIC
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Mic Playback Volume",
+ 		.info = aureon_ac97_vol_info,
+ 		.get = aureon_ac97_vol_get,
+ 		.put = aureon_ac97_vol_put,
+ 		.private_value = AC97_MIC
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ 		.name = "Mic Boost",
+ 		.info = aureon_ac97_micboost_info,
+ 		.get = aureon_ac97_micboost_get,
+ 		.put = aureon_ac97_micboost_put
+ 	}
+};
+ 
 static int __devinit aureon_add_controls(ice1712_t *ice)
 {
 	unsigned int i, counts;
@@ -697,7 +1260,7 @@
 
 	counts = ARRAY_SIZE(aureon_dac_controls);
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
-		counts--; /* no side */
+		counts -= 2; /* no side */
 	for (i = 0; i < counts; i++) {
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
 		if (err < 0)
@@ -709,6 +1272,13 @@
 		if (err < 0)
 			return err;
 	}
+	
+	for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
+		err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+	
 	return 0;
 }
 
@@ -720,9 +1290,9 @@
 {
 	static unsigned short wm_inits_aureon[] = {
 		/* These come first to reduce init pop noise */
-		0x1b, 0x000,		/* ADC Mux */
-		0x1c, 0x009,		/* Out Mux1 */
-		0x1d, 0x009,		/* Out Mux2 */
+		0x1b, 0x005,		/* ADC Mux (AC'97 source) */
+		0x1c, 0x00B,		/* Out Mux1 (VOUT1 = ADC+AUX, VOUT2 = ADC) */
+		0x1d, 0x009,		/* Out Mux2 (VOUT2 = ADC, VOUT3 = ADC) */
 
 		0x18, 0x000,		/* All power-up */
 
@@ -798,14 +1368,15 @@
 	};
 	static unsigned short cs_inits[] = {
 		0x0441, /* RUN */
-		0x0100, /* no mute */
-		0x0200, /* */
-		0x0600, /* slave, 24bit */
+		0x0180, /* no mute, OMCK output on RMCK pin */
+		0x0201, /* S/PDIF source on RXP1 */
+		0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
 		(unsigned short)-1
 	};
 	unsigned int tmp;
 	unsigned short *p;
 	unsigned int cscs;
+	int err, i;
 
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
 		ice->num_total_dacs = 6;
@@ -816,23 +1387,27 @@
 		ice->num_total_adcs = 2;
 	}
 
-	/* to remeber the register values */
+	/* to remeber the register values of CS8415 */
 	ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ice->akm)
 		return -ENOMEM;
 	ice->akm_codecs = 1;
+	
+	if ((err = aureon_ac97_init(ice)) != 0)
+		return err;
 
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
 		cscs = PRODIGY_CS8415_CS;
 	else
 		cscs = AUREON_CS8415_CS;
 
-	snd_ice1712_gpio_set_dir(ice, 0xbfffff); /* fix this for the time being */
+	snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
 
 	/* reset the wm codec as the SPI mode */
 	snd_ice1712_save_gpio_status(ice);
 	snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|
 					 cscs|AUREON_HP_SEL));
+
 	tmp = snd_ice1712_gpio_read(ice);
 	tmp &= ~AUREON_WM_RESET;
 	snd_ice1712_gpio_write(ice, tmp);
@@ -860,6 +1435,13 @@
 	aureon_set_headphone_amp(ice, 1);
 
 	snd_ice1712_restore_gpio_status(ice);
+	
+	ice->spec.aureon.master[0] = WM_VOL_MUTE;
+	ice->spec.aureon.master[1] = WM_VOL_MUTE;
+	for (i = 0; i < ice->num_total_dacs; i++) {
+		ice->spec.aureon.vol[i] = WM_VOL_MUTE;
+		wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
+	}
 
 	return 0;
 }
@@ -873,14 +1455,14 @@
 static unsigned char aureon51_eeprom[] __devinitdata = {
 	0x0a,	/* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
 	0x80,	/* ACLINK: I2S */
-	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
+	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
 	0xff,	/* GPIO_DIR */
 	0xff,	/* GPIO_DIR1 */
-	0xbf,	/* GPIO_DIR2 */
-	0xff,	/* GPIO_MASK */
-	0xff,	/* GPIO_MASK1 */
-	0xff,	/* GPIO_MASK2 */
+	0x5f,	/* GPIO_DIR2 */
+	0x00,	/* GPIO_MASK */
+	0x00,	/* GPIO_MASK1 */
+	0x00,	/* GPIO_MASK2 */
 	0x00,	/* GPIO_STATE */
 	0x00,	/* GPIO_STATE1 */
 	0x00,	/* GPIO_STATE2 */
@@ -889,11 +1471,11 @@
 static unsigned char aureon71_eeprom[] __devinitdata = {
 	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
 	0x80,	/* ACLINK: I2S */
-	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
+	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
 	0xff,	/* GPIO_DIR */
 	0xff,	/* GPIO_DIR1 */
-	0xbf,	/* GPIO_DIR2 */
+	0x5f,	/* GPIO_DIR2 */
 	0x00,	/* GPIO_MASK */
 	0x00,	/* GPIO_MASK1 */
 	0x00,	/* GPIO_MASK2 */
@@ -905,11 +1487,11 @@
 static unsigned char prodigy71_eeprom[] __devinitdata = {
 	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
 	0x80,	/* ACLINK: I2S */
-	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
+	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
 	0xff,	/* GPIO_DIR */
 	0xff,	/* GPIO_DIR1 */
-	0xbf,	/* GPIO_DIR2 */
+	0x5f,	/* GPIO_DIR2 */
 	0x00,	/* GPIO_MASK */
 	0x00,	/* GPIO_MASK1 */
 	0x00,	/* GPIO_MASK2 */
diff -Nru a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h
--- a/sound/pci/ice1712/aureon.h	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/ice1712/aureon.h	2004-10-28 22:25:59 -07:00
@@ -47,6 +47,11 @@
 #define AUREON_DIGITAL_SEL1	(1 << 15)
 #define AUREON_HP_SEL		(1 << 14)
 #define AUREON_WM_CS		(1 << 12)
+#define AUREON_AC97_COMMIT	(1 << 11)
+#define AUREON_AC97_ADDR	(1 << 10)
+#define AUREON_AC97_DATA_LOW	(1 << 9)
+#define AUREON_AC97_DATA_HIGH	(1 << 8)
+#define AUREON_AC97_DATA_MASK	0xFF
 
 /* Prodigy has different pin assignment for chip select */
 #define PRODIGY_CS8415_CS	(1 << 23)
diff -Nru a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
--- a/sound/pci/ice1712/delta.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/ice1712/delta.c	2004-10-28 22:25:57 -07:00
@@ -526,6 +526,7 @@
 		break;
 	case ICE1712_SUBDEVICE_DELTA1010:
 	case ICE1712_SUBDEVICE_DELTA1010LT:
+	case ICE1712_SUBDEVICE_MEDIASTATION:
 		ice->num_total_dacs = 8;
 		ice->num_total_adcs = 8;
 		break;
@@ -551,6 +552,7 @@
 			return err;
 		break;
 	case ICE1712_SUBDEVICE_DELTA1010:
+	case ICE1712_SUBDEVICE_MEDIASTATION:
 		ice->gpio.set_pro_rate = delta_1010_set_rate_val;
 		break;
 	case ICE1712_SUBDEVICE_DELTADIO2496:
@@ -572,6 +574,7 @@
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_DELTA1010:
 	case ICE1712_SUBDEVICE_DELTADIO2496:
+	case ICE1712_SUBDEVICE_MEDIASTATION:
 		return 0;
 	}
 
@@ -630,6 +633,7 @@
 	/* 1010 and dio specific controls */
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_DELTA1010:
+	case ICE1712_SUBDEVICE_MEDIASTATION:
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010_wordclock_select, ice));
 		if (err < 0)
 			return err;
@@ -654,6 +658,7 @@
 	case ICE1712_SUBDEVICE_DELTA1010:
 	case ICE1712_SUBDEVICE_DELTADIO2496:
 	case ICE1712_SUBDEVICE_DELTA66:
+	case ICE1712_SUBDEVICE_MEDIASTATION:
 		err = snd_ice1712_spdif_build_controls(ice);
 		if (err < 0)
 			return err;
@@ -665,6 +670,7 @@
 	case ICE1712_SUBDEVICE_DELTA1010:
 	case ICE1712_SUBDEVICE_DELTADIO2496:
 	case ICE1712_SUBDEVICE_DELTA66:
+	case ICE1712_SUBDEVICE_MEDIASTATION:
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta_spdif_in_status, ice));
 		if (err < 0)
 			return err;
@@ -750,6 +756,13 @@
 		.chip_init = snd_ice1712_delta_init,
 		.build_controls = snd_ice1712_delta_add_controls,
 		.no_mpu401 = 1,
+	},
+	{
+		.subvendor = ICE1712_SUBDEVICE_MEDIASTATION,
+		.name = "Lionstracs Mediastation",
+		.model = "mediastation",
+		.chip_init = snd_ice1712_delta_init,
+		.build_controls = snd_ice1712_delta_add_controls,
 	},
 	{ } /* terminator */
 };
diff -Nru a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
--- a/sound/pci/ice1712/delta.h	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/ice1712/delta.h	2004-10-28 22:25:58 -07:00
@@ -32,7 +32,8 @@
 		"{MidiMan M Audio,Delta 66},"\
 		"{MidiMan M Audio,Delta 44},"\
 		"{MidiMan M Audio,Audiophile 24/96},"\
-		"{Digigram,VX442},"
+		"{Digigram,VX442},"\
+		"{Lionstracs,Mediastation},"
 
 #define ICE1712_SUBDEVICE_DELTA1010	0x121430d6
 #define ICE1712_SUBDEVICE_DELTADIO2496	0x121431d6
@@ -42,6 +43,7 @@
 #define ICE1712_SUBDEVICE_DELTA410	0x121438d6
 #define ICE1712_SUBDEVICE_DELTA1010LT	0x12143bd6
 #define ICE1712_SUBDEVICE_VX442		0x12143cd6
+#define ICE1712_SUBDEVICE_MEDIASTATION	0x694c0100
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
diff -Nru a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
--- a/sound/pci/ice1712/ews.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/ice1712/ews.c	2004-10-28 22:25:57 -07:00
@@ -38,6 +38,13 @@
 #define SND_CS8404
 #include <sound/cs8403.h>
 
+enum {
+	EWS_I2C_CS8404 = 0, EWS_I2C_PCF1, EWS_I2C_PCF2,
+	EWS_I2C_88D = 0,
+	EWS_I2C_6FIRE = 0
+};
+	
+
 /*
  * access via i2c mode (for EWX 24/96, EWS 88MT&D)
  */
@@ -139,11 +146,11 @@
 
 	snd_assert(chip_mask >= 0 && chip_mask <= 0x0f, return -EINVAL);
 	snd_i2c_lock(ice->i2c);
-	if (snd_i2c_readbytes(ice->i2cdevs[1], &data, 1) != 1)
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &data, 1) != 1)
 		goto __error;
 	ndata = (data & 0xf0) | chip_mask;
 	if (ndata != data)
-		if (snd_i2c_sendbytes(ice->i2cdevs[1], &ndata, 1) != 1)
+		if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &ndata, 1) != 1)
 			goto __error;
 	snd_i2c_unlock(ice->i2c);
 	return 0;
@@ -224,13 +231,16 @@
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
-		snd_runtime_check(snd_i2c_sendbytes(ice->cs8404, &bits, 1) == 1, goto _error);
+		if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_CS8404], &bits, 1) != 1)
+			goto _error;
 		break;
 	case ICE1712_SUBDEVICE_EWS88D:
-		snd_runtime_check(snd_i2c_readbytes(ice->i2cdevs[0], bytes, 2) == 2, goto _error);
+		if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_88D], bytes, 2) != 2)
+			goto _error;
 		if (bits != bytes[1]) {
 			bytes[1] = bits;
-			snd_runtime_check(snd_i2c_readbytes(ice->i2cdevs[0], bytes, 2) == 2, goto _error);
+			if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_88D], bytes, 2) != 2)
+				goto _error;
 		}
 		break;
 	}
@@ -416,7 +426,10 @@
 		ice->num_total_adcs = 8;
 		break;
 	case ICE1712_SUBDEVICE_EWS88D:
-		break; /* no analog */
+		/* Note: not analog but ADAT I/O */
+		ice->num_total_dacs = 8;
+		ice->num_total_adcs = 8;
+		break;
 	case ICE1712_SUBDEVICE_DMX6FIRE:
 		ice->num_total_dacs = 6;
 		ice->num_total_adcs = 6;
@@ -434,7 +447,7 @@
 	/* create i2c devices */
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_DMX6FIRE:
-		if ((err = snd_i2c_device_create(ice->i2c, "PCF9554", ICE1712_6FIRE_PCF9554_ADDR, &ice->i2cdevs[0])) < 0) {
+		if ((err = snd_i2c_device_create(ice->i2c, "PCF9554", ICE1712_6FIRE_PCF9554_ADDR, &ice->spec.i2cdevs[EWS_I2C_6FIRE])) < 0) {
 			snd_printk("PCF9554 initialization failed\n");
 			return err;
 		}
@@ -443,18 +456,18 @@
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
 	case ICE1712_SUBDEVICE_PHASE88:
-		if ((err = snd_i2c_device_create(ice->i2c, "CS8404", ICE1712_EWS88MT_CS8404_ADDR, &ice->cs8404)) < 0)
+		if ((err = snd_i2c_device_create(ice->i2c, "CS8404", ICE1712_EWS88MT_CS8404_ADDR, &ice->spec.i2cdevs[EWS_I2C_CS8404])) < 0)
 			return err;
-		if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (1st)", ICE1712_EWS88MT_INPUT_ADDR, &ice->i2cdevs[0])) < 0)
+		if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (1st)", ICE1712_EWS88MT_INPUT_ADDR, &ice->spec.i2cdevs[EWS_I2C_PCF1])) < 0)
 			return err;
-		if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (2nd)", ICE1712_EWS88MT_OUTPUT_ADDR, &ice->i2cdevs[1])) < 0)
+		if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (2nd)", ICE1712_EWS88MT_OUTPUT_ADDR, &ice->spec.i2cdevs[EWS_I2C_PCF2])) < 0)
 			return err;
 		/* Check if the front module is connected */
 		if ((err = snd_ice1712_ews88mt_chip_select(ice, 0x0f)) < 0)
 			return err;
 		break;
 	case ICE1712_SUBDEVICE_EWS88D:
-		if ((err = snd_i2c_device_create(ice->i2c, "PCF8575", ICE1712_EWS88D_PCF_ADDR, &ice->i2cdevs[0])) < 0)
+		if ((err = snd_i2c_device_create(ice->i2c, "PCF8575", ICE1712_EWS88D_PCF_ADDR, &ice->spec.i2cdevs[EWS_I2C_88D])) < 0)
 			return err;
 		break;
 	}
@@ -595,7 +608,7 @@
 	unsigned char data;
 
 	snd_i2c_lock(ice->i2c);
-	if (snd_i2c_readbytes(ice->i2cdevs[1], &data, 1) != 1) {
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
@@ -611,12 +624,12 @@
 	unsigned char data, ndata;
 
 	snd_i2c_lock(ice->i2c);
-	if (snd_i2c_readbytes(ice->i2cdevs[1], &data, 1) != 1) {
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
 	ndata = (data & ~ICE1712_EWS88MT_OUTPUT_SENSE) | (ucontrol->value.enumerated.item[0] ? ICE1712_EWS88MT_OUTPUT_SENSE : 0);
-	if (ndata != data && snd_i2c_sendbytes(ice->i2cdevs[1], &ndata, 1) != 1) {
+	if (ndata != data && snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_PCF2], &ndata, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
@@ -633,7 +646,7 @@
 
 	snd_assert(channel >= 0 && channel <= 7, return 0);
 	snd_i2c_lock(ice->i2c);
-	if (snd_i2c_readbytes(ice->i2cdevs[0], &data, 1) != 1) {
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
@@ -652,12 +665,12 @@
 
 	snd_assert(channel >= 0 && channel <= 7, return 0);
 	snd_i2c_lock(ice->i2c);
-	if (snd_i2c_readbytes(ice->i2cdevs[0], &data, 1) != 1) {
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_PCF1], &data, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
 	ndata = (data & ~(1 << channel)) | (ucontrol->value.enumerated.item[0] ? 0 : (1 << channel));
-	if (ndata != data && snd_i2c_sendbytes(ice->i2cdevs[0], &ndata, 1) != 1) {
+	if (ndata != data && snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_PCF1], &ndata, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
@@ -704,7 +717,7 @@
 	unsigned char data[2];
 	
 	snd_i2c_lock(ice->i2c);
-	if (snd_i2c_readbytes(ice->i2cdevs[0], data, 2) != 2) {
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_88D], data, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
@@ -725,7 +738,7 @@
 	int change;
 
 	snd_i2c_lock(ice->i2c);
-	if (snd_i2c_readbytes(ice->i2cdevs[0], data, 2) != 2) {
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_88D], data, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
@@ -738,7 +751,7 @@
 			ndata[shift >> 3] |= (1 << (shift & 7));
 	}
 	change = (data[shift >> 3] != ndata[shift >> 3]);
-	if (change && snd_i2c_sendbytes(ice->i2cdevs[0], data, 2) != 2) {
+	if (change && snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_88D], data, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
@@ -774,9 +787,9 @@
 	unsigned char byte;
 	snd_i2c_lock(ice->i2c);
 	byte = reg;
-	snd_i2c_sendbytes(ice->i2cdevs[0], &byte, 1);
+	snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_6FIRE], &byte, 1);
 	byte = 0;
-	if (snd_i2c_readbytes(ice->i2cdevs[0], &byte, 1) != 1) {
+	if (snd_i2c_readbytes(ice->spec.i2cdevs[EWS_I2C_6FIRE], &byte, 1) != 1) {
 		snd_i2c_unlock(ice->i2c);
 		printk("cannot read pca\n");
 		return -EIO;
@@ -791,7 +804,7 @@
 	snd_i2c_lock(ice->i2c);
 	bytes[0] = reg;
 	bytes[1] = data;
-	if (snd_i2c_sendbytes(ice->i2cdevs[0], bytes, 2) != 2) {
+	if (snd_i2c_sendbytes(ice->spec.i2cdevs[EWS_I2C_6FIRE], bytes, 2) != 2) {
 		snd_i2c_unlock(ice->i2c);
 		return -EIO;
 	}
diff -Nru a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
--- a/sound/pci/ice1712/hoontech.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/ice1712/hoontech.c	2004-10-28 22:25:58 -07:00
@@ -49,24 +49,24 @@
 static void __devinit snd_ice1712_stdsp24_darear(ice1712_t *ice, int activate)
 {
 	down(&ice->gpio_mutex);
-	ICE1712_STDSP24_0_DAREAR(ice->hoontech_boxbits, activate);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[0]);
+	ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, activate);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]);
 	up(&ice->gpio_mutex);
 }
 
 static void __devinit snd_ice1712_stdsp24_mute(ice1712_t *ice, int activate)
 {
 	down(&ice->gpio_mutex);
-	ICE1712_STDSP24_3_MUTE(ice->hoontech_boxbits, activate);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
+	ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, activate);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]);
 	up(&ice->gpio_mutex);
 }
 
 static void __devinit snd_ice1712_stdsp24_insel(ice1712_t *ice, int activate)
 {
 	down(&ice->gpio_mutex);
-	ICE1712_STDSP24_3_INSEL(ice->hoontech_boxbits, activate);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
+	ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, activate);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]);
 	up(&ice->gpio_mutex);
 }
 
@@ -75,45 +75,45 @@
 	down(&ice->gpio_mutex);
 
 	/* select box */
-	ICE1712_STDSP24_0_BOX(ice->hoontech_boxbits, box);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[0]);
+	ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]);
 
 	/* prepare for write */
 	if (chn == 3)
-		ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 0);
-	ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, activate);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
-
-	ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 1);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[1]);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
+		ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 0);
+	ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, activate);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]);
+
+	ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 1);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[1]);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
 	udelay(100);
 	if (chn == 3) {
-		ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 0);
-		snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
+		ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 0);
+		snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
 	} else {
 		switch (chn) {
-		case 0:	ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 0); break;
-		case 1:	ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 0); break;
-		case 2:	ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 0); break;
+		case 0:	ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 0); break;
+		case 1:	ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 0); break;
+		case 2:	ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 0); break;
 		}
-		snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[1]);
+		snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[1]);
 	}
 	udelay(100);
-	ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 1);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[1]);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
+	ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 1);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[1]);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
 	udelay(100);
 
-	ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, 0);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
+	ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, 0);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
 
 	up(&ice->gpio_mutex);
 }
@@ -123,23 +123,23 @@
 	down(&ice->gpio_mutex);
 
 	/* select box */
-	ICE1712_STDSP24_0_BOX(ice->hoontech_boxbits, box);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[0]);
+	ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, box);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[0]);
 
-	ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, master);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
+	ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, master);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]);
 
 	udelay(100);
 	
-	ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 0);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
+	ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 0);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
 	
 	mdelay(10);
 	
-	ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 1);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
+	ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[2]);
 
 	up(&ice->gpio_mutex);
 }
@@ -147,8 +147,8 @@
 static void __devinit snd_ice1712_stdsp24_midi2(ice1712_t *ice, int activate)
 {
 	down(&ice->gpio_mutex);
-	ICE1712_STDSP24_3_MIDI2(ice->hoontech_boxbits, activate);
-	snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
+	ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, activate);
+	snd_ice1712_stdsp24_gpio_write(ice, ice->spec.hoontech.boxbits[3]);
 	up(&ice->gpio_mutex);
 }
 
@@ -159,57 +159,57 @@
 	ice->num_total_dacs = 8;
 	ice->num_total_adcs = 8;
 
-	ice->hoontech_boxbits[0] = 
-	ice->hoontech_boxbits[1] = 
-	ice->hoontech_boxbits[2] = 
-	ice->hoontech_boxbits[3] = 0;	/* should be already */
-
-	ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 0);
-	ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 0, 1);
-	ICE1712_STDSP24_0_BOX(ice->hoontech_boxbits, 0);
-	ICE1712_STDSP24_0_DAREAR(ice->hoontech_boxbits, 0);
-
-	ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 1, 1);
-	ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 1);
+	ice->spec.hoontech.boxbits[0] = 
+	ice->spec.hoontech.boxbits[1] = 
+	ice->spec.hoontech.boxbits[2] = 
+	ice->spec.hoontech.boxbits[3] = 0;	/* should be already */
+
+	ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 0);
+	ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 0, 1);
+	ICE1712_STDSP24_0_BOX(ice->spec.hoontech.boxbits, 0);
+	ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, 0);
+
+	ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 1, 1);
+	ICE1712_STDSP24_1_CHN1(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_1_CHN2(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_1_CHN3(ice->spec.hoontech.boxbits, 1);
 	
-	ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 2);
-	ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 2, 1);
-	ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, 0);
-
-	ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 3);
-	ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 3, 1);
-	ICE1712_STDSP24_3_MIDI2(ice->hoontech_boxbits, 0);
-	ICE1712_STDSP24_3_MUTE(ice->hoontech_boxbits, 1);
-	ICE1712_STDSP24_3_INSEL(ice->hoontech_boxbits, 0);
+	ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 2);
+	ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 2, 1);
+	ICE1712_STDSP24_2_CHN4(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_2_MIDIIN(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_2_MIDI1(ice->spec.hoontech.boxbits, 0);
+
+	ICE1712_STDSP24_SET_ADDR(ice->spec.hoontech.boxbits, 3);
+	ICE1712_STDSP24_CLOCK(ice->spec.hoontech.boxbits, 3, 1);
+	ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, 0);
+	ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, 1);
+	ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, 0);
 
 	/* let's go - activate only functions in first box */
-	ice->hoontech_config = 0;
+	ice->spec.hoontech.config = 0;
 			    /* ICE1712_STDSP24_MUTE |
 			       ICE1712_STDSP24_INSEL |
 			       ICE1712_STDSP24_DAREAR; */
-	ice->hoontech_boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
+	ice->spec.hoontech.boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
 				     ICE1712_STDSP24_BOX_CHN2 |
 				     ICE1712_STDSP24_BOX_CHN3 |
 				     ICE1712_STDSP24_BOX_CHN4 |
 				     ICE1712_STDSP24_BOX_MIDI1 |
 				     ICE1712_STDSP24_BOX_MIDI2;
-	ice->hoontech_boxconfig[1] = 
-	ice->hoontech_boxconfig[2] = 
-	ice->hoontech_boxconfig[3] = 0;
-	snd_ice1712_stdsp24_darear(ice, (ice->hoontech_config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
-	snd_ice1712_stdsp24_mute(ice, (ice->hoontech_config & ICE1712_STDSP24_MUTE) ? 1 : 0);
-	snd_ice1712_stdsp24_insel(ice, (ice->hoontech_config & ICE1712_STDSP24_INSEL) ? 1 : 0);
+	ice->spec.hoontech.boxconfig[1] = 
+	ice->spec.hoontech.boxconfig[2] = 
+	ice->spec.hoontech.boxconfig[3] = 0;
+	snd_ice1712_stdsp24_darear(ice, (ice->spec.hoontech.config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
+	snd_ice1712_stdsp24_mute(ice, (ice->spec.hoontech.config & ICE1712_STDSP24_MUTE) ? 1 : 0);
+	snd_ice1712_stdsp24_insel(ice, (ice->spec.hoontech.config & ICE1712_STDSP24_INSEL) ? 1 : 0);
 	for (box = 0; box < 4; box++) {
 		for (chn = 0; chn < 4; chn++)
-			snd_ice1712_stdsp24_box_channel(ice, box, chn, (ice->hoontech_boxconfig[box] & (1 << chn)) ? 1 : 0);
+			snd_ice1712_stdsp24_box_channel(ice, box, chn, (ice->spec.hoontech.boxconfig[box] & (1 << chn)) ? 1 : 0);
 		snd_ice1712_stdsp24_box_midi(ice, box,
-				(ice->hoontech_boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0);
-		if (ice->hoontech_boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
+				(ice->spec.hoontech.boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0);
+		if (ice->spec.hoontech.boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
 			snd_ice1712_stdsp24_midi2(ice, 1);
 	}
 
diff -Nru a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
--- a/sound/pci/ice1712/ice1712.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/ice1712/ice1712.c	2004-10-28 22:25:57 -07:00
@@ -2307,28 +2307,47 @@
 {
 	int dev = 0xa0;		/* EEPROM device address */
 	unsigned int i, size;
+	struct snd_ice1712_card_info **tbl, *c;
 
-	if ((inb(ICEREG(ice, I2C_CTRL)) & ICE1712_I2C_EEPROM) == 0) {
-		snd_printk("ICE1712 has not detected EEPROM\n");
-		return -EIO;
-	}
-	if (modelname && *modelname) {
-		struct snd_ice1712_card_info **tbl, *c;
-		for (tbl = card_tables; *tbl; tbl++) {
-			for (c = *tbl; c->subvendor; c++) {
-				if (c->model && !strcmp(modelname, c->model)) {
-					/* use the given subvendor */
-					printk(KERN_INFO "ice1712: Using board model %s\n", c->name);
-					ice->eeprom.subvendor = c->subvendor;
-					break;
-				}
+	if (! modelname || ! *modelname) {
+		ice->eeprom.subvendor = 0;
+		if ((inb(ICEREG(ice, I2C_CTRL)) & ICE1712_I2C_EEPROM) != 0)
+			ice->eeprom.subvendor = (snd_ice1712_read_i2c(ice, dev, 0x00) << 0) |
+				(snd_ice1712_read_i2c(ice, dev, 0x01) << 8) | 
+				(snd_ice1712_read_i2c(ice, dev, 0x02) << 16) | 
+				(snd_ice1712_read_i2c(ice, dev, 0x03) << 24);
+		if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) {
+			/* invalid subvendor from EEPROM, try the PCI subststem ID instead */
+			u16 vendor, device;
+			pci_read_config_word(ice->pci, PCI_SUBSYSTEM_VENDOR_ID, &vendor);
+			pci_read_config_word(ice->pci, PCI_SUBSYSTEM_ID, &device);
+			ice->eeprom.subvendor = ((unsigned int)swab16(vendor) << 16) | swab16(device);
+			if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) {
+				printk(KERN_ERR "ice1712: No valid ID is found\n");
+				return -ENXIO;
 			}
 		}
-	} else
-		ice->eeprom.subvendor = (snd_ice1712_read_i2c(ice, dev, 0x00) << 0) |
-			(snd_ice1712_read_i2c(ice, dev, 0x01) << 8) | 
-			(snd_ice1712_read_i2c(ice, dev, 0x02) << 16) | 
-			(snd_ice1712_read_i2c(ice, dev, 0x03) << 24);
+	}
+	for (tbl = card_tables; *tbl; tbl++) {
+		for (c = *tbl; c->subvendor; c++) {
+			if (modelname && c->model && ! strcmp(modelname, c->model)) {
+				printk(KERN_INFO "ice1712: Using board model %s\n", c->name);
+				ice->eeprom.subvendor = c->subvendor;
+			} else if (c->subvendor != ice->eeprom.subvendor)
+				continue;
+			if (! c->eeprom_size || ! c->eeprom_data)
+				goto found;
+			/* if the EEPROM is given by the driver, use it */
+			snd_printdd("using the defined eeprom..\n");
+			ice->eeprom.version = 1;
+			ice->eeprom.size = c->eeprom_size + 6;
+			memcpy(ice->eeprom.data, c->eeprom_data, c->eeprom_size);
+			goto read_skipped;
+		}
+	}
+	printk(KERN_WARNING "ice1712: No matching model found for ID 0x%x\n", ice->eeprom.subvendor);
+
+ found:
 	ice->eeprom.size = snd_ice1712_read_i2c(ice, dev, 0x04);
 	if (ice->eeprom.size < 6)
 		ice->eeprom.size = 32; /* FIXME: any cards without the correct size? */
@@ -2345,6 +2364,7 @@
 	for (i = 0; i < size; i++)
 		ice->eeprom.data[i] = snd_ice1712_read_i2c(ice, dev, i + 6);
 
+ read_skipped:
 	ice->eeprom.gpiomask = ice->eeprom.data[ICE_EEP1_GPIO_MASK];
 	ice->eeprom.gpiostate = ice->eeprom.data[ICE_EEP1_GPIO_STATE];
 	ice->eeprom.gpiodir = ice->eeprom.data[ICE_EEP1_GPIO_DIR];
diff -Nru a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
--- a/sound/pci/ice1712/ice1712.h	2004-10-28 22:25:56 -07:00
+++ b/sound/pci/ice1712/ice1712.h	2004-10-28 22:25:56 -07:00
@@ -331,9 +331,6 @@
 	unsigned int force_rdma1: 1;	/* VT1720/4 - RDMA1 as non-spdif */
 	unsigned int num_total_dacs;	/* total DACs */
 	unsigned int num_total_adcs;	/* total ADCs */
-	unsigned char hoontech_boxbits[4];
-	unsigned int hoontech_config;
-	unsigned short hoontech_boxconfig[4];
 	unsigned int cur_rate;		/* current rate */
 
 	struct semaphore open_mutex;
@@ -344,10 +341,8 @@
 	struct snd_ice1712_spdif spdif;
 
 	snd_i2c_bus_t *i2c;		/* I2C bus */
-	snd_i2c_device_t *cs8404;	/* CS8404A I2C device */
 	snd_i2c_device_t *cs8427;	/* CS8427 I2C device */
 	unsigned int cs8427_timeout;	/* CS8427 reset timeout in HZ/100 */
-	snd_i2c_device_t *i2cdevs[2];	/* additional i2c devices */
 	
 	struct ice1712_gpio {
 		unsigned int direction;		/* current direction bits */
@@ -362,6 +357,25 @@
 		void (*set_pro_rate)(ice1712_t *ice, unsigned int rate);
 	} gpio;
 	struct semaphore gpio_mutex;
+
+	/* other board-specific data */
+	union {
+		/* additional i2c devices for EWS boards*/
+		snd_i2c_device_t *i2cdevs[3];
+		/* AC97 register cache for Aureon */
+		struct aureon_spec {
+			unsigned short stac9744[64];
+			unsigned short master[2];
+			unsigned short vol[8];
+		} aureon;
+		/* Hoontech-specific setting */
+		struct hoontech_spec {
+			unsigned char boxbits[4];
+			unsigned int config;
+			unsigned short boxconfig[4];
+		} hoontech;
+	} spec;
+
 };
 
 
diff -Nru a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
--- a/sound/pci/ice1712/ice1724.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/ice1712/ice1724.c	2004-10-28 22:25:58 -07:00
@@ -46,6 +46,7 @@
 #include "aureon.h"
 #include "vt1720_mobo.h"
 #include "pontis.h"
+#include "prodigy192.h"
 
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -57,6 +58,7 @@
 	       AUREON_DEVICE_DESC
 	       VT1720_MOBO_DEVICE_DESC
 	       PONTIS_DEVICE_DESC
+	       PRODIGY192_DEVICE_DESC
 		"{VIA,VT1720},"
 		"{VIA,VT1724},"
 		"{ICEnsemble,Generic ICE1724},"
@@ -67,15 +69,14 @@
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;		/* Enable this card */
 static char *model[SNDRV_CARDS];
-static int boot_devs;
 
-module_param_array(index, int, &boot_devs, 0444);
+module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for ICE1724 soundcard.");
-module_param_array(id, charp, &boot_devs, 0444);
+module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for ICE1724 soundcard.");
-module_param_array(enable, bool, &boot_devs, 0444);
+module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable ICE1724 soundcard.");
-module_param_array(model, charp, &boot_devs, 0444);
+module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 
 #ifndef PCI_VENDOR_ID_ICE
@@ -1864,6 +1865,7 @@
 	snd_vt1724_aureon_cards,
 	snd_vt1720_mobo_cards,
 	snd_vt1720_pontis_cards,
+	snd_vt1724_prodigy192_cards,
 	NULL,
 };
 
diff -Nru a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/prodigy192.c	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,524 @@
+/*
+ *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for AudioTrak Prodigy 192 cards
+ *
+ *	Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
+ *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
+ *      Copyright (c) 2004 Kouichi ONO <co2b@ceres.dti.ne.jp>
+ *
+ *   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 <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "prodigy192.h"
+#include "stac946x.h"
+
+static void stac9460_put(ice1712_t *ice, int reg, unsigned char val)
+{
+	snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val);
+}
+
+static unsigned char stac9460_get(ice1712_t *ice, int reg)
+{
+	return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg);
+}
+
+/*
+ * DAC mute control
+ */
+static int stac9460_dac_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int stac9460_dac_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+	int idx;
+
+	if (kcontrol->private_value)
+		idx = STAC946X_MASTER_VOLUME;
+	else
+		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
+	val = stac9460_get(ice, idx);
+	ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
+	return 0;
+}
+
+static int stac9460_dac_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char new, old;
+	int idx;
+	int change;
+
+	if (kcontrol->private_value)
+		idx = STAC946X_MASTER_VOLUME;
+	else
+		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
+	old = stac9460_get(ice, idx);
+	new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
+	change = (new != old);
+	if (change)
+		stac9460_put(ice, idx, new);
+
+	return change;
+}
+
+/*
+ * DAC volume attenuation mixer control
+ */
+static int stac9460_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;			/* mute */
+	uinfo->value.integer.max = 0x7f;		/* 0dB */
+	return 0;
+}
+
+static int stac9460_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int idx;
+	unsigned char vol;
+
+	if (kcontrol->private_value)
+		idx = STAC946X_MASTER_VOLUME;
+	else
+		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
+	vol = stac9460_get(ice, idx) & 0x7f;
+	ucontrol->value.integer.value[0] = 0x7f - vol;
+
+	return 0;
+}
+
+static int stac9460_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int idx;
+	unsigned char tmp, ovol, nvol;
+	int change;
+
+	if (kcontrol->private_value)
+		idx = STAC946X_MASTER_VOLUME;
+	else
+		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + STAC946X_LF_VOLUME;
+	nvol = ucontrol->value.integer.value[0];
+	tmp = stac9460_get(ice, idx);
+	ovol = 0x7f - (tmp & 0x7f);
+	change = (ovol != nvol);
+	if (change) {
+		stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
+	}
+	return change;
+}
+
+/*
+ * ADC mute control
+ */
+static int stac9460_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int stac9460_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+	int i;
+
+	for (i = 0; i < 2; ++i) {
+		val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
+		ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
+	}
+
+	return 0;
+}
+
+static int stac9460_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char new, old;
+	int i, reg;
+	int change;
+
+	for (i = 0; i < 2; ++i) {
+		reg = STAC946X_MIC_L_VOLUME + i;
+		old = stac9460_get(ice, reg);
+		new = (~ucontrol->value.integer.value[i]<<7&0x80) | (old&~0x80);
+		change = (new != old);
+		if (change)
+			stac9460_put(ice, reg, new);
+	}
+
+	return change;
+}
+
+/*
+ * ADC gain mixer control
+ */
+static int stac9460_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;		/* 0dB */
+	uinfo->value.integer.max = 0x0f;	/* 22.5dB */
+	return 0;
+}
+
+static int stac9460_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int i, reg;
+	unsigned char vol;
+
+	for (i = 0; i < 2; ++i) {
+		reg = STAC946X_MIC_L_VOLUME + i;
+		vol = stac9460_get(ice, reg) & 0x0f;
+		ucontrol->value.integer.value[i] = 0x0f - vol;
+	}
+
+	return 0;
+}
+
+static int stac9460_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int i, reg;
+	unsigned char ovol, nvol;
+	int change;
+
+	for (i = 0; i < 2; ++i) {
+		reg = STAC946X_MIC_L_VOLUME + i;
+		nvol = ucontrol->value.integer.value[i];
+		ovol = 0x0f - stac9460_get(ice, reg);
+		change = ((ovol & 0x0f)  != nvol);
+		if (change)
+			stac9460_put(ice, reg, (0x0f - nvol) | (ovol & ~0x0f));
+	}
+
+	return change;
+}
+
+#if 0
+/*
+ * Headphone Amplifier
+ */
+static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
+{
+	unsigned int tmp, tmp2;
+
+	tmp2 = tmp = snd_ice1712_gpio_read(ice);
+	if (enable)
+		tmp |= AUREON_HP_SEL;
+	else
+		tmp &= ~ AUREON_HP_SEL;
+	if (tmp != tmp2) {
+		snd_ice1712_gpio_write(ice, tmp);
+		return 1;
+	}
+	return 0;
+}
+
+static int aureon_get_headphone_amp(ice1712_t *ice)
+{
+	unsigned int tmp = snd_ice1712_gpio_read(ice);
+
+	return ( tmp & AUREON_HP_SEL )!= 0;
+}
+
+static int aureon_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
+	return 0;
+}
+
+
+static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
+}
+
+/*
+ * Deemphasis
+ */
+static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
+	return 0;
+}
+
+static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int temp, temp2;
+	temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
+	if (ucontrol->value.integer.value[0])
+		temp |= 0xf;
+	else
+		temp &= ~0xf;
+	if (temp != temp2) {
+		wm_put(ice, WM_DAC_CTRL2, temp);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * ADC Oversampling
+ */
+static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[2] = { "128x", "64x"	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+
+        return 0;
+}
+
+static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
+	return 0;
+}
+
+static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	int temp, temp2;
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	temp2 = temp = wm_get(ice, WM_MASTER);
+
+	if (ucontrol->value.enumerated.item[0])
+		temp |= 0x8;
+	else
+		temp &= ~0x8;
+
+	if (temp != temp2) {
+		wm_put(ice, WM_MASTER, temp);
+		return 1;
+	}
+	return 0;
+}
+#endif
+
+/*
+ * mixers
+ */
+
+static snd_kcontrol_new_t stac_controls[] __devinitdata = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = stac9460_dac_mute_info,
+		.get = stac9460_dac_mute_get,
+		.put = stac9460_dac_mute_put,
+		.private_value = 1,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = stac9460_dac_vol_info,
+		.get = stac9460_dac_vol_get,
+		.put = stac9460_dac_vol_put,
+		.private_value = 1,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "DAC Switch",
+		.count = 6,
+		.info = stac9460_dac_mute_info,
+		.get = stac9460_dac_mute_get,
+		.put = stac9460_dac_mute_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "DAC Volume",
+		.count = 6,
+		.info = stac9460_dac_vol_info,
+		.get = stac9460_dac_vol_get,
+		.put = stac9460_dac_vol_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "ADC Switch",
+		.count = 1,
+		.info = stac9460_adc_mute_info,
+		.get = stac9460_adc_mute_get,
+		.put = stac9460_adc_mute_put,
+
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "ADC Volume",
+		.count = 1,
+		.info = stac9460_adc_vol_info,
+		.get = stac9460_adc_vol_get,
+		.put = stac9460_adc_vol_put,
+	},
+#if 0
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Route",
+		.info = wm_adc_mux_info,
+		.get = wm_adc_mux_get,
+		.put = wm_adc_mux_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Headphone Amplifier Switch",
+		.info = aureon_bool_info,
+		.get = aureon_hpamp_get,
+		.put = aureon_hpamp_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "DAC Deemphasis Switch",
+		.info = aureon_bool_info,
+		.get = aureon_deemp_get,
+		.put = aureon_deemp_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "ADC Oversampling",
+		.info = aureon_oversampling_info,
+		.get = aureon_oversampling_get,
+		.put = aureon_oversampling_put
+	},
+#endif
+};
+
+static int __devinit prodigy192_add_controls(ice1712_t *ice)
+{
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(stac_controls); i++) {
+		err = snd_ctl_add(ice->card, snd_ctl_new1(&stac_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+
+/*
+ * initialize the chip
+ */
+static int __devinit prodigy192_init(ice1712_t *ice)
+{
+	static unsigned short stac_inits_prodigy[] = {
+		STAC946X_RESET, 0,
+/*		STAC946X_MASTER_VOLUME, 0,
+		STAC946X_LF_VOLUME, 0,
+		STAC946X_RF_VOLUME, 0,
+		STAC946X_LR_VOLUME, 0,
+		STAC946X_RR_VOLUME, 0,
+		STAC946X_CENTER_VOLUME, 0,
+		STAC946X_LFE_VOLUME, 0,*/
+		(unsigned short)-1
+	};
+	unsigned short *p;
+
+	/* prodigy 192 */
+	ice->num_total_dacs = 6;
+	ice->num_total_adcs = 2;
+	
+	/* initialize codec */
+	p = stac_inits_prodigy;
+	for (; *p != (unsigned short)-1; p += 2)
+		stac9460_put(ice, p[0], p[1]);
+
+	return 0;
+}
+
+
+/*
+ * Aureon boards don't provide the EEPROM data except for the vendor IDs.
+ * hence the driver needs to sets up it properly.
+ */
+
+static unsigned char prodigy71_eeprom[] __devinitdata = {
+	0x2b,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
+	0x80,	/* ACLINK: I2S */
+	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
+	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
+	0xff,	/* GPIO_DIR */
+	0xff,	/* GPIO_DIR1 */
+	0xbf,	/* GPIO_DIR2 */
+	0x00,	/* GPIO_MASK */
+	0x00,	/* GPIO_MASK1 */
+	0x00,	/* GPIO_MASK2 */
+	0x00,	/* GPIO_STATE */
+	0x00,	/* GPIO_STATE1 */
+	0x00,	/* GPIO_STATE2 */
+};
+
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
+	{
+		.subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
+		.name = "Audiotrak Prodigy 192",
+		.model = "prodigy192",
+		.chip_init = prodigy192_init,
+		.build_controls = prodigy192_add_controls,
+		.eeprom_size = sizeof(prodigy71_eeprom),
+		.eeprom_data = prodigy71_eeprom,
+	},
+	{ } /* terminator */
+};
diff -Nru a/sound/pci/ice1712/prodigy192.h b/sound/pci/ice1712/prodigy192.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/prodigy192.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,11 @@
+#ifndef __SOUND_PRODIGY192_H
+#define __SOUND_PRODIGY192_H
+
+#define PRODIGY192_DEVICE_DESC 	       "{AudioTrak,Prodigy 192},"
+#define PRODIGY192_STAC9460_ADDR	0x54
+
+#define VT1724_SUBDEVICE_PRODIGY192VE	 0x34495345	/* PRODIGY 192 VE */
+
+extern struct snd_ice1712_card_info  snd_vt1724_prodigy192_cards[];
+
+#endif	/* __SOUND_PRODIGY192_H */
diff -Nru a/sound/pci/ice1712/stac946x.h b/sound/pci/ice1712/stac946x.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/stac946x.h	2004-10-28 22:25:59 -07:00
@@ -0,0 +1,25 @@
+#ifndef __SOUND_STAC946X_H
+#define __SOUND_STAC946X_H
+
+#define STAC946X_RESET			0x00
+#define STAC946X_STATUS			0x01
+#define STAC946X_MASTER_VOLUME		0x02
+#define STAC946X_LF_VOLUME		0x03
+#define STAC946X_RF_VOLUME		0x04
+#define STAC946X_LR_VOLUME		0x05
+#define STAC946X_RR_VOLUME		0x06
+#define STAC946X_CENTER_VOLUME		0x07
+#define STAC946X_LFE_VOLUME		0x08
+#define STAC946X_MIC_L_VOLUME		0x09
+#define STAC946X_MIC_R_VOLUME		0x0a
+#define STAC946X_DEEMPHASIS		0x0c
+#define STAC946X_GENERAL_PURPOSE	0x0d
+#define STAC946X_AUDIO_PORT_CONTROL	0x0e
+#define STAC946X_MASTER_CLOCKING	0x0f
+#define STAC946X_POWERDOWN_CTRL1	0x10
+#define STAC946X_POWERDOWN_CTRL2	0x11
+#define STAC946X_REVISION_CODE		0x12
+#define STAC946X_ADDRESS_CONTROL	0x13
+#define STAC946X_ADDRESS		0x14
+
+#endif  /*  __SOUND_STAC946X_H */
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/intel8x0.c	2004-10-28 22:25:58 -07:00
@@ -33,13 +33,11 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/gameport.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
-#include <sound/mpu401.h>
 #include <sound/initval.h>
 /* for 440MX workaround */
 #include <asm/pgtable.h>
@@ -64,20 +62,14 @@
 		"{AMD,AMD8111},"
 	        "{ALI,M5455}}");
 
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK 1
-#endif
-#define SUPPORT_MIDI 1
-
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
 static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT};
 static int buggy_irq[SNDRV_CARDS];
-#ifdef SUPPORT_JOYSTICK
-static int joystick[SNDRV_CARDS];
-#endif
+static int xbox[SNDRV_CARDS];
+
 #ifdef SUPPORT_MIDI
 static int mpu_port[SNDRV_CARDS]; /* disabled */
 #endif
@@ -94,14 +86,8 @@
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
 module_param_array(buggy_irq, bool, NULL, 0444);
 MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
-#ifdef SUPPORT_JOYSTICK
-module_param_array(joystick, bool, NULL, 0444);
-MODULE_PARM_DESC(joystick, "Enable joystick for Intel i8x0 soundcard.");
-#endif
-#ifdef SUPPORT_MIDI
-module_param_array(mpu_port, int, NULL, 0444);
-MODULE_PARM_DESC(mpu_port, "MPU401 port # for Intel i8x0 driver.");
-#endif
+module_param_array(xbox, bool, NULL, 0444);
+MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
 
 /*
  *  Direct registers
@@ -405,10 +391,10 @@
 
 	unsigned int mmio;
 	unsigned long addr;
-	void __iomem * remap_addr;
+	void __iomem *remap_addr;
 	unsigned int bm_mmio;
 	unsigned long bmaddr;
-	void __iomem * remap_bmaddr;
+	void __iomem *remap_bmaddr;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -419,18 +405,21 @@
 
 	unsigned multi4: 1,
 		 multi6: 1,
+		 dra: 1,
 		 smp20bit: 1;
 	unsigned in_ac97_init: 1,
 		 in_sdin_init: 1;
-	unsigned fix_nocache: 1; /* workaround for 440MX */
-	unsigned buggy_irq: 1; /* workaround for buggy mobos */
+	unsigned in_measurement: 1;	/* during ac97 clock measurement */
+	unsigned fix_nocache: 1; 	/* workaround for 440MX */
+	unsigned buggy_irq: 1;		/* workaround for buggy mobos */
+	unsigned xbox: 1;		/* workaround for Xbox AC'97 detection */
+
+	int spdif_idx;	/* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
 
 	ac97_bus_t *ac97_bus;
 	ac97_t *ac97[3];
 	unsigned int ac97_sdin[3];
 
-	snd_rawmidi_t *rmidi;
-
 	spinlock_t reg_lock;
 	spinlock_t ac97_lock;
 	
@@ -806,7 +795,8 @@
 	}
 
 	ichdev->position += step * ichdev->fragsize1;
-	ichdev->position %= ichdev->size;
+	if (! chip->in_measurement)
+		ichdev->position %= ichdev->size;
 	ichdev->lvi += step;
 	ichdev->lvi &= ICH_REG_LVI_MASK;
 	iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
@@ -953,6 +943,7 @@
 	ichdev_t *ichdev = get_ichdev(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	size_t size = params_buffer_bytes(hw_params);
+	int dbl = params_rate(hw_params) > 48000;
 	int err;
 
 	if (chip->fix_nocache && runtime->dma_area && runtime->dma_bytes < size)
@@ -968,11 +959,11 @@
 	}
 	err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
 				params_channels(hw_params),
-				ichdev->pcm->r[0].slots);
+				ichdev->pcm->r[dbl].slots);
 	if (err >= 0) {
 		ichdev->pcm_open_flag = 1;
-		/* FIXME: hack to enable spdif support */
-		if (ichdev->ichd == ICHD_PCMOUT && chip->device_type == DEVICE_SIS)
+		/* Force SPDIF setting */
+		if (ichdev->ichd == ICHD_PCMOUT && chip->spdif_idx < 0)
 			snd_ac97_set_rate(ichdev->pcm->r[0].codec[0], AC97_SPDIF, params_rate(hw_params));
 	}
 	return err;
@@ -993,34 +984,35 @@
 }
 
 static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
-				       int channels, int sample_bits)
+				       snd_pcm_runtime_t *runtime)
 {
 	unsigned int cnt;
+	int dbl = runtime->rate > 48000;
 	switch (chip->device_type) {
 	case DEVICE_ALI:
 		cnt = igetdword(chip, ICHREG(ALI_SCR));
 		cnt &= ~ICH_ALI_SC_PCM_246_MASK;
-		if (chip->multi4 && channels == 4)
+		if (runtime->channels == 4 || dbl)
 			cnt |= ICH_ALI_SC_PCM_4;
-		else if (chip->multi6 && channels == 6)
+		else if (runtime->channels == 6)
 			cnt |= ICH_ALI_SC_PCM_6;
 		iputdword(chip, ICHREG(ALI_SCR), cnt);
 		break;
 	case DEVICE_SIS:
 		cnt = igetdword(chip, ICHREG(GLOB_CNT));
 		cnt &= ~ICH_SIS_PCM_246_MASK;
-		if (chip->multi4 && channels == 4)
+		if (runtime->channels == 4 || dbl)
 			cnt |= ICH_SIS_PCM_4;
-		else if (chip->multi6 && channels == 6)
+		else if (runtime->channels == 6)
 			cnt |= ICH_SIS_PCM_6;
 		iputdword(chip, ICHREG(GLOB_CNT), cnt);
 		break;
 	default:
 		cnt = igetdword(chip, ICHREG(GLOB_CNT));
 		cnt &= ~(ICH_PCM_246_MASK | ICH_PCM_20BIT);
-		if (chip->multi4 && channels == 4)
+		if (runtime->channels == 4 || dbl)
 			cnt |= ICH_PCM_4;
-		else if (chip->multi6 && channels == 6)
+		else if (runtime->channels == 6)
 			cnt |= ICH_PCM_6;
 		if (chip->device_type == DEVICE_NFORCE) {
 			/* reset to 2ch once to keep the 6 channel data in alignment,
@@ -1031,7 +1023,7 @@
 				msleep(50); /* grrr... */
 			}
 		} else if (chip->device_type == DEVICE_INTEL_ICH4) {
-			if (sample_bits > 16)
+			if (runtime->sample_bits > 16)
 				cnt |= ICH_PCM_20BIT;
 		}
 		iputdword(chip, ICHREG(GLOB_CNT), cnt);
@@ -1050,8 +1042,7 @@
 	ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
 	spin_lock_irq(&chip->reg_lock);
 	if (ichdev->ichd == ICHD_PCMOUT) {
-		snd_intel8x0_setup_pcm_out(chip, runtime->channels,
-					   runtime->sample_bits);
+		snd_intel8x0_setup_pcm_out(chip, runtime);
 		if (chip->device_type == DEVICE_INTEL_ICH4) {
 			ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
 		}
@@ -1167,6 +1158,9 @@
 		runtime->hw.channels_max = 4;
 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels4);
 	}
+	if (chip->dra) {
+		snd_ac97_pcm_double_rate_rules(runtime);
+	}
 	if (chip->smp20bit) {
 		runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE;
 		snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20);
@@ -1661,6 +1655,12 @@
 					 (1 << AC97_SLOT_PCM_SLEFT) |
 					 (1 << AC97_SLOT_PCM_SRIGHT) |
 					 (1 << AC97_SLOT_LFE)
+			},
+			{
+				.slots = (1 << AC97_SLOT_PCM_LEFT) |
+					 (1 << AC97_SLOT_PCM_RIGHT) |
+					 (1 << AC97_SLOT_PCM_LEFT_0) |
+					 (1 << AC97_SLOT_PCM_RIGHT_0)
 			}
 		}
 	},
@@ -1717,6 +1717,12 @@
 static struct ac97_quirk ac97_quirks[] __devinitdata = {
 	{
 		.vendor = 0x0e11,
+		.device = 0x008a,
+		.name = "Compaq Evo W4000",	/* AD1885 */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.vendor = 0x0e11,
 		.device = 0x00b8,
 		.name = "Compaq Evo D510C",
 		.type = AC97_TUNE_HP_ONLY
@@ -1763,6 +1769,12 @@
 		.name = "HP xw4200",	/* AD1981B*/
 		.type = AC97_TUNE_HP_ONLY
 	},
+	{
+		.vendor = 0x104d,
+		.device = 0x8197,
+		.name = "Sony S1XP",
+		.type = AC97_TUNE_INV_EAPD
+	},
  	{
 		.vendor = 0x1043,
 		.device = 0x80f3,
@@ -1770,6 +1782,12 @@
 		.type = AC97_TUNE_AD_SHARING
 	},
 	{
+		.vendor = 0x10cf,
+		.device = 0x11c3,
+		.name = "Fujitsu-Siemens E4010",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
 		.vendor = 0x10f1,
 		.device = 0x2665,
 		.name = "Fujitsu-Siemens Celsius",	/* AD1981? */
@@ -1870,7 +1888,6 @@
 	int err;
 	unsigned int i, codecs;
 	unsigned int glob_sta = 0;
-	int spdif_idx = -1; /* disabled */
 	ac97_bus_ops_t *ops;
 	static ac97_bus_ops_t standard_bus_ops = {
 		.write = snd_intel8x0_codec_write,
@@ -1881,16 +1898,16 @@
 		.read = snd_intel8x0_ali_codec_read,
 	};
 
+	chip->spdif_idx = -1; /* use PCMOUT (or disabled) */
 	switch (chip->device_type) {
 	case DEVICE_NFORCE:
-		spdif_idx = NVD_SPBAR;
+		chip->spdif_idx = NVD_SPBAR;
 		break;
 	case DEVICE_ALI:
-		spdif_idx = ALID_AC97SPDIFOUT;
+		chip->spdif_idx = ALID_AC97SPDIFOUT;
 		break;
-	default:
-		if (chip->device_type == DEVICE_INTEL_ICH4)
-			spdif_idx = ICHD_SPBAR;
+	case DEVICE_INTEL_ICH4:
+		chip->spdif_idx = ICHD_SPBAR;
 		break;
 	};
 
@@ -1900,6 +1917,8 @@
 	ac97.private_data = chip;
 	ac97.private_free = snd_intel8x0_mixer_free_ac97;
 	ac97.scaps = AC97_SCAP_SKIP_MODEM;
+	if (chip->xbox)
+		ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR;
 	if (chip->device_type != DEVICE_ALI) {
 		glob_sta = igetdword(chip, ICHREG(GLOB_STA));
 		ops = &standard_bus_ops;
@@ -1943,6 +1962,7 @@
 	/* FIXME: my test board doesn't work well with VRA... */
 	if (chip->device_type == DEVICE_ALI)
 		pbus->no_vra = 1;
+	pbus->dra = 1;
 	chip->ac97_bus = pbus;
 
 	ac97.pci = chip->pci;
@@ -1965,7 +1985,7 @@
 	i = ARRAY_SIZE(ac97_pcm_defs);
 	if (chip->device_type != DEVICE_INTEL_ICH4)
 		i -= 2;		/* do not allocate PCM2IN and MIC2 */
-	if (spdif_idx < 0)
+	if (chip->spdif_idx < 0)
 		i--;		/* do not allocate S/PDIF */
 	err = snd_ac97_pcm_assign(pbus, i, ac97_pcm_defs);
 	if (err < 0)
@@ -1973,8 +1993,8 @@
 	chip->ichd[ICHD_PCMOUT].pcm = &pbus->pcms[0];
 	chip->ichd[ICHD_PCMIN].pcm = &pbus->pcms[1];
 	chip->ichd[ICHD_MIC].pcm = &pbus->pcms[2];
-	if (spdif_idx >= 0)
-		chip->ichd[spdif_idx].pcm = &pbus->pcms[3];
+	if (chip->spdif_idx >= 0)
+		chip->ichd[chip->spdif_idx].pcm = &pbus->pcms[3];
 	if (chip->device_type == DEVICE_INTEL_ICH4) {
 		chip->ichd[ICHD_PCM2IN].pcm = &pbus->pcms[4];
 		chip->ichd[ICHD_MIC2].pcm = &pbus->pcms[5];
@@ -2003,13 +2023,24 @@
 		if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE))
 			chip->multi6 = 1;
 	}
+	if (pbus->pcms[0].r[1].rslots[0]) {
+		chip->dra = 1;
+	}
 	if (chip->device_type == DEVICE_INTEL_ICH4) {
 		if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20)
 			chip->smp20bit = 1;
 	}
 	if (chip->device_type == DEVICE_NFORCE) {
 		/* 48kHz only */
-		chip->ichd[spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
+		chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
+	}
+	if (chip->device_type == DEVICE_INTEL_ICH4) {
+		/* use slot 10/11 for SPDIF */
+		u32 val;
+		val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK;
+		val |= ICH_PCM_SPDIF_1011;
+		iputdword(chip, ICHREG(GLOB_CNT), val);
+		snd_ac97_update_bits(chip->ac97[0], AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4);
 	}
 	chip->in_ac97_init = 0;
 	return 0;
@@ -2317,6 +2348,7 @@
 	snd_intel8x0_setup_periods(chip, ichdev);
 	port = ichdev->reg_offset;
 	spin_lock_irq(&chip->reg_lock);
+	chip->in_measurement = 1;
 	/* trigger */
 	if (chip->device_type != DEVICE_ALI)
 		iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM);
@@ -2326,18 +2358,14 @@
 	}
 	do_gettimeofday(&start_time);
 	spin_unlock_irq(&chip->reg_lock);
-#if 0
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ / 20);
-#else
-	/* FIXME: schedule() can take too long time and overlap the boundary.. */
-	mdelay(50);
-#endif
 	spin_lock_irq(&chip->reg_lock);
 	/* check the position */
 	pos = ichdev->fragsize1;
 	pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
 	pos += ichdev->position;
+	chip->in_measurement = 0;
 	do_gettimeofday(&stop_time);
 	/* stop */
 	if (chip->device_type == DEVICE_ALI) {
@@ -2501,8 +2529,9 @@
 	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
 		chip->mmio = 1;
 		chip->addr = pci_resource_start(pci, 2);
-		chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 2));
-		if (!chip->remap_addr) {
+		chip->remap_addr = ioremap_nocache(chip->addr,
+						   pci_resource_len(pci, 2));
+		if (chip->remap_addr == NULL) {
 			snd_printk("AC'97 space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
@@ -2513,8 +2542,9 @@
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
 		chip->bm_mmio = 1;
 		chip->bmaddr = pci_resource_start(pci, 3);
-		chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, pci_resource_len(pci, 3));
-		if (!chip->remap_bmaddr) {
+		chip->remap_bmaddr = ioremap_nocache(chip->bmaddr,
+						     pci_resource_len(pci, 3));
+		if (chip->remap_bmaddr == NULL) {
 			snd_printk("Controller space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
@@ -2659,6 +2689,9 @@
 	case DEVICE_NFORCE:
 		strcpy(card->driver, "NFORCE");
 		break;
+	case DEVICE_INTEL_ICH4:
+		strcpy(card->driver, "ICH4");
+		break;
 	default:
 		strcpy(card->driver, "ICH");
 		break;
@@ -2678,6 +2711,8 @@
 	}
 	if (buggy_irq[dev])
 		chip->buggy_irq = 1;
+	if (xbox[dev])
+		chip->xbox = 1;
 
 	if ((err = snd_intel8x0_mixer(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) {
 		snd_card_free(card);
@@ -2688,20 +2723,11 @@
 		return err;
 	}
 	
-	if (mpu_port[dev] == 0x300 || mpu_port[dev] == 0x330) {
-		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_INTEL8X0,
-					       mpu_port[dev], 0,
-					       -1, 0, &chip->rmidi)) < 0) {
-			printk(KERN_ERR "intel8x0: no UART401 device at 0x%x, skipping.\n", mpu_port[dev]);
-			mpu_port[dev] = 0;
-		}
-	} else
-		mpu_port[dev] = 0;
-
 	snd_intel8x0_proc_init(chip);
 
-	sprintf(card->longname, "%s at 0x%lx, irq %i",
-		card->shortname, chip->addr, chip->irq);
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s with %s at %#lx, irq %i", card->shortname,
+		 snd_ac97_get_short_name(chip->ac97[0]), chip->addr, chip->irq);
 
 	if (! ac97_clock[dev])
 		intel8x0_measure_ac97_clock(chip);
@@ -2730,129 +2756,18 @@
 };
 
 
-#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
-/*
- * initialize joystick/midi addresses
- */
-
-#ifdef SUPPORT_JOYSTICK
-/* there is only one available device, so we keep it here */
-static struct pci_dev *ich_gameport_pci;
-static struct gameport ich_gameport = { .io = 0x200 };
-#endif
-
-static int __devinit snd_intel8x0_joystick_probe(struct pci_dev *pci,
-						 const struct pci_device_id *id)
-{
-	u16 val;
-	static int dev;
-	if (dev >= SNDRV_CARDS)
-		return -ENODEV;
-	if (!enable[dev]) {
-		dev++;
-		return -ENOENT;
-	}
-
-	pci_read_config_word(pci, 0xe6, &val);
-#ifdef SUPPORT_JOYSTICK
-	val &= ~0x100;
-	if (joystick[dev]) {
-		if (! request_region(ich_gameport.io, 8, "ICH gameport")) {
-			printk(KERN_WARNING "intel8x0: cannot grab gameport 0x%x\n",  ich_gameport.io);
-			joystick[dev] = 0;
-		} else {
-			ich_gameport_pci = pci;
-			gameport_register_port(&ich_gameport);
-			val |= 0x100;
-		}
-	}
-#endif
-#ifdef SUPPORT_MIDI
-	val &= ~0x20;
-	if (mpu_port[dev] > 0) {
-		if (mpu_port[dev] == 0x300 || mpu_port[dev] == 0x330) {
-			u8 b;
-			val |= 0x20;
-			pci_read_config_byte(pci, 0xe2, &b);
-			if (mpu_port[dev] == 0x300)
-				b |= 0x08;
-			else
-				b &= ~0x08;
-			pci_write_config_byte(pci, 0xe2, b);
-		}
-	}
-#endif
-	pci_write_config_word(pci, 0xe6, val);
-	return 0;
-}
-
-static void __devexit snd_intel8x0_joystick_remove(struct pci_dev *pci)
-{
-	u16 val;
-#ifdef SUPPORT_JOYSTICK
-	if (ich_gameport_pci == pci) {
-		gameport_unregister_port(&ich_gameport);
-		release_region(ich_gameport.io, 8);
-		ich_gameport_pci = NULL;
-	}
-#endif
-	/* disable joystick and MIDI */
-	pci_read_config_word(pci, 0xe6, &val);
-	val &= ~0x120;
-	pci_write_config_word(pci, 0xe6, val);
-}
-
-static struct pci_device_id snd_intel8x0_joystick_ids[] = {
-	{ 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* 82801AA */
-	{ 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* 82901AB */
-	{ 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH2 */
-	{ 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH2M */
-	{ 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* ICH3 */
-	// { 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* 440MX */
-	// { 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* SI7012 */
-	{ 0x10de, 0x01b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* NFORCE */
-	{ 0x10de, 0x006b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* NFORCE2 */
-	{ 0x10de, 0x00db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* NFORCE3 */
-	{ 0, }
-};
-
-static struct pci_driver joystick_driver = {
-	.name = "Intel ICH Joystick",
-	.id_table = snd_intel8x0_joystick_ids,
-	.probe = snd_intel8x0_joystick_probe,
-	.remove = __devexit_p(snd_intel8x0_joystick_remove),
-};
-
-static int have_joystick;
-#endif
-
 static int __init alsa_card_intel8x0_init(void)
 {
 	int err;
 
         if ((err = pci_module_init(&driver)) < 0)
                 return err;
-
-#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
-	if (pci_module_init(&joystick_driver) < 0) {
-		snd_printdd(KERN_INFO "no joystick found\n");
-		have_joystick = 0;
-	} else {
-		snd_printdd(KERN_INFO "joystick(s) found\n");
-		have_joystick = 1;
-	}
-#endif
         return 0;
-
 }
 
 static void __exit alsa_card_intel8x0_exit(void)
 {
 	pci_unregister_driver(&driver);
-#if defined(SUPPORT_JOYSTICK) || defined(SUPPORT_MIDI)
-	if (have_joystick)
-		pci_unregister_driver(&joystick_driver);
-#endif
 }
 
 module_init(alsa_card_intel8x0_init)
diff -Nru a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
--- a/sound/pci/intel8x0m.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/intel8x0m.c	2004-10-28 22:25:58 -07:00
@@ -30,13 +30,11 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/gameport.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
-#include <sound/mpu401.h>
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -48,8 +46,13 @@
 		"{Intel,82801CA-ICH3},"
 		"{Intel,82801DB-ICH4},"
 		"{Intel,ICH5},"
-	        "{Intel,MX440}}");
-
+	        "{Intel,MX440},"
+		"{SiS,7013},"
+		"{NVidia,NForce Modem},"
+		"{NVidia,NForce2 Modem},"
+		"{NVidia,NForce2s Modem},"
+		"{NVidia,NForce3 Modem},"
+		"{AMD,AMD768}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -232,10 +235,10 @@
 
 	unsigned int mmio;
 	unsigned long addr;
-	unsigned long remap_addr;
+	void __iomem *remap_addr;
 	unsigned int bm_mmio;
 	unsigned long bmaddr;
-	unsigned long remap_bmaddr;
+	void __iomem *remap_bmaddr;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -1065,9 +1068,9 @@
 	if (chip->bdbars.area)
 		snd_dma_free_pages(&chip->bdbars);
 	if (chip->remap_addr)
-		iounmap((void *) chip->remap_addr);
+		iounmap(chip->remap_addr);
 	if (chip->remap_bmaddr)
-		iounmap((void *) chip->remap_bmaddr);
+		iounmap(chip->remap_bmaddr);
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
 	pci_release_regions(chip->pci);
@@ -1192,9 +1195,9 @@
 	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
 		chip->mmio = 1;
 		chip->addr = pci_resource_start(pci, 2);
-		chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr,
-								   pci_resource_len(pci, 2));
-		if (chip->remap_addr == 0) {
+		chip->remap_addr = ioremap_nocache(chip->addr,
+						   pci_resource_len(pci, 2));
+		if (chip->remap_addr == NULL) {
 			snd_printk("AC'97 space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
@@ -1205,9 +1208,9 @@
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
 		chip->bm_mmio = 1;
 		chip->bmaddr = pci_resource_start(pci, 3);
-		chip->remap_bmaddr = (unsigned long) ioremap_nocache(chip->bmaddr,
-								     pci_resource_len(pci, 3));
-		if (chip->remap_bmaddr == 0) {
+		chip->remap_bmaddr = ioremap_nocache(chip->bmaddr,
+						     pci_resource_len(pci, 3));
+		if (chip->remap_bmaddr == NULL) {
 			snd_printk("Controller space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
@@ -1331,15 +1334,7 @@
 	if (card == NULL)
 		return -ENOMEM;
 
-	switch (pci_id->driver_data) {
-	case DEVICE_NFORCE:
-		strcpy(card->driver, "NFORCE-MODEM");
-		break;
-	default:
-		strcpy(card->driver, "ICH-MODEM");
-		break;
-	}
-
+	strcpy(card->driver, "ICH-MODEM");
 	strcpy(card->shortname, "Intel ICH");
 	for (name = shortnames; name->id; name++) {
 		if (pci->device == name->id) {
diff -Nru a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
--- a/sound/pci/korg1212/korg1212.c	2004-10-28 22:25:56 -07:00
+++ b/sound/pci/korg1212/korg1212.c	2004-10-28 22:25:56 -07:00
@@ -168,7 +168,7 @@
 #define DOORBELL_VAL_MASK    0x00FF    // the doorbell value is one byte
 
 #define CARD_BOOT_DELAY_IN_MS  10
-
+#define CARD_BOOT_TIMEOUT      10
 #define DSP_BOOT_DELAY_IN_MS   200
 
 #define kNumBuffers		8
@@ -341,7 +341,7 @@
 	unsigned long iomem2;
         unsigned long irqcount;
         unsigned long inIRQ;
-        unsigned long iobase;
+        void __iomem *iobase;
 
 	struct snd_dma_buffer dma_dsp;
         struct snd_dma_buffer dma_play;
@@ -364,16 +364,16 @@
 	u32 RoutingTablePhy;
 	u32 AdatTimeCodePhy;
 
-        u32 * statusRegPtr;	     // address of the interrupt status/control register
-        u32 * outDoorbellPtr;	     // address of the host->card doorbell register
-        u32 * inDoorbellPtr;	     // address of the card->host doorbell register
-        u32 * mailbox0Ptr;	     // address of mailbox 0 on the card
-        u32 * mailbox1Ptr;	     // address of mailbox 1 on the card
-        u32 * mailbox2Ptr;	     // address of mailbox 2 on the card
-        u32 * mailbox3Ptr;	     // address of mailbox 3 on the card
-        u32 * controlRegPtr;	     // address of the EEPROM, PCI, I/O, Init ctrl reg
-        u16 * sensRegPtr;	     // address of the sensitivity setting register
-        u32 * idRegPtr;		     // address of the device and vendor ID registers
+        u32 __iomem * statusRegPtr;	     // address of the interrupt status/control register
+        u32 __iomem * outDoorbellPtr;	     // address of the host->card doorbell register
+        u32 __iomem * inDoorbellPtr;	     // address of the card->host doorbell register
+        u32 __iomem * mailbox0Ptr;	     // address of mailbox 0 on the card
+        u32 __iomem * mailbox1Ptr;	     // address of mailbox 1 on the card
+        u32 __iomem * mailbox2Ptr;	     // address of mailbox 2 on the card
+        u32 __iomem * mailbox3Ptr;	     // address of mailbox 3 on the card
+        u32 __iomem * controlRegPtr;	     // address of the EEPROM, PCI, I/O, Init ctrl reg
+        u16 __iomem * sensRegPtr;	     // address of the sensitivity setting register
+        u32 __iomem * idRegPtr;		     // address of the device and vendor ID registers
 
         size_t periodsize;
 	int channels;
@@ -382,6 +382,9 @@
         snd_pcm_substream_t *playback_substream;
         snd_pcm_substream_t *capture_substream;
 
+	pid_t capture_pid;
+	pid_t playback_pid;
+
  	CardState cardState;
         int running;
         int idleMonitorOn;           // indicates whether the card is in idle monitor mode.
@@ -796,11 +799,12 @@
 
 static void snd_korg1212_EnableCardInterrupts(korg1212_t * korg1212)
 {
-	* korg1212->statusRegPtr = PCI_INT_ENABLE_BIT            |
-                                   PCI_DOORBELL_INT_ENABLE_BIT   |
-                                   LOCAL_INT_ENABLE_BIT          |
-                                   LOCAL_DOORBELL_INT_ENABLE_BIT |
-                                   LOCAL_DMA1_INT_ENABLE_BIT;
+	writel(PCI_INT_ENABLE_BIT            |
+	       PCI_DOORBELL_INT_ENABLE_BIT   |
+	       LOCAL_INT_ENABLE_BIT          |
+	       LOCAL_DOORBELL_INT_ENABLE_BIT |
+	       LOCAL_DMA1_INT_ENABLE_BIT,
+	       korg1212->statusRegPtr);
 }
 
 #if 0 /* not used */
@@ -843,6 +847,20 @@
 
 #endif /* not used */
 
+static inline int snd_korg1212_use_is_exclusive(korg1212_t *korg1212)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&korg1212->lock, flags);
+	if ((korg1212->playback_pid != korg1212->capture_pid) &&
+	    (korg1212->playback_pid >= 0) && (korg1212->capture_pid >= 0)) {
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&korg1212->lock, flags);
+	return ret;
+}
+
 static int snd_korg1212_SetRate(korg1212_t *korg1212, int rate)
 {
         static ClockSourceIndex s44[] = { K1212_CLKIDX_AdatAt44_1K,
@@ -854,6 +872,10 @@
                                           K1212_CLKIDX_LocalAt48K };
         int parm;
 
+        if (!snd_korg1212_use_is_exclusive (korg1212)) {
+                return -EBUSY;
+        }
+
         switch(rate) {
                 case 44100:
                 parm = s44[korg1212->clkSource];
@@ -897,7 +919,7 @@
 
 static void snd_korg1212_DisableCardInterrupts(korg1212_t *korg1212)
 {
-	* korg1212->statusRegPtr = 0;
+	writel(0, korg1212->statusRegPtr);
 }
 
 static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
@@ -1244,7 +1266,7 @@
 	if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
 #endif
 
-	if (! sleep_on_timeout(&korg1212->wait, HZ * 4))
+	if (! sleep_on_timeout(&korg1212->wait, HZ * CARD_BOOT_TIMEOUT))
 		return -EBUSY; /* timeout */
 
 	snd_korg1212_OnDSPDownloadComplete(korg1212);
@@ -1413,6 +1435,7 @@
         spin_lock_irqsave(&korg1212->lock, flags);
 
         korg1212->playback_substream = substream;
+	korg1212->playback_pid = current->pid;
         korg1212->periodsize = K1212_PERIODS;
 	korg1212->channels = K1212_CHANNELS;
 
@@ -1443,6 +1466,7 @@
         spin_lock_irqsave(&korg1212->lock, flags);
 
         korg1212->capture_substream = substream;
+	korg1212->capture_pid = current->pid;
         korg1212->periodsize = K1212_PERIODS;
 	korg1212->channels = K1212_CHANNELS;
 
@@ -1465,6 +1489,7 @@
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
+	korg1212->playback_pid = -1;
         korg1212->playback_substream = NULL;
         korg1212->periodsize = 0;
 
@@ -1485,6 +1510,7 @@
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
+	korg1212->capture_pid = -1;
         korg1212->capture_substream = NULL;
         korg1212->periodsize = 0;
 
@@ -1521,22 +1547,45 @@
         unsigned long flags;
         korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         int err;
+	pid_t this_pid;
+	pid_t other_pid;
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_hw_params [%s]\n", stateName[korg1212->cardState]);
 #endif
 
         spin_lock_irqsave(&korg1212->lock, flags);
+
+	if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		this_pid = korg1212->playback_pid;
+		other_pid = korg1212->capture_pid;
+	} else {
+		this_pid = korg1212->capture_pid;
+		other_pid = korg1212->playback_pid;
+	}
+
+	if ((other_pid > 0) && (this_pid != other_pid)) {
+
+		/* The other stream is open, and not by the same
+		   task as this one. Make sure that the parameters
+		   that matter are the same.
+		 */
+
+		if ((int)params_rate(params) != korg1212->clkRate) {
+			spin_unlock_irqrestore(&korg1212->lock, flags);
+			_snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE);
+			return -EBUSY;
+		}
+
+        	spin_unlock_irqrestore(&korg1212->lock, flags);
+	        return 0;
+	}
+
         if ((err = snd_korg1212_SetRate(korg1212, params_rate(params))) < 0) {
                 spin_unlock_irqrestore(&korg1212->lock, flags);
                 return err;
         }
-/*
-        if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) {
-                spin_unlock_irqrestore(&korg1212->lock, flags);
-                return -EINVAL;
-        }
-*/
+
 	korg1212->channels = params_channels(params);
         korg1212->periodsize = K1212_PERIOD_BYTES;
 
@@ -2090,9 +2139,9 @@
                 korg1212->irq = -1;
         }
         
-        if (korg1212->iobase != 0) {
-                iounmap((void *)korg1212->iobase);
-                korg1212->iobase = 0;
+        if (korg1212->iobase != NULL) {
+                iounmap(korg1212->iobase);
+                korg1212->iobase = NULL;
         }
         
 	pci_release_regions(korg1212->pci);
@@ -2182,6 +2231,8 @@
 	korg1212->opencnt = 0;
 	korg1212->playcnt = 0;
 	korg1212->setcnt = 0;
+	korg1212->playback_pid = -1;
+	korg1212->capture_pid = -1;
         snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED);
         korg1212->idleMonitorOn = 0;
         korg1212->clkSrcRate = K1212_CLKIDX_LocalAt44_1K;
@@ -2216,9 +2267,9 @@
 		   stateName[korg1212->cardState]);
 #endif
 
-        if ((korg1212->iobase = (unsigned long) ioremap(korg1212->iomem, iomem_size)) == 0) {
-		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iobase,
-                           korg1212->iobase + iomem_size - 1);
+        if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) {
+		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
+                           korg1212->iomem + iomem_size - 1);
                 return -EBUSY;
         }
 
@@ -2235,16 +2286,16 @@
 
 	pci_set_master(korg1212->pci);
 
-        korg1212->statusRegPtr = (u32 *) (korg1212->iobase + STATUS_REG_OFFSET);
-        korg1212->outDoorbellPtr = (u32 *) (korg1212->iobase + OUT_DOORBELL_OFFSET);
-        korg1212->inDoorbellPtr = (u32 *) (korg1212->iobase + IN_DOORBELL_OFFSET);
-        korg1212->mailbox0Ptr = (u32 *) (korg1212->iobase + MAILBOX0_OFFSET);
-        korg1212->mailbox1Ptr = (u32 *) (korg1212->iobase + MAILBOX1_OFFSET);
-        korg1212->mailbox2Ptr = (u32 *) (korg1212->iobase + MAILBOX2_OFFSET);
-        korg1212->mailbox3Ptr = (u32 *) (korg1212->iobase + MAILBOX3_OFFSET);
-        korg1212->controlRegPtr = (u32 *) (korg1212->iobase + PCI_CONTROL_OFFSET);
-        korg1212->sensRegPtr = (u16 *) (korg1212->iobase + SENS_CONTROL_OFFSET);
-        korg1212->idRegPtr = (u32 *) (korg1212->iobase + DEV_VEND_ID_OFFSET);
+        korg1212->statusRegPtr = (u32 __iomem *) (korg1212->iobase + STATUS_REG_OFFSET);
+        korg1212->outDoorbellPtr = (u32 __iomem *) (korg1212->iobase + OUT_DOORBELL_OFFSET);
+        korg1212->inDoorbellPtr = (u32 __iomem *) (korg1212->iobase + IN_DOORBELL_OFFSET);
+        korg1212->mailbox0Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX0_OFFSET);
+        korg1212->mailbox1Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX1_OFFSET);
+        korg1212->mailbox2Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX2_OFFSET);
+        korg1212->mailbox3Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX3_OFFSET);
+        korg1212->controlRegPtr = (u32 __iomem *) (korg1212->iobase + PCI_CONTROL_OFFSET);
+        korg1212->sensRegPtr = (u16 __iomem *) (korg1212->iobase + SENS_CONTROL_OFFSET);
+        korg1212->idRegPtr = (u32 __iomem *) (korg1212->iobase + DEV_VEND_ID_OFFSET);
 
 #if K1212_DEBUG_LEVEL > 0
         K1212_DEBUG_PRINTK("K1212_DEBUG: card registers:\n"
@@ -2311,7 +2362,7 @@
 
 #if K1212_DEBUG_LEVEL > 0
         K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n",
-		korg1212->recordDataBufsPtr, korg1212->RecDataBufsPhy, korg1212->DataBufsSize);
+		korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize);
 #endif
 
 #else // K1212_LARGEALLOC
diff -Nru a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
--- a/sound/pci/mixart/mixart.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/mixart/mixart.c	2004-10-28 22:25:58 -07:00
@@ -1077,7 +1077,7 @@
 	/* release the i/o ports */
 	for (i = 0; i < 2; i++) {
 		if (mgr->mem[i].virt)
-			iounmap((void *)mgr->mem[i].virt);
+			iounmap(mgr->mem[i].virt);
 	}
 	pci_release_regions(mgr->pci);
 
@@ -1311,8 +1311,8 @@
 	}
 	for (i = 0; i < 2; i++) {
 		mgr->mem[i].phys = pci_resource_start(pci, i);
-		mgr->mem[i].virt = (unsigned long)ioremap_nocache(mgr->mem[i].phys,
-								  pci_resource_len(pci, i));
+		mgr->mem[i].virt = ioremap_nocache(mgr->mem[i].phys,
+						   pci_resource_len(pci, i));
 	}
 
 	if (request_irq(pci->irq, snd_mixart_interrupt, SA_INTERRUPT|SA_SHIRQ, CARD_NAME, (void *)mgr)) {
diff -Nru a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
--- a/sound/pci/mixart/mixart.h	2004-10-28 22:25:56 -07:00
+++ b/sound/pci/mixart/mixart.h	2004-10-28 22:25:56 -07:00
@@ -53,7 +53,7 @@
 
 struct mem_area {
 	unsigned long phys;
-	unsigned long virt;
+	void __iomem *virt;
 	struct resource *res;
 };
 
diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
--- a/sound/pci/nm256/nm256.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/nm256/nm256.c	2004-10-28 22:25:59 -07:00
@@ -61,6 +61,7 @@
 static int buffer_top[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* not specified */
 static int use_cache[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */
 static int vaio_hack[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */
+static int reset_workaround[SNDRV_CARDS];
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
@@ -80,6 +81,8 @@
 MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access.");
 module_param_array(vaio_hack, bool, NULL, 0444);
 MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks.");
+module_param_array(reset_workaround, bool, NULL, 0444);
+MODULE_PARM_DESC(reset_workaround, "Enable AC97 RESET workaround for some laptops.");
 
 /*
  * hw definitions
@@ -189,7 +192,7 @@
 	
 	u32 buf;	/* offset from chip->buffer */
 	int bufsize;	/* buffer size in bytes */
-	unsigned long bufptr;		/* mapped pointer */
+	void __iomem *bufptr;		/* mapped pointer */
 	unsigned long bufptr_addr;	/* physical address of the mapped pointer */
 
 	int dma_size;		/* buffer size of the substream in bytes */
@@ -204,11 +207,11 @@
 	
 	snd_card_t *card;
 
-	unsigned long cport;		/* control port */
+	void __iomem *cport;		/* control port */
 	struct resource *res_cport;	/* its resource */
 	unsigned long cport_addr;	/* physical address */
 
-	unsigned long buffer;		/* buffer */
+	void __iomem *buffer;		/* buffer */
 	struct resource *res_buffer;	/* its resource */
 	unsigned long buffer_addr;	/* buffer phyiscal address */
 
@@ -221,7 +224,7 @@
 
 	unsigned int coeffs_current: 1;	/* coeff. table is loaded? */
 	unsigned int use_cache: 1;	/* use one big coef. table */
-	unsigned int latitude_workaround: 1; /* Dell Latitude LS workaround needed */
+	unsigned int reset_workaround: 1; /* Workaround for some laptops to avoid freeze */
 
 	int mixer_base;			/* register offset of ac97 mixer */
 	int mixer_status_offset;	/* offset of mixer status reg. */
@@ -328,7 +331,7 @@
 		return;
 	}
 #endif
-	memcpy_toio((void *)chip->buffer + offset, src, size);
+	memcpy_toio(chip->buffer + offset, src, size);
 }
 
 /*
@@ -886,8 +889,8 @@
 
 	for (i = 0; i < 2; i++) {
 		nm256_stream_t *s = &chip->streams[i];
-		s->bufptr = chip->buffer +  s->buf - chip->buffer_start;
-		s->bufptr_addr = chip->buffer_addr + s->buf - chip->buffer_start;
+		s->bufptr = chip->buffer + (s->buf - chip->buffer_start);
+		s->bufptr_addr = chip->buffer_addr + (s->buf - chip->buffer_start);
 	}
 
 	err = snd_pcm_new(chip->card, chip->card->driver, device,
@@ -1161,16 +1164,14 @@
 {
 	nm256_t *chip = ac97->private_data;
 
-	spin_lock(&chip->reg_lock);
 	/* Reset the mixer.  'Tis magic!  */
 	snd_nm256_writeb(chip, 0x6c0, 1);
-	if (chip->latitude_workaround) {
+	if (! chip->reset_workaround) {
 		/* Dell latitude LS will lock up by this */
 		snd_nm256_writeb(chip, 0x6cc, 0x87);
 	}
 	snd_nm256_writeb(chip, 0x6cc, 0x80);
 	snd_nm256_writeb(chip, 0x6cc, 0x0);
-	spin_unlock(&chip->reg_lock);
 }
 
 /* create an ac97 mixer interface */
@@ -1225,13 +1226,13 @@
 snd_nm256_peek_for_sig(nm256_t *chip)
 {
 	/* The signature is located 1K below the end of video RAM.  */
-	unsigned long temp;
+	void __iomem *temp;
 	/* Default buffer end is 5120 bytes below the top of RAM.  */
 	unsigned long pointer_found = chip->buffer_end - 0x1400;
 	u32 sig;
 
-	temp = (unsigned long) ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16);
-	if (temp == 0) {
+	temp = ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16);
+	if (temp == NULL) {
 		snd_printk("Unable to scan for card signature in video RAM\n");
 		return -EBUSY;
 	}
@@ -1247,7 +1248,7 @@
 		    pointer < chip->buffer_size ||
 		    pointer > chip->buffer_end) {
 			snd_printk("invalid signature found: 0x%x\n", pointer);
-			iounmap((void *)temp);
+			iounmap(temp);
 			return -ENODEV;
 		} else {
 			pointer_found = pointer;
@@ -1255,7 +1256,7 @@
 		}
 	}
 
-	iounmap((void *)temp);
+	iounmap(temp);
 	chip->buffer_end = pointer_found;
 
 	return 0;
@@ -1304,9 +1305,9 @@
 		synchronize_irq(chip->irq);
 
 	if (chip->cport)
-		iounmap((void *) chip->cport);
+		iounmap(chip->cport);
 	if (chip->buffer)
-		iounmap((void *) chip->buffer);
+		iounmap(chip->buffer);
 	if (chip->res_cport) {
 		release_resource(chip->res_cport);
 		kfree_nocheck(chip->res_cport);
@@ -1342,7 +1343,6 @@
 		.dev_free =	snd_nm256_dev_free,
 	};
 	u32 addr;
-	u16 subsystem_vendor, subsystem_device;
 
 	*chip_ret = NULL;
 
@@ -1379,8 +1379,8 @@
 		err = -EBUSY;
 		goto __error;
 	}
-	chip->cport = (unsigned long) ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE);
-	if (chip->cport == 0) {
+	chip->cport = ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE);
+	if (chip->cport == NULL) {
 		snd_printk("unable to map control port %lx\n", chip->cport_addr);
 		err = -ENOMEM;
 		goto __error;
@@ -1444,8 +1444,8 @@
 		err = -EBUSY;
 		goto __error;
 	}
-	chip->buffer = (unsigned long) ioremap_nocache(chip->buffer_addr, chip->buffer_size);
-	if (chip->buffer == 0) {
+	chip->buffer = ioremap_nocache(chip->buffer_addr, chip->buffer_size);
+	if (chip->buffer == NULL) {
 		err = -ENOMEM;
 		snd_printk("unable to map ring buffer at %lx\n", chip->buffer_addr);
 		goto __error;
@@ -1479,19 +1479,6 @@
 
 	chip->coeffs_current = 0;
 
-	/* check workarounds */
-	chip->latitude_workaround = 1;
-	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
-	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-	if (subsystem_vendor == 0x104d && subsystem_device == 0x8041) {
-		/* this workaround will cause lock-up after suspend/resume on Sony PCG-F305 */
-		chip->latitude_workaround = 0;
-	}
-	if (subsystem_vendor == 0x1028 && subsystem_device == 0x0080) {
-		/* this workaround will cause lock-up after suspend/resume on a Dell laptop */
-		chip->latitude_workaround = 0;
-	}
-
 	snd_nm256_init_chip(chip);
 
 	if ((err = snd_nm256_pcm(chip, 0)) < 0)
@@ -1524,11 +1511,15 @@
 	int type;
 };
 
-#define NM_BLACKLISTED	1
+enum { NM_BLACKLISTED, NM_RESET_WORKAROUND };
 
 static struct nm256_quirk nm256_quirks[] __devinitdata = {
 	/* HP omnibook 4150 has cs4232 codec internally */
 	{ .vendor = 0x103c, .device = 0x0007, .type = NM_BLACKLISTED },
+	/* Sony PCG-F305 */
+	{ .vendor = 0x104d, .device = 0x8041, .type = NM_RESET_WORKAROUND },
+	/* Dell Latitude LS */
+	{ .vendor = 0x1028, .device = 0x0080, .type = NM_RESET_WORKAROUND },
 	{ } /* terminator */
 };
 
@@ -1559,9 +1550,13 @@
 
 	for (q = nm256_quirks; q->vendor; q++) {
 		if (q->vendor == subsystem_vendor && q->device == subsystem_device) {
-			if (q->type == NM_BLACKLISTED) {
+			switch (q->type) {
+			case NM_BLACKLISTED:
 				printk(KERN_INFO "nm256: The device is blacklisted.  Loading stopped\n");
 				return -ENODEV;
+			case NM_RESET_WORKAROUND:
+				reset_workaround[dev] = 1;
+				break;
 			}
 		}
 	}
@@ -1608,6 +1603,11 @@
 				    &chip)) < 0) {
 		snd_card_free(card);
 		return err;
+	}
+
+	if (reset_workaround[dev]) {
+		snd_printdd(KERN_INFO "nm256: reset_workaround activated\n");
+		chip->reset_workaround = 1;
 	}
 
 	sprintf(card->shortname, "NeoMagic %s", card->driver);
diff -Nru a/sound/pci/rme32.c b/sound/pci/rme32.c
--- a/sound/pci/rme32.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/rme32.c	2004-10-28 22:25:59 -07:00
@@ -210,7 +210,7 @@
 	spinlock_t lock;
 	int irq;
 	unsigned long port;
-	unsigned long iobase;
+	void __iomem *iobase;
 
 	u32 wcreg;		/* cached write control register value */
 	u32 wcreg_spdif;	/* S/PDIF setup */
@@ -725,9 +725,8 @@
 	/* S/PDIF setup */
 	if ((rme32->wcreg & RME32_WCR_ADAT) == 0) {
 		rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP);
-		writel(rme32->wcreg |=
-		       rme32->wcreg_spdif_stream,
-		       rme32->iobase + RME32_IO_CONTROL_REGISTER);
+		rme32->wcreg |= rme32->wcreg_spdif_stream;
+		writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	}
 	spin_unlock_irq(&rme32->lock);
 
@@ -1123,7 +1122,7 @@
 	}
 	
 	/* prefill playback buffer */
-	if (cmd == SNDRV_PCM_TRIGGER_START) {
+	if (cmd == SNDRV_PCM_TRIGGER_START && rme32->fullduplex_mode) {
 		snd_pcm_group_for_each(pos, substream) {
 			s = snd_pcm_group_substream_entry(pos);
 			if (s == rme32->playback_substream) {
@@ -1344,8 +1343,8 @@
 		rme32->irq = -1;
 	}
 	if (rme32->iobase) {
-		iounmap((void *) rme32->iobase);
-		rme32->iobase = 0;
+		iounmap(rme32->iobase);
+		rme32->iobase = NULL;
 	}
 	if (rme32->port) {
 		pci_release_regions(rme32->pci);
@@ -1387,7 +1386,7 @@
 	}
 	rme32->irq = pci->irq;
 
-	if ((rme32->iobase = (unsigned long) ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
+	if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
 		snd_printk("unable to remap memory region 0x%lx-0x%lx\n",
 			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
 		return -ENOMEM;
@@ -1636,8 +1635,8 @@
 		val &= ~RME32_WCR_MUTE;
 	else
 		val |= RME32_WCR_MUTE;
-	writel(rme32->wcreg =
-	       val, rme32->iobase + RME32_IO_CONTROL_REGISTER);
+	rme32->wcreg = val;
+	writel(val, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	spin_unlock_irq(&rme32->lock);
 	return change;
 }
@@ -1861,7 +1860,8 @@
 	change = val != rme32->wcreg_spdif_stream;
 	rme32->wcreg_spdif_stream = val;
 	rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP);
-	writel(rme32->wcreg |= val, rme32->iobase + RME32_IO_CONTROL_REGISTER);
+	rme32->wcreg |= val;
+	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	spin_unlock_irq(&rme32->lock);
 	return change;
 }
@@ -1969,16 +1969,14 @@
 	snd_card_t *card;
 	int err;
 
-	for (; dev < SNDRV_CARDS; dev++) {
-		if (!enable[dev]) {
-			dev++;
-			return -ENOENT;
-		}
-		break;
-	}
 	if (dev >= SNDRV_CARDS) {
 		return -ENODEV;
 	}
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
 	if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
 				 sizeof(rme32_t))) == NULL)
 		return -ENOMEM;
diff -Nru a/sound/pci/rme96.c b/sound/pci/rme96.c
--- a/sound/pci/rme96.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/rme96.c	2004-10-28 22:25:57 -07:00
@@ -56,13 +56,12 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int boot_devs;
 
-module_param_array(index, int, &boot_devs, 0444);
+module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi96 soundcard.");
-module_param_array(id, charp, &boot_devs, 0444);
+module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Digi96 soundcard.");
-module_param_array(enable, bool, &boot_devs, 0444);
+module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard.");
 
 /*
@@ -225,7 +224,7 @@
 	spinlock_t    lock;
 	int irq;
 	unsigned long port;
-	unsigned long iobase;
+	void __iomem *iobase;
 	
 	u32 wcreg;    /* cached write control register value */
 	u32 wcreg_spdif;		/* S/PDIF setup */
@@ -1547,8 +1546,8 @@
 		rme96->irq = -1;
 	}
 	if (rme96->iobase) {
-		iounmap((void *)rme96->iobase);
-		rme96->iobase = 0;
+		iounmap(rme96->iobase);
+		rme96->iobase = NULL;
 	}
 	if (rme96->port) {
 		pci_release_regions(rme96->pci);
@@ -1592,7 +1591,7 @@
 	}
 	rme96->irq = pci->irq;
 
-	if ((rme96->iobase = (unsigned long) ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
+	if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
 		snd_printk("unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
 		return -ENOMEM;
 	}
@@ -1859,7 +1858,8 @@
 	spin_lock_irq(&rme96->lock);
 	val = (rme96->wcreg & ~RME96_WCR_SEL) | val;
 	change = val != rme96->wcreg;
-	writel(rme96->wcreg = val, rme96->iobase + RME96_IO_CONTROL_REGISTER);
+	rme96->wcreg = val;
+	writel(val, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	spin_unlock_irq(&rme96->lock);
 	return change;
 }
@@ -2177,7 +2177,8 @@
 	change = val != rme96->wcreg_spdif_stream;
 	rme96->wcreg_spdif_stream = val;
 	rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
-	writel(rme96->wcreg |= val, rme96->iobase + RME96_IO_CONTROL_REGISTER);
+	rme96->wcreg |= val;
+	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	spin_unlock_irq(&rme96->lock);
 	return change;
 }
diff -Nru a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
--- a/sound/pci/rme9652/hdsp.c	2004-10-28 22:25:57 -07:00
+++ b/sound/pci/rme9652/hdsp.c	2004-10-28 22:25:57 -07:00
@@ -470,7 +470,7 @@
 	int                   dev;
 	int                   irq;
 	unsigned long         port;
-        unsigned long         iobase;
+        void __iomem         *iobase;
 	snd_card_t           *card;
 	snd_pcm_t            *pcm;
 	snd_hwdep_t          *hwdep;
@@ -934,9 +934,7 @@
 	}
 
 	position &= HDSP_BufferPositionMask;
-	position /= 4;
-	position -= 32;
-	position &= (HDSP_CHANNEL_BUFFER_SAMPLES-1);
+	position &= (hdsp->period_bytes/2) - 1;
 	return position;
 }
 
@@ -3227,7 +3225,7 @@
 	snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
 		    hdsp->capture_buffer, hdsp->playback_buffer);
 	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
-		    hdsp->irq, hdsp->port, hdsp->iobase);
+		    hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
 	snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
 	snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
 	snd_iprintf(buffer, "Status register: 0x%x\n", status);
@@ -4433,6 +4431,130 @@
 }
 
 
+/* helper functions for copying meter values */
+static inline int copy_u32_le(void __user *dest, void __iomem *src)
+{
+	u32 val = readl(src);
+	return copy_to_user(dest, &val, 4);
+}
+
+static inline int copy_u64_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
+{
+	u32 rms_low, rms_high;
+	u64 rms;
+	rms_low = readl(src_low);
+	rms_high = readl(src_high);
+	rms = ((u64)rms_high << 32) | rms_low;
+	return copy_to_user(dest, &rms, 8);
+}
+
+static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __iomem *src_high)
+{
+	u32 rms_low, rms_high;
+	u64 rms;
+	rms_low = readl(src_low) & 0xffffff00;
+	rms_high = readl(src_high) & 0xffffff00;
+	rms = ((u64)rms_high << 32) | rms_low;
+	return copy_to_user(dest, &rms, 8);
+}
+
+static int hdsp_9652_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+	int doublespeed = 0;
+	int i, j, channels, ofs;
+
+	if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
+		doublespeed = 1;
+	channels = doublespeed ? 14 : 26;
+	for (i = 0, j = 0; i < 26; ++i) {
+		if (doublespeed && (i & 4))
+			continue;
+		ofs = HDSP_9652_peakBase - j * 4;
+		if (copy_u32_le(&peak_rms->input_peaks[i], hdsp->iobase + ofs))
+			return -EFAULT;
+		ofs -= channels * 4;
+		if (copy_u32_le(&peak_rms->playback_peaks[i], hdsp->iobase + ofs))
+			return -EFAULT;
+		ofs -= channels * 4;
+		if (copy_u32_le(&peak_rms->output_peaks[i], hdsp->iobase + ofs))
+			return -EFAULT;
+		ofs = HDSP_9652_rmsBase + j * 8;
+		if (copy_u48_le(&peak_rms->input_rms[i], hdsp->iobase + ofs,
+				hdsp->iobase + ofs + 4))
+			return -EFAULT;
+		ofs += channels * 8;
+		if (copy_u48_le(&peak_rms->playback_rms[i], hdsp->iobase + ofs,
+				hdsp->iobase + ofs + 4))
+			return -EFAULT;
+		ofs += channels * 8;
+		if (copy_u48_le(&peak_rms->output_rms[i], hdsp->iobase + ofs,
+				hdsp->iobase + ofs + 4))
+			return -EFAULT;
+		j++;
+	}
+	return 0;
+}
+
+static int hdsp_9632_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+	int i, j;
+	hdsp_9632_meters_t __iomem *m;
+	int doublespeed = 0;
+
+	if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
+		doublespeed = 1;
+	m = (hdsp_9632_meters_t __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
+	for (i = 0, j = 0; i < 16; ++i, ++j) {
+		if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
+			return -EFAULT;
+		if (copy_u32_le(&peak_rms->playback_peaks[i], &m->playback_peak[j]))
+			return -EFAULT;
+		if (copy_u32_le(&peak_rms->output_peaks[i], &m->output_peak[j]))
+			return -EFAULT;
+		if (copy_u64_le(&peak_rms->input_rms[i], &m->input_rms_low[j],
+				&m->input_rms_high[j]))
+			return -EFAULT;
+		if (copy_u64_le(&peak_rms->playback_rms[i], &m->playback_rms_low[j],
+				&m->playback_rms_high[j]))
+			return -EFAULT;
+		if (copy_u64_le(&peak_rms->output_rms[i], &m->output_rms_low[j],
+				&m->output_rms_high[j]))
+			return -EFAULT;
+		if (doublespeed && i == 3) i += 4;
+	}
+	return 0;
+}
+
+static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+{
+	int i;
+
+	for (i = 0; i < 26; i++) {
+		if (copy_u32_le(&peak_rms->playback_peaks[i],
+				hdsp->iobase + HDSP_playbackPeakLevel + i * 4))
+			return -EFAULT;
+		if (copy_u32_le(&peak_rms->input_peaks[i],
+				hdsp->iobase + HDSP_inputPeakLevel + i * 4))
+			return -EFAULT;
+	}
+	for (i = 0; i < 28; i++) {
+		if (copy_u32_le(&peak_rms->output_peaks[i],
+				hdsp->iobase + HDSP_outputPeakLevel + i * 4))
+			return -EFAULT;
+	}
+	for (i = 0; i < 26; ++i) {
+		if (copy_u64_le(&peak_rms->playback_rms[i],
+				hdsp->iobase + HDSP_playbackRmsLevel + i * 8,
+				hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4))
+			return -EFAULT;
+		if (copy_u64_le(&peak_rms->input_rms[i], 
+				hdsp->iobase + HDSP_inputRmsLevel + i * 8,
+				hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4))
+			return -EFAULT;
+	}
+	return 0;
+}
+
 static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	hdsp_t *hdsp = (hdsp_t *)hw->private_data;	
@@ -4440,108 +4562,21 @@
 
 	switch (cmd) {
 	case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
-		hdsp_peak_rms_t __user *peak_rms;
-		int i;
-		
-		if (hdsp->io_type == H9652) {
-			unsigned long rms_low, rms_high;
-			int doublespeed = 0;
-			if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
-				doublespeed = 1;
-			peak_rms = (hdsp_peak_rms_t __user *)arg;
-			for (i = 0; i < 26; ++i) {
-				if (!(doublespeed && (i & 4))) {
-					if (copy_to_user_fromio((void __user *)peak_rms->input_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-i*4, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user_fromio((void __user *)peak_rms->playback_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-(doublespeed ? 14 : 26)*4-i*4, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user_fromio((void __user *)peak_rms->output_peaks+i*4, hdsp->iobase+HDSP_9652_peakBase-2*(doublespeed ? 14 : 26)*4-i*4, 4) != 0)
-						return -EFAULT;
-					rms_low = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+i*8) & 0xFFFFFF00;
-					rms_high = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+i*8+4) & 0xFFFFFF00;
-					rms_high += (rms_low >> 24);
-					rms_low <<= 8;
-					if (copy_to_user((void __user *)peak_rms->input_rms+i*8, &rms_low, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user((void __user *)peak_rms->input_rms+i*8+4, &rms_high, 4) != 0)
-						return -EFAULT;					
-					rms_low = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+(doublespeed ? 14 : 26)*8+i*8) & 0xFFFFFF00;
-					rms_high = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+(doublespeed ? 14 : 26)*8+i*8+4) & 0xFFFFFF00;
-					rms_high += (rms_low >> 24);
-					rms_low <<= 8;
-					if (copy_to_user((void __user *)peak_rms->playback_rms+i*8, &rms_low, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user((void __user *)peak_rms->playback_rms+i*8+4, &rms_high, 4) != 0)
-						return -EFAULT;					
-					rms_low = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+2*(doublespeed ? 14 : 26)*8+i*8) & 0xFFFFFF00;
-					rms_high = *(u32 *)(hdsp->iobase+HDSP_9652_rmsBase+2*(doublespeed ? 14 : 26)*8+i*8+4) & 0xFFFFFF00;
-					rms_high += (rms_low >> 24);
-					rms_low <<= 8;
-					if (copy_to_user((void __user *)peak_rms->output_rms+i*8, &rms_low, 4) != 0)
-						return -EFAULT;
-					if (copy_to_user((void __user *)peak_rms->output_rms+i*8+4, &rms_high, 4) != 0)
-						return -EFAULT;					
-				}
-			}
-			return 0;
-		}
-		if (hdsp->io_type == H9632) {
-			int j;
-			hdsp_9632_meters_t *m;
-			int doublespeed = 0;
-			if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
-				doublespeed = 1;
-			m = (hdsp_9632_meters_t *)(hdsp->iobase+HDSP_9632_metersBase);
-			peak_rms = (hdsp_peak_rms_t __user *)arg;
-			for (i = 0, j = 0; i < 16; ++i, ++j) {
-				if (copy_to_user((void __user *)peak_rms->input_peaks+i*4, &(m->input_peak[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->playback_peaks+i*4, &(m->playback_peak[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->output_peaks+i*4, &(m->output_peak[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->input_rms+i*8, &(m->input_rms_low[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->playback_rms+i*8, &(m->playback_rms_low[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->output_rms+i*8, &(m->output_rms_low[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->input_rms+i*8+4, &(m->input_rms_high[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->playback_rms+i*8+4, &(m->playback_rms_high[j]), 4) != 0)
-					return -EFAULT;
-				if (copy_to_user((void __user *)peak_rms->output_rms+i*8+4, &(m->output_rms_high[j]), 4) != 0)
-					return -EFAULT;
-				if (doublespeed && i == 3) i += 4;
-			}
-			return 0;
-		}
+		hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg;
+
 		if (!(hdsp->state & HDSP_FirmwareLoaded)) {
-			snd_printk("firmware needs to be uploaded to the card.\n");	
+			snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n");
 			return -EINVAL;
 		}
-		peak_rms = (hdsp_peak_rms_t __user *)arg;
-		for (i = 0; i < 26; ++i) {
-		    if (copy_to_user((void __user *)peak_rms->playback_peaks+i*4, (void *)hdsp->iobase+HDSP_playbackPeakLevel+i*4, 4) != 0)
-			    return -EFAULT;
-		    if (copy_to_user((void __user *)peak_rms->input_peaks+i*4, (void *)hdsp->iobase+HDSP_inputPeakLevel+i*4, 4) != 0)
-			    return -EFAULT;
-		}
-		for (i = 0; i < 26; ++i) {
-			if (copy_to_user((void __user *)peak_rms->playback_rms+i*8+4, (void *)hdsp->iobase+HDSP_playbackRmsLevel+i*8, 4) != 0)
-				return -EFAULT;
-			if (copy_to_user((void __user *)peak_rms->playback_rms+i*8, (void *)hdsp->iobase+HDSP_playbackRmsLevel+i*8+4, 4) != 0)
-				return -EFAULT;
-			if (copy_to_user((void __user *)peak_rms->input_rms+i*8+4, (void *)hdsp->iobase+HDSP_inputRmsLevel+i*8, 4) != 0)
-				return -EFAULT;
-			if (copy_to_user((void __user *)peak_rms->input_rms+i*8, (void *)hdsp->iobase+HDSP_inputRmsLevel+i*8+4, 4) != 0)
-				return -EFAULT;
-		}
-		for (i = 0; i < 28; ++i) {
-		    if (copy_to_user((void __user *)peak_rms->output_peaks+i*4, (void *)hdsp->iobase+HDSP_outputPeakLevel+i*4, 4) != 0)
-			    return -EFAULT;
+
+		switch (hdsp->io_type) {
+		case H9652:
+			return hdsp_9652_get_peak(hdsp, peak_rms);
+		case H9632:
+			return hdsp_9632_get_peak(hdsp, peak_rms);
+		default:
+			return hdsp_get_peak(hdsp, peak_rms);
 		}
-		break;
 	}
 	case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
 		hdsp_config_info_t info;
@@ -4619,7 +4654,7 @@
 	}
 	case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
 		hdsp_firmware_t __user *firmware;
-		unsigned long __user *firmware_data;
+		u32 __user *firmware_data;
 		int err;
 		
 		if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
@@ -4637,7 +4672,7 @@
 			return -EIO;
 		}
 
-		if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(unsigned long)*24413) != 0) {
+		if (copy_from_user(hdsp->firmware_cache, firmware_data, sizeof(hdsp->firmware_cache)) != 0) {
 			return -EFAULT;
 		}
 		
@@ -4878,7 +4913,7 @@
 	hdsp->midi[1].output = NULL;
 	spin_lock_init(&hdsp->midi[0].lock);
 	spin_lock_init(&hdsp->midi[1].lock);
-	hdsp->iobase = 0;
+	hdsp->iobase = NULL;
 	hdsp->control_register = 0;
 	hdsp->control2_register = 0;
 	hdsp->io_type = Undefined;
@@ -4936,7 +4971,7 @@
 	if ((err = pci_request_regions(pci, "hdsp")) < 0)
 		return err;
 	hdsp->port = pci_resource_start(pci, 0);
-	if ((hdsp->iobase = (unsigned long) ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == 0) {
+	if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
 		snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
 		return -EBUSY;
 	}
@@ -5020,7 +5055,7 @@
 	snd_hdsp_free_buffers(hdsp);
 	
 	if (hdsp->iobase)
-		iounmap((void *) hdsp->iobase);
+		iounmap(hdsp->iobase);
 
 	if (hdsp->port)
 		pci_release_regions(hdsp->pci);
diff -Nru a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
--- a/sound/pci/rme9652/rme9652.c	2004-10-28 22:25:58 -07:00
+++ b/sound/pci/rme9652/rme9652.c	2004-10-28 22:25:58 -07:00
@@ -211,7 +211,7 @@
 	spinlock_t lock;
 	int irq;
 	unsigned long port;
-	unsigned long iobase;
+	void __iomem *iobase;
 	
 	int precise_ptr;
 
@@ -1628,7 +1628,7 @@
 	snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
 		    rme9652->capture_buffer, rme9652->playback_buffer);
 	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
-		    rme9652->irq, rme9652->port, rme9652->iobase);
+		    rme9652->irq, rme9652->port, (unsigned long)rme9652->iobase);
 	snd_iprintf(buffer, "Control register: %x\n", rme9652->control_register);
 
 	snd_iprintf(buffer, "\n");
@@ -1808,7 +1808,7 @@
 	if (rme9652->irq >= 0)
 		free_irq(rme9652->irq, (void *)rme9652);
 	if (rme9652->iobase)
-		iounmap((void *) rme9652->iobase);
+		iounmap(rme9652->iobase);
 	if (rme9652->port)
 		pci_release_regions(rme9652->pci);
 
@@ -2496,8 +2496,8 @@
 	if ((err = pci_request_regions(pci, "rme9652")) < 0)
 		return err;
 	rme9652->port = pci_resource_start(pci, 0);
-	rme9652->iobase = (unsigned long) ioremap_nocache(rme9652->port, RME9652_IO_EXTENT);
-	if (rme9652->iobase == 0) {
+	rme9652->iobase = ioremap_nocache(rme9652->port, RME9652_IO_EXTENT);
+	if (rme9652->iobase == NULL) {
 		snd_printk("unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
 		return -EBUSY;
 	}
diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c
--- a/sound/pci/via82xx.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/via82xx.c	2004-10-28 22:25:59 -07:00
@@ -126,6 +126,7 @@
 #define VIA_REV_8233		0x30	/* 2 rec, 4 pb, 1 multi-pb, spdif */
 #define VIA_REV_8233A		0x40	/* 1 rec, 1 multi-pb, spdf */
 #define VIA_REV_8235		0x50	/* 2 rec, 4 pb, 1 multi-pb, spdif */
+#define VIA_REV_8237		0x60
 
 /*
  *  Direct registers
@@ -622,11 +623,6 @@
 	unsigned int status;
 	unsigned int i;
 
-#if 0
-	/* FIXME: does it work on via823x? */
-	if (chip->chip_type != TYPE_VIA686)
-		goto _skip_sgd;
-#endif
 	status = inl(VIAREG(chip, SGD_SHADOW));
 	if (! (status & chip->intr_mask)) {
 		if (chip->rmidi)
@@ -634,7 +630,6 @@
 			return snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
 		return IRQ_NONE;
 	}
-// _skip_sgd:
 
 	/* check status for each stream */
 	spin_lock(&chip->reg_lock);
@@ -1546,6 +1541,13 @@
 }
 
 static struct ac97_quirk ac97_quirks[] = {
+	{
+		.vendor = 0x1106,
+		.device = 0x4161,
+		.codec_id = 0x56494161, /* VT1612A */
+		.name = "Soltek SL-75DRV5",
+		.type = AC97_TUNE_NONE
+	},
 	{	/* FIXME: which codec? */
 		.vendor = 0x1106,
 		.device = 0x4161,
@@ -1605,6 +1607,7 @@
 		return err;
 	chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus;
 	chip->ac97_bus->clock = chip->ac97_clock;
+	chip->ac97_bus->shared_type = AC97_SHARED_TYPE_VIA;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -2068,6 +2071,7 @@
 	{ VIA_REV_8233, "VIA 8233", TYPE_VIA8233 },
 	{ VIA_REV_8233A, "VIA 8233A", TYPE_VIA8233A },
 	{ VIA_REV_8235, "VIA 8235", TYPE_VIA8233 },
+	{ VIA_REV_8237, "VIA 8237", TYPE_VIA8233 },
 };
 
 /*
@@ -2094,10 +2098,11 @@
 		{ .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
 		{ .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
 		{ .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
+		{ .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
 		{ .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
 		{ .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
 		{ .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
-		{ .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_NO_VRA }, /* Gigabyte GA-7VAXP (FIXME: or DXS_ENABLE?) */
+		{ .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
 		{ .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
 		{ .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
 		{ .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
@@ -2193,6 +2198,8 @@
 		}
 		if (chip_type == TYPE_VIA8233A)
 			strcpy(card->driver, "VIA8233A");
+		else if (revision >= VIA_REV_8237)
+			strcpy(card->driver, "VIA8237"); /* no slog assignment */
 		else
 			strcpy(card->driver, "VIA8233");
 		break;
@@ -2234,8 +2241,9 @@
 	for (i = 0; i < chip->num_devs; i++)
 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
 
-	sprintf(card->longname, "%s at 0x%lx, irq %d",
-		card->shortname, chip->port, chip->irq);
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s with %s at %#lx, irq %d", card->shortname,
+		 snd_ac97_get_short_name(chip->ac97), chip->port, chip->irq);
 
 	snd_via82xx_proc_init(chip);
 
diff -Nru a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
--- a/sound/pci/ymfpci/ymfpci_main.c	2004-10-28 22:25:59 -07:00
+++ b/sound/pci/ymfpci/ymfpci_main.c	2004-10-28 22:25:59 -07:00
@@ -2085,7 +2085,7 @@
 	}
 #endif
 	if (chip->reg_area_virt)
-		iounmap((void *)chip->reg_area_virt);
+		iounmap(chip->reg_area_virt);
 	if (chip->work_ptr.area)
 		snd_dma_free_pages(&chip->work_ptr);
 	
@@ -2217,7 +2217,7 @@
 	chip->device_id = pci->device;
 	pci_read_config_byte(pci, PCI_REVISION_ID, (u8 *)&chip->rev);
 	chip->reg_area_phys = pci_resource_start(pci, 0);
-	chip->reg_area_virt = (unsigned long)ioremap_nocache(chip->reg_area_phys, 0x8000);
+	chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
 	pci_set_master(pci);
 
 	if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) {
diff -Nru a/sound/pcmcia/Kconfig b/sound/pcmcia/Kconfig
--- a/sound/pcmcia/Kconfig	2004-10-28 22:25:58 -07:00
+++ b/sound/pcmcia/Kconfig	2004-10-28 22:25:58 -07:00
@@ -8,20 +8,32 @@
 	depends on SND && PCMCIA && ISA
 	select SND_VX_LIB
 	help
-	  Say 'Y' or 'M' to include support for Digigram VXpocket soundcard.
+	  Say Y here to include support for Digigram VXpocket
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-vxpocket.
 
 config SND_VXP440
 	tristate "Digigram VXpocket 440"
 	depends on SND && PCMCIA && ISA
 	select SND_VX_LIB
 	help
-	  Say 'Y' or 'M' to include support for Digigram VXpocket 440 soundcard.
+	  Say Y here to include support for Digigram VXpocket 440
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-vxp440.
 
 config SND_PDAUDIOCF
 	tristate "Sound Core PDAudioCF"
 	depends on SND && PCMCIA && ISA
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Sound Core PDAudioCF soundcard.
+	  Say Y here to include support for Sound Core PDAudioCF
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-pdaudiocf.
 
 endmenu
diff -Nru a/sound/ppc/Kconfig b/sound/ppc/Kconfig
--- a/sound/ppc/Kconfig	2004-10-28 22:25:57 -07:00
+++ b/sound/ppc/Kconfig	2004-10-28 22:25:57 -07:00
@@ -13,6 +13,11 @@
 	tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
 	depends on SND && I2C && INPUT
 	select SND_PCM
+	help
+	  Say Y here to include support for the integrated sound device.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-powermac.
 
 endmenu
 
diff -Nru a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
--- a/sound/ppc/tumbler.c	2004-10-28 22:25:56 -07:00
+++ b/sound/ppc/tumbler.c	2004-10-28 22:25:56 -07:00
@@ -79,7 +79,7 @@
 #ifdef CONFIG_PPC_HAS_FEATURE_CALLS
 	unsigned int addr;
 #else
-	void *addr;
+	void __iomem *addr;
 #endif
 	int active_state;
 } pmac_gpio_t;
@@ -162,7 +162,7 @@
 {
 	if (gp->addr) {
 		iounmap(gp->addr);
-		gp->addr = 0;
+		gp->addr = NULL;
 	}
 }
 #endif /* CONFIG_PPC_HAS_FEATURE_CALLS */
@@ -968,7 +968,7 @@
 #ifdef CONFIG_PPC_HAS_FEATURE_CALLS
 	gp->addr = (*base) & 0x0000ffff;
 #else
-	gp->addr = (void*)ioremap((unsigned long)(*base), 1);
+	gp->addr = ioremap((unsigned long)(*base), 1);
 #endif
 	base = (u32 *)get_property(node, "audio-gpio-active-state", NULL);
 	if (base)
diff -Nru a/sound/usb/Kconfig b/sound/usb/Kconfig
--- a/sound/usb/Kconfig	2004-10-28 22:25:59 -07:00
+++ b/sound/usb/Kconfig	2004-10-28 22:25:59 -07:00
@@ -1,6 +1,6 @@
 # ALSA USB drivers
 
-menu "ALSA USB devices"
+menu "USB devices"
 	depends on SND!=n && USB!=n
 
 config SND_USB_AUDIO
@@ -9,7 +9,11 @@
 	select SND_RAWMIDI
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for USB audio and USB MIDI devices.
+	  Say Y here to include support for USB audio and USB MIDI
+	  devices.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-usb-audio.
 
 config SND_USB_USX2Y
 	tristate "Tascam US-122, US-224 and US-428 USB driver"
@@ -18,8 +22,11 @@
 	select SND_RAWMIDI
 	select SND_PCM
 	help
-	  Say 'Y' or 'M' to include support for Tascam USB Audio/MIDI 
+	  Say Y here to include support for Tascam USB Audio/MIDI
 	  interfaces or controllers US-122, US-224 and US-428.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-usb-usx2y.
 
 endmenu
 
diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
--- a/sound/usb/usbaudio.c	2004-10-28 22:25:59 -07:00
+++ b/sound/usb/usbaudio.c	2004-10-28 22:25:59 -07:00
@@ -736,11 +736,11 @@
 		if (test_bit(i, &subs->active_mask)) {
 			if (! test_and_set_bit(i, &subs->unlink_mask)) {
 				struct urb *u = subs->dataurb[i].urb;
-				if (async)
+				if (async) {
 					u->transfer_flags |= URB_ASYNC_UNLINK;
-				else
-					u->transfer_flags &= ~URB_ASYNC_UNLINK;
-				usb_unlink_urb(u);
+					usb_unlink_urb(u);
+				} else
+					usb_kill_urb(u);
 			}
 		}
 	}
@@ -749,11 +749,11 @@
 			if (test_bit(i+16, &subs->active_mask)) {
  				if (! test_and_set_bit(i+16, &subs->unlink_mask)) {
 					struct urb *u = subs->syncurb[i].urb;
-					if (async)
+					if (async) {
 						u->transfer_flags |= URB_ASYNC_UNLINK;
-					else
-						u->transfer_flags &= ~URB_ASYNC_UNLINK;
-					usb_unlink_urb(u);
+						usb_unlink_urb(u);
+					} else
+						usb_kill_urb(u);
 				}
 			}
 		}
@@ -2746,12 +2746,13 @@
 }
 
 /*
- * Create a stream for an Edirol UA-700 interface.  The only way
+ * Create a stream for an Edirol UA-700/UA-25 interface.  The only way
  * to detect the sample rate is by looking at wMaxPacketSize.
  */
-static int create_ua700_quirk(snd_usb_audio_t *chip, struct usb_interface *iface)
+static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
+				   struct usb_interface *iface)
 {
-	static const struct audioformat ua700_format = {
+	static const struct audioformat ua_format = {
 		.format = SNDRV_PCM_FORMAT_S24_3LE,
 		.channels = 2,
 		.fmt_type = USB_FORMAT_TYPE_I,
@@ -2771,15 +2772,28 @@
 	altsd = get_iface_desc(alts);
 
 	if (altsd->bNumEndpoints == 2) {
-		static const snd_usb_midi_endpoint_info_t ep = {
+		static const snd_usb_midi_endpoint_info_t ua700_ep = {
 			.out_cables = 0x0003,
 			.in_cables  = 0x0003
 		};
-		static const snd_usb_audio_quirk_t quirk = {
+		static const snd_usb_audio_quirk_t ua700_quirk = {
+			.type = QUIRK_MIDI_FIXED_ENDPOINT,
+			.data = &ua700_ep
+		};
+		static const snd_usb_midi_endpoint_info_t ua25_ep = {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0001
+		};
+		static const snd_usb_audio_quirk_t ua25_quirk = {
 			.type = QUIRK_MIDI_FIXED_ENDPOINT,
-			.data = &ep
+			.data = &ua25_ep
 		};
-		return snd_usb_create_midi_interface(chip, iface, &quirk);
+		if (chip->dev->descriptor.idProduct == 0x002b)
+			return snd_usb_create_midi_interface(chip, iface,
+							     &ua700_quirk);
+		else
+			return snd_usb_create_midi_interface(chip, iface,
+							     &ua25_quirk);
 	}
 
 	if (altsd->bNumEndpoints != 1)
@@ -2788,7 +2802,7 @@
 	fp = kmalloc(sizeof(*fp), GFP_KERNEL);
 	if (!fp)
 		return -ENOMEM;
-	memcpy(fp, &ua700_format, sizeof(*fp));
+	memcpy(fp, &ua_format, sizeof(*fp));
 
 	fp->iface = altsd->bInterfaceNumber;
 	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
@@ -2800,9 +2814,11 @@
 		fp->rate_max = fp->rate_min = 44100;
 		break;
 	case 0x138:
+	case 0x140:
 		fp->rate_max = fp->rate_min = 48000;
 		break;
 	case 0x258:
+	case 0x260:
 		fp->rate_max = fp->rate_min = 96000;
 		break;
 	default:
@@ -2822,6 +2838,56 @@
 	return 0;
 }
 
+/*
+ * Create a stream for an Edirol UA-1000 interface.
+ */
+static int create_ua1000_quirk(snd_usb_audio_t *chip, struct usb_interface *iface)
+{
+	static const struct audioformat ua1000_format = {
+		.format = SNDRV_PCM_FORMAT_S32_LE,
+		.fmt_type = USB_FORMAT_TYPE_I,
+		.altsetting = 1,
+		.altset_idx = 1,
+		.attributes = 0,
+		.rates = SNDRV_PCM_RATE_CONTINUOUS,
+	};
+	struct usb_host_interface *alts;
+	struct usb_interface_descriptor *altsd;
+	struct audioformat *fp;
+	int stream, err;
+
+	if (iface->num_altsetting != 2)
+		return -ENXIO;
+	alts = &iface->altsetting[1];
+	altsd = get_iface_desc(alts);
+	if (alts->extralen != 11 || alts->extra[1] != CS_AUDIO_INTERFACE ||
+	    altsd->bNumEndpoints != 1)
+		return -ENXIO;
+
+	fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+	if (!fp)
+		return -ENOMEM;
+	memcpy(fp, &ua1000_format, sizeof(*fp));
+
+	fp->channels = alts->extra[4];
+	fp->iface = altsd->bInterfaceNumber;
+	fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+	fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+	fp->maxpacksize = get_endpoint(alts, 0)->wMaxPacketSize;
+	fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
+
+	stream = (fp->endpoint & USB_DIR_IN)
+		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+	err = add_audio_endpoint(chip, stream, fp);
+	if (err < 0) {
+		kfree(fp);
+		return err;
+	}
+	/* FIXME: playback must be synchronized to capture */
+	usb_set_interface(chip->dev, fp->iface, 0);
+	return 0;
+}
+
 static int snd_usb_create_quirk(snd_usb_audio_t *chip,
 				struct usb_interface *iface,
 				const snd_usb_audio_quirk_t *quirk);
@@ -2909,8 +2975,10 @@
 	case QUIRK_AUDIO_STANDARD_INTERFACE:
 	case QUIRK_MIDI_STANDARD_INTERFACE:
 		return create_standard_interface_quirk(chip, iface, quirk);
-	case QUIRK_AUDIO_EDIROL_UA700:
-		return create_ua700_quirk(chip, iface);
+	case QUIRK_AUDIO_EDIROL_UA700_UA25:
+		return create_ua700_ua25_quirk(chip, iface);
+	case QUIRK_AUDIO_EDIROL_UA1000:
+		return create_ua1000_quirk(chip, iface);
 	default:
 		snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
 		return -ENXIO;
diff -Nru a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
--- a/sound/usb/usbaudio.h	2004-10-28 22:25:58 -07:00
+++ b/sound/usb/usbaudio.h	2004-10-28 22:25:58 -07:00
@@ -155,7 +155,8 @@
 #define QUIRK_AUDIO_FIXED_ENDPOINT	4
 #define QUIRK_AUDIO_STANDARD_INTERFACE	5
 #define QUIRK_MIDI_STANDARD_INTERFACE	6
-#define QUIRK_AUDIO_EDIROL_UA700	7
+#define QUIRK_AUDIO_EDIROL_UA700_UA25	7
+#define QUIRK_AUDIO_EDIROL_UA1000	8
 
 typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
 typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
@@ -187,7 +188,7 @@
 
 /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
 
-/* for QUIRK_AUDIO_EDIROL_UA700, data is NULL */
+/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
 
 /*
  */
diff -Nru a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
--- a/sound/usb/usbmidi.c	2004-10-28 22:25:59 -07:00
+++ b/sound/usb/usbmidi.c	2004-10-28 22:25:59 -07:00
@@ -715,9 +715,9 @@
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 		snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
 		if (ep->out && ep->out->urb)
-			usb_unlink_urb(ep->out->urb);
+			usb_kill_urb(ep->out->urb);
 		if (ep->in && ep->in->urb)
-			usb_unlink_urb(ep->in->urb);
+			usb_kill_urb(ep->in->urb);
 	}
 }
 
@@ -1161,7 +1161,7 @@
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 		snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
 		if (ep->in)
-			usb_unlink_urb(ep->in->urb);
+			usb_kill_urb(ep->in->urb);
 	}
 }
 
diff -Nru a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
--- a/sound/usb/usbmixer_maps.c	2004-10-28 22:25:59 -07:00
+++ b/sound/usb/usbmixer_maps.c	2004-10-28 22:25:59 -07:00
@@ -91,6 +91,14 @@
 	{ 0 } /* terminator */
 };
 
+/* LineX FM Transmitter entry - needed to bypass controls bug */
+static struct usbmix_name_map linex_map[] = {
+	/* 1: IT pcm */
+	/* 2: OT Speaker */ 
+	{ 3, "Master" }, /* FU: master volume - left / right / mute */
+	{ 0 } /* terminator */
+};
+
 /* Section "justlink_map" below added by James Courtier-Dutton <James@superbug.demon.co.uk>
  * sourced from Maplin Electronics (http://www.maplin.co.uk), part number A56AK
  * Part has 2 connectors that act as a single output. (TOSLINK Optical for digital out, and 3.5mm Jack for Analogue out.)
@@ -120,6 +128,7 @@
 
 static struct usbmix_ctl_map usbmix_ctl_maps[] = {
 	{ 0x41e, 0x3000, extigy_map, 1 },
+	{ 0x8bb, 0x2702, linex_map, 1 },
 	{ 0xc45, 0x1158, justlink_map, 0 },
 	{ 0 } /* terminator */
 };
diff -Nru a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
--- a/sound/usb/usbquirks.h	2004-10-28 22:25:57 -07:00
+++ b/sound/usb/usbquirks.h	2004-10-28 22:25:57 -07:00
@@ -534,15 +534,15 @@
 		.data = (const snd_usb_audio_quirk_t[]) {
 			{
 				.ifnum = 1,
-				.type = QUIRK_AUDIO_EDIROL_UA700
+				.type = QUIRK_AUDIO_EDIROL_UA700_UA25
 			},
 			{
 				.ifnum = 2,
-				.type = QUIRK_AUDIO_EDIROL_UA700
+				.type = QUIRK_AUDIO_EDIROL_UA700_UA25
 			},
 			{
 				.ifnum = 3,
-				.type = QUIRK_AUDIO_EDIROL_UA700
+				.type = QUIRK_AUDIO_EDIROL_UA700_UA25
 			},
 			{
 				.ifnum = -1
@@ -638,37 +638,11 @@
 		.data = (const snd_usb_audio_quirk_t[]) {
 			{
 				.ifnum = 1,
-				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
-				.data = & (const struct audioformat) {
-					.format = SNDRV_PCM_FORMAT_S24,
-					.channels = 12,
-					.iface = 1,
-					.altsetting = 1,
-					.altset_idx = 1,
-					.attributes = 0,
-					.endpoint = 0x81,
-					.ep_attr = 0x01,
-					.rates = SNDRV_PCM_RATE_CONTINUOUS,
-					.rate_min = 48000,
-					.rate_max = 48000,
-				}
+				.type = QUIRK_AUDIO_EDIROL_UA1000
 			},
 			{
 				.ifnum = 2,
-				.type = QUIRK_AUDIO_FIXED_ENDPOINT,
-				.data = & (const struct audioformat) {
-					.format = SNDRV_PCM_FORMAT_S24,
-					.channels = 10,
-					.iface = 2,
-					.altsetting = 1,
-					.altset_idx = 1,
-					.attributes = 0,
-					.endpoint = 0x02,
-					.ep_attr = 0x01,
-					.rates = SNDRV_PCM_RATE_CONTINUOUS,
-					.rate_min = 48000,
-					.rate_max = 48000,
-				}
+				.type = QUIRK_AUDIO_EDIROL_UA1000
 			},
 			{
 				.ifnum = 3,
@@ -756,6 +730,37 @@
 		.product_name = "UM-1SX",
 		.ifnum = 0,
 		.type = QUIRK_MIDI_STANDARD_INTERFACE
+	}
+},
+{	/*
+	 * This quirk is for the "Advanced" modes of the Edirol UA-25.
+	 * If the switch is not in an advanced setting, the UA-25 has
+	 * ID 0x0582/0x0073 and is standard compliant (no quirks), but
+	 * offers only 16-bit PCM at 44.1 kHz and no MIDI.
+	 */
+	USB_DEVICE_VENDOR_SPEC(0x0582, 0x0074),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "EDIROL",
+		.product_name = "UA-25",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_AUDIO_EDIROL_UA700_UA25
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_EDIROL_UA700_UA25
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_EDIROL_UA700_UA25
+			},
+			{
+				.ifnum = -1
+			}
+		}
 	}
 },
 
diff -Nru a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
--- a/sound/usb/usx2y/usbusx2y.c	2004-10-28 22:25:57 -07:00
+++ b/sound/usb/usx2y/usbusx2y.c	2004-10-28 22:25:57 -07:00
@@ -1,6 +1,10 @@
 /*
  * usbus428.c - ALSA USB US-428 Driver
  *
+2004-09-20 Karsten Wiese
+	Version 0.7.3:
+	Use usb_kill_urb() instead of deprecated (kernel 2.6.9) usb_unlink_urb().
+
 2004-07-13 Karsten Wiese
 	Version 0.7.1:
 	Don't sleep in START/STOP callbacks anymore.
@@ -115,7 +119,7 @@
 
 
 MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
-MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.7.2");
+MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.7.3");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}");
 
@@ -276,7 +280,7 @@
 	int	i;
 	for (i = 0; i < URBS_AsyncSeq; ++i) {
 		if (S[i].urb) {
-			usb_unlink_urb(S->urb[i]);
+			usb_kill_urb(S->urb[i]);
 			usb_free_urb(S->urb[i]);
 			S->urb[i] = NULL;
 		}
@@ -407,7 +411,7 @@
 		usX2Y->chip.shutdown = 1;
 		usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
 		usX2Y_unlinkSeq(&usX2Y->AS04);
-		usb_unlink_urb(usX2Y->In04urb);
+		usb_kill_urb(usX2Y->In04urb);
 		snd_card_disconnect((snd_card_t*)ptr);
 		/* release the midi resources */
 		list_for_each(p, &usX2Y->chip.midi_list) {
diff -Nru a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
--- a/sound/usb/usx2y/usbusx2yaudio.c	2004-10-28 22:25:58 -07:00
+++ b/sound/usb/usx2y/usbusx2yaudio.c	2004-10-28 22:25:58 -07:00
@@ -656,7 +656,7 @@
 		if (us) {
 			us->submitted =	2*NOOF_SETRATE_URBS;
 			for (i = 0; i < NOOF_SETRATE_URBS; ++i) {
-				usb_unlink_urb(us->urb[i]);
+				usb_kill_urb(us->urb[i]);
 				usb_free_urb(us->urb[i]);
 			}
 			usX2Y->US04 = NULL;
@@ -671,7 +671,7 @@
 
 static int usX2Y_format_set(usX2Ydev_t *usX2Y, snd_pcm_format_t format)
 {
-	int alternate, unlink_err, err;
+	int alternate, err;
 	struct list_head* p;
 	if (format == SNDRV_PCM_FORMAT_S24_3LE) {
 		alternate = 2;
@@ -683,15 +683,13 @@
 	list_for_each(p, &usX2Y->chip.midi_list) {
 		snd_usbmidi_input_stop(p);
 	}
-	unlink_err = usb_unlink_urb(usX2Y->In04urb);
+	usb_kill_urb(usX2Y->In04urb);
 	if ((err = usb_set_interface(usX2Y->chip.dev, 0, alternate))) {
 		snd_printk("usb_set_interface error \n");
 		return err;
 	}
-	if (0 == unlink_err) {
-		usX2Y->In04urb->dev = usX2Y->chip.dev;
-		err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
-	}
+	usX2Y->In04urb->dev = usX2Y->chip.dev;
+	err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
 	list_for_each(p, &usX2Y->chip.midi_list) {
 		snd_usbmidi_input_start(p);
 	}
@@ -824,20 +822,20 @@
 			subs->prepared = 1;
 		}
 		while (subs->submitted_urbs)
-		for (u = 0; u < NRURBS; u++) {
-			snd_printdd("%i\n", subs->urb[u]->status);
-			while(subs->urb[u]->status  ||  NULL != subs->urb[u]->hcpriv) {
-				signed long timeout;
-				snd_printdd("ep=%i waiting for urb=%p status=%i hcpriv=%p\n",
-					   subs->endpoint, subs->urb[u],
-					   subs->urb[u]->status, subs->urb[u]->hcpriv);
-				set_current_state(TASK_INTERRUPTIBLE);
-				timeout = schedule_timeout(HZ/10);
-				if (signal_pending(current)) {
-					return -ERESTARTSYS;
+			for (u = 0; u < NRURBS; u++) {
+				snd_printdd("%i\n", subs->urb[u]->status);
+				while(subs->urb[u]->status  ||  NULL != subs->urb[u]->hcpriv) {
+					signed long timeout;
+					snd_printdd("ep=%i waiting for urb=%p status=%i hcpriv=%p\n",
+						    subs->endpoint, subs->urb[u],
+						    subs->urb[u]->status, subs->urb[u]->hcpriv);
+					set_current_state(TASK_INTERRUPTIBLE);
+					timeout = schedule_timeout(HZ/10);
+					if (signal_pending(current)) {
+						return -ERESTARTSYS;
+					}
 				}
 			}
-		}
 		subs->completed_urb = NULL;
 		subs->next_urb_complete = -1;
 		subs->stalled = 0;
diff -Nru a/usr/Makefile b/usr/Makefile
--- a/usr/Makefile	2004-10-28 22:25:58 -07:00
+++ b/usr/Makefile	2004-10-28 22:25:58 -07:00
@@ -3,7 +3,7 @@
 
 hostprogs-y  := gen_init_cpio
 
-clean-files := initramfs_data.cpio.gz
+clean-files := initramfs_data.cpio.gz initramfs_list
 
 # If you want a different list of files in the initramfs_data.cpio
 # then you can either overwrite the cpio_list in this directory
@@ -23,28 +23,17 @@
 # Commented out for now
 # initramfs-y := $(obj)/root/hello
 
-quiet_cmd_gen_list = GEN_INITRAMFS_LIST $@
-      cmd_gen_list = $(shell \
-        if test -f $(CONFIG_INITRAMFS_SOURCE); then \
-	  if [ $(CONFIG_INITRAMFS_SOURCE) != $@ ]; then \
-	    echo 'cp -f $(CONFIG_INITRAMFS_SOURCE) $@'; \
-	  else \
-	    echo 'echo Using shipped $@'; \
-	  fi; \
-	elif test -d $(CONFIG_INITRAMFS_SOURCE); then \
-	  echo 'scripts/gen_initramfs_list.sh $(CONFIG_INITRAMFS_SOURCE) > $@'; \
-	else \
-	  echo 'echo Using shipped $@'; \
-	fi)
-
-
-$(INITRAMFS_LIST): FORCE
-	$(call cmd,gen_list)
+filechk_initramfs_list = $(CONFIG_SHELL) \
+ $(srctree)/scripts/gen_initramfs_list.sh $(CONFIG_INITRAMFS_SOURCE)
+			   
+$(obj)/initramfs_list: FORCE
+	$(call filechk,initramfs_list)
 
 quiet_cmd_cpio = CPIO    $@
-      cmd_cpio = ./$< $(INITRAMFS_LIST) > $@
+      cmd_cpio = ./$< $(obj)/initramfs_list > $@
 
-$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio $(initramfs-y) $(INITRAMFS_LIST) FORCE
+$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio \
+                            $(initramfs-y) $(obj)/initramfs_list FORCE
 	$(call if_changed,cpio)
 
 targets += initramfs_data.cpio
diff -Nru a/usr/initramfs_list b/usr/initramfs_list
--- a/usr/initramfs_list	2004-10-28 22:25:57 -07:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,5 +0,0 @@
-# This is a very simple initramfs - mostly preliminary for future expansion
-
-dir /dev 0755 0 0
-nod /dev/console 0600 0 0 c 5 1
-dir /root 0700 0 0