# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	v2.5.75 -> 1.1444 
#	drivers/char/drm/drm_agpsupport.h	1.19    -> 1.21   
#	drivers/char/drm/drm_context.h	1.12    -> 1.13   
#	include/linux/proc_fs.h	1.23    -> 1.24   
#	drivers/net/e100/e100_phy.c	1.14    -> 1.15   
#	drivers/char/drm/i810_drm.h	1.7     -> 1.8    
#	drivers/net/irda/nsc-ircc.c	1.25    -> 1.26   
#	arch/sh/kernel/time.c	1.9     -> 1.10   
#	arch/parisc/kernel/pci.c	1.9     -> 1.10   
#	arch/s390/kernel/time.c	1.15    -> 1.16   
#	          fs/libfs.c	1.22    -> 1.23   
#	      kernel/ksyms.c	1.208   -> 1.209  
#	arch/parisc/kernel/ioctl32.c	1.11    -> 1.12   
#	net/irda/irnet/irnet_irda.c	1.20    -> 1.21   
#	           fs/open.c	1.44    -> 1.45   
#	  drivers/net/dgrs.c	1.17    -> 1.18   
#	net/ipv6/ip6_output.c	1.37    -> 1.38   
#	      mm/readahead.c	1.33    -> 1.34   
#	drivers/usb/core/inode.c	1.50    -> 1.51   
#	include/linux/irda.h	1.6     -> 1.7    
#	include/linux/mount.h	1.9     -> 1.10   
#	drivers/net/tokenring/skisa.c	1.10    -> 1.11   
#	drivers/char/drm/drm_proc.h	1.13    -> 1.14   
#	       kernel/fork.c	1.130   -> 1.131  
#	drivers/block/ll_rw_blk.c	1.190   -> 1.191  
#	     kernel/sysctl.c	1.47    -> 1.48   
#	           fs/attr.c	1.18    -> 1.19   
#	         fs/dcache.c	1.59    -> 1.60   
#	drivers/net/hamradio/mkiss.h	1.2     -> 1.3    
#	   arch/i386/Kconfig	1.65    -> 1.66   
#	fs/reiserfs/do_balan.c	1.17    -> 1.18   
#	drivers/char/drm/r128_state.c	1.11    -> 1.12   
#	drivers/char/drm/drm_memory_debug.h	1.2     -> 1.3    
#	    fs/jbd/journal.c	1.59    -> 1.61   
#	      net/ipv4/udp.c	1.44    -> 1.45   
#	     fs/devfs/base.c	1.93    -> 1.95   
#	drivers/char/drm/drm_memory.h	1.11    -> 1.12   
#	drivers/usb/class/usblp.c	1.49    -> 1.50   
#	           fs/stat.c	1.19    -> 1.20   
#	    fs/binfmt_aout.c	1.16    -> 1.17   
#	       mm/swapfile.c	1.80    -> 1.81   
#	          fs/ioctl.c	1.9     -> 1.10   
#	arch/ia64/kernel/time.c	1.27    -> 1.28   
#	drivers/char/drm/drm_bufs.h	1.15    -> 1.16   
#	drivers/block/Kconfig	1.5     -> 1.6    
#	 drivers/block/nbd.c	1.57    -> 1.64   
#	 fs/jbd/checkpoint.c	1.22    -> 1.23   
#	drivers/char/drm/drm.h	1.11    -> 1.12   
#	drivers/net/pcmcia/3c574_cs.c	1.18    -> 1.19   
#	drivers/char/drm/drm_ioctl.h	1.11    -> 1.12   
#	drivers/usb/core/message.c	1.28    -> 1.29   
#	          fs/mpage.c	1.41    -> 1.43   
#	arch/m68k/kernel/time.c	1.10    -> 1.11   
#	  include/linux/fs.h	1.255   -> 1.256  
#	 drivers/pcmcia/cs.c	1.50    -> 1.52   
#	drivers/net/appletalk/ltpc.c	1.11    -> 1.12   
#	fs/reiserfs/fix_node.c	1.28    -> 1.29   
#	fs/jbd/transaction.c	1.69    -> 1.70   
#	drivers/eisa/Kconfig	1.3     -> 1.4    
#	drivers/input/misc/gsc_ps2.c	1.2     -> 1.3    
#	arch/parisc/kernel/unaligned.c	1.2     -> 1.3    
#	net/irda/ircomm/ircomm_tty.c	1.25    -> 1.26   
#	 fs/reiserfs/inode.c	1.78    -> 1.79   
#	drivers/char/drm/i810.h	1.8     -> 1.9    
#	drivers/net/sunhme.c	1.36    -> 1.37   
#	arch/parisc/kernel/sys_parisc32.c	1.16    -> 1.17   
#	        mm/filemap.c	1.198   -> 1.199  
#	drivers/char/drm/i810_dma.c	1.27    -> 1.28   
#	          fs/namei.c	1.80    -> 1.81   
#	drivers/char/drm/r128.h	1.8     -> 1.9    
#	include/asm-parisc/parisc-device.h	1.1     -> 1.2    
#	           fs/exec.c	1.91    -> 1.92   
#	      fs/eventpoll.c	1.22    -> 1.23   
#	      net/ipv6/raw.c	1.36    -> 1.37   
#	drivers/usb/storage/initializers.c	1.7     -> 1.8    
#	arch/parisc/kernel/time.c	1.9     -> 1.11   
#	          mm/shmem.c	1.129   -> 1.130  
#	arch/mips/kernel/time.c	1.9     -> 1.10   
#	include/linux/seqlock.h	1.2     -> 1.3    
#	     fs/binfmt_elf.c	1.48    -> 1.49   
#	         mm/memory.c	1.125   -> 1.126  
#	            fs/aio.c	1.33    -> 1.34   
#	drivers/usb/usb-skeleton.c	1.38    -> 1.39   
#	drivers/net/e100/e100_main.c	1.79    -> 1.80   
#	arch/i386/kernel/time.c	1.38    -> 1.39   
#	arch/sparc64/kernel/time.c	1.41    -> 1.42   
#	drivers/net/wireless/atmel_cs.c	1.1     -> 1.2    
#	drivers/net/appletalk/cops.c	1.16    -> 1.17   
#	           ipc/shm.c	1.27    -> 1.28   
#	     kernel/compat.c	1.17    -> 1.18   
#	drivers/net/irda/irda-usb.c	1.40    -> 1.41   
#	    fs/ext2/ialloc.c	1.35    -> 1.36   
#	drivers/char/drm/radeon_drv.h	1.22    -> 1.23   
#	arch/alpha/kernel/time.c	1.19    -> 1.20   
#	include/linux/reiserfs_fs_sb.h	1.23    -> 1.24   
#	arch/parisc/hpux/sys_hpux.c	1.5     -> 1.6    
#	       mm/oom_kill.c	1.23    -> 1.24   
#	    arch/arm/Kconfig	1.25    -> 1.26   
#	include/asm-v850/statfs.h	1.1     -> 1.2    
#	drivers/usb/net/usbnet.c	1.57    -> 1.58   
#	include/linux/sysctl.h	1.47    -> 1.48   
#	drivers/char/drm/drm_fops.h	1.10    -> 1.11   
#	include/net/irda/nsc-ircc.h	1.1     -> 1.2    
#	   drivers/net/tg3.c	1.72    -> 1.73   
#	      net/ipv4/raw.c	1.38    -> 1.39   
#	    fs/nfsd/nfssvc.c	1.39    -> 1.40   
#	arch/mips64/kernel/time.c	1.1     -> 1.2    
#	arch/sparc/kernel/time.c	1.18    -> 1.19   
#	         fs/buffer.c	1.206   -> 1.207  
#	drivers/block/loop.c	1.100   -> 1.102  
#	      fs/direct-io.c	1.30    -> 1.31   
#	  arch/arm26/Kconfig	1.4     -> 1.5    
#	drivers/net/declance.c	1.16    -> 1.17   
#	         MAINTAINERS	1.153   -> 1.154  
#	 arch/parisc/Kconfig	1.17    -> 1.19   
#	    net/irda/irttp.c	1.15    -> 1.16   
#	drivers/net/sundance.c	1.45    -> 1.46   
#	fs/reiserfs/journal.c	1.69    -> 1.70   
#	drivers/char/drm/drm_scatter.h	1.10    -> 1.11   
#	      fs/proc/base.c	1.52    -> 1.53   
#	           mm/mmap.c	1.88    -> 1.89   
#	include/linux/time.h	1.17    -> 1.18   
#	     fs/read_write.c	1.31    -> 1.32   
#	drivers/char/drm/drm_dma.h	1.14    -> 1.15   
#	drivers/parisc/Kconfig	1.5     -> 1.6    
#	arch/v850/kernel/time.c	1.5     -> 1.6    
#	fs/reiserfs/bitmap.c	1.26    -> 1.27   
#	      fs/namespace.c	1.47    -> 1.48   
#	drivers/char/drm/radeon_drm.h	1.15    -> 1.16   
#	drivers/net/sk_mca.c	1.10    -> 1.11   
#	drivers/char/drm/drm_lock.h	1.8     -> 1.9    
#	arch/m68knommu/kernel/time.c	1.6     -> 1.7    
#	            Makefile	1.415   -> 1.416  
#	     fs/ext3/inode.c	1.77    -> 1.78   
#	drivers/net/pcmcia/smc91c92_cs.c	1.19    -> 1.20   
#	arch/x86_64/kernel/time.c	1.19    -> 1.20   
#	Documentation/DocBook/procfs-guide.tmpl	1.3     -> 1.4    
#	arch/v850/kernel/bug.c	1.3     -> 1.4    
#	drivers/char/drm/radeon_drv.c	1.7     -> 1.8    
#	 fs/reiserfs/stree.c	1.35    -> 1.36   
#	       fs/quota_v1.c	1.8     -> 1.9    
#	drivers/char/drm/drmP.h	1.25    -> 1.26   
#	      fs/nfs/write.c	1.40    -> 1.41   
#	drivers/net/irda/Kconfig	1.5     -> 1.6    
#	net/ipv4/tcp_input.c	1.43    -> 1.44   
#	arch/ppc/kernel/time.c	1.21    -> 1.22   
#	Documentation/nbd.txt	1.2     -> 1.3    
#	      fs/proc/root.c	1.15    -> 1.16   
#	drivers/usb/storage/unusual_devs.h	1.47    -> 1.48   
#	      fs/nfs/inode.c	1.81    -> 1.82   
#	drivers/usb/serial/ftdi_sio.c	1.43    -> 1.44   
#	 arch/x86_64/Kconfig	1.25    -> 1.26   
#	arch/v850/kernel/simcons.c	1.7     -> 1.8    
#	      kernel/sched.c	1.201   -> 1.202  
#	drivers/char/drm/drm_drawable.h	1.5     -> 1.6    
#	drivers/block/Makefile	1.18    -> 1.19   
#	        init/Kconfig	1.17    -> 1.18   
#	 include/linux/jbd.h	1.37    -> 1.38   
#	drivers/char/drm/drm_stub.h	1.7     -> 1.8    
#	      net/ipv6/udp.c	1.43    -> 1.44   
#	drivers/char/drm/drm_drv.h	1.20    -> 1.21   
#	include/asm-parisc/byteorder.h	1.1     -> 1.2    
#	drivers/char/agp/via-agp.c	1.46    -> 1.47   
#	drivers/char/drm/radeon_state.c	1.20    -> 1.21   
#	drivers/char/drm/drm_init.h	1.6     -> 1.7    
#	drivers/usb/serial/ftdi_sio.h	1.5     -> 1.6    
#	          mm/nommu.c	1.5     -> 1.6    
#	include/asm-parisc/pgtable.h	1.12    -> 1.13   
#	     fs/jbd/commit.c	1.37    -> 1.39   
#	arch/parisc/kernel/drivers.c	1.5     -> 1.6    
#	include/linux/reiserfs_fs.h	1.49    -> 1.50   
#	     fs/proc/inode.c	1.23    -> 1.24   
#	drivers/char/drm/radeon.h	1.12    -> 1.13   
#	drivers/char/drm/drm_auth.h	1.6     -> 1.7    
#	drivers/char/drm/ati_pcigart.h	1.9     -> 1.10   
#	drivers/net/wireless/wavelan.c	1.17    -> 1.18   
#	drivers/char/drm/drm_os_linux.h	1.10    -> 1.11   
#	drivers/net/sb1250-mac.c	1.5     -> 1.6    
#	 include/linux/nbd.h	1.17    -> 1.20   
#	arch/ppc64/kernel/time.c	1.21    -> 1.22   
#	    net/irda/irlap.c	1.21    -> 1.22   
#	          fs/locks.c	1.41    -> 1.42   
#	drivers/char/drm/i810_drv.h	1.10    -> 1.11   
#	drivers/net/irda/old_belkin.c	1.5     -> 1.6    
#	   arch/ia64/Kconfig	1.36    -> 1.37   
#	drivers/net/pcmcia/3c589_cs.c	1.18    -> 1.19   
#	drivers/net/tokenring/proteon.c	1.3     -> 1.4    
#	drivers/net/hamradio/mkiss.c	1.11    -> 1.12   
#	drivers/net/via-rhine.c	1.42    -> 1.43   
#	     net/ipv4/igmp.c	1.32    -> 1.33   
#	    arch/ppc/Kconfig	1.30    -> 1.31   
#	  drivers/net/plip.c	1.14    -> 1.15   
#	drivers/net/tokenring/3c359.c	1.9     -> 1.10   
#	drivers/usb/storage/datafab.c	1.16    -> 1.17   
#	          fs/inode.c	1.98    -> 1.99   
#	arch/v850/kernel/gbus_int.c	1.5     -> 1.6    
#	drivers/usb/storage/freecom.c	1.26    -> 1.27   
#	   fs/proc/generic.c	1.22    -> 1.23   
#	drivers/char/drm/drm_sarea.h	1.1     -> 1.2    
#	include/linux/loop.h	1.15    -> 1.16   
#	drivers/char/drm/drm_vm.h	1.24    -> 1.25   
#	drivers/char/drm/r128_drv.h	1.14    -> 1.15   
#	include/asm-parisc/processor.h	1.10    -> 1.11   
#	      fs/block_dev.c	1.134   -> 1.135  
#	arch/parisc/kernel/traps.c	1.9     -> 1.10   
#	fs/reiserfs/tail_conversion.c	1.25    -> 1.26   
#	arch/parisc/kernel/module.c	1.5     -> 1.6    
#	Documentation/kernel-parameters.txt	1.23    -> 1.24   
#	Documentation/DocBook/procfs_example.c	1.4     -> 1.5    
#	include/net/irda/irda_device.h	1.5     -> 1.6    
#	               (new)	        -> 1.1     drivers/block/cryptoloop.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1388
# Linux 2.5.75
# 
# Making ready for the pre-2.6.x series ...
# --------------------------------------------
# 03/07/10	greg@kroah.com	1.1372.2.10
# [PATCH] USB: remove pointless warning about using usbdevfs
# 
# This is being printed when it shouldn't, but there really isn't an
# easy way to fix it.  This closes bug #223.
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1389
# [IrDA] include cleanup
# 
# 	o [CORRECT] Cleanup cruft from <linux/irda.h>
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1390
# [IrDA] struct check
# 
# 		<Suggested by Russell King>
# 	o [FEATURE] Add struct size check for buggy compilers
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1391
# [IrDA] irtty leaks
# 
# 		<Stanford checker>
# 	o [CORRECT] fix two additional potential skb leaks in IrTTP.
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1392
# [IrDA] irnet cast
# 
# 		<Suggested by David S. Miller>
# 	o [FEATURE] remove pointer casting in IrNET debug code missed by David.
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1393
# [IrDA] IrCOMM devfs
# 
# 		<Original patch from Martin Diehl>
# 	o [CRITICA] fix IrCOMM bogus device names with devfs
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1394
# [IrDA] setup dma fix
# 
# 	o [CORRECT] Make ISA drivers depend on ISA. This is the consequence
# 		from David's change to setup_dma().
# 	o [CORRECT] Make new dongle drivers depend on sir-dev (they require it)
# 	o [FEATURE] Make old dongle drivers depend on irtty/irport
# 	o [FEATURE] irda-usb driver is no longer experimental
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1395
# [IrDA] irda-usb endian
# 
# 	o [FEATURE] Add USB-ID of new device
# 		<Original patch from Jacek Jakubowski>
# 	o [CORRECT] Endianess fixes (for PPC and co.)
# --------------------------------------------
# 03/07/10	jt@bougret.hpl.hp.com	1.1396
# [IrDA] nsc 39x support
# 
# 		<Original patch from Jan Frey>
# 	o [FEATURE] Add preliminary support for NSC PC8739x chipset
# 		(IBM R31 laptops)
# --------------------------------------------
# 03/07/10	greg@kroah.com	1.1388.1.1
# Merge kroah.com:/home/greg/linux/BK/bleed-2.5
# into kroah.com:/home/greg/linux/BK/gregkh-2.5
# --------------------------------------------
# 03/07/10	jcchen@icplus.com.tw	1.1388.2.1
# [netdrvr sundance] increase eeprom read timeout
# --------------------------------------------
# 03/07/10	taowenhwa@intel.com	1.1388.2.2
# [e100] cu_start: timeout waiting for cu
# 
# * Bug fix: 82557 (with National PHY) timeout during init
#   [Adam Kropelin] akropel1@rochester.rr.com
# --------------------------------------------
# 03/07/10	taowenhwa@intel.com	1.1388.2.3
# [e100] misc
# 
# * Allow changing Wake On LAN when EEPROM disabled
# * Change Log updated
# * Version changed
# --------------------------------------------
# 03/07/10	shemminger@osdl.org	1.1388.2.4
# [PATCH] convert plip to alloc_netdev
# 
# This converts the parallel network driver to use alloc_netdev instead
# of doing it's own allocation.
# 
# Tested (load/unload) on 2.5.74
# --------------------------------------------
# 03/07/10	ralf@linux-mips.org	1.1388.2.5
# [PATCH] mkiss
# 
# Below patch cleans the mkiss driver.  After the previous cleanup in
# 2.4.0-prerelease various code had become unreachable because nothing
# was ever setting MKISS_DRIVER_MAGIC.  This fixes fixes an oops - the
# mkiss pointer was potencially NULL.  And it also removes the
# MOD_{INC,DEC}_USE_COUNT calls.
# 
# Alan, lemme know if you want me to cook a 2.4 patch also.
# 
# Patch from Jeroen Vreeken PE1RXQ.
# 
# Ralf
# --------------------------------------------
# 03/07/10	daniel.ritz@gmx.ch	1.1388.2.6
# [PATCH] more net driver timer fixes
# 
# following patch fixes some bogus additions to jiffies (w/o HZ beeing involved)
# - appletalk/cops.c
# - appletalk/ltpc.c
# - declance.c
# - sb1250-mac.c
# - sk_mca.c
# - via-rhine.c
# against 2.5.73-bk
# --------------------------------------------
# 03/07/10	daniel.ritz@gmx.ch	1.1388.2.7
# [PATCH] net/pcmcia fix fast_poll timers (HZ > 100)
# 
# i think we want fast_poll to behave the same with HZ=100 and HZ=1000
# --------------------------------------------
# 03/07/10	shemminger@osdl.org	1.1388.2.8
# [netdrvr dgrs] convert to using alloc_etherdev
# --------------------------------------------
# 03/07/10	jgarzik@redhat.com	1.1388.2.9
# [netdrvr tg3] more ULL suffixes to make gcc 3.3 happy
# --------------------------------------------
# 03/07/10	jgarzik@redhat.com	1.1388.2.10
# [netdrvr] fix compiler warnings in 3c359, proteon, skisa
# tokenring drivers.
# --------------------------------------------
# 03/07/10	jgarzik@redhat.com	1.1388.2.11
# [netdrvr wavelan] remove check_region usage
# --------------------------------------------
# 03/07/10	jgarzik@redhat.com	1.1388.2.12
# [netdrvr atmel_cs] kill compiler warning (jumping to "empty" label)
# --------------------------------------------
# 03/07/10	davem@nuts.ninka.net	1.1388.3.1
# [TCP]: When in SYN-SENT, initialize metrics after move to established state.
# --------------------------------------------
# 03/07/10	yoshfuji@linux-ipv6.org	1.1388.3.2
# [IPV6]: Fix offset of payload with extension header.
# 
# Based upon a patch from Thomas Graf <tgraf@suug.ch>.
# --------------------------------------------
# 03/07/10	tgraf@suug.ch	1.1388.3.3
# [NET]: Return EDESTADDRREQ as appropriate in sendmsg implementations.
# 
# Another 1003.1 fix:
# 
# [EDESTADDRREQ]
#     The socket is not connection-mode and does not have its peer
#     address set, and no destination address was specified.
# 
# fixes sendmsg in ipv{4,6}/{raw,udp}
# --------------------------------------------
# 03/07/10	davem@nuts.ninka.net	1.1388.3.4
# [NET]: Ok, sunhme is VLAN challenged after all.
# --------------------------------------------
# 03/07/10	dlstevens@us.ibm.com	1.1388.3.5
# [IPV4]: Do not sent IGMP leave messages unless IFF_UP.
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1397
# Merge bk://kernel.bkbits.net/jgarzik/irda-2.5
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1398
# Merge bk://kernel.bkbits.net/jgarzik/net-drivers-2.5
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1399
# Avoid mmap() overflow case if TASK_SIZE is the
# full range of an "unsigned long" (sparc64).
# --------------------------------------------
# 03/07/10	petr@scssoft.com	1.1400
# [PATCH] via-agp.c - agp_try_unsupported typo
# 
# via-agp.c has the agp_try_unsupported test reverted
# --------------------------------------------
# 03/07/10	Andries.Brouwer@cwi.nl	1.1401
# [PATCH] cryptoloop
# 
# util-linux is waiting for this: it needs to update "struct loop_info64"
# to add the encryption policy name.
# --------------------------------------------
# 03/07/10	davem@kernel.bkbits.net	1.1402
# Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5
# into kernel.bkbits.net:/home/davem/net-2.5
# --------------------------------------------
# 03/07/10	willy@debian.org	1.1401.1.1
# [PATCH] parisc updates
# 
# arch/parisc, drivers/parisc and include/asm-parisc updates:
# 
#  - Fixups for struct timespec changes (James Bottomley)
#  - Add CONFIG_FRAME_POINTER (Thibaut Varene)
#  - Fix hpux ustat emulation (Helge Deller)
#  - Add a ->remove operation to struct parisc_device (James Bottomley)
#  - More work on modules (James Bottomley)
#  - More unaligned instructions handled (LaMont Jones)
#  - Fix byteswap assembly (Grant Grundler)
#  - Allow ISA support to be selected (Matthew Wilcox)
#  - Fix swapping (James Bottomley)
# --------------------------------------------
# 03/07/10	willy@debian.org	1.1401.1.2
# [PATCH] Makefile update for parisc
# 
# parisc64 machines should build parisc kernels.
# --------------------------------------------
# 03/07/10	willy@debian.org	1.1401.1.3
# [PATCH] eisa Kconfig update for parisc
# 
# PA-RISC doesn't have PCI<->EISA bridges (they're all GSC<->EISA).
# --------------------------------------------
# 03/07/10	willy@debian.org	1.1401.1.4
# [PATCH] Add two sysctls for PA-RISC
# 
# Add two PA-RISC sysctls.
# --------------------------------------------
# 03/07/10	willy@debian.org	1.1401.1.5
# [PATCH] Remove warning from binfmt_elf.c for upwards growing stack
# --------------------------------------------
# 03/07/10	willy@debian.org	1.1401.1.6
# [PATCH] gsc-ps2 update
# 
# Update gsc_ps2 for recent changes.
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1403
# Merge bk://kernel.bkbits.net/davem/net-2.5
# into home.osdl.org:/home/torvalds/v2.5/linux
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1404
# Merge comment updates from DRI CVS tree.
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1405
# Update i810 DRI driver from CVS to add page flipping.
# 
# (version 1.2.1 to 1.3.0)
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1406
# Update r128 driver from DRI CVS: add support for ycbcr textures.
# 
# (version 2.3.0 -> 2.4.0)
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1407
# Update radeon driver from DRI CVS: add more commands.
# 
# (version 1.8.0 -> 1.9.0)
# --------------------------------------------
# 03/07/10	torvalds@home.osdl.org	1.1408
# Merge from DRI CVS tree: avoid zero DRI "handles".
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1409
# [PATCH] fix return of compat_sys_sched_getaffinity
# 
# From: rwhron@earthlink.net
# 
# It returns sizeof(compat_ulong_t) even if put_user() faulted.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1410
# [PATCH] remove proc_mknod()
# 
# From: Christoph Hellwig <hch@lst.de>
# 
# It's not used anymore since ALSA switched to traditional devices and device
# nodes in procfs are a bad idea in general..
# 
# Also update the docs.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1411
# [PATCH] reiserfs dirty memory accounting fix
# 
# The ClearPageDirty() in there is wrong - it doesn't adjust the VM's dirty
# memory accounting.  The system thinks it's full of dirty memory and stops.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1412
# [PATCH] fix reiserfs for 64bit arches
# 
# From: Oleg Drokin <green@namesys.com>
# 
# From the time of reiserfs_file_write inclusion all 64bit arches were not
# able to work with reiserfs for pretty stupid reason (incorrect "unsigned
# long" definition of blocknumber type).
# 
# This fixes the problem.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1413
# [PATCH] wall_to_monotonic initialization fixes for
# 
# From: Tim Schmielau <tim@physik3.uni-rostock.de>
# 
# This patch adds (or fixes) initialization of wall_to_monotonic for a few
# more architectures.
# 
# This should get rid of the strange uptime>14600 days reports, except on arm
# whose arch file layout is too unfamiliar to me.
# 
# The patch is blessed by George Anzinger, but untested due to lack of
# hardware.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1414
# [PATCH] i_size atomic access: infrastructure
# 
# From: Daniel McNeil <daniel@osdl.org>
# 
# This adds a sequence counter only version of the reader/writer consistent
# mechanism to seqlock.h This is used in the second part of this patch give
# atomic access to i_size.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1415
# [PATCH] i_size atomic access
# 
# From: Daniel McNeil <daniel@osdl.org>
# 
# This adds i_seqcount to the inode structure and then uses i_size_read() and
# i_size_write() to provide atomic access to i_size.  This is a port of
# Andrea Arcangeli's i_size atomic access patch from 2.4.  This only uses the
# generic reader/writer consistent mechanism.
# 
# Before:
# mnm:/usr/src/25> size vmlinux
#    text    data     bss     dec     hex filename
# 2229582 1027683  162436 3419701  342e35 vmlinux
# 
# After:
# mnm:/usr/src/25> size vmlinux
#    text    data     bss     dec     hex filename
# 2225642 1027655  162436 3415733  341eb5 vmlinux
# 
# 3.9k more text, a lot of it fastpath :(
# 
# It's a very minor bug, and the fix has a fairly non-minor cost.  The most
# compelling reason for fixing this is that writepage() checks i_size.  If it
# sees a transient value it may decide that page is outside i_size and will
# refuse to write it.  Lost user data.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1416
# [PATCH] kmap() -> kmap_atomic() in fs/exec.c
# 
# replace a kmap() with kmap_atomic()
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1417
# [PATCH] make CONFIG_KALLSYMS default to "on"
# 
# From: Diego Calleja Garcia <diegocg@teleline.es>
# 
# Move CONFIG_KALLSYMS out of the arch directory and into init/.
# 
# It defaults to "on" unless the user explicitly turns it off in the
# "embedded systems" menu.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1418
# [PATCH] misc fixes
# 
# - remove accidental debug code from ext3 commit.
# 
# - /proc/profile documentation fix (Randy Dunlap)
# 
# - use sb_breadahead() in ext2_preread_inode()
# 
# - unused var in mpage_writepages()
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1419
# [PATCH] Set umask correctly for nfsd kernel threads
# 
# From: Andreas Gruenbacher <agruen@suse.de>
# 
# Without acls, when creating files the umask is applied directly in the vfs.
# ACLs require that the umask is applied at the file system level, depending on
# whether or not the containing directory has a default acl.  The daemonize()
# function makes kernel threads share their fs_struct structure with the init
# process.  Among other things, fs_struct contains the umask, so all kernel
# threads share their umask with init.
# 
# The kernel nfsd needs to create files with a umask of 0.  Init's umask cannot
# simply be changed to 0 --- this would have side effects on init, and init
# would have side effects on nfsd.  So this patch recreates a fs_struct
# structure for nfsd kernel threads, and sets its umask to 0.
# 
# This fixes bug #721, <http://www.osdl.net/show_bug.cgi?id=721>.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1420
# [PATCH] Bug fix in AIO initialization
# 
# From: "Chen, Kenneth W" <kenneth.w.chen@intel.com>
# 
# We hit this bug when we have the following scenario:
# 
# One process initializes an AIO context and then forks out many child
# processes.  When those child processes exit, many BUG checks
# (effectively kernel oops) were triggered from put_ioctx(ctx) in function
# exit_aio().
# 
# The issue was that the AIO context was incorrectly copied upon forking
# and mislead all child processes to think they have an IO context and
# trying to free it where they really don't own.  The following patch fix
# the issue.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1421
# [PATCH] Fix race condition between aio_complete and
# 
# From: "Chen, Kenneth W" <kenneth.w.chen@intel.com>
# 
# We hit a memory ordering race condition on AIO ring buffer tail pointer
# between function aio_complete() and aio_read_evt().
# 
# What happens is that on an architecture that has a relaxed memory ordering
# model like IPF(ia64), explicit memory barrier is required in a SMP
# execution environment.  Considering the following case:
# 
# 1 CPU is executing a tight loop of aio_read_evt.  It is pulling event off
# the ring buffer.  During that loop, another CPU is executing aio_complete()
# where it is putting event into the ring buffer and then update the tail
# pointer.  However, due to relaxed memory ordering model, the tail pointer
# can be visible before the actual event is being updated.  So the other CPU
# sees the updated tail pointer but picks up a staled event data.
# 
# A memory barrier is required in this case between the event data and tail
# pointer update.  Same is true for the head pointer but the window of the
# race condition is nil.  For function correctness, it is fixed here as well.
# 
# By the way, this bug is fixed in the major distributor's kernel on 2.4.x
# kernel series for a while, but somehow hasn't been propagated to 2.5 kernel
# yet.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1422
# [PATCH] separate locking for vfsmounts
# 
# From: Maneesh Soni <maneesh@in.ibm.com>
# 
# While path walking we do follow_mount or follow_down which uses
# dcache_lock for serialisation.  vfsmount related operations also use
# dcache_lock for all updates. I think we can use a separate lock for
# vfsmount related work and can improve path walking.
# 
# The following two patches does the same. The first one replaces
# dcache_lock with new vfsmount_lock in namespace.c. The lock is
# local to namespace.c and is not required outside. The second patch
# uses RCU to have lock free lookup_mnt(). The patches are quite simple
# and straight forward.
# 
# The lockmeter reults show reduced contention, and lock acquisitions
# for dcache_lock while running dcachebench* on a 4-way SMP box
# 
#     SPINLOCKS         HOLD            WAIT
#     UTIL  CON    MEAN(  MAX )   MEAN(  MAX )(% CPU)     TOTAL NOWAIT SPIN RJECT  NAME
# 
#   baselkm-2569:
#     20.7% 20.9%  0.5us( 146us)  2.9us( 144us)(0.81%)  31590840 79.1% 20.9%    0%  dcache_lock
#   mntlkm-2569:
#     14.3% 13.6%  0.4us( 170us)  2.9us( 187us)(0.42%)  23071746 86.4% 13.6%    0%  dcache_lock
# 
# We get more than 8% improvement on 4-way SMP and 44% improvement on 16-way
# NUMAQ while runing dcachebench*.
# 
# 		Average (usecs/iteration)	Std. Deviation
# 		(lower is better)
# 4-way SMP
#   2.5.69	15739.3				470.90
#   2.5.69-mnt	14459.6				298.51
# 
# 16-way NUMAQ
#   2.5.69	120426.5			363.78
#   2.5.69-mnt	 63225.8			427.60
# 
# *dcachebench is a microbenchmark written by Bill Hartner and is available at
# http://www-124.ibm.com/developerworks/opensource/linuxperf/dcachebench/dcachebench.html
# 
#  vfsmount_lock.patch
#  -------------------
#  - Patch for replacing dcache_lock with new vfsmount_lock for all mount
#    related operation. This removes the need to take dcache_lock while
#    doing follow_mount or follow_down operations in path walking.
# 
# I re-ran dcachebench with 2.5.70 as base on 16-way NUMAQ box.
# 
#                 	Average (usecs/iteration)       Std. Deviation
#                 	(lower is better)
# 16-way NUMAQ
# 2.5.70 				120710.9		 	230.67
#  + vfsmount_lock.patch  	65209.6				242.97
#     + lookup_mnt-rcu.patch 	64042.3				416.61
# 
# So just the lock splitting (vfsmount_lock.patch) gives almost similar benifits
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1423
# [PATCH] fix for CPU scheduler load distribution
# 
# From: Ingo Molnar <mingo@elte.hu>
# 
# It makes hot-balancing happen in the 'busy tick' case as well, which should
# spread out processes more agressively.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1424
# [PATCH] NBD: cosmetic cleanups
# 
# From: Lou Langholtz <ldl@aros.net>
# 
# It's a helpful step in being better able to identify code inefficiencies
# and problems particularly w.r.t.  locking.  It also modifies some of the
# output messages for greater consistancy and better diagnostic support.
# 
# This second patch is a lead in that way to the third patch, which will
# simply introduce the dprintk() debugging facility that my jumbo patch
# originally had.
# 
# With the cosmetics patch and debugging enhancement (patch), it will make it
# easier to fix or at least improve the locking bugs/races in NBD (that will
# likely make up the fourth patch in my envisioned roadmap).
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1425
# [PATCH] nbd: enhanced diagnostics support
# 
# From: Lou Langholtz <ldl@aros.net>
# 
# This third patch (for enhancing diagnostics support) applies incrementally
# after my last LKML'd patch (for cosmetic changes).  These changes introduce
# configurable KERN_DEBUG level printk output for a variety of different
# things that the driver does and provides the framework for enhanced future
# debugging support as well.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1426
# [PATCH] nbd: remove unneeded blksize_bits field
# 
# From: Lou Langholtz <ldl@aros.net>
# 
# This fourth patch simply removes the blksize_bits field from the nbd_device
# struct and driver implementation.  How this field made it into this driver
# to begin with is a mystery (where was Al Viro when that patch was
# submitted??).  :-)
# 
# This patch modifies both drivers/block/nbd.c and include/linux/nbd.h files.
#  It's intended to be applied incrementally on top of my third patch (for
# enhanced diagnostics support).
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1427
# [PATCH] nbd: initialise the embedded kobject
# 
# From: Lou Langholtz <ldl@aros.net>
# 
# Fixes the NBD oopses which people have been reporting.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1428
# [PATCH] nbd: cleanup PARANOIA usage & code
# 
# From: Lou Langholtz <ldl@aros.net>
# 
# This fifth patch cleans up usage of the PARANOIA sanity checking macro and
# code.  This patch modifies both drivers/block/nbd.c and
# include/linux/nbd.h.  It's intended to be applied incrementally on top of
# my fourth patch (4.1 really if you count the memset addition as .1's worth)
# that simply removed unneeded blksize_bits field.  Again, I wanted to get
# this smaller change out of the way before my next patch will is much more
# major.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1429
# [PATCH] NBD documentation update
# 
# From: Paul Clements <Paul.Clements@SteelEye.com>
# 
# Modernise nbd.txt a bit.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1430
# [PATCH] nbd: remove unneeded nbd_open/nbd_release and refcnt
# 
# From: Paul Clements <Paul.Clements@SteelEye.com>
# 
# Remove the unneeded nbd_open and nbd_release functions.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1431
# [PATCH] nbd: make nbd and block layer agree about device and
# 
# From: Paul Clements <Paul.Clements@SteelEye.com>
# 
# Ensure that nbd and the block layer agree about device block sizes and total
# device sizes.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1432
# [PATCH] JBD: checkpointing optimisations
# 
# From: Alex Tomas <bzzz@tmi.comex.ru>
# 
# Some transaction checkpointing improvements for the JBD commit phase.  Decent
# speedups:
# 
# creation of 500K files in single dir (with htree, of course):
#  before: 4m16.094s, 4m12.035s, 4m11.911s
#  after:  1m41.364s, 1m43.461s, 1m45.189s
# 
# removal of 500K files in single dir:
#  before: 43m50.161s
#  after:  38m45.510s
# 
# 
# - Make __log_wait_for_space() recalculate the needed blocks because journal
#   free space changes during commit
# 
# - Make log_do_checkpoint() starts scanning from the oldest transaction
# 
# - Make log_do_checkpoint() stop scanning if a transaction gets dropped.
#   The caller will reevaluate the transaction state and decide whether more
#   space needs to be generated in the log.
# 
#   The effect of this is to smooth out the I/O patterns, avoid the huge
#   stop-and-go which currently happens when forced checkpointing writes out
#   and waits upon 3/4 of the journal's size worth of data.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1433
# [PATCH] JBD: transaction buffer accounting fix
# 
# From: Alex Tomas <bzzz@tmi.comex.ru>
# 
# start_this_handle() takes into account t_outstanding_credits when calculating
# log free space, but journal_next_log_block() accounts for blocks being logged
# also.  Hence, blocks are accounting twice.  This effectively reduces the
# amount of log space available to transactions and forces more commits.
# 
# Fix it by decrementing t_outstanding_credits each time we allocate a new
# journal block.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1434
# [PATCH] ext3: sync_fs() fix
# 
# From: Alex Tomas <bzzz@tmi.comex.ru>
# 
# fsync_super() calls ->sync_fs() just after ->write_super().  But
# write_super() will start a commit.  In this case, ext3_sync_fs() will not
# itself start a commit, and it hence forgets to wait on the commit which
# ext3_write_super() started.
# 
# Fix that up by making journal_start_commit() return the transaction ID of
# any currently-running transaction.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1435
# [PATCH] oom killer fixes
# 
# From: William Lee Irwin III <wli@holomorphy.com>
# 
# There are reports of kernel threads being killed by the oomkiller.  We
# think this is because the oom killer tries to kill a task after it has
# exitted and set its ->mm to zero.  The oom killer will then try to kill all
# other tasks which have a null ->mm.
# 
# Attempt to detect that case and fix it up.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1436
# [PATCH] yenta-socket initialisation fix
# 
# From: Daniel Ritz <daniel.ritz@gmx.ch>
# 
# init_socket() enables interrupts, and the interrupt handler does a wakeup.
# Let's initialise that waitqueue head before turning on the interrupts.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1437
# [PATCH] Fix yenta-socket oops
# 
# From: Russell King <rmk@arm.linux.org.uk>
# 
# Interrupts can sometimes occur before the socket thread is started.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1438
# [PATCH] devfs oops fix
# 
# From: Andrey Borzenkov <arvidjaar@mail.ru>
# 
# Doing concurrent lookups for the same name in devfs with devfsd and modules
# enabled may result in stack coruption.
# 
# When devfs_lookup needs to call devfsd it arranges for other lookups for the
# same name to wait. It is using local variable as wait queue head. After
# devfsd returns devfs_lookup wakes up all waiters and returns. Unfortunately
# there is no garantee all waiters will actually get chance to run and clean up
# before devfs_lookup returns. so some of them attempt to access already freed
# storage on stack.
# 
# It is trivial to trigger with SMP kernel (I have single-CPU system if it
# matters) doing
# 
# while true
# do
#   ls /dev/foo &
# done
# 
# Without spinlock debug system usually hung dead with reset button as the only
# possibility.
# 
# I was not able to reproduce it on 2.4 on single-CPU system - in 2.4
# devfs_d_revalidate_wait does not attempt to remove itself from wait queue
# so it appears to be safe.
# 
# The patch makes lookup struct be allocated from heap and adds reference
# counter to free it when no more needed.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1439
# [PATCH] devfs deadlock fix
# 
# From: Andrey Borzenkov <arvidjaar@mail.ru>
# 
# I finally hit a painfully trivial way to reproduce another long standing devfs
# problem - deadlock between devfs_lookup and devfs_d_revalidate_wait. When
# devfs_lookup releases directory i_sem devfs_d_revalidate_wait grabs it (it
# happens not for every path) and goes to wait to be waked up. Unfortunately,
# devfs_lookup attempts to acquire directory i_sem before ever waking it up ...
# 
# To reproduce (2.5.74 UP or SMP - does not matter, single CPU system)
# 
# ls /dev/foo & rm -f /dev/foo &
# 
# or possibly in a loop but then it easily fills up process table. In my case it
# hangs 100% reliably - on 2.5 OR 2.4.
# 
# The current fix is to move re-acquire of i_sem after all
# devfs_d_revalidate_wait waiters have been waked up.  Much better fix would be
# to ensure that ->d_revalidate either is always called under i_sem or always
# without.  But that means the very heart of VFS and I do not dare to touch it.
# 
# The fix has been tested on 2.4 (and is part of unofficial Mandrake Club
# kernel); I expected the same bug is in 2.5; I just was stupid not seeing the
# way to reproduce it before.
# --------------------------------------------
# 03/07/11	akpm@osdl.org	1.1440
# [PATCH] epoll-per-fd fix
# 
# From: Davide Libenzi <davidel@xmailserver.org>
# 
# Fix epoll to allow pushing of multiple file descriptors sharing the same
# kernel's file*
# --------------------------------------------
# 03/07/11	axboe@suse.de	1.1441
# [PATCH] disk stats accounting fix
# 
# We should only account file system requests, ones originating from
# __make_request(). Otherwise it skews the counters and they go negative
# really fast.
# --------------------------------------------
# 03/07/11	miles@lsi.nec.co.jp	1.1442
# [PATCH] Use <asm-generic/statsfs.h> on v850
# --------------------------------------------
# 03/07/11	miles@lsi.nec.co.jp	1.1443
# [PATCH] More irqreturn_t changes for v850
# --------------------------------------------
# 03/07/11	miles@lsi.nec.co.jp	1.1444
# [PATCH] show_stack changes for v850
# --------------------------------------------
#
diff -Nru a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
--- a/Documentation/DocBook/procfs-guide.tmpl	Fri Jul 11 01:25:29 2003
+++ b/Documentation/DocBook/procfs-guide.tmpl	Fri Jul 11 01:25:29 2003
@@ -253,41 +253,6 @@
       </para>
     </sect1>
 
-
-
-
-    <sect1>
-      <title>Creating a device</title>
-
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>struct proc_dir_entry* <function>proc_mknod</function></funcdef>
-	  <paramdef>const char* <parameter>name</parameter></paramdef>
-	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
-	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
-	  <paramdef>kdev_t <parameter>rdev</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-      
-      <para>
-        Creates a device file <parameter>name</parameter> with mode
-        <parameter>mode</parameter> in the procfs directory
-        <parameter>parent</parameter>. The device file will work on
-        the device <parameter>rdev</parameter>, which can be generated
-        by using the <literal>MKDEV</literal> macro from
-        <literal>linux/kdev_t.h</literal>. The
-        <parameter>mode</parameter> parameter
-        <emphasis>must</emphasis> contain <constant>S_IFBLK</constant>
-        or <constant>S_IFCHR</constant> to create a device
-        node. Compare with userland <literal>mknod
-        --mode=</literal><parameter>mode</parameter>
-        <parameter>name</parameter> <parameter>rdev</parameter>.
-      </para>
-    </sect1>
-
-
-
-
     <sect1>
       <title>Creating a directory</title>
       
diff -Nru a/Documentation/DocBook/procfs_example.c b/Documentation/DocBook/procfs_example.c
--- a/Documentation/DocBook/procfs_example.c	Fri Jul 11 01:25:30 2003
+++ b/Documentation/DocBook/procfs_example.c	Fri Jul 11 01:25:30 2003
@@ -63,7 +63,7 @@
 
 
 static struct proc_dir_entry *example_dir, *foo_file,
-	*bar_file, *jiffies_file, *tty_device, *symlink;
+	*bar_file, *jiffies_file, *symlink;
 
 
 struct fb_data_t foo_data, bar_data;
@@ -173,16 +173,6 @@
 	bar_file->write_proc = proc_write_foobar;
 	bar_file->owner = THIS_MODULE;
 		
-	/* create tty device */
-	tty_device = proc_mknod("tty", S_IFCHR | 0666,
-				example_dir, MKDEV(5, 0));
-	if(tty_device == NULL) {
-		rv = -ENOMEM;
-		goto no_tty;
-	}
-	
-	tty_device->owner = THIS_MODULE;
-
 	/* create symlink */
 	symlink = proc_symlink("jiffies_too", example_dir, 
 			       "jiffies");
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	Fri Jul 11 01:25:30 2003
+++ b/Documentation/kernel-parameters.txt	Fri Jul 11 01:25:30 2003
@@ -772,7 +772,7 @@
 			Ranges are in pairs (memory base and size).
 
 	profile=	[KNL] Enable kernel profiling via /proc/profile
-			Format: <log_level>
+			(param: profile step/bucket size as a power of 2)
 
 	prompt_ramdisk=	[RAM] List of RAM disks to prompt for floppy disk
 			before loading.
diff -Nru a/Documentation/nbd.txt b/Documentation/nbd.txt
--- a/Documentation/nbd.txt	Fri Jul 11 01:25:29 2003
+++ b/Documentation/nbd.txt	Fri Jul 11 01:25:29 2003
@@ -1,57 +1,47 @@
                       Network Block Device (TCP version)
                                        
-   Note: Network Block Device is now experimental, which approximately
-   means, that it works on my computer, and it worked on one of school
-   computers.
+   What is it: With this compiled in the kernel (or as a module), Linux
+   can use a remote server as one of its block devices. So every time
+   the client computer wants to read, e.g., /dev/nb0, it sends a
+   request over TCP to the server, which will reply with the data read.
+   This can be used for stations with low disk space (or even diskless -
+   if you boot from floppy) to borrow disk space from another computer.
+   Unlike NFS, it is possible to put any filesystem on it, etc. It should
+   even be possible to use NBD as a root filesystem (I've never tried),
+   but it requires a user-level program to be in the initrd to start.
+   It also allows you to run block-device in user land (making server
+   and client physically the same computer, communicating using loopback).
    
-   What is it: With this compiled in the kernel, Linux can use a remote
-   server as one of its block devices. So every time the client computer
-   wants to read /dev/nd0, it sends a request over TCP to the server, which
-   will reply with the data read. This can be used for stations with
-   low disk space (or even diskless - if you boot from floppy) to
-   borrow disk space from another computer. Unlike NFS, it is possible to
-   put any filesystem on it etc. It is impossible to use NBD as a root
-   filesystem, since it requires a user-level program to start. It also
-   allows you to run block-device in user land (making server and client
-   physically the same computer, communicating using loopback).
+   Current state: It currently works. Network block device is stable.
+   I originally thought that it was impossible to swap over TCP. It
+   turned out not to be true - swapping over TCP now works and seems
+   to be deadlock-free, but it requires heavy patches into Linux's
+   network layer.
    
-   Current state: It currently works. Network block device looks like
-   being pretty stable. I originally thought that it is impossible to swap
-   over TCP. It turned out not to be true - swapping over TCP now works
-   and seems to be deadlock-free, but it requires heavy patches into
-   Linux's network layer.
-   
-   Devices: Network block device uses major 43, minors 0..n (where n is
-   configurable in nbd.h). Create these files by mknod when needed. After
-   that, your ls -l /dev/ should look like:
-
-brw-rw-rw-   1 root     root      43,   0 Apr 11 00:28 nd0
-brw-rw-rw-   1 root     root      43,   1 Apr 11 00:28 nd1
-...
-
-   Protocol: Userland program passes file handle with connected TCP
-   socket to actual kernel driver. This way, the kernel does not have to
-   care about connecting etc. Protocol is rather simple: If the driver is
-   asked to read from block device, it sends packet of following form
-   "request" (all data are in network byte order):
-   
-  __u32 magic;        must be equal to 0x12560953
-  __u32 from;         position in bytes to read from / write at
-  __u32 len;          number of bytes to be read / written
-  __u64 handle;       handle of operation
-  __u32 type;         0 = read
-                      1 = write
-  ...                 in case of write operation, this is
-                      immediately followed len bytes of data
+   For more information, or to download the nbd-client and nbd-server
+   tools, go to http://nbd.sf.net/.
 
-   When operation is completed, server responds with packet of following
-   structure "reply":
-   
-  __u32 magic;        must be equal to
-  __u64 handle;       handle copied from request
-  __u32 error;        0 = operation completed successfully,
-                      else error code
-  ...                 in case of read operation with no error,
-                      this is immediately followed len bytes of data
+   Howto: To setup nbd, you can simply do the following:
+
+   First, serve a device or file from a remote server:
+
+   nbd-server <port-number> <device-or-file-to-serve-to-client>
+
+   e.g.,
+	root@server1 # nbd-server 1234 /dev/sdb1
+
+	(serves sdb1 partition on TCP port 1234)
+
+   Then, on the local (client) system:
+
+   nbd-client <server-name-or-IP> <server-port-number> /dev/nb[0-n]
+
+   e.g.,
+	root@client1 # nbd-client server1 1234 /dev/nb0
+
+	(creates the nb0 device on client1)
 
-   For more information, look at http://nbd.sf.net/.
+   The nbd kernel module need only be installed on the client
+   system, as the nbd-server is completely in userspace. In fact,
+   the nbd-server has been successfully ported to other operating
+   systems, including Windows.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Fri Jul 11 01:25:29 2003
+++ b/MAINTAINERS	Fri Jul 11 01:25:29 2003
@@ -1910,7 +1910,7 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
-USB BLUETOOTH DRIVER
+USB BLUETOOTH TTY CONVERTER DRIVER
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
 L:	linux-usb-users@lists.sourceforge.net
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Fri Jul 11 01:25:29 2003
+++ b/Makefile	Fri Jul 11 01:25:29 2003
@@ -35,7 +35,7 @@
 
 SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 				  -e s/arm.*/arm/ -e s/sa110/arm/ \
-				  -e s/s390x/s390/ )
+				  -e s/s390x/s390/ -e s/parisc64/parisc/ )
 
 # Remove hyphens since they have special meaning in RPM filenames
 KERNELPATH=kernel-$(subst -,,$(KERNELRELEASE))
diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
--- a/arch/alpha/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/alpha/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -451,8 +451,9 @@
 int
 do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
 	unsigned long delta_nsec;
-	long sec, nsec;
 
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
@@ -474,30 +475,18 @@
 	delta_nsec *= 1000;
 #endif
 
-	sec = tv->tv_sec;
-	nsec = tv->tv_nsec;
 	nsec -= delta_nsec;
-	if (nsec < 0) {
-		nsec += NSEC_PER_SEC;
-		sec -= 1;
-	}
 
-	xtime.tv_sec = sec;
-	xtime.tv_nsec = nsec;
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-
-        wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
-        wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
-        if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
-                wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
-                wall_to_monotonic.tv_sec++;
-        } else if (wall_to_monotonic.tv_nsec < 0) {
-                wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
-                wall_to_monotonic.tv_sec--;
-        }
 
 	write_sequnlock_irq(&xtime_lock);
 	return 0;
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	Fri Jul 11 01:25:29 2003
+++ b/arch/arm/Kconfig	Fri Jul 11 01:25:29 2003
@@ -1061,14 +1061,6 @@
 	  you are concerned with the code size or don't want to see these
 	  messages.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
 # These options are only for real kernel hackers who want to get their hands dirty. 
 config DEBUG_LL
 	bool "Kernel low-level debugging functions"
diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig
--- a/arch/arm26/Kconfig	Fri Jul 11 01:25:29 2003
+++ b/arch/arm26/Kconfig	Fri Jul 11 01:25:29 2003
@@ -391,14 +391,6 @@
 	  you are concerned with the code size or don't want to see these
 	  messages.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
 # These options are only for real kernel hackers who want to get their hands dirty. 
 config DEBUG_LL
 	bool "Kernel low-level debugging functions"
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	Fri Jul 11 01:25:28 2003
+++ b/arch/i386/Kconfig	Fri Jul 11 01:25:28 2003
@@ -1354,13 +1354,6 @@
 	  This options enables addition error checking for high memory systems.
 	  Disable for production systems.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
 config DEBUG_SPINLOCK_SLEEP
 	bool "Sleep-inside-spinlock checking"
 	help
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/i386/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -115,6 +115,9 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -125,28 +128,15 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
-	tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
-
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
+	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
 
-	wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
-	wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
 
-	if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
-		wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec++;
-	}
-	if (wall_to_monotonic.tv_nsec < 0) {
-		wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec--;
-	}
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Fri Jul 11 01:25:30 2003
+++ b/arch/ia64/Kconfig	Fri Jul 11 01:25:30 2003
@@ -667,14 +667,6 @@
 	  Say Y here if you are developing drivers or trying to debug and
 	  identify kernel problems.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
 config IA64_PRINT_HAZARDS
 	bool "Print possible IA-64 dependency violations to console"
 	depends on DEBUG_KERNEL
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	Fri Jul 11 01:25:28 2003
+++ b/arch/ia64/kernel/time.c	Fri Jul 11 01:25:28 2003
@@ -104,21 +104,6 @@
 	.reset =	itc_reset
 };
 
-static inline void
-set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
-{
-	while (nsec > NSEC_PER_SEC) {
-		nsec -= NSEC_PER_SEC;
-		++sec;
-	}
-	while (nsec < 0) {
-		nsec += NSEC_PER_SEC;
-		--sec;
-	}
-	ts->tv_sec = sec;
-	ts->tv_nsec = nsec;
-}
-
 int
 do_settimeofday (struct timespec *tv)
 {
diff -Nru a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
--- a/arch/m68k/kernel/time.c	Fri Jul 11 01:25:28 2003
+++ b/arch/m68k/kernel/time.c	Fri Jul 11 01:25:28 2003
@@ -103,6 +103,7 @@
 				      time.tm_hour, time.tm_min, time.tm_sec);
 		xtime.tv_nsec = 0;
 	}
+	wall_to_monotonic.tv_sec = -xtime.tv_sec;
 
 	mach_sched_init(timer_interrupt);
 }
@@ -140,6 +141,8 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
 	extern unsigned long wall_jiffies;
 
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
@@ -152,16 +155,15 @@
 	 * Discover what correction gettimeofday
 	 * would have done, and then undo it!
 	 */
-	tv->tv_nsec -= 1000 * (mach_gettimeoffset() +
+	nsec -= 1000 * (mach_gettimeoffset() +
 			(jiffies - wall_jiffies) * (1000000 / HZ));
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
--- a/arch/m68knommu/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/m68knommu/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -131,6 +131,7 @@
 		year += 100;
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 	xtime.tv_nsec = 0;
+	wall_to_monotonic.tv_sec = -xtime.tv_sec;
 
 	mach_sched_init(timer_interrupt);
 }
@@ -165,6 +166,9 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -177,15 +181,14 @@
 	 * would have done, and then undo it!
 	 */
 	if (mach_gettimeoffset)
-		tv->tv_nsec -= (mach_gettimeoffset() * 1000);
+		nsec -= (mach_gettimeoffset() * 1000);
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
--- a/arch/mips/kernel/time.c	Fri Jul 11 01:25:28 2003
+++ b/arch/mips/kernel/time.c	Fri Jul 11 01:25:28 2003
@@ -98,6 +98,9 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -108,16 +111,15 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-	tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+	nsec -= do_gettimeoffset() * NSEC_PER_USEC;
+	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
@@ -499,6 +501,9 @@
 
 	xtime.tv_sec = rtc_get_time();
 	xtime.tv_nsec = 0;
+
+        set_normalized_timespec(&wall_to_monotonic,
+                                -xtime.tv_sec, -xtime.tv_nsec);
 
 	/* choose appropriate gettimeoffset routine */
 	if (!cpu_has_counter) {
diff -Nru a/arch/mips64/kernel/time.c b/arch/mips64/kernel/time.c
--- a/arch/mips64/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/mips64/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -98,6 +98,9 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -108,16 +111,15 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC;
-	tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+	nsec -= do_gettimeoffset() * NSEC_PER_USEC;
+	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - tsec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
@@ -499,6 +501,8 @@
 
 	xtime.tv_sec = rtc_get_time();
 	xtime.tv_nsec = 0;
+	set_normalized_timespec(&wall_to_monotonic,
+	                        -xtime.tv_sec, -xtime.tv_nsec);
 
 	/* choose appropriate gettimeoffset routine */
 	if (!cpu_has_counter) {
diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig
--- a/arch/parisc/Kconfig	Fri Jul 11 01:25:29 2003
+++ b/arch/parisc/Kconfig	Fri Jul 11 01:25:29 2003
@@ -1,6 +1,6 @@
 #
 # For a description of the syntax of this configuration file,
-# see the Configure script.
+# see Documentation/kbuild/kconfig-language.txt.
 #
 
 mainmenu "Linux/PA-RISC Kernel Configuration"
@@ -287,13 +287,13 @@
 	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
 	  unless you really know what this hack does.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
+config FRAME_POINTER
+	bool "Compile the kernel with frame pointers"
 	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
+	  If you say Y here the resulting kernel image will be slightly larger
+	  and slower, but it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame pointers.
 
 endmenu
 
diff -Nru a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
--- a/arch/parisc/hpux/sys_hpux.c	Fri Jul 11 01:25:29 2003
+++ b/arch/parisc/hpux/sys_hpux.c	Fri Jul 11 01:25:29 2003
@@ -121,7 +121,7 @@
 {
 	struct super_block *s;
 	struct hpux_ustat tmp;  /* Changed to hpux_ustat */
-	struct statfs sbuf;
+	struct kstatfs sbuf;
 	int err = -EINVAL;
 
 	s = user_get_super(dev);
diff -Nru a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
--- a/arch/parisc/kernel/drivers.c	Fri Jul 11 01:25:29 2003
+++ b/arch/parisc/kernel/drivers.c	Fri Jul 11 01:25:29 2003
@@ -112,7 +112,9 @@
 static int parisc_driver_remove(struct device *dev)
 {
 	struct parisc_device *pa_dev = to_parisc_device(dev);
-
+	struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
+	if (pa_drv->remove)
+		pa_drv->remove(pa_dev);
 	release_mem_region(pa_dev->hpa, 0x1000);
 
 	return 0;
diff -Nru a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
--- a/arch/parisc/kernel/ioctl32.c	Fri Jul 11 01:25:28 2003
+++ b/arch/parisc/kernel/ioctl32.c	Fri Jul 11 01:25:28 2003
@@ -36,8 +36,9 @@
 #include <linux/mtio.h>
 #include <linux/cdrom.h>
 #include <linux/loop.h>
-#include <linux/auto_fs.h>
+#include <linux/auto_fs4.h>
 #include <linux/devfs_fs.h>
+#include <linux/ncp_fs.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>
 #include <linux/fb.h>
diff -Nru a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
--- a/arch/parisc/kernel/module.c	Fri Jul 11 01:25:30 2003
+++ b/arch/parisc/kernel/module.c	Fri Jul 11 01:25:30 2003
@@ -671,6 +671,11 @@
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
 {
+	int i;
+	unsigned long nsyms;
+	const char *strtab = NULL;
+	Elf_Sym *newptr, *oldptr;
+	Elf_Shdr *symhdr = NULL;
 #ifdef DEBUG
 	struct fdesc_entry *entry;
 	u32 *addr;
@@ -690,7 +695,49 @@
 	       me->arch.got_count, me->arch.got_max,
 	       me->arch.fdesc_count, me->arch.fdesc_max);
 #endif
-		
+
+	/* haven't filled in me->symtab yet, so have to find it
+	 * ourselves */
+	for (i = 1; i < hdr->e_shnum; i++) {
+		if(sechdrs[i].sh_type == SHT_SYMTAB
+		   && (sechdrs[i].sh_type & SHF_ALLOC)) {
+			int strindex = sechdrs[i].sh_link;
+			/* FIXME: AWFUL HACK
+			 * The cast is to drop the const from
+			 * the sechdrs pointer */
+			symhdr = (Elf_Shdr *)&sechdrs[i];
+			strtab = (char *)sechdrs[strindex].sh_addr;
+			break;
+		}
+	}
+
+	printk("module %s: strtab %p, symhdr %p\n",
+	       me->name, strtab, symhdr);
+	
+	/* no symbol table */
+	if(symhdr == NULL)
+		return 0;
+
+	oldptr = (void *)symhdr->sh_addr;
+	newptr = oldptr + 1;	/* we start counting at 1 */
+	nsyms = symhdr->sh_size / sizeof(Elf_Sym);
+	DEBUGP("OLD num_symtab %lu\n", nsyms);
+
+	for (i = 1; i < nsyms; i++) {
+		oldptr++;	/* note, count starts at 1 so preincrement */
+		if(strncmp(strtab + oldptr->st_name,
+			      ".L", 2) == 0)
+			continue;
+
+		if(newptr != oldptr)
+			*newptr++ = *oldptr;
+		else
+			newptr++;
+
+	}
+	nsyms = newptr - (Elf_Sym *)symhdr->sh_addr;
+	DEBUGP("NEW num_symtab %lu\n", nsyms);
+	symhdr->sh_size = nsyms * sizeof(Elf_Sym);
 	return 0;
 }
 
diff -Nru a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
--- a/arch/parisc/kernel/pci.c	Fri Jul 11 01:25:28 2003
+++ b/arch/parisc/kernel/pci.c	Fri Jul 11 01:25:28 2003
@@ -10,11 +10,12 @@
  * Copyright (C) 1999-2001 Grant Grundler
  */
 #include <linux/config.h>
-#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/init.h>		/* for __init and __devinit */
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/types.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c	Fri Jul 11 01:25:28 2003
+++ b/arch/parisc/kernel/sys_parisc32.c	Fri Jul 11 01:25:28 2003
@@ -418,11 +418,11 @@
 }
 
 asmlinkage int
-sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+sys32_settimeofday(struct compat_timespec *tv, struct timezone *tz)
 {
     struct timeval ktv;
     struct timezone ktz;
-    extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+    extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
 
     if (tv) {
 	    if (get_compat_timeval(tv, &ktv))
diff -Nru a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
--- a/arch/parisc/kernel/time.c	Fri Jul 11 01:25:28 2003
+++ b/arch/parisc/kernel/time.c	Fri Jul 11 01:25:28 2003
@@ -188,8 +188,11 @@
 }
 
 int
-do_settimeofday (struct timeval *tv)
+do_settimeofday (struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -202,16 +205,15 @@
 		 * Discover what correction gettimeofday would have
 		 * done, and then undo it!
 		 */
-		tv->tv_nsec -= gettimeoffset() * 1000;
-		tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
+		nsec -= gettimeoffset() * 1000;
+		nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
+
+		wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+		wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
 
-		while (tv->tv_nsec < 0) {
-			tv->tv_nsec += NSEC_PER_SEC;
-			tv->tv_sec--;
-		}
+		set_normalized_timespec(&xtime, sec, nsec);
+		set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-		xtime.tv_sec = tv->tv_sec;
-		xtime.tv_nsec = tv->tv_nsec;
 		time_adjust = 0;		/* stop active adjtime() */
 		time_status |= STA_UNSYNC;
 		time_maxerror = NTP_PHASE_LIMIT;
@@ -243,6 +245,8 @@
 		write_seqlock_irq(&xtime_lock);
 		xtime.tv_sec = tod_data.tod_sec;
 		xtime.tv_nsec = tod_data.tod_usec * 1000;
+		set_normalized_timespec(&wall_to_monotonic,
+		                        -xtime.tv_sec, -xtime.tv_nsec);
 		write_sequnlock_irq(&xtime_lock);
 	} else {
 		printk(KERN_ERR "Error reading tod clock\n");
diff -Nru a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
--- a/arch/parisc/kernel/traps.c	Fri Jul 11 01:25:30 2003
+++ b/arch/parisc/kernel/traps.c	Fri Jul 11 01:25:30 2003
@@ -126,7 +126,7 @@
 void dump_stack(void)
 {
 	unsigned long stack;
-	show_trace(&stack);
+	show_trace(current, &stack);
 }
 
 
@@ -136,7 +136,7 @@
 static int kstack_depth_to_print = 128 * 4;
 #endif
 
-void show_stack(unsigned long *sp)
+void show_stack(struct task_struct *task, unsigned long *sp)
 {
 	unsigned long *stack;
 	int i;
@@ -145,8 +145,10 @@
 	 * debugging aid: "show_stack(NULL);" prints the
 	 * back trace for this cpu.
 	 */
-	if (sp==NULL)
+	if (task==NULL)
 		sp = (unsigned long*)&sp;
+	else if(sp == NULL)
+		sp = (unsigned long*)task->thread.regs.ksp;
 
 	stack = sp;
 	printk("\n" KERN_CRIT "Stack Dump:\n");
@@ -160,11 +162,11 @@
 		printk(RFMT " ", *stack--);
 	}
 	printk("\n" KERN_CRIT "\n");
-	show_trace(sp);
+	show_trace(task, sp);
 }
 
 
-void show_trace(unsigned long *stack)
+void show_trace(struct task_struct *task, unsigned long *stack)
 {
 	unsigned long *startstack;
 	unsigned long addr;
@@ -201,7 +203,7 @@
 
 void show_trace_task(struct task_struct *tsk)
 {
-	show_trace((unsigned long *)tsk->thread.regs.ksp);
+	show_trace(tsk, (unsigned long *)tsk->thread.regs.ksp);
 }
 
 void die_if_kernel(char *str, struct pt_regs *regs, long err)
@@ -426,7 +428,7 @@
 	if (code == 1)
 	    transfer_pim_to_trap_frame(regs);
 
-	show_stack((unsigned long *)regs->gr[30]);
+	show_stack(NULL, (unsigned long *)regs->gr[30]);
 
 	printk("\n");
 	printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
diff -Nru a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
--- a/arch/parisc/kernel/unaligned.c	Fri Jul 11 01:25:28 2003
+++ b/arch/parisc/kernel/unaligned.c	Fri Jul 11 01:25:28 2003
@@ -92,6 +92,15 @@
 #define OPCODE_STWA	OPCODE1(0x03,1,0xe)
 #define OPCODE_STDA	OPCODE1(0x03,1,0xf)
 
+#define OPCODE_FLDWX	OPCODE1(0x09,0,0x0)
+#define OPCODE_FSTWX	OPCODE1(0x09,0,0x4)
+#define OPCODE_FLDWS	OPCODE1(0x09,1,0x0)
+#define OPCODE_FSTWS	OPCODE1(0x09,1,0x4)
+#define OPCODE_FLDDX	OPCODE1(0x0b,0,0x0)
+#define OPCODE_FSTDX	OPCODE1(0x0b,0,0x4)
+#define OPCODE_FLDDS	OPCODE1(0x0b,1,0x0)
+#define OPCODE_FSTDS	OPCODE1(0x0b,1,0x4)
+
 #define OPCODE_LDD_L	OPCODE2(0x14,0)
 #define OPCODE_FLDD_L	OPCODE2(0x14,1)
 #define OPCODE_STD_L	OPCODE2(0x1c,0)
@@ -113,6 +122,7 @@
 #define R1(i) (((i)>>21)&0x1f)
 #define R2(i) (((i)>>16)&0x1f)
 #define R3(i) ((i)&0x1f)
+#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
 #define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
 #define IM5_2(i) IM((i)>>16,5)
 #define IM5_3(i) IM((i),5)
@@ -146,7 +156,7 @@
 
 	return 0;
 }
-static int emulate_ldw(struct pt_regs *regs, int toreg)
+static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
 	unsigned long val = 0;
@@ -169,20 +179,26 @@
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
-	if (toreg)
+	if (flop)
+		((__u32*)(regs->fr))[toreg] = val;
+	else if (toreg)
 		regs->gr[toreg] = val;
 
 	return 0;
 }
-#ifdef __LP64__
-static int emulate_ldd(struct pt_regs *regs, int toreg)
+static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
-	unsigned long val = 0;
+	__u64 val = 0;
 
 	DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n", 
 		regs->isr, regs->ior, toreg);
+#ifdef CONFIG_PA20
 
+#ifndef __LP64__
+	if (!flop)
+		return -1;
+#endif
 	__asm__ __volatile__  (
 "	depd,z	%2,60,3,%%r19\n"		/* r19=(ofs&7)*8 */
 "	mtsp	%3, %%sr1\n"
@@ -195,15 +211,36 @@
 	: "=r" (val)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
 	: "r19", "r20" );
+#else
+    {
+	unsigned long valh=0,vall=0;
+	__asm__ __volatile__  (
+"	zdep	%4,29,2,%%r19\n"		/* r19=(ofs&3)*8 */
+"	mtsp	%5, %%sr1\n"
+"	dep	%%r0,31,2,%4\n"
+"	ldw	0(%%sr1,%5),%0\n"
+"	ldw	4(%%sr1,%5),%1\n"
+"	ldw	8(%%sr1,%5),%%r20\n"
+"	subi	32,%%r19,%%r19\n"
+"	mtsar	%%r19\n"
+"	vshd	%0,%1,%0\n"
+"	vshd	%1,%%r20,%1\n"
+	: "=r" (valh), "=r" (vall)
+	: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
+	: "r19", "r20" );
+	val=((__u64)valh<<32)|(__u64)vall;
+    }
+#endif
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
-	if (toreg)
+	if (flop)
+		regs->fr[toreg] = val;
+	else if (toreg)
 		regs->gr[toreg] = val;
 
 	return 0;
 }
-#endif
 
 static int emulate_sth(struct pt_regs *regs, int frreg)
 {
@@ -212,7 +249,7 @@
 		val = 0;
 
 	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+		val, regs->isr, regs->ior);
 
 	__asm__ __volatile__ (
 "	mtsp %2, %%sr1\n"
@@ -225,14 +262,19 @@
 
 	return 0;
 }
-static int emulate_stw(struct pt_regs *regs, int frreg)
+static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 {
-	unsigned long val = regs->gr[frreg];
-	if (!frreg)
+	unsigned long val;
+
+	if (flop)
+		val = ((__u32*)(regs->fr))[frreg];
+	else if (frreg)
+		val = regs->gr[frreg];
+	else
 		val = 0;
 
 	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+		val, regs->isr, regs->ior);
 
 
 	__asm__ __volatile__ (
@@ -257,17 +299,25 @@
 
 	return 0;
 }
-#ifdef __LP64__
-static int emulate_std(struct pt_regs *regs, int frreg)
+static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 {
-	unsigned long val = regs->gr[frreg];
-	if (!frreg)
-		val = 0;
+	__u64 val;
 
-	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+	if (flop)
+		val = regs->fr[frreg];
+	else if (frreg)
+		val = regs->gr[frreg];
+	else
+		val = 0;
 
+	DPRINTF("store r%d (0x" %016llx ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
+		val,  regs->isr, regs->ior);
 
+#ifdef CONFIG_PA20
+#ifndef __LP64__
+	if (!flop)
+		return -1;
+#endif
 	__asm__ __volatile__ (
 "	mtsp %2, %%sr1\n"
 "	depd,z	%1, 60, 3, %%r19\n"
@@ -287,19 +337,45 @@
 	:
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
 	: "r19", "r20", "r21", "r22", "r1" );
+#else
+    {
+	unsigned long valh=(val>>32),vall=(val&0xffffffffl);
+	__asm__ __volatile__ (
+"	mtsp	%3, %%sr1\n"
+"	zdep	%1, 29, 2, %%r19\n"
+"	dep	%%r0, 31, 2, %1\n"
+"	mtsar	%%r19\n"
+"	zvdepi	-2, 32, %%r19\n"
+"	ldw	0(%%sr1,%2),%%r20\n"
+"	ldw	8(%%sr1,%2),%%r21\n"
+"	vshd	%0, %1, %%r1\n"
+"	vshd	%%r0, %0, %0\n"
+"	vshd	%1, %%r0, %1\n"
+"	and	%%r20, %%r19, %%r20\n"
+"	andcm	%%r21, %%r19, %%r21\n"
+"	or	%0, %%r20, %0\n"
+"	or	%1, %%r21, %1\n"
+"	stw	%0,0(%%sr1,%2)\n"
+"	stw	%%r1,4(%%sr1,%2)\n"
+"	stw	%1,8(%%sr1,%2)\n"
+	:
+	: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
+	: "r19", "r20", "r21", "r1" );
+    }
+#endif
 
 	return 0;
 }
-#endif
 
 void handle_unaligned(struct pt_regs *regs)
 {
 	unsigned long unaligned_count = 0;
 	unsigned long last_time = 0;
-	unsigned long newbase = regs->gr[R1(regs->iir)];
+	unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
 	int modify = 0;
 	int ret = -1;
 	struct siginfo si;
+	register int flop=0;	/* true if this is a flop */
 
 	/* if the unaligned access is inside the kernel:
 	 *   if the access is caused by a syscall, then we fault the calling
@@ -383,9 +459,9 @@
 				case OPCODE_LDDA_I:
 					shift= 3; break;
 				}
-				newbase += regs->gr[R2(regs->iir)]<<shift;
+				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift;
 			} else				/* simple indexed */
-				newbase += regs->gr[R2(regs->iir)];
+				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
 		}
 		break;
 	case 0x13:
@@ -438,7 +514,7 @@
 	case OPCODE_LDWA_I:
 	case OPCODE_LDW_S:
 	case OPCODE_LDWA_S:
-		ret = emulate_ldw(regs, R3(regs->iir));
+		ret = emulate_ldw(regs, R3(regs->iir),0);
 		break;
 
 	case OPCODE_STH:
@@ -447,23 +523,47 @@
 
 	case OPCODE_STW:
 	case OPCODE_STWA:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 
-#ifdef __LP64__
+#ifdef CONFIG_PA20
 	case OPCODE_LDD_I:
 	case OPCODE_LDDA_I:
 	case OPCODE_LDD_S:
 	case OPCODE_LDDA_S:
-		ret = emulate_ldd(regs, R3(regs->iir));
+		ret = emulate_ldd(regs, R3(regs->iir),0);
 		break;
 
 	case OPCODE_STD:
 	case OPCODE_STDA:
-		ret = emulate_std(regs, R2(regs->iir));
+		ret = emulate_std(regs, R2(regs->iir),0);
 		break;
 #endif
 
+	case OPCODE_FLDWX:
+	case OPCODE_FLDWS:
+		flop=1;
+		ret = emulate_ldw(regs,FR3(regs->iir),1);
+		break;
+
+	case OPCODE_FLDDX:
+	case OPCODE_FLDDS:
+		flop=1;
+		ret = emulate_ldd(regs,R3(regs->iir),1);
+		break;
+
+	case OPCODE_FSTWX:
+	case OPCODE_FSTWS:
+		flop=1;
+		ret = emulate_stw(regs,FR3(regs->iir),1);
+		break;
+
+	case OPCODE_FSTDX:
+	case OPCODE_FSTDS:
+		flop=1;
+		ret = emulate_std(regs,R3(regs->iir),1);
+		break;
+
 	case OPCODE_LDCD_I:
 	case OPCODE_LDCW_I:
 	case OPCODE_LDCD_S:
@@ -471,30 +571,44 @@
 		ret = -1;	/* "undefined", but lets kill them. */
 		break;
 	}
-#ifdef __LP64__
+#ifdef CONFIG_PA20
 	switch (regs->iir & OPCODE2_MASK)
 	{
-	case OPCODE_LDD_L:
 	case OPCODE_FLDD_L:
-		ret = emulate_ldd(regs, R2(regs->iir));
+		flop=1;
+		ret = emulate_ldd(regs,R2(regs->iir),1);
+		break;
+	case OPCODE_FSTD_L:
+		flop=1;
+		ret = emulate_std(regs, R2(regs->iir),1);
 		break;
 
+#ifdef CONFIG_PA20
+	case OPCODE_LDD_L:
+		ret = emulate_ldd(regs, R2(regs->iir),0);
+		break;
 	case OPCODE_STD_L:
-	case OPCODE_FSTD_L:
-		ret = emulate_std(regs, R2(regs->iir));
+		ret = emulate_std(regs, R2(regs->iir),0);
 		break;
+#endif
 	}
 #endif
 	switch (regs->iir & OPCODE3_MASK)
 	{
-	case OPCODE_LDW_M:
 	case OPCODE_FLDW_L:
-		ret = emulate_ldw(regs, R2(regs->iir));
+		flop=1;
+		ret = emulate_ldw(regs, R2(regs->iir),0);
+		break;
+	case OPCODE_LDW_M:
+		ret = emulate_ldw(regs, R2(regs->iir),1);
 		break;
 
 	case OPCODE_FSTW_L:
+		flop=1;
+		ret = emulate_stw(regs, R2(regs->iir),1);
+		break;
 	case OPCODE_STW_M:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 	}
 	switch (regs->iir & OPCODE4_MASK)
@@ -504,19 +618,18 @@
 		break;
 	case OPCODE_LDW_L:
 	case OPCODE_LDWM:
-		ret = emulate_ldw(regs, R2(regs->iir));
+		ret = emulate_ldw(regs, R2(regs->iir),0);
 		break;
 	case OPCODE_STH_L:
 		ret = emulate_sth(regs, R2(regs->iir));
 		break;
 	case OPCODE_STW_L:
 	case OPCODE_STWM:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 	}
-	/* XXX LJ - need to handle float load/store */
 
-	if (modify)
+	if (modify && R1(regs->iir))
 		regs->gr[R1(regs->iir)] = newbase;
 
 
@@ -540,9 +653,8 @@
 		return;
 	}
 
-	/* else we handled it, advance the PC.... */
-	regs->iaoq[0] = regs->iaoq[1];
-	regs->iaoq[1] = regs->iaoq[0] + 4;
+	/* else we handled it, let life go on. */
+	regs->gr[0]|=PSW_N;
 }
 
 /*
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	Fri Jul 11 01:25:30 2003
+++ b/arch/ppc/Kconfig	Fri Jul 11 01:25:30 2003
@@ -1449,13 +1449,6 @@
 	  This options enables additional error checking for high memory
 	  systems.  Disable for production systems.
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
 config DEBUG_SPINLOCK_SLEEP
 	bool "Sleep-inside-spinlock checking"
 	depends on DEBUG_KERNEL
diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
--- a/arch/ppc/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/ppc/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -241,6 +241,8 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, new_sec = tv->tv_sec;
+	long wtm_nsec, new_nsec = tv->tv_nsec;
 	unsigned long flags;
 	int tb_delta, new_nsec, new_sec;
 
@@ -268,14 +270,14 @@
 	 */
 	tb_delta = tb_ticks_since(last_jiffy_stamp(smp_processor_id()));
 	tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
-	new_sec = tv->tv_sec;
-	new_nsec = tv->tv_nsec - 1000 * mulhwu(tb_to_us, tb_delta);
-	while (new_nsec < 0) {
-		new_sec--; 
-		new_nsec += NSEC_PER_SEC;
-	}
-	xtime.tv_nsec = new_nsec;
-	xtime.tv_sec = new_sec;
+
+	new_nsec -= 1000 * mulhwu(tb_to_us, tb_delta);
+
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
+
+	set_normalized_timespec(&xtime, new_sec, new_nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
 	/* In case of a large backwards jump in time with NTP, we want the 
 	 * clock to be updated as soon as the PLL is again in lock.
@@ -347,6 +349,8 @@
 		sys_tz.tz_dsttime = 0;
 		xtime.tv_sec -= time_offset;
         }
+        set_normalized_timespec(&wall_to_monotonic,
+                                -xtime.tv_sec, -xtime.tv_nsec);
 }
 
 #define FEBRUARY		2
diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c	Fri Jul 11 01:25:30 2003
+++ b/arch/ppc64/kernel/time.c	Fri Jul 11 01:25:30 2003
@@ -339,9 +339,11 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, new_sec = tv->tv_sec;
+	long wtm_nsec, new_nsec = tv->tv_nsec;
 	unsigned long flags;
 	unsigned long delta_xsec;
-	long int tb_delta, new_nsec, new_sec;
+	long int tb_delta;
 	unsigned long new_xsec;
 
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
@@ -364,14 +366,13 @@
 	tb_delta = tb_ticks_since(tb_last_stamp);
 	tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
 
-	new_sec = tv->tv_sec;
-	new_nsec = tv->tv_nsec - (tb_delta / tb_ticks_per_usec / 1000);
-	while (new_nsec < 0) {
-		new_sec--; 
-		new_nsec += NSEC_PER_SEC;
-	}
-	xtime.tv_nsec = new_nsec;
-	xtime.tv_sec = new_sec;
+	new_nsec -= tb_delta / tb_ticks_per_usec / 1000;
+
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec);
+
+ 	set_normalized_timespec(&xtime, new_sec, new_nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
 	/* In case of a large backwards jump in time with NTP, we want the 
 	 * clock to be updated as soon as the PLL is again in lock.
@@ -484,6 +485,8 @@
 
 	xtime.tv_nsec = 0;
 	last_rtc_update = xtime.tv_sec;
+	set_normalized_timespec(&wall_to_monotonic,
+	                        -xtime.tv_sec, -xtime.tv_nsec);
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 
 	/* Not exact, but the timer interrupt takes care of this */
diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
--- a/arch/s390/kernel/time.c	Fri Jul 11 01:25:28 2003
+++ b/arch/s390/kernel/time.c	Fri Jul 11 01:25:28 2003
@@ -104,6 +104,9 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -114,15 +117,14 @@
 	 * Discover what correction gettimeofday
 	 * would have done, and then undo it!
 	 */
-	tv->tv_nsec -= do_gettimeoffset() * 1000;
+	nsec -= do_gettimeoffset() * 1000;
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
@@ -263,6 +265,8 @@
 	set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
 		(0x3c26700LL*1000000*4096);
         tod_to_timeval(set_time_cc, &xtime);
+        set_normalized_timespec(&wall_to_monotonic,
+                                -xtime.tv_sec, -xtime.tv_nsec);
 
         /* request the 0x1004 external interrupt */
         if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
diff -Nru a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
--- a/arch/sh/kernel/time.c	Fri Jul 11 01:25:28 2003
+++ b/arch/sh/kernel/time.c	Fri Jul 11 01:25:28 2003
@@ -179,6 +179,9 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -189,16 +192,15 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_nsec -= 1000 * (do_gettimeoffset() +
-				(jiffies - wall_jiffies) * (1000000 / HZ));
+	nsec -= 1000 * (do_gettimeoffset() +
+			(jiffies - wall_jiffies) * (1000000 / HZ));
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
@@ -417,6 +419,9 @@
 	current_cpu_data.module_clock = timer_freq * 4;
 
 	rtc_get_time(&xtime);
+
+        set_normalized_timespec(&wall_to_monotonic,
+                                -xtime.tv_sec, -xtime.tv_nsec);
 
 	if (board_timer_setup) {
 		board_timer_setup(&irq0);
diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
--- a/arch/sparc/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/sparc/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -408,9 +408,9 @@
 	mon = MSTK_REG_MONTH(mregs);
 	year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
-	wall_to_monotonic.tv_sec = -xtime.tv_sec;
 	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-	wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+        set_normalized_timespec(&wall_to_monotonic,
+                                -xtime.tv_sec, -xtime.tv_nsec);
 	mregs->creg &= ~MSTK_CREG_READ;
 	spin_unlock_irq(&mostek_lock);
 #ifdef CONFIG_SUN4
@@ -441,9 +441,9 @@
 		intersil_start(iregs);
 
 		xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
-		wall_to_monotonic.tv_sec = -xtime.tv_sec;
 		xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-		wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+	        set_normalized_timespec(&wall_to_monotonic,
+ 	                               -xtime.tv_sec, -xtime.tv_nsec);
 		printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec);
 	}
 #endif
@@ -512,6 +512,9 @@
 
 static int sbus_do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -521,28 +524,15 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_nsec -= 1000 * (do_gettimeoffset() +
+	nsec -= 1000 * (do_gettimeoffset() +
 			(jiffies - wall_jiffies) * (USEC_PER_SEC / HZ));
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
-
-	wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
-	wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
 
-	if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
-		wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec++;
-	}
-	if (wall_to_monotonic.tv_nsec < 0) {
-		wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec--;
-	}
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/sparc64/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -703,9 +703,9 @@
 	}
 
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
-	wall_to_monotonic.tv_sec = -xtime.tv_sec;
 	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-	wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+	set_normalized_timespec(&wall_to_monotonic,
+ 	                        -xtime.tv_sec, -xtime.tv_nsec);
 
 	if (mregs) {
 		tmp = mostek_read(mregs + MOSTEK_CREG);
@@ -743,9 +743,9 @@
 			(unsigned int) (long) &unix_tod);
 		prom_feval(obp_gettod);
 		xtime.tv_sec = unix_tod;
-		wall_to_monotonic.tv_sec = -xtime.tv_sec;
 		xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-		wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+		set_normalized_timespec(&wall_to_monotonic,
+		                        -xtime.tv_sec, -xtime.tv_nsec);
 		return;
 	}
 
@@ -1090,6 +1090,9 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
@@ -1103,28 +1106,15 @@
 	 * wall time.  Discover what correction gettimeofday() would have
 	 * made, and then undo it!
 	 */
-	tv->tv_nsec -= do_gettimeoffset() * 1000;
-	tv->tv_nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
-
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
+	nsec -= do_gettimeoffset() * 1000;
+	nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
 
-	wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
-	wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
 
-	if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
-		wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec++;
-	}
-	if (wall_to_monotonic.tv_nsec < 0) {
-		wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec--;
-	}
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
diff -Nru a/arch/v850/kernel/bug.c b/arch/v850/kernel/bug.c
--- a/arch/v850/kernel/bug.c	Fri Jul 11 01:25:29 2003
+++ b/arch/v850/kernel/bug.c	Fri Jul 11 01:25:29 2003
@@ -17,6 +17,7 @@
 
 #include <asm/errno.h>
 #include <asm/ptrace.h>
+#include <asm/processor.h>
 #include <asm/current.h>
 
 /* We should use __builtin_return_address, but it doesn't work in gcc-2.90
@@ -100,12 +101,21 @@
 	}
 }
 
-void show_stack (unsigned long *sp)
-{
-	unsigned long end;
-	unsigned long addr = (unsigned long)sp;
-
-	if (! addr)
+/*
+ * TASK is a pointer to the task whose backtrace we want to see (or NULL
+ * for current task), SP is the stack pointer of the first frame that
+ * should be shown in the back trace (or NULL if the entire call-chain of
+ * the task should be shown).
+ */
+void show_stack (struct task_struct *task, unsigned long *sp)
+{
+	unsigned long addr, end;
+
+	if (sp)
+		addr = (unsigned long)sp;
+	else if (task)
+		addr = task_sp (task);
+	else
 		addr = stack_addr ();
 
 	addr = addr & ~3;
@@ -125,5 +135,5 @@
 
 void dump_stack ()
 {
-	show_stack (0);
+	show_stack (0, 0);
 }
diff -Nru a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c
--- a/arch/v850/kernel/gbus_int.c	Fri Jul 11 01:25:30 2003
+++ b/arch/v850/kernel/gbus_int.c	Fri Jul 11 01:25:30 2003
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support
  *
- *  Copyright (C) 2001,02  NEC Corporation
- *  Copyright (C) 2001,02  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -99,9 +99,11 @@
 
 /* Handle a shared GINT interrupt by passing to the appropriate GBUS
    interrupt handler.  */
-static void gbus_int_handle_irq (int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t gbus_int_handle_irq (int irq, void *dev_id,
+					struct pt_regs *regs)
 {
 	unsigned w;
+	irqreturn_t rval = IRQ_NONE;
 	unsigned gint = irq - IRQ_GINT (0);
 
 	for (w = 0; w < GBUS_INT_NUM_WORDS; w++) {
@@ -127,6 +129,7 @@
 
 				/* Recursively call handle_irq to handle it. */
 				handle_irq (irq, regs);
+				rval = IRQ_HANDLED;
 			} while (status);
 		}
 	}
@@ -136,6 +139,8 @@
 	   still pending, and so result in another CPU interrupt.  */
 	GBUS_INT_ENABLE (0, gint) &= ~0x1;
 	GBUS_INT_ENABLE (0, gint) |=  0x1;
+
+	return rval;
 }
 
 
diff -Nru a/arch/v850/kernel/simcons.c b/arch/v850/kernel/simcons.c
--- a/arch/v850/kernel/simcons.c	Fri Jul 11 01:25:29 2003
+++ b/arch/v850/kernel/simcons.c	Fri Jul 11 01:25:29 2003
@@ -30,7 +30,7 @@
 	V850_SIM_SYSCALL (write, 1, buf, len);
 }
 
-static int simcons_read (struct console *co, const char *buf, unsigned len)
+static int simcons_read (struct console *co, char *buf, unsigned len)
 {
 	return V850_SIM_SYSCALL (read, 0, buf, len);
 }
diff -Nru a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
--- a/arch/v850/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/v850/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -51,7 +51,7 @@
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
  */
-static void timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
+static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
 {
 #if 0
 	/* last time the cmos clock got updated */
@@ -106,6 +106,8 @@
 	}
 #endif /* CONFIG_HEARTBEAT */
 #endif /* 0 */
+
+	return IRQ_HANDLED;
 }
 
 /*
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	Fri Jul 11 01:25:29 2003
+++ b/arch/x86_64/Kconfig	Fri Jul 11 01:25:29 2003
@@ -540,13 +540,6 @@
 	  Fill __init and __initdata at the end of boot. This helps debugging
 	  illegal uses of __init and __initdata after initialization.	  
 
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
 config FRAME_POINTER
        bool "Compile the kernel with frame pointers"
        help
diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
--- a/arch/x86_64/kernel/time.c	Fri Jul 11 01:25:29 2003
+++ b/arch/x86_64/kernel/time.c	Fri Jul 11 01:25:29 2003
@@ -125,33 +125,22 @@
 
 int do_settimeofday(struct timespec *tv)
 {
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
 	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
 	write_seqlock_irq(&xtime_lock);
 
-	tv->tv_nsec -= do_gettimeoffset() * 1000 +
+	nsec -= do_gettimeoffset() * 1000 +
 		(jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ);
 
-	while (tv->tv_nsec < 0) {
-		tv->tv_nsec += NSEC_PER_SEC;
-		tv->tv_sec--;
-	}
-
-	wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
-	wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
-
-	if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
-		wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec++;
-	}
-	if (wall_to_monotonic.tv_nsec < 0) {
-		wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
-		wall_to_monotonic.tv_sec--;
-	}
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
 
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_nsec = tv->tv_nsec;
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
 
 	time_adjust = 0;		/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
@@ -603,8 +592,8 @@
 	xtime.tv_sec = get_cmos_time();
 	xtime.tv_nsec = 0;
 
-	wall_to_monotonic.tv_sec = -xtime.tv_sec;
-	wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
+	set_normalized_timespec(&wall_to_monotonic,
+	                        -xtime.tv_sec, -xtime.tv_nsec);
 
 	if (!hpet_init()) {
                 vxtime_hz = (1000000000000000L + hpet_period / 2) /
diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig
--- a/drivers/block/Kconfig	Fri Jul 11 01:25:28 2003
+++ b/drivers/block/Kconfig	Fri Jul 11 01:25:28 2003
@@ -237,29 +237,20 @@
 	  root file system inside a DOS FAT file using this loop device
 	  driver.
 
-	  The loop device driver can also be used to "hide" a file system in a
-	  disk partition, floppy, or regular file, either using encryption
+	  To use the loop device, you need the losetup utility, found in the
+	  util-linux package, see
+	  <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>.
+
+	  The loop device driver can also be used to "hide" a file system in
+	  a disk partition, floppy, or regular file, either using encryption
 	  (scrambling the data) or steganography (hiding the data in the low
 	  bits of, say, a sound file). This is also safe if the file resides
-	  on a remote file server. If you want to do this, you will first have
-	  to acquire and install a kernel patch from
-	  <ftp://ftp.kerneli.org/pub/kerneli/>, and then you need to
-	  say Y to this option.
-
-	  Note that alternative ways to use encrypted file systems are
-	  provided by the cfs package, which can be gotten from
-	  <ftp://ftp.kerneli.org/pub/kerneli/net-source/>, and the newer tcfs
-	  package, available at <http://tcfs.dia.unisa.it/>. You do not need
-	  to say Y here if you want to use one of these. However, using cfs
-	  requires saying Y to "NFS file system support" below while using
-	  tcfs requires applying a kernel patch. An alternative steganography
-	  solution is provided by StegFS, also available from
-	  <ftp://ftp.kerneli.org/pub/kerneli/net-source/>.
-
-	  To use the loop device, you need the losetup utility and a recent
-	  version of the mount program, both contained in the util-linux
-	  package. The location and current version number of util-linux is
-	  contained in the file <file:Documentation/Changes>.
+	  on a remote file server.
+
+	  There are several ways of doing this. Some of these require kernel
+	  patches. The vanilla kernel offers the cryptoloop option. If you
+	  want to use that, say Y to both LOOP and CRYPTOLOOP, and make sure
+	  you have a recent (version 2.12 or later) version of util-linux.
 
 	  Note that this loop device has nothing to do with the loopback
 	  device used for network connections from the machine to itself.
@@ -270,6 +261,14 @@
 	  will be called loop.
 
 	  Most users will answer N here.
+
+config BLK_DEV_CRYPTOLOOP
+	tristate "Cryptoloop Support"
+	depends on BLK_DEV_LOOP
+	---help---
+	  Say Y here if you want to be able to use the ciphers that are 
+	  provided by the CryptoAPI as loop transformation. This might be
+	  used as hard disk encryption.
 
 config BLK_DEV_NBD
 	tristate "Network block device support"
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile	Fri Jul 11 01:25:29 2003
+++ b/drivers/block/Makefile	Fri Jul 11 01:25:29 2003
@@ -36,3 +36,4 @@
 
 obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
 obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
+obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
diff -Nru a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/block/cryptoloop.c	Fri Jul 11 01:25:30 2003
@@ -0,0 +1,182 @@
+/*
+   Linux loop encryption enabling module
+
+   Copyright (C)  2002 Herbert Valerio Riedel <hvr@gnu.org>
+   Copyright (C)  2003 Fruhwirth Clemens <clemens@endorphin.org>
+
+   This module is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This module is 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 module; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/blkdev.h>
+#include <linux/loop.h>
+#include <linux/blk.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("loop blockdevice transferfunction adaptor / CryptoAPI");
+MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>");
+
+#define LOOP_IV_SECTOR_BITS 9
+#define LOOP_IV_SECTOR_SIZE (1 << LOOP_IV_SECTOR_BITS)
+
+static int
+cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info)
+{
+	int err = -EINVAL;
+	char cms[LO_NAME_SIZE];			/* cipher-mode string */
+	char *cipher;
+	char *mode;
+	char *cmsp = cms;			/* c-m string pointer */
+	struct crypto_tfm *tfm = NULL;
+
+	/* encryption breaks for non sector aligned offsets */
+
+	if (info->lo_offset % LOOP_IV_SECTOR_SIZE)
+		goto out;
+
+	strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE);
+	cms[LO_NAME_SIZE - 1] = 0;
+	cipher = strsep(&cmsp, "-");
+	mode = strsep(&cmsp, "-");
+
+	if (mode == NULL || strcmp(mode, "cbc") == 0)
+		tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC);
+	else if (strcmp(mode, "ecb") == 0)
+		tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB);
+	if (tfm == NULL)
+		return -EINVAL;
+
+	err = tfm->crt_u.cipher.cit_setkey(tfm, info->lo_encrypt_key,
+					   info->lo_encrypt_key_size);
+	
+	if (err != 0)
+		goto out_free_tfm;
+
+	lo->key_data = tfm;
+	return 0;
+
+ out_free_tfm:
+	crypto_free_tfm(tfm);
+
+ out:
+	return err;
+}
+
+typedef int (*encdec_t)(struct crypto_tfm *tfm,
+			struct scatterlist *sg_out,
+			struct scatterlist *sg_in,
+			unsigned int nsg, u8 *iv);
+
+static int
+cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf,
+		     char *loop_buf, int size, sector_t IV)
+{
+	struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
+	struct scatterlist sg_out = { 0, };
+	struct scatterlist sg_in = { 0, };
+
+	encdec_t encdecfunc;
+	char const *in;
+	char *out;
+
+	if (cmd == READ) {
+		in = raw_buf;
+		out = loop_buf;
+		encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv;
+	} else {
+		in = loop_buf;
+		out = raw_buf;
+		encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv;
+	}
+
+	while (size > 0) {
+		const int sz = min(size, LOOP_IV_SECTOR_SIZE);
+		u32 iv[4] = { 0, };
+		iv[0] = cpu_to_le32(IV & 0xffffffff);
+
+		sg_in.page = virt_to_page(in);
+		sg_in.offset = (unsigned long)in & ~PAGE_MASK;
+		sg_in.length = sz;
+
+		sg_out.page = virt_to_page(out);
+		sg_out.offset = (unsigned long)out & ~PAGE_MASK;
+		sg_out.length = sz;
+
+		encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv);
+
+		IV++;
+		size -= sz;
+		in += sz;
+		out += sz;
+	}
+
+	return 0;
+}
+
+
+static int
+cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+static int
+cryptoloop_release(struct loop_device *lo)
+{
+	struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
+	if (tfm != NULL) {
+		crypto_free_tfm(tfm);
+		lo->key_data = NULL;
+		return 0;
+	}
+	printk(KERN_ERR "cryptoloop_release(): tfm == NULL?\n");
+	return -EINVAL;
+}
+
+static struct loop_func_table cryptoloop_funcs = {
+	.number = LO_CRYPT_CRYPTOAPI,
+	.init = cryptoloop_init,
+	.ioctl = cryptoloop_ioctl,
+	.transfer = cryptoloop_transfer,
+	.release = cryptoloop_release,
+	.owner = THIS_MODULE
+};
+
+static int __init
+init_cryptoloop(void)
+{
+	int rc = loop_register_transfer(&cryptoloop_funcs);
+
+	if (rc)
+		printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n");
+	return rc;
+}
+
+static void __exit
+cleanup_cryptoloop(void)
+{
+	if (loop_unregister_transfer(LO_CRYPT_CRYPTOAPI))
+		printk(KERN_ERR
+			"cryptoloop: loop_unregister_transfer failed\n");
+}
+
+module_init(init_cryptoloop);
+module_exit(cleanup_cryptoloop);
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/block/ll_rw_blk.c	Fri Jul 11 01:25:28 2003
@@ -2354,7 +2354,7 @@
 	struct gendisk *disk = req->rq_disk;
 	struct completion *waiting = req->waiting;
 
-	if (disk) {
+	if (disk && blk_fs_request(req)) {
 		unsigned long duration = jiffies - req->start_time;
 		switch (rq_data_dir(req)) {
 		    case WRITE:
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/block/loop.c	Fri Jul 11 01:25:29 2003
@@ -140,7 +140,8 @@
 	sector_t x;
 
 	/* Compute loopsize in bytes */
-	size = lo->lo_backing_file->f_dentry->d_inode->i_mapping->host->i_size;
+	size = i_size_read(lo->lo_backing_file->f_dentry->
+				d_inode->i_mapping->host);
 	offset = lo->lo_offset;
 	loopsize = size - offset;
 	if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
@@ -840,7 +841,8 @@
 	lo->lo_flags = 0;
 	lo->lo_queue.queuedata = NULL;
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
-	memset(lo->lo_name, 0, LO_NAME_SIZE);
+	memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
+	memset(lo->lo_file_name, 0, LO_NAME_SIZE);
 	invalidate_bdev(bdev, 0);
 	set_capacity(disks[lo->lo_number], 0);
 	filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp;
@@ -892,7 +894,10 @@
 			return -EFBIG;
 	}
 
-	strlcpy(lo->lo_name, info->lo_name, LO_NAME_SIZE);
+	memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
+	memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
+	lo->lo_file_name[LO_NAME_SIZE-1] = 0;
+	lo->lo_crypt_name[LO_NAME_SIZE-1] = 0;
 
 	if (!xfer)
 		xfer = &none_funcs;
@@ -931,7 +936,8 @@
 	info->lo_offset = lo->lo_offset;
 	info->lo_sizelimit = lo->lo_sizelimit;
 	info->lo_flags = lo->lo_flags;
-	strlcpy(info->lo_name, lo->lo_name, LO_NAME_SIZE);
+	memcpy(info->lo_file_name, lo->lo_file_name, LO_NAME_SIZE);
+	memcpy(info->lo_crypt_name, lo->lo_crypt_name, LO_NAME_SIZE);
 	info->lo_encrypt_type =
 		lo->lo_encryption ? lo->lo_encryption->number : 0;
 	if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) {
@@ -957,7 +963,10 @@
 	info64->lo_flags = info->lo_flags;
 	info64->lo_init[0] = info->lo_init[0];
 	info64->lo_init[1] = info->lo_init[1];
-	memcpy(info64->lo_name, info->lo_name, LO_NAME_SIZE);
+	if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+		memcpy(info64->lo_crypt_name, info->lo_name, LO_NAME_SIZE);
+	else
+		memcpy(info64->lo_file_name, info->lo_name, LO_NAME_SIZE);
 	memcpy(info64->lo_encrypt_key, info->lo_encrypt_key, LO_KEY_SIZE);
 }
 
@@ -975,8 +984,11 @@
 	info->lo_flags = info64->lo_flags;
 	info->lo_init[0] = info64->lo_init[0];
 	info->lo_init[1] = info64->lo_init[1];
-	memcpy(info->lo_name, info64->lo_name, LO_NAME_SIZE);
-	memcpy(info->lo_encrypt_key,info64->lo_encrypt_key,LO_KEY_SIZE);
+	if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+		memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
+	else
+		memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE);
+	memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
 
 	/* error in case values were truncated */
 	if (info->lo_device != info64->lo_device ||
diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c
--- a/drivers/block/nbd.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/block/nbd.c	Fri Jul 11 01:25:28 2003
@@ -31,13 +31,17 @@
  * 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes
  *   memory corruption from module removal and possible memory corruption
  *   from sending/receiving disk data. <ldl@aros.net>
+ * 03-06-23 Cosmetic changes. <ldl@aros.net>
+ * 03-06-23 Enhance diagnostics support. <ldl@aros.net>
+ * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct.
+ *   <ldl@aros.net>
+ * 03-06-24 Cleanup PARANOIA usage & code. <ldl@aros.net>
  *
  * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
  * why not: would need verify_area and friends, would share yet another 
  *          structure with userland
  */
 
-#define PARANOIA
 #include <linux/major.h>
 
 #include <linux/blk.h>
@@ -60,9 +64,27 @@
 #include <asm/uaccess.h>
 #include <asm/types.h>
 
+/* Define PARANOIA in linux/nbd.h to turn on extra sanity checking */
 #include <linux/nbd.h>
 
+#ifdef PARANOIA
 #define LO_MAGIC 0x68797548
+#endif
+
+#ifdef NDEBUG
+#define dprintk(flags, fmt...)
+#else /* NDEBUG */
+#define dprintk(flags, fmt...) do { \
+	if (debugflags & (flags)) printk(KERN_DEBUG fmt); \
+} while (0)
+#define DBG_IOCTL       0x0004
+#define DBG_INIT        0x0010
+#define DBG_EXIT        0x0020
+#define DBG_BLKDEV      0x0100
+#define DBG_RX          0x0200
+#define DBG_TX          0x0400
+static unsigned int debugflags;
+#endif /* NDEBUG */
 
 static struct nbd_device nbd_dev[MAX_NBD];
 
@@ -78,12 +100,40 @@
  */
 static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED;
 
-#define DEBUG( s )
-/* #define DEBUG( s ) printk( s ) 
- */
-
+#ifdef PARANOIA
 static int requests_in;
 static int requests_out;
+#endif
+
+#ifndef NDEBUG
+static const char *ioctl_cmd_to_ascii(int cmd)
+{
+	switch (cmd) {
+	case NBD_SET_SOCK: return "set-sock";
+	case NBD_SET_BLKSIZE: return "set-blksize";
+	case NBD_SET_SIZE: return "set-size";
+	case NBD_DO_IT: return "do-it";
+	case NBD_CLEAR_SOCK: return "clear-sock";
+	case NBD_CLEAR_QUE: return "clear-que";
+	case NBD_PRINT_DEBUG: return "print-debug";
+	case NBD_SET_SIZE_BLOCKS: return "set-size-blocks";
+	case NBD_DISCONNECT: return "disconnect";
+	case BLKROSET: return "set-read-only";
+	case BLKFLSBUF: return "flush-buffer-cache";
+	}
+	return "unknown";
+}
+
+static const char *nbdcmd_to_ascii(int cmd)
+{
+	switch (cmd) {
+	case  NBD_CMD_READ: return "read";
+	case NBD_CMD_WRITE: return "write";
+	case  NBD_CMD_DISC: return "disconnect";
+	}
+	return "invalid";
+}
+#endif /* NDEBUG */
 
 static void nbd_end_request(struct request *req)
 {
@@ -91,6 +141,8 @@
 	request_queue_t *q = req->q;
 	unsigned long flags;
 
+	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
+			req, uptodate? "done": "failed");
 #ifdef PARANOIA
 	requests_out++;
 #endif
@@ -101,17 +153,11 @@
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
-static int nbd_open(struct inode *inode, struct file *file)
-{
-	struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
-	lo->refcnt++;
-	return 0;
-}
-
 /*
  *  Send or receive packet.
  */
-static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_flags)
+static int sock_xmit(struct socket *sock, int send, void *buf, int size,
+		int msg_flags)
 {
 	mm_segment_t oldfs;
 	int result;
@@ -131,7 +177,6 @@
 	recalc_sigpending();
 	spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
-
 	do {
 		sock->sk->sk_allocation = GFP_NOIO;
 		iov.iov_base = buf;
@@ -153,7 +198,7 @@
 		if (signal_pending(current)) {
 			siginfo_t info;
 			spin_lock_irqsave(&current->sighand->siglock, flags);
-			printk(KERN_WARNING "NBD (pid %d: %s) got signal %d\n",
+			printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
 				current->pid, current->comm, 
 				dequeue_signal(current, &current->blocked, &info));
 			spin_unlock_irqrestore(&current->sighand->siglock, flags);
@@ -163,8 +208,8 @@
 
 		if (result <= 0) {
 #ifdef PARANOIA
-			printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n",
-			       send ? "send" : "receive", (long) sock, (long) buf, size, result);
+			printk(KERN_ERR "nbd: %s - sock=%p at buf=%p, size=%d returned %d.\n",
+			       send? "send": "receive", sock, buf, size, result);
 #endif
 			break;
 		}
@@ -186,14 +231,12 @@
 {
 	int result;
 	void *kaddr = kmap(bvec->bv_page);
-	result = nbd_xmit(1, sock, kaddr + bvec->bv_offset, bvec->bv_len,
+	result = sock_xmit(sock, 1, kaddr + bvec->bv_offset, bvec->bv_len,
 			flags);
 	kunmap(bvec->bv_page);
 	return result;
 }
 
-#define FAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); goto error_out; }
-
 void nbd_send_req(struct nbd_device *lo, struct request *req)
 {
 	int result, i, flags;
@@ -201,24 +244,31 @@
 	unsigned long size = req->nr_sectors << 9;
 	struct socket *sock = lo->sock;
 
-	DEBUG("NBD: sending control, ");
-	
 	request.magic = htonl(NBD_REQUEST_MAGIC);
 	request.type = htonl(nbd_cmd(req));
-	request.from = cpu_to_be64( (u64) req->sector << 9);
+	request.from = cpu_to_be64((u64) req->sector << 9);
 	request.len = htonl(size);
 	memcpy(request.handle, &req, sizeof(req));
 
 	down(&lo->tx_lock);
 
 	if (!sock || !lo->sock) {
-		printk(KERN_ERR "NBD: Attempted sendmsg to closed socket\n");
+		printk(KERN_ERR "%s: Attempted send on closed socket\n",
+				lo->disk->disk_name);
 		goto error_out;
 	}
 
-	result = nbd_xmit(1, sock, (char *) &request, sizeof(request), nbd_cmd(req) == NBD_CMD_WRITE ? MSG_MORE : 0);
-	if (result <= 0)
-		FAIL("Sendmsg failed for control.");
+	dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
+			lo->disk->disk_name, req,
+			nbdcmd_to_ascii(nbd_cmd(req)),
+			req->sector << 9, req->nr_sectors << 9);
+	result = sock_xmit(sock, 1, &request, sizeof(request),
+			(nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0);
+	if (result <= 0) {
+		printk(KERN_ERR "%s: Send control failed (result %d)\n",
+				lo->disk->disk_name, result);
+		goto error_out;
+	}
 
 	if (nbd_cmd(req) == NBD_CMD_WRITE) {
 		struct bio *bio;
@@ -232,10 +282,16 @@
 				flags = 0;
 				if ((i < (bio->bi_vcnt - 1)) || bio->bi_next)
 					flags = MSG_MORE;
-				DEBUG("data, ");
+				dprintk(DBG_TX, "%s: request %p: sending %d bytes data\n",
+						lo->disk->disk_name, req,
+						bvec->bv_len);
 				result = sock_send_bvec(sock, bvec, flags);
-				if (result <= 0)
-					FAIL("Send data failed.");
+				if (result <= 0) {
+					printk(KERN_ERR "%s: Send data failed (result %d)\n",
+							lo->disk->disk_name,
+							result);
+					goto error_out;
+				}
 			}
 		}
 	}
@@ -272,55 +328,71 @@
 {
 	int result;
 	void *kaddr = kmap(bvec->bv_page);
-	result = nbd_xmit(0, sock, kaddr + bvec->bv_offset, bvec->bv_len,
+	result = sock_xmit(sock, 0, kaddr + bvec->bv_offset, bvec->bv_len,
 			MSG_WAITALL);
 	kunmap(bvec->bv_page);
 	return result;
 }
 
-#define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); lo->harderror = result; return NULL; }
+/* NULL returned = something went wrong, inform userspace */
 struct request *nbd_read_stat(struct nbd_device *lo)
-		/* NULL returned = something went wrong, inform userspace       */ 
 {
 	int result;
 	struct nbd_reply reply;
 	struct request *req;
 	struct socket *sock = lo->sock;
 
-	DEBUG("reading control, ");
 	reply.magic = 0;
-	result = nbd_xmit(0, sock, (char *) &reply, sizeof(reply), MSG_WAITALL);
-	if (result <= 0)
-		HARDFAIL("Recv control failed.");
+	result = sock_xmit(sock, 0, &reply, sizeof(reply), MSG_WAITALL);
+	if (result <= 0) {
+		printk(KERN_ERR "%s: Receive control failed (result %d)\n",
+				lo->disk->disk_name, result);
+		lo->harderror = result;
+		return NULL;
+	}
 	req = nbd_find_request(lo, reply.handle);
-	if (req == NULL)
-		HARDFAIL("Unexpected reply");
-
-	DEBUG("ok, ");
-	if (ntohl(reply.magic) != NBD_REPLY_MAGIC)
-		HARDFAIL("Not enough magic.");
-	if (ntohl(reply.error))
-		FAIL("Other side returned error.");
+	if (req == NULL) {
+		printk(KERN_ERR "%s: Unexpected reply (%p)\n",
+				lo->disk->disk_name, reply.handle);
+		lo->harderror = result;
+		return NULL;
+	}
+
+	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
+		printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
+				lo->disk->disk_name,
+				(unsigned long)ntohl(reply.magic));
+		lo->harderror = result;
+		return NULL;
+	}
+	if (ntohl(reply.error)) {
+		printk(KERN_ERR "%s: Other side returned error (%d)\n",
+				lo->disk->disk_name, ntohl(reply.error));
+		req->errors++;
+		return req;
+	}
 
+	dprintk(DBG_RX, "%s: request %p: got reply\n",
+			lo->disk->disk_name, req);
 	if (nbd_cmd(req) == NBD_CMD_READ) {
 		int i;
 		struct bio *bio;
-		DEBUG("data, ");
 		rq_for_each_bio(bio, req) {
 			struct bio_vec *bvec;
 			bio_for_each_segment(bvec, bio, i) {
 				result = sock_recv_bvec(sock, bvec);
-				if (result <= 0)
-					HARDFAIL("Recv data failed.");
+				if (result <= 0) {
+					printk(KERN_ERR "%s: Receive data failed (result %d)\n",
+							lo->disk->disk_name,
+							result);
+					lo->harderror = result;
+					return NULL;
+				}
+				dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
+					lo->disk->disk_name, req, bvec->bv_len);
 			}
 		}
 	}
-	DEBUG("done.\n");
-	return req;
-
-/* Can we get here? Yes, if other side returns error */
-      error_out:
-	req->errors++;
 	return req;
 }
 
@@ -328,17 +400,13 @@
 {
 	struct request *req;
 
-	while (1) {
-		req = nbd_read_stat(lo);
-
-		if (!req) {
-			printk(KERN_ALERT "req should never be null\n" );
-			goto out;
-		}
-		BUG_ON(lo->magic != LO_MAGIC);
+#ifdef PARANOIA
+	BUG_ON(lo->magic != LO_MAGIC);
+#endif
+	while ((req = nbd_read_stat(lo)) != NULL)
 		nbd_end_request(req);
-	}
- out:
+	printk(KERN_NOTICE "%s: req should never be null\n",
+			lo->disk->disk_name);
 	return;
 }
 
@@ -346,7 +414,9 @@
 {
 	struct request *req;
 
+#ifdef PARANOIA
 	BUG_ON(lo->magic != LO_MAGIC);
+#endif
 
 	do {
 		req = NULL;
@@ -360,7 +430,7 @@
 			req->errors++;
 			nbd_end_request(req);
 		}
-	} while(req);
+	} while (req);
 }
 
 /*
@@ -370,9 +440,6 @@
  *   { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
  */
 
-#undef FAIL
-#define FAIL( s ) { printk( KERN_ERR "%s: " s "\n", req->rq_disk->disk_name ); goto error_out; }
-
 static void do_nbd_request(request_queue_t * q)
 {
 	struct request *req;
@@ -380,30 +447,44 @@
 	while ((req = elv_next_request(q)) != NULL) {
 		struct nbd_device *lo;
 
+		blkdev_dequeue_request(req);
+		dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
+				req->rq_disk->disk_name, req, req->flags);
+
 		if (!(req->flags & REQ_CMD))
 			goto error_out;
 
 		lo = req->rq_disk->private_data;
-		if (!lo->file)
-			FAIL("Request when not-ready.");
+#ifdef PARANOIA
+		BUG_ON(lo->magic != LO_MAGIC);
+#endif
+		if (!lo->file) {
+			printk(KERN_ERR "%s: Request when not-ready\n",
+					lo->disk->disk_name);
+			goto error_out;
+		}
 		nbd_cmd(req) = NBD_CMD_READ;
 		if (rq_data_dir(req) == WRITE) {
 			nbd_cmd(req) = NBD_CMD_WRITE;
-			if (lo->flags & NBD_READ_ONLY)
-				FAIL("Write on read-only");
+			if (lo->flags & NBD_READ_ONLY) {
+				printk(KERN_ERR "%s: Write on read-only\n",
+						lo->disk->disk_name);
+				goto error_out;
+			}
 		}
-		BUG_ON(lo->magic != LO_MAGIC);
+#ifdef PARANOIA
 		requests_in++;
+#endif
 
 		req->errors = 0;
-		blkdev_dequeue_request(req);
 		spin_unlock_irq(q->queue_lock);
 
 		spin_lock(&lo->queue_lock);
 
 		if (!lo->file) {
 			spin_unlock(&lo->queue_lock);
-			printk(KERN_ERR "nbd: failed between accept and semaphore, file lost\n");
+			printk(KERN_ERR "%s: failed between accept and semaphore, file lost\n",
+					lo->disk->disk_name);
 			req->errors++;
 			nbd_end_request(req);
 			spin_lock_irq(q->queue_lock);
@@ -416,7 +497,8 @@
 		nbd_send_req(lo, req);
 
 		if (req->errors) {
-			printk(KERN_ERR "nbd: nbd_send_req failed\n");
+			printk(KERN_ERR "%s: Request send failed\n",
+					lo->disk->disk_name);
 			spin_lock(&lo->queue_lock);
 			list_del_init(&req->queuelist);
 			spin_unlock(&lo->queue_lock);
@@ -430,7 +512,6 @@
 
 	      error_out:
 		req->errors++;
-		blkdev_dequeue_request(req);
 		spin_unlock(q->queue_lock);
 		nbd_end_request(req);
 		spin_lock(q->queue_lock);
@@ -442,18 +523,30 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
-	int error, temp;
+	int error;
 	struct request sreq ;
 
-	/* Anyone capable of this syscall can do *real bad* things */
-
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
+#ifdef PARANOIA
+	BUG_ON(lo->magic != LO_MAGIC);
+#endif
+	/* Anyone capable of this syscall can do *real bad* things */
+	dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
+			lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
+
 	switch (cmd) {
 	case NBD_DISCONNECT:
-	        printk(KERN_INFO "NBD_DISCONNECT\n");
+	        printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
 		sreq.flags = REQ_SPECIAL;
 		nbd_cmd(&sreq) = NBD_CMD_DISC;
+		/*
+		 * Set these to sane values in case server implementation
+		 * fails to check the request type first and also to keep
+		 * debugging output cleaner.
+		 */
+		sreq.sector = 0;
+		sreq.nr_sectors = 0;
                 if (!lo->sock)
 			return -EINVAL;
                 nbd_send_req(lo, &sreq);
@@ -464,7 +557,8 @@
 		spin_lock(&lo->queue_lock);
 		if (!list_empty(&lo->queue_head)) {
 			spin_unlock(&lo->queue_lock);
-			printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n");
+			printk(KERN_ERR "%s: Some requests are in progress -> can not turn off.\n",
+					lo->disk->disk_name);
 			return -EBUSY;
 		}
 		file = lo->file;
@@ -494,24 +588,22 @@
 		}
 		return error;
 	case NBD_SET_BLKSIZE:
-		if ((arg & (arg-1)) || (arg < 512) || (arg > PAGE_SIZE))
-			return -EINVAL;
 		lo->blksize = arg;
-		temp = arg >> 9;
-		lo->blksize_bits = 9;
-		while (temp > 1) {
-			lo->blksize_bits++;
-			temp >>= 1;
-		}
-		lo->bytesize &= ~(lo->blksize-1); 
+		lo->bytesize &= ~(lo->blksize-1);
+		inode->i_bdev->bd_inode->i_size = lo->bytesize;
+		set_blocksize(inode->i_bdev, lo->blksize);
 		set_capacity(lo->disk, lo->bytesize >> 9);
 		return 0;
 	case NBD_SET_SIZE:
-		lo->bytesize = arg & ~(lo->blksize-1); 
+		lo->bytesize = arg & ~(lo->blksize-1);
+		inode->i_bdev->bd_inode->i_size = lo->bytesize;
+		set_blocksize(inode->i_bdev, lo->blksize);
 		set_capacity(lo->disk, lo->bytesize >> 9);
 		return 0;
 	case NBD_SET_SIZE_BLOCKS:
-		lo->bytesize = ((u64) arg) << lo->blksize_bits;
+		lo->bytesize = ((u64) arg) * lo->blksize;
+		inode->i_bdev->bd_inode->i_size = lo->bytesize;
+		set_blocksize(inode->i_bdev, lo->blksize);
 		set_capacity(lo->disk, lo->bytesize >> 9);
 		return 0;
 	case NBD_DO_IT:
@@ -526,7 +618,8 @@
 		 * there should be a more generic interface rather than
 		 * calling socket ops directly here */
 		down(&lo->tx_lock);
-		printk(KERN_WARNING "nbd: shutting down socket\n");
+		printk(KERN_WARNING "%s: shutting down socket\n",
+				lo->disk->disk_name);
 		lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN);
 		lo->sock = NULL;
 		up(&lo->tx_lock);
@@ -535,39 +628,31 @@
 		lo->file = NULL;
 		spin_unlock(&lo->queue_lock);
 		nbd_clear_que(lo);
-		printk(KERN_WARNING "nbd: queue cleared\n");
+		printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
 		if (file)
 			fput(file);
 		return lo->harderror;
 	case NBD_CLEAR_QUE:
 		nbd_clear_que(lo);
 		return 0;
-#ifdef PARANOIA
 	case NBD_PRINT_DEBUG:
+#ifdef PARANOIA
 		printk(KERN_INFO "%s: next = %p, prev = %p. Global: in %d, out %d\n",
-		       inode->i_bdev->bd_disk->disk_name, lo->queue_head.next,
-		       lo->queue_head.prev, requests_in, requests_out);
-		return 0;
+			inode->i_bdev->bd_disk->disk_name, lo->queue_head.next,
+			lo->queue_head.prev, requests_in, requests_out);
+#else
+		printk(KERN_INFO "%s: next = %p, prev = %p\n",
+			inode->i_bdev->bd_disk->disk_name,
+			lo->queue_head.next, lo->queue_head.prev);
 #endif
+		return 0;
 	}
 	return -EINVAL;
 }
 
-static int nbd_release(struct inode *inode, struct file *file)
-{
-	struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
-	if (lo->refcnt <= 0)
-		printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt);
-	lo->refcnt--;
-	/* N.B. Doesn't lo->file need an fput?? */
-	return 0;
-}
-
 static struct block_device_operations nbd_fops =
 {
 	.owner =	THIS_MODULE,
-	.open =		nbd_open,
-	.release =	nbd_release,
 	.ioctl =	nbd_ioctl,
 };
 
@@ -581,10 +666,12 @@
 	int err = -ENOMEM;
 	int i;
 
+#ifdef PARANOIA
 	if (sizeof(struct nbd_request) != 28) {
-		printk(KERN_CRIT "Sizeof nbd_request needs to be 28 in order to work!\n" );
+		printk(KERN_CRIT "nbd: Sizeof nbd_request needs to be 28 in order to work!\n" );
 		return -EIO;
 	}
+#endif
 
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = alloc_disk(1);
@@ -601,6 +688,7 @@
 			put_disk(disk);
 			goto out;
 		}
+		memset(disk->queue, 0, sizeof(struct request_queue));
 		blk_init_queue(disk->queue, do_nbd_request, &nbd_lock);
 	}
 
@@ -608,21 +696,22 @@
 		err = -EIO;
 		goto out;
 	}
-#ifdef MODULE
-	printk("nbd: registered device at major %d\n", NBD_MAJOR);
-#endif
+
+	printk(KERN_INFO "nbd: registered device at major %d\n", NBD_MAJOR);
+	dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags);
+
 	devfs_mk_dir("nbd");
 	for (i = 0; i < MAX_NBD; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
-		nbd_dev[i].refcnt = 0;
 		nbd_dev[i].file = NULL;
+#ifdef PARANOIA
 		nbd_dev[i].magic = LO_MAGIC;
+#endif
 		nbd_dev[i].flags = 0;
 		spin_lock_init(&nbd_dev[i].queue_lock);
 		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
 		init_MUTEX(&nbd_dev[i].tx_lock);
 		nbd_dev[i].blksize = 1024;
-		nbd_dev[i].blksize_bits = 10;
 		nbd_dev[i].bytesize = ((u64)0x7ffffc00) << 10; /* 2TB */
 		disk->major = NBD_MAJOR;
 		disk->first_minor = i;
@@ -660,9 +749,7 @@
 	}
 	devfs_remove("nbd");
 	unregister_blkdev(NBD_MAJOR, "nbd");
-#ifdef MODULE
-	printk("nbd: unregistered device at major %d\n", NBD_MAJOR);
-#endif
+	printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR);
 }
 
 module_init(nbd_init);
@@ -671,4 +758,7 @@
 MODULE_DESCRIPTION("Network Block Device");
 MODULE_LICENSE("GPL");
 
-
+#ifndef NDEBUG
+MODULE_PARM(debugflags, "i");
+MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
+#endif
diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/agp/via-agp.c	Fri Jul 11 01:25:29 2003
@@ -382,7 +382,7 @@
 		}
 	}
 
-	if (agp_try_unsupported) {
+	if (!agp_try_unsupported) {
 		printk(KERN_ERR PFX 
 		    "Unsupported VIA chipset (device id: %04x),"
 		    " you might want to try agp_try_unsupported=1.\n",
diff -Nru a/drivers/char/drm/ati_pcigart.h b/drivers/char/drm/ati_pcigart.h
--- a/drivers/char/drm/ati_pcigart.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/ati_pcigart.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,11 @@
-/* ati_pcigart.h -- ATI PCI GART support -*- linux-c -*-
+/**
+ * \file ati_pcigart.h 
+ * ATI PCI GART support
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com
  *
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@@ -22,9 +29,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *   Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
@@ -45,8 +49,8 @@
 # error - PAGE_SIZE not 64K, 16K, 8K or 4K
 #endif
 
-# define ATI_MAX_PCIGART_PAGES		8192	/* 32 MB aperture, 4K pages */
-# define ATI_PCIGART_PAGE_SIZE		4096	/* PCI GART page size */
+# define ATI_MAX_PCIGART_PAGES		8192	/**< 32 MB aperture, 4K pages */
+# define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
 
 static unsigned long DRM(ati_alloc_pcigart_table)( void )
 {
diff -Nru a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
--- a/drivers/char/drm/drm.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm.h	Fri Jul 11 01:25:28 2003
@@ -1,6 +1,14 @@
-/* drm.h -- Header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan  4 10:05:05 1999 by faith@precisioninsight.com
+/**
+ * \file drm.h 
+ * Header for the Direct Rendering Manager
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
  *
+ * \par Acknowledgments:
+ * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
+ */
+
+/*
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All rights reserved.
@@ -23,15 +31,9 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *
- * Acknowledgements:
- * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic cmpxchg.
- *
  */
 
+
 #ifndef _DRM_H_
 #define _DRM_H_
 
@@ -82,29 +84,33 @@
 #define DRM_MAJOR       226
 #define DRM_MAX_MINOR   15
 #endif
-#define DRM_NAME	"drm"	  /* Name in kernel, /dev, and /proc	    */
-#define DRM_MIN_ORDER	5	  /* At least 2^5 bytes = 32 bytes	    */
-#define DRM_MAX_ORDER	22	  /* Up to 2^22 bytes = 4MB		    */
-#define DRM_RAM_PERCENT 10	  /* How much system ram can we lock?	    */
+#define DRM_NAME	"drm"	  /**< Name in kernel, /dev, and /proc */
+#define DRM_MIN_ORDER	5	  /**< At least 2^5 bytes = 32 bytes */
+#define DRM_MAX_ORDER	22	  /**< Up to 2^22 bytes = 4MB */
+#define DRM_RAM_PERCENT 10	  /**< How much system ram can we lock? */
 
-#define _DRM_LOCK_HELD	0x80000000 /* Hardware lock is held		    */
-#define _DRM_LOCK_CONT	0x40000000 /* Hardware lock is contended	    */
+#define _DRM_LOCK_HELD	0x80000000 /**< Hardware lock is held */
+#define _DRM_LOCK_CONT	0x40000000 /**< Hardware lock is contended */
 #define _DRM_LOCK_IS_HELD(lock)	   ((lock) & _DRM_LOCK_HELD)
 #define _DRM_LOCK_IS_CONT(lock)	   ((lock) & _DRM_LOCK_CONT)
 #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
 
+
 typedef unsigned long drm_handle_t;
 typedef unsigned int  drm_context_t;
 typedef unsigned int  drm_drawable_t;
 typedef unsigned int  drm_magic_t;
 
-/* Warning: If you change this structure, make sure you change
- * XF86DRIClipRectRec in the server as well */
 
-/* KW: Actually it's illegal to change either for
+/**
+ * Cliprect.
+ * 
+ * \warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well
+ *
+ * \note KW: Actually it's illegal to change either for
  * backwards-compatibility reasons.
  */
-
 typedef struct drm_clip_rect {
 	unsigned short	x1;
 	unsigned short	y1;
@@ -112,6 +118,10 @@
 	unsigned short	y2;
 } drm_clip_rect_t;
 
+
+/**
+ * Texture region,
+ */
 typedef struct drm_tex_region {
 	unsigned char	next;
 	unsigned char	prev;
@@ -120,32 +130,52 @@
 	unsigned int	age;
 } drm_tex_region_t;
 
+
+/**
+ * DRM_IOCTL_VERSION ioctl argument type.
+ * 
+ * \sa drmGetVersion().
+ */
 typedef struct drm_version {
-	int    version_major;	  /* Major version			    */
-	int    version_minor;	  /* Minor version			    */
-	int    version_patchlevel;/* Patch level			    */
-	size_t name_len;	  /* Length of name buffer		    */
-	char   *name;		  /* Name of driver			    */
-	size_t date_len;	  /* Length of date buffer		    */
-	char   *date;		  /* User-space buffer to hold date	    */
-	size_t desc_len;	  /* Length of desc buffer		    */
-	char   *desc;		  /* User-space buffer to hold desc	    */
+	int    version_major;	  /**< Major version */
+	int    version_minor;	  /**< Minor version */
+	int    version_patchlevel;/**< Patch level */
+	size_t name_len;	  /**< Length of name buffer */
+	char   *name;		  /**< Name of driver */
+	size_t date_len;	  /**< Length of date buffer */
+	char   *date;		  /**< User-space buffer to hold date */
+	size_t desc_len;	  /**< Length of desc buffer */
+	char   *desc;		  /**< User-space buffer to hold desc */
 } drm_version_t;
 
+
+/**
+ * DRM_IOCTL_GET_UNIQUE ioctl argument type.
+ *
+ * \sa drmGetBusid() and drmSetBusId().
+ */
 typedef struct drm_unique {
-	size_t unique_len;	  /* Length of unique			    */
-	char   *unique;		  /* Unique name for driver instantiation   */
+	size_t unique_len;	  /**< Length of unique */
+	char   *unique;		  /**< Unique name for driver instantiation */
 } drm_unique_t;
 
+
 typedef struct drm_list {
-	int		 count;	  /* Length of user-space structures	    */
+	int		 count;	  /**< Length of user-space structures */
 	drm_version_t	 *version;
 } drm_list_t;
 
+
 typedef struct drm_block {
 	int		 unused;
 } drm_block_t;
 
+
+/**
+ * DRM_IOCTL_CONTROL ioctl argument type.
+ *
+ * \sa drmCtlInstHandler() and drmCtlUninstHandler().
+ */
 typedef struct drm_control {
 	enum {
 		DRM_ADD_COMMAND,
@@ -156,49 +186,70 @@
 	int		 irq;
 } drm_control_t;
 
+
+/**
+ * Type of memory to map.
+ */
 typedef enum drm_map_type {
-	_DRM_FRAME_BUFFER   = 0,  /* WC (no caching), no core dump	    */
-	_DRM_REGISTERS	    = 1,  /* no caching, no core dump		    */
-	_DRM_SHM	    = 2,  /* shared, cached			    */
-	_DRM_AGP            = 3,  /* AGP/GART                               */
-	_DRM_SCATTER_GATHER = 4	  /* Scatter/gather memory for PCI DMA      */
+	_DRM_FRAME_BUFFER   = 0,  /**< WC (no caching), no core dump */
+	_DRM_REGISTERS	    = 1,  /**< no caching, no core dump */
+	_DRM_SHM	    = 2,  /**< shared, cached */
+	_DRM_AGP            = 3,  /**< AGP/GART */
+	_DRM_SCATTER_GATHER = 4	  /**< Scatter/gather memory for PCI DMA */
 } drm_map_type_t;
 
+
+/**
+ * Memory mapping flags.
+ */
 typedef enum drm_map_flags {
-	_DRM_RESTRICTED	     = 0x01, /* Cannot be mapped to user-virtual    */
+	_DRM_RESTRICTED	     = 0x01, /**< Cannot be mapped to user-virtual */
 	_DRM_READ_ONLY	     = 0x02,
-	_DRM_LOCKED	     = 0x04, /* shared, cached, locked		    */
-	_DRM_KERNEL	     = 0x08, /* kernel requires access		    */
-	_DRM_WRITE_COMBINING = 0x10, /* use write-combining if available    */
-	_DRM_CONTAINS_LOCK   = 0x20, /* SHM page that contains lock	    */
-	_DRM_REMOVABLE	     = 0x40  /* Removable mapping		    */
+	_DRM_LOCKED	     = 0x04, /**< shared, cached, locked */
+	_DRM_KERNEL	     = 0x08, /**< kernel requires access */
+	_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
+	_DRM_CONTAINS_LOCK   = 0x20, /**< SHM page that contains lock */
+	_DRM_REMOVABLE	     = 0x40  /**< Removable mapping */
 } drm_map_flags_t;
 
+
 typedef struct drm_ctx_priv_map {
-	unsigned int	ctx_id;  /* Context requesting private mapping */
-	void		*handle; /* Handle of map */
+	unsigned int	ctx_id;  /**< Context requesting private mapping */
+	void		*handle; /**< Handle of map */
 } drm_ctx_priv_map_t;
 
+
+/**
+ * DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
+ * argument type.
+ *
+ * \sa drmAddMap().
+ */
 typedef struct drm_map {
-	unsigned long	offset;	 /* Requested physical address (0 for SAREA)*/
-	unsigned long	size;	 /* Requested physical size (bytes)	    */
-	drm_map_type_t	type;	 /* Type of memory to map		    */
-	drm_map_flags_t flags;	 /* Flags				    */
-	void		*handle; /* User-space: "Handle" to pass to mmap    */
-				 /* Kernel-space: kernel-virtual address    */
-	int		mtrr;	 /* MTRR slot used			    */
-				 /* Private data			    */
+	unsigned long	offset;	 /**< Requested physical address (0 for SAREA)*/
+	unsigned long	size;	 /**< Requested physical size (bytes) */
+	drm_map_type_t	type;	 /**< Type of memory to map */
+	drm_map_flags_t flags;	 /**< Flags */
+	void		*handle; /**< User-space: "Handle" to pass to mmap() */
+				 /**< Kernel-space: kernel-virtual address */
+	int		mtrr;	 /**< MTRR slot used */
+				 /*   Private data */
 } drm_map_t;
 
+
+/**
+ * DRM_IOCTL_GET_CLIENT ioctl argument type.
+ */
 typedef struct drm_client {
-	int		idx;	/* Which client desired?                    */
-	int		auth;	/* Is client authenticated?                 */
-	unsigned long	pid;	/* Process id                               */
-	unsigned long	uid;	/* User id                                  */
-	unsigned long	magic;	/* Magic                                    */
-	unsigned long	iocs;	/* Ioctl count                              */
+	int		idx;	/**< Which client desired? */
+	int		auth;	/**< Is client authenticated? */
+	unsigned long	pid;	/**< Process ID */
+	unsigned long	uid;	/**< User ID */
+	unsigned long	magic;	/**< Magic */
+	unsigned long	iocs;	/**< Ioctl count */
 } drm_client_t;
 
+
 typedef enum {
 	_DRM_STAT_LOCK,
 	_DRM_STAT_OPENS,
@@ -206,20 +257,24 @@
 	_DRM_STAT_IOCTLS,
 	_DRM_STAT_LOCKS,
 	_DRM_STAT_UNLOCKS,
-	_DRM_STAT_VALUE,	/* Generic value                      */
-	_DRM_STAT_BYTE,		/* Generic byte counter (1024bytes/K) */
-	_DRM_STAT_COUNT,	/* Generic non-byte counter (1000/k)  */
-
-	_DRM_STAT_IRQ,		/* IRQ */
-	_DRM_STAT_PRIMARY,	/* Primary DMA bytes */
-	_DRM_STAT_SECONDARY,	/* Secondary DMA bytes */
-	_DRM_STAT_DMA,		/* DMA */
-	_DRM_STAT_SPECIAL,	/* Special DMA (e.g., priority or polled) */
-	_DRM_STAT_MISSED	/* Missed DMA opportunity */
+	_DRM_STAT_VALUE,	/**< Generic value */
+	_DRM_STAT_BYTE,		/**< Generic byte counter (1024bytes/K) */
+	_DRM_STAT_COUNT,	/**< Generic non-byte counter (1000/k) */
+
+	_DRM_STAT_IRQ,		/**< IRQ */
+	_DRM_STAT_PRIMARY,	/**< Primary DMA bytes */
+	_DRM_STAT_SECONDARY,	/**< Secondary DMA bytes */
+	_DRM_STAT_DMA,		/**< DMA */
+	_DRM_STAT_SPECIAL,	/**< Special DMA (e.g., priority or polled) */
+	_DRM_STAT_MISSED	/**< Missed DMA opportunity */
 
 				/* Add to the *END* of the list */
 } drm_stat_type_t;
 
+
+/**
+ * DRM_IOCTL_GET_STATS ioctl argument type.
+ */
 typedef struct drm_stats {
 	unsigned long count;
 	struct {
@@ -228,137 +283,220 @@
 	} data[15];
 } drm_stats_t;
 
+
+/**
+ * Hardware locking flags.
+ */
 typedef enum drm_lock_flags {
-	_DRM_LOCK_READY	     = 0x01, /* Wait until hardware is ready for DMA */
-	_DRM_LOCK_QUIESCENT  = 0x02, /* Wait until hardware quiescent	     */
-	_DRM_LOCK_FLUSH	     = 0x04, /* Flush this context's DMA queue first */
-	_DRM_LOCK_FLUSH_ALL  = 0x08, /* Flush all DMA queues first	     */
+	_DRM_LOCK_READY	     = 0x01, /**< Wait until hardware is ready for DMA */
+	_DRM_LOCK_QUIESCENT  = 0x02, /**< Wait until hardware quiescent */
+	_DRM_LOCK_FLUSH	     = 0x04, /**< Flush this context's DMA queue first */
+	_DRM_LOCK_FLUSH_ALL  = 0x08, /**< Flush all DMA queues first */
 				/* These *HALT* flags aren't supported yet
 				   -- they will be used to support the
 				   full-screen DGA-like mode. */
-	_DRM_HALT_ALL_QUEUES = 0x10, /* Halt all current and future queues   */
-	_DRM_HALT_CUR_QUEUES = 0x20  /* Halt all current queues		     */
+	_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+	_DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
 } drm_lock_flags_t;
 
+
+/**
+ * DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
+ * 
+ * \sa drmGetLock() and drmUnlock().
+ */
 typedef struct drm_lock {
 	int		 context;
 	drm_lock_flags_t flags;
 } drm_lock_t;
 
-typedef enum drm_dma_flags {	      /* These values *MUST* match xf86drm.h */
-				      /* Flags for DMA buffer dispatch	     */
-	_DRM_DMA_BLOCK	      = 0x01, /* Block until buffer dispatched.
-					 Note, the buffer may not yet have
-					 been processed by the hardware --
-					 getting a hardware lock with the
-					 hardware quiescent will ensure
-					 that the buffer has been
-					 processed.			     */
-	_DRM_DMA_WHILE_LOCKED = 0x02, /* Dispatch while lock held	     */
-	_DRM_DMA_PRIORITY     = 0x04, /* High priority dispatch		     */
-
-				      /* Flags for DMA buffer request	     */
-	_DRM_DMA_WAIT	      = 0x10, /* Wait for free buffers		     */
-	_DRM_DMA_SMALLER_OK   = 0x20, /* Smaller-than-requested buffers ok   */
-	_DRM_DMA_LARGER_OK    = 0x40  /* Larger-than-requested buffers ok    */
+
+/**
+ * DMA flags
+ *
+ * \warning 
+ * These values \e must match xf86drm.h.
+ *
+ * \sa drm_dma.
+ */
+typedef enum drm_dma_flags {	      
+				      /* Flags for DMA buffer dispatch */
+	_DRM_DMA_BLOCK	      = 0x01, /**<
+				       * Block until buffer dispatched.
+				       * 
+				       * \note The buffer may not yet have
+				       * been processed by the hardware --
+				       * getting a hardware lock with the
+				       * hardware quiescent will ensure
+				       * that the buffer has been
+				       * processed.
+				       */
+	_DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+	_DRM_DMA_PRIORITY     = 0x04, /**< High priority dispatch */
+
+				      /* Flags for DMA buffer request */
+	_DRM_DMA_WAIT	      = 0x10, /**< Wait for free buffers */
+	_DRM_DMA_SMALLER_OK   = 0x20, /**< Smaller-than-requested buffers OK */
+	_DRM_DMA_LARGER_OK    = 0x40  /**< Larger-than-requested buffers OK */
 } drm_dma_flags_t;
 
+
+/**
+ * DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
+ *
+ * \sa drmAddBufs().
+ */
 typedef struct drm_buf_desc {
-	int	      count;	 /* Number of buffers of this size	     */
-	int	      size;	 /* Size in bytes			     */
-	int	      low_mark;	 /* Low water mark			     */
-	int	      high_mark; /* High water mark			     */
+	int	      count;	 /**< Number of buffers of this size */
+	int	      size;	 /**< Size in bytes */
+	int	      low_mark;	 /**< Low water mark */
+	int	      high_mark; /**< High water mark */
 	enum {
-		_DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA  */
-		_DRM_AGP_BUFFER = 0x02, /* Buffer is in agp space            */
-		_DRM_SG_BUFFER  = 0x04  /* Scatter/gather memory buffer      */
+		_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+		_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+		_DRM_SG_BUFFER  = 0x04  /**< Scatter/gather memory buffer */
 	}	      flags;
-	unsigned long agp_start; /* Start address of where the agp buffers
-				  * are in the agp aperture */
+	unsigned long agp_start; /**< 
+				  * Start address of where the AGP buffers are
+				  * in the AGP aperture
+				  */
 } drm_buf_desc_t;
 
+
+/**
+ * DRM_IOCTL_INFO_BUFS ioctl argument type.
+ */
 typedef struct drm_buf_info {
-	int	       count;	/* Entries in list			     */
+	int	       count;	/**< Entries in list */
 	drm_buf_desc_t *list;
 } drm_buf_info_t;
 
+
+/**
+ * DRM_IOCTL_FREE_BUFS ioctl argument type.
+ */
 typedef struct drm_buf_free {
 	int	       count;
 	int	       *list;
 } drm_buf_free_t;
 
+
+/**
+ * Buffer information
+ *
+ * \sa drm_buf_map.
+ */
 typedef struct drm_buf_pub {
-	int		  idx;	       /* Index into master buflist	     */
-	int		  total;       /* Buffer size			     */
-	int		  used;	       /* Amount of buffer in use (for DMA)  */
-	void		  *address;    /* Address of buffer		     */
+	int		  idx;	       /**< Index into the master buffer list */
+	int		  total;       /**< Buffer size */
+	int		  used;	       /**< Amount of buffer in use (for DMA) */
+	void		  *address;    /**< Address of buffer */
 } drm_buf_pub_t;
 
+
+/**
+ * DRM_IOCTL_MAP_BUFS ioctl argument type.
+ */
 typedef struct drm_buf_map {
-	int	      count;	/* Length of buflist			    */
-	void	      *virtual;	/* Mmaped area in user-virtual		    */
-	drm_buf_pub_t *list;	/* Buffer information			    */
+	int	      count;	/**< Length of the buffer list */
+	void	      *virtual;	/**< Mmap'd area in user-virtual */
+	drm_buf_pub_t *list;	/**< Buffer information */
 } drm_buf_map_t;
 
+
+/**
+ * DRM_IOCTL_DMA ioctl argument type.
+ *
+ * Indices here refer to the offset into the buffer list in drm_buf_get.
+ *
+ * \sa drmDMA().
+ */
 typedef struct drm_dma {
-				/* Indices here refer to the offset into
-				   buflist in drm_buf_get_t.  */
-	int		context;	  /* Context handle		    */
-	int		send_count;	  /* Number of buffers to send	    */
-	int		*send_indices;	  /* List of handles to buffers	    */
-	int		*send_sizes;	  /* Lengths of data to send	    */
-	drm_dma_flags_t flags;		  /* Flags			    */
-	int		request_count;	  /* Number of buffers requested    */
-	int		request_size;	  /* Desired size for buffers	    */
-	int		*request_indices; /* Buffer information		    */
+	int		context;	  /**< Context handle */
+	int		send_count;	  /**< Number of buffers to send */
+	int		*send_indices;	  /**< List of handles to buffers */
+	int		*send_sizes;	  /**< Lengths of data to send */
+	drm_dma_flags_t flags;		  /**< Flags */
+	int		request_count;	  /**< Number of buffers requested */
+	int		request_size;	  /**< Desired size for buffers */
+	int		*request_indices; /**< Buffer information */
 	int		*request_sizes;
-	int		granted_count;	  /* Number of buffers granted	    */
+	int		granted_count;	  /**< Number of buffers granted */
 } drm_dma_t;
 
+
 typedef enum {
 	_DRM_CONTEXT_PRESERVED = 0x01,
 	_DRM_CONTEXT_2DONLY    = 0x02
 } drm_ctx_flags_t;
 
+
+/**
+ * DRM_IOCTL_ADD_CTX ioctl argument type.
+ *
+ * \sa drmCreateContext() and drmDestroyContext().
+ */
 typedef struct drm_ctx {
 	drm_context_t	handle;
 	drm_ctx_flags_t flags;
 } drm_ctx_t;
 
+
+/**
+ * DRM_IOCTL_RES_CTX ioctl argument type.
+ */
 typedef struct drm_ctx_res {
 	int		count;
 	drm_ctx_t	*contexts;
 } drm_ctx_res_t;
 
+
+/**
+ * DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
+ */
 typedef struct drm_draw {
 	drm_drawable_t	handle;
 } drm_draw_t;
 
+
+/**
+ * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
+ */
 typedef struct drm_auth {
 	drm_magic_t	magic;
 } drm_auth_t;
 
+
+/**
+ * DRM_IOCTL_IRQ_BUSID ioctl argument type.
+ *
+ * \sa drmGetInterruptFromBusID().
+ */
 typedef struct drm_irq_busid {
-	int irq;
-	int busnum;
-	int devnum;
-	int funcnum;
+	int irq;	/**< IRQ number */
+	int busnum;	/**< bus number */
+	int devnum;	/**< device number */
+	int funcnum;	/**< function number */
 } drm_irq_busid_t;
 
+
 typedef enum {
-    _DRM_VBLANK_ABSOLUTE = 0x0,		/* Wait for specific vblank sequence number */
-    _DRM_VBLANK_RELATIVE = 0x1,		/* Wait for given number of vblanks */
-    _DRM_VBLANK_SIGNAL   = 0x40000000	/* Send signal instead of blocking */
+    _DRM_VBLANK_ABSOLUTE = 0x0,		/**< Wait for specific vblank sequence number */
+    _DRM_VBLANK_RELATIVE = 0x1,		/**< Wait for given number of vblanks */
+    _DRM_VBLANK_SIGNAL   = 0x40000000	/**< Send signal instead of blocking */
 } drm_vblank_seq_type_t;
 
+
 #define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
 
+
 struct drm_wait_vblank_request {
 	drm_vblank_seq_type_t type;
 	unsigned int sequence;
 	unsigned long signal;
 };
 
+
 struct drm_wait_vblank_reply {
 	drm_vblank_seq_type_t type;
 	unsigned int sequence;
@@ -366,29 +504,59 @@
 	long tval_usec;
 };
 
+
+/**
+ * DRM_IOCTL_WAIT_VBLANK ioctl argument type.
+ *
+ * \sa drmWaitVBlank().
+ */
 typedef union drm_wait_vblank {
 	struct drm_wait_vblank_request request;
 	struct drm_wait_vblank_reply reply;
 } drm_wait_vblank_t;
 
+
+/**
+ * DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+ * \sa drmAgpEnable().
+ */
 typedef struct drm_agp_mode {
-	unsigned long mode;
+	unsigned long mode;	/**< AGP mode */
 } drm_agp_mode_t;
 
-				/* For drm_agp_alloc -- allocated a buffer */
+
+/**
+ * DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
+ *
+ * \sa drmAgpAlloc() and drmAgpFree().
+ */
 typedef struct drm_agp_buffer {
-	unsigned long size;	/* In bytes -- will round to page boundary */
-	unsigned long handle;	/* Used for BIND/UNBIND ioctls */
-	unsigned long type;     /* Type of memory to allocate  */
-        unsigned long physical; /* Physical used by i810       */
+	unsigned long size;	/**< In bytes -- will round to page boundary */
+	unsigned long handle;	/**< Used for binding / unbinding */
+	unsigned long type;     /**< Type of memory to allocate */
+        unsigned long physical; /**< Physical used by i810 */
 } drm_agp_buffer_t;
 
-				/* For drm_agp_bind */
+
+/**
+ * DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
+ *
+ * \sa drmAgpBind() and drmAgpUnbind().
+ */
 typedef struct drm_agp_binding {
-	unsigned long handle;   /* From drm_agp_buffer */
-	unsigned long offset;	/* In bytes -- will round to page boundary */
+	unsigned long handle;   /**< From drm_agp_buffer */
+	unsigned long offset;	/**< In bytes -- will round to page boundary */
 } drm_agp_binding_t;
 
+
+/**
+ * DRM_IOCTL_AGP_INFO ioctl argument type.
+ *
+ * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
+ * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
+ * drmAgpVendorId() and drmAgpDeviceId().
+ */
 typedef struct drm_agp_info {
 	int            agp_version_major;
 	int            agp_version_minor;
@@ -403,11 +571,16 @@
 	unsigned short id_device;
 } drm_agp_info_t;
 
+
+/**
+ * DRM_IOCTL_SG_ALLOC ioctl argument type.
+ */
 typedef struct drm_scatter_gather {
-	unsigned long size;	/* In bytes -- will round to page boundary */
-	unsigned long handle;	/* Used for mapping / unmapping */
+	unsigned long size;	/**< In bytes -- will round to page boundary */
+	unsigned long handle;	/**< Used for mapping / unmapping */
 } drm_scatter_gather_t;
 
+
 #define DRM_IOCTL_BASE			'd'
 #define DRM_IO(nr)			_IO(DRM_IOCTL_BASE,nr)
 #define DRM_IOR(nr,type)		_IOR(DRM_IOCTL_BASE,nr,type)
@@ -467,8 +640,13 @@
 
 #define DRM_IOCTL_WAIT_VBLANK		DRM_IOWR(0x3a, drm_wait_vblank_t)
 
-/* Device specfic ioctls should only be in their respective headers
- * The device specific ioctl range is 0x40 to 0x79.                  */
+/**
+ * Device specific ioctls should only be in their respective headers
+ * The device specific ioctl range is from 0x40 to 0x79.
+ *
+ * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
+ * drmCommandReadWrite().
+ */
 #define DRM_COMMAND_BASE                0x40
 
 #endif
diff -Nru a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
--- a/drivers/char/drm/drmP.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drmP.h	Fri Jul 11 01:25:29 2003
@@ -1,6 +1,12 @@
-/* drmP.h -- Private header for Direct Rendering Manager -*- linux-c -*-
- * Created: Mon Jan  4 10:05:05 1999 by faith@precisioninsight.com
- *
+/**
+ * \file drmP.h 
+ * Private header for Direct Rendering Manager
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All rights reserved.
@@ -23,15 +29,12 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #ifndef _DRM_P_H_
 #define _DRM_P_H_
 
+
 #ifdef __KERNEL__
 #ifdef __alpha__
 /* add include of current.h so that "current" is defined
@@ -72,8 +75,11 @@
 
 #include "drm_os_linux.h"
 
-/* DRM template customization defaults
- */
+
+/***********************************************************************/
+/** \name DRM template customization defaults */
+/*@{*/
+
 #ifndef __HAVE_AGP
 #define __HAVE_AGP		0
 #endif
@@ -101,19 +107,23 @@
 #define __REALLY_HAVE_MTRR	(__HAVE_MTRR && defined(CONFIG_MTRR))
 #define __REALLY_HAVE_SG	(__HAVE_SG)
 
-/* Begin the DRM...
- */
+/*@}*/
+
 
-#define DRM_DEBUG_CODE 2	  /* Include debugging code (if > 1, then
+/***********************************************************************/
+/** \name Begin the DRM... */
+/*@{*/
+
+#define DRM_DEBUG_CODE 2	  /**< Include debugging code if > 1, then
 				     also include looping detection. */
 
-#define DRM_HASH_SIZE	      16 /* Size of key hash table		  */
-#define DRM_KERNEL_CONTEXT    0	 /* Change drm_resctx if changed	  */
-#define DRM_RESERVED_CONTEXTS 1	 /* Change drm_resctx if changed	  */
+#define DRM_HASH_SIZE	      16 /**< Size of key hash table. Must be power of 2. */
+#define DRM_KERNEL_CONTEXT    0	 /**< Change drm_resctx if changed */
+#define DRM_RESERVED_CONTEXTS 1	 /**< Change drm_resctx if changed */
 #define DRM_LOOPING_LIMIT     5000000
-#define DRM_BSZ		      1024 /* Buffer size for /dev/drm? output	  */
-#define DRM_TIME_SLICE	      (HZ/20)  /* Time slice for GLXContexts	  */
-#define DRM_LOCK_SLICE	      1	/* Time slice for lock, in jiffies	  */
+#define DRM_BSZ		      1024 /**< Buffer size for /dev/drm? output */
+#define DRM_TIME_SLICE	      (HZ/20)  /**< Time slice for GLXContexts */
+#define DRM_LOCK_SLICE	      1	/**< Time slice for lock, in jiffies */
 
 #define DRM_FLAG_DEBUG	  0x01
 
@@ -140,8 +150,14 @@
 #define DRM_MEM_SGLISTS   20
 
 #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8)
+	
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Backward compatibility section */
+/*@{*/
 
-				/* Backward compatibility section */
 #ifndef minor
 #define minor(x) MINOR((x))
 #endif
@@ -191,17 +207,42 @@
 #define DRM_RPR_ARG(vma) vma,
 #endif
 
-
 #define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
 
-				/* Macros to make printk easier */
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Macros to make printk easier */
+/*@{*/
+
+/**
+ * Error output.
+ *
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
 #define DRM_ERROR(fmt, arg...) \
 	printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
+
+/**
+ * Memory error output.
+ *
+ * \param area memory area where the error occurred.
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
 #define DRM_MEM_ERROR(area, fmt, arg...) \
 	printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
 	       DRM(mem_stats)[area].name , ##arg)
 #define DRM_INFO(fmt, arg...)  printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
 
+/**
+ * Debug output.
+ * 
+ * \param fmt printf() like format string.
+ * \param arg arguments
+ */
 #if DRM_DEBUG_CODE
 #define DRM_DEBUG(fmt, arg...)						\
 	do {								\
@@ -224,7 +265,13 @@
    len += sprintf(&buf[len], fmt , ##arg);				\
    if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }
 
-				/* Mapping helper macros */
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Mapping helper macros */
+/*@{*/
+
 #define DRM_IOREMAP(map, dev)							\
 	(map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) )
 
@@ -237,6 +284,15 @@
 			DRM(ioremapfree)( (map)->handle, (map)->size, (dev) );	\
 	} while (0)
 
+/**
+ * Find mapping.
+ *
+ * \param _map matching mapping if found, untouched otherwise.
+ * \param _o offset.
+ *
+ * Expects the existence of a local variable named \p dev pointing to the
+ * drm_device structure.
+ */
 #define DRM_FIND_MAP(_map, _o)								\
 do {											\
 	struct list_head *_list;							\
@@ -249,9 +305,21 @@
  		}									\
 	}										\
 } while(0)
+
+/**
+ * Drop mapping.
+ *
+ * \sa #DRM_FIND_MAP.
+ */
 #define DRM_DROP_MAP(_map)
 
-				/* Internal types and structures */
+/*@}*/
+
+
+/***********************************************************************/
+/** \name Internal types and structures */
+/*@{*/
+
 #define DRM_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
 #define DRM_MIN(a,b) ((a)<(b)?(a):(b))
 #define DRM_MAX(a,b) ((a)>(b)?(a):(b))
@@ -260,10 +328,23 @@
 #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x))
 #define DRM_WAITCOUNT(dev,idx) DRM_BUFCOUNT(&dev->queuelist[idx]->waitlist)
 
+/**
+ * Get the private SAREA mapping.
+ *
+ * \param _dev DRM device.
+ * \param _ctx context number.
+ * \param _map output mapping.
+ */
 #define DRM_GET_PRIV_SAREA(_dev, _ctx, _map) do {	\
 	(_map) = (_dev)->context_sareas[_ctx];		\
 } while(0)
 
+/**
+ * Test that the hardware lock is held by the caller, returning otherwise.
+ *
+ * \param dev DRM device.
+ * \param filp file pointer of the caller.
+ */
 #define LOCK_TEST_WITH_RETURN( dev, filp )				\
 do {									\
 	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||		\
@@ -274,7 +355,14 @@
 	}								\
 } while (0)
 
-
+/**
+ * Ioctl function type.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg argument.
+ */
 typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg );
 
@@ -290,8 +378,7 @@
 } drm_ioctl_desc_t;
 
 typedef struct drm_devstate {
-	pid_t		  owner;	/* X server pid holding x_lock */
-
+	pid_t		  owner;	/**< X server pid holding x_lock */
 } drm_devstate_t;
 
 typedef struct drm_magic_entry {
@@ -311,21 +398,24 @@
 	pid_t		      pid;
 } drm_vma_entry_t;
 
+/**
+ * DMA buffer.
+ */
 typedef struct drm_buf {
-	int		  idx;	       /* Index into master buflist	     */
-	int		  total;       /* Buffer size			     */
-	int		  order;       /* log-base-2(total)		     */
-	int		  used;	       /* Amount of buffer in use (for DMA)  */
-	unsigned long	  offset;      /* Byte offset (used internally)	     */
-	void		  *address;    /* Address of buffer		     */
-	unsigned long	  bus_address; /* Bus address of buffer		     */
-	struct drm_buf	  *next;       /* Kernel-only: used for free list    */
-	__volatile__ int  waiting;     /* On kernel DMA queue		     */
-	__volatile__ int  pending;     /* On hardware DMA queue		     */
-	wait_queue_head_t dma_wait;    /* Processes waiting		     */
-	struct file       *filp;       /* Pointer to holding file descr	     */
-	int		  context;     /* Kernel queue for this buffer	     */
-	int		  while_locked;/* Dispatch this buffer while locked  */
+	int		  idx;	       /**< Index into master buflist */
+	int		  total;       /**< Buffer size */
+	int		  order;       /**< log-base-2(total) */
+	int		  used;	       /**< Amount of buffer in use (for DMA) */
+	unsigned long	  offset;      /**< Byte offset (used internally) */
+	void		  *address;    /**< Address of buffer */
+	unsigned long	  bus_address; /**< Bus address of buffer */
+	struct drm_buf	  *next;       /**< Kernel-only: used for free list */
+	__volatile__ int  waiting;     /**< On kernel DMA queue */
+	__volatile__ int  pending;     /**< On hardware DMA queue */
+	wait_queue_head_t dma_wait;    /**< Processes waiting */
+	struct file       *filp;       /**< Pointer to holding file descr */
+	int		  context;     /**< Kernel queue for this buffer */
+	int		  while_locked;/**< Dispatch this buffer while locked */
 	enum {
 		DRM_LIST_NONE	 = 0,
 		DRM_LIST_FREE	 = 1,
@@ -333,41 +423,43 @@
 		DRM_LIST_PEND	 = 3,
 		DRM_LIST_PRIO	 = 4,
 		DRM_LIST_RECLAIM = 5
-	}		  list;	       /* Which list we're on		     */
-
+	}		  list;	       /**< Which list we're on */
 
-	int		  dev_priv_size; /* Size of buffer private stoarge   */
-	void		  *dev_private;  /* Per-buffer private storage       */
+	int		  dev_priv_size; /**< Size of buffer private storage */
+	void		  *dev_private;  /**< Per-buffer private storage */
 } drm_buf_t;
 
 
-				/* bufs is one longer than it has to be */
+/** bufs is one longer than it has to be */
 typedef struct drm_waitlist {
-	int		  count;	/* Number of possible buffers	   */
-	drm_buf_t	  **bufs;	/* List of pointers to buffers	   */
-	drm_buf_t	  **rp;		/* Read pointer			   */
-	drm_buf_t	  **wp;		/* Write pointer		   */
-	drm_buf_t	  **end;	/* End pointer			   */
+	int		  count;	/**< Number of possible buffers */
+	drm_buf_t	  **bufs;	/**< List of pointers to buffers */
+	drm_buf_t	  **rp;		/**< Read pointer */
+	drm_buf_t	  **wp;		/**< Write pointer */
+	drm_buf_t	  **end;	/**< End pointer */
 	spinlock_t	  read_lock;
 	spinlock_t	  write_lock;
 } drm_waitlist_t;
 
 typedef struct drm_freelist {
-	int		  initialized; /* Freelist in use		   */
-	atomic_t	  count;       /* Number of free buffers	   */
-	drm_buf_t	  *next;       /* End pointer			   */
-
-	wait_queue_head_t waiting;     /* Processes waiting on free bufs   */
-	int		  low_mark;    /* Low water mark		   */
-	int		  high_mark;   /* High water mark		   */
-	atomic_t	  wfh;	       /* If waiting for high mark	   */
+	int		  initialized; /**< Freelist in use */
+	atomic_t	  count;       /**< Number of free buffers */
+	drm_buf_t	  *next;       /**< End pointer */
+
+	wait_queue_head_t waiting;     /**< Processes waiting on free bufs */
+	int		  low_mark;    /**< Low water mark */
+	int		  high_mark;   /**< High water mark */
+	atomic_t	  wfh;	       /**< If waiting for high mark */
 	spinlock_t        lock;
 } drm_freelist_t;
 
+/**
+ * Buffer entry.  There is one of this for each buffer size order.
+ */
 typedef struct drm_buf_entry {
-	int		  buf_size;
-	int		  buf_count;
-	drm_buf_t	  *buflist;
+	int		  buf_size;	/**< size */
+	int		  buf_count;	/**< number of buffers */
+	drm_buf_t	  *buflist;	/**< buffer list */
 	int		  seg_count;
 	int		  page_order;
 	unsigned long	  *seglist;
@@ -375,11 +467,19 @@
 	drm_freelist_t	  freelist;
 } drm_buf_entry_t;
 
+/**
+ * Hardware lock.
+ *
+ * The lock structure is a simple cache-line aligned integer.  To avoid
+ * processor bus contention on a multiprocessor system, there should not be any
+ * other data stored in the same cache line.
+ */
 typedef struct drm_hw_lock {
-	__volatile__ unsigned int lock;
-	char			  padding[60]; /* Pad to cache line */
+	__volatile__ unsigned int lock;		/**< lock variable */
+	char			  padding[60];	/**< Pad to cache line */
 } drm_hw_lock_t;
 
+/** File private data */
 typedef struct drm_file {
 	int		  authenticated;
 	int		  minor;
@@ -394,69 +494,85 @@
 	unsigned long     lock_count;
 } drm_file_t;
 
-
+/** Wait queue */
 typedef struct drm_queue {
-	atomic_t	  use_count;	/* Outstanding uses (+1)	    */
-	atomic_t	  finalization;	/* Finalization in progress	    */
-	atomic_t	  block_count;	/* Count of processes waiting	    */
-	atomic_t	  block_read;	/* Queue blocked for reads	    */
-	wait_queue_head_t read_queue;	/* Processes waiting on block_read  */
-	atomic_t	  block_write;	/* Queue blocked for writes	    */
-	wait_queue_head_t write_queue;	/* Processes waiting on block_write */
+	atomic_t	  use_count;	/**< Outstanding uses (+1) */
+	atomic_t	  finalization;	/**< Finalization in progress */
+	atomic_t	  block_count;	/**< Count of processes waiting */
+	atomic_t	  block_read;	/**< Queue blocked for reads */
+	wait_queue_head_t read_queue;	/**< Processes waiting on block_read */
+	atomic_t	  block_write;	/**< Queue blocked for writes */
+	wait_queue_head_t write_queue;	/**< Processes waiting on block_write */
 #if 1
-	atomic_t	  total_queued;	/* Total queued statistic	    */
-	atomic_t	  total_flushed;/* Total flushes statistic	    */
-	atomic_t	  total_locks;	/* Total locks statistics	    */
-#endif
-	drm_ctx_flags_t	  flags;	/* Context preserving and 2D-only   */
-	drm_waitlist_t	  waitlist;	/* Pending buffers		    */
-	wait_queue_head_t flush_queue;	/* Processes waiting until flush    */
+	atomic_t	  total_queued;	/**< Total queued statistic */
+	atomic_t	  total_flushed;/**< Total flushes statistic */
+	atomic_t	  total_locks;	/**< Total locks statistics */
+#endif
+	drm_ctx_flags_t	  flags;	/**< Context preserving and 2D-only */
+	drm_waitlist_t	  waitlist;	/**< Pending buffers */
+	wait_queue_head_t flush_queue;	/**< Processes waiting until flush */
 } drm_queue_t;
 
+/**
+ * Lock data.
+ */
 typedef struct drm_lock_data {
-	drm_hw_lock_t	  *hw_lock;	/* Hardware lock		   */
-	struct file       *filp;	/* File descr of lock holder (0=kernel)   */
-	wait_queue_head_t lock_queue;	/* Queue of blocked processes	   */
-	unsigned long	  lock_time;	/* Time of last lock in jiffies	   */
+	drm_hw_lock_t	  *hw_lock;	/**< Hardware lock */
+	struct file       *filp;	/**< File descr of lock holder (0=kernel) */
+	wait_queue_head_t lock_queue;	/**< Queue of blocked processes */
+	unsigned long	  lock_time;	/**< Time of last lock in jiffies */
 } drm_lock_data_t;
 
+/**
+ * DMA data.
+ */
 typedef struct drm_device_dma {
 
-	drm_buf_entry_t	  bufs[DRM_MAX_ORDER+1];
-	int		  buf_count;
-	drm_buf_t	  **buflist;	/* Vector of pointers info bufs	   */
+	drm_buf_entry_t	  bufs[DRM_MAX_ORDER+1];	/**< buffers, grouped by their size order */
+	int		  buf_count;	/**< total number of buffers */
+	drm_buf_t	  **buflist;	/**< Vector of pointers into drm_device_dma::bufs */
 	int		  seg_count;
-	int		  page_count;
-	unsigned long	  *pagelist;
+	int		  page_count;	/**< number of pages */
+	unsigned long	  *pagelist;	/**< page list */
 	unsigned long	  byte_count;
 	enum {
 		_DRM_DMA_USE_AGP = 0x01,
 		_DRM_DMA_USE_SG  = 0x02
 	} flags;
 
-				/* DMA support */
-	drm_buf_t	  *this_buffer;	/* Buffer being sent		   */
-	drm_buf_t	  *next_buffer; /* Selected buffer to send	   */
-	drm_queue_t	  *next_queue;	/* Queue from which buffer selected*/
-	wait_queue_head_t waiting;	/* Processes waiting on free bufs  */
+	/** \name DMA support */
+	/*@{*/
+	drm_buf_t	  *this_buffer;	/**< Buffer being sent */
+	drm_buf_t	  *next_buffer; /**< Selected buffer to send */
+	drm_queue_t	  *next_queue;	/**< Queue from which buffer selected*/
+	wait_queue_head_t waiting;	/**< Processes waiting on free bufs */
+	/*@}*/
 } drm_device_dma_t;
 
 #if __REALLY_HAVE_AGP
+/** 
+ * AGP memory entry.  Stored as a doubly linked list.
+ */
 typedef struct drm_agp_mem {
-	unsigned long      handle;
-	struct agp_memory         *memory;
-	unsigned long      bound; /* address */
+	unsigned long      handle;	/**< handle */
+	struct agp_memory *memory;	
+	unsigned long      bound;	/**< address */
 	int                pages;
-	struct drm_agp_mem *prev;
-	struct drm_agp_mem *next;
+	struct drm_agp_mem *prev;	/**< previous entry */
+	struct drm_agp_mem *next;	/**< next entry */
 } drm_agp_mem_t;
 
+/**
+ * AGP data.
+ *
+ * \sa DRM(agp_init)() and drm_device::agp.
+ */
 typedef struct drm_agp_head {
-	struct agp_kern_info      agp_info;
-	drm_agp_mem_t      *memory;
-	unsigned long      mode;
-	int                enabled;
-	int                acquired;
+	struct agp_kern_info      agp_info;	/**< AGP device information */
+	drm_agp_mem_t      *memory;	/**< memory entries */
+	unsigned long      mode;	/**< AGP mode */
+	int                enabled;	/**< whether the AGP bus as been enabled */
+	int                acquired;	/**< whether the AGP device has been acquired */
 	unsigned long      base;
    	int 		   agp_mtrr;
 	int		   cant_use_aperture;
@@ -464,6 +580,9 @@
 } drm_agp_head_t;
 #endif
 
+/**
+ * Scatter-gather memory.
+ */
 typedef struct drm_sg_mem {
 	unsigned long   handle;
 	void            *virtual;
@@ -477,9 +596,12 @@
 	drm_hw_lock_t *lock;
 } drm_sigdata_t;
 
+/**
+ * Mappings list
+ */
 typedef struct drm_map_list {
-	struct list_head	head;
-	drm_map_t		*map;
+	struct list_head	head;	/**< list head */
+	drm_map_t		*map;	/**< mapping */
 } drm_map_list_t;
 
 typedef drm_map_t drm_local_map_t;
@@ -495,88 +617,108 @@
 
 #endif
 
+/**
+ * DRM device structure.
+ */
 typedef struct drm_device {
-	const char	  *name;	/* Simple driver name		   */
-	char		  *unique;	/* Unique identifier: e.g., busid  */
-	int		  unique_len;	/* Length of unique field	   */
-	dev_t		  device;	/* Device number for mknod	   */
-	char		  *devname;	/* For /proc/interrupts		   */
-
-	int		  blocked;	/* Blocked due to VC switch?	   */
-	struct proc_dir_entry *root;	/* Root for this device's entries  */
-
-				/* Locks */
-	spinlock_t	  count_lock;	/* For inuse, open_count, buf_use  */
-	struct semaphore  struct_sem;	/* For others			   */
-
-				/* Usage Counters */
-	int		  open_count;	/* Outstanding files open	   */
-	atomic_t	  ioctl_count;	/* Outstanding IOCTLs pending	   */
-	atomic_t	  vma_count;	/* Outstanding vma areas open	   */
-	int		  buf_use;	/* Buffers in use -- cannot alloc  */
-	atomic_t	  buf_alloc;	/* Buffer allocation in progress   */
+	const char	  *name;	/**< Simple driver name */
+	char		  *unique;	/**< Unique identifier: e.g., busid */
+	int		  unique_len;	/**< Length of unique field */
+	dev_t		  device;	/**< Device number for mknod */
+	char		  *devname;	/**< For /proc/interrupts */
+
+	int		  blocked;	/**< Blocked due to VC switch? */
+	struct proc_dir_entry *root;	/**< Root for this device's entries */
+
+	/** \name Locks */
+	/*@{*/
+	spinlock_t	  count_lock;	/**< For inuse, drm_device::open_count, drm_device::buf_use */
+	struct semaphore  struct_sem;	/**< For others */
+	/*@}*/
+
+	/** \name Usage Counters */
+	/*@{*/
+	int		  open_count;	/**< Outstanding files open */
+	atomic_t	  ioctl_count;	/**< Outstanding IOCTLs pending */
+	atomic_t	  vma_count;	/**< Outstanding vma areas open */
+	int		  buf_use;	/**< Buffers in use -- cannot alloc */
+	atomic_t	  buf_alloc;	/**< Buffer allocation in progress */
+	/*@}*/
 
-				/* Performance counters */
+	/** \name Performance counters */
+	/*@{*/
 	unsigned long     counters;
 	drm_stat_type_t   types[15];
 	atomic_t          counts[15];
+	/*@}*/
 
-				/* Authentication */
-	drm_file_t	  *file_first;
-	drm_file_t	  *file_last;
-	drm_magic_head_t  magiclist[DRM_HASH_SIZE];
-
-				/* Memory management */
-	drm_map_list_t	  *maplist;	/* Linked list of regions	   */
+	/** \name Authentication */
+	/*@{*/
+	drm_file_t	  *file_first;	/**< file list head */
+	drm_file_t	  *file_last;	/**< file list tail */
+	drm_magic_head_t  magiclist[DRM_HASH_SIZE];	/**< magic hash table */
+	/*@}*/
+
+	/** \name Memory management */
+	/*@{*/
+	drm_map_list_t	  *maplist;	/**< Linked list of regions */
+	int		  map_count;	/**< Number of mappable regions */
 
-	drm_map_t	  **context_sareas;
+	drm_map_t	  **context_sareas; /**< per-context SAREA's */
 	int		  max_context;
 
-	drm_vma_entry_t	  *vmalist;	/* List of vmas (for debugging)	   */
-	drm_lock_data_t	  lock;		/* Information on hardware lock	   */
-
-				/* DMA queues (contexts) */
-	int		  queue_count;	/* Number of active DMA queues	   */
-	int		  queue_reserved; /* Number of reserved DMA queues */
-	int		  queue_slots;	/* Actual length of queuelist	   */
-	drm_queue_t	  **queuelist;	/* Vector of pointers to DMA queues */
-	drm_device_dma_t  *dma;		/* Optional pointer for DMA support */
-
-				/* Context support */
-	int		  irq;		/* Interrupt used by board	   */
-	__volatile__ long context_flag;	/* Context swapping flag	   */
-	__volatile__ long interrupt_flag; /* Interruption handler flag	   */
-	__volatile__ long dma_flag;	/* DMA dispatch flag		   */
-	struct timer_list timer;	/* Timer for delaying ctx switch   */
-	wait_queue_head_t context_wait; /* Processes waiting on ctx switch */
-	int		  last_checked;	/* Last context checked for DMA	   */
-	int		  last_context;	/* Last current context		   */
-	unsigned long	  last_switch;	/* jiffies at last context switch  */
-	struct work_struct		  work;
+	drm_vma_entry_t	  *vmalist;	/**< List of vmas (for debugging) */
+	drm_lock_data_t	  lock;		/**< Information on hardware lock */
+	/*@}*/
+
+	/** \name DMA queues (contexts) */
+	/*@{*/
+	int		  queue_count;	/**< Number of active DMA queues */
+	int		  queue_reserved; /**< Number of reserved DMA queues */
+	int		  queue_slots;	/**< Actual length of queuelist */
+	drm_queue_t	  **queuelist;	/**< Vector of pointers to DMA queues */
+	drm_device_dma_t  *dma;		/**< Optional pointer for DMA support */
+	/*@}*/
+
+	/** \name Context support */
+	/*@{*/
+	int		  irq;		/**< Interrupt used by board */
+	__volatile__ long context_flag;	/**< Context swapping flag */
+	__volatile__ long interrupt_flag; /**< Interruption handler flag */
+	__volatile__ long dma_flag;	/**< DMA dispatch flag */
+	struct timer_list timer;	/**< Timer for delaying ctx switch */
+	wait_queue_head_t context_wait; /**< Processes waiting on ctx switch */
+	int		  last_checked;	/**< Last context checked for DMA */
+	int		  last_context;	/**< Last current context */
+	unsigned long	  last_switch;	/**< jiffies at last context switch */
+	/*@}*/
+	
+	struct work_struct	work;
+	/** \name VBLANK IRQ support */
+	/*@{*/
 #if __HAVE_VBL_IRQ
-   	wait_queue_head_t vbl_queue;
+   	wait_queue_head_t vbl_queue;	/**< VBLANK wait queue */
    	atomic_t          vbl_received;
 	spinlock_t        vbl_lock;
-	drm_vbl_sig_t     vbl_sigs;
+	drm_vbl_sig_t     vbl_sigs;	/**< signal list to send on VBLANK */
 	unsigned int      vbl_pending;
 #endif
+	/*@}*/
 	cycles_t	  ctx_start;
 	cycles_t	  lck_start;
 
-				/* Callback to X server for context switch
-				   and for heavy-handed reset. */
-	char		  buf[DRM_BSZ]; /* Output buffer		   */
-	char		  *buf_rp;	/* Read pointer			   */
-	char		  *buf_wp;	/* Write pointer		   */
-	char		  *buf_end;	/* End pointer			   */
-	struct fasync_struct *buf_async;/* Processes waiting for SIGIO	   */
-	wait_queue_head_t buf_readers;	/* Processes waiting to read	   */
-	wait_queue_head_t buf_writers;	/* Processes waiting to ctx switch */
+	char		  buf[DRM_BSZ]; /**< Output buffer */
+	char		  *buf_rp;	/**< Read pointer */
+	char		  *buf_wp;	/**< Write pointer */
+	char		  *buf_end;	/**< End pointer */
+	struct fasync_struct *buf_async;/**< Processes waiting for SIGIO */
+	wait_queue_head_t buf_readers;	/**< Processes waiting to read */
+	wait_queue_head_t buf_writers;	/**< Processes waiting to ctx switch */
 
 #if __REALLY_HAVE_AGP
-	drm_agp_head_t    *agp;
+	drm_agp_head_t    *agp;	/**< AGP data */
 #endif
-	struct pci_dev *pdev;
+	struct pci_dev *pdev;		/**< PCI device structure */
 #ifdef __alpha__
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3)
 	struct pci_controler *hose;
@@ -584,17 +726,17 @@
 	struct pci_controller *hose;
 #endif
 #endif
-	drm_sg_mem_t      *sg;  /* Scatter gather memory */
-	unsigned long     *ctx_bitmap;
-	void		  *dev_private;
-	drm_sigdata_t     sigdata; /* For block_all_signals */
+	drm_sg_mem_t      *sg;  /**< Scatter gather memory */
+	unsigned long     *ctx_bitmap;	/**< context bitmap */
+	void		  *dev_private; /**< device private data */
+	drm_sigdata_t     sigdata; /**< For block_all_signals */
 	sigset_t          sigmask;
 } drm_device_t;
 
 
-/* ================================================================
- * Internal function definitions
- */
+/******************************************************************/
+/** \name Internal function definitions */
+/*@{*/
 
 				/* Misc. support (drm_init.h) */
 extern int	     DRM(flags);
@@ -653,7 +795,8 @@
 extern void	     DRM(free_pages)(unsigned long address, int order,
 				     int area);
 extern void	     *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev);
-extern void	     *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev);
+extern void	     *DRM(ioremap_nocache)(unsigned long offset, unsigned long size,
+					   drm_device_t *dev);
 extern void	     DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);
 
 #if __REALLY_HAVE_AGP
@@ -841,6 +984,8 @@
 extern int            DRM(ati_pcigart_cleanup)(drm_device_t *dev,
 					       unsigned long addr,
 					       dma_addr_t bus_addr);
+
+/*@}*/
 
 #endif /* __KERNEL__ */
 #endif
diff -Nru a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h
--- a/drivers/char/drm/drm_agpsupport.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm_agpsupport.h	Fri Jul 11 01:25:28 2003
@@ -1,6 +1,12 @@
-/* drm_agpsupport.h -- DRM support for AGP/GART backend -*- linux-c -*-
- * Created: Mon Dec 13 09:56:45 1999 by faith@precisioninsight.com
- *
+/**
+ * \file drm_agpsupport.h 
+ * DRM support for AGP/GART backend
+ *    
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
@@ -23,10 +29,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Author:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
@@ -34,17 +36,33 @@
 
 #if __REALLY_HAVE_AGP
 
+
 #define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
 #define DRM_AGP_PUT inter_module_put("drm_agp")
 
+/**
+ * Pointer to the drm_agp_t structure made available by the agpgart module.
+ */
 static const drm_agp_t *drm_agp = NULL;
 
+/**
+ * AGP information ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a (output) drm_agp_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been initialized and acquired and fills in the
+ * drm_agp_info structure with the information in drm_agp_head::agp_info.
+ */
 int DRM(agp_info)(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
 	drm_device_t	 *dev	 = priv->dev;
-	struct agp_kern_info *kern;
+	struct agp_kern_info    *kern;
 	drm_agp_info_t   info;
 
 	if (!dev->agp || !dev->agp->acquired || !drm_agp->copy_info)
@@ -66,6 +84,18 @@
 	return 0;
 }
 
+/**
+ * Acquire the AGP device (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or a negative number on failure. 
+ *
+ * Verifies the AGP device hasn't been acquired before and calls
+ * drm_agp->acquire().
+ */
 int DRM(agp_acquire)(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -80,6 +110,17 @@
 	return 0;
 }
 
+/**
+ * Release the AGP device (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired and calls drm_agp->release().
+ */
 int DRM(agp_release)(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -94,11 +135,28 @@
 
 }
 
+/**
+ * Release the AGP device.
+ *
+ * Calls drm_agp->release().
+ */
 void DRM(agp_do_release)(void)
 {
 	if (drm_agp->release) drm_agp->release();
 }
 
+/**
+ * Enable the AGP bus.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_mode structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device has been acquired but not enabled, and calls
+ * drm_agp->enable().
+ */
 int DRM(agp_enable)(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -119,6 +177,18 @@
 	return 0;
 }
 
+/**
+ * Allocate AGP memory.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ * 
+ * Verifies the AGP device is present and has been acquired, allocates the
+ * memory via alloc_agp() and creates a drm_agp_mem entry for it.
+ */
 int DRM(agp_alloc)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
 {
@@ -146,7 +216,7 @@
 		return -ENOMEM;
 	}
 
-	entry->handle    = (unsigned long)memory->key;
+	entry->handle    = (unsigned long)memory->key + 1;
 	entry->memory    = memory;
 	entry->bound     = 0;
 	entry->pages     = pages;
@@ -168,6 +238,15 @@
 	return 0;
 }
 
+/**
+ * Search for the AGP memory entry associated with a handle.
+ *
+ * \param dev DRM device structure.
+ * \param handle AGP memory handle.
+ * \return pointer to the drm_agp_mem structure associated with \p handle.
+ * 
+ * Walks through drm_agp_head::memory until finding a matching handle.
+ */
 static drm_agp_mem_t *DRM(agp_lookup_entry)(drm_device_t *dev,
 					    unsigned long handle)
 {
@@ -179,6 +258,18 @@
 	return NULL;
 }
 
+/**
+ * Unbind AGP memory from the GATT (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and acquired, looks-up the AGP memory
+ * entry and passes it to the unbind_agp() function.
+ */
 int DRM(agp_unbind)(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -200,6 +291,19 @@
 	return ret;
 }
 
+/**
+ * Bind AGP memory into the GATT (ioctl)
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_binding structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and that no memory
+ * is currently bound into the GATT. Looks-up the AGP memory entry and passes
+ * it to bind_agp() function.
+ */
 int DRM(agp_bind)(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
@@ -225,6 +329,20 @@
 	return 0;
 }
 
+/**
+ * Free AGP memory (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_agp_buffer structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the AGP device is present and has been acquired and looks up the
+ * AGP memory entry. If the memory it's currently bound, unbind it via
+ * unbind_agp(). Frees it via free_agp() as well as the entry itself
+ * and unlinks from the doubly linked list it's inserted in.
+ */
 int DRM(agp_free)(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
@@ -248,6 +366,15 @@
 	return 0;
 }
 
+/**
+ * Initialize the AGP resources.
+ *
+ * \return pointer to a drm_agp_head structure.
+ *
+ * Gets the drm_agp_t structure which is made available by the agpgart module
+ * via the inter_module_* functions. Creates and initializes a drm_agp_head
+ * structure.
+ */
 drm_agp_head_t *DRM(agp_init)(void)
 {
 	drm_agp_head_t *head         = NULL;
@@ -274,18 +401,25 @@
 	return head;
 }
 
+/**
+ * Free the AGP resources.
+ *
+ * Releases the pointer in ::drm_agp.
+ */
 void DRM(agp_uninit)(void)
 {
 	DRM_AGP_PUT;
 	drm_agp = NULL;
 }
 
+/** Calls drm_agp->allocate_memory() */
 struct agp_memory *DRM(agp_allocate_memory)(size_t pages, u32 type)
 {
 	if (!drm_agp->allocate_memory) return NULL;
 	return drm_agp->allocate_memory(pages, type);
 }
 
+/** Calls drm_agp->free_memory() */
 int DRM(agp_free_memory)(struct agp_memory *handle)
 {
 	if (!handle || !drm_agp->free_memory) return 0;
@@ -293,12 +427,14 @@
 	return 1;
 }
 
+/** Calls drm_agp->bind_memory() */
 int DRM(agp_bind_memory)(struct agp_memory *handle, off_t start)
 {
 	if (!handle || !drm_agp->bind_memory) return -EINVAL;
 	return drm_agp->bind_memory(handle, start);
 }
 
+/** Calls drm_agp->unbind_memory() */
 int DRM(agp_unbind_memory)(struct agp_memory *handle)
 {
 	if (!handle || !drm_agp->unbind_memory) return -EINVAL;
diff -Nru a/drivers/char/drm/drm_auth.h b/drivers/char/drm/drm_auth.h
--- a/drivers/char/drm/drm_auth.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_auth.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,12 @@
-/* drm_auth.h -- IOCTLs for authentication -*- linux-c -*-
+/**
+ * \file drm_auth.h 
+ * IOCTLs for authentication
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,19 +31,34 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 
+/**
+ * Generate a hash key from a magic.
+ *
+ * \param magic magic.
+ * \return hash key.
+ *
+ * The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be
+ * a power of 2.
+ */
 static int DRM(hash_magic)(drm_magic_t magic)
 {
 	return magic & (DRM_HASH_SIZE-1);
 }
 
+/**
+ * Find the file with the given magic number.
+ *
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches in drm_device::magiclist within all files with the same hash key
+ * the one with matching magic number, while holding the drm_device::struct_sem
+ * lock.
+ */
 static drm_file_t *DRM(find_file)(drm_device_t *dev, drm_magic_t magic)
 {
 	drm_file_t	  *retval = NULL;
@@ -53,6 +76,17 @@
 	return retval;
 }
 
+/**
+ * Adds a magic number.
+ * 
+ * \param dev DRM device.
+ * \param priv file private data.
+ * \param magic magic number.
+ *
+ * Creates a drm_magic_entry structure and appends to the linked list
+ * associated the magic number hash key in drm_device::magiclist, while holding
+ * the drm_device::struct_sem lock.
+ */
 int DRM(add_magic)(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
 {
 	int		  hash;
@@ -81,12 +115,22 @@
 	return 0;
 }
 
+/**
+ * Remove a magic number.
+ * 
+ * \param dev DRM device.
+ * \param magic magic number.
+ *
+ * Searches and unlinks the entry in drm_device::magiclist with the magic
+ * number hash key, while holding the drm_device::struct_sem lock.
+ */
 int DRM(remove_magic)(drm_device_t *dev, drm_magic_t magic)
 {
 	drm_magic_entry_t *prev = NULL;
 	drm_magic_entry_t *pt;
 	int		  hash;
 
+
 	DRM_DEBUG("%d\n", magic);
 	hash = DRM(hash_magic)(magic);
 
@@ -113,6 +157,19 @@
 	return -EINVAL;
 }
 
+/**
+ * Get a unique magic number (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a resulting drm_auth structure.
+ * \return zero on success, or a negative number on failure.
+ *
+ * If there is a magic number in drm_file::magic then use it, otherwise
+ * searches an unique non-zero magic number and add it associating it with \p
+ * filp.
+ */
 int DRM(getmagic)(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
@@ -142,6 +199,17 @@
 	return 0;
 }
 
+/**
+ * Authenticate with a magic.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_auth structure.
+ * \return zero if authentication successed, or a negative number otherwise.
+ *
+ * Checks if \p filp is associated with the magic number passed in \arg.
+ */
 int DRM(authmagic)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
 {
diff -Nru a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h
--- a/drivers/char/drm/drm_bufs.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm_bufs.h	Fri Jul 11 01:25:28 2003
@@ -1,4 +1,12 @@
-/* drm_bufs.h -- Generic buffer template -*- linux-c -*-
+/**
+ * \file drm_bufs.h 
+ * Generic buffer template
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
  *
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,10 +31,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/vmalloc.h>
@@ -51,8 +55,15 @@
 #endif
 #endif
 
-/*
- * Compute order.  Can be made faster.
+
+/**
+ * Compute size order.  Returns the exponent of the smaller power of two which
+ * is greater or equal to given number.
+ * 
+ * \param size size.
+ * \return order.
+ *
+ * \todo Can be made faster.
  */
 int DRM(order)( unsigned long size )
 {
@@ -67,6 +78,19 @@
 	return order;
 }
 
+/**
+ * Ioctl to specify a range of memory that is available for mapping by a non-root process.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_map structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Adjusts the memory offset to its absolute value according to the mapping
+ * type.  Adds the map to the map list drm_device::maplist. Adds MTRR's where
+ * applicable and if supported by the kernel.
+ */
 int DRM(addmap)( struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg )
 {
@@ -186,10 +210,22 @@
 }
 
 
-/* Remove a map private from list and deallocate resources if the mapping
+/**
+ * Remove a map private from list and deallocate resources if the mapping
  * isn't in use.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_map_t structure.
+ * \return zero on success or a negative value on error.
+ *
+ * Searches the map on drm_device::maplist, removes it from the list, see if
+ * its being used, and free any associate resource (such as MTRR's) if it's not
+ * being on use.
+ *
+ * \sa addmap().
  */
-
 int DRM(rmmap)(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
@@ -262,7 +298,13 @@
 
 #if __HAVE_DMA
 
-
+/**
+ * Cleanup after an error on one of the addbufs() functions.
+ *
+ * \param entry buffer entry where the error occurred.
+ *
+ * Frees any pages and buffers associated with the given entry.
+ */
 static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
 {
 	int i;
@@ -305,6 +347,19 @@
 }
 
 #if __REALLY_HAVE_AGP
+/**
+ * Add AGP buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_desc_t request.
+ * \return zero on success or a negative number on failure.
+ * 
+ * After some sanity checks creates a drm_buf structure for each buffer and
+ * reallocates the buffer list of the same size order to accommodate the new
+ * buffers.
+ */
 int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg )
 {
@@ -884,6 +939,20 @@
 }
 #endif /* __HAVE_SG */
 
+/**
+ * Add buffers for DMA transfers (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_desc_t request.
+ * \return zero on success or a negative number on failure.
+ *
+ * According with the memory type specified in drm_buf_desc::flags and the
+ * build options, it dispatches the call either to addbufs_agp(),
+ * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent
+ * PCI memory respectively.
+ */
 int DRM(addbufs)( struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg )
 {
@@ -910,6 +979,24 @@
 #endif
 }
 
+
+/**
+ * Get information about the buffer mappings.
+ *
+ * This was originally mean for debugging purposes, or by a sophisticated
+ * client library to determine how best to use the available buffers (e.g.,
+ * large buffers can be used for image transfer).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_info structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Increments drm_device::buf_use while holding the drm_device::count_lock
+ * lock, preventing of allocating more buffers after this call. Information
+ * about each requested buffer is then copied into user space.
+ */
 int DRM(infobufs)( struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg )
 {
@@ -981,6 +1068,20 @@
 	return 0;
 }
 
+/**
+ * Specifies a low and high water mark for buffer allocation
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg a pointer to a drm_buf_desc structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies that the size order is bounded between the admissible orders and
+ * updates the respective drm_device_dma::bufs entry low and high water mark.
+ *
+ * \note This ioctl is deprecated and mostly never used.
+ */
 int DRM(markbufs)( struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg )
 {
@@ -1015,6 +1116,18 @@
 	return 0;
 }
 
+/**
+ * Unreserve the buffers in list, previously reserved using drmDMA. 
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_free structure.
+ * \return zero on success or a negative number on failure.
+ * 
+ * Calls free_buffer() for each used buffer.
+ * This function is primarily used for debugging.
+ */
 int DRM(freebufs)( struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg )
 {
@@ -1056,6 +1169,19 @@
 	return 0;
 }
 
+/**
+ * Maps all of the DMA buffers into client-virtual space (ioctl).
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg pointer to a drm_buf_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Maps the AGP or SG buffer region with do_mmap(), and copies information
+ * about each buffer into user space. The PCI buffers are already mapped on the
+ * addbufs_pci() call.
+ */
 int DRM(mapbufs)( struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg )
 {
diff -Nru a/drivers/char/drm/drm_context.h b/drivers/char/drm/drm_context.h
--- a/drivers/char/drm/drm_context.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm_context.h	Fri Jul 11 01:25:28 2003
@@ -1,4 +1,12 @@
-/* drm_context.h -- IOCTLs for generic contexts -*- linux-c -*-
+/**
+ * \file drm_context.h 
+ * IOCTLs for generic contexts
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Fri Nov 24 18:31:37 2000 by gareth@valinux.com
  *
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,10 +31,9 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * ChangeLog:
  *  2001-11-16	Torsten Duwe <duwe@caldera.de>
  *		added context constructor/destructor hooks,
@@ -40,10 +47,20 @@
 #endif
 
 
-/* ================================================================
- * Context bitmap support
- */
+/******************************************************************/
+/** \name Context bitmap support */
+/*@{*/
 
+/**
+ * Free a handle from the context bitmap.
+ *
+ * \param dev DRM device.
+ * \param ctx_handle context handle.
+ *
+ * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
+ * in drm_device::context_sareas, while holding the drm_device::struct_sem
+ * lock.
+ */
 void DRM(ctxbitmap_free)( drm_device_t *dev, int ctx_handle )
 {
 	if ( ctx_handle < 0 ) goto failed;
@@ -62,6 +79,16 @@
        	return;
 }
 
+/** 
+ * Context bitmap allocation.
+ *
+ * \param dev DRM device.
+ * \return (non-negative) context handle on success or a negative number on failure.
+ *
+ * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates
+ * drm_device::context_sareas to accommodate the new entry while holding the
+ * drm_device::struct_sem lock.
+ */
 int DRM(ctxbitmap_next)( drm_device_t *dev )
 {
 	int bit;
@@ -112,6 +139,14 @@
 	return -1;
 }
 
+/**
+ * Context bitmap initialization.
+ *
+ * \param dev DRM device.
+ *
+ * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding
+ * the drm_device::struct_sem lock.
+ */
 int DRM(ctxbitmap_init)( drm_device_t *dev )
 {
 	int i;
@@ -137,6 +172,14 @@
 	return 0;
 }
 
+/**
+ * Context bitmap cleanup.
+ *
+ * \param dev DRM device.
+ *
+ * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding
+ * the drm_device::struct_sem lock.
+ */
 void DRM(ctxbitmap_cleanup)( drm_device_t *dev )
 {
 	down(&dev->struct_sem);
@@ -148,10 +191,24 @@
 	up(&dev->struct_sem);
 }
 
-/* ================================================================
- * Per Context SAREA Support
- */
+/*@}*/
 
+/******************************************************************/
+/** \name Per Context SAREA Support */
+/*@{*/
+
+/**
+ * Get per-context SAREA.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Gets the map from drm_device::context_sareas with the handle specified and
+ * returns its handle.
+ */
 int DRM(getsareactx)(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -180,6 +237,18 @@
 	return 0;
 }
 
+/**
+ * Set per-context SAREA.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_priv_map structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the mapping specified in \p arg and update the entry in
+ * drm_device::context_sareas with it.
+ */
 int DRM(setsareactx)(struct inode *inode, struct file *filp,
 		     unsigned int cmd, unsigned long arg)
 {
@@ -218,10 +287,22 @@
 	return 0;
 }
 
-/* ================================================================
- * The actual DRM context handling routines
- */
+/*@}*/
 
+/******************************************************************/
+/** \name The actual DRM context handling routines */
+/*@{*/
+
+/**
+ * Switch context.
+ *
+ * \param dev DRM device.
+ * \param old old context handle.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to set drm_device::context_flag.
+ */
 int DRM(context_switch)( drm_device_t *dev, int old, int new )
 {
         if ( test_and_set_bit( 0, &dev->context_flag ) ) {
@@ -240,6 +321,17 @@
         return 0;
 }
 
+/**
+ * Complete context switch.
+ *
+ * \param dev DRM device.
+ * \param new new context handle.
+ * \return zero on success or a negative number on failure.
+ *
+ * Updates drm_device::last_context and drm_device::last_switch. Verifies the
+ * hardware lock is held, clears the drm_device::context_flag and wakes up
+ * drm_device::context_wait.
+ */
 int DRM(context_switch_complete)( drm_device_t *dev, int new )
 {
         dev->last_context = new;  /* PRE/POST: This is the _only_ writer. */
@@ -258,6 +350,15 @@
         return 0;
 }
 
+/**
+ * Reserve contexts.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx_res structure.
+ * \return zero on success or a negative number on failure.
+ */
 int DRM(resctx)( struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg )
 {
@@ -284,6 +385,17 @@
 	return 0;
 }
 
+/**
+ * Add context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Get a new handle for the context and copy to userspace.
+ */
 int DRM(addctx)( struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg )
 {
@@ -322,6 +434,15 @@
 	return 0;
 }
 
+/**
+ * Get context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ */
 int DRM(getctx)( struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg )
 {
@@ -338,6 +459,17 @@
 	return 0;
 }
 
+/**
+ * Switch context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch().
+ */
 int DRM(switchctx)( struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg )
 {
@@ -352,6 +484,17 @@
 	return DRM(context_switch)( dev, dev->last_context, ctx.handle );
 }
 
+/**
+ * New context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls context_switch_complete().
+ */
 int DRM(newctx)( struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg )
 {
@@ -368,6 +511,17 @@
 	return 0;
 }
 
+/**
+ * Remove context.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument pointing to a drm_ctx structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * If not the special kernel context, calls ctxbitmap_free() to free the specified context.
+ */
 int DRM(rmctx)( struct inode *inode, struct file *filp,
 		unsigned int cmd, unsigned long arg )
 {
@@ -392,3 +546,4 @@
 	return 0;
 }
 
+/*@}*/
diff -Nru a/drivers/char/drm/drm_dma.h b/drivers/char/drm/drm_dma.h
--- a/drivers/char/drm/drm_dma.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_dma.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,12 @@
-/* drm_dma.c -- DMA IOCTL and function support -*- linux-c -*-
+/**
+ * \file drm_dma.h 
+ * DMA IOCTL and function support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
  *
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,10 +31,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
@@ -51,6 +55,14 @@
 
 #if __HAVE_DMA
 
+/**
+ * Initialize the DMA data.
+ * 
+ * \param dev DRM device.
+ * \return zero on success or a negative value on failure.
+ *
+ * Allocate and initialize a drm_device_dma structure.
+ */
 int DRM(dma_setup)( drm_device_t *dev )
 {
 	int i;
@@ -67,6 +79,14 @@
 	return 0;
 }
 
+/**
+ * Cleanup the DMA resources.
+ *
+ * \param dev DRM device.
+ *
+ * Free all pages associated with DMA buffers, the buffers and pages lists, and
+ * finally the the drm_device::dma structure itself.
+ */
 void DRM(dma_takedown)(drm_device_t *dev)
 {
 	drm_device_dma_t  *dma = dev->dma;
@@ -128,7 +148,14 @@
 }
 
 
-
+/**
+ * Free a buffer.
+ *
+ * \param dev DRM device.
+ * \param buf buffer to free.
+ * 
+ * Resets the fields of \p buf.
+ */
 void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
 {
 	if (!buf) return;
@@ -154,6 +181,13 @@
 }
 
 #if !__HAVE_DMA_RECLAIM
+/**
+ * Reclaim the buffers.
+ *
+ * \param filp file pointer.
+ *
+ * Frees each buffer associated with \p filp not already on the hardware.
+ */
 void DRM(reclaim_buffers)( struct file *filp )
 {
 	drm_file_t    *priv   = filp->private_data;
@@ -185,6 +219,16 @@
 
 #if __HAVE_DMA_IRQ
 
+/**
+ * Install IRQ handler.
+ *
+ * \param dev DRM device.
+ * \param irq IRQ number.
+ *
+ * Initializes the IRQ related data, and setups drm_device::vbl_queue. Installs the handler, calling the driver
+ * \c DRM(driver_irq_preinstall)() and \c DRM(driver_irq_postinstall)() functions
+ * before and after the installation.
+ */
 int DRM(irq_install)( drm_device_t *dev, int irq )
 {
 	int ret;
@@ -250,6 +294,13 @@
 	return 0;
 }
 
+/**
+ * Uninstall the IRQ handler.
+ *
+ * \param dev DRM device.
+ *
+ * Calls the driver's \c DRM(driver_irq_uninstall)() function, and stops the irq.
+ */
 int DRM(irq_uninstall)( drm_device_t *dev )
 {
 	int irq;
@@ -271,6 +322,17 @@
 	return 0;
 }
 
+/**
+ * IRQ control ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_control structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Calls irq_install() or irq_uninstall() according to \p arg.
+ */
 int DRM(control)( struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg )
 {
@@ -293,6 +355,25 @@
 
 #if __HAVE_VBL_IRQ
 
+/**
+ * Wait for VBLANK.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param data user argument, pointing to a drm_wait_vblank structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Verifies the IRQ is installed. 
+ *
+ * If a signal is requested checks if this task has already scheduled the same signal
+ * for the same vblank sequence number - nothing to be done in
+ * that case. If the number of tasks waiting for the interrupt exceeds 100 the
+ * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
+ * task.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
 int DRM(wait_vblank)( DRM_IOCTL_ARGS )
 {
 	drm_file_t *priv = filp->private_data;
@@ -381,6 +462,15 @@
 	return ret;
 }
 
+/**
+ * Send the VBLANK signals.
+ *
+ * \param dev DRM device.
+ *
+ * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
+ *
+ * If a signal is not requested, then calls vblank_wait().
+ */
 void DRM(vbl_send_signals)( drm_device_t *dev )
 {
 	struct list_head *list, *tmp;
diff -Nru a/drivers/char/drm/drm_drawable.h b/drivers/char/drm/drm_drawable.h
--- a/drivers/char/drm/drm_drawable.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_drawable.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,12 @@
-/* drm_drawable.h -- IOCTLs for drawables -*- linux-c -*-
+/**
+ * \file drm_drawable.h 
+ * IOCTLs for drawables
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,14 +31,11 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 
+/** No-op. */
 int DRM(adddraw)(struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg)
 {
@@ -43,6 +48,7 @@
 	return 0;
 }
 
+/** No-op. */
 int DRM(rmdraw)(struct inode *inode, struct file *filp,
 		unsigned int cmd, unsigned long arg)
 {
diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
--- a/drivers/char/drm/drm_drv.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_drv.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,31 @@
-/* drm_drv.h -- Generic driver template -*- linux-c -*-
+/**
+ * \file drm_drv.h 
+ * Generic driver template
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ *
+ * To use this template, you must at least define the following (samples
+ * given for the MGA driver):
+ *
+ * \code
+ * #define DRIVER_AUTHOR	"VA Linux Systems, Inc."
+ *
+ * #define DRIVER_NAME		"mga"
+ * #define DRIVER_DESC		"Matrox G200/G400"
+ * #define DRIVER_DATE		"20001127"
+ *
+ * #define DRIVER_MAJOR		2
+ * #define DRIVER_MINOR		0
+ * #define DRIVER_PATCHLEVEL	2
+ *
+ * #define DRIVER_IOCTL_COUNT	DRM_ARRAY_SIZE( mga_ioctls )
+ *
+ * #define DRM(x)		mga_##x
+ * \endcode
+ */
+
+/*
  * Created: Thu Nov 23 03:10:50 2000 by gareth@valinux.com
  *
  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,29 +50,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * To use this template, you must at least define the following (samples
- * given for the MGA driver):
- *
- * #define DRIVER_AUTHOR	"VA Linux Systems, Inc."
- *
- * #define DRIVER_NAME		"mga"
- * #define DRIVER_DESC		"Matrox G200/G400"
- * #define DRIVER_DATE		"20001127"
- *
- * #define DRIVER_MAJOR		2
- * #define DRIVER_MINOR		0
- * #define DRIVER_PATCHLEVEL	2
- *
- * #define DRIVER_IOCTL_COUNT	DRM_ARRAY_SIZE( mga_ioctls )
- *
- * #define DRM(x)		mga_##x
  */
 
 #ifndef __MUST_HAVE_AGP
@@ -134,12 +138,13 @@
 #endif
 
 #ifndef MODULE
-/* DRM(options) is called by the kernel to parse command-line options
- * passed via the boot-loader (e.g., LILO).  It calls the insmod option
- * routine, drm_parse_drm.
- */
-/* Use an additional macro to avoid preprocessor troubles */
+/** Use an additional macro to avoid preprocessor troubles */
 #define DRM_OPTIONS_FUNC DRM(options)
+/**
+ * Called by the kernel to parse command-line options passed via the
+ * boot-loader (e.g., LILO).  It calls the insmod option routine,
+ * parse_options().
+ */
 static int __init DRM(options)( char *str )
 {
 	DRM(parse_options)( str );
@@ -150,7 +155,7 @@
 #undef DRM_OPTIONS_FUNC
 #endif
 
-/*
+/**
  * The default number of instances (minor numbers) to initialize.
  */
 #ifndef DRIVER_NUM_CARDS
@@ -163,6 +168,7 @@
 
 DRIVER_FOPS;
 
+/** Ioctl table */
 static drm_ioctl_desc_t		  DRM(ioctls)[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
@@ -348,7 +354,8 @@
 
 	DRM_DEBUG( "\n" );
 
-	/* The kernel's context could be created here, but is now created
+	/*
+	 * The kernel's context could be created here, but is now created
 	 * in drm_dma_enqueue.	This is more resource-efficient for
 	 * hardware that does not do DMA, but may mean that
 	 * drm_select_queue fails between the time the interrupt is
@@ -359,6 +366,15 @@
 }
 
 
+/**
+ * Take down the DRM device.
+ *
+ * \param dev DRM device structure.
+ *
+ * Frees every resource in \p dev.
+ *
+ * \sa drm_device and setup().
+ */
 static int DRM(takedown)( drm_device_t *dev )
 {
 	drm_magic_entry_t *pt, *next;
@@ -516,8 +532,12 @@
 	return 0;
 }
 
-/*
+/**
  * Figure out how many instances to initialize.
+ *
+ * \return number of cards found.
+ *
+ * Searches for every PCI card in \c DRIVER_CARD_LIST with matching vendor and device ids.
  */
 static int drm_count_cards(void)
 {
@@ -551,8 +571,18 @@
 	return num;
 }
 
-/* drm_init is called via init_module at module load time, or via
+/**
+ * Module initialization. Called via init_module at module load time, or via
  * linux/init/main.c (this is not currently supported).
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Allocates and initialize an array of drm_device structures, and attempts to
+ * initialize all available devices, using consecutive minors, registering the
+ * stubs and initializing the AGP device.
+ * 
+ * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
+ * after the initialization for driver customization.
  */
 static int __init drm_init( void )
 {
@@ -641,7 +671,12 @@
 	return 0;
 }
 
-/* drm_cleanup is called via cleanup_module at module unload time.
+/**
+ * Called via cleanup_module() at module unload time.
+ *
+ * Cleans up all DRM device, calling takedown().
+ * 
+ * \sa drm_init().
  */
 static void __exit drm_cleanup( void )
 {
@@ -694,6 +729,17 @@
 module_exit( drm_cleanup );
 
 
+/**
+ * Get version information
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_version structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Fills in the version information in \p arg.
+ */
 int DRM(version)( struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg )
 {
@@ -729,6 +775,17 @@
 	return 0;
 }
 
+/**
+ * Open file.
+ * 
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches the DRM device with the same minor number, calls open_helper(), and
+ * increments the device open count. If the open count was previous at zero,
+ * i.e., it's the first that the device is open, then calls setup().
+ */
 int DRM(open)( struct inode *inode, struct file *filp )
 {
 	drm_device_t *dev = NULL;
@@ -759,6 +816,18 @@
 	return retcode;
 }
 
+/**
+ * Release file.
+ *
+ * \param inode device inode
+ * \param filp file pointer.
+ * \return zero on success or a negative number on failure.
+ *
+ * If the hardware lock is held then free it, and take it again for the kernel
+ * context since it's necessary to reclaim buffers. Unlink the file private
+ * data from its list and free it. Decreases the open count and if it reaches
+ * zero calls takedown().
+ */
 int DRM(release)( struct inode *inode, struct file *filp )
 {
 	drm_file_t *priv = filp->private_data;
@@ -885,7 +954,17 @@
 	return retcode;
 }
 
-/* DRM(ioctl) is called whenever a process performs an ioctl on /dev/drm.
+/** 
+ * Called whenever a process performs an ioctl on /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ *
+ * Looks up the ioctl function in the ::ioctls table, checking for root
+ * previleges if so required, and dispatches to the respective function.
  */
 int DRM(ioctl)( struct inode *inode, struct file *filp,
 		unsigned int cmd, unsigned long arg )
@@ -926,6 +1005,17 @@
 	return retcode;
 }
 
+/** 
+ * Lock ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Add the current task to the lock wait queue, and attempt to take to lock.
+ */
 int DRM(lock)( struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg )
 {
@@ -1031,7 +1121,17 @@
         return ret;
 }
 
-
+/** 
+ * Unlock ioctl.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_lock structure.
+ * \return zero on success or negative number on failure.
+ *
+ * Transfer and free the lock.
+ */
 int DRM(unlock)( struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg )
 {
diff -Nru a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h
--- a/drivers/char/drm/drm_fops.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_fops.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,13 @@
-/* drm_fops.h -- File operations for DRM -*- linux-c -*-
+/**
+ * \file drm_fops.h 
+ * File operations for DRM
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Daryll Strauss <daryll@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,18 +32,23 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Daryll Strauss <daryll@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 #include <linux/poll.h>
 
-/* drm_open is called whenever a process opens /dev/drm. */
 
+/**
+ * Called whenever a process opens /dev/drm. 
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param dev device.
+ * \return zero on success or a negative number on failure.
+ * 
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
 int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
 {
 	int	     minor = minor(inode->i_rdev);
@@ -90,6 +104,7 @@
 	return 0;
 }
 
+/** No-op. */
 int DRM(flush)(struct file *filp)
 {
 	drm_file_t    *priv   = filp->private_data;
@@ -100,6 +115,7 @@
 	return 0;
 }
 
+/** No-op. */
 int DRM(fasync)(int fd, struct file *filp, int on)
 {
 	drm_file_t    *priv   = filp->private_data;
@@ -113,6 +129,7 @@
 }
 
 #if !__HAVE_DRIVER_FOPS_POLL
+/** No-op. */
 unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
 {
 	return 0;
@@ -121,6 +138,7 @@
 
 
 #if !__HAVE_DRIVER_FOPS_READ
+/** No-op. */
 ssize_t DRM(read)(struct file *filp, char *buf, size_t count, loff_t *off)
 {
 	return 0;
diff -Nru a/drivers/char/drm/drm_init.h b/drivers/char/drm/drm_init.h
--- a/drivers/char/drm/drm_init.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_init.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,12 @@
-/* drm_init.h -- Setup/Cleanup for DRM -*- linux-c -*-
+/**
+ * \file drm_init.h 
+ * Setup/Cleanup for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,22 +31,23 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 
+/** Debug flags.  Set by parse_option(). */
 #if 0
 int DRM(flags) = DRM_FLAG_DEBUG;
 #else
 int DRM(flags) = 0;
 #endif
 
-/* drm_parse_option parses a single option.  See description for
- * drm_parse_options for details.
+/**
+ * Parse a single option.
+ *
+ * \param s option string.
+ *
+ * \sa See parse_options() for details.
  */
 static void DRM(parse_option)(char *s)
 {
@@ -58,26 +67,33 @@
 	return;
 }
 
-/* drm_parse_options parse the insmod "drm_opts=" options, or the command-line
- * options passed to the kernel via LILO.  The grammar of the format is as
+/**
+ * Parse the insmod "drm_opts=" options, or the command-line
+ * options passed to the kernel via LILO.  
+ *
+ * \param s contains option_list without the 'drm_opts=' part.
+ *
+ * The grammar of the format is as
  * follows:
  *
+ * \code
  * drm		::= 'drm_opts=' option_list
  * option_list	::= option [ ';' option_list ]
  * option	::= 'device:' major
  *		|   'debug'
  *		|   'noctx'
  * major	::= INTEGER
+ * \endcode
  *
- * Note that 's' contains option_list without the 'drm_opts=' part.
- *
- * device=major,minor specifies the device number used for /dev/drm
- *	  if major == 0 then the misc device is used
- *	  if major == 0 and minor == 0 then dynamic misc allocation is used
- * debug=on specifies that debugging messages will be printk'd
- * debug=trace specifies that each function call will be logged via printk
- * debug=off turns off all debugging options
+ * - device=major,minor specifies the device number used for /dev/drm
+ *   - if major == 0 then the misc device is used
+ *   - if major == 0 and minor == 0 then dynamic misc allocation is used
+ * - debug=on specifies that debugging messages will be printk'd
+ * - debug=trace specifies that each function call will be logged via printk
+ * - debug=off turns off all debugging options
  *
+ * \todo Actually only the \e presence of the 'debug' option is currently
+ * checked.
  */
 
 void DRM(parse_options)(char *s)
@@ -95,8 +111,10 @@
 	}
 }
 
-/* drm_cpu_valid returns non-zero if the DRI will run on this CPU, and 0
- * otherwise.
+/**
+ * Check whether DRI will run on this CPU.
+ *
+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.
  */
 int DRM(cpu_valid)(void)
 {
diff -Nru a/drivers/char/drm/drm_ioctl.h b/drivers/char/drm/drm_ioctl.h
--- a/drivers/char/drm/drm_ioctl.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm_ioctl.h	Fri Jul 11 01:25:28 2003
@@ -1,4 +1,12 @@
-/* drm_ioctl.h -- IOCTL processing for DRM -*- linux-c -*-
+/**
+ * \file drm_ioctl.h 
+ * IOCTL processing for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Fri Jan  8 09:01:26 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,15 +31,22 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 
 
+/**
+ * Get interrupt from bus id.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_irq_busid structure.
+ * \return zero on success or a negative number on failure.
+ * 
+ * Finds the PCI device with the specified bus id and gets its IRQ number.
+ */
 int DRM(irq_busid)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
 {
@@ -84,6 +99,17 @@
 	return 0;
 }
 
+/**
+ * Get the bus id.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from drm_device::unique into user space.
+ */
 int DRM(getunique)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
 {
@@ -103,6 +129,18 @@
 	return 0;
 }
 
+/**
+ * Set the bus id.
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_unique structure.
+ * \return zero on success or a negative number on failure.
+ *
+ * Copies the bus id from userspace into drm_device::unique, and searches for
+ * the respective PCI device, updating drm_device::pdev.
+ */
 int DRM(setunique)(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
 {
@@ -180,6 +218,19 @@
 }
 
 
+/**
+ * Get a mapping information.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_map structure.
+ * 
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the mapping with the specified offset and copies its information
+ * into userspace
+ */
 int DRM(getmap)( struct inode *inode, struct file *filp,
 		 unsigned int cmd, unsigned long arg )
 {
@@ -226,6 +277,19 @@
 	return 0;
 }
 
+/**
+ * Get client information.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_client structure.
+ * 
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the client with the specified index and copies its information
+ * into userspace
+ */
 int DRM(getclient)( struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg )
 {
@@ -259,6 +323,16 @@
 	return 0;
 }
 
+/** 
+ * Get statistics information. 
+ * 
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_stats structure.
+ * 
+ * \return zero on success or a negative number on failure.
+ */
 int DRM(getstats)( struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg )
 {
diff -Nru a/drivers/char/drm/drm_lock.h b/drivers/char/drm/drm_lock.h
--- a/drivers/char/drm/drm_lock.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_lock.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,12 @@
-/* lock.c -- IOCTLs for locking -*- linux-c -*-
+/**
+ * \file drm_lock.h 
+ * IOCTLs for locking
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Tue Feb  2 08:37:54 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,14 +31,11 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 
+/** No-op ioctl. */
 int DRM(noop)(struct inode *inode, struct file *filp, unsigned int cmd,
 	       unsigned long arg)
 {
@@ -38,7 +43,15 @@
 	return 0;
 }
 
-
+/**
+ * Take the heavyweight lock.
+ *
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return one if the lock is held, or zero otherwise.
+ *
+ * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction.
+ */
 int DRM(lock_take)(__volatile__ unsigned int *lock, unsigned int context)
 {
 	unsigned int old, new, prev;
@@ -65,8 +78,18 @@
 	return 0;
 }
 
-/* This takes a lock forcibly and hands it to context.	Should ONLY be used
-   inside *_unlock to give lock to kernel before calling *_dma_schedule. */
+/**
+ * This takes a lock forcibly and hands it to context.	Should ONLY be used
+ * inside *_unlock to give lock to kernel before calling *_dma_schedule. 
+ * 
+ * \param dev DRM device.
+ * \param lock lock pointer.
+ * \param context locking context.
+ * \return always one.
+ *
+ * Resets the lock file pointer.
+ * Marks the lock as held by the given context, via the \p cmpxchg instruction.
+ */
 int DRM(lock_transfer)(drm_device_t *dev,
 		       __volatile__ unsigned int *lock, unsigned int context)
 {
@@ -81,6 +104,17 @@
 	return 1;
 }
 
+/**
+ * Free lock.
+ * 
+ * \param dev DRM device.
+ * \param lock lock.
+ * \param context context.
+ * 
+ * Resets the lock file pointer.
+ * Marks the lock as not held, via the \p cmpxchg instruction. Wakes any task
+ * waiting on the lock queue.
+ */
 int DRM(lock_free)(drm_device_t *dev,
 		   __volatile__ unsigned int *lock, unsigned int context)
 {
@@ -102,18 +136,17 @@
 	return 0;
 }
 
-/* If we get here, it means that the process has called DRM_IOCTL_LOCK
-   without calling DRM_IOCTL_UNLOCK.
-
-   If the lock is not held, then let the signal proceed as usual.
-
-   If the lock is held, then set the contended flag and keep the signal
-   blocked.
-
-
-   Return 1 if the signal should be delivered normally.
-   Return 0 if the signal should be blocked.  */
-
+/**
+ * If we get here, it means that the process has called DRM_IOCTL_LOCK
+ * without calling DRM_IOCTL_UNLOCK.
+ *
+ * If the lock is not held, then let the signal proceed as usual.  If the lock
+ * is held, then set the contended flag and keep the signal blocked.
+ *
+ * \param priv pointer to a drm_sigdata structure.
+ * \return one if the signal should be delivered normally, or zero if the
+ * signal should be blocked.
+ */
 int DRM(notifier)(void *priv)
 {
 	drm_sigdata_t *s = (drm_sigdata_t *)priv;
diff -Nru a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
--- a/drivers/char/drm/drm_memory.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm_memory.h	Fri Jul 11 01:25:28 2003
@@ -1,4 +1,12 @@
-/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
+/** 
+ * \file drm_memory.h 
+ * Memory management wrappers for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/* 
  * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,17 +31,14 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
 #include <linux/highmem.h>
 #include "drmP.h"
 
-/* Cut down version of drm_memory_debug.h, which used to be called
+/**
+ * Cut down version of drm_memory_debug.h, which used to be called
  * drm_memory.h.  If you want the debug functionality, change 0 to 1
  * below.
  */
@@ -188,22 +193,38 @@
 #if DEBUG_MEMORY
 #include "drm_memory_debug.h"
 #else
+
+/** No-op. */
 void DRM(mem_init)(void)
 {
 }
 
-/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
+/**
+ * Called when "/proc/dri/%dev%/mem" is read.
+ * 
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param len requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ *
+ * No-op. 
+ */
 int DRM(mem_info)(char *buf, char **start, off_t offset,
 		  int len, int *eof, void *data)
 {
 	return 0;
 }
 
+/** Wrapper around kmalloc() */
 void *DRM(alloc)(size_t size, int area)
 {
 	return kmalloc(size, GFP_KERNEL);
 }
 
+/** Wrapper around kmalloc() and kfree() */
 void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
 {
 	void *pt;
@@ -216,11 +237,21 @@
 	return pt;
 }
 
+/** Wrapper around kfree() */
 void DRM(free)(void *pt, size_t size, int area)
 {
 	kfree(pt);
 }
 
+/**
+ * Allocate pages.
+ *
+ * \param order size order.
+ * \param area memory area. (Not used.)
+ * \return page address on success, or zero on failure.
+ *
+ * Allocate and reserve free pages.
+ */
 unsigned long DRM(alloc_pages)(int order, int area)
 {
 	unsigned long address;
@@ -245,6 +276,15 @@
 	return address;
 }
 
+/**
+ * Free pages.
+ * 
+ * \param address address of the pages to free.
+ * \param order size order.
+ * \param area memory area. (Not used.)
+ *
+ * Unreserve and free pages allocated by alloc_pages().
+ */
 void DRM(free_pages)(unsigned long address, int order, int area)
 {
 	unsigned long bytes = PAGE_SIZE << order;
@@ -264,37 +304,44 @@
 	free_pages(address, order);
 }
 
+/** Wrapper around drm_ioremap() */
 void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
 	return drm_ioremap(offset, size, dev);
 }
 
+/** Wrapper around drm_ioremap_nocache() */
 void *DRM(ioremap_nocache)(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
 	return drm_ioremap_nocache(offset, size, dev);
 }
 
+/** Wrapper around drm_iounmap() */
 void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
 {
 	drm_ioremapfree(pt, size, dev);
 }
 
 #if __REALLY_HAVE_AGP
+/** Wrapper around agp_allocate_memory() */
 struct agp_memory *DRM(alloc_agp)(int pages, u32 type)
 {
 	return DRM(agp_allocate_memory)(pages, type);
 }
 
+/** Wrapper around agp_free_memory() */
 int DRM(free_agp)(struct agp_memory *handle, int pages)
 {
 	return DRM(agp_free_memory)(handle) ? 0 : -EINVAL;
 }
 
+/** Wrapper around agp_bind_memory() */
 int DRM(bind_agp)(struct agp_memory *handle, unsigned int start)
 {
 	return DRM(agp_bind_memory)(handle, start);
 }
 
+/** Wrapper around agp_unbind_memory() */
 int DRM(unbind_agp)(struct agp_memory *handle)
 {
 	return DRM(agp_unbind_memory)(handle);
diff -Nru a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
--- a/drivers/char/drm/drm_memory_debug.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm_memory_debug.h	Fri Jul 11 01:25:28 2003
@@ -1,6 +1,12 @@
-/* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
- * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
+/**
+ * \file drm_memory.h 
+ * Memory management wrappers for DRM.
  *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
@@ -23,10 +29,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
diff -Nru a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
--- a/drivers/char/drm/drm_os_linux.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_os_linux.h	Fri Jul 11 01:25:29 2003
@@ -1,35 +1,55 @@
+/**
+ * \file drm_os_linux.h
+ * OS abstraction macros.
+ */
+
 
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/delay.h>
 
+/** File pointer type */
 #define DRMFILE                         struct file *
+/** Ioctl arguments */
 #define DRM_IOCTL_ARGS			struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data
 #define DRM_ERR(d)			-(d)
+/** Current process ID */
 #define DRM_CURRENTPID			current->pid
 #define DRM_UDELAY(d)			udelay(d)
+/** Read a byte from a MMIO region */
 #define DRM_READ8(map, offset)		readb(((unsigned long)(map)->handle) + (offset))
+/** Read a dword from a MMIO region */
 #define DRM_READ32(map, offset)		readl(((unsigned long)(map)->handle) + (offset))
+/** Write a byte into a MMIO region */
 #define DRM_WRITE8(map, offset, val)	writeb(val, ((unsigned long)(map)->handle) + (offset))
+/** Write a dword into a MMIO region */
 #define DRM_WRITE32(map, offset, val)	writel(val, ((unsigned long)(map)->handle) + (offset))
+/** Read memory barrier */
 #define DRM_READMEMORYBARRIER()		rmb()
+/** Write memory barrier */
 #define DRM_WRITEMEMORYBARRIER()	wmb()
+/** Read/write memory barrier */
 #define DRM_MEMORYBARRIER()		mb()
+/** DRM device local declaration */
 #define DRM_DEVICE	drm_file_t	*priv	= filp->private_data; \
 			drm_device_t	*dev	= priv->dev
-
+			
+/** IRQ handler arguments */
 #define DRM_IRQ_ARGS	        int irq, void *arg, struct pt_regs *regs
+/** Task queue handler arguments */
 #define DRM_TASKQUEUE_ARGS	void *arg
 
-/* For data going from/to the kernel through the ioctl argument */
+/** For data going into the kernel through the ioctl argument */
 #define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3)	\
 	if ( copy_from_user(&arg1, arg2, arg3) )	\
 		return -EFAULT
+/** For data going from the kernel through the ioctl argument */
 #define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3)	\
 	if ( copy_to_user(arg1, &arg2, arg3) )		\
 		return -EFAULT
-/* Other copying of data from/to kernel space */
+/** Other copying of data to kernel space */
 #define DRM_COPY_FROM_USER(arg1, arg2, arg3)		\
 	copy_from_user(arg1, arg2, arg3)
+/** Other copying of data from kernel space */
 #define DRM_COPY_TO_USER(arg1, arg2, arg3)		\
 	copy_to_user(arg1, arg2, arg3)
 /* Macros for copyfrom user, but checking readability only once */
@@ -41,10 +61,16 @@
 	__get_user(val, uaddr)
 
 
-/* malloc/free without the overhead of DRM(alloc) */
+/** 'malloc' without the overhead of DRM(alloc)() */
 #define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL)
+/** 'free' without the overhead of DRM(free)() */
 #define DRM_FREE(x,size) kfree(x)
 
+/** 
+ * Get the pointer to the SAREA.
+ *
+ * Searches the SAREA on the mapping lists and points drm_device::sarea to it.
+ */
 #define DRM_GETSAREA()							 \
 do { 									 \
 	drm_map_list_t *entry;						 \
diff -Nru a/drivers/char/drm/drm_proc.h b/drivers/char/drm/drm_proc.h
--- a/drivers/char/drm/drm_proc.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/drm_proc.h	Fri Jul 11 01:25:28 2003
@@ -1,4 +1,16 @@
-/* drm_proc.h -- /proc support for DRM -*- linux-c -*-
+/**
+ * \file drm_proc.h 
+ * /proc support for DRM
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ *
+ * \par Acknowledgements:
+ *    Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
+ *    the problem with the proc files not outputting all their information.
+ */
+
+/*
  * Created: Mon Jan 11 09:48:47 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,14 +35,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *
- * Acknowledgements:
- *    Matthew J Sottek <matthew.j.sottek@intel.com> sent in a patch to fix
- *    the problem with the proc files not outputting all their information.
  */
 
 #include "drmP.h"
@@ -50,9 +54,12 @@
 				 int request, int *eof, void *data);
 #endif
 
+/**
+ * Proc file list.
+ */
 struct drm_proc_list {
-	const char *name;
-	int	   (*f)(char *, char **, off_t, int, int *, void *);
+	const char *name;	/**< file name */
+	int	   (*f)(char *, char **, off_t, int, int *, void *);	/**< proc callback*/
 } DRM(proc_list)[] = {
 	{ "name",    DRM(name_info)    },
 	{ "mem",     DRM(mem_info)     },
@@ -66,6 +73,19 @@
 };
 #define DRM_PROC_ENTRIES (sizeof(DRM(proc_list))/sizeof(DRM(proc_list)[0]))
 
+/**
+ * Initialize the DRI proc filesystem for a device.
+ *
+ * \param dev DRM device.
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root resulting DRI device proc dir entry.
+ * \return root entry pointer on success, or NULL on failure.
+ * 
+ * Create the DRI proc root entry "/proc/dri", the device proc root entry
+ * "/proc/dri/%minor%/", and each entry in proc_list as
+ * "/proc/dri/%minor%/%name%".
+ */
 struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, int minor,
 				      struct proc_dir_entry *root,
 				      struct proc_dir_entry **dev_root)
@@ -83,7 +103,7 @@
 	sprintf(name, "%d", minor);
 	*dev_root = create_proc_entry(name, S_IFDIR, root);
 	if (!*dev_root) {
-		DRM_ERROR("Cannot create /proc/%s\n", name);
+		DRM_ERROR("Cannot create /proc/dri/%s\n", name);
 		return NULL;
 	}
 
@@ -108,6 +128,16 @@
 }
 
 
+/**
+ * Cleanup the proc filesystem resources.
+ *
+ * \param minor device minor number.
+ * \param root DRI proc dir entry.
+ * \param dev_root DRI device proc dir entry.
+ * \return always zero.
+ *
+ * Remove all proc entries created by proc_init().
+ */
 int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root,
 		      struct proc_dir_entry *dev_root)
 {
@@ -125,6 +155,19 @@
 	return 0;
 }
 
+/**
+ * Called when "/proc/dri/.../name" is read.
+ * 
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ * 
+ * Prints the device name together with the bus id if available.
+ */
 static int DRM(name_info)(char *buf, char **start, off_t offset, int request,
 			  int *eof, void *data)
 {
@@ -151,6 +194,19 @@
 	return len - offset;
 }
 
+/**
+ * Called when "/proc/dri/.../vm" is read.
+ * 
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ * 
+ * Prints information about all mappings in drm_device::maplist.
+ */
 static int DRM(_vm_info)(char *buf, char **start, off_t offset, int request,
 			 int *eof, void *data)
 {
@@ -204,6 +260,9 @@
 	return len - offset;
 }
 
+/**
+ * Simply calls _vm_info() while holding the drm_device::struct_sem lock.
+ */
 static int DRM(vm_info)(char *buf, char **start, off_t offset, int request,
 			int *eof, void *data)
 {
@@ -216,7 +275,17 @@
 	return ret;
 }
 
-
+/**
+ * Called when "/proc/dri/.../queues" is read.
+ * 
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
 static int DRM(_queues_info)(char *buf, char **start, off_t offset,
 			     int request, int *eof, void *data)
 {
@@ -261,6 +330,9 @@
 	return len - offset;
 }
 
+/**
+ * Simply calls _queues_info() while holding the drm_device::struct_sem lock.
+ */
 static int DRM(queues_info)(char *buf, char **start, off_t offset, int request,
 			    int *eof, void *data)
 {
@@ -273,9 +345,17 @@
 	return ret;
 }
 
-/* drm_bufs_info is called whenever a process reads
-   /dev/dri/<dev>/bufs. */
-
+/**
+ * Called when "/proc/dri/.../bufs" is read.
+ * 
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
 static int DRM(_bufs_info)(char *buf, char **start, off_t offset, int request,
 			   int *eof, void *data)
 {
@@ -320,6 +400,9 @@
 	return len - offset;
 }
 
+/**
+ * Simply calls _bufs_info() while holding the drm_device::struct_sem lock.
+ */
 static int DRM(bufs_info)(char *buf, char **start, off_t offset, int request,
 			  int *eof, void *data)
 {
@@ -332,7 +415,17 @@
 	return ret;
 }
 
-
+/**
+ * Called when "/proc/dri/.../clients" is read.
+ * 
+ * \param buf output buffer.
+ * \param start start of output data.
+ * \param offset requested start offset.
+ * \param request requested number of bytes.
+ * \param eof whether there is no more data to return.
+ * \param data private data.
+ * \return number of written bytes.
+ */
 static int DRM(_clients_info)(char *buf, char **start, off_t offset,
 			      int request, int *eof, void *data)
 {
@@ -364,6 +457,9 @@
 	return len - offset;
 }
 
+/**
+ * Simply calls _clients_info() while holding the drm_device::struct_sem lock.
+ */
 static int DRM(clients_info)(char *buf, char **start, off_t offset,
 			     int request, int *eof, void *data)
 {
diff -Nru a/drivers/char/drm/drm_sarea.h b/drivers/char/drm/drm_sarea.h
--- a/drivers/char/drm/drm_sarea.h	Fri Jul 11 01:25:30 2003
+++ b/drivers/char/drm/drm_sarea.h	Fri Jul 11 01:25:30 2003
@@ -1,5 +1,11 @@
-/* sarea.h -- SAREA definitions -*- linux-c -*-
+/**
+ * \file drm_sarea.h 
+ * \brief SAREA definitions
  *
+ * \author Michel Dänzer <michel@daenzer.net>
+ */
+
+/*
  * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
  *
@@ -21,22 +27,22 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Michel Dänzer <michel@daenzer.net>
  */
 
 #ifndef _DRM_SAREA_H_
 #define _DRM_SAREA_H_
 
+/** Maximum number of drawables in the SAREA */
 #define SAREA_MAX_DRAWABLES 		256
 
-typedef struct _drm_sarea_drawable_t {
+/** SAREA drawable */
+typedef struct drm_sarea_drawable {
     unsigned int	stamp;
     unsigned int	flags;
 } drm_sarea_drawable_t;
 
-typedef struct _dri_sarea_frame_t {
+/** SAREA frame */
+typedef struct drm_sarea_frame {
     unsigned int        x;
     unsigned int        y;
     unsigned int        width;
@@ -44,13 +50,14 @@
     unsigned int        fullscreen;
 } drm_sarea_frame_t;
 
-typedef struct _drm_sarea_t {
-    /* first thing is always the drm locking structure */
+/** SAREA */
+typedef struct drm_sarea {
+    /** first thing is always the DRM locking structure */
     drm_hw_lock_t		lock;
-		/* NOT_DONE: Use readers/writer lock for drawable_lock */
+    /** \todo Use readers/writer lock for drm_sarea::drawable_lock */
     drm_hw_lock_t		drawable_lock;
-    drm_sarea_drawable_t	drawableTable[SAREA_MAX_DRAWABLES];
-    drm_sarea_frame_t		frame;
+    drm_sarea_drawable_t	drawableTable[SAREA_MAX_DRAWABLES];	/**< drawables */
+    drm_sarea_frame_t		frame;	/**< frame */
     drm_context_t		dummy_context;
 } drm_sarea_t;
 
diff -Nru a/drivers/char/drm/drm_scatter.h b/drivers/char/drm/drm_scatter.h
--- a/drivers/char/drm/drm_scatter.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_scatter.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,11 @@
-/* drm_scatter.h -- IOCTLs to manage scatter/gather memory -*- linux-c -*-
+/**
+ * \file drm_scatter.h 
+ * IOCTLs to manage scatter/gather memory
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com
  *
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
@@ -22,9 +29,6 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *   Gareth Hughes <gareth@valinux.com>
  */
 
 #include <linux/config.h>
diff -Nru a/drivers/char/drm/drm_stub.h b/drivers/char/drm/drm_stub.h
--- a/drivers/char/drm/drm_stub.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/drm_stub.h	Fri Jul 11 01:25:29 2003
@@ -1,4 +1,11 @@
-/* drm_stub.h -- -*- linux-c -*-
+/**
+ * \file drm_stub.h
+ * Stub support
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+/*
  * Created: Fri Jan 19 10:48:35 2001 by faith@acm.org
  *
  * Copyright 2001 VA Linux Systems, Inc., Sunnyvale, California.
@@ -22,30 +29,37 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *
  */
 
 #include "drmP.h"
 
 #define DRM_STUB_MAXCARDS 16	/* Enough for one machine */
 
+/** Stub list. One for each minor. */
 static struct drm_stub_list {
 	const char             *name;
-	struct file_operations *fops;
-	struct proc_dir_entry  *dev_root;
+	struct file_operations *fops;	/**< file operations */
+	struct proc_dir_entry  *dev_root;	/**< proc directory entry */
 } *DRM(stub_list);
 
 static struct proc_dir_entry *DRM(stub_root);
 
+/** Stub information */
 static struct drm_stub_info {
 	int (*info_register)(const char *name, struct file_operations *fops,
 			     drm_device_t *dev);
 	int (*info_unregister)(int minor);
 } DRM(stub_info);
 
+/**
+ * File \c open operation.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ *
+ * Puts the drm_stub_list::fops corresponding to the device minor number into
+ * \p filp, call the \c open method, and restore the file operations.
+ */
 static int DRM(stub_open)(struct inode *inode, struct file *filp)
 {
 	int                    minor = minor(inode->i_rdev);
@@ -64,11 +78,24 @@
 	return err;
 }
 
+/** File operations structure */
 static struct file_operations DRM(stub_fops) = {
 	.owner = THIS_MODULE,
 	.open  = DRM(stub_open)
 };
 
+/**
+ * Get a device minor number.
+ *
+ * \param name driver name.
+ * \param fops file operations.
+ * \param dev DRM device.
+ * \return minor number on success, or a negative number on failure.
+ *
+ * Allocate and initialize ::stub_list if one doesn't exist already.  Search an
+ * empty entry and initialize it to the given parameters, and create the proc
+ * init entry via proc_init().
+ */
 static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
 			      drm_device_t *dev)
 {
@@ -96,6 +123,16 @@
 	return -1;
 }
 
+/**
+ * Put a device minor number.
+ *
+ * \param minor minor number.
+ * \return always zero.
+ *
+ * Cleans up the proc resources. If a minor is zero then release the foreign
+ * "drm" data, otherwise unregisters the "drm" data, frees the stub list and
+ * unregisters the character device. 
+ */
 static int DRM(stub_putminor)(int minor)
 {
 	if (minor < 0 || minor >= DRM_STUB_MAXCARDS) return -1;
@@ -115,7 +152,20 @@
 	return 0;
 }
 
-
+/**
+ * Register.
+ *
+ * \param name driver name.
+ * \param fops file operations
+ * \param dev DRM device.
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to register the char device and get the foreign "drm" data. If
+ * successful then another module already registered so gets the stub info,
+ * otherwise use this module stub info and make it available for other modules.
+ *
+ * Finally calls stub_info::info_register.
+ */
 int DRM(stub_register)(const char *name, struct file_operations *fops,
 		       drm_device_t *dev)
 {
@@ -141,6 +191,13 @@
 	return -1;
 }
 
+/**
+ * Unregister.
+ *
+ * \param minor
+ *
+ * Calls drm_stub_info::unregister.
+ */
 int DRM(stub_unregister)(int minor)
 {
 	DRM_DEBUG("%d\n", minor);
diff -Nru a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h
--- a/drivers/char/drm/drm_vm.h	Fri Jul 11 01:25:30 2003
+++ b/drivers/char/drm/drm_vm.h	Fri Jul 11 01:25:30 2003
@@ -1,4 +1,12 @@
-/* drm_vm.h -- Memory mapping for DRM -*- linux-c -*-
+/**
+ * \file drm_vm.h
+ * Memory mapping for DRM
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Created: Mon Jan  4 08:58:31 1999 by faith@valinux.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
@@ -23,38 +31,49 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
  */
 
 #include "drmP.h"
 
+/** AGP virtual memory operations */
 struct vm_operations_struct   DRM(vm_ops) = {
 	.nopage = DRM(vm_nopage),
 	.open	= DRM(vm_open),
 	.close	= DRM(vm_close),
 };
 
+/** Shared virtual memory operations */
 struct vm_operations_struct   DRM(vm_shm_ops) = {
 	.nopage = DRM(vm_shm_nopage),
 	.open	= DRM(vm_open),
 	.close	= DRM(vm_shm_close),
 };
 
+/** DMA virtual memory operations */
 struct vm_operations_struct   DRM(vm_dma_ops) = {
 	.nopage = DRM(vm_dma_nopage),
 	.open	= DRM(vm_open),
 	.close	= DRM(vm_close),
 };
 
+/** Scatter-gather virtual memory operations */
 struct vm_operations_struct   DRM(vm_sg_ops) = {
 	.nopage = DRM(vm_sg_nopage),
 	.open   = DRM(vm_open),
 	.close  = DRM(vm_close),
 };
 
+/**
+ * \c nopage method for AGP virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ * 
+ * Find the right map and if it's AGP memory find the real physical page to
+ * map, get the page, increment the use count and return it.
+ */
 struct page *DRM(vm_nopage)(struct vm_area_struct *vma,
 			    unsigned long address,
 			    int write_access)
@@ -122,6 +141,17 @@
 	return NOPAGE_SIGBUS;		/* Disallow mremap */
 }
 
+/**
+ * \c nopage method for shared virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ * 
+ * Get the the mapping, find the real physical page to map, get the page, and
+ * return it.
+ */
 struct page *DRM(vm_shm_nopage)(struct vm_area_struct *vma,
 				unsigned long address,
 				int write_access)
@@ -145,10 +175,15 @@
 	return page;
 }
 
-/* Special close routine which deletes map information if we are the last
+
+/**
+ * \c close method for shared virtual memory.
+ * 
+ * \param vma virtual memory area.
+ * 
+ * Deletes map information if we are the last
  * person to close a mapping and it's not in the global maplist.
  */
-
 void DRM(vm_shm_close)(struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= vma->vm_file->private_data;
@@ -221,6 +256,16 @@
 	up(&dev->struct_sem);
 }
 
+/**
+ * \c nopage method for DMA virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ * 
+ * Determine the page number from the page offset and get it from drm_device_dma::pagelist.
+ */
 struct page *DRM(vm_dma_nopage)(struct vm_area_struct *vma,
 				unsigned long address,
 				int write_access)
@@ -247,6 +292,16 @@
 	return page;
 }
 
+/**
+ * \c nopage method for scatter-gather virtual memory.
+ *
+ * \param vma virtual memory area.
+ * \param address access address.
+ * \param write_access sharing.
+ * \return pointer to the page structure.
+ * 
+ * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
+ */
 struct page *DRM(vm_sg_nopage)(struct vm_area_struct *vma,
 			       unsigned long address,
 			       int write_access)
@@ -274,6 +329,14 @@
 	return page;
 }
 
+/**
+ * \c open method for shared virtual memory.
+ * 
+ * \param vma virtual memory area.
+ * 
+ * Create a new drm_vma_entry structure as the \p vma private data entry and
+ * add it to drm_device::vmalist.
+ */
 void DRM(vm_open)(struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= vma->vm_file->private_data;
@@ -295,6 +358,14 @@
 	}
 }
 
+/**
+ * \c close method for all virtual memory types.
+ * 
+ * \param vma virtual memory area.
+ * 
+ * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
+ * free it.
+ */
 void DRM(vm_close)(struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= vma->vm_file->private_data;
@@ -320,6 +391,16 @@
 	up(&dev->struct_sem);
 }
 
+/**
+ * mmap DMA memory.
+ *
+ * \param filp file pointer.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+ * 
+ * Sets the virtual memory area operations structure to vm_dma_ops, the file
+ * pointer, and calls vm_open().
+ */
 int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
 {
 	drm_file_t	 *priv	 = filp->private_data;
@@ -366,6 +447,19 @@
 #endif
 #endif
 
+/**
+ * mmap DMA memory.
+ *
+ * \param filp file pointer.
+ * \param vma virtual memory area.
+ * \return zero on success or a negative number on failure.
+ * 
+ * If the virtual memory area has no offset associated with it then it's a DMA
+ * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
+ * checks that the restricted flag is not set, sets the virtual memory operations
+ * according to the mapping type and remaps the pages. Finally sets the file
+ * pointer and calls vm_open().
+ */
 int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= filp->private_data;
diff -Nru a/drivers/char/drm/i810.h b/drivers/char/drm/i810.h
--- a/drivers/char/drm/i810.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/i810.h	Fri Jul 11 01:25:28 2003
@@ -45,7 +45,7 @@
 
 #define DRIVER_NAME		"i810"
 #define DRIVER_DESC		"Intel i810"
-#define DRIVER_DATE		"20020211"
+#define DRIVER_DATE		"20030605"
 
 /* Interface history
  *
@@ -54,10 +54,11 @@
  *       - XFree86 4.2
  * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility)
  *       - Remove requirement for interrupt (leave stubs again)
+ * 1.3   - Add page flipping.
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		2
-#define DRIVER_PATCHLEVEL	1
+#define DRIVER_MINOR		3
+#define DRIVER_PATCHLEVEL	0
 
 #define DRIVER_IOCTLS							    \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)]   = { i810_dma_init,    1, 1 }, \
@@ -73,8 +74,9 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_FSTATUS)] = { i810_fstatus,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_OV0FLIP)] = { i810_ov0_flip,   1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_MC)]      = { i810_dma_mc,     1, 1 }, \
-	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }
-
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }, \
+	[DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] =    { i810_flip_bufs,  1, 0 }
+ 
 
 #define __HAVE_COUNTERS         4
 #define __HAVE_COUNTER6         _DRM_STAT_IRQ
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/i810_dma.c	Fri Jul 11 01:25:28 2003
@@ -282,10 +282,12 @@
 	   	ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
 	   	ring->space = ring->head - (ring->tail+8);
 		if (ring->space < 0) ring->space += ring->Size;
-
-		if (ring->head != last_head)
-		   end = jiffies + (HZ*3);
-
+	   
+		if (ring->head != last_head) {
+			end = jiffies + (HZ*3);
+			last_head = ring->head;
+		}
+	  
 	   	iters++;
 		if(time_before(end, jiffies)) {
 		   	DRM_ERROR("space: %d wanted %d\n", ring->space, n);
@@ -403,6 +405,7 @@
 	dev_priv->pitch = init->pitch;
 	dev_priv->back_offset = init->back_offset;
 	dev_priv->depth_offset = init->depth_offset;
+	dev_priv->front_offset = init->front_offset;
 
 	dev_priv->overlay_offset = init->overlay_offset;
 	dev_priv->overlay_physical = init->overlay_physical;
@@ -582,6 +585,8 @@
    	drm_i810_private_t *dev_priv = dev->dev_private;
       	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
+	
+	DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
 
 	if (dirty & I810_UPLOAD_BUFFERS) {
 		i810EmitDestVerified( dev, sarea_priv->BufferState );
@@ -620,6 +625,14 @@
 	int cpp = 2;
 	int i;
 	RING_LOCALS;
+	
+	if ( dev_priv->current_page == 1 ) {
+	        unsigned int tmp = flags;
+	       
+		flags &= ~(I810_FRONT | I810_BACK);
+		if (tmp & I810_FRONT) flags |= I810_BACK;
+		if (tmp & I810_BACK) flags |= I810_FRONT;
+	}
 
   	i810_kernel_lost_context(dev);
 
@@ -685,10 +698,11 @@
 	drm_clip_rect_t *pbox = sarea_priv->boxes;
 	int pitch = dev_priv->pitch;
 	int cpp = 2;
-	int ofs = dev_priv->back_offset;
 	int i;
 	RING_LOCALS;
 
+	DRM_DEBUG("swapbuffers\n");
+
   	i810_kernel_lost_context(dev);
 
       	if (nbox > I810_NR_SAREA_CLIPRECTS)
@@ -699,7 +713,7 @@
 		unsigned int w = pbox->x2 - pbox->x1;
 		unsigned int h = pbox->y2 - pbox->y1;
 		unsigned int dst = pbox->x1*cpp + pbox->y1*pitch;
-		unsigned int start = ofs + dst;
+		unsigned int start = dst;
 
 		if (pbox->x1 > pbox->x2 ||
 		    pbox->y1 > pbox->y2 ||
@@ -711,9 +725,15 @@
 		OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 );
 		OUT_RING( pitch | (0xCC << 16));
 		OUT_RING( (h << 16) | (w * cpp));
-		OUT_RING( dst );
+		if (dev_priv->current_page == 0)
+		  OUT_RING(dev_priv->front_offset + start);
+		else
+		  OUT_RING(dev_priv->back_offset + start);
 		OUT_RING( pitch );
-		OUT_RING( start );
+		if (dev_priv->current_page == 0)
+		  OUT_RING(dev_priv->back_offset + start);
+		else
+		  OUT_RING(dev_priv->front_offset + start);
 		ADVANCE_LP_RING();
 	}
 }
@@ -800,6 +820,52 @@
 	}
 }
 
+static void i810_dma_dispatch_flip( drm_device_t *dev )
+{
+        drm_i810_private_t *dev_priv = dev->dev_private;
+	int pitch = dev_priv->pitch;
+	RING_LOCALS;
+
+	DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", 
+		__FUNCTION__, 
+		dev_priv->current_page,
+		dev_priv->sarea_priv->pf_current_page);
+	
+        i810_kernel_lost_context(dev);
+
+	BEGIN_LP_RING( 2 );
+   	OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); 
+	OUT_RING( 0 );
+	ADVANCE_LP_RING();
+
+	BEGIN_LP_RING( I810_DEST_SETUP_SIZE + 2 );
+	/* On i815 at least ASYNC is buggy */
+	/* pitch<<5 is from 11.2.8 p158,
+	   its the pitch / 8 then left shifted 8,
+	   so (pitch >> 3) << 8 */
+	OUT_RING( CMD_OP_FRONTBUFFER_INFO | (pitch<<5) /*| ASYNC_FLIP */ );
+	if ( dev_priv->current_page == 0 ) {
+		OUT_RING( dev_priv->back_offset );
+		dev_priv->current_page = 1;
+	} else {
+		OUT_RING( dev_priv->front_offset );
+		dev_priv->current_page = 0;
+	}
+	OUT_RING(0);
+	ADVANCE_LP_RING();
+
+	BEGIN_LP_RING(2);
+	OUT_RING( CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP );
+	OUT_RING( 0 );
+	ADVANCE_LP_RING();
+
+	/* Increment the frame counter.  The client-side 3D driver must
+	 * throttle the framerate by waiting for this value before
+	 * performing the swapbuffer ioctl.
+	 */
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+
+}
 
 void i810_dma_quiescent(drm_device_t *dev)
 {
@@ -1191,3 +1257,47 @@
 }
 
 
+/* Not sure why this isn't set all the time:
+ */ 
+static void i810_do_init_pageflip( drm_device_t *dev )
+{
+	drm_i810_private_t *dev_priv = dev->dev_private;
+	
+	DRM_DEBUG("%s\n", __FUNCTION__);
+	dev_priv->page_flipping = 1;
+	dev_priv->current_page = 0;
+	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+}
+
+int i810_do_cleanup_pageflip( drm_device_t *dev )
+{
+	drm_i810_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+	if (dev_priv->current_page != 0)
+		i810_dma_dispatch_flip( dev );
+
+	dev_priv->page_flipping = 0;
+	return 0;
+}
+
+int i810_flip_bufs(struct inode *inode, struct file *filp,
+		   unsigned int cmd, unsigned long arg)
+{
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	drm_i810_private_t *dev_priv = dev->dev_private;
+
+	DRM_DEBUG("%s\n", __FUNCTION__);
+
+   	if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
+		DRM_ERROR("i810_flip_buf called without lock held\n");
+		return -EINVAL;
+	}
+
+	if (!dev_priv->page_flipping) 
+		i810_do_init_pageflip( dev );
+
+	i810_dma_dispatch_flip( dev );
+   	return 0;
+}
diff -Nru a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h
--- a/drivers/char/drm/i810_drm.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/i810_drm.h	Fri Jul 11 01:25:28 2003
@@ -166,6 +166,9 @@
 
 	int vertex_prim;
 
+	int pf_enabled;               /* is pageflipping allowed? */
+	int pf_active;
+	int pf_current_page;	    /* which buffer is being displayed? */
 } drm_i810_sarea_t;
 
 /* WARNING: If you change any of these defines, make sure to change the
@@ -189,6 +192,7 @@
 #define DRM_IOCTL_I810_OV0FLIP		DRM_IO ( 0x4b)
 #define DRM_IOCTL_I810_MC		DRM_IOW( 0x4c, drm_i810_mc_t)
 #define DRM_IOCTL_I810_RSTATUS		DRM_IO ( 0x4d )
+#define DRM_IOCTL_I810_FLIP             DRM_IO ( 0x4e )
 
 typedef struct _drm_i810_clear {
 	int clear_color;
diff -Nru a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
--- a/drivers/char/drm/i810_drv.h	Fri Jul 11 01:25:30 2003
+++ b/drivers/char/drm/i810_drv.h	Fri Jul 11 01:25:30 2003
@@ -75,7 +75,20 @@
 	int overlay_physical;
 	int w, h;
 	int pitch;
+  	int back_pitch;
+	int depth_pitch;
 
+	int do_boxes;
+	int dma_used;
+
+	int current_page;
+	int page_flipping;
+
+	wait_queue_head_t irq_queue;
+   	atomic_t irq_received;
+   	atomic_t irq_emitted;
+  
+        int front_offset;
 } drm_i810_private_t;
 
 				/* i810_dma.c */
@@ -124,6 +137,8 @@
 int i810_clear_bufs(struct inode *inode, struct file *filp,
 		    unsigned int cmd, unsigned long arg);
 
+int i810_flip_bufs(struct inode *inode, struct file *filp,
+		   unsigned int cmd, unsigned long arg);
 
 #define I810_BASE(reg)		((unsigned long) \
 				dev_priv->mmio_map->handle)
@@ -225,12 +240,15 @@
 #define CMD_OP_Z_BUFFER_INFO     ((0x0<<29)|(0x16<<23))
 #define CMD_OP_DESTBUFFER_INFO   ((0x0<<29)|(0x15<<23))
 #define CMD_OP_FRONTBUFFER_INFO  ((0x0<<29)|(0x14<<23))
+#define CMD_OP_WAIT_FOR_EVENT    ((0x0<<29)|(0x03<<23))
 
 #define BR00_BITBLT_CLIENT   0x40000000
 #define BR00_OP_COLOR_BLT    0x10000000
 #define BR00_OP_SRC_COPY_BLT 0x10C00000
 #define BR13_SOLID_PATTERN   0x80000000
 
-
+#define WAIT_FOR_PLANE_A_SCANLINES (1<<1) 
+#define WAIT_FOR_PLANE_A_FLIP      (1<<2) 
+#define WAIT_FOR_VBLANK (1<<3)
 
 #endif
diff -Nru a/drivers/char/drm/r128.h b/drivers/char/drm/r128.h
--- a/drivers/char/drm/r128.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/r128.h	Fri Jul 11 01:25:28 2003
@@ -47,13 +47,17 @@
 
 #define DRIVER_NAME		"r128"
 #define DRIVER_DESC		"ATI Rage 128"
-#define DRIVER_DATE		"20021029"
+#define DRIVER_DATE		"20030526"
 
 #define DRIVER_MAJOR		2
-#define DRIVER_MINOR		3
+#define DRIVER_MINOR		4
 #define DRIVER_PATCHLEVEL	0
 
-
+/* Interface history:
+ *
+ * ??  - ??
+ * 2.4 - Add support for ycbcr textures (no new ioctls)
+ */
 #define DRIVER_IOCTLS							    \
    [DRM_IOCTL_NR(DRM_IOCTL_DMA)]             = { r128_cce_buffers,  1, 0 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)]       = { r128_cce_init,     1, 1 }, \
diff -Nru a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
--- a/drivers/char/drm/r128_drv.h	Fri Jul 11 01:25:30 2003
+++ b/drivers/char/drm/r128_drv.h	Fri Jul 11 01:25:30 2003
@@ -343,13 +343,20 @@
 #define R128_CCE_VC_CNTL_PRIM_WALK_RING		0x00000030
 #define R128_CCE_VC_CNTL_NUM_SHIFT		16
 
+#define R128_DATATYPE_VQ		0
+#define R128_DATATYPE_CI4		1
 #define R128_DATATYPE_CI8		2
 #define R128_DATATYPE_ARGB1555		3
 #define R128_DATATYPE_RGB565		4
 #define R128_DATATYPE_RGB888		5
 #define R128_DATATYPE_ARGB8888		6
 #define R128_DATATYPE_RGB332		7
+#define R128_DATATYPE_Y8		8
 #define R128_DATATYPE_RGB8		9
+#define R128_DATATYPE_CI16		10
+#define R128_DATATYPE_YVYU422		11
+#define R128_DATATYPE_VYUY422		12
+#define R128_DATATYPE_AYUV444		14
 #define R128_DATATYPE_ARGB4444		15
 
 /* Constants */
diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
--- a/drivers/char/drm/r128_state.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/char/drm/r128_state.c	Fri Jul 11 01:25:28 2003
@@ -802,6 +802,8 @@
 	case R128_DATATYPE_ARGB1555:
 	case R128_DATATYPE_RGB565:
 	case R128_DATATYPE_ARGB4444:
+	case R128_DATATYPE_YVYU422:
+	case R128_DATATYPE_VYUY422:
 		dword_shift = 1;
 		break;
 	case R128_DATATYPE_CI8:
diff -Nru a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h
--- a/drivers/char/drm/radeon.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/radeon.h	Fri Jul 11 01:25:29 2003
@@ -51,7 +51,7 @@
 #define DRIVER_DATE		"20020828"
 
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		8
+#define DRIVER_MINOR		9
 #define DRIVER_PATCHLEVEL	0
 
 /* Interface history:
diff -Nru a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
--- a/drivers/char/drm/radeon_drm.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/radeon_drm.h	Fri Jul 11 01:25:29 2003
@@ -141,7 +141,10 @@
 #define R200_EMIT_PP_CUBIC_OFFSETS_4                70
 #define R200_EMIT_PP_CUBIC_FACES_5                  71
 #define R200_EMIT_PP_CUBIC_OFFSETS_5                72
-#define RADEON_MAX_STATE_PACKETS                    73
+#define RADEON_EMIT_PP_TEX_SIZE_0                   73
+#define RADEON_EMIT_PP_TEX_SIZE_1                   74
+#define RADEON_EMIT_PP_TEX_SIZE_2                   75
+#define RADEON_MAX_STATE_PACKETS                    76
 
 
 /* Commands understood by cmd_buffer ioctl.  More can be added but
diff -Nru a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
--- a/drivers/char/drm/radeon_drv.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/radeon_drv.c	Fri Jul 11 01:25:29 2003
@@ -1,6 +1,11 @@
-/* radeon_drv.c -- ATI Radeon driver -*- linux-c -*-
- * Created: Wed Feb 14 17:10:04 2001 by gareth@valinux.com
+/**
+ * \file radeon_drv.c
+ * ATI Radeon driver
  *
+ * \author Gareth Hughes <gareth@valinux.com>
+ */
+
+/*
  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
@@ -22,10 +27,8 @@
  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Gareth Hughes <gareth@valinux.com>
  */
+
 
 #include <linux/config.h>
 #include "radeon.h"
diff -Nru a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
--- a/drivers/char/drm/radeon_drv.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/radeon_drv.h	Fri Jul 11 01:25:29 2003
@@ -669,6 +669,10 @@
 #define R200_RE_POINTSIZE                 0x2648
 #define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254
 
+#define RADEON_PP_TEX_SIZE_0                0x1d04  /* NPOT */
+#define RADEON_PP_TEX_SIZE_1                0x1d0c
+#define RADEON_PP_TEX_SIZE_2                0x1d14
+
 
 #define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
diff -Nru a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
--- a/drivers/char/drm/radeon_state.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/char/drm/radeon_state.c	Fri Jul 11 01:25:29 2003
@@ -292,6 +292,9 @@
 	{ R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
 	{ R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" },
 	{ R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
+	{ RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
+	{ RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
+	{ RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_1" },
 };
 
 
@@ -885,15 +888,14 @@
 
 static void radeon_cp_dispatch_vertex( drm_device_t *dev,
 				       drm_buf_t *buf,
-				       drm_radeon_tcl_prim_t *prim,
-				       drm_clip_rect_t *boxes,
-				       int nbox )
+				       drm_radeon_tcl_prim_t *prim )
 
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_clip_rect_t box;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int offset = dev_priv->agp_buffers_offset + buf->offset + prim->start;
 	int numverts = (int)prim->numverts;
+	int nbox = sarea_priv->nbox;
 	int i = 0;
 	RING_LOCALS;
 
@@ -913,10 +915,8 @@
 	do {
 		/* Emit the next cliprect */
 		if ( i < nbox ) {
-			if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
-				return;
-
-			radeon_emit_clip_rect( dev_priv, &box );
+			radeon_emit_clip_rect( dev_priv, 
+					       &sarea_priv->boxes[i] );
 		}
 
 		/* Emit the vertex buffer rendering commands */
@@ -995,18 +995,17 @@
 
 static void radeon_cp_dispatch_indices( drm_device_t *dev,
 					drm_buf_t *elt_buf,
-					drm_radeon_tcl_prim_t *prim, 
-					drm_clip_rect_t *boxes,
-					int nbox )
+					drm_radeon_tcl_prim_t *prim )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
-	drm_clip_rect_t box;
+	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int offset = dev_priv->agp_buffers_offset + prim->offset;
 	u32 *data;
 	int dwords;
 	int i = 0;
 	int start = prim->start + RADEON_INDEX_PRIM_OFFSET;
 	int count = (prim->finish - start) / sizeof(u16);
+	int nbox = sarea_priv->nbox;
 
 	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",
 		  prim->prim,
@@ -1045,12 +1044,9 @@
 		   (count << RADEON_NUM_VERTICES_SHIFT) );
 
 	do {
-		if ( i < nbox ) {
-			if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
-				return;
-			
-			radeon_emit_clip_rect( dev_priv, &box );
-		}
+		if ( i < nbox ) 
+			radeon_emit_clip_rect( dev_priv, 
+					       &sarea_priv->boxes[i] );
 
 		radeon_cp_dispatch_indirect( dev, elt_buf,
 					     prim->start,
@@ -1450,9 +1446,7 @@
 		prim.numverts = vertex.count;
 		prim.vc_format = dev_priv->sarea_priv->vc_format;
 		
-		radeon_cp_dispatch_vertex( dev, buf, &prim,
-					   dev_priv->sarea_priv->boxes,
-					   dev_priv->sarea_priv->nbox );
+		radeon_cp_dispatch_vertex( dev, buf, &prim );
 	}
 
 	if (vertex.discard) {
@@ -1550,9 +1544,7 @@
 	prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
 	prim.vc_format = dev_priv->sarea_priv->vc_format;
 	
-	radeon_cp_dispatch_indices( dev, buf, &prim,
-				   dev_priv->sarea_priv->boxes,
-				   dev_priv->sarea_priv->nbox );
+	radeon_cp_dispatch_indices( dev, buf, &prim );
 	if (elts.discard) {
 		radeon_cp_discard_buffer( dev, buf );
 	}
@@ -1769,16 +1761,12 @@
 			tclprim.offset = prim.numverts * 64;
 			tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
 
-			radeon_cp_dispatch_indices( dev, buf, &tclprim,
-						    sarea_priv->boxes,
-						    sarea_priv->nbox);
+			radeon_cp_dispatch_indices( dev, buf, &tclprim );
 		} else {
 			tclprim.numverts = prim.numverts;
 			tclprim.offset = 0; /* not used */
 
-			radeon_cp_dispatch_vertex( dev, buf, &tclprim,
-						   sarea_priv->boxes,
-						   sarea_priv->nbox);
+			radeon_cp_dispatch_vertex( dev, buf, &tclprim );
 		}
 		
 		if (sarea_priv->nbox == 1)
diff -Nru a/drivers/eisa/Kconfig b/drivers/eisa/Kconfig
--- a/drivers/eisa/Kconfig	Fri Jul 11 01:25:28 2003
+++ b/drivers/eisa/Kconfig	Fri Jul 11 01:25:28 2003
@@ -14,7 +14,7 @@
 
 config EISA_PCI_EISA
 	bool "Generic PCI/EISA bridge"
-	depends on PCI && EISA
+	depends on !PARISC && PCI && EISA
 	default y
 	---help---
 	  Activate this option if your system contains a PCI to EISA
diff -Nru a/drivers/input/misc/gsc_ps2.c b/drivers/input/misc/gsc_ps2.c
--- a/drivers/input/misc/gsc_ps2.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/input/misc/gsc_ps2.c	Fri Jul 11 01:25:28 2003
@@ -56,12 +56,13 @@
 #include <linux/sched.h>        /* for request_irq/free_irq */        
 #include <linux/spinlock.h>
 #include <linux/delay.h>
-#include <linux/pc_keyb.h>
 #include <linux/ioport.h>
 #include <linux/kd.h>
+#include <linux/pci_ids.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/parisc-device.h>
 
 /* Debugging stuff */
 #undef KBD_DEBUG
@@ -79,6 +80,7 @@
 /* PS/2 keyboard and mouse constants */
 #define AUX_RECONNECT		0xAA	/* PS/2 Mouse end of test successful */
 #define AUX_REPLY_ACK		0xFA
+#define AUX_ENABLE_DEV		0xF4	/* Enables aux device */
 
 /* Order of the mouse bytes coming to the host */
 #define PACKET_X		1
@@ -131,6 +133,12 @@
 #define MOUSE_XOVFLOW		0x40
 #define MOUSE_YOVFLOW		0x80
 
+/* Remnant of pc_keyb.h */
+#define KBD_CMD_SET_LEDS	0xED	/* Sets keyboard leds */
+#define KBD_CMD_SET_RATE	0xF3	/* Sets typematic rate */
+#define KBD_CMD_ENABLE		0xF4	/* Enables scanning */
+#define KBD_CMD_DISABLE		0xF5
+#define KBD_CMD_RESET		0xFF
 
 static unsigned char hpkeyb_keycode[KBD_TBLSIZE] =
 {
@@ -341,7 +349,7 @@
 		default:
 			hpkeyb.scancode = scancode;
 			DPRINTK("sent=%d, rel=%d\n",hpkeyb.scancode, hpkeyb.released);
-			input_regs(regs);
+			/*input_regs(regs);*/
 			input_report_key(&hpkeyb.dev, hpkeyb_keycode[hpkeyb.scancode], !hpkeyb.released);
 			input_sync(&hpkeyb.dev);
 			if (hpkeyb.escaped)
@@ -388,7 +396,7 @@
 		if ((hpmouse.bytes[PACKET_CTRL] & (MOUSE_XOVFLOW | MOUSE_YOVFLOW)))
 			DPRINTK("Mouse: position overflow\n");
 		
-		input_regs(regs);
+		/*input_regs(regs);*/
 
 		input_report_key(&hpmouse.dev, BTN_LEFT, hpmouse.bytes[PACKET_CTRL] & MOUSE_LEFTBTN);
 		input_report_key(&hpmouse.dev, BTN_MIDDLE, hpmouse.bytes[PACKET_CTRL] & MOUSE_MIDBTN);
@@ -420,7 +428,7 @@
  * key value to the system.
  */
 
-static void gscps2_interrupt(int irq, void *dev, struct pt_regs *reg)
+static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *reg)
 {
 	/* process mouse actions */
 	while (gscps2_readb_status(hpmouse.addr) & GSC_STAT_RBNE)
@@ -429,6 +437,8 @@
 	/* process keyboard scancode */
 	while (gscps2_readb_status(hpkeyb.addr) & GSC_STAT_RBNE)
 		gscps2_kbd_docode(reg);
+
+	return IRQ_HANDLED;
 }
 
 
@@ -525,7 +535,7 @@
 	
 	/* TODO These need some adjustement, are they really useful ? */
 	hpkeyb.dev.id.bustype	= BUS_GSC;
-	hpkeyb.dev.id.vendor	= 0x0001;
+	hpkeyb.dev.id.vendor	= PCI_VENDOR_ID_HP;
 	hpkeyb.dev.id.product	= 0x0001;
 	hpkeyb.dev.id.version	= 0x0010;
 	hpkeyb.initialized	= 1;
@@ -580,7 +590,7 @@
 {
 	u8 id;
 	char *addr, *name;
-	int ret, device_found = 0;
+	int ret = 0, device_found = 0;
 	unsigned long hpa = dev->hpa;
 
 	if (!dev->irq)
diff -Nru a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
--- a/drivers/net/appletalk/cops.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/appletalk/cops.c	Fri Jul 11 01:25:29 2003
@@ -424,7 +424,7 @@
 		    init_timer(&cops_timer);
 		    cops_timer.function = cops_poll;
 		    cops_timer.data 	= (unsigned long)dev;
-		    cops_timer.expires 	= jiffies + 5;
+		    cops_timer.expires 	= jiffies + HZ/20;
 		    add_timer(&cops_timer);
 		} 
 		else 
@@ -700,7 +700,8 @@
 		status = inb(ioaddr+TANG_CARD_STATUS);
 	} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));
 
-	cops_timer.expires = jiffies+5;
+	/* poll 20 times per second */
+	cops_timer.expires = jiffies + HZ/20;
 	add_timer(&cops_timer);
 
 	return;
diff -Nru a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
--- a/drivers/net/appletalk/ltpc.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/appletalk/ltpc.c	Fri Jul 11 01:25:28 2003
@@ -926,8 +926,9 @@
 	if (!dev)
 		return;  /* we've been downed */
 
+	/* poll 20 times per second */
 	idle(dev);
-	ltpc_timer.expires = jiffies+5;
+	ltpc_timer.expires = jiffies + HZ/20;
 	
 	add_timer(&ltpc_timer);
 }
@@ -1217,7 +1218,7 @@
 		ltpc_timer.function=ltpc_poll;
 		ltpc_timer.data = (unsigned long) dev;
 
-		ltpc_timer.expires = jiffies + 5;
+		ltpc_timer.expires = jiffies + HZ/20;
 		add_timer(&ltpc_timer);
 	}
 
diff -Nru a/drivers/net/declance.c b/drivers/net/declance.c
--- a/drivers/net/declance.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/declance.c	Fri Jul 11 01:25:29 2003
@@ -992,7 +992,7 @@
 		return;
 
 	if (lp->tx_old != lp->tx_new) {
-		mod_timer(&lp->multicast_timer, jiffies + 4);
+		mod_timer(&lp->multicast_timer, jiffies + 4 * HZ/100);
 		netif_wake_queue(dev);
 		return;
 	}
diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c
--- a/drivers/net/dgrs.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/dgrs.c	Fri Jul 11 01:25:28 2003
@@ -1252,18 +1252,12 @@
 {
 	DGRS_PRIV	*priv;
 	struct net_device *dev, *aux;
-
-	/* Allocate and fill new device structure. */
-	int dev_size = sizeof(struct net_device) + sizeof(DGRS_PRIV);
 	int i, ret;
 
-	dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
-
+	dev = alloc_etherdev(sizeof(DGRS_PRIV));
 	if (!dev)
 		return -ENOMEM;
 
-	memset(dev, 0, dev_size);
-	dev->priv = ((void *)dev) + sizeof(struct net_device);
 	priv = (DGRS_PRIV *)dev->priv;
 
 	dev->base_addr = io;
@@ -1279,7 +1273,7 @@
 
 	dev->init = dgrs_probe1;
 	SET_MODULE_OWNER(dev);
-	ether_setup(dev);
+
 	if (register_netdev(dev) != 0) {
 		kfree(dev);
 		return -EIO;
@@ -1302,15 +1296,18 @@
 		struct net_device	*devN;
 		DGRS_PRIV	*privN;
 			/* Allocate new dev and priv structures */
-		devN = (struct net_device *) kmalloc(dev_size, GFP_KERNEL);
-			/* Make it an exact copy of dev[0]... */
+		devN = alloc_etherdev(sizeof(DGRS_PRIV));
 		ret = -ENOMEM;
 		if (!devN) 
 			goto fail;
-		memcpy(devN, dev, dev_size);
-		memset(devN->name, 0, sizeof(devN->name));
-		devN->priv = ((void *)devN) + sizeof(struct net_device);
+
+		/* Make it an exact copy of dev[0]... */
+		*devN = *dev;
+
+		/* copy the priv structure of dev[0] */
 		privN = (DGRS_PRIV *)devN->priv;
+		*privN = *priv;
+
 			/* ... and zero out VM areas */
 		privN->vmem = 0;
 		privN->vplxdma = 0;
@@ -1318,9 +1315,11 @@
 		devN->irq = 0;
 			/* ... and base MAC address off address of 1st port */
 		devN->dev_addr[5] += i;
+			/* ... choose a new name */
+		strncpy(devN->name, "eth%d", IFNAMSIZ);
 		devN->init = dgrs_initclone;
 		SET_MODULE_OWNER(devN);
-		ether_setup(devN);
+
 		ret = -EIO;
 		if (register_netdev(devN)) {
 			kfree(devN);
diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
--- a/drivers/net/e100/e100_main.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/e100/e100_main.c	Fri Jul 11 01:25:29 2003
@@ -46,6 +46,13 @@
 
 /* Change Log
  * 
+ * 2.3.18       07/08/03
+ * o Bug fix: read skb->len after freeing skb
+ *   [Andrew Morton] akpm@zip.com.au
+ * o Bug fix: 82557 (with National PHY) timeout during init
+ *   [Adam Kropelin] akropel1@rochester.rr.com
+ * o Feature add: allow to change Wake On LAN when EEPROM disabled
+ * 
  * 2.3.13       05/08/03
  * o Feature remove: /proc/net/PRO_LAN_Adapters support gone completely
  * o Feature remove: IDIAG support (use ethtool -t instead)
@@ -65,20 +72,6 @@
  * o Bug fix: statistic command failure would stop statistic collection.
  * 
  * 2.2.21	02/11/03
- * o Removed marketing brand strings. Instead, Using generic string 
- *   "Intel(R) PRO/100 Network Connection" for all adapters.
- * o Implemented ethtool -S option
- * o Strip /proc/net/PRO_LAN_Adapters files for kernel driver
- * o Bug fix: Read wrong byte in EEPROM when offset is odd number
- * o Bug fix: PHY loopback test fails on ICH devices
- * o Bug fix: System panic on e100_close when repeating Hot Remove and 
- *   Add in a team
- * o Bug fix: Linux Bonding driver claims adapter's link loss because of
- *   not updating last_rx field
- * o Bug fix: e100 does not check validity of MAC address
- * o New feature: added ICH5 support
- * 
- * 2.1.27	11/20/02
  */
  
 #include <linux/config.h>
@@ -144,7 +137,7 @@
 static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
 /* Global Data structures and variables */
 char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation";
-char e100_driver_version[]="2.3.13-k1";
+char e100_driver_version[]="2.3.18-k1";
 const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
 char e100_short_driver_name[] = "e100";
 static int e100nics = 0;
@@ -689,17 +682,16 @@
 
 	bdp->wolsupported = 0;
 	bdp->wolopts = 0;
+	if (bdp->rev_id >= D101A4_REV_ID)
+		bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
+	if (bdp->rev_id >= D101MA_REV_ID)
+		bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
 	
 	/* Check if WoL is enabled on EEPROM */
 	if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) {
 		/* Magic Packet WoL is enabled on device by default */
 		/* if EEPROM WoL bit is TRUE                        */
-		bdp->wolsupported = WAKE_MAGIC;
 		bdp->wolopts = WAKE_MAGIC;
-		if (bdp->rev_id >= D101A4_REV_ID)
-			bdp->wolsupported = WAKE_PHY | WAKE_MAGIC;
-		if (bdp->rev_id >= D101MA_REV_ID)
-			bdp->wolsupported |= WAKE_UCAST | WAKE_ARP;
 	}
 
 	printk(KERN_NOTICE "\n");
diff -Nru a/drivers/net/e100/e100_phy.c b/drivers/net/e100/e100_phy.c
--- a/drivers/net/e100/e100_phy.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/e100/e100_phy.c	Fri Jul 11 01:25:28 2003
@@ -919,6 +919,7 @@
 unsigned char __devinit
 e100_phy_init(struct e100_private *bdp)
 {
+	e100_phy_reset(bdp);
 	e100_phy_address_detect(bdp);
 	e100_phy_isolate(bdp);
 	e100_phy_id_detect(bdp);
@@ -930,7 +931,6 @@
 	bdp->PhyDelay = 0;
 	bdp->zlock_state = ZLOCK_INITIAL;
 
-	e100_phy_reset(bdp);
 	e100_phy_set_speed_duplex(bdp, false);
 	e100_fix_polarity(bdp);
 
diff -Nru a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
--- a/drivers/net/hamradio/mkiss.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/hamradio/mkiss.c	Fri Jul 11 01:25:30 2003
@@ -22,6 +22,8 @@
  *	Matthias (DG2FEF)       Added support for FlexNet CRC (on special request)
  *                              Fixed bug in ax25_close(): dev_lock_wait() was
  *                              called twice, causing a deadlock.
+ *	Jeroen (PE1RXQ)		Removed old MKISS_MAGIC stuff and calls to
+ *				MOD_*_USE_COUNT
  */
 
 #include <linux/config.h>
@@ -55,15 +57,6 @@
 
 static char banner[] __initdata = KERN_INFO "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n";
 
-#define NR_MKISS 4
-#define MKISS_SERIAL_TYPE_NORMAL 1
-
-struct mkiss_channel {
-	int magic;		/* magic word */
-	int init;		/* channel exists? */
-	struct tty_struct *tty; /* link to tty control structure */
-};
-
 typedef struct ax25_ctrl {
 	struct ax_disp ctrl;	/* 				*/
 	struct net_device  dev;	/* the device			*/
@@ -310,19 +303,11 @@
 /* Send one completely decapsulated AX.25 packet to the AX.25 layer. */
 static void ax_bump(struct ax_disp *ax)
 {
-	struct ax_disp *tmp_ax;
 	struct sk_buff *skb;
-	struct mkiss_channel *mkiss;
 	int count;
 
-        tmp_ax = ax;
-
 	if (ax->rbuff[0] > 0x0f) {
-		if (ax->mkiss != NULL) {
-			mkiss= ax->mkiss->tty->driver_data;
-			if (mkiss->magic == MKISS_DRIVER_MAGIC)
-				tmp_ax = ax->mkiss;
-		} else if (ax->rbuff[0] & 0x20) {
+		if (ax->rbuff[0] & 0x20) {
 		        ax->crcmode = CRC_MODE_FLEX;
 			if (check_crc_flex(ax->rbuff, ax->rcount) < 0) {
 			        ax->rx_errors++;
@@ -346,14 +331,14 @@
 		return;
 	}
 
-	skb->dev      = tmp_ax->dev;
+	skb->dev      = ax->dev;
 	memcpy(skb_put(skb,count), ax->rbuff, count);
 	skb->mac.raw  = skb->data;
 	skb->protocol = htons(ETH_P_AX25);
 	netif_rx(skb);
-	tmp_ax->dev->last_rx = jiffies;
-	tmp_ax->rx_packets++;
-	tmp_ax->rx_bytes+=count;
+	ax->dev->last_rx = jiffies;
+	ax->rx_packets++;
+	ax->rx_bytes+=count;
 }
 
 /* Encapsulate one AX.25 packet and stuff into a TTY queue. */
@@ -361,7 +346,6 @@
 {
 	unsigned char *p;
 	int actual, count;
-	struct mkiss_channel *mkiss = ax->tty->driver_data;
 
 	if (ax->mtu != ax->dev->mtu + 73)	/* Someone has been ifconfigging */
 		ax_changedmtu(ax);
@@ -376,37 +360,26 @@
 
 	p = icp;
 
-	if (mkiss->magic  != MKISS_DRIVER_MAGIC) {
-	        switch (ax->crcmode) {
-		         unsigned short crc;
-
-		case CRC_MODE_FLEX:
-		         *p |= 0x20;
-		         crc = calc_crc_flex(p, len);
-			 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
-			 break;
-
-		default:
-		         count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
-			 break;
-		}
-		ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-		actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count);
-		ax->tx_packets++;
-		ax->tx_bytes+=actual;
-		ax->dev->trans_start = jiffies;
-		ax->xleft = count - actual;
-		ax->xhead = ax->xbuff + actual;
-	} else {
-		count = kiss_esc(p, (unsigned char *) ax->mkiss->xbuff, len);
-		ax->mkiss->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-		actual = ax->mkiss->tty->driver->write(ax->mkiss->tty, 0, ax->mkiss->xbuff, count);
-		ax->tx_packets++;
-		ax->tx_bytes+=actual;
-		ax->mkiss->dev->trans_start = jiffies;
-		ax->mkiss->xleft = count - actual;
-		ax->mkiss->xhead = ax->mkiss->xbuff + actual;
-	}
+        switch (ax->crcmode) {
+	         unsigned short crc;
+
+	case CRC_MODE_FLEX:
+	         *p |= 0x20;
+	         crc = calc_crc_flex(p, len);
+		 count = kiss_esc_crc(p, (unsigned char *)ax->xbuff, crc, len+2);
+		 break;
+
+	default:
+	         count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
+		 break;
+	}
+	ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+	actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count);
+	ax->tx_packets++;
+	ax->tx_bytes+=actual;
+	ax->dev->trans_start = jiffies;
+	ax->xleft = count - actual;
+	ax->xhead = ax->xbuff + actual;
 }
 
 /*
@@ -417,7 +390,6 @@
 {
 	int actual;
 	struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
-	struct mkiss_channel *mkiss;
 
 	/* First make sure we're connected. */
 	if (ax == NULL || ax->magic != AX25_MAGIC || !netif_running(ax->dev))
@@ -428,12 +400,6 @@
 		 */
 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
-		if (ax->mkiss != NULL) {
-			mkiss= ax->mkiss->tty->driver_data;
-			if (mkiss->magic  == MKISS_DRIVER_MAGIC)
-				ax_unlock(ax->mkiss);
-	        }
-
 		netif_wake_queue(ax->dev);
 		return;
 	}
@@ -447,32 +413,12 @@
 static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ax_disp *ax = (struct ax_disp *) dev->priv;
-	struct mkiss_channel *mkiss = ax->tty->driver_data;
-	struct ax_disp *tmp_ax;
-
-	tmp_ax = NULL;
-
-	if (mkiss->magic  == MKISS_DRIVER_MAGIC) {
-		if (skb->data[0] < 0x10)
-			skb->data[0] = skb->data[0] + 0x10;
-		tmp_ax = ax->mkiss;
-	}
 
 	if (!netif_running(dev))  {
 		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
 		return 1;
 	}
 
-	if (tmp_ax != NULL)
-		if (netif_queue_stopped(tmp_ax->dev))
-			return 1;
-
-	if (tmp_ax != NULL)
-		if (netif_queue_stopped(dev)) {
-			printk(KERN_ERR "mkiss: dev busy while serial dev is free\n");
-			ax_unlock(ax);
-	        }
-
 	if (netif_queue_stopped(dev)) {
 		/*
 		 * May be we must check transmitter timeout here ?
@@ -495,8 +441,6 @@
 	/* We were not busy, so we are now... :-) */
 	if (skb != NULL) {
 		ax_lock(ax);
-		if (tmp_ax != NULL)
-			ax_lock(tmp_ax);
 		ax_encaps(ax, skb->data, skb->len);
 		kfree_skb(skb);
 	}
@@ -634,9 +578,7 @@
 static int ax25_open(struct tty_struct *tty)
 {
 	struct ax_disp *ax = (struct ax_disp *) tty->disc_data;
-	struct ax_disp *tmp_ax;
-	struct mkiss_channel *mkiss;
-	int err, cnt;
+	int err;
 
 	/* First make sure we're not already connected. */
 	if (ax && ax->magic == AX25_MAGIC)
@@ -649,9 +591,6 @@
 	ax->tty = tty;
 	tty->disc_data = ax;
 
-	ax->mkiss = NULL;
-	tmp_ax    = NULL;
-
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 	if (tty->ldisc.flush_buffer)
@@ -664,29 +603,6 @@
 	if ((err = ax_open(ax->dev)))
 		return err;
 
-	mkiss = ax->tty->driver_data;
-
-	if (mkiss->magic  == MKISS_DRIVER_MAGIC) {
-		for (cnt = 1; cnt < ax25_maxdev; cnt++) {
-			if (ax25_ctrls[cnt]) {
-				if (netif_running(&ax25_ctrls[cnt]->dev)) {
-					if (ax == &ax25_ctrls[cnt]->ctrl) {
-						cnt--;
-						tmp_ax = &ax25_ctrls[cnt]->ctrl;
-						break;
-					}
-				}
-			}
-		}
-	}
-
-	if (tmp_ax != NULL) {
-		ax->mkiss     = tmp_ax;
-		tmp_ax->mkiss = ax;
-	}
-
-	MOD_INC_USE_COUNT;
-
 	/* Done.  We have linked the TTY line to a channel. */
 	return ax->dev->base_addr;
 }
@@ -705,7 +621,6 @@
 	ax->tty        = NULL;
 
 	ax_free(ax);
-	MOD_DEC_USE_COUNT;
 }
 
 
diff -Nru a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h
--- a/drivers/net/hamradio/mkiss.h	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/hamradio/mkiss.h	Fri Jul 11 01:25:28 2003
@@ -19,7 +19,6 @@
 	/* Various fields. */
 	struct tty_struct  *tty;		/* ptr to TTY structure		*/
 	struct net_device      *dev;		/* easy for intr handling	*/
-	struct ax_disp     *mkiss;		/* mkiss txport if mkiss channel*/
 
 	/* These are pointers to the malloc()ed frame buffers. */
 	unsigned char      *rbuff;		/* receiver buffer		*/
@@ -60,4 +59,3 @@
 };
 
 #define AX25_MAGIC		0x5316
-#define MKISS_DRIVER_MAGIC	1215
diff -Nru a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
--- a/drivers/net/irda/Kconfig	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/irda/Kconfig	Fri Jul 11 01:25:29 2003
@@ -22,6 +22,7 @@
 
 config DONGLE
 	bool "Serial dongle support"
+	depends on IRTTY_SIR
 	help
 	  Say Y here if you have an infrared device that connects to your
 	  computer's serial port. These devices are called dongles. Then say Y
@@ -69,7 +70,7 @@
 
 config IRTTY_OLD
 	tristate "Old IrTTY (broken)"
-	depends on IRDA
+	depends on IRDA && EXPERIMENTAL
 	help
 	  Say Y here if you want to build support for the IrTTY line
 	  discipline.  If you want to compile it as a module (irtty), say M
@@ -102,6 +103,7 @@
 
 config DONGLE_OLD
 	bool "Old Serial dongle support"
+	depends on IRTTY_OLD || IRPORT_SIR
 	help
 	  Say Y here if you have an infrared device that connects to your
 	  computer's serial port. These devices are called dongles. Then say Y
@@ -226,8 +228,8 @@
 comment "FIR device drivers"
 
 config USB_IRDA
-	tristate "IrDA USB dongles (EXPERIMENTAL)"
-	depends on IRDA && USB && EXPERIMENTAL
+	tristate "IrDA USB dongles"
+	depends on IRDA && USB
 	---help---
 	  Say Y here if you want to build support for the USB IrDA FIR Dongle
 	  device driver.  If you want to compile it as a module (irda-usb),
@@ -243,7 +245,7 @@
 
 config NSC_FIR
 	tristate "NSC PC87108/PC87338"
-	depends on IRDA
+	depends on IRDA && ISA
 	help
 	  Say Y here if you want to build support for the NSC PC87108 and
 	  PC87338 IrDA chipsets.  This driver supports SIR,
@@ -255,7 +257,7 @@
 
 config WINBOND_FIR
 	tristate "Winbond W83977AF (IR)"
-	depends on IRDA
+	depends on IRDA && ISA
 	help
 	  Say Y here if you want to build IrDA support for the Winbond
 	  W83977AF super-io chipset.  This driver should be used for the IrDA
@@ -295,7 +297,7 @@
 
 config SMC_IRCC_OLD
 	tristate "SMC IrCC (old driver) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && IRDA
+	depends on EXPERIMENTAL && IRDA && ISA
 	help
 	  Say Y here if you want to build support for the SMC Infrared
 	  Communications Controller.  It is used in the Fujitsu Lifebook 635t
@@ -307,7 +309,7 @@
 
 config SMC_IRCC_FIR
 	tristate "SMSC IrCC (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && IRDA
+	depends on EXPERIMENTAL && IRDA && ISA
 	help
 	  Say Y here if you want to build support for the SMC Infrared
 	  Communications Controller.  It is used in a wide variety of
@@ -318,7 +320,7 @@
 
 config ALI_FIR
 	tristate "ALi M5123 FIR (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && IRDA
+	depends on EXPERIMENTAL && IRDA && ISA
 	help
 	  Say Y here if you want to build support for the ALi M5123 FIR
 	  Controller.  The ALi M5123 FIR Controller is embedded in ALi M1543C,
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/irda/irda-usb.c	Fri Jul 11 01:25:29 2003
@@ -74,8 +74,10 @@
 
 /* These are the currently known IrDA USB dongles. Add new dongles here */
 static struct usb_device_id dongles[] = {
-	/* ACTiSYS Corp,  ACT-IR2000U FIR-USB Adapter */
+	/* ACTiSYS Corp.,  ACT-IR2000U FIR-USB Adapter */
 	{ USB_DEVICE(0x9c4, 0x011), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
+	/* Look like ACTiSYS, Report : IBM Corp., IBM UltraPort IrDA */
+	{ USB_DEVICE(0x4428, 0x012), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW },
 	/* KC Technology Inc.,  KC-180 USB IrDA Device */
 	{ USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
 	/* Extended Systems, Inc.,  XTNDAccess IrDA USB (ESI-9685) */
@@ -1123,7 +1125,10 @@
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&self->qos);
 
-	self->qos.baud_rate.bits       = desc->wBaudRate;
+	/* See spec section 7.2 for meaning.
+	 * Values are little endian (as most USB stuff), the IrDA stack
+	 * use it in native order (see parameters.c). - Jean II */
+	self->qos.baud_rate.bits       = le16_to_cpu(desc->wBaudRate);
 	self->qos.min_turn_time.bits   = desc->bmMinTurnaroundTime;
 	self->qos.additional_bofs.bits = desc->bmAdditionalBOFs;
 	self->qos.window_size.bits     = desc->bmWindowSize;
@@ -1134,7 +1139,7 @@
 
 	/* Don't always trust what the dongle tell us */
 	if(self->capability & IUC_SIR_ONLY)
-		self->qos.baud_rate.bits	&= 0xff;
+		self->qos.baud_rate.bits	&= 0x00ff;
 	if(self->capability & IUC_SMALL_PKT)
 		self->qos.data_size.bits	 = 0x07;
 	if(self->capability & IUC_NO_WINDOW)
@@ -1327,13 +1332,14 @@
  */
 static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc)
 {
+	/* Values are little endian */
 	printk("bLength=%x\n", desc->bLength);
 	printk("bDescriptorType=%x\n", desc->bDescriptorType);
-	printk("bcdSpecRevision=%x\n", desc->bcdSpecRevision); 
+	printk("bcdSpecRevision=%x\n", le16_to_cpu(desc->bcdSpecRevision)); 
 	printk("bmDataSize=%x\n", desc->bmDataSize);
 	printk("bmWindowSize=%x\n", desc->bmWindowSize);
 	printk("bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime);
-	printk("wBaudRate=%x\n", desc->wBaudRate);
+	printk("wBaudRate=%x\n", le16_to_cpu(desc->wBaudRate));
 	printk("bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs);
 	printk("bIrdaRateSniff=%x\n", desc->bIrdaRateSniff);
 	printk("bMaxUnicastList=%x\n", desc->bMaxUnicastList);
diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
--- a/drivers/net/irda/nsc-ircc.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/irda/nsc-ircc.c	Fri Jul 11 01:25:28 2003
@@ -81,8 +81,10 @@
 
 static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info);
 
 /* These are the known NSC chips */
 static nsc_chip_t chips[] = {
@@ -94,6 +96,10 @@
 	/* Contributed by Kevin Thayer - OmniBook 6100 */
 	{ "PC87338?", { 0x2e, 0x15c, 0x398 }, 0x08, 0x00, 0xf8, 
 	  nsc_ircc_probe_338, nsc_ircc_init_338 },
+	/* Contributed by Jan Frey - IBM A30/A31 */
+	/* Should use nsc_ircc_probe_39x properly */
+	{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, 
+	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
 	{ NULL }
 };
 
@@ -426,7 +432,7 @@
 	outb(0x00, cfg_base+1); /* Disable device */
 	
 	/* Base Address and Interrupt Control Register (BAIC) */
-	outb(0, cfg_base);
+	outb(CFG_108_BAIC, cfg_base);
 	switch (info->fir_base) {
 	case 0x3e8: outb(0x14, cfg_base+1); break;
 	case 0x2e8: outb(0x15, cfg_base+1); break;
@@ -446,7 +452,7 @@
 	case 15: temp = 0x07; break;
 	default: ERROR("%s(), invalid irq", __FUNCTION__);
 	}
-	outb(1, cfg_base);
+	outb(CFG_108_CSRT, cfg_base);
 	
 	switch (info->dma) {	
 	case 0: outb(0x08+temp, cfg_base+1); break;
@@ -455,7 +461,7 @@
 	default: ERROR("%s(), invalid dma", __FUNCTION__);
 	}
 	
-	outb(2, cfg_base);      /* Mode Control Register (MCTL) */
+	outb(CFG_108_MCTL, cfg_base);      /* Mode Control Register (MCTL) */
 	outb(0x03, cfg_base+1); /* Enable device */
 
 	return 0;
@@ -473,7 +479,7 @@
 	int reg;
 
 	/* Read address and interrupt control register (BAIC) */
-	outb(CFG_BAIC, cfg_base);
+	outb(CFG_108_BAIC, cfg_base);
 	reg = inb(cfg_base+1);
 	
 	switch (reg & 0x03) {
@@ -495,7 +501,7 @@
 		   info->fir_base);
 
 	/* Read control signals routing register (CSRT) */
-	outb(CFG_CSRT, cfg_base);
+	outb(CFG_108_CSRT, cfg_base);
 	reg = inb(cfg_base+1);
 
 	switch (reg & 0x07) {
@@ -544,7 +550,7 @@
 	IRDA_DEBUG(2, "%s(), probing dma=%d\n", __FUNCTION__, info->dma);
 
 	/* Read mode control register (MCTL) */
-	outb(CFG_MCTL, cfg_base);
+	outb(CFG_108_MCTL, cfg_base);
 	reg = inb(cfg_base+1);
 
 	info->enabled = reg & 0x01;
@@ -581,13 +587,194 @@
 	int pnp;
 
 	/* Read funtion enable register (FER) */
-	outb(CFG_FER, cfg_base);
+	outb(CFG_338_FER, cfg_base);
+	reg = inb(cfg_base+1);
+
+	info->enabled = (reg >> 2) & 0x01;
+
+	/* Check if we are in Legacy or PnP mode */
+	outb(CFG_338_PNP0, cfg_base);
+	reg = inb(cfg_base+1);
+	
+	pnp = (reg >> 3) & 0x01;
+	if (pnp) {
+		IRDA_DEBUG(2, "(), Chip is in PnP mode\n");
+		outb(0x46, cfg_base);
+		reg = (inb(cfg_base+1) & 0xfe) << 2;
+
+		outb(0x47, cfg_base);
+		reg |= ((inb(cfg_base+1) & 0xfc) << 8);
+
+		info->fir_base = reg;
+	} else {
+		/* Read function address register (FAR) */
+		outb(CFG_338_FAR, cfg_base);
+		reg = inb(cfg_base+1);
+		
+		switch ((reg >> 4) & 0x03) {
+		case 0:
+			info->fir_base = 0x3f8;
+			break;
+		case 1:
+			info->fir_base = 0x2f8;
+			break;
+		case 2:
+			com = 3;
+			break;
+		case 3:
+			com = 4;
+			break;
+		}
+		
+		if (com) {
+			switch ((reg >> 6) & 0x03) {
+			case 0:
+				if (com == 3)
+					info->fir_base = 0x3e8;
+				else
+					info->fir_base = 0x2e8;
+				break;
+			case 1:
+				if (com == 3)
+					info->fir_base = 0x338;
+				else
+					info->fir_base = 0x238;
+				break;
+			case 2:
+				if (com == 3)
+					info->fir_base = 0x2e8;
+				else
+					info->fir_base = 0x2e0;
+				break;
+			case 3:
+				if (com == 3)
+					info->fir_base = 0x220;
+				else
+					info->fir_base = 0x228;
+				break;
+			}
+		}
+	}
+	info->sir_base = info->fir_base;
+
+	/* Read PnP register 1 (PNP1) */
+	outb(CFG_338_PNP1, cfg_base);
+	reg = inb(cfg_base+1);
+	
+	info->irq = reg >> 4;
+	
+	/* Read PnP register 3 (PNP3) */
+	outb(CFG_338_PNP3, cfg_base);
+	reg = inb(cfg_base+1);
+
+	info->dma = (reg & 0x07) - 1;
+
+	/* Read power and test register (PTR) */
+	outb(CFG_338_PTR, cfg_base);
+	reg = inb(cfg_base+1);
+
+	info->suspended = reg & 0x01;
+
+	return 0;
+}
+
+
+/*
+ * Function nsc_ircc_init_39x (chip, info)
+ *
+ *    Now that we know it's a '39x (see probe below), we need to
+ *    configure it so we can use it.
+ *
+ * The NSC '338 chip is a Super I/O chip with a "bank" architecture,
+ * the configuration of the different functionality (serial, parallel,
+ * floppy...) are each in a different bank (Logical Device Number).
+ * The base address, irq and dma configuration registers are common
+ * to all functionalities (index 0x30 to 0x7F).
+ * There is only one configuration register specific to the
+ * serial port, CFG_39X_SPC.
+ * JeanII
+ *
+ * Note : this code was written by Jan Frey <janfrey@web.de>
+ */
+static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info) 
+{
+	int cfg_base = info->cfg_base;
+	int reg1, reg2, irq, irqt, dma1, dma2;
+	int enabled, susp;
+
+	/* This function should be executed with irq off to avoid
+	 * another driver messing with the Super I/O bank - Jean II */
+
+	/* Access bank for SP2 */
+	outb(CFG_39X_LDN, cfg_base);
+	outb(0x02, cfg_base+1);
+
+	/* Read infos about SP2 */
+	outb(CFG_39X_BASEH, cfg_base);
+	reg1 = inb(cfg_base+1);
+	outb(CFG_39X_BASEL, cfg_base);
+	reg2 = inb(cfg_base+1);
+	info->fir_base = (reg1 << 8) | reg2;
+
+	outb(CFG_39X_IRQNUM, cfg_base);
+	irq = inb(cfg_base+1);
+	outb(CFG_39X_IRQSEL, cfg_base);
+	irqt = inb(cfg_base+1);
+	info->irq = irq;
+
+	outb(CFG_39X_DMA0, cfg_base);
+	dma1 = inb(cfg_base+1);
+	outb(CFG_39X_DMA1, cfg_base);
+	dma2 = inb(cfg_base+1);
+	info->dma = dma1 -1;
+
+	outb(CFG_39X_ACT, cfg_base);
+	enabled = inb(cfg_base+1) & 0x01;
+
+	outb(CFG_39X_SPC, cfg_base);
+	susp = 1 - ((inb(cfg_base+1) & 0x02) >> 1);
+
+	/* We should store those values in info ? Jean II */
+
+	IRDA_DEBUG(2, "%s(): io=0x%02x%02x, irq=%d (type %d), rxdma=%d, txdma=%d, enabled=%d (suspended=%d)\n", __FUNCTION__, reg1,reg2,irq,irqt,dma1,dma2,enabled,susp);
+
+	/* Configure SP2 */
+
+	/* Do we want to enable the device if not enabled ? */
+
+	/* Enable UART bank switching (bit 7) */
+	outb(CFG_39X_SPC, cfg_base);
+	outb(0x80, cfg_base+1);
+
+	return 0;
+}
+
+/*
+ * Function nsc_ircc_probe_39x (chip, info)
+ *
+ *    Test if we really have a '39x chip at the given address
+ *
+ */
+static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) 
+{
+#if 0
+	int cfg_base = info->cfg_base;
+	int reg, com = 0;
+	int pnp;
+#endif
+
+	/* Why are we using the '338 configuration registers in here ?
+	 * This probably need to be rewritten...
+	 * Jean II */
+#if 0
+	/* Read funtion enable register (FER) */
+	outb(CFG_338_FER, cfg_base);
 	reg = inb(cfg_base+1);
 
 	info->enabled = (reg >> 2) & 0x01;
 
 	/* Check if we are in Legacy or PnP mode */
-	outb(CFG_PNP0, cfg_base);
+	outb(CFG_338_PNP0, cfg_base);
 	reg = inb(cfg_base+1);
 	
 	pnp = (reg >> 3) & 0x01;
@@ -602,7 +789,7 @@
 		info->fir_base = reg;
 	} else {
 		/* Read function address register (FAR) */
-		outb(CFG_FAR, cfg_base);
+		outb(CFG_338_FAR, cfg_base);
 		reg = inb(cfg_base+1);
 		
 		switch ((reg >> 4) & 0x03) {
@@ -652,22 +839,23 @@
 	info->sir_base = info->fir_base;
 
 	/* Read PnP register 1 (PNP1) */
-	outb(CFG_PNP1, cfg_base);
+	outb(CFG_338_PNP1, cfg_base);
 	reg = inb(cfg_base+1);
 	
 	info->irq = reg >> 4;
 	
 	/* Read PnP register 3 (PNP3) */
-	outb(CFG_PNP3, cfg_base);
+	outb(CFG_338_PNP3, cfg_base);
 	reg = inb(cfg_base+1);
 
 	info->dma = (reg & 0x07) - 1;
 
 	/* Read power and test register (PTR) */
-	outb(CFG_PTR, cfg_base);
+	outb(CFG_338_PTR, cfg_base);
 	reg = inb(cfg_base+1);
 
 	info->suspended = reg & 0x01;
+#endif
 
 	return 0;
 }
diff -Nru a/drivers/net/irda/old_belkin.c b/drivers/net/irda/old_belkin.c
--- a/drivers/net/irda/old_belkin.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/irda/old_belkin.c	Fri Jul 11 01:25:30 2003
@@ -32,8 +32,6 @@
 #include <linux/delay.h>
 #include <linux/tty.h>
 #include <linux/init.h>
-#include <linux/net.h>
-#include <linux/irda.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>
diff -Nru a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
--- a/drivers/net/pcmcia/3c574_cs.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/pcmcia/3c574_cs.c	Fri Jul 11 01:25:28 2003
@@ -1048,7 +1048,7 @@
 	}
 	if (lp->fast_poll) {
 		lp->fast_poll--;
-		lp->media.expires = jiffies + 2;
+		lp->media.expires = jiffies + 2*HZ/100;
 		add_timer(&lp->media);
 		return;
 	}
diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
--- a/drivers/net/pcmcia/3c589_cs.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/pcmcia/3c589_cs.c	Fri Jul 11 01:25:30 2003
@@ -921,7 +921,7 @@
     }
     if (lp->fast_poll) {
 	lp->fast_poll--;
-	lp->media.expires = jiffies + 1;
+	lp->media.expires = jiffies + HZ/100;
 	add_timer(&lp->media);
 	return;
     }
diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
--- a/drivers/net/pcmcia/smc91c92_cs.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/pcmcia/smc91c92_cs.c	Fri Jul 11 01:25:29 2003
@@ -1996,7 +1996,7 @@
     }
     if (smc->fast_poll) {
 	smc->fast_poll--;
-	smc->media.expires = jiffies + 1;
+	smc->media.expires = jiffies + HZ/100;
 	add_timer(&smc->media);
 	SMC_SELECT_BANK(saved_bank);
 	return;
diff -Nru a/drivers/net/plip.c b/drivers/net/plip.c
--- a/drivers/net/plip.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/plip.c	Fri Jul 11 01:25:30 2003
@@ -277,27 +277,10 @@
    then calls us here.
 
    */
-int __init
-plip_init_dev(struct net_device *dev, struct parport *pb)
+static int
+plip_init_netdev(struct net_device *dev)
 {
-	struct net_local *nl;
-	struct pardevice *pardev;
-
-	SET_MODULE_OWNER(dev);
-	dev->irq = pb->irq;
-	dev->base_addr = pb->base;
-
-	if (pb->irq == -1) {
-		printk(KERN_INFO "plip: %s has no IRQ. Using IRQ-less mode,"
-		                 "which is fairly inefficient!\n", pb->name);
-	}
-
-	pardev = parport_register_device(pb, dev->name, plip_preempt,
-					 plip_wakeup, plip_interrupt, 
-					 0, dev);
-
-	if (!pardev)
-		return -ENODEV;
+	struct net_local *nl = dev->priv;
 
 	printk(KERN_INFO "%s", version);
 	if (dev->irq != -1)
@@ -307,9 +290,6 @@
 		printk(KERN_INFO "%s: Parallel port at %#3lx, not using IRQ.\n",
 		       dev->name, dev->base_addr);
 
-	/* Fill in the generic fields of the device structure. */
-	ether_setup(dev);
-
 	/* Then, override parts of it */
 	dev->hard_start_xmit	 = plip_tx_packet;
 	dev->open		 = plip_open;
@@ -322,22 +302,12 @@
 	memset(dev->dev_addr, 0xfc, ETH_ALEN);
 
 	/* Set the private structure */
-	dev->priv = kmalloc(sizeof (struct net_local), GFP_KERNEL);
-	if (dev->priv == NULL) {
-		printk(KERN_ERR "%s: out of memory\n", dev->name);
-		parport_unregister_device(pardev);
-		return -ENOMEM;
-	}
-	memset(dev->priv, 0, sizeof(struct net_local));
-	nl = (struct net_local *) dev->priv;
-
 	nl->orig_hard_header    = dev->hard_header;
 	dev->hard_header        = plip_hard_header;
 
 	nl->orig_hard_header_cache = dev->hard_header_cache;
 	dev->hard_header_cache     = plip_hard_header_cache;
 
-	nl->pardev = pardev; 
 
 	nl->port_owner = 0;
 
@@ -1299,29 +1269,52 @@
  * available to use. */
 static void plip_attach (struct parport *port)
 {
-	static int i;
+	static int unit;
+	struct net_device *dev;
+	struct net_local *nl;
+	char name[IFNAMSIZ];
 
 	if ((parport[0] == -1 && (!timid || !port->devices)) || 
 	    plip_searchfor(parport, port->number)) {
-		if (i == PLIP_MAX) {
+		if (unit == PLIP_MAX) {
 			printk(KERN_ERR "plip: too many devices\n");
 			return;
 		}
-		dev_plip[i] = kmalloc(sizeof(struct net_device),
-				      GFP_KERNEL);
-		if (!dev_plip[i]) {
+
+		sprintf(name, "plip%d", unit);
+		dev = alloc_netdev(sizeof(struct net_local), name, 
+				   ether_setup);
+		if (!dev) {
 			printk(KERN_ERR "plip: memory squeeze\n");
 			return;
 		}
-		memset(dev_plip[i], 0, sizeof(struct net_device));
-		sprintf(dev_plip[i]->name, "plip%d", i);
-		dev_plip[i]->priv = port;
-		if (plip_init_dev(dev_plip[i],port) ||
-		    register_netdev(dev_plip[i])) {
-			kfree(dev_plip[i]);
-			dev_plip[i] = NULL;
+		
+		dev->init = plip_init_netdev;
+
+		SET_MODULE_OWNER(dev);
+		dev->irq = port->irq;
+		dev->base_addr = port->base;
+		if (port->irq == -1) {
+			printk(KERN_INFO "plip: %s has no IRQ. Using IRQ-less mode,"
+		                 "which is fairly inefficient!\n", port->name);
+		}
+
+		nl = dev->priv;
+		nl->pardev = parport_register_device(port, name, plip_preempt,
+						 plip_wakeup, plip_interrupt, 
+						 0, dev);
+
+		if (!nl->pardev) {
+			printk(KERN_ERR "%s: parport_register failed\n", name);
+			kfree(dev);
+			return;
+		}
+
+		if (register_netdev(dev)) {
+			printk(KERN_ERR "%s: network register failed\n", name);
+			kfree(dev);
 		} else {
-			i++;
+			dev_plip[unit++] = dev;
 		}
 	}
 }
@@ -1341,20 +1334,19 @@
 
 static void __exit plip_cleanup_module (void)
 {
+	struct net_device *dev;
 	int i;
 
 	parport_unregister_driver (&plip_driver);
 
 	for (i=0; i < PLIP_MAX; i++) {
-		if (dev_plip[i]) {
-			struct net_local *nl =
-				(struct net_local *)dev_plip[i]->priv;
-			unregister_netdev(dev_plip[i]);
+		if ((dev = dev_plip[i])) {
+			struct net_local *nl = dev->priv;
+			unregister_netdev(dev);
 			if (nl->port_owner)
 				parport_release(nl->pardev);
 			parport_unregister_device(nl->pardev);
-			kfree(dev_plip[i]->priv);
-			kfree(dev_plip[i]);
+			kfree(dev);
 			dev_plip[i] = NULL;
 		}
 	}
diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
--- a/drivers/net/sb1250-mac.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/sb1250-mac.c	Fri Jul 11 01:25:30 2003
@@ -2493,7 +2493,7 @@
 	
 	/* Set the timer to check for link beat. */
 	init_timer(&sc->sbm_timer);
-	sc->sbm_timer.expires = jiffies + 2;
+	sc->sbm_timer.expires = jiffies + 2 * HZ/100;
 	sc->sbm_timer.data = (unsigned long)dev;
 	sc->sbm_timer.function = &sbmac_timer;
 	add_timer(&sc->sbm_timer);
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/sk_mca.c	Fri Jul 11 01:25:29 2003
@@ -537,7 +537,7 @@
 	ResetBoard(dev);
 	InitBoard(dev);
 
-	njiffies = jiffies + 100;
+	njiffies = jiffies + HZ;
 	do {
 		csr0val = GetLANCE(dev, LANCE_CSR0);
 	}
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/sundance.c	Fri Jul 11 01:25:29 2003
@@ -87,11 +87,15 @@
 	Version LK1.09 (D-Link):
 	- Fix the flowctrl bug.	
 	- Set Pause bit in MII ANAR if flow control enabled.	
+
+	Version LK1.09a (ICPlus):
+	- Add the delay time in reading the contents of EEPROM
+
 */
 
 #define DRV_NAME	"sundance"
 #define DRV_VERSION	"1.01+LK1.09a"
-#define DRV_RELDATE	"16-May-2003"
+#define DRV_RELDATE	"10-Jul-2003"
 
 
 /* The user-configurable values.
@@ -744,12 +748,14 @@
 	return 0;
 }
 
+#define eeprom_delay(ee_addr)	readl(ee_addr)
 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
 static int __devinit eeprom_read(long ioaddr, int location)
 {
-	int boguscnt = 1000;		/* Typical 190 ticks. */
+	int boguscnt = 10000;		/* Typical 1900 ticks. */
 	writew(0x0200 | (location & 0xff), ioaddr + EECtrl);
 	do {
+		eeprom_delay(ioaddr + EECtrl);
 		if (! (readw(ioaddr + EECtrl) & 0x8000)) {
 			return readw(ioaddr + EEData);
 		}
diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c
--- a/drivers/net/sunhme.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/sunhme.c	Fri Jul 11 01:25:28 2003
@@ -1521,12 +1521,6 @@
 	hme_write32(hp, bregs + BMAC_IGAP1, DEFAULT_IPG1);
 	hme_write32(hp, bregs + BMAC_IGAP2, DEFAULT_IPG2);
 
-	/* Make sure we can handle VLAN frames.  */
-	hme_write32(hp, bregs + BMAC_TXMAX,
-		    ETH_DATA_LEN + ETH_HLEN + 8);
-	hme_write32(hp, bregs + BMAC_RXMAX,
-		    ETH_DATA_LEN + ETH_HLEN + 8);
-
 	/* Load up the MAC address and random seed. */
 	HMD(("rseed/macaddr, "));
 
@@ -2805,8 +2799,8 @@
 	dev->watchdog_timeo = 5*HZ;
 	dev->do_ioctl = &happy_meal_ioctl;
 
-	/* Happy Meal can do it all... */
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+	/* Happy Meal can do it all... except VLAN. */
+	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_VLAN_CHALLENGED;
 
 	dev->irq = sdev->irqs[0];
 
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/tg3.c	Fri Jul 11 01:25:29 2003
@@ -6679,10 +6679,9 @@
 	}
 
 	/* Configure DMA attributes. */
-	if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) {
+	if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
 		pci_using_dac = 1;
-		if (pci_set_consistent_dma_mask(pdev,
-						(u64) 0xffffffffffffffff)) {
+		if (pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL)) {
 			printk(KERN_ERR PFX "Unable to obtain 64 bit DMA "
 			       "for consistent allocations\n");
 			goto err_out_free_res;
diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
--- a/drivers/net/tokenring/3c359.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/tokenring/3c359.c	Fri Jul 11 01:25:30 2003
@@ -464,7 +464,7 @@
 		
 		printk(KERN_INFO "3C359: Uploading Microcode: "); 
 		
-		for (i = start,j=0; (j < mc_size && i <= 0xffff) ; i++,j++) { 
+		for (i = start, j = 0; j < mc_size; i++, j++) { 
 			writel(MEM_BYTE_WRITE | 0XD0000 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; 
 			writeb(microcode[j],xl_mmio + MMIO_MACDATA) ; 
 			if (j % 1024 == 0)
diff -Nru a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
--- a/drivers/net/tokenring/proteon.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/tokenring/proteon.c	Fri Jul 11 01:25:30 2003
@@ -401,7 +401,6 @@
 int init_module(void)
 {
 	int i, num;
-	struct net_device *dev;
 
 	num = 0;
 	if (io[0]) { /* Only probe addresses from command line */
diff -Nru a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
--- a/drivers/net/tokenring/skisa.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/net/tokenring/skisa.c	Fri Jul 11 01:25:28 2003
@@ -414,7 +414,6 @@
 int init_module(void)
 {
 	int i, num;
-	struct net_device *dev;
 
 	num = 0;
 	if (io[0]) { /* Only probe addresses from command line */
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/net/via-rhine.c	Fri Jul 11 01:25:30 2003
@@ -1152,7 +1152,7 @@
 
 	/* Set the timer to check for link beat. */
 	init_timer(&np->timer);
-	np->timer.expires = jiffies + 2;
+	np->timer.expires = jiffies + 2 * HZ/100;
 	np->timer.data = (unsigned long)dev;
 	np->timer.function = &via_rhine_timer;				/* timer handler */
 	add_timer(&np->timer);
diff -Nru a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
--- a/drivers/net/wireless/atmel_cs.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/wireless/atmel_cs.c	Fri Jul 11 01:25:29 2003
@@ -391,7 +391,7 @@
 	local_info_t *dev;
 	int last_fn, last_ret;
 	u_char buf[64];
-	int card_index = -1;
+	int card_index = -1, done = 0;
 	
 	handle = link->handle;
 	dev = link->priv;
@@ -415,13 +415,13 @@
 			    manfid->manf == card_table[i].manf &&
 			    manfid->card == card_table[i].card) {
 				card_index = i;
-				goto done;
+				done = 1;
 			}
 		}
 	}
 
 	tuple.DesiredTuple = CISTPL_VERS_1;
-	if (CardServices(GetFirstTuple, handle, &tuple) == 0) {
+	if (!done && (CardServices(GetFirstTuple, handle, &tuple) == 0)) {
 		int i, j, k;
 		cistpl_vers_1_t *ver1;
 		CS_CHECK(GetTupleData, handle, &tuple);
@@ -446,12 +446,11 @@
 					goto mismatch;
 			}
 			card_index = i;
-			goto done;
+			break;	/* done */
 			
 		mismatch:
-			
+			j = 0; /* dummy stmt to shut up compiler */
 		}
-	done:
 	}		
 
 	/*
diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
--- a/drivers/net/wireless/wavelan.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/net/wireless/wavelan.c	Fri Jul 11 01:25:29 2003
@@ -3730,8 +3730,8 @@
 	int i;			/* Loop counter */
 
 	/* Check if the base address if available. */
-	if (check_region(ioaddr, sizeof(ha_t)))
-		return -EADDRINUSE;	/* ioaddr already used */
+	if (!request_region(ioaddr, sizeof(ha_t), "wavelan probe"))
+		return -EBUSY;		/* ioaddr already used */
 
 	/* Reset host interface */
 	wv_hacr_reset(ioaddr);
@@ -3739,6 +3739,8 @@
 	/* Read the MAC address from the parameter storage area. */
 	psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr),
 		 mac, 6);
+
+	release_region(ioaddr, sizeof(ha_t));
 
 	/*
 	 * Check the first three octets of the address for the manufacturer's code.
diff -Nru a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig
--- a/drivers/parisc/Kconfig	Fri Jul 11 01:25:29 2003
+++ b/drivers/parisc/Kconfig	Fri Jul 11 01:25:29 2003
@@ -57,8 +57,11 @@
 source "drivers/eisa/Kconfig"
 
 config ISA
-	bool
+	bool "ISA support"
 	depends on EISA
+	help
+	  If you want to plug an ISA card into your EISA bus, say Y here.
+	  Most people should say N.
 
 config PCI
 	bool "PCI support"
diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
--- a/drivers/pcmcia/cs.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/pcmcia/cs.c	Fri Jul 11 01:25:28 2003
@@ -338,13 +338,13 @@
 	socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy;
 	INIT_LIST_HEAD(&socket->cis_cache);
 	spin_lock_init(&socket->lock);
-
-	init_socket(socket);
-
 	init_completion(&socket->thread_done);
 	init_waitqueue_head(&socket->thread_wait);
 	init_MUTEX(&socket->skt_sem);
 	spin_lock_init(&socket->thread_lock);
+
+	init_socket(socket);
+
 	ret = kernel_thread(pccardd, socket, CLONE_KERNEL);
 	if (ret < 0)
 		return ret;
@@ -868,13 +868,19 @@
 	complete_and_exit(&skt->thread_done, 0);
 }
 
+/*
+ * Yenta (at least) probes interrupts before registering the socket and
+ * starting the handler thread.
+ */
 void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
 {
-	spin_lock(&s->thread_lock);
-	s->thread_events |= events;
-	spin_unlock(&s->thread_lock);
+	if (s->thread) {
+		spin_lock(&s->thread_lock);
+		s->thread_events |= events;
+		spin_unlock(&s->thread_lock);
 
-	wake_up(&s->thread_wait);
+		wake_up(&s->thread_wait);
+	}
 } /* pcmcia_parse_events */
 
 
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/usb/class/usblp.c	Fri Jul 11 01:25:28 2003
@@ -146,6 +146,7 @@
 	int			rcomplete;		/* reading is completed */
 	unsigned int		quirks;			/* quirks flags */
 	unsigned char		used;			/* True if open */
+	unsigned char		present;		/* True if not disconnected */
 	unsigned char		bidir;			/* interface is bidirectional */
 	unsigned char		*device_id_string;	/* IEEE 1284 DEVICE ID string (ptr) */
 							/* first 2 bytes are (big-endian) length */
@@ -157,6 +158,7 @@
 
 	dbg("usblp=0x%p", usblp);
 	dbg("dev=0x%p", usblp->dev);
+	dbg("present=%d", usblp->present);
 	dbg("buf=0x%p", usblp->buf);
 	dbg("readcount=%d", usblp->readcount);
 	dbg("ifnum=%d", usblp->ifnum);
@@ -253,7 +255,7 @@
 {
 	struct usblp *usblp = urb->context;
 
-	if (!usblp || !usblp->dev || !usblp->used)
+	if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
 		return;
 
 	if (unlikely(urb->status))
@@ -267,7 +269,7 @@
 {
 	struct usblp *usblp = urb->context;
 
-	if (!usblp || !usblp->dev || !usblp->used)
+	if (!usblp || !usblp->dev || !usblp->used || !usblp->present)
 		return;
 
 	if (unlikely(urb->status))
@@ -332,7 +334,7 @@
 		goto out;
 	}
 	usblp = usb_get_intfdata (intf);
-	if (!usblp || !usblp->dev)
+	if (!usblp || !usblp->dev || !usblp->present)
 		goto out;
 
 	retval = -EBUSY;
@@ -404,7 +406,7 @@
 	down (&usblp->sem);
 	lock_kernel();
 	usblp->used = 0;
-	if (usblp->dev) {
+	if (usblp->present) {
 		usblp_unlink_urbs(usblp);
 		up(&usblp->sem);
 	} else 		/* finish cleanup from disconnect */
@@ -432,7 +434,7 @@
 	int retval = 0;
 
 	down (&usblp->sem);
-	if (!usblp->dev) {
+	if (!usblp->present) {
 		retval = -ENODEV;
 		goto done;
 	}
@@ -630,7 +632,7 @@
 		}
 
 		down (&usblp->sem);
-		if (!usblp->dev) {
+		if (!usblp->present) {
 			up (&usblp->sem);
 			return -ENODEV;
 		}
@@ -691,7 +693,7 @@
 		return -EINVAL;
 
 	down (&usblp->sem);
-	if (!usblp->dev) {
+	if (!usblp->present) {
 		count = -ENODEV;
 		goto done;
 	}
@@ -726,7 +728,7 @@
 		remove_wait_queue(&usblp->wait, &wait);
 	}
 
-	if (!usblp->dev) {
+	if (!usblp->present) {
 		count = -ENODEV;
 		goto done;
 	}
@@ -916,6 +918,8 @@
 
 	usb_set_intfdata (intf, usblp);
 
+	usblp->present = 1;
+
 	return 0;
 
 abort_minor:
@@ -1115,14 +1119,14 @@
 
 	down (&usblp->sem);
 	lock_kernel();
-	usblp->dev = NULL;
+	usblp->present = 0;
 	usb_set_intfdata (intf, NULL);
 
 	usblp_unlink_urbs(usblp);
 
 	if (!usblp->used)
 		usblp_cleanup (usblp);
-	else 	/* cleanup later, on close */
+	else 	/* cleanup later, on release */
 		up (&usblp->sem);
 	unlock_kernel();
 }
diff -Nru a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
--- a/drivers/usb/core/inode.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/usb/core/inode.c	Fri Jul 11 01:25:28 2003
@@ -491,10 +491,6 @@
 static struct super_block *usb_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
-	if (fs_type == &usbdevice_fs_type)
-		printk (KERN_INFO "Please use the 'usbfs' filetype instead, "
-				"the 'usbdevfs' name is deprecated.\n");
-
 	return get_sb_single(fs_type, flags, data, usbfs_fill_super);
 }
 
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/usb/core/message.c	Fri Jul 11 01:25:28 2003
@@ -986,7 +986,7 @@
 		if (err < 0) {
 			err("error getting string descriptor 0 (error=%d)", err);
 			goto errout;
-		} else if (tbuf[0] < 4) {
+		} else if (err < 4 || tbuf[0] < 4) {
 			err("string descriptor 0 too short");
 			err = -EINVAL;
 			goto errout;
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/usb/net/usbnet.c	Fri Jul 11 01:25:29 2003
@@ -2391,7 +2391,7 @@
 	if (retval) {
 		devdbg (dev, "drop, code %d", retval);
 drop:
-		retval = NET_XMIT_DROP;
+		retval = NET_XMIT_SUCCESS;
 		dev->stats.tx_dropped++;
 		if (skb)
 			dev_kfree_skb_any (skb);
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	Fri Jul 11 01:25:29 2003
+++ b/drivers/usb/serial/ftdi_sio.c	Fri Jul 11 01:25:29 2003
@@ -4,6 +4,8 @@
  * 	Copyright (C) 1999 - 2001
  * 	    Greg Kroah-Hartman (greg@kroah.com)
  *          Bill Ryder (bryder@sgi.com)
+ *	Copyright (C) 2002
+ *	    Kuba Ober (kuba@mareimbrium.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
@@ -13,49 +15,156 @@
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
- *     and extra documentation
+ *	and extra documentation
+ *
+ * (27/Jun/2003) Ian Abbott
+ *	Reworked the urb handling logic.  We have no more pool, but dynamically
+ *	allocate the urb and the transfer buffer on the fly.  In testing this
+ *	does not incure any measurable overhead.  This also relies on the fact
+ *	that we have proper reference counting logic for urbs.  I nicked this
+ *	from Greg KH's Visor driver.
+ *      
+ * (23/Jun/2003) Ian Abbott
+ *      Reduced flip buffer pushes and corrected a data length test in
+ *      ftdi_read_bulk_callback.
+ *      Defererence pointers after any paranoid checks, not before.
+ *
+ * (21/Jun/2003) Erik Nygren
+ *      Added support for Home Electronics Tira-1 IR tranceiver using FT232BM chip.
+ *      See <http://www.home-electro.com/tira1.htm>.  Only operates properly 
+ *      at 100000 and RTS-CTS, so set custom divisor mode on startup.
+ *      Also force the Tira-1 and USB-UIRT to only use their custom baud rates.
+ *
+ * (18/Jun/2003) Ian Abbott
+ *      Added Device ID of the USB relais from Rudolf Gugler (backported from
+ *      Philipp Gühring's patch for 2.5.x kernel).
+ *      Moved read transfer buffer reallocation into startup function.
+ *      Free existing write urb and transfer buffer in startup function.
+ *      Only use urbs in write urb pool that were successfully allocated.
+ *      Moved some constant macros out of functions.
+ *      Minor whitespace and comment changes.
+ *
+ * (12/Jun/2003) David Norwood
+ *      Added support for USB-UIRT IR tranceiver using 8U232AM chip.
+ *      See <http://home.earthlink.net/~jrhees/USBUIRT/index.htm>.  Only
+ *      operates properly at 312500, so set custom divisor mode on startup.
+ *
+ * (12/Jun/2003) Ian Abbott
+ *      Added Sealevel SeaLINK+ 210x, 220x, 240x, 280x vid/pids from Tuan Hoang
+ *      - I've eliminated some that don't seem to exist!
+ *      Added Home Electronics Tira-1 IR transceiver pid from Chris Horn
+ *      Some whitespace/coding-style cleanups
+ *
+ * (11/Jun/2003) Ian Abbott
+ *      Fixed unsafe spinlock usage in ftdi_write
+ *
+ * (24/Feb/2003) Richard Shooter
+ *      Increase read buffer size to improve read speeds at higher baud rates
+ *      (specifically tested with up to 1Mb/sec at 1.5M baud)
+ *
+ * (23/Feb/2003) John Wilkins
+ *      Added Xon/xoff flow control (activating support in the ftdi device)
+ *      Added vid/pid for Videonetworks/Homechoice (UK ISP)
+ *
+ * (23/Feb/2003) Bill Ryder
+ *      Added matrix orb device vid/pids from Wayne Wylupski
+ *
+ * (19/Feb/2003) Ian Abbott
+ *      For TIOCSSERIAL, set alt_speed to 0 when ASYNC_SPD_MASK value has
+ *      changed to something other than ASYNC_SPD_HI, ASYNC_SPD_VHI,
+ *      ASYNC_SPD_SHI or ASYNC_SPD_WARP.  Also, unless ASYNC_SPD_CUST is in
+ *      force, don't bother changing baud rate when custom_divisor has changed.
+ *
+ * (18/Feb/2003) Ian Abbott
+ *      Fixed TIOCMGET handling to include state of DTR and RTS, the state
+ *      of which are now saved by set_dtr() and set_rts().
+ *      Fixed improper storage class for buf in set_dtr() and set_rts().
+ *      Added FT232BM chip type and support for its extra baud rates (compared
+ *      to FT8U232AM).
+ *      Took account of special case divisor values for highest baud rates of
+ *      FT8U232AM and FT232BM.
+ *      For TIOCSSERIAL, forced alt_speed to 0 when ASYNC_SPD_CUST kludge used,
+ *      as previous alt_speed setting is now stale.
+ *      Moved startup code common between the startup routines for the
+ *      different chip types into a common subroutine.
+ *
+ * (17/Feb/2003) Bill Ryder
+ *      Added write urb buffer pool on a per device basis
+ *      Added more checking for open file on callbacks (fixed OOPS)
+ *      Added CrystalFontz 632 and 634 PIDs 
+ *         (thanx to CrystalFontz for the sample devices - they flushed out
+ *           some driver bugs)
+ *      Minor debugging message changes
+ *      Added throttle, unthrottle and chars_in_buffer functions
+ *      Fixed FTDI_SIO (the original device) bug
+ *      Fixed some shutdown handling
+ *      
+ * 
+ * 
  * 
+ * (07/Jun/2002) Kuba Ober
+ *	Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor
+ *	function. It was getting too complex.
+ *	Fix the divisor calculation logic which was setting divisor of 0.125
+ *	instead of 0.5 for fractional parts of divisor equal to 5/8, 6/8, 7/8.
+ *	Also make it bump up the divisor to next integer in case of 7/8 - it's
+ *	a better approximation.
+ *
+ * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch
+ *      Not tested by me but it doesn't break anything I use.
+ * 
+ * (04/Jan/2002) Kuba Ober
+ *	Implemented 38400 baudrate kludge, where it can be substituted with other
+ *	  values. That's the only way to set custom baudrates.
+ *	Implemented TIOCSSERIAL, TIOCGSERIAL ioctl's so that setserial is happy.
+ *	FIXME: both baudrate things should eventually go to usbserial.c as other
+ *	  devices may need that functionality too. Actually, it can probably be
+ *	  merged in serial.c somehow - too many drivers repeat this code over
+ *	  and over.
+ *	Fixed baudrate forgetfulness - open() used to reset baudrate to 9600 every time.
+ *	Divisors for baudrates are calculated by a macro.
+ *	Small code cleanups. Ugly whitespace changes for Plato's sake only ;-].
+ *
  * (04/Nov/2001) Bill Ryder
- *     Fixed bug in read_bulk_callback where incorrect urb buffer was used.
- *     cleaned up write offset calculation
- *     added write_room since default values can be incorrect for sio
- *     changed write_bulk_callback to use same queue_task as other drivers
- *       (the previous version caused panics)
- *     Removed port iteration code since the device only has one I/O port and it 
- *       was wrong anyway.
+ *	Fixed bug in read_bulk_callback where incorrect urb buffer was used.
+ *	Cleaned up write offset calculation
+ *	Added write_room since default values can be incorrect for sio
+ *	Changed write_bulk_callback to use same queue_task as other drivers
+ *        (the previous version caused panics)
+ *	Removed port iteration code since the device only has one I/O port and it
+ *	  was wrong anyway.
  * 
  * (31/May/2001) gkh
- *	switched from using spinlock to a semaphore, which fixes lots of problems.
+ *	Switched from using spinlock to a semaphore, which fixes lots of problems.
  *
  * (23/May/2001)   Bill Ryder
- *     Added runtime debug patch (thanx Tyson D Sawyer).
- *     Cleaned up comments for 8U232
- *     Added parity, framing and overrun error handling
- *     Added receive break handling.
+ *	Added runtime debug patch (thanx Tyson D Sawyer).
+ *	Cleaned up comments for 8U232
+ *	Added parity, framing and overrun error handling
+ *	Added receive break handling.
  * 
  * (04/08/2001) gb
  *	Identify version on module load.
  *       
  * (18/March/2001) Bill Ryder
- *     (Not released)
- *     Added send break handling. (requires kernel patch too)
- *     Fixed 8U232AM hardware RTS/CTS etc status reporting.
- *     Added flipbuf fix copied from generic device
+ *	(Not released)
+ *	Added send break handling. (requires kernel patch too)
+ *	Fixed 8U232AM hardware RTS/CTS etc status reporting.
+ *	Added flipbuf fix copied from generic device
  * 
  * (12/3/2000) Bill Ryder
- *     Added support for 8U232AM device.
- *     Moved PID and VIDs into header file only.
- *     Turned on low-latency for the tty (device will do high baudrates)
- *     Added shutdown routine to close files when device removed.
- *     More debug and error message cleanups.
- *     
+ *	Added support for 8U232AM device.
+ *	Moved PID and VIDs into header file only.
+ *	Turned on low-latency for the tty (device will do high baudrates)
+ *	Added shutdown routine to close files when device removed.
+ *	More debug and error message cleanups.
  *
  * (11/13/2000) Bill Ryder
- *     Added spinlock protected open code and close code.
- *     Multiple opens work (sort of - see webpage mentioned above).
- *     Cleaned up comments. Removed multiple PID/VID definitions.
- *     Factorised cts/dtr code
- *     Made use of __FUNCTION__ in dbg's
+ *	Added spinlock protected open code and close code.
+ *	Multiple opens work (sort of - see webpage mentioned above).
+ *	Cleaned up comments. Removed multiple PID/VID definitions.
+ *	Factorised cts/dtr code
+ *	Made use of __FUNCTION__ in dbg's
  *      
  * (11/01/2000) Adam J. Richter
  *	usb_device_id table support
@@ -72,16 +181,16 @@
  *	driver is a loadable module now.
  *
  * (04/04/2000) Bill Ryder 
- *      Fixed bugs in TCGET/TCSET ioctls (by removing them - they are 
+ *	Fixed bugs in TCGET/TCSET ioctls (by removing them - they are
  *        handled elsewhere in the tty io driver chain).
  *
  * (03/30/2000) Bill Ryder 
- *      Implemented lots of ioctls
- * 	Fixed a race condition in write
- * 	Changed some dbg's to errs
+ *	Implemented lots of ioctls
+ *	Fixed a race condition in write
+ *	Changed some dbg's to errs
  *
  * (03/26/2000) gkh
- * 	Split driver up into device specific pieces.
+ *	Split driver up into device specific pieces.
  *
  */
 
@@ -90,7 +199,6 @@
 /*   to talk to the device */
 /* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */
 
-
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -103,6 +211,7 @@
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
+#include <linux/serial.h>
 #ifdef CONFIG_USB_SERIAL_DEBUG
 	static int debug = 1;
 #else
@@ -112,47 +221,244 @@
 #include "usb-serial.h"
 #include "ftdi_sio.h"
 
-
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.2.0"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>"
-#define DRIVER_DESC "USB FTDI RS232 Converters Driver"
+#define DRIVER_VERSION "v1.4.0"
+#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
+#define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
 static struct usb_device_id id_table_sio [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ }						/* Terminating entry */
 };
 
-/* THe 8U232AM has the same API as the sio except for:
-   - it can support MUCH higher baudrates (921600 at 48MHz/230400 
-     at 12MHz so .. it's baudrate setting codes are different 
-   - it has a two byte status code.
-   - it returns characters very 16ms (the FTDI does it every 40ms)
-  */
+/*
+ * The 8U232AM has the same API as the sio except for:
+ * - it can support MUCH higher baudrates; up to:
+ *   o 921600 for RS232 and 2000000 for RS422/485 at 48MHz
+ *   o 230400 at 12MHz
+ *   so .. 8U232AM's baudrate setting codes are different
+ * - it has a two byte status code.
+ * - it returns characters every 16ms (the FTDI does it every 40ms)
+ *
+ * the bcdDevice value is used to differentiate FT232BM and FT245BM from
+ * the earlier FT8U232AM and FT8U232BM.  For now, include all known VID/PID
+ * combinations in both tables.
+ * FIXME: perhaps bcdDevice can also identify 12MHz devices, but I don't know
+ * if those ever went into mass production. [Ian Abbott]
+ */
+
 
-   
 static struct usb_device_id id_table_8U232AM [] = {
-	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
-	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
-	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0, 0x3ff) },
+	{ }						/* Terminating entry */
+};
+
+
+static struct usb_device_id id_table_FT232BM [] = {
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2101_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2102_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2103_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2104_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2201_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2202_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2203_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_3_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2401_4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_3_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2402_4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_3_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2403_4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_3_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_5_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_6_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_7_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2801_8_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_3_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_5_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_6_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_7_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2802_8_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_2_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_3_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_4_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_5_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_6_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_7_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(SEALEVEL_VID, SEALEVEL_2803_8_PID, 0x400, 0xffff) },
 	{ }						/* Terminating entry */
 };
 
 
-static struct usb_device_id id_table_combined [] = {
+static struct usb_device_id id_table_USB_UIRT [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
+	{ }						/* Terminating entry */
+};
+
+
+static struct usb_device_id id_table_HE_TIRA1 [] = {
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
+	{ }						/* Terminating entry */
+};
+
+
+static __devinitdata struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) },
 	{ USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) },
+	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) },
+	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID) },
+	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID) },
+	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_3_PID) },
+	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_4_PID) },
+	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_5_PID) },
+	{ USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_6_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2104_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2201_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2202_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2203_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2401_4_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2402_4_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2403_4_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_4_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_5_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_6_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_7_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2801_8_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_4_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_5_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_6_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_7_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2802_8_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_1_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_2_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_3_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_4_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_5_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
+	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_HE_TIRA1_PID, 0x400, 0xffff) },
+	{ USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID) },
 	{ }						/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 static struct usb_driver ftdi_driver = {
-	.owner =	THIS_MODULE,
 	.name =		"ftdi_sio",
 	.probe =	usb_serial_probe,
 	.disconnect =	usb_serial_disconnect,
@@ -160,31 +466,63 @@
 };
 
 
+/* Constants for read urb and write urb */
+#define BUFSZ 512
+#define PKTSZ 64
+
 struct ftdi_private {
-	enum ftdi_type ftdi_type;
-	__u16 last_set_data_urb_value ; /* the last data state set - needed for doing a break */
-        int write_offset;
+	ftdi_chip_type_t chip_type;
+				/* type of the device, either SIO or FT8U232AM */
+	int baud_base;		/* baud base clock for divisor setting */
+	int custom_divisor;	/* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+	__u16 last_set_data_urb_value ;
+				/* the last data state set - needed for doing a break */
+        int write_offset;       /* This is the offset in the usb data block to write the serial data - 
+				 * it is different between devices
+				 */
+	int flags;		/* some ASYNC_xxxx flags are supported */
+	unsigned long last_dtr_rts;	/* saved modem control outputs */
+        wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ 	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
+
+	int force_baud;		/* if non-zero, force the baud rate to this value */
+	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
 };
+
+/* Used for TIOCMIWAIT */
+#define FTDI_STATUS_B0_MASK	(FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
+#define FTDI_STATUS_B1_MASK	(FTDI_RS_BI)
+/* End TIOCMIWAIT */
+
+#define FTDI_IMPL_ASYNC_FLAGS = ( ASYNC_SPD_HI | ASYNC_SPD_VHI \
+ ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP )
+
 /* function prototypes for a FTDI serial converter */
-static int  ftdi_sio_startup		(struct usb_serial *serial);
+static int  ftdi_SIO_startup		(struct usb_serial *serial);
 static int  ftdi_8U232AM_startup	(struct usb_serial *serial);
-static void ftdi_sio_shutdown		(struct usb_serial *serial);
-static int  ftdi_sio_open		(struct usb_serial_port *port, struct file *filp);
-static void ftdi_sio_close		(struct usb_serial_port *port, struct file *filp);
-static int  ftdi_sio_write		(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
-static int  ftdi_sio_write_room		(struct usb_serial_port *port);
-static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void ftdi_sio_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void ftdi_sio_set_termios	(struct usb_serial_port *port, struct termios * old);
-static int  ftdi_sio_tiocmget		(struct usb_serial_port *port, struct file *file);
-static int  ftdi_sio_tiocmset		(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
-static int  ftdi_sio_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void ftdi_sio_break_ctl		(struct usb_serial_port *port, int break_state );
-
-/* Should rename most ftdi_sio's to ftdi_ now since there are two devices 
-   which share common code */ 
+static int  ftdi_FT232BM_startup	(struct usb_serial *serial);
+static int  ftdi_USB_UIRT_startup	(struct usb_serial *serial);
+static int  ftdi_HE_TIRA1_startup	(struct usb_serial *serial);
+static void ftdi_shutdown		(struct usb_serial *serial);
+static int  ftdi_open			(struct usb_serial_port *port, struct file *filp);
+static void ftdi_close			(struct usb_serial_port *port, struct file *filp);
+static int  ftdi_write			(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int  ftdi_write_room		(struct usb_serial_port *port);
+static int  ftdi_chars_in_buffer	(struct usb_serial_port *port);
+static void ftdi_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
+static void ftdi_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
+static void ftdi_set_termios		(struct usb_serial_port *port, struct termios * old);
+static int  ftdi_ioctl			(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+static void ftdi_break_ctl		(struct usb_serial_port *port, int break_state );
+static void ftdi_throttle		(struct usb_serial_port *port);
+static void ftdi_unthrottle		(struct usb_serial_port *port);
+
+static unsigned short int ftdi_232am_baud_base_to_divisor (int baud, int base);
+static unsigned short int ftdi_232am_baud_to_divisor (int baud);
+static __u32 ftdi_232bm_baud_base_to_divisor (int baud, int base);
+static __u32 ftdi_232bm_baud_to_divisor (int baud);
 
-static struct usb_serial_device_type ftdi_sio_device = {
+static struct usb_serial_device_type ftdi_SIO_device = {
 	.owner =		THIS_MODULE,
 	.name =			"FTDI SIO",
 	.id_table =		id_table_sio,
@@ -192,77 +530,206 @@
 	.num_bulk_in =		1,
 	.num_bulk_out =		1,
 	.num_ports =		1,
-	.open =			ftdi_sio_open,
-	.close =		ftdi_sio_close,
-	.write =		ftdi_sio_write,
-	.write_room =		ftdi_sio_write_room,
-	.read_bulk_callback =	ftdi_sio_read_bulk_callback,
-	.write_bulk_callback =	ftdi_sio_write_bulk_callback,
-	.ioctl =		ftdi_sio_ioctl,
-	.set_termios =		ftdi_sio_set_termios,
-	.break_ctl =		ftdi_sio_break_ctl,
-	.tiocmget =		ftdi_sio_tiocmget,
-	.tiocmset =		ftdi_sio_tiocmset,
-	.attach =		ftdi_sio_startup,
-        .shutdown =             ftdi_sio_shutdown,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
+	.attach =		ftdi_SIO_startup,
+	.shutdown =		ftdi_shutdown,
 };
 
 static struct usb_serial_device_type ftdi_8U232AM_device = {
 	.owner =		THIS_MODULE,
-	.name =			"FTDI 8U232AM",
+	.name =			"FTDI 8U232AM Compatible",
 	.id_table =		id_table_8U232AM,
 	.num_interrupt_in =	0,
 	.num_bulk_in =		1,
 	.num_bulk_out =		1,
 	.num_ports =		1,
-	.open =			ftdi_sio_open,
-	.close =		ftdi_sio_close,
-	.write =		ftdi_sio_write,
-	.write_room =		ftdi_sio_write_room,
-	.read_bulk_callback =	ftdi_sio_read_bulk_callback,
-	.write_bulk_callback =	ftdi_sio_write_bulk_callback,
-	.ioctl =		ftdi_sio_ioctl,
-	.set_termios =		ftdi_sio_set_termios,
-	.break_ctl =		ftdi_sio_break_ctl,
-	.tiocmget =		ftdi_sio_tiocmget,
-	.tiocmset =		ftdi_sio_tiocmset,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
 	.attach =		ftdi_8U232AM_startup,
-        .shutdown =             ftdi_sio_shutdown,
+	.shutdown =		ftdi_shutdown,
+};
+
+static struct usb_serial_device_type ftdi_FT232BM_device = {
+	.owner =		THIS_MODULE,
+	.name =			"FTDI FT232BM Compatible",
+	.id_table =		id_table_FT232BM,
+	.num_interrupt_in =	0,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
+	.attach =		ftdi_FT232BM_startup,
+	.shutdown =		ftdi_shutdown,
 };
 
+static struct usb_serial_device_type ftdi_USB_UIRT_device = {
+	.owner =		THIS_MODULE,
+	.name =			"USB-UIRT Infrared Receiver/Transmitter",
+	.id_table =		id_table_USB_UIRT,
+	.num_interrupt_in =	0,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
+	.attach =		ftdi_USB_UIRT_startup,
+	.shutdown =		ftdi_shutdown,
+};
+
+/* The TIRA1 is based on a  FT232BM which requires a fixed baud rate of 100000
+ * and which requires RTS-CTS to be enabled. */
+static struct usb_serial_device_type ftdi_HE_TIRA1_device = {
+	.owner =		THIS_MODULE,
+	.name =			"Home-Electronics TIRA-1 IR Transceiver",
+	.id_table =		id_table_HE_TIRA1,
+	.num_interrupt_in =	0,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
+	.attach =		ftdi_HE_TIRA1_startup,
+	.shutdown =		ftdi_shutdown,
+};
+
+
+
+#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+
+/* High and low are for DTR, RTS etc etc */
+#define HIGH 1
+#define LOW 0
 
 /*
  * ***************************************************************************
- * FTDI SIO Serial Converter specific driver functions
+ * Utlity functions
  * ***************************************************************************
  */
 
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base)
+{
+	unsigned short int divisor;
+	int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
+	if ((divisor3 & 0x7) == 7) divisor3 ++; // round x.7/8 up to x+1
+	divisor = divisor3 >> 3;
+	divisor3 &= 0x7;
+	if (divisor3 == 1) divisor |= 0xc000; else // 0.125
+	if (divisor3 >= 4) divisor |= 0x4000; else // 0.5
+	if (divisor3 != 0) divisor |= 0x8000;      // 0.25
+	if (divisor == 1) divisor = 0;	/* special case for maximum baud rate */
+	return divisor;
+}
 
-/* utility functions to set and unset dtr and rts */
-#define HIGH 1
-#define LOW 0
-static int set_rts(struct usb_device *dev, 
-		   unsigned int pipe,
-		   int high_or_low)
-{
-	static char buf[1];
-	unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_RTS_HIGH : 
-				FTDI_SIO_SET_RTS_LOW);
-	return(usb_control_msg(dev, pipe,
+static unsigned short int ftdi_232am_baud_to_divisor(int baud)
+{
+	 return(ftdi_232am_baud_base_to_divisor(baud, 48000000));
+}
+
+static __u32 ftdi_232bm_baud_base_to_divisor(int baud, int base)
+{
+	static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 };
+	__u32 divisor;
+	int divisor3 = base / 2 / baud; // divisor shifted 3 bits to the left
+	divisor = divisor3 >> 3;
+	divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
+	/* Deal with special cases for highest baud rates. */
+	if (divisor == 1) divisor = 0; else	// 1.0
+	if (divisor == 0x4001) divisor = 1;	// 1.5
+	return divisor;
+}
+
+static __u32 ftdi_232bm_baud_to_divisor(int baud)
+{
+	 return(ftdi_232bm_baud_base_to_divisor(baud, 48000000));
+}
+
+static int set_rts(struct usb_serial_port *port, int high_or_low)
+{
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	char buf[1];
+	unsigned ftdi_high_or_low;
+	if (high_or_low) {
+		ftdi_high_or_low = FTDI_SIO_SET_RTS_HIGH;
+		priv->last_dtr_rts |= TIOCM_RTS;
+	} else {
+		ftdi_high_or_low = FTDI_SIO_SET_RTS_LOW;
+		priv->last_dtr_rts &= ~TIOCM_RTS;
+	}
+	return(usb_control_msg(port->serial->dev,
+			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
 			       ftdi_high_or_low, 0, 
 			       buf, 0, WDR_TIMEOUT));
 }
-static int set_dtr(struct usb_device *dev, 
-		   unsigned int pipe,
-		   int high_or_low)
-{
-	static char buf[1];
-	unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_DTR_HIGH : 
-				FTDI_SIO_SET_DTR_LOW);
-	return(usb_control_msg(dev, pipe,
+
+
+static int set_dtr(struct usb_serial_port *port, int high_or_low)
+{
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	char buf[1];
+	unsigned ftdi_high_or_low;
+	if (high_or_low) {
+		ftdi_high_or_low = FTDI_SIO_SET_DTR_HIGH;
+		priv->last_dtr_rts |= TIOCM_DTR;
+	} else {
+		ftdi_high_or_low = FTDI_SIO_SET_DTR_LOW;
+		priv->last_dtr_rts &= ~TIOCM_DTR;
+	}
+	return(usb_control_msg(port->serial->dev,
+			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
 			       ftdi_high_or_low, 0, 
@@ -270,71 +737,409 @@
 }
 
 
+static __u32 get_ftdi_divisor(struct usb_serial_port * port);
+
+
+static int change_speed(struct usb_serial_port *port)
+{
+	char buf[1];
+        __u16 urb_value;
+	__u16 urb_index;
+	__u32 urb_index_value;
+
+	urb_index_value = get_ftdi_divisor(port);
+	urb_value = (__u16)urb_index_value;
+	urb_index = (__u16)(urb_index_value >> 16);
+	
+	return (usb_control_msg(port->serial->dev,
+			    usb_sndctrlpipe(port->serial->dev, 0),
+			    FTDI_SIO_SET_BAUDRATE_REQUEST,
+			    FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
+			    urb_value, urb_index,
+			    buf, 0, 100) < 0);
+}
+
+
+static __u32 get_ftdi_divisor(struct usb_serial_port * port)
+{ /* get_ftdi_divisor */
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	__u32 div_value = 0;
+	int div_okay = 1;
+	char *chip_name = "";
+	int baud;
+
+	/*
+	 * The logic involved in setting the baudrate can be cleanly split in 3 steps.
+	 * Obtaining the actual baud rate is a little tricky since unix traditionally
+	 * somehow ignored the possibility to set non-standard baud rates.
+	 * 1. Standard baud rates are set in tty->termios->c_cflag
+	 * 2. If these are not enough, you can set any speed using alt_speed as follows:
+	 *    - set tty->termios->c_cflag speed to B38400
+	 *    - set your real speed in tty->alt_speed; it gets ignored when
+	 *      alt_speed==0, (or)
+	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+	 *      flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP], this just
+	 *      sets alt_speed to (HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800)
+	 * ** Steps 1, 2 are done courtesy of tty_get_baud_rate
+	 * 3. You can also set baud rate by setting custom divisor as follows
+	 *    - set tty->termios->c_cflag speed to B38400
+	 *    - call TIOCSSERIAL ioctl with (struct serial_struct) set as follows:
+	 *      o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
+	 *      o custom_divisor set to baud_base / your_new_baudrate
+	 * ** Step 3 is done courtesy of code borrowed from serial.c - I should really
+	 *    spend some time and separate+move this common code to serial.c, it is
+	 *    replicated in nearly every serial driver you see.
+	 */
+
+	/* 1. Get the baud rate from the tty settings, this observes alt_speed hack */
+
+	baud = tty_get_baud_rate(port->tty);
+	dbg("%s - tty_get_baud_rate reports speed %d", __FUNCTION__, baud);
+
+	/* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */
+
+	if (baud == 38400 &&
+	    ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+	     (priv->custom_divisor)) {
+		baud = priv->baud_base / priv->custom_divisor;
+		dbg("%s - custom divisor %d sets baud rate to %d", __FUNCTION__, priv->custom_divisor, baud);
+	}
+
+	/* 3. Convert baudrate to device-specific divisor */
+
+	if (!baud) baud = 9600;	
+	switch(priv->chip_type) {
+	case SIO: /* SIO chip */
+		chip_name = "SIO";
+		switch(baud) {
+		case 300: div_value = ftdi_sio_b300; break;
+		case 600: div_value = ftdi_sio_b600; break;
+		case 1200: div_value = ftdi_sio_b1200; break;
+		case 2400: div_value = ftdi_sio_b2400; break;
+		case 4800: div_value = ftdi_sio_b4800; break;
+		case 9600: div_value = ftdi_sio_b9600; break;
+		case 19200: div_value = ftdi_sio_b19200; break;
+		case 38400: div_value = ftdi_sio_b38400; break;
+		case 57600: div_value = ftdi_sio_b57600;  break;
+		case 115200: div_value = ftdi_sio_b115200; break;
+		} /* baud */
+		if (div_value == 0) {
+  			dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__,  baud);
+			div_value = ftdi_sio_b9600;
+			div_okay = 0;
+		}
+		break;
+	case FT8U232AM: /* 8U232AM chip */
+		chip_name = "FT8U232AM";
+		if (baud <= 3000000) {
+			div_value = ftdi_232am_baud_to_divisor(baud);
+		} else {
+	                dbg("%s - Baud rate too high!", __FUNCTION__);
+			div_value = ftdi_232am_baud_to_divisor(9600);
+			div_okay = 0;
+		}
+		break;
+	case FT232BM: /* FT232BM chip */
+		chip_name = "FT232BM";
+		if (baud <= 3000000) {
+			div_value = ftdi_232bm_baud_to_divisor(baud);
+		} else {
+	                dbg("%s - Baud rate too high!", __FUNCTION__);
+			div_value = ftdi_232bm_baud_to_divisor(9600);
+			div_okay = 0;
+		}
+		break;
+	} /* priv->chip_type */
+
+	if (div_okay) {
+		dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s",
+			__FUNCTION__, baud, (unsigned long)div_value, chip_name);
+	}
+
+	return(div_value);
+}
+
 
-static int ftdi_sio_startup (struct usb_serial *serial)
+static int get_serial_info(struct usb_serial_port * port, struct serial_struct * retinfo)
 {
-	struct ftdi_private *priv;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.flags = priv->flags;
+	tmp.baud_base = priv->baud_base;
+	tmp.custom_divisor = priv->custom_divisor;
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+} /* get_serial_info */
+
+
+static int set_serial_info(struct usb_serial_port * port, struct serial_struct * newinfo)
+{ /* set_serial_info */
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	struct serial_struct new_serial;
+	struct ftdi_private old_priv;
+
+	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
+		return -EFAULT;
+	old_priv = * priv;
+
+	/* Do error checking and permission checking */
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (priv->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		priv->flags = ((priv->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		priv->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	if ((new_serial.baud_base != priv->baud_base) ||
+	    (new_serial.baud_base < 9600))
+		return -EINVAL;
+
+	/* Make the changes - these are privileged changes! */
+
+	priv->flags = ((priv->flags & ~ASYNC_FLAGS) |
+	               (new_serial.flags & ASYNC_FLAGS));	
+	priv->custom_divisor = new_serial.custom_divisor;
+
+	port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+check_and_exit:
+	if ((old_priv.flags & ASYNC_SPD_MASK) !=
+	     (priv->flags & ASYNC_SPD_MASK)) {
+		if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			port->tty->alt_speed = 57600;
+		else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			port->tty->alt_speed = 115200;
+		else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			port->tty->alt_speed = 230400;
+		else if ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			port->tty->alt_speed = 460800;
+		else
+			port->tty->alt_speed = 0;
+	}
+	if (((old_priv.flags & ASYNC_SPD_MASK) !=
+	     (priv->flags & ASYNC_SPD_MASK)) ||
+	    (((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) &&
+	     (old_priv.custom_divisor != priv->custom_divisor))) {
+		change_speed(port);
+	}
 	
+	return (0);
+
+} /* set_serial_info */
+
+/*
+ * ***************************************************************************
+ * FTDI driver specific functions
+ * ***************************************************************************
+ */
+
+/* Common startup subroutine */
+/* Called from ftdi_SIO_startup, etc. */
+static int ftdi_common_startup (struct usb_serial *serial)
+{
+	struct usb_serial_port *port = &serial->port[0];
+	struct ftdi_private *priv;
 	
+	dbg("%s",__FUNCTION__);
+
 	priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
 	if (!priv){
 		err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
 		return -ENOMEM;
 	}
+	memset(priv, 0, sizeof(*priv));
 
-	priv->ftdi_type = sio;
-	priv->write_offset = 1;
-	usb_set_serial_port_data(serial->port, priv);
+        init_waitqueue_head(&priv->delta_msr_wait);
+	/* This will push the characters through immediately rather
+	   than queue a task to deliver them */
+	priv->flags = ASYNC_LOW_LATENCY;
+
+	/* Increase the size of read buffers */
+	if (port->bulk_in_buffer) {
+		kfree (port->bulk_in_buffer);
+	}
+	port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
+	if (!port->bulk_in_buffer) {
+		kfree (priv);
+		return -ENOMEM;
+	}
+	if (port->read_urb) {
+		port->read_urb->transfer_buffer = port->bulk_in_buffer;
+		port->read_urb->transfer_buffer_length = BUFSZ;
+	}
+
+	/* Free port's existing write urb and transfer buffer. */
+	if (port->write_urb) {
+		usb_free_urb (port->write_urb);
+		port->write_urb = NULL;
+	}
+	if (port->bulk_out_buffer) {
+		kfree (port->bulk_out_buffer);
+		port->bulk_out_buffer = NULL;
+	}
 
+	usb_set_serial_port_data(serial->port, priv);
+	
 	return (0);
 }
 
 
-static int ftdi_8U232AM_startup (struct usb_serial *serial)
+/* Startup for the SIO chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_SIO_startup (struct usb_serial *serial)
 {
 	struct ftdi_private *priv;
- 
+	int err;
 
-	priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
-	if (!priv){
-		err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
-		return -ENOMEM;
-	}
+	dbg("%s",__FUNCTION__);
 
-	priv->ftdi_type = F8U232AM;
-	priv->write_offset = 0;
-	usb_set_serial_port_data(serial->port, priv);
+	err = ftdi_common_startup(serial);
+	if (err){
+		return (err);
+	}
 
+	priv = usb_get_serial_port_data(serial->port);
+	priv->chip_type = SIO;
+	priv->baud_base = 12000000 / 16;
+	priv->write_offset = 1;
+	
 	return (0);
 }
 
-static void ftdi_sio_shutdown (struct usb_serial *serial)
-{
-	void *priv;
+/* Startup for the 8U232AM chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_8U232AM_startup (struct usb_serial *serial)
+{ /* ftdi_8U232AM_startup */
+	struct ftdi_private *priv;
+	int err;
+
+	dbg("%s",__FUNCTION__);
+	err = ftdi_common_startup(serial);
+	if (err){
+		return (err);
+	}
+
+	priv = usb_get_serial_port_data(serial->port);
+	priv->chip_type = FT8U232AM;
+	priv->baud_base = 48000000 / 2; /* Would be / 16, but FTDI supports 0.125, 0.25 and 0.5 divisor fractions! */
+	
+	return (0);
+} /* ftdi_8U232AM_startup */
+
+/* Startup for the FT232BM chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_FT232BM_startup (struct usb_serial *serial)
+{ /* ftdi_FT232BM_startup */
+	struct ftdi_private *priv;
+	int err;
+
+	dbg("%s",__FUNCTION__);
+	err = ftdi_common_startup(serial);
+	if (err){
+		return (err);
+	}
+
+	priv = usb_get_serial_port_data(serial->port);
+	priv->chip_type = FT232BM;
+	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */
+	
+	return (0);
+} /* ftdi_FT232BM_startup */
+
+/* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */
+/* Called from usbserial:serial_probe */
+static int ftdi_USB_UIRT_startup (struct usb_serial *serial)
+{ /* ftdi_USB_UIRT_startup */
+	struct ftdi_private *priv;
+	int err;
+
+	dbg("%s",__FUNCTION__);
+	err = ftdi_8U232AM_startup(serial);
+	if (err){
+		return (err);
+	}
+
+	priv = usb_get_serial_port_data(serial->port);
+	priv->flags |= ASYNC_SPD_CUST;
+	priv->custom_divisor = 77;
+	priv->force_baud = B38400;
+	
+	return (0);
+} /* ftdi_USB_UIRT_startup */
+
+/* Startup for the HE-TIRA1 device, which requires hardwired
+ * baudrate (38400 gets mapped to 100000) */
+static int ftdi_HE_TIRA1_startup (struct usb_serial *serial)
+{ /* ftdi_HE_TIRA1_startup */
+	struct ftdi_private *priv;
+	int err;
+
+	dbg("%s",__FUNCTION__);
+	err = ftdi_FT232BM_startup(serial);
+	if (err){
+		return (err);
+	}
+
+	priv = usb_get_serial_port_data(serial->port);
+	priv->flags |= ASYNC_SPD_CUST;
+	priv->custom_divisor = 240;
+	priv->force_baud = B38400;
+	priv->force_rtscts = 1;
+	
+	return (0);
+} /* ftdi_HE_TIRA1_startup */
+
+
+/* ftdi_shutdown is called from usbserial:usb_serial_disconnect 
+ *   it is called when the usb device is disconnected
+ *
+ *   usbserial:usb_serial_disconnect
+ *      calls __serial_close for each open of the port
+ *      shutdown is called then (ie ftdi_shutdown)
+ */
+
+
+static void ftdi_shutdown (struct usb_serial *serial)
+{ /* ftdi_shutdown */
+	
+	struct usb_serial_port *port = serial->port;	
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 
 	dbg("%s", __FUNCTION__);
 
-	priv = usb_get_serial_port_data(&serial->port[0]);
-	if (priv){
+	/* all open ports are closed at this point 
+         *    (by usbserial.c:__serial_close, which calls ftdi_close)  
+	 */
+
+	if (priv) {
 		kfree(priv);
-		usb_set_serial_port_data(&serial->port[0], NULL);
+		usb_set_serial_port_data(port, NULL);
 	}
-}
-
+} /* ftdi_shutdown */
 
 
-static int  ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
-{ /* ftdi_sio_open */
+static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
+{ /* ftdi_open */
 	struct termios tmp_termios;
 	struct usb_serial *serial = port->serial;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	
 	int result = 0;
 	char buf[1]; /* Needed for the usb_control_msg I think */
 
 	dbg("%s", __FUNCTION__);
 
-	/* This will push the characters through immediately rather 
-	   than queue a task to deliver them */
-	port->tty->low_latency = 1;
+
+	port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 	/* No error checking for this (will get errors later anyway) */
 	/* See ftdi_sio.h for description of what is reset */
@@ -343,19 +1148,20 @@
 			FTDI_SIO_RESET_SIO, 
 			0, buf, 0, WDR_TIMEOUT);
 
-	/* Setup termios defaults. According to tty_io.c the 
-	   settings are driver specific */
-	port->tty->termios->c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	/* Termios defaults are set by usb_serial_init. We don't change
+	   port->tty->termios - this would loose speed settings, etc.
+	   This is same behaviour as serial.c/rs_open() - Kuba */
 
-	/* ftdi_sio_set_termios  will send usb control messages */
-	ftdi_sio_set_termios(port, &tmp_termios);	
+	/* ftdi_set_termios  will send usb control messages */
+	ftdi_set_termios(port, &tmp_termios);
 
+	/* FIXME: Flow control might be enabled, so it should be checked -
+	   we have no control of defaults! */
 	/* Turn on RTS and DTR since we are not flow controlling by default */
-	if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) {
+	if (set_dtr(port, HIGH) < 0) {
 		err("%s Error from DTR HIGH urb", __FUNCTION__);
 	}
-	if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){
+	if (set_rts(port, HIGH) < 0){
 		err("%s Error from RTS HIGH urb", __FUNCTION__);
 	}
 
@@ -363,23 +1169,37 @@
 	usb_fill_bulk_urb(port->read_urb, serial->dev, 
 		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
 		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      ftdi_sio_read_bulk_callback, port);
+		      ftdi_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result)
 		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
 
+
 	return result;
-} /* ftdi_sio_open */
+} /* ftdi_open */
+
 
 
-static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
-{ /* ftdi_sio_close */
-	struct usb_serial *serial = port->serial; /* Checked in usbserial.c */
+/* 
+ * usbserial:__serial_close  only calls ftdi_close if the point is open
+ *
+ *   This only gets called when it is the last close
+ *   
+ *   
+ */
+
+static void ftdi_close (struct usb_serial_port *port, struct file *filp)
+{ /* ftdi_close */
+	struct usb_serial *serial;
 	unsigned int c_cflag = port->tty->termios->c_cflag;
 	char buf[1];
 
 	dbg("%s", __FUNCTION__);
 
+	serial = get_usb_serial ( port, __FUNCTION__);
+	if (!serial)
+		return;
+
 	if (serial->dev) {
 		if (c_cflag & HUPCL){
 			/* Disable flow control */
@@ -392,38 +1212,46 @@
 			}	    
 
 			/* drop DTR */
-			if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){
+			if (set_dtr(port, LOW) < 0){
 				err("Error from DTR LOW urb");
 			}
 			/* drop RTS */
-			if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) {
+			if (set_rts(port, LOW) < 0) {
 				err("Error from RTS LOW urb");
 			}	
+			/* shutdown our bulk read */
+			if (port->read_urb) {
+				usb_unlink_urb (port->read_urb);	
+			}
+			/* unlink the running write urbs */
+			
+
 		} /* Note change no line is hupcl is off */
+	} /* if (serial->dev) */
 
-		/* shutdown our bulk reads and writes */
-		/* ***CHECK*** behaviour when there is nothing queued */
-		usb_unlink_urb (port->write_urb);
-		usb_unlink_urb (port->read_urb);
-	}
-} /* ftdi_sio_close */
+
+} /* ftdi_close */
 
 
   
-/* The ftdi_sio requires the first byte to have:
+/* The SIO requires the first byte to have:
  *  B0 1
  *  B1 0
  *  B2..7 length of message excluding byte 0
+ *
+ * The new devices do not require this byte
  */
-static int ftdi_sio_write (struct usb_serial_port *port, int from_user, 
+static int ftdi_write (struct usb_serial_port *port, int from_user,
 			   const unsigned char *buf, int count)
-{ /* ftdi_sio_write */
-	struct usb_serial *serial = port->serial;
+{ /* ftdi_write */
+	struct usb_serial *serial = get_usb_serial ( port, __FUNCTION__);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	unsigned char *first_byte = port->write_urb->transfer_buffer;
-	int data_offset ;
-	int result;
-	
+	struct urb *urb;
+	unsigned char *buffer;
+	int data_offset ;       /* will be 1 for the SIO and 0 otherwise */
+	int status;
+	int transfer_size;
+
 	dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
 
 	if (count == 0) {
@@ -434,123 +1262,209 @@
 	data_offset = priv->write_offset;
         dbg("data_offset set to %d",data_offset);
 
-	if (port->write_urb->status == -EINPROGRESS) {
-		dbg("%s - already writing", __FUNCTION__);
-		return (0);
-	}		
-
-	count += data_offset;
-	count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
-	/* Copy in the data to send */
-	if (from_user) {
-		if (copy_from_user(port->write_urb->transfer_buffer + data_offset,
-				   buf, count - data_offset )){
-			return -EFAULT;
+	/* Determine total transfer size */
+	transfer_size = count;
+	if (data_offset > 0) {
+		/* Original sio needs control bytes too... */
+		transfer_size += (data_offset *
+				((count + (PKTSZ - 1 - data_offset)) /
+				 (PKTSZ - data_offset)));
+	}
+
+	buffer = kmalloc (transfer_size, GFP_ATOMIC);
+	if (!buffer) {
+		err("%s ran out of kernel memory for urb ...", __FUNCTION__);
+		return -ENOMEM;
+	}
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		err("%s - no more free urbs", __FUNCTION__);
+		kfree (buffer);
+		return -ENOMEM;
+	}
+
+	/* Copy data */
+	if (data_offset > 0) {
+		/* Original sio requires control byte at start of each packet. */
+		int user_pktsz = PKTSZ - data_offset;
+		int todo = count;
+		unsigned char *first_byte = buffer;
+		const unsigned char *current_position = buf;
+
+		while (todo > 0) {
+			if (user_pktsz > todo) {
+				user_pktsz = todo;
+			}
+			/* Write the control byte at the front of the packet*/
+			*first_byte = 1 | ((user_pktsz) << 2); 
+			/* Copy data for packet */
+			if (from_user) {
+				if (copy_from_user (first_byte + data_offset,
+						    current_position, user_pktsz)){
+					kfree (buffer);
+					usb_free_urb (urb);
+					return -EFAULT;
+				}
+			} else {
+				memcpy (first_byte + data_offset,
+					current_position, user_pktsz);
+			}
+			first_byte += user_pktsz + data_offset;
+			current_position += user_pktsz;
+			todo -= user_pktsz;
 		}
 	} else {
-		memcpy(port->write_urb->transfer_buffer + data_offset,
-		       buf, count - data_offset );
-	}  
-
-	first_byte = port->write_urb->transfer_buffer;
-	if (data_offset > 0){
-		/* Write the control byte at the front of the packet*/
-		*first_byte = 1 | ((count-data_offset) << 2) ; 
+		/* No control byte required. */
+		/* Copy in the data to send */
+		if (from_user) {
+			if (copy_from_user (buffer, buf, count)) {
+				kfree (buffer);
+				usb_free_urb (urb);
+				return -EFAULT;
+			}
+		} else {
+			memcpy (buffer, buf, count);
+		}
 	}
 
-	dbg("%s Bytes: %d, First Byte: 0x%02x", __FUNCTION__,count, first_byte[0]);
-	usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte);
-		
-	/* send the data out the bulk port */
-	usb_fill_bulk_urb(port->write_urb, serial->dev, 
+	usb_serial_debug_data (__FILE__, __FUNCTION__, transfer_size, buffer);
+
+	/* fill the buffer and send it */
+	usb_fill_bulk_urb(urb, serial->dev, 
 		      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
-		      port->write_urb->transfer_buffer, count,
-		      ftdi_sio_write_bulk_callback, port);
-		
-	result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
-	if (result) {
-		err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
-		return 0;
+		      buffer, transfer_size,
+		      ftdi_write_bulk_callback, port);
+
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status) {
+		err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
+		count = status;
 	}
 
-	dbg("%s write returning: %d", __FUNCTION__, count - data_offset);
-	return (count - data_offset);
-} /* ftdi_sio_write */
+	/* we are done with this urb, so let the host driver
+	 * really free it when it is finished with it */
+	usb_free_urb (urb);
+
+	dbg("%s write returning: %d", __FUNCTION__, count);
+	return count;
+} /* ftdi_write */
 
-static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+
+/* This function may get called when the device is closed */
+
+static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
-	struct usb_serial *serial;
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 
 	dbg("%s", __FUNCTION__);
 
-	if (port_paranoia_check (port, "ftdi_sio_write_bulk_callback")) {
+	if (port_paranoia_check (port, __FUNCTION__))
 		return;
-	}
-	
-	serial = port->serial;
-	if (serial_paranoia_check (serial, "ftdi_sio_write_bulk_callback")) {
-		return;
-	}
 	
 	if (urb->status) {
 		dbg("nonzero write bulk status received: %d", urb->status);
 		return;
 	}
 
-	schedule_work(&port->work);
-} /* ftdi_sio_write_bulk_callback */
+	if (!serial) {
+		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+		return;
+	}
+
+	/* Have to check for validity of queueing up the tasks */
+	dbg("%s - port->open_count = %d", __FUNCTION__, port->open_count);
+
+ 	if (port->open_count > 0){
+		schedule_work(&port->work);
+	} 
 
+	return;
+} /* ftdi_write_bulk_callback */
 
-static int ftdi_sio_write_room( struct usb_serial_port *port )
+
+static int ftdi_write_room( struct usb_serial_port *port )
 {
-	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	int room;
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/*
+	 * We really can take anything the user throws at us
+	 * but let's pick a nice big number to tell the tty
+	 * layer that we have lots of free space
+	 */
+	return 2048;
+} /* ftdi_write_room */
 
-	if ( port->write_urb->status == -EINPROGRESS) {
-		/* There is a race here with the _write routines but it won't hurt */
-		room = 0;
-	} else { 
-		room = port->bulk_out_size - priv->write_offset;
-	}
-	return(room);
-} /* ftdi_sio_write_room */
 
+static int ftdi_chars_in_buffer (struct usb_serial_port *port)
+{ /* ftdi_chars_in_buffer */
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	/* 
+	 * We can't really account for how much data we
+	 * have sent out, but hasn't made it through to the
+	 * device, so just tell the tty layer that everything
+	 * is flushed.
+	 */
+	return 0;
+} /* ftdi_chars_in_buffer */
 
-static void ftdi_sio_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{ /* ftdi_sio_serial_buld_callback */
+
+
+static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+{ /* ftdi_read_bulk_callback */
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial;
-       	struct tty_struct *tty = port->tty ;
+	struct tty_struct *tty;
+	struct ftdi_private *priv;
 	char error_flag;
        	unsigned char *data = urb->transfer_buffer;
 
-	const int data_offset = 2;
 	int i;
 	int result;
+	int need_flip;
+	int packet_offset;
 
-	dbg("%s - port %d", __FUNCTION__, port->number);
+	if (urb->number_of_packets > 0) {
+		err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
+		    urb->transfer_buffer_length, urb->actual_length, urb->number_of_packets );
+		err("%s transfer_flags %x ", __FUNCTION__,urb->transfer_flags );
+	}
+
+	dbg("%s", __FUNCTION__);
 
-	if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) {
+	if (port_paranoia_check (port, __FUNCTION__)) {
 		return;
 	}
+	if (port->open_count <= 0)
+		return;
 
-	serial = port->serial;
-	if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) {
+	serial = get_usb_serial(port,__FUNCTION__);
+	if (!serial){
+		dbg("%s - bad serial pointer - exiting",__FUNCTION__);
+		return;
+	}
+	
+	tty = port->tty;
+	if (!tty) {
+		dbg("%s - bad tty pointer - exiting",__FUNCTION__);
 		return;
 	}
 
+	priv = usb_get_serial_port_data(port);
+
 	if (urb->status) {
 		/* This will happen at close every time so it is a dbg not an err */
-		dbg("nonzero read bulk status received: %d", urb->status);
+		dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status);
 		return;
 	}
 
+        /* The first two bytes of every read packet are status */
 	if (urb->actual_length > 2) {
 		usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
 	} else {
-                dbg("Just status 0o%03o0o%03o",data[0],data[1]);
+                dbg("Status only: %03oo %03oo",data[0],data[1]);
         }
 
 
@@ -559,129 +1473,101 @@
 	/* See acm.c - you do a tty_hangup  - eg tty_hangup(tty) */
 	/* if CD is dropped and the line is not CLOCAL then we should hangup */
 
-	/* Handle errors and break */
-	error_flag = TTY_NORMAL;
-        /* Although the device uses a bitmask and hence can have multiple */
-        /* errors on a packet - the order here sets the priority the */
-        /* error is returned to the tty layer  */
-	
-	if ( data[1] & FTDI_RS_OE ) { 
-		error_flag = TTY_OVERRUN;
-                dbg("OVERRRUN error");
-	}
-	if ( data[1] & FTDI_RS_BI ) { 
-		error_flag = TTY_BREAK;
-                dbg("BREAK received");
-	}
-	if ( data[1] & FTDI_RS_PE ) { 
-		error_flag = TTY_PARITY;
-                dbg("PARITY error");
-	}
-	if ( data[1] & FTDI_RS_FE ) { 
-		error_flag = TTY_FRAME;
-                dbg("FRAMING error");
-	}
-	if (urb->actual_length > data_offset) {
-
-		for (i = data_offset ; i < urb->actual_length ; ++i) {
-			/* have to make sure we don't overflow the buffer
-			  with tty_insert_flip_char's */
-			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-				tty_flip_buffer_push(tty);
-			}
-			/* Note that the error flag is duplicated for 
-			   every character received since we don't know
-			   which character it applied to */
-			tty_insert_flip_char(tty, data[i], error_flag);
+	need_flip = 0;
+	for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+		/* Compare new line status to the old one, signal if different */
+		if (priv != NULL) {
+			char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
+			if (new_status != priv->prev_status) {
+				priv->diff_status |= new_status ^ priv->prev_status;
+				wake_up_interruptible(&priv->delta_msr_wait);
+				priv->prev_status = new_status;
+			}
 		}
-	  	tty_flip_buffer_push(tty);
-
 
-	} 
+		/* Handle errors and break */
+		error_flag = TTY_NORMAL;
+		/* Although the device uses a bitmask and hence can have multiple */
+		/* errors on a packet - the order here sets the priority the */
+		/* error is returned to the tty layer  */
+
+		if ( data[packet_offset+1] & FTDI_RS_OE ) {
+			error_flag = TTY_OVERRUN;
+			dbg("OVERRRUN error");
+		}
+		if ( data[packet_offset+1] & FTDI_RS_BI ) {
+			error_flag = TTY_BREAK;
+			dbg("BREAK received");
+		}
+		if ( data[packet_offset+1] & FTDI_RS_PE ) {
+			error_flag = TTY_PARITY;
+			dbg("PARITY error");
+		}
+		if ( data[packet_offset+1] & FTDI_RS_FE ) {
+			error_flag = TTY_FRAME;
+			dbg("FRAMING error");
+		}
+		if (urb->actual_length > packet_offset + 2) {
+			for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) {
+				/* have to make sure we don't overflow the buffer
+				  with tty_insert_flip_char's */
+				if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+					tty_flip_buffer_push(tty);
+				}
+				/* Note that the error flag is duplicated for 
+				   every character received since we don't know
+				   which character it applied to */
+				tty_insert_flip_char(tty, data[packet_offset+i], error_flag);
+			}
+			need_flip = 1;
+		}
 
 #ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW
-	/* if a parity error is detected you get status packets forever
-	   until a character is sent without a parity error.
-	   This doesn't work well since the application receives a never
-	   ending stream of bad data - even though new data hasn't been sent.
-	   Therefore I (bill) have taken this out.
-	   However - this might make sense for framing errors and so on 
-	   so I am leaving the code in for now.
-	*/
-      else {
-		if (error_flag != TTY_NORMAL){
-			dbg("error_flag is not normal");
+		/* if a parity error is detected you get status packets forever
+		   until a character is sent without a parity error.
+		   This doesn't work well since the application receives a never
+		   ending stream of bad data - even though new data hasn't been sent.
+		   Therefore I (bill) have taken this out.
+		   However - this might make sense for framing errors and so on 
+		   so I am leaving the code in for now.
+		*/
+		else {
+			if (error_flag != TTY_NORMAL){
+				dbg("error_flag is not normal");
 				/* In this case it is just status - if that is an error send a bad character */
 				if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
 					tty_flip_buffer_push(tty);
 				}
 				tty_insert_flip_char(tty, 0xff, error_flag);
-				tty_flip_buffer_push(tty);
+				need_flip = 1;
+			}
 		}
-	}
 #endif
+	} /* "for(packet_offset=0..." */
 
-	/* Continue trying to always read  */
-	usb_fill_bulk_urb(port->read_urb, serial->dev, 
-		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      ftdi_sio_read_bulk_callback, port);
-
-	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-	if (result)
-		err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+	/* Low latency */
+	if (need_flip) {
+		tty_flip_buffer_push(tty);
+	}
+
+	/* if the port is closed stop trying to read */
+	if (port->open_count > 0){
+		/* Continue trying to always read  */
+		usb_fill_bulk_urb(port->read_urb, serial->dev, 
+			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+			      ftdi_read_bulk_callback, port);
+
+		result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+		if (result)
+			err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+	}
 
 	return;
-} /* ftdi_sio_serial_read_bulk_callback */
-
+} /* ftdi_read_bulk_callback */
 
-static __u16 translate_baudrate_to_ftdi(unsigned int cflag, enum ftdi_type ftdi_type) 
-{ /* translate_baudrate_to_ftdi */
-	
-	__u16 urb_value = ftdi_sio_b9600;
 
-	if (ftdi_type == sio){
-		switch(cflag & CBAUD){
-		case B0: break; /* ignored by this */
-		case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break;
-		case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break;
-		case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break;
-		case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break;
-		case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break;
-		case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
-		case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break;
-		case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break;
-		case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break;
-		case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break;
-		default: dbg("%s - FTDI_SIO does not support the baudrate (%d) requested",
-			     __FUNCTION__, (cflag & CBAUD)); 
-		   break;
-		}
-	} else { /* it is 8U232AM */
-		switch(cflag & CBAUD){
-		case B0: break; /* ignored by this */
-		case B300: urb_value = ftdi_8U232AM_48MHz_b300; dbg("Set to 300"); break;
-		case B600: urb_value = ftdi_8U232AM_48MHz_b600; dbg("Set to 600") ; break;
-		case B1200: urb_value = ftdi_8U232AM_48MHz_b1200; dbg("Set to 1200") ; break;
-		case B2400: urb_value = ftdi_8U232AM_48MHz_b2400; dbg("Set to 2400") ; break;
-		case B4800: urb_value = ftdi_8U232AM_48MHz_b4800; dbg("Set to 4800") ; break;
-		case B9600: urb_value = ftdi_8U232AM_48MHz_b9600; dbg("Set to 9600") ; break;
-		case B19200: urb_value = ftdi_8U232AM_48MHz_b19200; dbg("Set to 19200") ; break;
-		case B38400: urb_value = ftdi_8U232AM_48MHz_b38400; dbg("Set to 38400") ; break;
-		case B57600: urb_value = ftdi_8U232AM_48MHz_b57600; dbg("Set to 57600") ; break;
-		case B115200: urb_value = ftdi_8U232AM_48MHz_b115200; dbg("Set to 115200") ; break;
-		case B230400: urb_value = ftdi_8U232AM_48MHz_b230400; dbg("Set to 230400") ; break;
-		case B460800: urb_value = ftdi_8U232AM_48MHz_b460800; dbg("Set to 460800") ; break;
-		case B921600: urb_value = ftdi_8U232AM_48MHz_b921600; dbg("Set to 921600") ; break;
-		default: dbg("%s - The baudrate (%d) requested is not implemented",
-			     __FUNCTION__, (cflag & CBAUD)); 
-		   break;
-		}
-	}
-	return(urb_value);
-}
-
-static void ftdi_sio_break_ctl( struct usb_serial_port *port, int break_state )
+static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
 {
 	struct usb_serial *serial = port->serial;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -704,32 +1590,48 @@
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
 			    urb_value , 0,
 			    buf, 0, WDR_TIMEOUT) < 0) {
-		err("%s - FAILED to enable/disable break state (state was %d)",
-		    __FUNCTION__, break_state);
+		err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
 	}	   
 
-	dbg("%s - break state is %d - urb is %d", __FUNCTION__, break_state, urb_value);
+	dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value);
 	
 }
 
 
+/* old_termios contains the original termios settings and tty->termios contains
+ * the new setting to be used
+ * WARNING: set_termios calls this with old_termios in kernel space
+ */
 
-/* As I understand this - old_termios contains the original termios settings */
-/*  and tty->termios contains the new setting to be used */
-/* */
-/*   WARNING: set_termios calls this with old_termios in kernel space */
-
-static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *old_termios)
-{ /* ftdi_sio_set_termios */
+static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+{ /* ftdi_termios */
 	struct usb_serial *serial = port->serial;
 	unsigned int cflag = port->tty->termios->c_cflag;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	__u16 urb_value; /* will hold the new flags */
 	char buf[1]; /* Perhaps I should dynamically alloc this? */
 	
+	// Added for xon/xoff support
+	unsigned int iflag = port->tty->termios->c_iflag;
+	unsigned char vstop;
+	unsigned char vstart;
 	
 	dbg("%s", __FUNCTION__);
 
+	/* Force baud rate if this device requires it, unless it is set to B0. */
+	if (priv->force_baud && ((port->tty->termios->c_cflag & CBAUD) != B0)) {
+		dbg("%s: forcing baud rate for this device", __FUNCTION__);
+		port->tty->termios->c_cflag &= ~CBAUD;
+		port->tty->termios->c_cflag |= priv->force_baud;
+	}
+
+	/* Force RTS-CTS if this device requires it. */
+	if (priv->force_rtscts) {
+		dbg("%s: forcing rtscts for this device", __FUNCTION__);
+		port->tty->termios->c_cflag |= CRTSCTS;
+	}
+
+	cflag = port->tty->termios->c_cflag;
 
 	/* FIXME -For this cut I don't care if the line is really changing or 
 	   not  - so just do the change regardless  - should be able to 
@@ -771,8 +1673,6 @@
 	}	   
 
 	/* Now do the baudrate */
-	urb_value = translate_baudrate_to_ftdi((cflag & CBAUD), priv->ftdi_type);
-	
 	if ((cflag & CBAUD) == B0 ) {
 		/* Disable flow control */
 		if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -783,24 +1683,20 @@
 			err("%s error from disable flowcontrol urb", __FUNCTION__);
 		}	    
 		/* Drop RTS and DTR */
-		if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
+		if (set_dtr(port, LOW) < 0){
 			err("%s Error from DTR LOW urb", __FUNCTION__);
 		}
-		if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){
+		if (set_rts(port, LOW) < 0){
 			err("%s Error from RTS LOW urb", __FUNCTION__);
 		}	
 		
 	} else {
 		/* set the baudrate determined before */
-		if (usb_control_msg(serial->dev, 
-				    usb_sndctrlpipe(serial->dev, 0),
-				    FTDI_SIO_SET_BAUDRATE_REQUEST, 
-				    FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
-				    urb_value, 0, 
-				    buf, 0, 100) < 0) {
+		if (change_speed(port)) {
 			err("%s urb failed to set baurdrate", __FUNCTION__);
 		}
 	}
+
 	/* Set flow control */
 	/* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
 	if (cflag & CRTSCTS) {
@@ -815,146 +1711,290 @@
 		}		
 		
 	} else { 
-		/* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
-		dbg("%s Turning off hardware flow control", __FUNCTION__);
-		if (usb_control_msg(serial->dev, 
-				    usb_sndctrlpipe(serial->dev, 0),
-				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
-				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, 0, 
-				    buf, 0, WDR_TIMEOUT) < 0) {
-			err("urb failed to clear flow control");
-		}				
+		/*
+		 * Xon/Xoff code
+		 *
+		 * Check the IXOFF status in the iflag component of the termios structure
+		 * if IXOFF is not set, the pre-xon/xoff code is executed.
+		*/
+		if (iflag & IXOFF) {
+			dbg("%s  request to enable xonxoff iflag=%04x",__FUNCTION__,iflag);
+			// Try to enable the XON/XOFF on the ftdi_sio
+			// Set the vstart and vstop -- could have been done up above where
+			// a lot of other dereferencing is done but that would be very
+			// inefficient as vstart and vstop are not always needed
+			vstart=port->tty->termios->c_cc[VSTART];
+			vstop=port->tty->termios->c_cc[VSTOP];
+			urb_value=(vstop << 8) | (vstart);
+
+			if (usb_control_msg(serial->dev,
+					    usb_sndctrlpipe(serial->dev, 0),
+					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+					    urb_value , FTDI_SIO_XON_XOFF_HS,
+					    buf, 0, WDR_TIMEOUT) < 0) {
+				err("urb failed to set to xon/xoff flow control");
+			}
+		} else {
+			/* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */
+			/* CHECKME Assuming XON/XOFF handled by tty stack - not by device */
+			dbg("%s Turning off hardware flow control", __FUNCTION__);
+			if (usb_control_msg(serial->dev, 
+					    usb_sndctrlpipe(serial->dev, 0),
+					    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+					    0, 0, 
+					    buf, 0, WDR_TIMEOUT) < 0) {
+				err("urb failed to clear flow control");
+			}				
+		}
 		
 	}
 	return;
-} /* ftdi_sio_set_termios */
+} /* ftdi_termios */
 
-static int ftdi_sio_tiocmget (struct usb_serial_port *port, struct file *file)
+
+static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial *serial = port->serial;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
-	char *buf = NULL;
-	int ret = -EINVAL;
-	int size;
+
+	__u16 urb_value=0; /* Will hold the new flags */
+	char buf[2];
+	int  ret, mask;
 	
-	dbg("%s", __FUNCTION__);
+	dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
 
-	buf = kmalloc(2, GFP_KERNEL);
-	if (!buf)
-		goto exit;
+	/* Based on code from acm.c and others */
+	switch (cmd) {
 
-	if (priv->ftdi_type == sio) {
-		size = 1;
-	} else {
-		/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same 
-		   format as the data returned from the in point */
-		size = 2;
-	}
-	ret = usb_control_msg(serial->dev,
-			      usb_rcvctrlpipe(serial->dev, 0),
-			      FTDI_SIO_GET_MODEM_STATUS_REQUEST,
-			      FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-			      0, 0, buf, size, WDR_TIMEOUT);
-	if (ret < 0) {
-		err("%s Could not get modem status of device - err: %d",
-		    __FUNCTION__, ret);
-		goto exit;
-	}
-
-	ret = (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
-		(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
-		(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
-		(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0);
-
-exit:
-	kfree(buf);
-	return ret;
-}
+	case TIOCMGET:
+		dbg("%s TIOCMGET", __FUNCTION__);
+		switch (priv->chip_type) {
+		case SIO:
+			/* Request the status from the device */
+			if ((ret = usb_control_msg(serial->dev, 
+						   usb_rcvctrlpipe(serial->dev, 0),
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+						   0, 0, 
+						   buf, 1, WDR_TIMEOUT)) < 0 ) {
+				err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+				    ret);
+				return(ret);
+			}
+			break;
+		case FT8U232AM:
+		case FT232BM:
+			/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
+			   format as the data returned from the in point */
+			if ((ret = usb_control_msg(serial->dev, 
+						   usb_rcvctrlpipe(serial->dev, 0),
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+						   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+						   0, 0, 
+						   buf, 2, WDR_TIMEOUT)) < 0 ) {
+				err("%s Could not get modem status of device - err: %d", __FUNCTION__,
+				    ret);
+				return(ret);
+			}
+			break;
+		default:
+			return -EFAULT;
+			break;
+		}
 
-static int ftdi_sio_tiocmset (struct usb_serial_port *port, struct file *file,
-			      unsigned int set, unsigned int clear)
-{
-	struct usb_serial *serial = port->serial;
-	int ret = 0;
-	
-	dbg("%s", __FUNCTION__);
+		return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+				(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+				(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
+				(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0) |
+				priv->last_dtr_rts,
+				(unsigned long *) arg);
+		break;
 
-	if (set & TIOCM_RTS)
-		if ((ret = set_rts(serial->dev, 
-				   usb_sndctrlpipe(serial->dev, 0),
-				   HIGH)) < 0) {
-			err("Urb to set RTS failed");
-			goto exit;
+	case TIOCMSET: /* Turns on and off the lines as specified by the mask */
+		dbg("%s TIOCMSET", __FUNCTION__);
+		if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
+		urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW);
+		if ((ret = set_dtr(port, urb_value)) < 0){
+			err("Error from DTR set urb (TIOCMSET)");
+			return(ret);
 		}
-
-	if (set & TIOCM_DTR)
-		if ((ret = set_dtr(serial->dev, 
-				   usb_sndctrlpipe(serial->dev, 0),
-				   HIGH)) < 0) {
-			err("Urb to set DTR failed");
-			goto exit;
+		urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW);
+		if ((ret = set_rts(port, urb_value)) < 0){
+			err("Error from RTS set urb (TIOCMSET)");
+			return(ret);
 		}
-
-	if (clear & TIOCM_RTS)
-		if ((ret = set_rts(serial->dev, 
-				   usb_sndctrlpipe(serial->dev, 0),
-				   LOW)) < 0) {
-			err("Urb to unset RTS failed");
-			goto exit;
+		return(0);
+		break;
+					
+	case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */
+		dbg("%s TIOCMBIS", __FUNCTION__);
+ 	        if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
+  	        if (mask & TIOCM_DTR){
+			if ((ret = set_dtr(port, HIGH)) < 0) {
+				err("Urb to set DTR failed");
+				return(ret);
+			}
 		}
+		if (mask & TIOCM_RTS) {
+			if ((ret = set_rts(port, HIGH)) < 0){
+				err("Urb to set RTS failed");
+				return(ret);
+			}
+		}
+		return(0);
+		break;
 
-	if (clear & TIOCM_DTR)
-		if ((ret = set_dtr(serial->dev, 
-				   usb_sndctrlpipe(serial->dev, 0),
-				   LOW)) < 0) {
-			err("Urb to unset DTR failed");
-			goto exit;
+	case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */
+		dbg("%s TIOCMBIC", __FUNCTION__);
+ 	        if (get_user(mask, (unsigned long *) arg))
+			return -EFAULT;
+  	        if (mask & TIOCM_DTR){
+			if ((ret = set_dtr(port, LOW)) < 0){
+				err("Urb to unset DTR failed");
+				return(ret);
+			}
+		}	
+		if (mask & TIOCM_RTS) {
+			if ((ret = set_rts(port, LOW)) < 0){
+				err("Urb to unset RTS failed");
+				return(ret);
+			}
 		}
+		return(0);
+		break;
 
-exit:
-	return ret;
-}
+		/*
+		 * I had originally implemented TCSET{A,S}{,F,W} and
+		 * TCGET{A,S} here separately, however when testing I
+		 * found that the higher layers actually do the termios
+		 * conversions themselves and pass the call onto
+		 * ftdi_sio_set_termios. 
+		 *
+		 */
+
+	case TIOCGSERIAL: /* gets serial port data */
+		return get_serial_info(port, (struct serial_struct *) arg);
+
+	case TIOCSSERIAL: /* sets serial port data */
+		return set_serial_info(port, (struct serial_struct *) arg);
+
+	/*
+	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+	 * - mask passed in arg for lines of interest
+	 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+	 * Caller should use TIOCGICOUNT to see which one it was.
+	 *
+	 * This code is borrowed from linux/drivers/char/serial.c
+	 */
+	case TIOCMIWAIT:
+		while (priv != NULL) {
+			interruptible_sleep_on(&priv->delta_msr_wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			else {
+				char diff = priv->diff_status;
 
-static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	dbg("%s cmd 0x%04x", __FUNCTION__, cmd);
+				if (diff == 0) {
+					return -EIO; /* no change => error */
+				}
 
-	switch (cmd) {
+				/* Consume all events */
+				priv->diff_status = 0;
+
+				/* Return 0 if caller wanted to know about these bits */
+				if ( ((arg & TIOCM_RNG) && (diff & FTDI_RS0_RI)) ||
+				     ((arg & TIOCM_DSR) && (diff & FTDI_RS0_DSR)) ||
+				     ((arg & TIOCM_CD)  && (diff & FTDI_RS0_RLSD)) ||
+				     ((arg & TIOCM_CTS) && (diff & FTDI_RS0_CTS)) ) {
+					return 0;
+				}
+				/*
+				 * Otherwise caller can't care less about what happened,
+				 * and so we continue to wait for more events.
+				 */
+			}
+		}
+		return(0);
+		break;
 	default:
-	  /* This is not an error - turns out the higher layers will do 
-	   *  some ioctls itself
- 	   */
-		dbg("%s arg not supported - it was 0x%04x", __FUNCTION__,cmd);
-		return(-ENOIOCTLCMD);
 		break;
+		
 	}
-	return 0;
-} /* ftdi_sio_ioctl */
 
 
-static int __init ftdi_sio_init (void)
+	/* This is not necessarily an error - turns out the higher layers will do 
+	 *  some ioctls itself (see comment above)
+	 */
+	dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd);
+
+	return(-ENOIOCTLCMD);
+} /* ftdi_ioctl */
+
+
+static void ftdi_throttle (struct usb_serial_port *port)
 {
+	dbg("%s - port %d", __FUNCTION__, port->number);
+	usb_unlink_urb (port->read_urb);
+}
+
+
+static void ftdi_unthrottle (struct usb_serial_port *port)
+{
+	int result;
+	struct usb_serial *serial = port->serial;
+
+	dbg("%s - port %d", __FUNCTION__, port->number);
+
+	port->read_urb->dev = serial->dev;
+
+	usb_fill_bulk_urb(port->read_urb, serial->dev, 
+		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+		      ftdi_read_bulk_callback, port);
+
+	result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+	if (result)
+		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+}
+
+static int __init ftdi_init (void)
+{
+
 	dbg("%s", __FUNCTION__);
-	usb_serial_register (&ftdi_sio_device);
+	usb_serial_register (&ftdi_SIO_device);
 	usb_serial_register (&ftdi_8U232AM_device);
+	usb_serial_register (&ftdi_FT232BM_device);
+	usb_serial_register (&ftdi_USB_UIRT_device);
+	usb_serial_register (&ftdi_HE_TIRA1_device);
 	usb_register (&ftdi_driver);
+
 	info(DRIVER_VERSION ":" DRIVER_DESC);
 	return 0;
 }
 
 
-static void __exit ftdi_sio_exit (void)
+static void __exit ftdi_exit (void)
 {
+
 	dbg("%s", __FUNCTION__);
+
 	usb_deregister (&ftdi_driver);
-	usb_serial_deregister (&ftdi_sio_device);
+	usb_serial_deregister (&ftdi_HE_TIRA1_device);
+	usb_serial_deregister (&ftdi_USB_UIRT_device);
+	usb_serial_deregister (&ftdi_FT232BM_device);
 	usb_serial_deregister (&ftdi_8U232AM_device);
+	usb_serial_deregister (&ftdi_SIO_device);
+
 }
 
 
-module_init(ftdi_sio_init);
-module_exit(ftdi_sio_exit);
+module_init(ftdi_init);
+module_exit(ftdi_exit);
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/usb/serial/ftdi_sio.h	Fri Jul 11 01:25:29 2003
@@ -14,11 +14,12 @@
  * of the protocol required to talk to the device and ongoing assistence
  * during development.
  *
- * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc.- wrote the 
+ * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the 
  * FTDI_SIO implementation.
  *
  * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais
  * from Rudolf Gugler
+ *
  */
 
 #define FTDI_VID	0x0403	/* Vendor Id */
@@ -28,6 +29,93 @@
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
 
+
+/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
+/* they use the ftdi chipset for the USB interface and the vendor id is the same */
+#define FTDI_XF_634_PID  0xFC09	/* Four line device */
+#define FTDI_XF_632_PID  0xFC08	/* Two line device */
+
+/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */
+/* broadband internet service.  The following PID is exhibited by the usb device supplied */
+/* (the VID is the standard ftdi vid (FTDI_VID) */
+#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */
+
+/*
+ * The following are the values for the Matrix Orbital LCD displays,
+ * which are the FT232BM ( similar to the 8U232AM )
+ */
+#define FTDI_MTXORB_VID                FTDI_VID        /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_0_PID      0xFA00  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_1_PID      0xFA01  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_2_PID      0xFA02  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_3_PID      0xFA03  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_4_PID      0xFA04  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
+#define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
+
+/*
+ * The following are the values for the Sealevel SeaLINK+ adapters.
+ * (Original list sent by Tuan Hoang.  Ian Abbott renamed the macros and
+ * removed some PIDs that don't seem to match any existing products.)
+ */
+#define SEALEVEL_VID		0x0c52	/* Sealevel Vendor ID */
+#define SEALEVEL_2101_PID	0x2101	/* SeaLINK+232 (2101/2105) */
+#define SEALEVEL_2102_PID	0x2102	/* SeaLINK+485 (2102) */
+#define SEALEVEL_2103_PID	0x2103	/* SeaLINK+232I (2103) */
+#define SEALEVEL_2104_PID	0x2104	/* SeaLINK+485I (2104) */
+#define SEALEVEL_2201_1_PID	0x2211	/* SeaPORT+2/232 (2201) Port 1 */
+#define SEALEVEL_2201_2_PID	0x2221	/* SeaPORT+2/232 (2201) Port 2 */
+#define SEALEVEL_2202_1_PID	0x2212	/* SeaPORT+2/485 (2202) Port 1 */
+#define SEALEVEL_2202_2_PID	0x2222	/* SeaPORT+2/485 (2202) Port 2 */
+#define SEALEVEL_2203_1_PID	0x2213	/* SeaPORT+2 (2203) Port 1 */
+#define SEALEVEL_2203_2_PID	0x2223	/* SeaPORT+2 (2203) Port 2 */
+#define SEALEVEL_2401_1_PID	0x2411	/* SeaPORT+4/232 (2401) Port 1 */
+#define SEALEVEL_2401_2_PID	0x2421	/* SeaPORT+4/232 (2401) Port 2 */
+#define SEALEVEL_2401_3_PID	0x2431	/* SeaPORT+4/232 (2401) Port 3 */
+#define SEALEVEL_2401_4_PID	0x2441	/* SeaPORT+4/232 (2401) Port 4 */
+#define SEALEVEL_2402_1_PID	0x2412	/* SeaPORT+4/485 (2402) Port 1 */
+#define SEALEVEL_2402_2_PID	0x2422	/* SeaPORT+4/485 (2402) Port 2 */
+#define SEALEVEL_2402_3_PID	0x2432	/* SeaPORT+4/485 (2402) Port 3 */
+#define SEALEVEL_2402_4_PID	0x2442	/* SeaPORT+4/485 (2402) Port 4 */
+#define SEALEVEL_2403_1_PID	0x2413	/* SeaPORT+4 (2403) Port 1 */
+#define SEALEVEL_2403_2_PID	0x2423	/* SeaPORT+4 (2403) Port 2 */
+#define SEALEVEL_2403_3_PID	0x2433	/* SeaPORT+4 (2403) Port 3 */
+#define SEALEVEL_2403_4_PID	0x2443	/* SeaPORT+4 (2403) Port 4 */
+#define SEALEVEL_2801_1_PID	0X2811	/* SeaLINK+8/232 (2801) Port 1 */
+#define SEALEVEL_2801_2_PID	0X2821	/* SeaLINK+8/232 (2801) Port 2 */
+#define SEALEVEL_2801_3_PID	0X2831	/* SeaLINK+8/232 (2801) Port 3 */
+#define SEALEVEL_2801_4_PID	0X2841	/* SeaLINK+8/232 (2801) Port 4 */
+#define SEALEVEL_2801_5_PID	0X2851	/* SeaLINK+8/232 (2801) Port 5 */
+#define SEALEVEL_2801_6_PID	0X2861	/* SeaLINK+8/232 (2801) Port 6 */
+#define SEALEVEL_2801_7_PID	0X2871	/* SeaLINK+8/232 (2801) Port 7 */
+#define SEALEVEL_2801_8_PID	0X2881	/* SeaLINK+8/232 (2801) Port 8 */
+#define SEALEVEL_2802_1_PID	0X2812	/* SeaLINK+8/485 (2802) Port 1 */
+#define SEALEVEL_2802_2_PID	0X2822	/* SeaLINK+8/485 (2802) Port 2 */
+#define SEALEVEL_2802_3_PID	0X2832	/* SeaLINK+8/485 (2802) Port 3 */
+#define SEALEVEL_2802_4_PID	0X2842	/* SeaLINK+8/485 (2802) Port 4 */
+#define SEALEVEL_2802_5_PID	0X2852	/* SeaLINK+8/485 (2802) Port 5 */
+#define SEALEVEL_2802_6_PID	0X2862	/* SeaLINK+8/485 (2802) Port 6 */
+#define SEALEVEL_2802_7_PID	0X2872	/* SeaLINK+8/485 (2802) Port 7 */
+#define SEALEVEL_2802_8_PID	0X2882	/* SeaLINK+8/485 (2802) Port 8 */
+#define SEALEVEL_2803_1_PID	0X2813	/* SeaLINK+8 (2803) Port 1 */
+#define SEALEVEL_2803_2_PID	0X2823 	/* SeaLINK+8 (2803) Port 2 */
+#define SEALEVEL_2803_3_PID	0X2833 	/* SeaLINK+8 (2803) Port 3 */
+#define SEALEVEL_2803_4_PID	0X2843 	/* SeaLINK+8 (2803) Port 4 */
+#define SEALEVEL_2803_5_PID	0X2853 	/* SeaLINK+8 (2803) Port 5 */
+#define SEALEVEL_2803_6_PID	0X2863 	/* SeaLINK+8 (2803) Port 6 */
+#define SEALEVEL_2803_7_PID	0X2873 	/* SeaLINK+8 (2803) Port 7 */
+#define SEALEVEL_2803_8_PID	0X2883 	/* SeaLINK+8 (2803) Port 8 */
+ 
+/*
+ * Home Electronics (www.home-electro.com) USB gadgets
+ */
+#define FTDI_HE_TIRA1_PID	0xFA78	/* Tira-1 IR tranceiver */
+
+/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */
+/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
+#define FTDI_USB_UIRT_PID	0xF850	/* Product Id */
+
+/* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
 #define FTDI_SIO_SET_FLOW_CTRL	2 /* Set flow control register */
@@ -84,19 +172,61 @@
 /*
  * BmRequestType:  0100 0000B
  * bRequest:       FTDI_SIO_SET_BAUDRATE
- * wValue:         BaudRate value - see below
+ * wValue:         BaudDivisor value - see below
  * wIndex:         Port
  * wLength:        0
  * Data:           None
+ * The BaudDivisor values are calculated as follows:
+ * - BaseClock is either 12000000 or 48000000 depending on the device. FIXME: I wish
+ *   I knew how to detect old chips to select proper base clock!
+ * - BaudDivisor is a fixed point number encoded in a funny way.
+ *   (--WRONG WAY OF THINKING--)
+ *   BaudDivisor is a fixed point number encoded with following bit weighs:
+ *   (-2)(-1)(13..0). It is a radical with a denominator of 4, so values
+ *   end with 0.0 (00...), 0.25 (10...), 0.5 (01...), and 0.75 (11...).
+ *   (--THE REALITY--)
+ *   The both-bits-set has quite different meaning from 0.75 - the chip designers
+ *   have decided it to mean 0.125 instead of 0.75.
+ *   This info looked up in FTDI application note "FT8U232 DEVICES \ Data Rates
+ *   and Flow Control Consideration for USB to RS232".
+ * - BaudDivisor = (BaseClock / 16) / BaudRate, where the (=) operation should
+ *   automagically re-encode the resulting value to take fractions into consideration.
+ * As all values are integers, some bit twiddling is in order:
+ *   BaudDivisor = (BaseClock / 16 / BaudRate) |
+ *   (((BaseClock / 2 / BaudRate) & 4) ? 0x4000    // 0.5
+ *    : ((BaseClock / 2 / BaudRate) & 2) ? 0x8000  // 0.25
+ *    : ((BaseClock / 2 / BaudRate) & 1) ? 0xc000  // 0.125
+ *    : 0)
+ *
+ * For the FT232BM, a 17th divisor bit was introduced to encode the multiples
+ * of 0.125 missing from the FT8U232AM.  Bits 16 to 14 are coded as follows
+ * (the first four codes are the same as for the FT8U232AM, where bit 16 is
+ * always 0):
+ *   000 - add .000 to divisor
+ *   001 - add .500 to divisor
+ *   010 - add .250 to divisor
+ *   011 - add .125 to divisor
+ *   100 - add .375 to divisor
+ *   101 - add .625 to divisor
+ *   110 - add .750 to divisor
+ *   111 - add .875 to divisor
+ * Bits 15 to 0 of the 17-bit divisor are placed in the urb value.  Bit 16 is 
+ * placed in bit 0 of the urb index.
+ *
+ * Note that there are a couple of special cases to support the highest baud
+ * rates.  If the calculated divisor value is 1, this needs to be replaced with
+ * 0.  Additionally for the FT232BM, if the calculated divisor value is 0x4001
+ * (1.5), this needs to be replaced with 0x0001 (1) (but this divisor value is
+ * not supported by the FT8U232AM).
  */
 
-enum ftdi_type {
-	sio = 1,
-	F8U232AM = 2,
-};
+typedef enum {
+	SIO = 1,
+	FT8U232AM = 2,
+	FT232BM = 3,
+} ftdi_chip_type_t;
 
-
-enum {
+typedef enum {
  ftdi_sio_b300 = 0, 
  ftdi_sio_b600 = 1, 
  ftdi_sio_b1200 = 2,
@@ -107,39 +237,12 @@
  ftdi_sio_b38400 = 7,
  ftdi_sio_b57600 = 8,
  ftdi_sio_b115200 = 9
-};
-
+} FTDI_SIO_baudrate_t ;
 
-enum {
-  ftdi_8U232AM_12MHz_b300 = 0x09c4,
-  ftdi_8U232AM_12MHz_b600 = 0x04E2,
-  ftdi_8U232AM_12MHz_b1200 = 0x0271,
-  ftdi_8U232AM_12MHz_b2400 = 0x4138,
-  ftdi_8U232AM_12MHz_b4800 = 0x809c,
-  ftdi_8U232AM_12MHz_b9600 = 0xc04e,
-  ftdi_8U232AM_12MHz_b19200 = 0x0027,
-  ftdi_8U232AM_12MHz_b38400 = 0x4013,
-  ftdi_8U232AM_12MHz_b57600 = 0x000d,
-  ftdi_8U232AM_12MHz_b115200 = 0x4006,
-  ftdi_8U232AM_12MHz_b230400 = 0x8003,
-};
-/* Apparently all devices are 48MHz */
-enum {
-  ftdi_8U232AM_48MHz_b300 = 0x2710,
-  ftdi_8U232AM_48MHz_b600 = 0x1388,
-  ftdi_8U232AM_48MHz_b1200 = 0x09c4,
-  ftdi_8U232AM_48MHz_b2400 = 0x04e2,
-  ftdi_8U232AM_48MHz_b4800 = 0x0271,
-  ftdi_8U232AM_48MHz_b9600 = 0x4138,
-  ftdi_8U232AM_48MHz_b19200 = 0x809c,
-  ftdi_8U232AM_48MHz_b38400 = 0xc04e,
-  ftdi_8U232AM_48MHz_b57600 = 0x0034,
-  ftdi_8U232AM_48MHz_b115200 = 0x001a,
-  ftdi_8U232AM_48MHz_b230400 = 0x000d,
-  ftdi_8U232AM_48MHz_b460800 = 0x4006,
-  ftdi_8U232AM_48MHz_b921600 = 0x8003,
-
-};
+/*
+ * The ftdi_8U232AM_xxMHz_byyy constants have been removed. The encoded divisor values
+ * are calculated internally.
+ */
 
 #define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
 #define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
@@ -443,6 +546,11 @@
  * B7	Error in RCVR FIFO
  * 
  */
+#define FTDI_RS0_CTS	(1 << 4)
+#define FTDI_RS0_DSR	(1 << 5)
+#define FTDI_RS0_RI	(1 << 6)
+#define FTDI_RS0_RLSD	(1 << 7)
+
 #define FTDI_RS_DR  1
 #define FTDI_RS_OE (1<<1)
 #define FTDI_RS_PE (1<<2)
diff -Nru a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
--- a/drivers/usb/storage/datafab.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/usb/storage/datafab.c	Fri Jul 11 01:25:30 2003
@@ -94,7 +94,7 @@
 			     unsigned char *dest, 
 			     int use_sg)
 {
-	unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x20, 0x01 };
+	unsigned char *command = us->iobuf;
 	unsigned char *buffer = NULL;
 	unsigned char *ptr;
 	unsigned char  thistime;
@@ -116,8 +116,6 @@
 			return rc;
 	}
 
-	command[5] += (info->lun << 4);
-
 	totallen = sectors * info->ssize;
 
 	do {
@@ -138,10 +136,13 @@
 		command[3] = (sector >> 8) & 0xFF;
 		command[4] = (sector >> 16) & 0xFF;
 	
+		command[5] = 0xE0 + (info->lun << 4);
 		command[5] |= (sector >> 24) & 0x0F;
+		command[6] = 0x20;
+		command[7] = 0x01;
 
 		// send the read command
-		result = datafab_bulk_write(us, command, sizeof(command));
+		result = datafab_bulk_write(us, command, 8);
 		if (result != USB_STOR_XFER_GOOD)
 			goto leave;
 
@@ -180,8 +181,8 @@
 			      unsigned char *src, 
 			      int use_sg)
 {
-	unsigned char command[8] = { 0, 0, 0, 0, 0, 0xE0, 0x30, 0x02 };
-	unsigned char reply[2] = { 0, 0 };
+	unsigned char *command = us->iobuf;
+	unsigned char *reply = us->iobuf;
 	unsigned char *buffer = NULL;
 	unsigned char *ptr;
 	unsigned char thistime;
@@ -202,8 +203,6 @@
 			return rc;
 	}
 
-	command[5] += (info->lun << 4);
-
 	// If we're using scatter-gather, we have to create a new
 	// buffer to read all of the data in first, since a
 	// scatter-gather buffer could in theory start in the middle
@@ -237,10 +236,13 @@
 		command[3] = (sector >> 8) & 0xFF;
 		command[4] = (sector >> 16) & 0xFF;
 
+		command[5] = 0xE0 + (info->lun << 4);
 		command[5] |= (sector >> 24) & 0x0F;
+		command[6] = 0x30;
+		command[7] = 0x02;
 
 		// send the command
-		result = datafab_bulk_write(us, command, sizeof(command));
+		result = datafab_bulk_write(us, command, 8);
 		if (result != USB_STOR_XFER_GOOD)
 			goto leave;
 
@@ -250,7 +252,7 @@
 			goto leave;
 
 		// read the result
-		result = datafab_bulk_read(us, reply, sizeof(reply));
+		result = datafab_bulk_read(us, reply, 2);
 		if (result != USB_STOR_XFER_GOOD)
 			goto leave;
 
@@ -291,13 +293,19 @@
 	//
 	// There might be a better way of doing this?
 
-	unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
-	unsigned char buf[512];
+	static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
+	unsigned char *command = us->iobuf;
+	unsigned char *buf;
 	int count = 0, rc;
 
 	if (!us || !info)
 		return USB_STOR_TRANSPORT_ERROR;
 
+	memcpy(command, scommand, 8);
+	buf = kmalloc(512, GFP_NOIO);
+	if (!buf)
+		return USB_STOR_TRANSPORT_ERROR;
+
 	US_DEBUGP("datafab_determine_lun:  locating...\n");
 
 	// we'll try 3 times before giving up...
@@ -306,31 +314,41 @@
 		command[5] = 0xa0;
 
 		rc = datafab_bulk_write(us, command, 8);
-		if (rc != USB_STOR_XFER_GOOD) 
-			return USB_STOR_TRANSPORT_ERROR;
+		if (rc != USB_STOR_XFER_GOOD) {
+			rc = USB_STOR_TRANSPORT_ERROR;
+			goto leave;
+		}
 
-		rc = datafab_bulk_read(us, buf, sizeof(buf));
+		rc = datafab_bulk_read(us, buf, 512);
 		if (rc == USB_STOR_XFER_GOOD) {
 			info->lun = 0;
-			return USB_STOR_TRANSPORT_GOOD;
+			rc = USB_STOR_TRANSPORT_GOOD;
+			goto leave;
 		}
 
 		command[5] = 0xb0;
 
 		rc = datafab_bulk_write(us, command, 8);
-		if (rc != USB_STOR_XFER_GOOD) 
-			return USB_STOR_TRANSPORT_ERROR;
+		if (rc != USB_STOR_XFER_GOOD) {
+			rc = USB_STOR_TRANSPORT_ERROR;
+			goto leave;
+		}
 
-		rc = datafab_bulk_read(us, buf, sizeof(buf));
+		rc = datafab_bulk_read(us, buf, 512);
 		if (rc == USB_STOR_XFER_GOOD) {
 			info->lun = 1;
-			return USB_STOR_TRANSPORT_GOOD;
+			rc = USB_STOR_TRANSPORT_GOOD;
+			goto leave;
 		}
 
 		wait_ms(20);
 	}
 
-	return USB_STOR_TRANSPORT_ERROR;
+	rc = USB_STOR_TRANSPORT_ERROR;
+
+ leave:
+	kfree(buf);
+	return rc;
 }
 
 static int datafab_id_device(struct us_data *us,
@@ -340,8 +358,9 @@
 	// to the ATA spec, 'Sector Count' isn't used but the Windows driver
 	// sets this bit so we do too...
 	//
-	unsigned char command[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
-	unsigned char reply[512];
+	static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
+	unsigned char *command = us->iobuf;
+	unsigned char *reply;
 	int rc;
 
 	if (!us || !info)
@@ -353,11 +372,18 @@
 			return rc;
 	}
 
+	memcpy(command, scommand, 8);
+	reply = kmalloc(512, GFP_NOIO);
+	if (!reply)
+		return USB_STOR_TRANSPORT_ERROR;
+
 	command[5] += (info->lun << 4);
 
 	rc = datafab_bulk_write(us, command, 8);
-	if (rc != USB_STOR_XFER_GOOD) 
-		return USB_STOR_TRANSPORT_ERROR;
+	if (rc != USB_STOR_XFER_GOOD) {
+		rc = USB_STOR_TRANSPORT_ERROR;
+		goto leave;
+	}
 
 	// we'll go ahead and extract the media capacity while we're here...
 	//
@@ -369,10 +395,15 @@
 				((u32)(reply[116]) << 16) |
 				((u32)(reply[115]) <<  8) | 
 				((u32)(reply[114])      );
-		return USB_STOR_TRANSPORT_GOOD;
+		rc = USB_STOR_TRANSPORT_GOOD;
+		goto leave;
 	}
-		
-	return USB_STOR_TRANSPORT_ERROR;
+
+	rc = USB_STOR_TRANSPORT_ERROR;
+
+ leave:
+	kfree(reply);
+	return rc;
 }
 
 
@@ -571,8 +602,7 @@
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
-	// don't bother implementing READ_6 or WRITE_6.  Just set MODE_XLATE and
-	// let the usb storage code convert to READ_10/WRITE_10
+	// don't bother implementing READ_6 or WRITE_6.
 	//
 	if (srb->cmnd[0] == READ_10) {
 		block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	Fri Jul 11 01:25:30 2003
+++ b/drivers/usb/storage/freecom.c	Fri Jul 11 01:25:30 2003
@@ -44,11 +44,6 @@
 #define ERR_STAT		0x01
 #define DRQ_STAT		0x08
 
-struct freecom_udata {
-	u8    buffer[64];	/* Common command block. */
-};
-typedef struct freecom_udata *freecom_udata_t;
-
 /* All of the outgoing packets are 64 bytes long. */
 struct freecom_cb_wrap {
 	u8    Type;		/* Command type. */
@@ -112,9 +107,8 @@
 freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
 		unsigned int ipipe, unsigned int opipe, int count)
 {
-	freecom_udata_t extra = (freecom_udata_t) us->extra;
 	struct freecom_xfer_wrap *fxfr =
-		(struct freecom_xfer_wrap *) extra->buffer;
+		(struct freecom_xfer_wrap *) us->iobuf;
 	int result;
 
 	fxfr->Type = FCM_PACKET_INPUT | 0x00;
@@ -147,9 +141,8 @@
 freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
 		int unsigned ipipe, unsigned int opipe, int count)
 {
-	freecom_udata_t extra = (freecom_udata_t) us->extra;
 	struct freecom_xfer_wrap *fxfr =
-		(struct freecom_xfer_wrap *) extra->buffer;
+		(struct freecom_xfer_wrap *) us->iobuf;
 	int result;
 
 	fxfr->Type = FCM_PACKET_OUTPUT | 0x00;
@@ -190,12 +183,9 @@
 	int result;
 	unsigned int partial;
 	int length;
-	freecom_udata_t extra;
 
-	extra = (freecom_udata_t) us->extra;
-
-	fcb = (struct freecom_cb_wrap *) extra->buffer;
-	fst = (struct freecom_status *) extra->buffer;
+	fcb = (struct freecom_cb_wrap *) us->iobuf;
+	fst = (struct freecom_status *) us->iobuf;
 
 	US_DEBUGP("Freecom TRANSPORT STARTED\n");
 
@@ -386,18 +376,11 @@
 freecom_init (struct us_data *us)
 {
 	int result;
-	char buffer[33];
+	char *buffer = us->iobuf;
 
-	/* Allocate a buffer for us.  The upper usb transport code will
-	 * free this for us when cleaning up. */
-	if (us->extra == NULL) {
-		us->extra = kmalloc (sizeof (struct freecom_udata),
-				GFP_KERNEL);
-		if (us->extra == NULL) {
-			US_DEBUGP("Out of memory\n");
-			return USB_STOR_TRANSPORT_ERROR;
-		}
-	}
+	/* The DMA-mapped I/O buffer is 64 bytes long, just right for
+	 * all our packets.  No need to allocate any extra buffer space.
+	 */
 
 	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
 			0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
diff -Nru a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
--- a/drivers/usb/storage/initializers.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/usb/storage/initializers.c	Fri Jul 11 01:25:28 2003
@@ -47,38 +47,27 @@
  * mode */
 int usb_stor_euscsi_init(struct us_data *us)
 {
-	unsigned char data = 0x1;
 	int result;
 
 	US_DEBUGP("Attempting to init eUSCSI bridge...\n");
+	us->iobuf[0] = 0x1;
 	result = usb_stor_control_msg(us, us->send_ctrl_pipe,
 			0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
-			0x01, 0x0, &data, 0x1, 5*HZ);
+			0x01, 0x0, us->iobuf, 0x1, 5*HZ);
 	US_DEBUGP("-- result is %d\n", result);
-	US_DEBUGP("-- data afterwards is %d\n", data);
+	US_DEBUGP("-- data afterwards is %d\n", us->iobuf[0]);
 
 	return 0;
 }
 
 /* This function is required to activate all four slots on the UCR-61S2B
  * flash reader */
-
 int usb_stor_ucr61s2b_init(struct us_data *us)
 {
-	struct bulk_cb_wrap *bcb;
-	struct bulk_cs_wrap *bcs;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap*) us->iobuf;
+	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap*) us->iobuf;
 	int res, partial;
 
-	bcb = kmalloc(sizeof *bcb, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
-	if (!bcb) {
-		return(-1);
-	}
-	bcs = kmalloc(sizeof *bcs, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
-	if (!bcs) {
-		kfree(bcb);
-		return(-1);
-	}
-
 	US_DEBUGP("Sending UCR-61S2B initialization packet...\n");
 
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -91,19 +80,12 @@
 
 	res = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb,
 			US_BULK_CB_WRAP_LEN, &partial);
-	US_DEBUGP("-- result is %d\n", res);
-	kfree(bcb);
-
-	if(res) {
-		kfree(bcs);
-		return(res);
-	}
+	if(res)
+		return res;
 
+	US_DEBUGP("Getting status packet...\n");
 	res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
 			US_BULK_CS_WRAP_LEN, &partial);
-	US_DEBUGP("-- result of status read is %d\n", res);
-
-	kfree(bcs);
 
-	return(res ? -1 : 0);
+	return (res ? -1 : 0);
 }
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	Fri Jul 11 01:25:29 2003
+++ b/drivers/usb/storage/unusual_devs.h	Fri Jul 11 01:25:29 2003
@@ -90,12 +90,6 @@
  		US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
 #endif
 
-/* Made with the help of Edd Dumbill <edd@usefulinc.com> */
-UNUSUAL_DEV(  0x0451, 0x5409, 0x0001, 0x0001,
-		"Frontier Labs",
-		"Nex II Digital",
-		US_SC_SCSI, US_PR_BULK, NULL, 0),
-
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
 		"Kyocera",
@@ -276,7 +270,7 @@
 UNUSUAL_DEV(  0x054c, 0x0032, 0x0000, 0x9999,
 		"Sony",
 		"Memorystick MSC-U01N",
-		US_SC_UFI, US_PR_CB, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN ),
 		
 UNUSUAL_DEV(  0x054c, 0x0069, 0x0000, 0x9999,
@@ -301,7 +295,7 @@
 UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999, 
 		"Y-E Data",
 		"Flashbuster-U",
-		US_SC_UFI,  US_PR_CBI, NULL,
+		US_SC_DEVICE,  US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
 UNUSUAL_DEV(  0x059f, 0xa601, 0x0200, 0x0200, 
diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
--- a/drivers/usb/usb-skeleton.c	Fri Jul 11 01:25:28 2003
+++ b/drivers/usb/usb-skeleton.c	Fri Jul 11 01:25:28 2003
@@ -646,9 +646,6 @@
 	dev = usb_get_intfdata (interface);
 	usb_set_intfdata (interface, NULL);
 
-	if (!dev)
-		return;
-
 	down (&dev->sem);
 
 	/* disable open() */
diff -Nru a/fs/aio.c b/fs/aio.c
--- a/fs/aio.c	Fri Jul 11 01:25:28 2003
+++ b/fs/aio.c	Fri Jul 11 01:25:28 2003
@@ -679,12 +679,11 @@
 	/* after flagging the request as done, we
 	 * must never even look at it again
 	 */
-	barrier();
+	smp_wmb();	/* make event visible before updating tail */
 
 	info->tail = tail;
 	ring->tail = tail;
 
-	wmb();
 	put_aio_ring_event(event, KM_IRQ0);
 	kunmap_atomic(ring, KM_IRQ1);
 
@@ -721,7 +720,7 @@
 	dprintk("in aio_read_evt h%lu t%lu m%lu\n",
 		 (unsigned long)ring->head, (unsigned long)ring->tail,
 		 (unsigned long)ring->nr);
-	barrier();
+
 	if (ring->head == ring->tail)
 		goto out;
 
@@ -732,7 +731,7 @@
 		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
 		*ent = *evp;
 		head = (head + 1) % info->nr;
-		barrier();
+		smp_mb(); /* finish reading the event before updatng the head */
 		ring->head = head;
 		ret = 1;
 		put_aio_ring_event(evp, KM_USER1);
diff -Nru a/fs/attr.c b/fs/attr.c
--- a/fs/attr.c	Fri Jul 11 01:25:28 2003
+++ b/fs/attr.c	Fri Jul 11 01:25:28 2003
@@ -65,7 +65,7 @@
 	int error = 0;
 
 	if (ia_valid & ATTR_SIZE) {
-		if (attr->ia_size != inode->i_size) {
+		if (attr->ia_size != i_size_read(inode)) {
 			error = vmtruncate(inode, attr->ia_size);
 			if (error || (ia_valid == ATTR_SIZE))
 				goto out;
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c	Fri Jul 11 01:25:28 2003
+++ b/fs/binfmt_aout.c	Fri Jul 11 01:25:28 2003
@@ -269,7 +269,7 @@
 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
 	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
 	    N_TRSIZE(ex) || N_DRSIZE(ex) ||
-	    bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+	    i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
 		return -ENOEXEC;
 	}
 
@@ -454,7 +454,7 @@
 	/* We come in here for the regular a.out style of shared libraries */
 	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
 	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
-	    inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
+	    i_size_read(inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
 		goto out;
 	}
 
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Fri Jul 11 01:25:28 2003
+++ b/fs/binfmt_elf.c	Fri Jul 11 01:25:28 2003
@@ -114,7 +114,7 @@
 #define STACK_ADD(sp, items) ((elf_addr_t *)(sp) + (items))
 #define STACK_ROUND(sp, items) \
 	((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
-#define STACK_ALLOC(sp, len) ({ elf_addr_t *old_sp = sp; sp += len; old_sp; })
+#define STACK_ALLOC(sp, len) ({ elf_addr_t *old_sp = (elf_addr_t *)sp; sp += len; old_sp; })
 #else
 #define STACK_ADD(sp, items) ((elf_addr_t *)(sp) - (items))
 #define STACK_ROUND(sp, items) \
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Fri Jul 11 01:25:30 2003
+++ b/fs/block_dev.c	Fri Jul 11 01:25:30 2003
@@ -29,7 +29,7 @@
 static sector_t max_block(struct block_device *bdev)
 {
 	sector_t retval = ~((sector_t)0);
-	loff_t sz = bdev->bd_inode->i_size;
+	loff_t sz = i_size_read(bdev->bd_inode);
 
 	if (sz) {
 		unsigned int size = block_size(bdev);
@@ -161,7 +161,7 @@
 
 	bd_inode = file->f_dentry->d_inode->i_bdev->bd_inode;
 	down(&bd_inode->i_sem);
-	size = bd_inode->i_size;
+	size = i_size_read(bd_inode);
 
 	switch (origin) {
 		case 2:
@@ -487,7 +487,7 @@
 static void bd_set_size(struct block_device *bdev, loff_t size)
 {
 	unsigned bsize = bdev_hardsect_size(bdev);
-	bdev->bd_inode->i_size = size;
+	i_size_write(bdev->bd_inode, size);
 	while (bsize < PAGE_CACHE_SIZE) {
 		if (size & bsize)
 			break;
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Fri Jul 11 01:25:29 2003
+++ b/fs/buffer.c	Fri Jul 11 01:25:29 2003
@@ -1721,7 +1721,7 @@
 
 	BUG_ON(!PageLocked(page));
 
-	last_block = (inode->i_size - 1) >> inode->i_blkbits;
+	last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
 
 	if (!page_has_buffers(page)) {
 		if (!PageUptodate(page))
@@ -2057,7 +2057,7 @@
 	head = page_buffers(page);
 
 	iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-	lblock = (inode->i_size+blocksize-1) >> inode->i_blkbits;
+	lblock = (i_size_read(inode)+blocksize-1) >> inode->i_blkbits;
 	bh = head;
 	nr = 0;
 	i = 0;
@@ -2282,8 +2282,12 @@
 	struct inode *inode = page->mapping->host;
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 	__block_commit_write(inode,page,from,to);
+	/*
+	 * No need to use i_size_read() here, the i_size
+	 * cannot change under us because we hold i_sem.
+	 */
 	if (pos > inode->i_size) {
-		inode->i_size = pos;
+		i_size_write(inode, pos);
 		mark_inode_dirty(inode);
 	}
 	return 0;
@@ -2435,7 +2439,7 @@
 
 	set_page_dirty(page);
 	if (pos > inode->i_size) {
-		inode->i_size = pos;
+		i_size_write(inode, pos);
 		mark_inode_dirty(inode);
 	}
 	return 0;
@@ -2565,7 +2569,8 @@
 			struct writeback_control *wbc)
 {
 	struct inode * const inode = page->mapping->host;
-	const unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	loff_t i_size = i_size_read(inode);
+	const unsigned long end_index = i_size >> PAGE_CACHE_SHIFT;
 	unsigned offset;
 	void *kaddr;
 
@@ -2574,7 +2579,7 @@
 		return __block_write_full_page(inode, page, get_block, wbc);
 
 	/* Is the page fully outside i_size? (truncate in progress) */
-	offset = inode->i_size & (PAGE_CACHE_SIZE-1);
+	offset = i_size & (PAGE_CACHE_SIZE-1);
 	if (page->index >= end_index+1 || !offset) {
 		/*
 		 * The page may have dirty, unmapped buffers.  For example,
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	Fri Jul 11 01:25:28 2003
+++ b/fs/dcache.c	Fri Jul 11 01:25:28 2003
@@ -1451,19 +1451,24 @@
 int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry)
 {
 	int result;
+	unsigned long seq;
 
 	result = 0;
-	for (;;) {
-		if (new_dentry != old_dentry) {
-			struct dentry * parent = new_dentry->d_parent;
-			if (parent == new_dentry)
-				break;
-			new_dentry = parent;
-			continue;
+        do {
+		seq = read_seqbegin(&rename_lock);
+		for (;;) {
+			if (new_dentry != old_dentry) {
+				struct dentry * parent = new_dentry->d_parent;
+				if (parent == new_dentry)
+					break;
+				new_dentry = parent;
+				continue;
+			}
+			result = 1;
+			break;
 		}
-		result = 1;
-		break;
-	}
+	} while (read_seqretry(&rename_lock, seq));
+
 	return result;
 }
 
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Fri Jul 11 01:25:28 2003
+++ b/fs/devfs/base.c	Fri Jul 11 01:25:28 2003
@@ -2208,8 +2208,46 @@
 {
     devfs_handle_t de;
     wait_queue_head_t wait_queue;
+    atomic_t count;
 };
 
+static struct devfs_lookup_struct *
+new_devfs_lookup_struct(void)
+{
+	struct devfs_lookup_struct *p = kmalloc(sizeof(*p), GFP_KERNEL);
+
+	if (!p)
+		return NULL;
+
+	init_waitqueue_head (&p->wait_queue);
+	atomic_set(&p->count, 1);
+	return p;
+}
+
+static void
+get_devfs_lookup_struct(struct devfs_lookup_struct *info)
+{
+	if (info)
+		atomic_inc(&info->count);
+	else {
+		printk(KERN_ERR "null devfs_lookup_struct pointer\n");
+		dump_stack();
+	}
+}
+
+static void
+put_devfs_lookup_struct(struct devfs_lookup_struct *info)
+{
+	if (info) {
+		if (!atomic_dec_and_test(&info->count))
+			return;
+		kfree(info);
+	} else {
+		printk(KERN_ERR "null devfs_lookup_struct pointer\n");
+		dump_stack();
+	}
+}
+
 /* XXX: this doesn't handle the case where we got a negative dentry
         but a devfs entry has been registered in the meanwhile */
 static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *nd)
@@ -2252,11 +2290,13 @@
     read_lock (&parent->u.dir.lock);
     if (dentry->d_fsdata)
     {
+	get_devfs_lookup_struct(lookup_info);
 	set_current_state (TASK_UNINTERRUPTIBLE);
 	add_wait_queue (&lookup_info->wait_queue, &wait);
 	read_unlock (&parent->u.dir.lock);
 	schedule ();
 	remove_wait_queue (&lookup_info->wait_queue, &wait);
+	put_devfs_lookup_struct(lookup_info);
     }
     else read_unlock (&parent->u.dir.lock);
     return 1;
@@ -2268,7 +2308,7 @@
 static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
     struct devfs_entry tmp;  /*  Must stay in scope until devfsd idle again  */
-    struct devfs_lookup_struct lookup_info;
+    struct devfs_lookup_struct *lookup_info;
     struct fs_info *fs_info = dir->i_sb->s_fs_info;
     struct devfs_entry *parent, *de;
     struct inode *inode;
@@ -2285,9 +2325,10 @@
     read_lock (&parent->u.dir.lock);
     de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len);
     read_unlock (&parent->u.dir.lock);
-    lookup_info.de = de;
-    init_waitqueue_head (&lookup_info.wait_queue);
-    dentry->d_fsdata = &lookup_info;
+    lookup_info = new_devfs_lookup_struct();
+    if (!lookup_info) return ERR_PTR(-ENOMEM);
+    lookup_info->de = de;
+    dentry->d_fsdata = lookup_info;
     if (de == NULL)
     {   /*  Try with devfsd. For any kind of failure, leave a negative dentry
 	    so someone else can deal with it (in the case where the sysadmin
@@ -2297,6 +2338,7 @@
 	if (try_modload (parent, fs_info,
 			 dentry->d_name.name, dentry->d_name.len, &tmp) < 0)
 	{   /*  Lookup event was not queued to devfsd  */
+	    put_devfs_lookup_struct(lookup_info);
 	    d_add (dentry, NULL);
 	    return NULL;
 	}
@@ -2308,8 +2350,7 @@
 	revalidation  */
     up (&dir->i_sem);
     wait_for_devfsd_finished (fs_info);  /*  If I'm not devfsd, must wait  */
-    down (&dir->i_sem);      /*  Grab it again because them's the rules  */
-    de = lookup_info.de;
+    de = lookup_info->de;
     /*  If someone else has been so kind as to make the inode, we go home
 	early  */
     if (dentry->d_inode) goto out;
@@ -2333,11 +2374,13 @@
 	     de->name, de->inode.ino, inode, de, current->comm);
     d_instantiate (dentry, inode);
 out:
+    write_lock (&parent->u.dir.lock);
     dentry->d_op = &devfs_dops;
     dentry->d_fsdata = NULL;
-    write_lock (&parent->u.dir.lock);
-    wake_up (&lookup_info.wait_queue);
+    wake_up (&lookup_info->wait_queue);
+    put_devfs_lookup_struct(lookup_info);
     write_unlock (&parent->u.dir.lock);
+    down (&dir->i_sem);      /*  Grab it again because them's the rules  */
     devfs_put (de);
     return retval;
 }   /*  End Function devfs_lookup  */
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	Fri Jul 11 01:25:29 2003
+++ b/fs/direct-io.c	Fri Jul 11 01:25:29 2003
@@ -757,7 +757,7 @@
 				char *kaddr;
 
 				if (dio->block_in_file >=
-						dio->inode->i_size>>blkbits) {
+					i_size_read(dio->inode)>>blkbits) {
 					/* We hit eof */
 					page_cache_release(page);
 					goto out;
@@ -943,13 +943,15 @@
 		if (ret == 0)
 			ret = dio->page_errors;
 		if (ret == 0 && dio->result) {
+			loff_t i_size = i_size_read(inode);
+
 			ret = dio->result;
 			/*
 			 * Adjust the return value if the read crossed a
 			 * non-block-aligned EOF.
 			 */
-			if (rw == READ && (offset + ret > inode->i_size))
-				ret = inode->i_size - offset;
+			if (rw == READ && (offset + ret > i_size))
+				ret = i_size - offset;
 		}
 		kfree(dio);
 	}
diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c	Fri Jul 11 01:25:28 2003
+++ b/fs/eventpoll.c	Fri Jul 11 01:25:28 2003
@@ -245,6 +245,9 @@
 	/* The "container" of this item */
 	struct eventpoll *ep;
 
+	/* The file descriptor this item refers to */
+	int fd;
+
 	/* The file this item refers to */
 	struct file *file;
 
@@ -285,15 +288,17 @@
 static int ep_alloc_pages(char **pages, int numpages);
 static int ep_free_pages(char **pages, int numpages);
 static int ep_file_init(struct file *file, unsigned int hashbits);
-static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file);
+static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, int fd);
 static struct list_head *ep_hash_entry(struct eventpoll *ep, unsigned int index);
 static int ep_init(struct eventpoll *ep, unsigned int hashbits);
 static void ep_free(struct eventpoll *ep);
-static struct epitem *ep_find(struct eventpoll *ep, struct file *file);
+static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
 static void ep_use_epitem(struct epitem *epi);
 static void ep_release_epitem(struct epitem *epi);
-static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt);
-static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile);
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
+				 poll_table *pt);
+static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
+		     struct file *tfile, int fd);
 static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_event *event);
 static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi);
 static int ep_unlink(struct eventpoll *ep, struct epitem *epi);
@@ -580,7 +585,7 @@
 	down_write(&ep->sem);
 
 	/* Try to lookup the file inside our hash table */
-	epi = ep_find(ep, tfile);
+	epi = ep_find(ep, tfile, fd);
 
 	error = -EINVAL;
 	switch (op) {
@@ -588,7 +593,7 @@
 		if (!epi) {
 			epds.events |= POLLERR | POLLHUP;
 
-			error = ep_insert(ep, &epds, tfile);
+			error = ep_insert(ep, &epds, tfile, fd);
 		} else
 			error = -EEXIST;
 		break;
@@ -814,10 +819,11 @@
 /*
  * Calculate the index of the hash relative to "file".
  */
-static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file)
+static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, int fd)
 {
+	unsigned long ptr = (unsigned long) file ^ (fd << ep->hashbits);
 
-	return (unsigned int) hash_ptr(file, ep->hashbits);
+	return (unsigned int) hash_ptr((void *) ptr, ep->hashbits);
 }
 
 
@@ -920,7 +926,7 @@
  * the returned item, so the caller must call ep_release_epitem()
  * after finished using the "struct epitem".
  */
-static struct epitem *ep_find(struct eventpoll *ep, struct file *file)
+static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
 {
 	unsigned long flags;
 	struct list_head *lsthead, *lnk;
@@ -928,11 +934,11 @@
 
 	read_lock_irqsave(&ep->lock, flags);
 
-	lsthead = ep_hash_entry(ep, ep_hash_index(ep, file));
+	lsthead = ep_hash_entry(ep, ep_hash_index(ep, file, fd));
 	list_for_each(lnk, lsthead) {
 		epi = list_entry(lnk, struct epitem, llink);
 
-		if (epi->file == file) {
+		if (epi->file == file && epi->fd == fd) {
 			ep_use_epitem(epi);
 			break;
 		}
@@ -976,7 +982,8 @@
  * This is the callback that is used to add our wait queue to the
  * target file wakeup lists.
  */
-static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt)
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
+				 poll_table *pt)
 {
 	struct epitem *epi = EP_ITEM_FROM_EPQUEUE(pt);
 	struct eppoll_entry *pwq;
@@ -995,7 +1002,8 @@
 }
 
 
-static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile)
+static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
+		     struct file *tfile, int fd)
 {
 	int error, revents, pwake = 0;
 	unsigned long flags;
@@ -1014,6 +1022,7 @@
 	INIT_LIST_HEAD(&epi->pwqlist);
 	epi->ep = ep;
 	epi->file = tfile;
+	epi->fd = fd;
 	epi->event = *event;
 	atomic_set(&epi->usecnt, 1);
 	epi->nwait = 0;
@@ -1046,7 +1055,7 @@
 	write_lock_irqsave(&ep->lock, flags);
 
 	/* Add the current item to the hash table */
-	list_add(&epi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile)));
+	list_add(&epi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile, fd)));
 
 	/* If the file is already "ready" we drop it inside the ready list */
 	if ((revents & event->events) && !EP_IS_LINKED(&epi->rdllink)) {
@@ -1065,8 +1074,8 @@
 	if (pwake)
 		ep_poll_safewake(&psw, &ep->poll_wait);
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %p)\n",
-		     current, ep, tfile));
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %p, %d)\n",
+		     current, ep, tfile, fd));
 
 	return 0;
 
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Fri Jul 11 01:25:28 2003
+++ b/fs/exec.c	Fri Jul 11 01:25:28 2003
@@ -923,12 +923,12 @@
 			if (offset != PAGE_SIZE)
 				continue;
 			offset = 0;
-			kunmap(page);
+			kunmap_atomic(kaddr, KM_USER0);
 inside:
 			page = bprm->page[bprm->p/PAGE_SIZE];
-			kaddr = kmap(page);
+			kaddr = kmap_atomic(page, KM_USER0);
 		}
-		kunmap(page);
+		kunmap_atomic(kaddr, KM_USER0);
 		bprm->argc--;
 	}
 }
diff -Nru a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
--- a/fs/ext2/ialloc.c	Fri Jul 11 01:25:29 2003
+++ b/fs/ext2/ialloc.c	Fri Jul 11 01:25:29 2003
@@ -235,10 +235,7 @@
 				EXT2_INODE_SIZE(inode->i_sb);
 	block = le32_to_cpu(gdp->bg_inode_table) +
 				(offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
-	bh = sb_getblk(inode->i_sb, block);
-	if (!buffer_uptodate(bh) && !buffer_locked(bh))
-		ll_rw_block(READA, 1, &bh);
-	__brelse(bh);
+	sb_breadahead(inode->i_sb, block);
 }
 
 /*
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Fri Jul 11 01:25:29 2003
+++ b/fs/ext3/inode.c	Fri Jul 11 01:25:29 2003
@@ -1200,7 +1200,7 @@
 	if (!partial)
 		SetPageUptodate(page);
 	if (pos > inode->i_size)
-		inode->i_size = pos;
+		i_size_write(inode, pos);
 	EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
 	if (inode->i_size > EXT3_I(inode)->i_disksize) {
 		EXT3_I(inode)->i_disksize = inode->i_size;
@@ -1574,7 +1574,7 @@
 			loff_t end = offset + ret;
 			if (end > inode->i_size) {
 				ei->i_disksize = end;
-				inode->i_size = end;
+				i_size_write(inode, end);
 				err = ext3_mark_inode_dirty(handle, inode);
 				if (!ret) 
 					ret = err;
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	Fri Jul 11 01:25:30 2003
+++ b/fs/inode.c	Fri Jul 11 01:25:30 2003
@@ -189,6 +189,7 @@
 	INIT_LIST_HEAD(&inode->i_data.i_mmap);
 	INIT_LIST_HEAD(&inode->i_data.i_mmap_shared);
 	spin_lock_init(&inode->i_lock);
+	i_size_ordered_init(inode);
 }
 
 static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
diff -Nru a/fs/ioctl.c b/fs/ioctl.c
--- a/fs/ioctl.c	Fri Jul 11 01:25:28 2003
+++ b/fs/ioctl.c	Fri Jul 11 01:25:28 2003
@@ -40,7 +40,7 @@
 				return -EBADF;
 			return put_user(inode->i_sb->s_blocksize, (int *) arg);
 		case FIONREAD:
-			return put_user(inode->i_size - filp->f_pos, (int *) arg);
+			return put_user(i_size_read(inode) - filp->f_pos, (int *) arg);
 	}
 	if (filp->f_op && filp->f_op->ioctl)
 		return filp->f_op->ioctl(inode, filp, cmd, arg);
diff -Nru a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
--- a/fs/jbd/checkpoint.c	Fri Jul 11 01:25:28 2003
+++ b/fs/jbd/checkpoint.c	Fri Jul 11 01:25:28 2003
@@ -75,11 +75,12 @@
  * Called under j-state_lock *only*.  It will be unlocked if we have to wait
  * for a checkpoint to free up some space in the log.
  */
-
-void __log_wait_for_space(journal_t *journal, int nblocks)
+void __log_wait_for_space(journal_t *journal)
 {
+	int nblocks;
 	assert_spin_locked(&journal->j_state_lock);
 
+	nblocks = jbd_space_needed(journal);
 	while (__log_space_left(journal) < nblocks) {
 		if (journal->j_flags & JFS_ABORT)
 			return;
@@ -91,9 +92,10 @@
 		 * were waiting for the checkpoint lock
 		 */
 		spin_lock(&journal->j_state_lock);
+		nblocks = jbd_space_needed(journal);
 		if (__log_space_left(journal) < nblocks) {
 			spin_unlock(&journal->j_state_lock);
-			log_do_checkpoint(journal, nblocks);
+			log_do_checkpoint(journal);
 			spin_lock(&journal->j_state_lock);
 		}
 		up(&journal->j_checkpoint_sem);
@@ -279,9 +281,7 @@
  *
  * The journal should be locked before calling this function.
  */
-
-/* @@@ `nblocks' is unused.  Should it be used? */
-int log_do_checkpoint(journal_t *journal, int nblocks)
+int log_do_checkpoint(journal_t *journal)
 {
 	int result;
 	int batch_count = 0;
@@ -315,7 +315,7 @@
 		int cleanup_ret, retry = 0;
 		tid_t this_tid;
 
-		transaction = journal->j_checkpoint_transactions->t_cpnext;
+		transaction = journal->j_checkpoint_transactions;
 		this_tid = transaction->t_tid;
 		jh = transaction->t_checkpoint_list;
 		last_jh = jh->b_cpprev;
@@ -332,27 +332,19 @@
 				retry = 1;
 				break;
 			}
-			retry = __flush_buffer(journal, jh, bhs, &batch_count,
-						&drop_count);
+			retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count);
 		} while (jh != last_jh && !retry);
-		if (batch_count) {
+
+		if (batch_count)
 			__flush_batch(journal, bhs, &batch_count);
-			continue;
-		}
-		if (retry)
-			continue;
 
 		/*
-		 * If someone emptied the checkpoint list while we slept, we're
-		 * done.
-		 */
-		if (!journal->j_checkpoint_transactions)
-			break;
-		/*
 		 * If someone cleaned up this transaction while we slept, we're
 		 * done
 		 */
-		if (journal->j_checkpoint_transactions->t_cpnext != transaction)
+		if (journal->j_checkpoint_transactions != transaction)
+			break;
+		if (retry)
 			continue;
 		/*
 		 * Maybe it's a new transaction, but it fell at the same
@@ -367,6 +359,8 @@
 		 */
 		cleanup_ret = __cleanup_transaction(journal, transaction);
 		J_ASSERT(drop_count != 0 || cleanup_ret != 0);
+		if (journal->j_checkpoint_transactions != transaction)
+			break;
 	}
 	spin_unlock(&journal->j_list_lock);
 	result = cleanup_journal_tail(journal);
diff -Nru a/fs/jbd/commit.c b/fs/jbd/commit.c
--- a/fs/jbd/commit.c	Fri Jul 11 01:25:29 2003
+++ b/fs/jbd/commit.c	Fri Jul 11 01:25:29 2003
@@ -169,23 +169,10 @@
 	 * that multiple journal_get_write_access() calls to the same
 	 * buffer are perfectly permissable.
 	 */
-	{
-		int nr = 0;
-		while (commit_transaction->t_reserved_list) {
-			jh = commit_transaction->t_reserved_list;
-			JBUFFER_TRACE(jh, "reserved, unused: refile");
-			journal_refile_buffer(journal, jh);
-			nr++;
-		}
-		if (nr) {
-			static int noisy;
-
-			if (noisy < 10) {
-				noisy++;
-				printk("%s: freed %d reserved buffers\n",
-					__FUNCTION__, nr);
-			}
-		}
+	while (commit_transaction->t_reserved_list) {
+		jh = commit_transaction->t_reserved_list;
+		JBUFFER_TRACE(jh, "reserved, unused: refile");
+		journal_refile_buffer(journal, jh);
 	}
 
 	/*
@@ -413,6 +400,13 @@
 			__journal_abort_hard(journal);
 			continue;
 		}
+
+		/*
+		 * start_this_handle() uses t_outstanding_credits to determine
+		 * the free space in the log, but this counter is changed
+		 * by journal_next_log_block() also.
+		 */
+		commit_transaction->t_outstanding_credits--;
 
 		/* Bump b_count to prevent truncate from stumbling over
                    the shadowed buffer!  @@@ This can go if we ever get
diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c
--- a/fs/jbd/journal.c	Fri Jul 11 01:25:28 2003
+++ b/fs/jbd/journal.c	Fri Jul 11 01:25:28 2003
@@ -484,6 +484,13 @@
 		ret = __log_start_commit(journal, tid);
 		if (ret && ptid)
 			*ptid = tid;
+	} else if (journal->j_committing_transaction && ptid) {
+		/*
+		 * If ext3_write_super() recently started a commit, then we
+		 * have to wait for completion of that transaction
+		 */
+		*ptid = journal->j_committing_transaction->t_tid;
+		ret = 1;
 	}
 	spin_unlock(&journal->j_state_lock);
 	return ret;
@@ -1076,7 +1083,7 @@
 	spin_lock(&journal->j_list_lock);
 	while (journal->j_checkpoint_transactions != NULL) {
 		spin_unlock(&journal->j_list_lock);
-		log_do_checkpoint(journal, 1);
+		log_do_checkpoint(journal);
 		spin_lock(&journal->j_list_lock);
 	}
 
@@ -1284,7 +1291,7 @@
 	spin_lock(&journal->j_list_lock);
 	while (!err && journal->j_checkpoint_transactions != NULL) {
 		spin_unlock(&journal->j_list_lock);
-		err = log_do_checkpoint(journal, journal->j_maxlen);
+		err = log_do_checkpoint(journal);
 		spin_lock(&journal->j_list_lock);
 	}
 	spin_unlock(&journal->j_list_lock);
diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c
--- a/fs/jbd/transaction.c	Fri Jul 11 01:25:28 2003
+++ b/fs/jbd/transaction.c	Fri Jul 11 01:25:28 2003
@@ -206,15 +206,10 @@
 	 * Also, this test is inconsitent with the matching one in
 	 * journal_extend().
 	 */
-	needed = journal->j_max_transaction_buffers;
-	if (journal->j_committing_transaction) 
-		needed += journal->j_committing_transaction->
-					t_outstanding_credits;
-
-	if (__log_space_left(journal) < needed) {
+	if (__log_space_left(journal) < jbd_space_needed(journal)) {
 		jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
 		spin_unlock(&transaction->t_handle_lock);
-		__log_wait_for_space(journal, needed);
+		__log_wait_for_space(journal);
 		goto repeat_locked;
 	}
 
diff -Nru a/fs/libfs.c b/fs/libfs.c
--- a/fs/libfs.c	Fri Jul 11 01:25:28 2003
+++ b/fs/libfs.c	Fri Jul 11 01:25:28 2003
@@ -328,8 +328,12 @@
 	struct inode *inode = page->mapping->host;
 	loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
+	/*
+	 * No need to use i_size_read() here, the i_size
+	 * cannot change under us because we hold the i_sem.
+	 */
 	if (pos > inode->i_size)
-		inode->i_size = pos;
+		i_size_write(inode, pos);
 	set_page_dirty(page);
 	return 0;
 }
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Fri Jul 11 01:25:30 2003
+++ b/fs/locks.c	Fri Jul 11 01:25:30 2003
@@ -285,7 +285,7 @@
 		start = filp->f_pos;
 		break;
 	case 2: /*SEEK_END*/
-		start = filp->f_dentry->d_inode->i_size;
+		start = i_size_read(filp->f_dentry->d_inode);
 		break;
 	default:
 		return -EINVAL;
@@ -335,7 +335,7 @@
 		start = filp->f_pos;
 		break;
 	case 2: /*SEEK_END*/
-		start = filp->f_dentry->d_inode->i_size;
+		start = i_size_read(filp->f_dentry->d_inode);
 		break;
 	default:
 		return -EINVAL;
diff -Nru a/fs/mpage.c b/fs/mpage.c
--- a/fs/mpage.c	Fri Jul 11 01:25:28 2003
+++ b/fs/mpage.c	Fri Jul 11 01:25:28 2003
@@ -227,7 +227,7 @@
 		goto confused;
 
 	block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits);
-	last_block = (inode->i_size + blocksize - 1) >> blkbits;
+	last_block = (i_size_read(inode) + blocksize - 1) >> blkbits;
 
 	bh.b_page = page;
 	for (page_block = 0; page_block < blocks_per_page;
@@ -459,7 +459,7 @@
 	 */
 	BUG_ON(!PageUptodate(page));
 	block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits);
-	last_block = (inode->i_size - 1) >> blkbits;
+	last_block = (i_size_read(inode) - 1) >> blkbits;
 	map_bh.b_page = page;
 	for (page_block = 0; page_block < blocks_per_page; ) {
 
@@ -489,9 +489,9 @@
 
 	first_unmapped = page_block;
 
-	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
 	if (page->index >= end_index) {
-		unsigned offset = inode->i_size & (PAGE_CACHE_SIZE - 1);
+		unsigned offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1);
 		char *kaddr;
 
 		if (page->index > end_index || !offset)
@@ -614,7 +614,6 @@
 	sector_t last_block_in_bio = 0;
 	int ret = 0;
 	int done = 0;
-	struct pagevec pvec;
 	int (*writepage)(struct page *page, struct writeback_control *wbc);
 
 	if (wbc->nonblocking && bdi_write_congested(bdi)) {
@@ -626,7 +625,6 @@
 	if (get_block == NULL)
 		writepage = mapping->a_ops->writepage;
 
-	pagevec_init(&pvec, 0);
 	spin_lock(&mapping->page_lock);
 	while (!list_empty(&mapping->io_pages) && !done) {
 		struct page *page = list_entry(mapping->io_pages.prev,
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	Fri Jul 11 01:25:28 2003
+++ b/fs/namei.c	Fri Jul 11 01:25:28 2003
@@ -434,19 +434,17 @@
 	return 1;
 }
 
+/* no need for dcache_lock, as serialization is taken care in
+ * namespace.c
+ */
 static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
 {
 	int res = 0;
 	while (d_mountpoint(*dentry)) {
-		struct vfsmount *mounted;
-		spin_lock(&dcache_lock);
-		mounted = lookup_mnt(*mnt, *dentry);
-		if (!mounted) {
-			spin_unlock(&dcache_lock);
+		struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
+		if (!mounted)
 			break;
-		}
-		*mnt = mntget(mounted);
-		spin_unlock(&dcache_lock);
+		*mnt = mounted;
 		dput(*dentry);
 		mntput(mounted->mnt_parent);
 		*dentry = dget(mounted->mnt_root);
@@ -455,21 +453,21 @@
 	return res;
 }
 
+/* no need for dcache_lock, as serialization is taken care in
+ * namespace.c
+ */
 static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
 {
 	struct vfsmount *mounted;
 
-	spin_lock(&dcache_lock);
 	mounted = lookup_mnt(*mnt, *dentry);
 	if (mounted) {
-		*mnt = mntget(mounted);
-		spin_unlock(&dcache_lock);
+		*mnt = mounted;
 		dput(*dentry);
 		mntput(mounted->mnt_parent);
 		*dentry = dget(mounted->mnt_root);
 		return 1;
 	}
-	spin_unlock(&dcache_lock);
 	return 0;
 }
 
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	Fri Jul 11 01:25:29 2003
+++ b/fs/namespace.c	Fri Jul 11 01:25:29 2003
@@ -26,6 +26,8 @@
 extern int __init init_rootfs(void);
 extern int __init sysfs_init(void);
 
+/* spinlock for vfsmount related operations, inplace of dcache_lock */
+spinlock_t vfsmount_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 static struct list_head *mount_hashtable;
 static int hash_mask, hash_bits;
 static kmem_cache_t *mnt_cache; 
@@ -66,30 +68,38 @@
 	kmem_cache_free(mnt_cache, mnt);
 }
 
+/*
+ * Now, lookup_mnt increments the ref count before returning
+ * the vfsmount struct.
+ */
 struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry)
 {
 	struct list_head * head = mount_hashtable + hash(mnt, dentry);
 	struct list_head * tmp = head;
-	struct vfsmount *p;
+	struct vfsmount *p, *found = NULL;
 
+	spin_lock(&vfsmount_lock);
 	for (;;) {
 		tmp = tmp->next;
 		p = NULL;
 		if (tmp == head)
 			break;
 		p = list_entry(tmp, struct vfsmount, mnt_hash);
-		if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry)
+		if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) {
+			found = mntget(p);
 			break;
+		}
 	}
-	return p;
+	spin_unlock(&vfsmount_lock);
+	return found;
 }
 
 static int check_mnt(struct vfsmount *mnt)
 {
-	spin_lock(&dcache_lock);
+	spin_lock(&vfsmount_lock);
 	while (mnt->mnt_parent != mnt)
 		mnt = mnt->mnt_parent;
-	spin_unlock(&dcache_lock);
+	spin_unlock(&vfsmount_lock);
 	return mnt == current->namespace->root;
 }
 
@@ -263,15 +273,15 @@
 		mnt = list_entry(kill.next, struct vfsmount, mnt_list);
 		list_del_init(&mnt->mnt_list);
 		if (mnt->mnt_parent == mnt) {
-			spin_unlock(&dcache_lock);
+			spin_unlock(&vfsmount_lock);
 		} else {
 			struct nameidata old_nd;
 			detach_mnt(mnt, &old_nd);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&vfsmount_lock);
 			path_release(&old_nd);
 		}
 		mntput(mnt);
-		spin_lock(&dcache_lock);
+		spin_lock(&vfsmount_lock);
 	}
 }
 
@@ -324,17 +334,17 @@
 	}
 
 	down_write(&current->namespace->sem);
-	spin_lock(&dcache_lock);
+	spin_lock(&vfsmount_lock);
 
 	if (atomic_read(&sb->s_active) == 1) {
 		/* last instance - try to be smart */
-		spin_unlock(&dcache_lock);
+		spin_unlock(&vfsmount_lock);
 		lock_kernel();
 		DQUOT_OFF(sb);
 		acct_auto_close(sb);
 		unlock_kernel();
 		security_sb_umount_close(mnt);
-		spin_lock(&dcache_lock);
+		spin_lock(&vfsmount_lock);
 	}
 	retval = -EBUSY;
 	if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) {
@@ -342,7 +352,7 @@
 			umount_tree(mnt);
 		retval = 0;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&vfsmount_lock);
 	if (retval)
 		security_sb_umount_busy(mnt);
 	up_write(&current->namespace->sem);
@@ -449,18 +459,18 @@
 			q = clone_mnt(p, p->mnt_root);
 			if (!q)
 				goto Enomem;
-			spin_lock(&dcache_lock);
+			spin_lock(&vfsmount_lock);
 			list_add_tail(&q->mnt_list, &res->mnt_list);
 			attach_mnt(q, &nd);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&vfsmount_lock);
 		}
 	}
 	return res;
  Enomem:
 	if (res) {
-		spin_lock(&dcache_lock);
+		spin_lock(&vfsmount_lock);
 		umount_tree(res);
-		spin_unlock(&dcache_lock);
+		spin_unlock(&vfsmount_lock);
 	}
 	return NULL;
 }
@@ -485,7 +495,7 @@
 		goto out_unlock;
 
 	err = -ENOENT;
-	spin_lock(&dcache_lock);
+	spin_lock(&vfsmount_lock);
 	if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) {
 		struct list_head head;
 
@@ -495,7 +505,7 @@
 		mntget(mnt);
 		err = 0;
 	}
-	spin_unlock(&dcache_lock);
+	spin_unlock(&vfsmount_lock);
 out_unlock:
 	up(&nd->dentry->d_inode->i_sem);
 	if (!err)
@@ -532,9 +542,9 @@
 	if (mnt) {
 		err = graft_tree(mnt, nd);
 		if (err) {
-			spin_lock(&dcache_lock);
+			spin_lock(&vfsmount_lock);
 			umount_tree(mnt);
-			spin_unlock(&dcache_lock);
+			spin_unlock(&vfsmount_lock);
 		} else
 			mntput(mnt);
 	}
@@ -599,7 +609,7 @@
 	if (IS_DEADDIR(nd->dentry->d_inode))
 		goto out1;
 
-	spin_lock(&dcache_lock);
+	spin_lock(&vfsmount_lock);
 	if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry))
 		goto out2;
 
@@ -623,7 +633,7 @@
 	detach_mnt(old_nd.mnt, &parent_nd);
 	attach_mnt(old_nd.mnt, nd);
 out2:
-	spin_unlock(&dcache_lock);
+	spin_unlock(&vfsmount_lock);
 out1:
 	up(&nd->dentry->d_inode->i_sem);
 out:
@@ -804,9 +814,9 @@
 	down_write(&tsk->namespace->sem);
 	/* First pass: copy the tree topology */
 	new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root);
-	spin_lock(&dcache_lock);
+	spin_lock(&vfsmount_lock);
 	list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&vfsmount_lock);
 
 	/* Second pass: switch the tsk->fs->* elements */
 	if (fs) {
@@ -1027,7 +1037,7 @@
 	if (new_nd.mnt->mnt_root != new_nd.dentry)
 		goto out2; /* not a mountpoint */
 	tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */
-	spin_lock(&dcache_lock);
+	spin_lock(&vfsmount_lock);
 	if (tmp != new_nd.mnt) {
 		for (;;) {
 			if (tmp->mnt_parent == tmp)
@@ -1044,7 +1054,7 @@
 	detach_mnt(user_nd.mnt, &root_parent);
 	attach_mnt(user_nd.mnt, &old_nd);
 	attach_mnt(new_nd.mnt, &root_parent);
-	spin_unlock(&dcache_lock);
+	spin_unlock(&vfsmount_lock);
 	chroot_fs_refs(&user_nd, &new_nd);
 	security_sb_post_pivotroot(&user_nd, &new_nd);
 	error = 0;
@@ -1061,7 +1071,7 @@
 	unlock_kernel();
 	return error;
 out3:
-	spin_unlock(&dcache_lock);
+	spin_unlock(&vfsmount_lock);
 	goto out2;
 }
 
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	Fri Jul 11 01:25:29 2003
+++ b/fs/nfs/inode.c	Fri Jul 11 01:25:29 2003
@@ -1001,6 +1001,7 @@
 	loff_t		new_isize;
 	int		invalid = 0;
 	int		mtime_update = 0;
+	loff_t		cur_isize;
 
 	dfprintk(VFS, "NFS: refresh_inode(%s/%ld ct=%d info=0x%x)\n",
 			inode->i_sb->s_id, inode->i_ino,
@@ -1087,8 +1088,9 @@
 	 * If we have pending writebacks, things can get
 	 * messy.
 	 */
-	if (nfs_have_writebacks(inode) && new_isize < inode->i_size)
-		new_isize = inode->i_size;
+	cur_isize = i_size_read(inode);
+	if (nfs_have_writebacks(inode) && new_isize < cur_isize)
+		new_isize = cur_isize;
 
 	nfsi->read_cache_ctime = fattr->ctime;
 	inode->i_ctime = fattr->ctime;
@@ -1102,7 +1104,7 @@
 	}
 
 	nfsi->read_cache_isize = new_size;
-	inode->i_size = new_isize;
+	i_size_write(inode, new_isize);
 
 	if (inode->i_mode != fattr->mode ||
 	    inode->i_uid != fattr->uid ||
diff -Nru a/fs/nfs/write.c b/fs/nfs/write.c
--- a/fs/nfs/write.c	Fri Jul 11 01:25:29 2003
+++ b/fs/nfs/write.c	Fri Jul 11 01:25:29 2003
@@ -180,8 +180,8 @@
 		 * If we've extended the file, update the inode
 		 * now so we don't invalidate the cache.
 		 */
-		if (base > inode->i_size)
-			inode->i_size = base;
+		if (base > i_size_read(inode))
+			i_size_write(inode, base);
 	} while (count);
 
 	if (PageError(page))
@@ -211,8 +211,8 @@
 	nfs_unlock_request(req);
 	nfs_strategy(inode);
 	end = ((loff_t)page->index<<PAGE_CACHE_SHIFT) + (loff_t)(offset + count);
-	if (inode->i_size < end)
-		inode->i_size = end;
+	if (i_size_read(inode) < end)
+		i_size_write(inode, end);
 
  out:
 	return status;
@@ -227,9 +227,10 @@
 	struct inode *inode = page->mapping->host;
 	unsigned long end_index;
 	unsigned offset = PAGE_CACHE_SIZE;
+	loff_t i_size = i_size_read(inode);
 	int err;
 
-	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+	end_index = i_size >> PAGE_CACHE_SHIFT;
 
 	/* Ensure we've flushed out any previous writes */
 	nfs_wb_page(inode,page);
@@ -238,7 +239,7 @@
 	if (page->index < end_index)
 		goto do_it;
 	/* things got complicated... */
-	offset = inode->i_size & (PAGE_CACHE_SIZE-1);
+	offset = i_size & (PAGE_CACHE_SIZE-1);
 
 	/* OK, are we completely out? */
 	err = -EIO;
@@ -701,8 +702,8 @@
 
 	status = 0;
 	end = ((loff_t)page->index<<PAGE_CACHE_SHIFT) + (loff_t)(offset + count);
-	if (inode->i_size < end)
-		inode->i_size = end;
+	if (i_size_read(inode) < end)
+		i_size_write(inode, end);
 
 	/* If we wrote past the end of the page.
 	 * Call the strategy routine so it can send out a bunch
@@ -716,7 +717,7 @@
 		nfs_unlock_request(req);
 done:
         dprintk("NFS:      nfs_updatepage returns %d (isize %Ld)\n",
-                                                status, (long long)inode->i_size);
+			status, (long long)i_size_read(inode));
 	if (status < 0)
 		ClearPageUptodate(page);
 	return status;
@@ -951,7 +952,7 @@
 	end = req_offset(last) + last->wb_bytes;
 	len = end - start;
 	/* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */
-	if (end >= inode->i_size || len < 0 || len > (~((u32)0) >> 1))
+	if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1))
 		len = 0;
 
 	data->inode	  = inode;
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c	Fri Jul 11 01:25:29 2003
+++ b/fs/nfsd/nfssvc.c	Fri Jul 11 01:25:29 2003
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/fs_struct.h>
 
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/stats.h>
@@ -168,6 +169,7 @@
 nfsd(struct svc_rqst *rqstp)
 {
 	struct svc_serv	*serv = rqstp->rq_server;
+	struct fs_struct *fsp;
 	int		err;
 	struct nfsd_list me;
 	sigset_t shutdown_mask, allowed_mask;
@@ -178,6 +180,18 @@
 	daemonize("nfsd");
 	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
 
+	/* After daemonize() this kernel thread shares current->fs
+	 * with the init process. We need to create files with a
+	 * umask of 0 instead of init's umask. */
+	fsp = copy_fs_struct(current->fs);
+	if (!fsp) {
+		printk("Unable to start nfsd thread: out of memory\n");
+		goto out;
+	}
+	exit_fs(current);
+	current->fs = fsp;
+	current->fs->umask = 0;
+
 	siginitsetinv(&shutdown_mask, SHUTDOWN_SIGS);
 	siginitsetinv(&allowed_mask, ALLOWED_SIGS);
 
@@ -262,6 +276,7 @@
 	list_del(&me.list);
 	nfsdstats.th_cnt --;
 
+out:
 	/* Release the thread */
 	svc_exit_thread(rqstp);
 
diff -Nru a/fs/open.c b/fs/open.c
--- a/fs/open.c	Fri Jul 11 01:25:28 2003
+++ b/fs/open.c	Fri Jul 11 01:25:28 2003
@@ -1008,7 +1008,7 @@
  */
 int generic_file_open(struct inode * inode, struct file * filp)
 {
-	if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS)
+	if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
 		return -EFBIG;
 	return 0;
 }
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	Fri Jul 11 01:25:29 2003
+++ b/fs/proc/base.c	Fri Jul 11 01:25:29 2003
@@ -307,20 +307,22 @@
 	base = dget(current->fs->root);
 	read_unlock(&current->fs->lock);
 
-	spin_lock(&dcache_lock);
+	spin_lock(&vfsmount_lock);
 	de = root;
 	mnt = vfsmnt;
 
 	while (vfsmnt != our_vfsmnt) {
-		if (vfsmnt == vfsmnt->mnt_parent)
+		if (vfsmnt == vfsmnt->mnt_parent) {
+			spin_unlock(&vfsmount_lock);
 			goto out;
+		}
 		de = vfsmnt->mnt_mountpoint;
 		vfsmnt = vfsmnt->mnt_parent;
 	}
+	spin_unlock(&vfsmount_lock);
 
 	if (!is_subdir(de, base))
 		goto out;
-	spin_unlock(&dcache_lock);
 
 exit:
 	dput(base);
@@ -329,7 +331,6 @@
 	mntput(mnt);
 	return res;
 out:
-	spin_unlock(&dcache_lock);
 	res = -EACCES;
 	goto exit;
 }
diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c
--- a/fs/proc/generic.c	Fri Jul 11 01:25:30 2003
+++ b/fs/proc/generic.c	Fri Jul 11 01:25:30 2003
@@ -566,22 +566,6 @@
 	return ent;
 }
 
-struct proc_dir_entry *proc_mknod(const char *name, mode_t mode,
-		struct proc_dir_entry *parent, kdev_t rdev)
-{
-	struct proc_dir_entry *ent;
-
-	ent = proc_create(&parent,name,mode,1);
-	if (ent) {
-		ent->rdev = rdev;
-		if (proc_register(parent, ent) < 0) {
-			kfree(ent);
-			ent = NULL;
-		}
-	}
-	return ent;
-}
-
 struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
 {
 	struct proc_dir_entry *ent;
diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c
--- a/fs/proc/inode.c	Fri Jul 11 01:25:29 2003
+++ b/fs/proc/inode.c	Fri Jul 11 01:25:29 2003
@@ -204,8 +204,6 @@
 			inode->i_op = de->proc_iops;
 		if (de->proc_fops)
 			inode->i_fop = de->proc_fops;
-		else if (S_ISBLK(de->mode)||S_ISCHR(de->mode)||S_ISFIFO(de->mode))
-			init_special_inode(inode,de->mode,kdev_t_to_nr(de->rdev));
 	}
 
 out:
diff -Nru a/fs/proc/root.c b/fs/proc/root.c
--- a/fs/proc/root.c	Fri Jul 11 01:25:29 2003
+++ b/fs/proc/root.c	Fri Jul 11 01:25:29 2003
@@ -153,7 +153,6 @@
 EXPORT_SYMBOL(proc_sys_root);
 #endif
 EXPORT_SYMBOL(proc_symlink);
-EXPORT_SYMBOL(proc_mknod);
 EXPORT_SYMBOL(proc_mkdir);
 EXPORT_SYMBOL(create_proc_entry);
 EXPORT_SYMBOL(remove_proc_entry);
diff -Nru a/fs/quota_v1.c b/fs/quota_v1.c
--- a/fs/quota_v1.c	Fri Jul 11 01:25:29 2003
+++ b/fs/quota_v1.c	Fri Jul 11 01:25:29 2003
@@ -132,12 +132,14 @@
 	mm_segment_t fs;
 	ssize_t size;
 	loff_t offset = 0;
+	loff_t isize;
 	static const uint quota_magics[] = V2_INITQMAGICS;
 
-	if (!inode->i_size)
+	isize = i_size_read(inode);
+	if (!isize)
 		return 0;
-	blocks = inode->i_size >> BLOCK_SIZE_BITS;
-	off = inode->i_size & (BLOCK_SIZE - 1);
+	blocks = isize >> BLOCK_SIZE_BITS;
+	off = isize & (BLOCK_SIZE - 1);
 	if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk))
 		return 0;
 	/* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	Fri Jul 11 01:25:29 2003
+++ b/fs/read_write.c	Fri Jul 11 01:25:29 2003
@@ -55,7 +55,7 @@
 	lock_kernel();
 	switch (origin) {
 		case 2:
-			offset += file->f_dentry->d_inode->i_size;
+			offset += i_size_read(file->f_dentry->d_inode);
 			break;
 		case 1:
 			offset += file->f_pos;
@@ -84,7 +84,7 @@
 	lock_kernel();
 	switch (origin) {
 		case 2:
-			offset += file->f_dentry->d_inode->i_size;
+			offset += i_size_read(file->f_dentry->d_inode);
 			break;
 		case 1:
 			offset += file->f_pos;
diff -Nru a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
--- a/fs/reiserfs/bitmap.c	Fri Jul 11 01:25:29 2003
+++ b/fs/reiserfs/bitmap.c	Fri Jul 11 01:25:29 2003
@@ -43,7 +43,7 @@
     test_bit(_ALLOC_ ## optname , &SB_ALLOC_OPTS(s))
 
 static inline void get_bit_address (struct super_block * s,
-				    unsigned long block, int * bmap_nr, int * offset)
+				    b_blocknr_t block, int * bmap_nr, int * offset)
 {
     /* It is in the bitmap block number equal to the block
      * number divided by the number of bits in a block. */
@@ -54,7 +54,7 @@
 }
 
 #ifdef CONFIG_REISERFS_CHECK
-int is_reusable (struct super_block * s, unsigned long block, int bit_value)
+int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value)
 {
     int i, j;
 
@@ -107,7 +107,7 @@
 static inline  int is_block_in_journal (struct super_block * s, int bmap, int
 off, int *next)
 {
-    unsigned long tmp;
+    b_blocknr_t tmp;
 
     if (reiserfs_in_journal (s, bmap, off, 1, &tmp)) {
 	if (tmp) {              /* hint supplied */
@@ -235,7 +235,7 @@
 /* Tries to find contiguous zero bit window (given size) in given region of
  * bitmap and place new blocks there. Returns number of allocated blocks. */
 static int scan_bitmap (struct reiserfs_transaction_handle *th,
-			unsigned long *start, unsigned long finish,
+			b_blocknr_t *start, b_blocknr_t finish,
 			int min, int max, int unfm, unsigned long file_block)
 {
     int nr_allocated=0;
@@ -281,7 +281,7 @@
 }
 
 static void _reiserfs_free_block (struct reiserfs_transaction_handle *th,
-				  unsigned long block)
+				  b_blocknr_t block)
 {
     struct super_block * s = th->t_super;
     struct reiserfs_super_block * rs;
@@ -327,7 +327,7 @@
 }
 
 void reiserfs_free_block (struct reiserfs_transaction_handle *th, 
-                          unsigned long block)
+                          b_blocknr_t block)
 {
     struct super_block * s = th->t_super;
 
@@ -340,7 +340,7 @@
 
 /* preallocated blocks don't need to be run through journal_mark_freed */
 void reiserfs_free_prealloc_block (struct reiserfs_transaction_handle *th, 
-                          unsigned long block) {
+                          b_blocknr_t block) {
     RFALSE(!th->t_super, "vs-4060: trying to free block on nonexistent device");
     RFALSE(is_reusable (th->t_super, block, 1) == 0, "vs-4070: can not free such block");
     _reiserfs_free_block(th, block) ;
@@ -589,15 +589,15 @@
 
 static inline int old_hashed_relocation (reiserfs_blocknr_hint_t * hint)
 {
-    unsigned long border;
-    unsigned long hash_in;
+    b_blocknr_t border;
+    u32 hash_in;
     
     if (hint->formatted_node || hint->inode == NULL) {
 	return 0;
       }
 
     hash_in = le32_to_cpu((INODE_PKEY(hint->inode))->k_dir_id);
-    border = hint->beg + (unsigned long) keyed_hash(((char *) (&hash_in)), 4) % (hint->end - hint->beg - 1);
+    border = hint->beg + (u32) keyed_hash(((char *) (&hash_in)), 4) % (hint->end - hint->beg - 1);
     if (border > hint->search_start)
 	hint->search_start = border;
 
@@ -606,7 +606,7 @@
   
 static inline int old_way (reiserfs_blocknr_hint_t * hint)
 {
-    unsigned long border;
+    b_blocknr_t border;
     
     if (hint->formatted_node || hint->inode == NULL) {
 	return 0;
@@ -622,7 +622,7 @@
 static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint)
 {
     struct key * key = &hint->key;
-    unsigned long slice_start;
+    b_blocknr_t slice_start;
 
     slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100);
     if ( slice_start > hint->search_start || slice_start + (hint->end / 100) <= hint->search_start) {
@@ -910,7 +910,7 @@
 int reiserfs_can_fit_pages ( struct super_block *sb /* superblock of filesystem
 						       to estimate space */ )
 {
-	unsigned long space;
+	b_blocknr_t space;
 
 	spin_lock(&REISERFS_SB(sb)->bitmap_lock);
 	space = (SB_FREE_BLOCKS(sb) - REISERFS_SB(sb)->reserved_blocks) >> ( PAGE_CACHE_SHIFT - sb->s_blocksize_bits);
diff -Nru a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c
--- a/fs/reiserfs/do_balan.c	Fri Jul 11 01:25:28 2003
+++ b/fs/reiserfs/do_balan.c	Fri Jul 11 01:25:28 2003
@@ -1250,12 +1250,12 @@
 
 static void free_thrown(struct tree_balance *tb) {
     int i ;
-    unsigned long blocknr ;
+    b_blocknr_t blocknr ;
     for (i = 0; i < sizeof (tb->thrown)/sizeof (tb->thrown[0]); i++) {
 	if (tb->thrown[i]) {
 	    blocknr = tb->thrown[i]->b_blocknr ;
 	    if (buffer_dirty (tb->thrown[i]))
-	      printk ("free_thrown deals with dirty buffer %ld\n", blocknr);
+	      printk ("free_thrown deals with dirty buffer %d\n", blocknr);
 	    brelse(tb->thrown[i]) ; /* incremented in store_thrown */
 	    reiserfs_free_block (tb->transaction_handle, blocknr);
 	}
@@ -1339,7 +1339,7 @@
 
 #ifdef CONFIG_REISERFS_CHECK
 
-int is_reusable (struct super_block * s, unsigned long block, int bit_value);
+int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
 static void check_internal_node (struct super_block * s, struct buffer_head * bh, char * mes)
 {
   struct disk_child * dc;
diff -Nru a/fs/reiserfs/fix_node.c b/fs/reiserfs/fix_node.c
--- a/fs/reiserfs/fix_node.c	Fri Jul 11 01:25:28 2003
+++ b/fs/reiserfs/fix_node.c	Fri Jul 11 01:25:28 2003
@@ -758,7 +758,7 @@
             ) {
   struct buffer_head  * p_s_new_bh,
     		      *	p_s_Sh = PATH_H_PBUFFER (p_s_tb->tb_path, n_h);
-  unsigned long	      *	p_n_blocknr,
+  b_blocknr_t	      *	p_n_blocknr,
     			a_n_blocknrs[MAX_AMOUNT_NEEDED] = {0, };
   int       		n_counter,
    			n_number_of_freeblk,
@@ -879,7 +879,7 @@
             ) {
   struct buffer_head  * p_s_father, * left;
   struct super_block  * p_s_sb = p_s_tb->tb_sb;
-  unsigned long         n_left_neighbor_blocknr;
+  b_blocknr_t		n_left_neighbor_blocknr;
   int                   n_left_neighbor_position;
 
   if ( ! p_s_tb->FL[n_h] ) /* Father of the left neighbor does not exist. */
@@ -2501,7 +2501,7 @@
     /* deal with list of allocated (used and unused) nodes */
     for ( i = 0; i < MAX_FEB_SIZE; i++ ) {
 	if ( tb->FEB[i] ) {
-	    unsigned long blocknr  = tb->FEB[i]->b_blocknr ;
+	    b_blocknr_t blocknr  = tb->FEB[i]->b_blocknr ;
 	    /* de-allocated block which was not used by balancing and
                bforget about buffer for it */
 	    brelse (tb->FEB[i]);
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	Fri Jul 11 01:25:28 2003
+++ b/fs/reiserfs/inode.c	Fri Jul 11 01:25:28 2003
@@ -506,7 +506,7 @@
 			struct buffer_head * bh_result, int create)
 {
     int repeat, retval;
-    b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is unsigned long
+    b_blocknr_t allocated_block_nr = 0;// b_blocknr_t is (unsigned) 32 bit int
     INITIALIZE_PATH(path);
     int pos_in_item;
     struct cpu_key key;
diff -Nru a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
--- a/fs/reiserfs/journal.c	Fri Jul 11 01:25:29 2003
+++ b/fs/reiserfs/journal.c	Fri Jul 11 01:25:29 2003
@@ -507,7 +507,7 @@
 */
 int reiserfs_in_journal(struct super_block *p_s_sb,
                         int bmap_nr, int bit_nr, int search_all, 
-			unsigned long *next_zero_bit) {
+			b_blocknr_t *next_zero_bit) {
   struct reiserfs_journal_cnode *cn ;
   struct reiserfs_list_bitmap *jb ;
   int i ;
@@ -761,7 +761,7 @@
 */
 static struct reiserfs_journal_list *find_newer_jl_for_cn(struct reiserfs_journal_cnode *cn) {
   struct super_block *sb = cn->sb;
-  unsigned long blocknr = cn->blocknr ;
+  b_blocknr_t blocknr = cn->blocknr ;
 
   cn = cn->hprev ;
   while(cn) {
@@ -791,7 +791,7 @@
   while(cn) {
     if (cn->blocknr != 0) {
       if (debug) {
-        printk("block %lu, bh is %d, state %ld\n", cn->blocknr, cn->bh ? 1: 0, 
+        printk("block %u, bh is %d, state %ld\n", cn->blocknr, cn->bh ? 1: 0,
 	        cn->state) ;
       }
       cn->state = 0 ;
@@ -1105,7 +1105,7 @@
 {
     struct reiserfs_journal_list *pjl ; /* previous list for this cn */
     struct reiserfs_journal_cnode *cn, *walk_cn ;
-    unsigned long blocknr ;
+    b_blocknr_t blocknr ;
     int run = 0 ;
     int orig_trans_id = jl->j_trans_id ;
     struct buffer_head *saved_bh ; 
@@ -2421,7 +2421,7 @@
 **
 ** returns 1 if it cleaned and relsed the buffer. 0 otherwise
 */
-static int remove_from_transaction(struct super_block *p_s_sb, unsigned long blocknr, int already_cleaned) {
+static int remove_from_transaction(struct super_block *p_s_sb, b_blocknr_t blocknr, int already_cleaned) {
   struct buffer_head *bh ;
   struct reiserfs_journal_cnode *cn ;
   int ret = 0;
@@ -2474,7 +2474,7 @@
 */
 static int can_dirty(struct reiserfs_journal_cnode *cn) {
   struct super_block *sb = cn->sb;
-  unsigned long blocknr = cn->blocknr  ;
+  b_blocknr_t blocknr = cn->blocknr  ;
   struct reiserfs_journal_cnode *cur = cn->hprev ;
   int can_dirty = 1 ;
   
@@ -2710,7 +2710,7 @@
 **
 ** Then remove it from the current transaction, decrementing any counters and filing it on the clean list.
 */
-int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long blocknr) {
+int journal_mark_freed(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, b_blocknr_t blocknr) {
   struct reiserfs_journal_cnode *cn = NULL ;
   struct buffer_head *bh = NULL ;
   struct reiserfs_list_bitmap *jb = NULL ;
@@ -2719,7 +2719,7 @@
   if (reiserfs_dont_log(th->t_super)) {
     bh = sb_find_get_block(p_s_sb, blocknr) ;
     if (bh && buffer_dirty (bh)) {
-      printk ("journal_mark_freed(dont_log): dirty buffer on hash list: %lx %ld\n", bh->b_state, blocknr);
+      printk ("journal_mark_freed(dont_log): dirty buffer on hash list: %lx %d\n", bh->b_state, blocknr);
       BUG ();
     }
     brelse (bh);
diff -Nru a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
--- a/fs/reiserfs/stree.c	Fri Jul 11 01:25:29 2003
+++ b/fs/reiserfs/stree.c	Fri Jul 11 01:25:29 2003
@@ -102,7 +102,7 @@
   int n_key_length = REISERFS_SHORT_KEY_LEN;
 
   p_s_le_u32 = (__u32 *)le_key;
-  p_s_cpu_u32 = (__u32 *)cpu_key;
+  p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key;
   for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) {
     if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 )
       return -1;
diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
--- a/fs/reiserfs/tail_conversion.c	Fri Jul 11 01:25:30 2003
+++ b/fs/reiserfs/tail_conversion.c	Fri Jul 11 01:25:30 2003
@@ -191,7 +191,7 @@
 	bh = next ;
       } while (bh != head) ;
       if ( PAGE_SIZE == bh->b_size ) {
-	ClearPageDirty(page);
+	clear_page_dirty(page);
       }
     }
   } 
diff -Nru a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c	Fri Jul 11 01:25:28 2003
+++ b/fs/stat.c	Fri Jul 11 01:25:28 2003
@@ -28,7 +28,7 @@
 	stat->atime = inode->i_atime;
 	stat->mtime = inode->i_mtime;
 	stat->ctime = inode->i_ctime;
-	stat->size = inode->i_size;
+	stat->size = i_size_read(inode);
 	stat->blocks = inode->i_blocks;
 	stat->blksize = inode->i_blksize;
 }
diff -Nru a/include/asm-parisc/byteorder.h b/include/asm-parisc/byteorder.h
--- a/include/asm-parisc/byteorder.h	Fri Jul 11 01:25:29 2003
+++ b/include/asm-parisc/byteorder.h	Fri Jul 11 01:25:29 2003
@@ -30,9 +30,9 @@
 */
 static __inline__ __const__ __u64 ___arch__swab64(__u64 x) {
 	__u64 temp;
-	__asm__("permh 3210, %0, %0\n\t"
+	__asm__("permh,3210 %0, %0\n\t"
 		"hshl %0, 8, %1\n\t"
-		"hshr u, %0, 8, %0\n\t"
+		"hshr,u %0, 8, %0\n\t"
 		"or %1, %0, %0"
 		: "=r" (x), "=&r" (temp)
 		: "0" (x));
diff -Nru a/include/asm-parisc/parisc-device.h b/include/asm-parisc/parisc-device.h
--- a/include/asm-parisc/parisc-device.h	Fri Jul 11 01:25:28 2003
+++ b/include/asm-parisc/parisc-device.h	Fri Jul 11 01:25:28 2003
@@ -33,6 +33,7 @@
 	char *name; 
 	const struct parisc_device_id *id_table;
 	int (*probe) (struct parisc_device *dev); /* New device discovered */
+	int (*remove) (struct parisc_device *dev);
 	struct device_driver drv;
 };
 
diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
--- a/include/asm-parisc/pgtable.h	Fri Jul 11 01:25:29 2003
+++ b/include/asm-parisc/pgtable.h	Fri Jul 11 01:25:29 2003
@@ -368,11 +368,11 @@
 /* Encode and de-code a swap entry */
 
 #define __swp_type(x)                     ((x).val & 0x1f)
-#define __swp_offset(x)                   ( (((x).val >> 5) &  0xf) | \
-					  (((x).val >> 7) & ~0xf) )
+#define __swp_offset(x)                   ( (((x).val >> 6) &  0x7) | \
+					  (((x).val >> 8) & ~0x7) )
 #define __swp_entry(type, offset)         ((swp_entry_t) { (type) | \
-					    ((offset &  0xf) << 5) | \
-					    ((offset & ~0xf) << 7) })
+					    ((offset &  0x7) << 6) | \
+					    ((offset & ~0x7) << 8) })
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
 
diff -Nru a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
--- a/include/asm-parisc/processor.h	Fri Jul 11 01:25:30 2003
+++ b/include/asm-parisc/processor.h	Fri Jul 11 01:25:30 2003
@@ -142,6 +142,7 @@
  */
 
 unsigned long thread_saved_pc(struct task_struct *t);
+void show_trace(struct task_struct *task, unsigned long *stack);
 
 /*
  * Start user thread in another space.
diff -Nru a/include/asm-v850/statfs.h b/include/asm-v850/statfs.h
--- a/include/asm-v850/statfs.h	Fri Jul 11 01:25:29 2003
+++ b/include/asm-v850/statfs.h	Fri Jul 11 01:25:29 2003
@@ -1,25 +1,6 @@
 #ifndef __V850_STATFS_H__
 #define __V850_STATFS_H__
 
-#ifndef __KERNEL_STRICT_NAMES
-
-#include <linux/types.h>
-
-typedef __kernel_fsid_t	fsid_t;
-
-#endif
-
-struct statfs {
-	long f_type;
-	long f_bsize;
-	long f_blocks;
-	long f_bfree;
-	long f_bavail;
-	long f_files;
-	long f_ffree;
-	__kernel_fsid_t f_fsid;
-	long f_namelen;
-	long f_spare[6];
-};
+#include <asm-generic/statfs.h>
 
 #endif /* __V850_STATFS_H__ */
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Fri Jul 11 01:25:28 2003
+++ b/include/linux/fs.h	Fri Jul 11 01:25:28 2003
@@ -349,6 +349,17 @@
 	struct gendisk *	bd_disk;
 };
 
+/*
+ * Use sequence counter to get consistent i_size on 32-bit processors.
+ */
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+#include <linux/seqlock.h>
+#define __NEED_I_SIZE_ORDERED
+#define i_size_ordered_init(inode) seqcount_init(&inode->i_size_seqcount)
+#else
+#define i_size_ordered_init(inode) do { } while (0)
+#endif
+
 struct inode {
 	struct hlist_node	i_hash;
 	struct list_head	i_list;
@@ -399,7 +410,59 @@
 	union {
 		void		*generic_ip;
 	} u;
+#ifdef __NEED_I_SIZE_ORDERED
+	seqcount_t		i_size_seqcount;
+#endif
 };
+
+/*
+ * NOTE: in a 32bit arch with a preemptable kernel and
+ * an UP compile the i_size_read/write must be atomic
+ * with respect to the local cpu (unlike with preempt disabled),
+ * but they don't need to be atomic with respect to other cpus like in
+ * true SMP (so they need either to either locally disable irq around
+ * the read or for example on x86 they can be still implemented as a
+ * cmpxchg8b without the need of the lock prefix). For SMP compiles
+ * and 64bit archs it makes no difference if preempt is enabled or not.
+ */
+static inline loff_t i_size_read(struct inode *inode)
+{
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+	loff_t i_size;
+	unsigned int seq;
+
+	do {
+		seq = read_seqcount_begin(&inode->i_size_seqcount);
+		i_size = inode->i_size;
+	} while (read_seqcount_retry(&inode->i_size_seqcount, seq));
+	return i_size;
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+	loff_t i_size;
+
+	preempt_disable();
+	i_size = inode->i_size;
+	preempt_enable();
+	return i_size;
+#else
+	return inode->i_size;
+#endif
+}
+
+
+static inline void i_size_write(struct inode *inode, loff_t i_size)
+{
+#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+	write_seqcount_begin(&inode->i_size_seqcount);
+	inode->i_size = i_size;
+	write_seqcount_end(&inode->i_size_seqcount);
+#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+	preempt_disable();
+	inode->i_size = i_size;
+	preempt_enable();
+#else
+	inode->i_size = i_size;
+#endif
+}
 
 struct fown_struct {
 	rwlock_t lock;          /* protects pid, uid, euid fields */
diff -Nru a/include/linux/irda.h b/include/linux/irda.h
--- a/include/linux/irda.h	Fri Jul 11 01:25:28 2003
+++ b/include/linux/irda.h	Fri Jul 11 01:25:28 2003
@@ -25,7 +25,11 @@
 #ifndef KERNEL_IRDA_H
 #define KERNEL_IRDA_H
 
-#include <linux/socket.h> /* only for sa_family_t */
+/* Please do *not* add any #include in this file, this file is
+ * included as-is in user space.
+ * Please fix the calling file to properly included needed files before
+ * this one, or preferably to include <net/irda/irda.h> instead.
+ * Jean II */
 
 /* Hint bit positions for first hint byte */
 #define HINT_PNP         0x01
diff -Nru a/include/linux/jbd.h b/include/linux/jbd.h
--- a/include/linux/jbd.h	Fri Jul 11 01:25:29 2003
+++ b/include/linux/jbd.h	Fri Jul 11 01:25:29 2003
@@ -992,9 +992,9 @@
 int __log_start_commit(journal_t *journal, tid_t tid);
 int journal_start_commit(journal_t *journal, tid_t *tid);
 int log_wait_commit(journal_t *journal, tid_t tid);
-int log_do_checkpoint(journal_t *journal, int nblocks);
+int log_do_checkpoint(journal_t *journal);
 
-void __log_wait_for_space(journal_t *journal, int nblocks);
+void __log_wait_for_space(journal_t *journal);
 extern void	__journal_drop_transaction(journal_t *, transaction_t *);
 extern int	cleanup_journal_tail(journal_t *);
 
@@ -1052,6 +1052,19 @@
 }
 
 extern int journal_blocks_per_page(struct inode *inode);
+
+/*
+ * Return the minimum number of blocks which must be free in the journal
+ * before a new transaction may be started.  Must be called under j_state_lock.
+ */
+static inline int jbd_space_needed(journal_t *journal)
+{
+	int nblocks = journal->j_max_transaction_buffers;
+	if (journal->j_committing_transaction)
+		nblocks += journal->j_committing_transaction->
+					t_outstanding_credits;
+	return nblocks;
+}
 
 /*
  * Definitions which augment the buffer_head layer
diff -Nru a/include/linux/loop.h b/include/linux/loop.h
--- a/include/linux/loop.h	Fri Jul 11 01:25:30 2003
+++ b/include/linux/loop.h	Fri Jul 11 01:25:30 2003
@@ -36,7 +36,8 @@
 	int		(*transfer)(struct loop_device *, int cmd,
 				    char *raw_buf, char *loop_buf, int size,
 				    sector_t real_block);
-	char		lo_name[LO_NAME_SIZE];
+	char		lo_file_name[LO_NAME_SIZE];
+	char		lo_crypt_name[LO_NAME_SIZE];
 	char		lo_encrypt_key[LO_KEY_SIZE];
 	int		lo_encrypt_key_size;
 	struct loop_func_table *lo_encryption;
@@ -49,7 +50,6 @@
 	struct block_device *lo_device;
 	unsigned	lo_blocksize;
 	void		*key_data; 
-	char		key_reserved[48]; /* for use by the filter modules */
 
 	int		old_gfp_mask;
 
@@ -102,7 +102,8 @@
 	__u32		   lo_encrypt_type;
 	__u32		   lo_encrypt_key_size;		/* ioctl w/o */
 	__u32		   lo_flags;			/* ioctl r/o */
-	__u8		   lo_name[LO_NAME_SIZE];
+	__u8		   lo_file_name[LO_NAME_SIZE];
+	__u8		   lo_crypt_name[LO_NAME_SIZE];
 	__u8		   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
 	__u64		   lo_init[2];
 };
diff -Nru a/include/linux/mount.h b/include/linux/mount.h
--- a/include/linux/mount.h	Fri Jul 11 01:25:28 2003
+++ b/include/linux/mount.h	Fri Jul 11 01:25:28 2003
@@ -54,6 +54,7 @@
 extern struct vfsmount *alloc_vfsmnt(const char *name);
 extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
 				      const char *name, void *data);
+extern spinlock_t vfsmount_lock;
 
 #endif
 #endif /* _LINUX_MOUNT_H */
diff -Nru a/include/linux/nbd.h b/include/linux/nbd.h
--- a/include/linux/nbd.h	Fri Jul 11 01:25:30 2003
+++ b/include/linux/nbd.h	Fri Jul 11 01:25:30 2003
@@ -5,6 +5,9 @@
  * 2001 Copyright (C) Steven Whitehouse
  *            New nbd_end_request() for compatibility with new linux block
  *            layer code.
+ * 2003/06/24 Louis D. Langholtz <ldl@aros.net>
+ *            Removed unneeded blksize_bits field from nbd_device struct.
+ *            Cleanup PARANOIA usage & code.
  */
 
 #ifndef LINUX_NBD_H
@@ -26,31 +29,27 @@
 	NBD_CMD_DISC = 2
 };
 
-
-#ifdef PARANOIA
-extern int requests_in;
-extern int requests_out;
-#endif
-
 #define nbd_cmd(req) ((req)->cmd[0])
-
 #define MAX_NBD 128
 
+/* Define PARANOIA to include extra sanity checking code in here & driver */
+#define PARANOIA
+
 struct nbd_device {
-	int refcnt;	
 	int flags;
 	int harderror;		/* Code of hard error			*/
 #define NBD_READ_ONLY 0x0001
 #define NBD_WRITE_NOCHK 0x0002
 	struct socket * sock;
 	struct file * file; 	/* If == NULL, device is not ready, yet	*/
+#ifdef PARANOIA
 	int magic;		/* FIXME: not if debugging is off	*/
+#endif
 	spinlock_t queue_lock;
 	struct list_head queue_head;/* Requests are added here...	*/
 	struct semaphore tx_lock;
 	struct gendisk *disk;
 	int blksize;
-	int blksize_bits;
 	u64 bytesize;
 };
 
diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h
--- a/include/linux/proc_fs.h	Fri Jul 11 01:25:28 2003
+++ b/include/linux/proc_fs.h	Fri Jul 11 01:25:28 2003
@@ -71,7 +71,6 @@
 	write_proc_t *write_proc;
 	atomic_t count;		/* use count */
 	int deleted;		/* delete flag */
-	kdev_t	rdev;
 };
 
 struct kcore_list {
@@ -141,8 +140,6 @@
 
 extern struct proc_dir_entry *proc_symlink(const char *,
 		struct proc_dir_entry *, const char *);
-extern struct proc_dir_entry *proc_mknod(const char *,mode_t,
-		struct proc_dir_entry *,kdev_t);
 extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
 
 static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
@@ -209,8 +206,6 @@
 
 static inline struct proc_dir_entry *proc_symlink(const char *name,
 		struct proc_dir_entry *parent,char *dest) {return NULL;}
-static inline struct proc_dir_entry *proc_mknod(const char *name,mode_t mode,
-		struct proc_dir_entry *parent,kdev_t rdev) {return NULL;}
 static inline struct proc_dir_entry *proc_mkdir(const char *name,
 	struct proc_dir_entry *parent) {return NULL;}
 
diff -Nru a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
--- a/include/linux/reiserfs_fs.h	Fri Jul 11 01:25:29 2003
+++ b/include/linux/reiserfs_fs.h	Fri Jul 11 01:25:29 2003
@@ -269,7 +269,7 @@
 #define NO_BALANCING_NEEDED  (-4)
 #define NO_MORE_UNUSED_CONTIGUOUS_BLOCKS (-5)
 
-typedef unsigned long b_blocknr_t;
+typedef __u32 b_blocknr_t;
 typedef __u32 unp_t;
 
 struct unfm_nodeinfo {
@@ -570,7 +570,7 @@
 static inline int uniqueness2type (__u32 uniqueness) CONSTF;
 static inline int uniqueness2type (__u32 uniqueness)
 {
-    switch (uniqueness) {
+    switch ((int)uniqueness) {
     case V1_SD_UNIQUENESS: return TYPE_STAT_DATA;
     case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT;
     case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT;
@@ -1730,11 +1730,11 @@
 int journal_end(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ;
 int journal_end_sync(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ;
 int journal_mark_dirty_nolog(struct reiserfs_transaction_handle *, struct super_block *, struct buffer_head *bh) ;
-int journal_mark_freed(struct reiserfs_transaction_handle *, struct super_block *, unsigned long blocknr) ;
+int journal_mark_freed(struct reiserfs_transaction_handle *, struct super_block *, b_blocknr_t blocknr) ;
 int push_journal_writer(char *w) ;
 int pop_journal_writer(int windex) ;
 int journal_transaction_should_end(struct reiserfs_transaction_handle *, int) ;
-int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr, int searchall, unsigned long *next) ;
+int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr, int searchall, b_blocknr_t *next) ;
 int journal_begin(struct reiserfs_transaction_handle *, struct super_block *p_s_sb, unsigned long) ;
 void flush_async_commits(struct super_block *p_s_sb) ;
 
@@ -2105,8 +2105,8 @@
 typedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t;
 
 int reiserfs_parse_alloc_options (struct super_block *, char *);
-int is_reusable (struct super_block * s, unsigned long block, int bit_value);
-void reiserfs_free_block (struct reiserfs_transaction_handle *th, unsigned long);
+int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value);
+void reiserfs_free_block (struct reiserfs_transaction_handle *th, b_blocknr_t);
 int reiserfs_allocate_blocknrs(reiserfs_blocknr_hint_t *, b_blocknr_t * , int, int);
 extern inline int reiserfs_new_form_blocknrs (struct tree_balance * tb,
 					      b_blocknr_t *new_blocknrs, int amount_needed)
diff -Nru a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
--- a/include/linux/reiserfs_fs_sb.h	Fri Jul 11 01:25:29 2003
+++ b/include/linux/reiserfs_fs_sb.h	Fri Jul 11 01:25:29 2003
@@ -133,7 +133,7 @@
 struct reiserfs_journal_cnode {
   struct buffer_head *bh ;		 /* real buffer head */
   struct super_block *sb ;		 /* dev of real buffer head */
-  unsigned long blocknr ;		 /* block number of real buffer head, == 0 when buffer on disk */		 
+  __u32 blocknr ;		 /* block number of real buffer head, == 0 when buffer on disk */
   long state ;
   struct reiserfs_journal_list *jlist ;  /* journal list this cnode lives in */
   struct reiserfs_journal_cnode *next ;  /* next in transaction list */
diff -Nru a/include/linux/seqlock.h b/include/linux/seqlock.h
--- a/include/linux/seqlock.h	Fri Jul 11 01:25:28 2003
+++ b/include/linux/seqlock.h	Fri Jul 11 01:25:28 2003
@@ -94,6 +94,57 @@
 	return (iv & 1) | (sl->sequence ^ iv);
 }
 
+
+/*
+ * Version using sequence counter only.
+ * This can be used when code has its own mutex protecting the
+ * updating starting before the write_seqcountbeqin() and ending
+ * after the write_seqcount_end().
+ */
+
+typedef struct seqcount {
+	unsigned sequence;
+} seqcount_t;
+
+#define SEQCNT_ZERO { 0 }
+#define seqcount_init(x)	do { *(x) = (seqcount_t) SEQCNT_ZERO; } while (0)
+
+/* Start of read using pointer to a sequence counter only.  */
+static inline unsigned read_seqcount_begin(const seqcount_t *s)
+{
+	unsigned ret = s->sequence;
+	smp_rmb();
+	return ret;
+}
+
+/* Test if reader processed invalid data.
+ * Equivalent to: iv is odd or sequence number has changed.
+ *                (iv & 1) || (*s != iv)
+ * Using xor saves one conditional branch.
+ */
+static inline int read_seqcount_retry(const seqcount_t *s, unsigned iv)
+{
+	smp_rmb();
+	return (iv & 1) | (s->sequence ^ iv);
+}
+
+
+/*
+ * Sequence counter only version assumes that callers are using their
+ * own mutexing.
+ */
+static inline void write_seqcount_begin(seqcount_t *s)
+{
+	s->sequence++;
+	smp_wmb();
+}
+
+static inline void write_seqcount_end(seqcount_t *s)
+{
+	smp_wmb();
+	s->sequence++;
+}
+
 /*
  * Possible sw/hw IRQ protected versions of the interfaces.
  */
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	Fri Jul 11 01:25:29 2003
+++ b/include/linux/sysctl.h	Fri Jul 11 01:25:29 2003
@@ -130,6 +130,8 @@
 	KERN_PIDMAX=55,		/* int: PID # limit */
   	KERN_CORE_PATTERN=56,	/* string: pattern for core-file names */
 	KERN_PANIC_ON_OOPS=57,  /* int: whether we will panic on an oops */
+	KERN_HPPA_PWRSW=58,	/* int: hppa soft-power enable */
+	KERN_HPPA_UNALIGNED=59,	/* int: hppa unaligned-trap enable */
 };
 
 
diff -Nru a/include/linux/time.h b/include/linux/time.h
--- a/include/linux/time.h	Fri Jul 11 01:25:29 2003
+++ b/include/linux/time.h	Fri Jul 11 01:25:29 2003
@@ -217,6 +217,21 @@
 extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
 extern long do_nanosleep(struct timespec *t);
 extern long do_utimes(char __user * filename, struct timeval * times);
+
+static inline void
+set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
+{
+	while (nsec > NSEC_PER_SEC) {
+		nsec -= NSEC_PER_SEC;
+		++sec;
+	}
+	while (nsec < 0) {
+		nsec += NSEC_PER_SEC;
+		--sec;
+	}
+	ts->tv_sec = sec;
+	ts->tv_nsec = nsec;
+}
 #endif
 
 #define FD_SETSIZE		__FD_SETSIZE
diff -Nru a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
--- a/include/net/irda/irda_device.h	Fri Jul 11 01:25:30 2003
+++ b/include/net/irda/irda_device.h	Fri Jul 11 01:25:30 2003
@@ -230,7 +230,9 @@
 dongle_t *irda_device_dongle_init(struct net_device *dev, int type);
 int irda_device_dongle_cleanup(dongle_t *dongle);
 
+#ifdef CONFIG_ISA
 void setup_dma(int channel, char *buffer, int count, int mode);
+#endif
 
 void irda_task_delete(struct irda_task *task);
 int  irda_task_kick(struct irda_task *task);
diff -Nru a/include/net/irda/nsc-ircc.h b/include/net/irda/nsc-ircc.h
--- a/include/net/irda/nsc-ircc.h	Fri Jul 11 01:25:29 2003
+++ b/include/net/irda/nsc-ircc.h	Fri Jul 11 01:25:29 2003
@@ -39,17 +39,28 @@
 #define DMA_RX_MODE     0x04    /* I/O to mem, ++, demand. */
 
 /* Config registers for the '108 */
-#define CFG_BAIC 0x00
-#define CFG_CSRT 0x01
-#define CFG_MCTL 0x02
+#define CFG_108_BAIC 0x00
+#define CFG_108_CSRT 0x01
+#define CFG_108_MCTL 0x02
 
 /* Config registers for the '338 */
-#define CFG_FER  0x00
-#define CFG_FAR  0x01
-#define CFG_PTR  0x02
-#define CFG_PNP0 0x1b
-#define CFG_PNP1 0x1c
-#define CFG_PNP3 0x4f
+#define CFG_338_FER  0x00
+#define CFG_338_FAR  0x01
+#define CFG_338_PTR  0x02
+#define CFG_338_PNP0 0x1b
+#define CFG_338_PNP1 0x1c
+#define CFG_338_PNP3 0x4f
+
+/* Config registers for the '39x (in the logical device bank) */
+#define CFG_39X_LDN	0x07	/* Logical device number (Super I/O bank) */
+#define CFG_39X_ACT	0x30	/* Device activation */
+#define CFG_39X_BASEH	0x60	/* Device base address (high bits) */
+#define CFG_39X_BASEL	0x61	/* Device base address (low bits) */
+#define CFG_39X_IRQNUM	0x70	/* Interrupt number & wake up enable */
+#define CFG_39X_IRQSEL	0x71	/* Interrupt select (edge/level + polarity) */
+#define CFG_39X_DMA0	0x74	/* DMA 0 configuration */
+#define CFG_39X_DMA1	0x75	/* DMA 1 configuration */
+#define CFG_39X_SPC	0xF0	/* Serial port configuration register */
 
 /* Flags for configuration register CRF0 */
 #define APEDCRC		0x02
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	Fri Jul 11 01:25:29 2003
+++ b/init/Kconfig	Fri Jul 11 01:25:29 2003
@@ -118,6 +118,14 @@
 	  a "non-standard" kernel.  Only use this if you really know what you
 	  are doing.
 
+config KALLSYMS
+	 bool "Load all symbols for debugging/kksymoops" if EMBEDDED
+	 default y
+	 help
+	   Say Y here to let the kernel print out symbolic crash information and
+	   symbolic stack backtraces. This increases the size of the kernel
+	   somewhat, as all symbols have to be loaded into the kernel image.
+
 config FUTEX
 	bool "Enable futex support" if EMBEDDED
 	default y
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	Fri Jul 11 01:25:29 2003
+++ b/ipc/shm.c	Fri Jul 11 01:25:29 2003
@@ -703,7 +703,7 @@
 	}
 		
 	file = shp->shm_file;
-	size = file->f_dentry->d_inode->i_size;
+	size = i_size_read(file->f_dentry->d_inode);
 	shp->shm_nattch++;
 	shm_unlock(shp);
 
diff -Nru a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c	Fri Jul 11 01:25:29 2003
+++ b/kernel/compat.c	Fri Jul 11 01:25:29 2003
@@ -425,11 +425,9 @@
 				    &kernel_mask);
 	set_fs(old_fs);
 
-	if (ret > 0) {
+	if (ret > 0)
 		if (put_user(kernel_mask, user_mask_ptr))
-			ret = -EFAULT;
-		ret = sizeof(compat_ulong_t);
-	}
+			return -EFAULT;
 
 	return ret;
 }
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Fri Jul 11 01:25:28 2003
+++ b/kernel/fork.c	Fri Jul 11 01:25:28 2003
@@ -375,6 +375,7 @@
 	mm->core_waiters = 0;
 	mm->page_table_lock = SPIN_LOCK_UNLOCKED;
 	mm->ioctx_list_lock = RW_LOCK_UNLOCKED;
+	mm->ioctx_list = NULL;
 	mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
 
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Fri Jul 11 01:25:28 2003
+++ b/kernel/ksyms.c	Fri Jul 11 01:25:28 2003
@@ -41,6 +41,7 @@
 #include <linux/capability.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
+#include <linux/fs_struct.h>
 #include <linux/uio.h>
 #include <linux/tty.h>
 #include <linux/in6.h>
@@ -76,6 +77,8 @@
 EXPORT_SYMBOL(do_munmap);
 EXPORT_SYMBOL(do_brk);
 EXPORT_SYMBOL(exit_mm);
+EXPORT_SYMBOL_GPL(exit_fs);
+EXPORT_SYMBOL_GPL(copy_fs_struct);
 
 /* internal kernel memory management */
 EXPORT_SYMBOL(__alloc_pages);
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Fri Jul 11 01:25:29 2003
+++ b/kernel/sched.c	Fri Jul 11 01:25:29 2003
@@ -1047,7 +1047,7 @@
 	 */
 
 #define CAN_MIGRATE_TASK(p,rq,this_cpu)					\
-	((jiffies - (p)->last_run > cache_decay_ticks) &&	\
+	((!idle || (jiffies - (p)->last_run > cache_decay_ticks)) &&	\
 		!task_running(rq, p) &&					\
 			((p)->cpus_allowed & (1UL << (this_cpu))))
 
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Fri Jul 11 01:25:28 2003
+++ b/kernel/sysctl.c	Fri Jul 11 01:25:28 2003
@@ -87,6 +87,11 @@
 extern int stop_a_enabled;
 #endif
 
+#ifdef __hppa__
+extern int pwrsw_enabled;
+extern int unaligned_enabled;
+#endif
+
 #ifdef CONFIG_ARCH_S390
 #ifdef CONFIG_MATHEMU
 extern int sysctl_ieee_emulation_warnings;
@@ -312,6 +317,30 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+#endif
+#ifdef __hppa__
+	{
+		.ctl_name	= KERN_HPPA_PWRSW,
+		.procname	= "soft-power",
+		.data		= &pwrsw_enabled,
+		.maxlen		= sizeof (int),
+	 	.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= KERN_HPPA_UNALIGNED,
+		.procname	= "unaligned-trap",
+		.data		= &unaligned_enabled,
+		.maxlen		= sizeof (int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
+#ifdef __hppa__
+	{KERN_HPPA_PWRSW, "soft-power", &pwrsw_enabled, sizeof (int),
+	 0644, NULL, &proc_dointvec},
+	{KERN_HPPA_UNALIGNED, "unaligned-trap", &unaligned_enabled, sizeof (int),
+	 0644, NULL, &proc_dointvec},
 #endif
 #if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
 	{
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Fri Jul 11 01:25:28 2003
+++ b/mm/filemap.c	Fri Jul 11 01:25:28 2003
@@ -555,14 +555,15 @@
 	for (;;) {
 		struct page *page;
 		unsigned long end_index, nr, ret;
+		loff_t isize = i_size_read(inode);
 
-		end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+		end_index = isize >> PAGE_CACHE_SHIFT;
 			
 		if (index > end_index)
 			break;
 		nr = PAGE_CACHE_SIZE;
 		if (index == end_index) {
-			nr = inode->i_size & ~PAGE_CACHE_MASK;
+			nr = isize & ~PAGE_CACHE_MASK;
 			if (nr <= offset)
 				break;
 		}
@@ -763,7 +764,7 @@
 		retval = 0;
 		if (!count)
 			goto out; /* skip atime */
-		size = inode->i_size;
+		size = i_size_read(inode);
 		if (pos < size) {
 			retval = generic_file_direct_IO(READ, iocb,
 						iov, pos, nr_segs);
@@ -951,7 +952,7 @@
 	endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
 
 retry_all:
-	size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	if (pgoff >= size)
 		goto outside_data_content;
 
@@ -1233,7 +1234,7 @@
 					pgoff, len >> PAGE_CACHE_SHIFT);
 
 repeat:
-	size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	if (pgoff + (len >> PAGE_CACHE_SHIFT) > size)
 		return -EINVAL;
 
@@ -1544,7 +1545,7 @@
 	if (!isblk) {
 		/* FIXME: this is for backwards compatibility with 2.4 */
 		if (file->f_flags & O_APPEND)
-                        *pos = inode->i_size;
+                        *pos = i_size_read(inode);
 
 		if (limit != RLIM_INFINITY) {
 			if (*pos >= limit) {
@@ -1590,15 +1591,17 @@
 		if (unlikely(*pos + *count > inode->i_sb->s_maxbytes))
 			*count = inode->i_sb->s_maxbytes - *pos;
 	} else {
+		loff_t isize;
 		if (bdev_read_only(inode->i_bdev))
 			return -EPERM;
-		if (*pos >= inode->i_size) {
-			if (*count || *pos > inode->i_size)
+		isize = i_size_read(inode);
+		if (*pos >= isize) {
+			if (*count || *pos > isize)
 				return -ENOSPC;
 		}
 
-		if (*pos + *count > inode->i_size)
-			*count = inode->i_size - *pos;
+		if (*pos + *count > isize)
+			*count = isize - *pos;
 	}
 	return 0;
 }
@@ -1685,8 +1688,8 @@
 					iov, pos, nr_segs);
 		if (written > 0) {
 			loff_t end = pos + written;
-			if (end > inode->i_size && !isblk) {
-				inode->i_size = end;
+			if (end > i_size_read(inode) && !isblk) {
+				i_size_write(inode,  end);
 				mark_inode_dirty(inode);
 			}
 			*ppos = end;
@@ -1730,14 +1733,15 @@
 
 		status = a_ops->prepare_write(file, page, offset, offset+bytes);
 		if (unlikely(status)) {
+			loff_t isize = i_size_read(inode);
 			/*
 			 * prepare_write() may have instantiated a few blocks
 			 * outside i_size.  Trim these off again.
 			 */
 			unlock_page(page);
 			page_cache_release(page);
-			if (pos + bytes > inode->i_size)
-				vmtruncate(inode, inode->i_size);
+			if (pos + bytes > isize)
+				vmtruncate(inode, isize);
 			break;
 		}
 		if (likely(nr_segs == 1))
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Fri Jul 11 01:25:28 2003
+++ b/mm/memory.c	Fri Jul 11 01:25:28 2003
@@ -1109,7 +1109,7 @@
 
 	if (inode->i_size < offset)
 		goto do_expand;
-	inode->i_size = offset;
+	i_size_write(inode, offset);
 	pgoff = (offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	down(&mapping->i_shared_sem);
 	if (unlikely(!list_empty(&mapping->i_mmap)))
@@ -1126,7 +1126,7 @@
 		goto out_sig;
 	if (offset > inode->i_sb->s_maxbytes)
 		goto out;
-	inode->i_size = offset;
+	i_size_write(inode, offset);
 
 out_truncate:
 	if (inode->i_op && inode->i_op->truncate)
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Fri Jul 11 01:25:29 2003
+++ b/mm/mmap.c	Fri Jul 11 01:25:29 2003
@@ -476,10 +476,10 @@
 	if (!len)
 		return addr;
 
-	if (len > TASK_SIZE)
-		return -EINVAL;
-
+	/* Careful about overflows.. */
 	len = PAGE_ALIGN(len);
+	if (!len || len > TASK_SIZE)
+		return -EINVAL;
 
 	/* offset overflow? */
 	if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
diff -Nru a/mm/nommu.c b/mm/nommu.c
--- a/mm/nommu.c	Fri Jul 11 01:25:29 2003
+++ b/mm/nommu.c	Fri Jul 11 01:25:29 2003
@@ -48,7 +48,7 @@
 
 	if (inode->i_size < offset)
 		goto do_expand;
-	inode->i_size = offset;
+	i_size_write(inode, offset);
 
 	truncate_inode_pages(mapping, offset);
 	goto out_truncate;
@@ -59,7 +59,7 @@
 		goto out_sig;
 	if (offset > inode->i_sb->s_maxbytes)
 		goto out;
-	inode->i_size = offset;
+	i_size_write(inode, offset);
 
 out_truncate:
 	if (inode->i_op && inode->i_op->truncate)
diff -Nru a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c	Fri Jul 11 01:25:29 2003
+++ b/mm/oom_kill.c	Fri Jul 11 01:25:29 2003
@@ -141,8 +141,16 @@
  * CAP_SYS_RAW_IO set, send SIGTERM instead (but it's unlikely that
  * we select a process with CAP_SYS_RAW_IO set).
  */
-void oom_kill_task(struct task_struct *p)
+static void __oom_kill_task(task_t *p)
 {
+	task_lock(p);
+	if (!p->mm || p->mm == &init_mm) {
+		WARN_ON(1);
+		printk(KERN_WARNING "tried to kill an mm-less task!\n");
+		task_unlock(p);
+		return;
+	}
+	task_unlock(p);
 	printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", p->pid, p->comm);
 
 	/*
@@ -161,6 +169,16 @@
 	}
 }
 
+static struct mm_struct *oom_kill_task(task_t *p)
+{
+	struct mm_struct *mm = get_task_mm(p);
+	if (!mm || mm == &init_mm)
+		return NULL;
+	__oom_kill_task(p);
+	return mm;
+}
+
+
 /**
  * oom_kill - kill the "best" process when we run out of memory
  *
@@ -171,9 +189,11 @@
  */
 static void oom_kill(void)
 {
+	struct mm_struct *mm;
 	struct task_struct *g, *p, *q;
 	
 	read_lock(&tasklist_lock);
+retry:
 	p = select_bad_process();
 
 	/* Found nothing?!?! Either we hang forever, or we panic. */
@@ -182,17 +202,21 @@
 		panic("Out of memory and no killable processes...\n");
 	}
 
-	oom_kill_task(p);
+	mm = oom_kill_task(p);
+	if (!mm)
+		goto retry;
 	/*
 	 * kill all processes that share the ->mm (i.e. all threads),
 	 * but are in a different thread group
 	 */
 	do_each_thread(g, q)
-		if (q->mm == p->mm && q->tgid != p->tgid)
-			oom_kill_task(q);
+		if (q->mm == mm && q->tgid != p->tgid)
+			__oom_kill_task(q);
 	while_each_thread(g, q);
-
+	if (!p->mm)
+		printk(KERN_INFO "Fixed up OOM kill of mm-less task\n");
 	read_unlock(&tasklist_lock);
+	mmput(mm);
 
 	/*
 	 * Make kswapd go out of the way, so "p" has a good chance of
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	Fri Jul 11 01:25:28 2003
+++ b/mm/readahead.c	Fri Jul 11 01:25:28 2003
@@ -208,11 +208,12 @@
 	LIST_HEAD(page_pool);
 	int page_idx;
 	int ret = 0;
+	loff_t isize = i_size_read(inode);
 
-	if (inode->i_size == 0)
+	if (isize == 0)
 		goto out;
 
- 	end_index = ((inode->i_size - 1) >> PAGE_CACHE_SHIFT);
+ 	end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
 
 	/*
 	 * Preallocate as many pages as we will need.
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	Fri Jul 11 01:25:28 2003
+++ b/mm/shmem.c	Fri Jul 11 01:25:28 2003
@@ -299,7 +299,7 @@
 	static const swp_entry_t unswapped = {0};
 
 	if (sgp != SGP_WRITE &&
-	    ((loff_t) index << PAGE_CACHE_SHIFT) >= inode->i_size)
+	    ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode))
 		return ERR_PTR(-EINVAL);
 
 	while (!(entry = shmem_swp_entry(info, index, &page))) {
@@ -332,7 +332,7 @@
 			return ERR_PTR(-ENOMEM);
 		}
 		if (sgp != SGP_WRITE &&
-		    ((loff_t) index << PAGE_CACHE_SHIFT) >= inode->i_size) {
+		    ((loff_t) index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
 			entry = ERR_PTR(-EINVAL);
 			break;
 		}
@@ -641,7 +641,7 @@
 
 	/* Racing against delete or truncate? Must leave out of page cache */
 	limit = (inode->i_state & I_FREEING)? 0:
-		(inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+		(i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 	if (idx >= limit ||
 	    move_from_swap_cache(page, idx, inode->i_mapping) == 0)
@@ -964,7 +964,7 @@
 	enum sgp_type sgp = nonblock? SGP_QUICK: SGP_CACHE;
 	unsigned long size;
 
-	size = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	size = (i_size_read(inode) + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	if (pgoff >= size || pgoff + (len >> PAGE_SHIFT) > size)
 		return -EINVAL;
 
@@ -1239,12 +1239,13 @@
 	for (;;) {
 		struct page *page = NULL;
 		unsigned long end_index, nr, ret;
+		loff_t i_size = i_size_read(inode);
 
-		end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+		end_index = i_size >> PAGE_CACHE_SHIFT;
 		if (index > end_index)
 			break;
 		if (index == end_index) {
-			nr = inode->i_size & ~PAGE_CACHE_MASK;
+			nr = i_size & ~PAGE_CACHE_MASK;
 			if (nr <= offset)
 				break;
 		}
@@ -1261,9 +1262,10 @@
 		 * are called without i_sem protection against truncate
 		 */
 		nr = PAGE_CACHE_SIZE;
-		end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+		i_size = i_size_read(inode);
+		end_index = i_size >> PAGE_CACHE_SHIFT;
 		if (index == end_index) {
-			nr = inode->i_size & ~PAGE_CACHE_MASK;
+			nr = i_size & ~PAGE_CACHE_MASK;
 			if (nr <= offset) {
 				page_cache_release(page);
 				break;
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	Fri Jul 11 01:25:28 2003
+++ b/mm/swapfile.c	Fri Jul 11 01:25:28 2003
@@ -926,7 +926,7 @@
 	 */
 	probe_block = 0;
 	page_no = 0;
-	last_block = inode->i_size >> blkbits;
+	last_block = i_size_read(inode) >> blkbits;
 	while ((probe_block + blocks_per_page) <= last_block &&
 			page_no < sis->max) {
 		unsigned block_in_page;
@@ -1312,7 +1312,7 @@
 		goto bad_swap;
 	}
 
-	swapfilesize = mapping->host->i_size >> PAGE_SHIFT;
+	swapfilesize = i_size_read(mapping->host) >> PAGE_SHIFT;
 
 	/*
 	 * Read the swap header.
diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c
--- a/net/ipv4/igmp.c	Fri Jul 11 01:25:30 2003
+++ b/net/ipv4/igmp.c	Fri Jul 11 01:25:30 2003
@@ -1060,17 +1060,19 @@
 	reporter = im->reporter;
 	igmp_stop_timer(im);
 
-	if (IGMP_V1_SEEN(in_dev))
-		goto done;
-	if (IGMP_V2_SEEN(in_dev)) {
-		if (reporter)
-			igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
-		goto done;
-	}
-	/* IGMPv3 */
-	igmpv3_add_delrec(in_dev, im);
+	if (in_dev->dev->flags & IFF_UP) {
+		if (IGMP_V1_SEEN(in_dev))
+			goto done;
+		if (IGMP_V2_SEEN(in_dev)) {
+			if (reporter)
+				igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
+			goto done;
+		}
+		/* IGMPv3 */
+		igmpv3_add_delrec(in_dev, im);
 
-	igmp_ifc_event(in_dev);
+		igmp_ifc_event(in_dev);
+	}
 done:
 #endif
 	ip_mc_clear_src(im);
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
--- a/net/ipv4/raw.c	Fri Jul 11 01:25:29 2003
+++ b/net/ipv4/raw.c	Fri Jul 11 01:25:29 2003
@@ -383,7 +383,7 @@
 		 * IP_HDRINCL is much more convenient.
 		 */
 	} else {
-		err = -EINVAL;
+		err = -EDESTADDRREQ;
 		if (sk->sk_state != TCP_ESTABLISHED) 
 			goto out;
 		daddr = inet->daddr;
diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
--- a/net/ipv4/tcp_input.c	Fri Jul 11 01:25:29 2003
+++ b/net/ipv4/tcp_input.c	Fri Jul 11 01:25:29 2003
@@ -3694,6 +3694,13 @@
 		tcp_sync_mss(sk, tp->pmtu_cookie);
 		tcp_initialize_rcv_mss(sk);
 
+		/* Remember, tcp_poll() does not lock socket!
+		 * Change state from SYN-SENT only after copied_seq
+		 * is initialized. */
+		tp->copied_seq = tp->rcv_nxt;
+		mb();
+		tcp_set_state(sk, TCP_ESTABLISHED);
+
 		/* Make sure socket is routed, for correct metrics.  */
 		tp->af_specific->rebuild_header(sk);
 
@@ -3713,13 +3720,6 @@
 			__tcp_fast_path_on(tp, tp->snd_wnd);
 		else
 			tp->pred_flags = 0;
-
-		/* Remember, tcp_poll() does not lock socket!
-		 * Change state from SYN-SENT only after copied_seq
-		 * is initialized. */
-		tp->copied_seq = tp->rcv_nxt;
-		mb();
-		tcp_set_state(sk, TCP_ESTABLISHED);
 
 		if (!sock_flag(sk, SOCK_DEAD)) {
 			sk->sk_state_change(sk);
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
--- a/net/ipv4/udp.c	Fri Jul 11 01:25:28 2003
+++ b/net/ipv4/udp.c	Fri Jul 11 01:25:28 2003
@@ -540,7 +540,7 @@
 			return -EINVAL;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			return -EDESTADDRREQ;
 		daddr = inet->daddr;
 		dport = inet->dport;
 		/* Open fast path for connected socket.
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	Fri Jul 11 01:25:28 2003
+++ b/net/ipv6/ip6_output.c	Fri Jul 11 01:25:28 2003
@@ -1247,11 +1247,9 @@
 		inet->cork.length = 0;
 		inet->sndmsg_page = NULL;
 		inet->sndmsg_off = 0;
-		if ((exthdrlen = rt->u.dst.header_len) != 0) {
-			length += exthdrlen;
-			transhdrlen += exthdrlen;
-		}
-		exthdrlen += opt ? opt->opt_flen : 0;
+		exthdrlen = rt->u.dst.header_len + (opt ? opt->opt_flen : 0);
+		length += exthdrlen;
+		transhdrlen += exthdrlen;
 	} else {
 		rt = np->cork.rt;
 		if (inet->cork.flags & IPCORK_OPT)
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	Fri Jul 11 01:25:28 2003
+++ b/net/ipv6/raw.c	Fri Jul 11 01:25:28 2003
@@ -602,7 +602,7 @@
 			fl.oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED) 
-			return(-EINVAL);
+			return -EDESTADDRREQ;
 		
 		proto = inet->num;
 		daddr = &np->daddr;
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	Fri Jul 11 01:25:29 2003
+++ b/net/ipv6/udp.c	Fri Jul 11 01:25:29 2003
@@ -862,7 +862,7 @@
 			fl.oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			return -EDESTADDRREQ;
 
 		up->dport = inet->dport;
 		daddr = &np->daddr;
diff -Nru a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
--- a/net/irda/ircomm/ircomm_tty.c	Fri Jul 11 01:25:28 2003
+++ b/net/irda/ircomm/ircomm_tty.c	Fri Jul 11 01:25:28 2003
@@ -119,6 +119,7 @@
 
 	driver->driver_name     = "ircomm";
 	driver->name            = "ircomm";
+	driver->devfs_name      = "ircomm";
 	driver->major           = IRCOMM_TTY_MAJOR;
 	driver->minor_start     = IRCOMM_TTY_MINOR;
 	driver->type            = TTY_DRIVER_TYPE_SERIAL;
diff -Nru a/net/irda/irlap.c b/net/irda/irlap.c
--- a/net/irda/irlap.c	Fri Jul 11 01:25:30 2003
+++ b/net/irda/irlap.c	Fri Jul 11 01:25:30 2003
@@ -79,6 +79,13 @@
 
 int __init irlap_init(void)
 {
+	/* Check if the compiler did its job properly.
+	 * May happen on some ARM configuration, check with Russell King. */
+	ASSERT(sizeof(struct xid_frame) == 14, ;);
+	ASSERT(sizeof(struct test_frame) == 10, ;);
+	ASSERT(sizeof(struct ua_frame) == 10, ;);
+	ASSERT(sizeof(struct snrm_frame) == 11, ;);
+
 	/* Allocate master array */
 	irlap = hashbin_new(HB_LOCK);
 	if (irlap == NULL) {
diff -Nru a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
--- a/net/irda/irnet/irnet_irda.c	Fri Jul 11 01:25:28 2003
+++ b/net/irda/irnet/irnet_irda.c	Fri Jul 11 01:25:28 2003
@@ -953,7 +953,7 @@
 		      (void *) &irnet_server.s);
 #endif
 
-  DEXIT(IRDA_SERV_TRACE, " - self=0x%X\n", (unsigned int) &irnet_server.s);
+  DEXIT(IRDA_SERV_TRACE, " - self=0x%p\n", &irnet_server.s);
   return 0;
 }
 
diff -Nru a/net/irda/irttp.c b/net/irda/irttp.c
--- a/net/irda/irttp.c	Fri Jul 11 01:25:29 2003
+++ b/net/irda/irttp.c	Fri Jul 11 01:25:29 2003
@@ -1094,7 +1094,8 @@
 		 *  Check that the client has reserved enough space for
 		 *  headers
 		 */
-		ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER, return -1;);
+		ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,
+		       { dev_kfree_skb(tx_skb); return -1; } );
 	}
 
 	/* Initialize connection parameters */
@@ -1123,7 +1124,7 @@
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
 		ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),
-		       return -1;);
+		       { dev_kfree_skb(tx_skb); return -1; } );
 
 		/* Insert SAR parameters */
 		frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);
