# 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 # -------------------------------------------- # 03/07/10 jt@bougret.hpl.hp.com 1.1390 # [IrDA] struct check # # # o [FEATURE] Add struct size check for buggy compilers # -------------------------------------------- # 03/07/10 jt@bougret.hpl.hp.com 1.1391 # [IrDA] irtty leaks # # # o [CORRECT] fix two additional potential skb leaks in IrTTP. # -------------------------------------------- # 03/07/10 jt@bougret.hpl.hp.com 1.1392 # [IrDA] irnet cast # # # 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 # # # 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 # # o [CORRECT] Endianess fixes (for PPC and co.) # -------------------------------------------- # 03/07/10 jt@bougret.hpl.hp.com 1.1396 # [IrDA] nsc 39x support # # # 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 . # -------------------------------------------- # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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, . # -------------------------------------------- # 03/07/11 akpm@osdl.org 1.1420 # [PATCH] Bug fix in AIO initialization # # From: "Chen, Kenneth W" # # 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" # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 # # 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 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 @@ - - - - - Creating a device - - - - struct proc_dir_entry* proc_mknod - const char* name - mode_t mode - struct proc_dir_entry* parent - kdev_t rdev - - - - - Creates a device file name with mode - mode in the procfs directory - parent. The device file will work on - the device rdev, which can be generated - by using the MKDEV macro from - linux/kdev_t.h. The - mode parameter - must contain S_IFBLK - or S_IFCHR to create a device - node. Compare with userland mknod - --mode=mode - name rdev. - - - - - - Creating a directory 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: + (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 + + e.g., + root@server1 # nbd-server 1234 /dev/sdb1 + + (serves sdb1 partition on TCP port 1234) + + Then, on the local (client) system: + + nbd-client /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 . 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 #include #include -#include +#include #include +#include #include #include #include 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 -#include +#include +#include #include -#include /* for __init and __devinit */ #include #include +#include #include #include 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)]<iir)?regs->gr[R2(regs->iir)]:0)<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 #include +#include #include /* 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 + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * * 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 + . + + 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 - , 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 - , and the newer tcfs - package, available at . 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 - . - - 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 . + 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 + Copyright (C) 2003 Fruhwirth Clemens + + 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("loop blockdevice transferfunction adaptor / CryptoAPI"); +MODULE_AUTHOR("Herbert Valerio Riedel "); + +#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. + * 03-06-23 Cosmetic changes. + * 03-06-23 Enhance diagnostics support. + * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct. + * + * 03-06-24 Cleanup PARANOIA usage & code. * * 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 #include @@ -60,9 +64,27 @@ #include #include +/* Define PARANOIA in linux/nbd.h to turn on extra sanity checking */ #include +#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(¤t->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(¤t->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, ¤t->blocked, &info)); spin_unlock_irqrestore(¤t->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 + */ + +/* * 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 */ #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 * + * \par Acknowledgments: + * Dec 1999, Richard Henderson , 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 - * - * Acknowledgements: - * Dec 1999, Richard Henderson , 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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #include @@ -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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes + */ + +/* * ChangeLog: * 2001-11-16 Torsten Duwe * 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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + * + * 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 - * Gareth Hughes - */ - -/* - * 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 + * \author Daryll Strauss + * \author Gareth Hughes + */ + +/* * 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 - * Daryll Strauss - * Gareth Hughes */ #include "drmP.h" #include -/* 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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #include #include #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #include 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 /* For task queue support */ #include +/** 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 + * \author Gareth Hughes + * + * \par Acknowledgements: + * Matthew J Sottek 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 - * Gareth Hughes - * - * Acknowledgements: - * Matthew J Sottek 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//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 + */ + +/* * 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 */ #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 + */ + +/* * 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 */ #include 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 + */ + +/* * 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 - * */ #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 + * \author Gareth Hughes + */ + +/* * 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 - * Gareth Hughes */ #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 + */ + +/* * 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 */ + #include #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 /* for request_irq/free_irq */ #include #include -#include #include #include +#include #include #include +#include /* 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(<pc_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(<pc_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 @@ -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 @@ -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 + */ +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 #include #include -#include -#include #include #include 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 . 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 . 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 #include #include @@ -103,6 +211,7 @@ #include #include #include +#include #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 , Bill Ryder " -#define DRIVER_DESC "USB FTDI RS232 Converters Driver" +#define DRIVER_VERSION "v1.4.0" +#define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder , Kuba Ober " +#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 */ -UNUSUAL_DEV( 0x0451, 0x5409, 0x0001, 0x0001, - "Frontier Labs", - "Nex II Digital", - US_SC_SCSI, US_PR_BULK, NULL, 0), - /* Patch submitted by Philipp Friedrich */ 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(¤t->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(¤t->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<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<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 #include #include +#include #include #include @@ -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(¤t->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 - -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 #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 +#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 /* 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 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 + * 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 #include #include +#include #include #include #include @@ -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);