]> git.neil.brown.name Git - history.git/commitdiff
- Andries Brouwer: final isofs pieces. 2.4.0-test12pre4
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:40:27 +0000 (15:40 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:40:27 +0000 (15:40 -0500)
- Kai Germaschewski: ISDN
- play CD audio correctly, don't stop after 12 minutes.
- Anton Altaparmakov: disable NTFS mmap for now, as it doesn't work.
- Stephen Tweedie: fix inode dirty block handling
- Bill Hartner: reschedule_idle - prefer right cpu
- Johannes Erdfelt: USB updates
- Alan Cox: synchronize
- Richard Henderson: alpha updates and optimizations
- Geert Uytterhoeven: fbdev could be fooled into crashing fix
- Trond Myklebust: NFS filehandles in inode rather than dentry

155 files changed:
Documentation/SubmittingDrivers
Documentation/SubmittingPatches [new file with mode: 0644]
Documentation/filesystems/devfs/README
Documentation/initrd.txt
Documentation/sound/CMI8330
Makefile
arch/alpha/Makefile
arch/alpha/config.in
arch/alpha/kernel/pci.c
arch/alpha/lib/Makefile
arch/alpha/lib/ev6-clear_user.S [new file with mode: 0644]
arch/alpha/lib/ev6-copy_user.S [new file with mode: 0644]
arch/alpha/lib/ev6-csum_ipv6_magic.S [new file with mode: 0644]
arch/alpha/lib/ev6-divide.S [new file with mode: 0644]
arch/alpha/lib/ev6-strcpy.S [new file with mode: 0644]
arch/alpha/lib/ev6-strncpy.S [new file with mode: 0644]
arch/alpha/lib/ev6-strncpy_from_user.S [new file with mode: 0644]
arch/alpha/lib/ev67-strcat.S [new file with mode: 0644]
arch/alpha/lib/ev67-strchr.S [new file with mode: 0644]
arch/alpha/lib/ev67-strlen.S [new file with mode: 0644]
arch/alpha/lib/ev67-strlen_user.S [new file with mode: 0644]
arch/alpha/lib/ev67-strncat.S [new file with mode: 0644]
arch/arm/kernel/traps.c
arch/i386/kernel/irq.c
arch/i386/kernel/setup.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/traps.c
arch/ia64/kernel/irq.c
arch/m68k/mac/baboon.c
arch/m68k/mac/config.c
arch/m68k/mac/macints.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/mips/kernel/traps.c
arch/mips64/kernel/traps.c
arch/s390/kernel/traps.c
arch/sh/kernel/traps.c
drivers/block/ll_rw_blk.c
drivers/char/adbmouse.c
drivers/char/applicom.c
drivers/char/drm/mga_dma.c
drivers/char/drm/mga_drv.c
drivers/char/drm/mga_drv.h
drivers/char/mixcomwd.c
drivers/char/moxa.c
drivers/char/rio/host.h
drivers/char/riscom8.c
drivers/char/riscom8.h
drivers/char/sysrq.c
drivers/ide/ide-cd.c
drivers/isdn/hisax/avm_pci.c
drivers/isdn/hisax/bkm_a4t.c
drivers/isdn/hisax/bkm_a8.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/diva.c
drivers/isdn/hisax/gazel.c
drivers/isdn/hisax/niccy.c
drivers/isdn/hisax/nj_s.c
drivers/isdn/hisax/nj_u.c
drivers/isdn/hisax/sedlbauer.c
drivers/isdn/hisax/telespci.c
drivers/isdn/hisax/w6692.c
drivers/macintosh/mac_keyb.c
drivers/macintosh/via-macii.c
drivers/media/video/bttv-cards.c
drivers/media/video/bttv-driver.c
drivers/media/video/msp3400.c
drivers/media/video/tvaudio.c
drivers/mtd/Config.in
drivers/mtd/cfi_cmdset_0002.c
drivers/mtd/doc1000.c
drivers/mtd/ftl.c
drivers/mtd/pmc551.c
drivers/net/8139too.c
drivers/net/8390.c
drivers/net/appletalk/cops.c
drivers/net/appletalk/ipddp.c
drivers/net/appletalk/ltpc.c
drivers/net/daynaport.c
drivers/net/dummy.c
drivers/net/eql.c
drivers/net/hamradio/6pack.h
drivers/net/hamradio/mkiss.h
drivers/net/shaper.c
drivers/net/slip.c
drivers/net/slip.h
drivers/net/tulip/eeprom.c
drivers/net/tun.c
drivers/nubus/nubus.c
drivers/pci/pci.c
drivers/pci/setup-bus.c
drivers/sound/maestro.c
drivers/sound/sound_core.c
drivers/usb/bluetooth.c
drivers/usb/printer.c
drivers/usb/serial/usbserial.c
drivers/usb/uhci.c
drivers/usb/usb-uhci.c
drivers/video/aty128fb.c
drivers/video/atyfb.c
drivers/video/platinumfb.c
drivers/video/tdfxfb.c
fs/buffer.c
fs/ext2/ialloc.c
fs/ext2/namei.c
fs/inode.c
fs/isofs/dir.c
fs/isofs/inode.c
fs/isofs/namei.c
fs/isofs/rock.c
fs/isofs/util.c
fs/lockd/clntproc.c
fs/locks.c
fs/namei.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs3proc.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/symlink.c
fs/nfs/write.c
fs/ntfs/fs.c
include/asm-alpha/bitops.h
include/asm-alpha/byteorder.h
include/asm-alpha/fpu.h
include/asm-alpha/pgtable.h
include/asm-i386/hardirq.h
include/asm-i386/page.h
include/asm-ia64/hardirq.h
include/asm-sh/page.h
include/linux/agpgart.h
include/linux/ext2_fs.h
include/linux/fs.h
include/linux/kernel.h
include/linux/mtd/cfi.h
include/linux/mtd/pmc551.h
include/linux/nfs_fs.h
include/linux/nfs_fs_i.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/pci_ids.h
include/linux/signal.h
init/main.c
ipc/shm.c
kernel/exit.c
kernel/ksyms.c
kernel/sched.c
kernel/sysctl.c
mm/filemap.c
mm/vmscan.c
net/core/skbuff.c
net/ipx/af_ipx.c
scripts/kernel-doc

index 29c5973851e72e62f99f03b4cf33a17ca52aa02b..92a169ac2d0377006768b95e91d2e7fdb7e378e5 100644 (file)
@@ -6,13 +6,17 @@ Linux 2.2 and 2.4test kernel trees. Note that if you are interested in video
 card drivers you should probably talk to XFree86 (http://wwww.xfree86.org) 
 instead.
 
+Also read the Documentation/SubmittingPatches document.
+
+
 Allocating Device Numbers
 -------------------------
 
-Major and minor numbers for devices are allocated by the Linux assigned name
-and number authority (currently better known as H Peter Anvin). The
-site is http://www.lanana.org/. This also deals with allocating numbers for
-devices that are not going to be submitted to the mainstream kernel.
+Major and minor numbers for block and character devices are allocated
+by the Linux assigned name and number authority (currently better
+known as H Peter Anvin). The site is http://www.lanana.org/. This
+also deals with allocating numbers for devices that are not going to
+be submitted to the mainstream kernel.
 
 If you don't use assigned numbers then when you device is submitted it will
 get given an assigned number even if that is different from values you may
@@ -76,7 +80,8 @@ Control:      In general if there is active maintainance of a driver by
                the author then patches will be redirected to them unless 
                they are totally obvious and without need of checking.
                If you want to be the contact and update point for the
-               driver it is a good idea to state this in the comments.
+               driver it is a good idea to state this in the comments,
+               and include an entry in MAINTAINERS for your driver.
 
 What Criteria Do Not Determine Acceptance
 -----------------------------------------
@@ -97,7 +102,8 @@ Resources
 ---------
 
 Linux kernel master tree:
-       ftp.kernel.org:/pub/linux/kernel/...
+       ftp.??.kernel.org:/pub/linux/kernel/...
+       ?? == your country code, such as "us", "uk", "fr", etc.
 
 Linux kernel mailing list:             
        linux-kernel@vger.kernel.org
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
new file mode 100644 (file)
index 0000000..4f48032
--- /dev/null
@@ -0,0 +1,286 @@
+
+       How to Get Your Change Into the Linux Kernel
+               or
+       Care And Operation Of Your Linus Torvalds
+
+
+
+For a person or company who wishes to submit a change to the Linux
+kernel, the process can sometimes be daunting if you're not familiar
+with "the system."  This text is a collection of suggestions which
+can greatly increase the chances of your change being accepted.
+
+If you are submitting a driver, also read Documentation/SubmittingDrivers.
+
+
+
+--------------------------------------------
+SECTION 1 - CREATING AND SENDING YOUR CHANGE
+--------------------------------------------
+
+
+
+1) "diff -u"
+------------
+
+Use "diff -u" or "diff -urN" to create patches.
+
+All changes to the Linux kernel occur in the form of patches, as
+generated by diff(1).  When creating your patch, make sure to create it
+in "unified diff" format, as supplied by the '-u' argument to diff(1).
+Patches should be based in the root kernel source directory, not in
+any lower subdirectory.
+
+To create a patch for a single file, it is often sufficient to do:
+
+       SRCTREE= /devel/linux-2.4
+       MYFILE=  drivers/net/mydriver.c
+
+       cd $SRCTREE
+       cp $MYFILE $MYFILE.orig
+       vi $MYFILE      # make your change
+       diff -u $MYFILE.orig $MYFILE > /tmp/patch
+
+To create a patch for multiple files, you should unpack a "vanilla",
+or unmodified kernel source tree, and generate a diff against your
+own source tree.  For example:
+
+       MYSRC= /devel/linux-2.4
+
+       tar xvfz linux-2.4.0-test11.tar.gz
+       mv linux linux-vanilla
+       wget http://www.moses.uklinux.net/patches/dontdiff
+       diff -urN -X dontdiff linux-vanilla $MYSRC > /tmp/patch
+       rm -f dontdiff
+
+"dontdiff" is a list of files which are generated by the kernel during
+the build process, and should be ignored in any diff(1)-generated
+patch.  dontdiff is maintained by Tigran Aivazian <tigran@veritas.com>
+
+Make sure your patch does not include any extra files which do not
+belong in a patch submission.  Make sure to review your patch -after-
+generated it with diff(1), to ensure accuracy.
+
+
+2) Describe your changes.
+
+Describe the technical detail of the change(s) your patch includes.
+
+Be as specific as possible.  The WORST descriptions possible include
+things like "update driver X", "bug fix for driver X", or "this patch
+includes updates for subsystem X.  Please apply."
+
+If your description starts to get long, that's a sign that you probably
+need to split up your patch.  See #3, next.
+
+
+
+3) Separate your changes.
+
+Separate each logical change into its own patch.
+
+For example, if your changes include both bug fixes and performance
+enhancements for a single driver, separate those changes into two
+or more patches.  If your changes include an API update, and a new
+driver which uses that new API, separate those into two patches.
+
+On the other hand, if you make a single change to numerous files,
+group those changes into a single patch.  Thus a single logical change
+is contained within a single patch.
+
+If one patch depends on another patch in order for a change to be
+complete, that is OK.  Simply note "this patch depends on patch X"
+in your patch description.
+
+
+4) Select e-mail destination.
+
+Look through the MAINTAINERS file and the source code, and determine
+if your change applies to a specific subsystem of the kernel, with
+an assigned maintainer.  If so, e-mail that person.
+
+If no maintainer is listed, or the maintainer does not respond, send
+your patch to the primary Linux kernel developer's mailing list,
+linux-kernel@vger.kernel.org.  Most kernel developers monitor this
+e-mail list, and can comment on your changes.
+
+Linus Torvalds is the final arbiter of all changes accepted into the
+Linux kernel.  His e-mail address is torvalds@transmeta.com.  He gets
+a lot of e-mail, so typically you should do your best to -avoid- sending
+him e-mail.
+
+Patches which are bug fixes, are "obvious" changes, or similarly
+require little discussion should be sent or CC'd to Linus.  Patches
+which require discussion or do not have a clear advantage should
+usually be sent first to linux-kernel.  Only after the patch is
+discussed should the patch then be submitted to Linus.
+
+
+
+5) Select your CC (e-mail carbon copy) list.
+
+Unless you have a reason NOT to do so, CC linux-kernel@vger.kernel.org.
+
+Other kernel developers besides Linus need to be aware of your change,
+so that they may comment on it and offer code review and suggestions.
+linux-kernel is the primary Linux kernel developer mailing list.
+Other mailing lists are available for specific subsystems, such as
+USB, framebuffer devices, the VFS, the SCSI subsystem, etc.  See the
+MAINTAINERS file for a mailing list that relates specifically to
+your change.
+
+Even if the maintainer did not respond in step #4, make sure to ALWAYS
+copy the maintainer when you change their code.
+
+
+
+6) No MIME, no links, no compression, no attachments.  Just plain text.
+
+Linus and other kernel developers need to be able to read and comment
+on the changes you are submitting.  It is important for a kernel
+developer to be able to "quote" your changes, using standard e-mail
+tools, so that they may comment on specific portions of your code.
+
+For this reason, all patches should be submitting e-mail "inline".
+WARNING:  Be wary of your editor's word-wrap corrupting your patch,
+if you choose to cut-n-paste your patch.
+
+Do not attach the patch as a MIME attachment, compressed or not.
+Many popular e-mail applications will not always transmit a MIME
+attachment as plain text, making it impossible to comment on your
+code.  A MIME attachment also takes Linus a bit more time to process,
+decreasing the likelihood of your MIME-attached change being accepted.
+
+Exception:  If your mailer is mangling patches then someone may ask
+you to re-send them using MIME.
+
+
+
+7) E-mail size.
+
+When sending patches to Linus, always follow step #6.
+
+Large changes are not appropriate for mailing lists, and some
+maintainers.  If your patch, uncompressed, exceeds 40Kb in size,
+it is preferred that you store your patch on an Internet-accessible
+server, and provide instead a URL (link) pointing to your patch.
+
+
+
+8) Name your kernel version.
+
+It is important to note, either in the subject line or in the patch
+description, the kernel version to which this patch applies.
+
+If the patch does not apply cleanly to the latest kernel version,
+Linus will not apply it.
+
+
+
+9) Don't get discouraged.  Re-submit.
+
+After you have submitted your change, be patient and wait.  If Linus
+likes your change and applies it, it will appear in the next version
+of the kernel that he releases.
+
+However, if your change doesn't appear in the next version of the
+kernel, there could be any number of reasons.  It's YOUR job to
+narrow down those reasons, correct what was wrong, and submit your
+updated change.
+
+It is quite common for Linus to "drop" your patch without comment.
+That's the nature of the system.  If he drops your patch, it could be
+due to
+* Your patch did not apply cleanly to the latest kernel version
+* Your patch was not sufficiently discussed on linux-kernel.
+* A style issue (see section 2),
+* An e-mail formatting issue (re-read this section)
+* A technical problem with your change
+* He gets tons of e-mail, and yours got lost in the shuffle
+* You are being annoying (See Figure 1)
+
+When in doubt, solicit comments on linux-kernel mailing list.
+
+
+
+10) Include PATCH in the subject
+
+Due to high e-mail traffic to Linus, and to linux-kernel, it is common
+convention to prefix your subject line with [PATCH].  This lets Linus
+and other kernel developers more easily distinguish patches from other
+e-mail discussions.
+
+
+
+-----------------------------------
+SECTION 2 - HINTS, TIPS, AND TRICKS
+-----------------------------------
+
+This section lists many of the common "rules" associated with code
+submitted to the kernel.  There are always exceptions... but you must
+have a really good reason for doing so.  You could probably call this
+section Linus Computer Science 101.
+
+
+
+1) Read Documentation/CodingStyle
+
+Nuff said.  If your code deviates too much from this, it is likely
+to be rejected without further review, and without comment.
+
+
+
+2) #ifdefs are ugly
+
+Code cluttered with ifdefs is difficult to read and maintain.  Don't do
+it.  Instead, put your ifdefs in a header, and conditionally define
+'static inline' functions, or macros, which are used in the code.
+Let the compiler optimize away the "no-op" case.
+
+Simple example, of poor code:
+
+       dev = init_etherdev (NULL, 0);
+       if (!dev)
+               return -ENODEV;
+       #ifdef CONFIG_NET_FUNKINESS
+               init_funky_net(dev);
+       #endif
+
+Cleaned-up example:
+
+(in header)
+       #ifndef CONFIG_NET_FUNKINESS
+       static inline void init_funky_net (struct net_device *d) {}
+       #endif
+
+(in the code itself)
+       dev = init_etherdev (NULL, 0);
+       if (!dev)
+               return -ENODEV;
+       init_funky_net(dev);
+
+
+
+3) 'static inline' is better than a macro
+
+Static inline functions are greatly preferred over macros.
+They provide type safety, have no length limitations, no formatting
+limitations, and under gcc they are as cheap as macros.
+
+Macros should only be used for cases where a static inline is clearly
+suboptimal [there a few, isolated cases of this in fast paths],
+or where it is impossible to use a static inline function [such as
+string-izing].
+
+'static inline' is preferred over 'static __inline__', 'extern inline',
+and 'extern __inline__'.
+
+
+
+4) Don't over-design.
+
+Don't try to anticipate nebulous future cases which may or may not
+be useful:  "Make it as simple as you can, and no simpler"
+
+
+
index 6febda525427746c7ce8be8d0abdfb48750d4760..0c6fde510600d8bc5534d73e62dadbc03fc95e91 100644 (file)
@@ -529,7 +529,7 @@ yielded code size reductions and simplifications.
 If you want to construct a minimal chroot() gaol, the following
 command should suffice:
 
-mount -bind /dev/null /gaol/dev/null
+mount --bind /dev/null /gaol/dev/null
 
 
 Repeat for other device nodes you want to expose. Simple!
@@ -739,7 +739,7 @@ create the /dev-state directory
 add the following lines near the very beginning of your boot
 scripts:
 
-mount -bind /dev /dev-state
+mount --bind /dev /dev-state
 mount -t devfs none /dev
 devfsd /dev
 
index acc2315a451d6468ff1451fe846ca747c1d219ac..941f9ddd0fbc78ff6e69fbc96248423cfdebb7bf 100644 (file)
@@ -1,25 +1,28 @@
 Using the initial RAM disk (initrd)
 ===================================
 
-Written 1996 by Werner Almesberger <almesber@lrc.epfl.ch> and
-               Hans Lermen <lermen@elserv.ffm.fgan.de>
+Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch> and
+                     Hans Lermen <lermen@fgan.de>
 
 
-initrd adds the capability to load a RAM disk by the boot loader. This
-RAM disk can then be mounted as the root file system and programs can be
-run from it. Afterwards, a new root file system can be mounted from a
-different device. The previous root (from initrd) is then either moved
-to the directory /initrd or it is unmounted.
+initrd provides the capability to load a RAM disk by the boot loader.
+This RAM disk can then be mounted as the root file system and programs
+can be run from it. Afterwards, a new root file system can be mounted
+from a different device. The previous root (from initrd) is then moved
+to a directory and can be subsequently unmounted.
 
 initrd is mainly designed to allow system startup to occur in two phases,
 where the kernel comes up with a minimum set of compiled-in drivers, and
 where additional modules are loaded from initrd.
 
+This document gives a brief overview of the use of initrd. A more detailed
+discussion of the boot process can be found in [1].
+
 
 Operation
 ---------
 
-When using initrd, the system boots as follows:
+When using initrd, the system typically boots as follows:
 
   1) the boot loader loads the kernel and the initial RAM disk
   2) the kernel converts initrd into a "normal" RAM disk and
@@ -28,28 +31,17 @@ When using initrd, the system boots as follows:
   4) /linuxrc is executed (this can be any valid executable, including
      shell scripts; it is run with uid 0 and can do basically everything
      init can do)
-  5) when linuxrc terminates, the "real" root file system is mounted
-  6) if a directory /initrd exists, the initrd is moved there
-     otherwise, initrd is unmounted
+  5) linuxrc mounts the "real" root file system
+  6) linuxrc places the root file system at the root directory using the
+     pivot_root system call
   7) the usual boot sequence (e.g. invocation of /sbin/init) is performed
      on the root file system
+  8) the initrd file system is removed
 
-Note that moving initrd from / to /initrd does not involve unmounting it.
-It is therefore possible to leave processes running on initrd (or leave
-file systems mounted, but see below) during that procedure. However, if
-/initrd doesn't exist, initrd can only be unmounted if it is not used by
-anything. If it can't be unmounted, it will stay in memory.
-
-Also note that file systems mounted under initrd continue to be accessible,
-but their /proc/mounts entries are not updated. Also, if /initrd doesn't
-exist, initrd can't be unmounted and will "disappear" and take those file
-systems with it, thereby preventing them from being re-mounted. It is
-therefore strongly suggested to generally unmount all file systems (except
-of course for the root file system, but including /proc) before switching
-from initrd to the "normal" root file system.
-
-In order to deallocate the memory used for the initial RAM disk, you have
-to execute freeramdisk (see 'Resources' below) after unmounting /initrd.
+Note that changing the root directory does not involve unmounting it.
+It is therefore possible to leave processes running on initrd during that
+procedure. Also note that file systems mounted under initrd continue to
+be accessible.
 
 
 Boot command-line options
@@ -57,7 +49,7 @@ Boot command-line options
 
 initrd adds the following new options:
 
-  initrd=<path>    (LOADLIN only)
+  initrd=<path>    (e.g. LOADLIN)
 
     Loads the specified file as the initial RAM disk. When using LILO, you
     have to specify the RAM disk image file in /etc/lilo.conf, using the
@@ -71,40 +63,38 @@ initrd adds the following new options:
     in this case and doesn't necessarily have to be a file system image.
     This option is used mainly for debugging.
 
-    Note that /dev/initrd is read-only and that it can only be used once.
-    As soon as the last process has closed it, all data is freed and
-    /dev/initrd can't be opened any longer.
+    Note: /dev/initrd is read-only and it can only be used once. As soon
+    as the last process has closed it, all data is freed and /dev/initrd
+    can't be opened anymore.
 
-  root=/dev/ram
+  root=/dev/ram0   (without devfs)
+  root=/dev/rd/0   (with devfs)
 
-    initrd is mounted as root, and /linuxrc is started. If no /linuxrc
-    exists, the normal boot procedure is followed, with the RAM disk
-    still mounted as root. This option is mainly useful when booting from
-    a floppy disk. Compared to directly mounting an on-disk file system,
-    the intermediate step of going via initrd adds a little speed
-    advantage and it allows the use of a compressed file system.
-    Also, together with LOADLIN you may load the RAM disk directly from
-    CDROM or disk, hence having a floppyless boot from CD,
-    e.g.: E:\loadlin E:\bzImage root=/dev/ram initrd=E:\rdimage
+    initrd is mounted as root, and the normal boot procedure is followed,
+    with the RAM disk still mounted as root.
 
 
 Installation
 ------------
 
-First, the "normal" root file system has to be prepared as follows:
+First, a directory for the initrd file system has to be created on the
+"normal" root file system, e.g.
 
-# mknod /dev/initrd b 1 250 
-# chmod 400 /dev/initrd
 # mkdir /initrd
 
+The name is not relevant. More details can be found on the pivot_root(2)
+man page.
+
 If the root file system is created during the boot procedure (i.e. if
-you're creating an install floppy), the root file system creation
-procedure should perform these operations.
+you're building an install floppy), the root file system creation
+procedure should create the /initrd directory.
+
+If initrd will not be mounted in some cases, its content is still
+accessible if the following device has been created (note that this
+does not work if using devfs):
 
-Note that neither /dev/initrd nor /initrd are strictly required for
-correct operation of initrd, but it is a lot easier to experiment with
-initrd if you have them, and you may also want to use /initrd to pass
-data to the "real" system.
+# mknod /dev/initrd b 1 250 
+# chmod 400 /dev/initrd
 
 Second, the kernel has to be compiled with RAM disk support and with
 support for the initial RAM disk enabled. Also, at least all components
@@ -112,100 +102,148 @@ needed to execute programs from initrd (e.g. executable format and file
 system) must be compiled into the kernel.
 
 Third, you have to create the RAM disk image. This is done by creating a
-file system on a block device and then by copying files to it as needed.
-With recent kernels, at least three types of devices are suitable for
-that:
+file system on a block device, copying files to it as needed, and then
+copying the content of the block device to the initrd file. With recent
+kernels, at least three types of devices are suitable for that:
 
  - a floppy disk (works everywhere but it's painfully slow)
  - a RAM disk (fast, but allocates physical memory)
- - a loopback device (the most elegant solution, but currently requires a
-   modified mount)
+ - a loopback device (the most elegant solution)
 
-We'll describe the RAM disk method:
+We'll describe the loopback device method:
 
- 1) make sure you have a RAM disk device /dev/ram (block, major 1, minor 0)
+ 1) make sure loopback block devices are configured into the kernel
  2) create an empty file system of the appropriate size, e.g.
-    # mke2fs -m0 /dev/ram 300   
+    # dd if=/dev/zero of=initrd bs=300k count=1
+    # mke2fs -F -m0 initrd
     (if space is critical, you may want to use the Minix FS instead of Ext2)
- 3) mount the file system on an appropriate directory, e.g.
-    # mount -t ext2 /dev/ram /mnt
- 4) create the console device:
+ 3) mount the file system, e.g.
+    # mount -t ext2 -o loop initrd /mnt
+ 4) create the console device (not necessary if using devfs, but it can't
+    hurt to do it anyway):
     # mkdir /mnt/dev
-    # mknod /mnt/dev/tty1 c 4 1
+    # mknod /mnt/dev/console c 5 1
  5) copy all the files that are needed to properly use the initrd
     environment. Don't forget the most important file, /linuxrc
     Note that /linuxrc's permissions must include "x" (execute).
- 6) unmount the RAM disk
-    # umount /dev/ram
- 7) copy the image to a file
-    # dd if=/dev/ram bs=1k count=300 of=/boot/initrd
- 8) deallocate the RAM disk
-    # freeramdisk /dev/ram
-
-For experimenting with initrd, you may want to take a rescue floppy (e.g.
-rescue.gz from Slackware) and only add a symbolic link from /linuxrc to
-/bin/sh, e.g.
-
- # gunzip <rescue.gz >/dev/ram
- # mount -t minix /dev/ram /mnt
- # ln -s /bin/sh /mnt/linuxrc
- # umount /dev/ram
- # dd if=/dev/ram bs=1k count=1440 of=/boot/initrd
- # freeramdisk /dev/ram
-
-Finally, you have to boot the kernel and load initrd. Currently,
-preliminary versions of LOADLIN 1.6 and LILO 18 support initrd (see
-below for where to get them). With LOADLIN, you simply execute
+ 6) correct operation the initrd environment can frequently be tested
+    even without rebooting with the command
+    # chroot /mnt /linuxrc
+    This is of course limited to initrds that do not interfere with the
+    general system state (e.g. by reconfiguring network interfaces,
+    overwriting mounted devices, trying to start already running demons,
+    etc. Note however that it is usually possible to use pivot_root in
+    such a chroot'ed initrd environment.)
+ 7) unmount the file system
+    # umount /mnt
+ 8) the initrd is now in the file "initrd". Optionally, it can now be
+    compressed
+    # gzip -9 initrd
+
+For experimenting with initrd, you may want to take a rescue floppy and
+only add a symbolic link from /linuxrc to /bin/sh. Alternatively, you
+can try the experimental newlib environment [2] to create a small
+initrd.
+
+Finally, you have to boot the kernel and load initrd. Almost all Linux
+boot loaders support initrd. Since the boot process is still compatible
+with an older mechanism, the following boot command line parameters
+have to be given:
+
+  root=/dev/ram0 init=/linuxrc rw
+
+if not using devfs, or
+
+  root=/dev/rd/0 init=/linuxrc rw
+
+if using devfs. (rw is only necessary if writing to the initrd file
+system.)
+
+With LOADLIN, you simply execute
 
      LOADLIN <kernel> initrd=<disk_image>
-e.g. LOADLIN C:\LINUX\VMLINUZ initrd=C:\LINUX\INITRD
+e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0
+       init=/linuxrc rw
 
 With LILO, you add the option INITRD=<path> to either the global section
-or to the section of the respective kernel in /etc/lilo.conf, e.g.
+or to the section of the respective kernel in /etc/lilo.conf, and pass
+the options using APPEND, e.g.
 
-  image = /vmlinuz
-    initrd = /boot/initrd
+  image = /bzImage
+    initrd = /boot/initrd.gz
+    append = "root=/dev/ram0 init=/linuxrc rw"
 
 and run /sbin/lilo
 
+For other boot loaders, please refer to the respective documentation.
+
 Now you can boot and enjoy using initrd.
 
 
-Setting the root device
------------------------
+Changing the root device
+------------------------
 
-By default, the standard settings in the kernel are used for the root
-device, i.e. the default compiled in or set with rdev, or what was passed
-with root=xxx on the command line, or, with LILO, what was specified in
-/etc/lilo.conf It is also possible to use initrd with an NFS-mounted
-root; you have to use the nfs_root_name and nfs_root_addrs boot options
-for this.
+When finished with its duties, linuxrc typically changes the root device
+and proceeds with starting the Linux system on the "real" root device.
 
-It is also possible to change the root device from within the initrd
-environment. In order to do so, /proc has to be mounted. Then, the
-following files are available:
+The procedure involves the following steps:
+ - mounting the new root file system
+ - turning it into the root file system
+ - removing all accesses to the old (initrd) root file system
+ - unmounting the initrd file system and de-allocating the RAM disk
 
-  /proc/sys/kernel/real-root-dev
-  /proc/sys/kernel/nfs-root-name
-  /proc/sys/kernel/nfs-root-addrs
+Mounting the new root file system is easy: it just needs to be mounted on
+a directory under the current root. Example:
 
-real-root-dev can be changed by writing the number of the new root FS
-device to it, e.g.
+# mkdir /new-root
+# mount -o ro /dev/hda1 /new-root
 
-  # echo 0x301 >/proc/sys/kernel/real-root-dev
+The root change is accomplished with the pivot_root system call, which
+is also available via the pivot_root utility (see pivot_root(8) man
+page; pivot_root is distributed with util-linux version 2.10h or higher
+[3]). pivot_root moves the current root to a directory under the new
+root, and puts the new root at its place. The directory for the old root
+must exist before calling pivot_root. Example:
+
+# cd /new-root
+# mkdir initrd
+# pivot_root . initrd
+
+Now, the linuxrc process may still access the old root via its
+executable, shared libraries, standard input/output/error, and its
+current root directory. All these references are dropped by the
+following command:
+
+# exec chroot . what-follows <dev/console >dev/console 2>&1
+
+Where what-follows is a program under the new root, e.g. /sbin/init
+If the new root file system will be used with devfs and has no valid
+/dev directory, devfs must be mounted before invoking chroot in order to
+provide /dev/console.
 
-for /dev/hda1. When using an NFS-mounted root, nfs-root-name and
-nfs-root-addrs have to be set accordingly and then real-root-dev has to
-be set to 0xff, e.g.
+Note: implementation details of pivot_root may change with time. In order
+to ensure compatibility, the following points should be observed:
 
-  # echo /var/nfsroot >/proc/sys/kernel/nfs-root-name
-  # echo 193.8.232.2:193.8.232.7::255.255.255.0:idefix \
-    >/proc/sys/kernel/nfs-root-addrs
-  # echo 255 >/proc/sys/kernel/real-root-dev
+ - before calling pivot_root, the current directory of the invoking
+   process should point to the new root directory
+ - use . as the first argument, and the _relative_ path of the directory
+   for the old root as the second argument
+ - a chroot program must be available under the old and the new root
+ - chroot to the new root afterwards
+ - use relative paths for dev/console in the exec command
 
-If the root device is set to the RAM disk, the root file system is not
-moved to /initrd, but the boot procedure is simply continued by starting
-init on the initial RAM disk.
+Now, the initrd can be unmounted and the memory allocated by the RAM
+disk can be freed:
+
+# umount /initrd
+# blockdev --flushbufs /dev/ram0    # /dev/rd/0 if using devfs
+
+It is also possible to use initrd with an NFS-mounted root, see the
+pivot_root(8) man page for details.
+
+Note: if linuxrc or any program exec'ed from it terminates for some
+reason, the old change_root mechanism is invoked (see section "Obsolete
+root change mechanism").
 
 
 Usage scenarios
@@ -215,32 +253,30 @@ The main motivation for implementing initrd was to allow for modular
 kernel configuration at system installation. The procedure would work
 as follows:
 
-  1) systems boots from floppy or other media with a minimal kernel
-     (e.g. support for RAM disks, initrd, a.out, and the ext2 FS) and
+  1) system boots from floppy or other media with a minimal kernel
+     (e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and
      loads initrd
   2) /linuxrc determines what is needed to (1) mount the "real" root FS
      (i.e. device type, device drivers, file system) and (2) the
      distribution media (e.g. CD-ROM, network, tape, ...). This can be
      done by asking the user, by auto-probing, or by using a hybrid
      approach.
-  3) /linuxrc loads the necessary modules
+  3) /linuxrc loads the necessary kernel modules
   4) /linuxrc creates and populates the root file system (this doesn't
      have to be a very usable system yet)
-  5) /linuxrc unmounts the root file system and possibly any other file
-     systems it has mounted, sets /proc/sys/kernel/..., and terminates
-  6) the root file system is mounted
-  7) now that we're sure that the file system is accessible and intact,
-     the boot loader can be installed
-  8) the boot loader is configured to load an initrd with the set of
+  5) /linuxrc invokes pivot_root to change the root file system and
+     execs - via chroot - a program that continues the installation
+  6) the boot loader is installed
+  7) the boot loader is configured to load an initrd with the set of
      modules that was used to bring up the system (e.g. /initrd can be
      modified, then unmounted, and finally, the image is written from
-     /dev/ram to a file)
-  9) now the system is bootable and additional installation tasks can be
+     /dev/ram0 or /dev/rd/0 to a file)
+  8) now the system is bootable and additional installation tasks can be
      performed
 
 The key role of initrd here is to re-use the configuration data during
 normal system operation without requiring the use of a bloated "generic"
-kernel or re-compilation or re-linking of the kernel.
+kernel or re-compiling or re-linking the kernel.
 
 A second scenario is for installations where Linux runs on systems with
 different hardware configurations in a single administrative domain. In
@@ -252,35 +288,53 @@ read by it would have to be different.
 
 A third scenario are more convenient recovery disks, because information
 like the location of the root FS partition doesn't have to be provided at
-boot time, but the system loaded from initrd can use a user-friendly
+boot time, but the system loaded from initrd can invoke a user-friendly
 dialog and it can also perform some sanity checks (or even some form of
 auto-detection).
 
-Last not least, CDROM distributors may use it for better installation from CD,
-either using a LILO boot floppy and bootstrapping a bigger RAM disk via
-initrd from CD, or using LOADLIN to directly load the RAM disk from CD
-without need of floppies.
+Last not least, CD-ROM distributors may use it for better installation
+from CD, e.g. by using a boot floppy and bootstrapping a bigger RAM disk
+via initrd from CD; or by booting via a loader like LOADLIN or directly
+from the CD-ROM, and loading the RAM disk from CD without need of
+floppies. 
 
-Since initrd is a fairly generic mechanism, it is likely that additional
-uses will be found.
 
+Obsolete root change mechanism
+------------------------------
 
-Resources
----------
+The following mechanism was used before the introduction of pivot_root.
+Current kernels still support it, but you should _not_ rely on its
+continued availability.
+
+It works by mounting the "real" root device (i.e. the one set with rdev
+in the kernel image or with root=... at the boot command line) as the
+root file system when linuxrc exits. The initrd file system is then
+unmounted, or, if it is still busy, moved to a directory /initrd, if
+such a directory exists on the new root file system.
+
+In order to use this mechanism, you do not have to specify the boot
+command options root, init, or rw. (If specified, they will affect
+the real root file system, not the initrd environment.)
+  
+If /proc is mounted, the "real" root device can be changed from within
+linuxrc by writing the number of the new root FS device to the special
+file /proc/sys/kernel/real-root-dev, e.g.
+
+  # echo 0x301 >/proc/sys/kernel/real-root-dev
+
+Note that the mechanism is incompatible with NFS and similar file
+systems.
 
-The bzImage+initrd patch (bzImage is an extension to load kernels directly
-above 1 MB, which allows kernels sizes of up to approximately 2 MB) can be
-found at
-ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/bzImage+initrd-1.3.71.patch.gz
-and
-ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/bzImage+initrd-1.3.71.patch.gz
+This old, deprecated mechanism is commonly called "change_root", while
+the new, supported mechanism is called "pivot_root".
 
-A preliminary version of LOADLIN 1.6 is available on
-ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/loadlin-1.6-pre8-bin.tgz
 
-A preliminary version of LILO 18 is available on
-ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/lilo.18dev3.tar.gz
+Resources
+---------
 
-A very simple example for building an image for initrd, also including
-the program 'freeramdisk', can be found on
-ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/initrd-example.tgz
+[1] Almesberger, Werner; "Booting Linux: The History and the Future"
+    ftp://icaftp.epfl.ch/pub/people/almesber/booting/bootinglinux-current.ps.gz
+[2] newlib package (experimental), with initrd example
+    ftp://icaftp.epfl.ch/pub/people/almesber/misc/newlib-linux/
+[3] Brouwer, Andries; "util-linux: Miscellaneous utilities for Linux"
+    ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/
index 8885d3307bc873431263224f39d848b6d2357287..28779988406a5d07082aa5cb337de878376523e4 100644 (file)
@@ -57,7 +57,7 @@ How to enable CMI 8330 (SOUNDPRO) soundchip on Linux
 ------------------------------------------
 Stefan Laudat <Stefan.Laudat@asit.ro>
 
-[Note: The CMI 8338 is unrelated and right now unsupported]
+[Note: The CMI 8338 is unrelated and is supported by cmpci.o]
 
        
        In order to use CMI8330 under Linux  you just have to use a proper isapnp.conf, a good isapnp and a little bit of patience.  I use isapnp 1.17, but
index de12c264b1f30940f3e449e9810a22e09e95d526..00615a37aef398d646bbbc134567d9b1cd561803 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -206,7 +206,6 @@ MRPROPER_FILES = \
        drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h \
        drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h \
        drivers/net/hamradio/soundmodem/gentbl \
-       drivers/char/hfmodem/gentbl drivers/char/hfmodem/tables.h \
        drivers/sound/*_boot.h drivers/sound/.*.boot \
        drivers/sound/msndinit.c \
        drivers/sound/msndperm.c \
index 44ae94a99b4311d6fcba85e0d9a26e130e46759a..c07b2576491e688878cd658de6d65e3ad4ddc5c1 100644 (file)
@@ -36,6 +36,10 @@ ifeq ($(have_mcpu),y)
     CFLAGS := $(CFLAGS) -mcpu=ev5
     mcpu_done := y
   endif
+  ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy)
+    CFLAGS := $(CFLAGS) -mcpu=pca56
+    mcpu_done := y
+  endif
   ifeq ($(mcpu_done)$(CONFIG_ALPHA_PYXIS),ny)
     CFLAGS := $(CFLAGS) -mcpu=ev56
     mcpu_done := y
@@ -48,14 +52,14 @@ ifeq ($(have_mcpu),y)
     endif
     mcpu_done := y
   endif
-  ifeq ($(mcpu_done)$(CONFIG_ALPHA_NAUTILUS)$(have_mcpu_ev67),nyy)
-    CFLAGS := $(CFLAGS) -mcpu=ev67
-    mcpu_done := y
-  endif
   ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny)
     CFLAGS := $(CFLAGS) -mcpu=ev4
     mcpu_done := y
   endif
+  ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy)
+    CFLAGS := $(CFLAGS) -mcpu=ev67
+    mcpu_done := y
+  endif
   ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny)
     ifeq ($(have_mcpu_ev6),y)
       CFLAGS := $(CFLAGS) -mcpu=ev6
index da5c361c9a7a4b9f5484db4e4ca5d4ad2ff28822..649047e6659ec5922eb0a2e8b2a47ef88db8fdbf 100644 (file)
@@ -56,7 +56,7 @@ choice 'Alpha system type' \
         Wildfire               CONFIG_ALPHA_WILDFIRE" Generic
 
 # clear all implied options (don't want default values for those):
-unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
+unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 CONFIG_ALPHA_EV67
 unset CONFIG_ALPHA_EISA
 unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
 unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS
@@ -138,16 +138,12 @@ if [ "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_EIGER" = "y" ]
 then
        define_bool CONFIG_ALPHA_EV6 y
        define_bool CONFIG_ALPHA_TSUNAMI y
+       bool 'EV67 (or later) CPU (speed > 600MHz)?' CONFIG_ALPHA_EV67
 fi
-if [ "$CONFIG_ALPHA_WILDFIRE" = "y" ]
+if [ "$CONFIG_ALPHA_WILDFIRE" = "y" -o "$CONFIG_ALPHA_TITAN" = "y" ]
 then
-       define_bool CONFIG_PCI y
-       define_bool CONFIG_ALPHA_EV6 y
-fi
-if [ "$CONFIG_ALPHA_TITAN" = "y" ]
-then
-        define_bool CONFIG_PCI y
         define_bool CONFIG_ALPHA_EV6 y
+       define_bool CONFIG_ALPHA_EV67 y
 fi
 if [ "$CONFIG_ALPHA_RAWHIDE" = "y" ]
 then
@@ -165,8 +161,9 @@ then
 fi
 if [ "$CONFIG_ALPHA_NAUTILUS" = "y" ]
 then
-       define_bool CONFIG_ALPHA_EV6 y
        define_bool CONFIG_ALPHA_IRONGATE y
+       define_bool CONFIG_ALPHA_EV6 y
+       define_bool CONFIG_ALPHA_EV67 y
 fi
 
 if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
index b06c6bd806827159d790e227d09e1bf7973b26f1..e17cbcd7089235636bc37352482cac4794abbfa1 100644 (file)
@@ -56,13 +56,13 @@ struct pci_controler *pci_isa_hose;
 static void __init
 quirk_eisa_bridge(struct pci_dev *dev)
 {
-       dev->class = PCI_CLASS_BRIDGE_EISA;
+       dev->class = PCI_CLASS_BRIDGE_EISA << 8;
 }
 
 static void __init
 quirk_isa_bridge(struct pci_dev *dev)
 {
-       dev->class = PCI_CLASS_BRIDGE_ISA;
+       dev->class = PCI_CLASS_BRIDGE_ISA << 8;
 }
 
 static void __init
@@ -282,7 +282,7 @@ pcibios_fixup_bus(struct pci_bus *bus)
        }
 }
 
-void __init
+void
 pcibios_update_resource(struct pci_dev *dev, struct resource *root,
                        struct resource *res, int resource)
 {
index 913331a955254487ebe063a67024a9bc42f417e6..5de58a6ad2addcccb4bf1746d756231b1af2f162 100644 (file)
@@ -3,32 +3,45 @@
 #
 
 .S.s:
-       $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+       $(CPP) -D__ASSEMBLY__ $(CFLAGS) -o $*.s $<
 .S.o:
-       $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+       $(CC) -D__ASSEMBLY__ $(CFLAGS) -c -o $*.o $<
+
+# Many of these routines have implementations tuned for ev6.
+# Choose them iff we're targeting ev6 specifically.
+ev6 :=
+ifeq ($(CONFIG_ALPHA_EV6),y)
+  ev6 := ev6-
+endif
+
+# Several make use of the cttz instruction introduced in ev67.
+ev67 :=
+ifeq ($(CONFIG_ALPHA_EV67),y)
+  ev67 := ev67-
+endif
 
 OBJS  = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
-       checksum.o csum_partial_copy.o strlen.o \
-       strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
-       strchr.o strrchr.o memchr.o \
-       copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
-       csum_ipv6_magic.o strcasecmp.o fpreg.o \
+       checksum.o csum_partial_copy.o $(ev67)strlen.o \
+       $(ev67)strcat.o $(ev6)strcpy.o $(ev67)strncat.o $(ev6)strncpy.o \
+       stxcpy.o stxncpy.o $(ev67)strchr.o strrchr.o memchr.o \
+       $(ev6)copy_user.o $(ev6)clear_user.o $(ev6)strncpy_from_user.o \
+       $(ev67)strlen_user.o $(ev6)csum_ipv6_magic.o strcasecmp.o fpreg.o \
        callback_srm.o srm_puts.o srm_printk.o
 
 lib.a: $(OBJS)
        $(AR) rcs lib.a $(OBJS)
 
-__divqu.o: divide.S
-       $(CC) $(AFLAGS) -DDIV -c -o __divqu.o divide.S
+__divqu.o: $(ev6)divide.S
+       $(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S
 
-__remqu.o: divide.S
-       $(CC) $(AFLAGS) -DREM -c -o __remqu.o divide.S
+__remqu.o: $(ev6)divide.S
+       $(CC) $(AFLAGS) -DREM -c -o __remqu.o $(ev6)divide.S
 
-__divlu.o: divide.S
-       $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o divide.S
+__divlu.o: $(ev6)divide.S
+       $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o $(ev6)divide.S
 
-__remlu.o: divide.S
-       $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o divide.S
+__remlu.o: $(ev6)divide.S
+       $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S
 
 dep:
 
diff --git a/arch/alpha/lib/ev6-clear_user.S b/arch/alpha/lib/ev6-clear_user.S
new file mode 100644 (file)
index 0000000..090f060
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * arch/alpha/lib/ev6-clear_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Zero user space, handling exceptions as we go.
+ *
+ * We have to make sure that $0 is always up-to-date and contains the
+ * right "bytes left to zero" value (and that it is updated only _after_
+ * a successful copy).  There is also some rather minor exception setup
+ * stuff.
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics
+ * are different:
+ *
+ * Inputs:
+ *     length in $0
+ *     destination address in $6
+ *     exception pointer in $7
+ *     return address in $28 (exceptions expect it there)
+ *
+ * Outputs:
+ *     bytes left to copy in $0
+ *
+ * Clobbers:
+ *     $1,$2,$3,$4,$5,$6
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
+ * From perusing the source code context where this routine is called, it is
+ * a fair assumption that significant fractions of entire pages are zeroed, so
+ * it's going to be worth the effort to hand-unroll a big loop, and use wh64.
+ * ASSUMPTION:
+ *     The believed purpose of only updating $0 after a store is that a signal
+ *     may come along during the execution of this chunk of code, and we don't
+ *     want to leave a hole (and we also want to avoid repeating lots of work)
+ */
+
+/* Allow an exception for an insn; exit if we get one.  */
+#define EX(x,y...)                     \
+       99: x,##y;                      \
+       .section __ex_table,"a";        \
+       .gprel32 99b;                   \
+       lda $31, $exception-99b($31);   \
+       .previous
+
+       .set noat
+       .set noreorder
+       .align 4
+
+       .globl __do_clear_user
+       .ent __do_clear_user
+       .frame  $30, 0, $28
+       .prologue 0
+
+                               # Pipeline info : Slotting & Comments
+__do_clear_user:
+       ldgp    $29,0($27)      # we do exceptions -- we need the gp.
+                               # Macro instruction becomes ldah/lda
+                               # .. .. E  E    :
+       and     $6, 7, $4       # .. E  .. ..   : find dest head misalignment
+       beq     $0, $zerolength # U  .. .. ..   :  U L U L
+
+       addq    $0, $4, $1      # .. .. .. E    : bias counter
+       and     $1, 7, $2       # .. .. E  ..   : number of misaligned bytes in tail
+# Note - we never actually use $2, so this is a moot computation
+# and we can rewrite this later...
+       srl     $1, 3, $1       # .. E  .. ..   : number of quadwords to clear
+       beq     $4, $headalign  # U  .. .. ..   : U L U L
+
+/*
+ * Head is not aligned.  Write (8 - $4) bytes to head of destination
+ * This means $6 is known to be misaligned
+ */
+       EX( ldq_u $5, 0($6) )   # .. .. .. L    : load dst word to mask back in
+       beq     $1, $onebyte    # .. .. U  ..   : sub-word store?
+       mskql   $5, $6, $5      # .. U  .. ..   : take care of misaligned head
+       addq    $6, 8, $6       # E  .. .. ..   : L U U L
+
+       EX( stq_u $5, -8($6) )  # .. .. .. L    :
+       subq    $1, 1, $1       # .. .. E  ..   :
+       addq    $0, $4, $0      # .. E  .. ..   : bytes left -= 8 - misalignment
+       subq    $0, 8, $0       # E  .. .. ..   : U L U L
+
+       .align  4
+/*
+ * (The .align directive ought to be a moot point)
+ * values upon initial entry to the loop
+ * $1 is number of quadwords to clear (zero is a valid value)
+ * $2 is number of trailing bytes (0..7) ($2 never used...)
+ * $6 is known to be aligned 0mod8
+ */
+$headalign:
+       subq    $1, 16, $4      # .. .. .. E    : If < 16, we can not use the huge loop
+       and     $6, 0x3f, $2    # .. .. E  ..   : Forward work for huge loop
+       subq    $2, 0x40, $3    # .. E  .. ..   : bias counter (huge loop)
+       blt     $4, $trailquad  # U  .. .. ..   : U L U L
+
+/*
+ * We know that we're going to do at least 16 quads, which means we are
+ * going to be able to use the large block clear loop at least once.
+ * Figure out how many quads we need to clear before we are 0mod64 aligned
+ * so we can use the wh64 instruction.
+ */
+
+       nop                     # .. .. .. E
+       nop                     # .. .. E  ..
+       nop                     # .. E  .. ..
+       beq     $3, $bigalign   # U  .. .. ..   : U L U L : Aligned 0mod64
+
+$alignmod64:
+       EX( stq_u $31, 0($6) )  # .. .. .. L
+       addq    $3, 8, $3       # .. .. E  ..
+       subq    $0, 8, $0       # .. E  .. ..
+       nop                     # E  .. .. ..   : U L U L
+
+       nop                     # .. .. .. E
+       subq    $1, 1, $1       # .. .. E  ..
+       addq    $6, 8, $6       # .. E  .. ..
+       blt     $3, $alignmod64 # U  .. .. ..   : U L U L
+
+$bigalign:
+/*
+ * $0 is the number of bytes left
+ * $1 is the number of quads left
+ * $6 is aligned 0mod64
+ * we know that we'll be taking a minimum of one trip through
+ * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
+ * We are _not_ going to update $0 after every single store.  That
+ * would be silly, because there will be cross-cluster dependencies
+ * no matter how the code is scheduled.  By doing it in slightly
+ * staggered fashion, we can still do this loop in 5 fetches
+ * The worse case will be doing two extra quads in some future execution,
+ * in the event of an interrupted clear.
+ * Assumes the wh64 needs to be for 2 trips through the loop in the future
+ * The wh64 is issued on for the starting destination address for trip +2
+ * through the loop, and if there are less than two trips left, the target
+ * address will be for the current trip.
+ */
+       nop                     # E :
+       nop                     # E :
+       nop                     # E :
+       bis     $6,$6,$3        # E : U L U L : Initial wh64 address is dest
+       /* This might actually help for the current trip... */
+
+$do_wh64:
+       wh64    ($3)            # .. .. .. L1   : memory subsystem hint
+       subq    $1, 16, $4      # .. .. E  ..   : Forward calculation - repeat the loop?
+       EX( stq_u $31, 0($6) )  # .. L  .. ..
+       subq    $0, 8, $0       # E  .. .. ..   : U L U L
+
+       addq    $6, 128, $3     # E : Target address of wh64
+       EX( stq_u $31, 8($6) )  # L :
+       EX( stq_u $31, 16($6) ) # L :
+       subq    $0, 16, $0      # E : U L L U
+
+       nop                     # E :
+       EX( stq_u $31, 24($6) ) # L :
+       EX( stq_u $31, 32($6) ) # L :
+       subq    $0, 168, $5     # E : U L L U : two trips through the loop left?
+       /* 168 = 192 - 24, since we've already completed some stores */
+
+       subq    $0, 16, $0      # E :
+       EX( stq_u $31, 40($6) ) # L :
+       EX( stq_u $31, 48($6) ) # L :
+       cmovlt  $5, $6, $3      # E : U L L U : Latency 2, extra mapping cycle
+
+       subq    $1, 8, $1       # E :
+       subq    $0, 16, $0      # E :
+       EX( stq_u $31, 56($6) ) # L :
+       nop                     # E : U L U L
+
+       nop                     # E :
+       subq    $0, 8, $0       # E :
+       addq    $6, 64, $6      # E :
+       bge     $4, $do_wh64    # U : U L U L
+
+$trailquad:
+       # zero to 16 quadwords left to store, plus any trailing bytes
+       # $1 is the number of quadwords left to go.
+       # 
+       nop                     # .. .. .. E
+       nop                     # .. .. E  ..
+       nop                     # .. E  .. ..
+       beq     $1, $trailbytes # U  .. .. ..   : U L U L : Only 0..7 bytes to go
+
+$onequad:
+       EX( stq_u $31, 0($6) )  # .. .. .. L
+       subq    $1, 1, $1       # .. .. E  ..
+       subq    $0, 8, $0       # .. E  .. ..
+       nop                     # E  .. .. ..   : U L U L
+
+       nop                     # .. .. .. E
+       nop                     # .. .. E  ..
+       addq    $6, 8, $6       # .. E  .. ..
+       bgt     $1, $onequad    # U  .. .. ..   : U L U L
+
+       # We have an unknown number of bytes left to go.
+$trailbytes:
+       nop                     # .. .. .. E
+       nop                     # .. .. E  ..
+       nop                     # .. E  .. ..
+       beq     $0, $zerolength # U  .. .. ..   : U L U L
+
+       # $0 contains the number of bytes left to copy (0..31)
+       # so we will use $0 as the loop counter
+       # We know for a fact that $0 > 0 zero due to previous context
+$onebyte:
+       EX( stb $31, 0($6) )    # .. .. .. L
+       subq    $0, 1, $0       # .. .. E  ..   :
+       addq    $6, 1, $6       # .. E  .. ..   :
+       bgt     $0, $onebyte    # U  .. .. ..   : U L U L
+
+$zerolength:
+$exception:                    # Destination for exception recovery(?)
+       nop                     # .. .. .. E    :
+       nop                     # .. .. E  ..   :
+       nop                     # .. E  .. ..   :
+       ret     $31, ($28), 1   # L0 .. .. ..   : L U L U
+       .end __do_clear_user
+
diff --git a/arch/alpha/lib/ev6-copy_user.S b/arch/alpha/lib/ev6-copy_user.S
new file mode 100644 (file)
index 0000000..a30f732
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * arch/alpha/lib/ev6-copy_user.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Copy to/from user space, handling exceptions as we go..  This
+ * isn't exactly pretty.
+ *
+ * This is essentially the same as "memcpy()", but with a few twists.
+ * Notably, we have to make sure that $0 is always up-to-date and
+ * contains the right "bytes left to copy" value (and that it is updated
+ * only _after_ a successful copy). There is also some rather minor
+ * exception setup stuff..
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics are
+ * different:
+ *
+ * Inputs:
+ *     length in $0
+ *     destination address in $6
+ *     source address in $7
+ *     return address in $28
+ *
+ * Outputs:
+ *     bytes left to copy in $0
+ *
+ * Clobbers:
+ *     $1,$2,$3,$4,$5,$6,$7
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ */
+
+/* Allow an exception for an insn; exit if we get one.  */
+#define EXI(x,y...)                    \
+       99: x,##y;                      \
+       .section __ex_table,"a";        \
+       .gprel32 99b;                   \
+       lda $31, $exitin-99b($31);      \
+       .previous
+
+#define EXO(x,y...)                    \
+       99: x,##y;                      \
+       .section __ex_table,"a";        \
+       .gprel32 99b;                   \
+       lda $31, $exitout-99b($31);     \
+       .previous
+
+       .set noat
+       .align 4
+       .globl __copy_user
+       .ent __copy_user
+                               # Pipeline info: Slotting & Comments
+__copy_user:
+       ldgp $29,0($27)         # we do exceptions -- we need the gp.
+                               # Macro instruction becomes ldah/lda
+                               # .. .. E  E
+       .prologue 1
+       subq $0, 32, $1         # .. E  .. ..   : Is this going to be a small copy?
+       beq $0, $zerolength     # U  .. .. ..   : U L U L
+
+       and $6,7,$3             # .. .. .. E    : is leading dest misalignment
+       ble $1, $onebyteloop    # .. .. U  ..   : 1st branch : small amount of data
+       beq $3, $destaligned    # .. U  .. ..   : 2nd (one cycle fetcher stall)
+       subq $3, 8, $3          # E  .. .. ..   : L U U L : trip counter
+/*
+ * The fetcher stall also hides the 1 cycle cross-cluster stall for $3 (L --> U)
+ * This loop aligns the destination a byte at a time
+ * We know we have at least one trip through this loop
+ */
+$aligndest:
+       EXI( ldbu $1,0($7) )    # .. .. .. L    : Keep loads separate from stores
+       addq $6,1,$6            # .. .. E  ..   : Section 3.8 in the CWG
+       addq $3,1,$3            # .. E  .. ..   :
+       nop                     # E  .. .. ..   : U L U L
+
+/*
+ * the -1 is to compensate for the inc($6) done in a previous quadpack
+ * which allows us zero dependencies within either quadpack in the loop
+ */
+       EXO( stb $1,-1($6) )    # .. .. .. L    :
+       addq $7,1,$7            # .. .. E  ..   : Section 3.8 in the CWG
+       subq $0,1,$0            # .. E  .. ..   :
+       bne $3, $aligndest      # U  .. .. ..   : U L U L
+
+/*
+ * If we fell through into here, we have a minimum of 33 - 7 bytes
+ * If we arrived via branch, we have a minimum of 32 bytes
+ */
+$destaligned:
+       and $7,7,$1             # .. .. .. E    : Check _current_ source alignment
+       bic $0,7,$4             # .. .. E  ..   : number bytes as a quadword loop
+       EXI( ldq_u $3,0($7) )   # .. L  .. ..   : Forward fetch for fallthrough code
+       beq $1,$quadaligned     # U  .. .. ..   : U L U L
+
+/*
+ * In the worst case, we've just executed an ldq_u here from 0($7)
+ * and we'll repeat it once if we take the branch
+ */
+
+/* Misaligned quadword loop - not unrolled.  Leave it that way. */
+$misquad:
+       EXI( ldq_u $2,8($7) )   # .. .. .. L    :
+       subq $4,8,$4            # .. .. E  ..   :
+       extql $3,$7,$3          # .. U  .. ..   :
+       extqh $2,$7,$1          # U  .. .. ..   : U U L L
+
+       bis $3,$1,$1            # .. .. .. E    :
+       EXO( stq $1,0($6) )     # .. .. L  ..   :
+       addq $7,8,$7            # .. E  .. ..   :
+       subq $0,8,$0            # E  .. .. ..   : U L L U
+
+       addq $6,8,$6            # .. .. .. E    :
+       bis $2,$2,$3            # .. .. E  ..   :
+       nop                     # .. E  .. ..   :
+       bne $4,$misquad         # U  .. .. ..   : U L U L
+
+       nop                     # .. .. .. E
+       nop                     # .. .. E  ..
+       nop                     # .. E  .. ..
+       beq $0,$zerolength      # U  .. .. ..   : U L U L
+
+/* We know we have at least one trip through the byte loop */
+       EXI ( ldbu $2,0($7) )   # .. .. .. L    : No loads in the same quad
+       addq $6,1,$6            # .. .. E  ..   : as the store (Section 3.8 in CWG)
+       nop                     # .. E  .. ..   :
+       br $31, $dirtyentry     # L0 .. .. ..   : L U U L
+/* Do the trailing byte loop load, then hop into the store part of the loop */
+
+/*
+ * A minimum of (33 - 7) bytes to do a quad at a time.
+ * Based upon the usage context, it's worth the effort to unroll this loop
+ * $0 - number of bytes to be moved
+ * $4 - number of bytes to move as quadwords
+ * $6 is current destination address
+ * $7 is current source address
+ */
+$quadaligned:
+       subq    $4, 32, $2      # .. .. .. E    : do not unroll for small stuff
+       nop                     # .. .. E  ..
+       nop                     # .. E  .. ..
+       blt     $2, $onequad    # U  .. .. ..   : U L U L
+
+/*
+ * There is a significant assumption here that the source and destination
+ * addresses differ by more than 32 bytes.  In this particular case, a
+ * sparsity of registers further bounds this to be a minimum of 8 bytes.
+ * But if this isn't met, then the output result will be incorrect.
+ * Furthermore, due to a lack of available registers, we really can't
+ * unroll this to be an 8x loop (which would enable us to use the wh64
+ * instruction memory hint instruction).
+ */
+$unroll4:
+       EXI( ldq $1,0($7) )     # .. .. .. L
+       EXI( ldq $2,8($7) )     # .. .. L  ..
+       subq    $4,32,$4        # .. E  .. ..
+       nop                     # E  .. .. ..   : U U L L
+
+       addq    $7,16,$7        # .. .. .. E
+       EXO( stq $1,0($6) )     # .. .. L  ..
+       EXO( stq $2,8($6) )     # .. L  .. ..
+       subq    $0,16,$0        # E  .. .. ..   : U L L U
+
+       addq    $6,16,$6        # .. .. .. E
+       EXI( ldq $1,0($7) )     # .. .. L  ..
+       EXI( ldq $2,8($7) )     # .. L  .. ..
+       subq    $4, 32, $3      # E  .. .. ..   : U U L L : is there enough for another trip?
+
+       EXO( stq $1,0($6) )     # .. .. .. L
+       EXO( stq $2,8($6) )     # .. .. L  ..
+       subq    $0,16,$0        # .. E  .. ..
+       addq    $7,16,$7        # E  .. .. ..   : U L L U
+
+       nop                     # .. .. .. E
+       nop                     # .. .. E  ..
+       addq    $6,16,$6        # .. E  .. ..
+       bgt     $3,$unroll4     # U  .. .. ..   : U L U L
+
+       nop
+       nop
+       nop
+       beq     $4, $noquads
+
+$onequad:
+       EXI( ldq $1,0($7) )
+       subq    $4,8,$4
+       addq    $7,8,$7
+       nop
+
+       EXO( stq $1,0($6) )
+       subq    $0,8,$0
+       addq    $6,8,$6
+       bne     $4,$onequad
+
+$noquads:
+       nop
+       nop
+       nop
+       beq $0,$zerolength
+
+/*
+ * For small copies (or the tail of a larger copy), do a very simple byte loop.
+ * There's no point in doing a lot of complex alignment calculations to try to
+ * to quadword stuff for a small amount of data.
+ *     $0 - remaining number of bytes left to copy
+ *     $6 - current dest addr
+ *     $7 - current source addr
+ */
+
+$onebyteloop:
+       EXI ( ldbu $2,0($7) )   # .. .. .. L    : No loads in the same quad
+       addq $6,1,$6            # .. .. E  ..   : as the store (Section 3.8 in CWG)
+       nop                     # .. E  .. ..   :
+       nop                     # E  .. .. ..   : U L U L
+
+$dirtyentry:
+/*
+ * the -1 is to compensate for the inc($6) done in a previous quadpack
+ * which allows us zero dependencies within either quadpack in the loop
+ */
+       EXO ( stb $2,-1($6) )   # .. .. .. L    :
+       addq $7,1,$7            # .. .. E  ..   : quadpack as the load
+       subq $0,1,$0            # .. E  .. ..   : change count _after_ copy
+       bgt $0,$onebyteloop     # U  .. .. ..   : U L U L
+
+$zerolength:
+$exitout:                      # Destination for exception recovery(?)
+       nop                     # .. .. .. E
+       nop                     # .. .. E  ..
+       nop                     # .. E  .. ..
+       ret $31,($28),1         # L0 .. .. ..   : L U L U
+
+$exitin:
+
+       /* A stupid byte-by-byte zeroing of the rest of the output
+          buffer.  This cures security holes by never leaving 
+          random kernel data around to be copied elsewhere.  */
+
+       nop
+       nop
+       nop
+       mov     $0,$1
+
+$101:
+       EXO ( stb $31,0($6) )   # L
+       subq $1,1,$1            # E
+       addq $6,1,$6            # E
+       bgt $1,$101             # U
+
+       nop
+       nop
+       nop
+       ret $31,($28),1         # L0
+
+       .end __copy_user
+
diff --git a/arch/alpha/lib/ev6-csum_ipv6_magic.S b/arch/alpha/lib/ev6-csum_ipv6_magic.S
new file mode 100644 (file)
index 0000000..de1948a
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * arch/alpha/lib/ev6-csum_ipv6_magic.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
+ *                                struct in6_addr *daddr,
+ *                                __u32 len,
+ *                                unsigned short proto,
+ *                                unsigned int csum);
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
+ *
+ * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
+ *                                struct in6_addr *daddr,
+ *                                __u32 len,
+ *                                unsigned short proto,
+ *                                unsigned int csum);
+ *
+ * Swap <proto> (takes form 0xaabb)
+ * Then shift it left by 48, so result is:
+ *     0xbbaa0000 00000000
+ * Then turn it back into a sign extended 32-bit item
+ *     0xbbaa0000
+ *
+ * Swap <len> (an unsigned int) using Mike Burrows' 7-instruction sequence
+ * (we can't hide the 3-cycle latency of the unpkbw in the 6-instruction sequence)
+ * Assume input takes form 0xAABBCCDD
+ *
+ * Finally, original 'folding' approach is to split the long into 4 unsigned shorts
+ * add 4 ushorts, resulting in ushort/carry
+ * add carry bits + ushort --> ushort
+ * add carry bits + ushort --> ushort (in case the carry results in an overflow)
+ * Truncate to a ushort.  (took 13 instructions)
+ * From doing some testing, using the approach in checksum.c:from64to16()
+ * results in the same outcome:
+ * split into 2 uints, add those, generating a ulong
+ * add the 3 low ushorts together, generating a uint
+ * a final add of the 2 lower ushorts
+ * truncating the result.
+ */
+
+       .globl csum_ipv6_magic
+       .align 4
+       .ent csum_ipv6_magic
+       .frame $30,0,$26,0
+csum_ipv6_magic:
+       .prologue 0
+
+       ldq     $0,0($16)       # L : Latency: 3
+       inslh   $18,7,$4        # U : 0000000000AABBCC
+       ldq     $1,8($16)       # L : Latency: 3
+       sll     $19,8,$7        # U : U L U L : 0x00000000 00aabb00
+
+       zapnot  $20,15,$20      # U : zero extend incoming csum
+       ldq     $2,0($17)       # L : Latency: 3
+       sll     $19,24,$19      # U : U L L U : 0x000000aa bb000000
+       inswl   $18,3,$18       # U : 000000CCDD000000
+
+       ldq     $3,8($17)       # L : Latency: 3
+       bis     $18,$4,$18      # E : 000000CCDDAABBCC
+       addl    $19,$7,$19      # E : <sign bits>bbaabb00
+       nop                     # E : U L U L
+
+       addq    $20,$0,$20      # E : begin summing the words
+       srl     $18,16,$4       # U : 0000000000CCDDAA
+       zap     $19,0x3,$19     # U : <sign bits>bbaa0000
+       nop                     # E : L U U L
+
+       cmpult  $20,$0,$0       # E :
+       addq    $20,$1,$20      # E :
+       zapnot  $18,0xa,$18     # U : 00000000DD00BB00
+       zap     $4,0xa,$4       # U : U U L L : 0000000000CC00AA
+
+       or      $18,$4,$18      # E : 00000000DDCCBBAA
+       nop                     # E :
+       cmpult  $20,$1,$1       # E :
+       addq    $20,$2,$20      # E : U L U L
+
+       cmpult  $20,$2,$2       # E :
+       addq    $20,$3,$20      # E :
+       cmpult  $20,$3,$3       # E : (1 cycle stall on $20)
+       addq    $20,$18,$20     # E : U L U L (1 cycle stall on $20)
+
+       cmpult  $20,$18,$18     # E :
+       addq    $20,$19,$20     # E : (1 cycle stall on $20)
+       addq    $0,$1,$0        # E : merge the carries back into the csum
+       addq    $2,$3,$2        # E :
+
+       cmpult  $20,$19,$19     # E :
+       addq    $18,$19,$18     # E : (1 cycle stall on $19)
+       addq    $0,$2,$0        # E :
+       addq    $20,$18,$20     # E : U L U L :
+               /* (1 cycle stall on $18, 2 cycles on $20) */
+
+       addq    $0,$20,$0       # E :
+       zapnot  $0,15,$1        # U : Start folding output (1 cycle stall on $0)
+       nop                     # E :
+       srl     $0,32,$0        # U : U L U L : (1 cycle stall on $0)
+
+       addq    $1,$0,$1        # E : Finished generating ulong
+       extwl   $1,2,$2         # U : ushort[1] (1 cycle stall on $1)
+       zapnot  $1,3,$0         # U : ushort[0] (1 cycle stall on $1)
+       extwl   $1,4,$1         # U : ushort[2] (1 cycle stall on $1)
+
+       addq    $0,$2,$0        # E
+       addq    $0,$1,$3        # E : Finished generating uint
+               /* (1 cycle stall on $0) */
+       extwl   $3,2,$1         # U : ushort[1] (1 cycle stall on $3)
+       nop                     # E : L U L U
+
+       addq    $1,$3,$0        # E : Final carry
+       not     $0,$4           # E : complement (1 cycle stall on $0)
+       zapnot  $4,3,$0         # U : clear upper garbage bits
+               /* (1 cycle stall on $4) */
+       ret                     # L0 : L U L U
+
+       .end csum_ipv6_magic
diff --git a/arch/alpha/lib/ev6-divide.S b/arch/alpha/lib/ev6-divide.S
new file mode 100644 (file)
index 0000000..2a82b9b
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * arch/alpha/lib/ev6-divide.S
+ *
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Alpha division..
+ */
+
+/*
+ * The alpha chip doesn't provide hardware division, so we have to do it
+ * by hand.  The compiler expects the functions
+ *
+ *     __divqu: 64-bit unsigned long divide
+ *     __remqu: 64-bit unsigned long remainder
+ *     __divqs/__remqs: signed 64-bit
+ *     __divlu/__remlu: unsigned 32-bit
+ *     __divls/__remls: signed 32-bit
+ *
+ * These are not normal C functions: instead of the normal
+ * calling sequence, these expect their arguments in registers
+ * $24 and $25, and return the result in $27. Register $28 may
+ * be clobbered (assembly temporary), anything else must be saved. 
+ *
+ * In short: painful.
+ *
+ * This is a rather simple bit-at-a-time algorithm: it's very good
+ * at dividing random 64-bit numbers, but the more usual case where
+ * the divisor is small is handled better by the DEC algorithm
+ * using lookup tables. This uses much less memory, though, and is
+ * nicer on the cache.. Besides, I don't know the copyright status
+ * of the DEC code.
+ */
+
+/*
+ * My temporaries:
+ *     $0 - current bit
+ *     $1 - shifted divisor
+ *     $2 - modulus/quotient
+ *
+ *     $23 - return address
+ *     $24 - dividend
+ *     $25 - divisor
+ *
+ *     $27 - quotient/modulus
+ *     $28 - compare status
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#define halt .long 0
+
+/*
+ * Select function type and registers
+ */
+#define mask   $0
+#define divisor        $1
+#define compare $28
+#define tmp1   $3
+#define tmp2   $4
+
+#ifdef DIV
+#define DIV_ONLY(x,y...) x,##y
+#define MOD_ONLY(x,y...)
+#define func(x) __div##x
+#define modulus $2
+#define quotient $27
+#define GETSIGN(x) xor $24,$25,x
+#define STACK 48
+#else
+#define DIV_ONLY(x,y...)
+#define MOD_ONLY(x,y...) x,##y
+#define func(x) __rem##x
+#define modulus $27
+#define quotient $2
+#define GETSIGN(x) bis $24,$24,x
+#define STACK 32
+#endif
+
+/*
+ * For 32-bit operations, we need to extend to 64-bit
+ */
+#ifdef INTSIZE
+#define ufunction func(lu)
+#define sfunction func(l)
+#define LONGIFY(x) zapnot x,15,x
+#define SLONGIFY(x) addl x,0,x
+#else
+#define ufunction func(qu)
+#define sfunction func(q)
+#define LONGIFY(x)
+#define SLONGIFY(x)
+#endif
+
+.set noat
+.align 4
+.globl ufunction
+.ent   ufunction
+ufunction:
+       subq    $30,STACK,$30           # E :
+       .frame  $30,STACK,$23
+       .prologue 0
+
+7:     stq     $1, 0($30)              # L :
+       bis     $25,$25,divisor         # E :
+       stq     $2, 8($30)              # L : L U L U
+
+       bis     $24,$24,modulus         # E :
+       stq     $0,16($30)              # L :
+       bis     $31,$31,quotient        # E :
+       LONGIFY(divisor)                # E : U L L U
+
+       stq     tmp1,24($30)            # L :
+       LONGIFY(modulus)                # E :
+       bis     $31,1,mask              # E :
+       DIV_ONLY(stq tmp2,32($30))      # L : L U U L
+
+       beq     divisor, 9f                     /* div by zero */
+       /*
+        * In spite of the DIV_ONLY being either a non-instruction
+        * or an actual stq, the addition of the .align directive
+        * below ensures that label 1 is going to be nicely aligned
+        */
+
+       .align  4
+#ifdef INTSIZE
+       /*
+        * shift divisor left, using 3-bit shifts for
+        * 32-bit divides as we can't overflow. Three-bit
+        * shifts will result in looping three times less
+        * here, but can result in two loops more later.
+        * Thus using a large shift isn't worth it (and
+        * s8add pairs better than a sll..)
+        */
+1:     cmpult  divisor,modulus,compare # E :
+       s8addq  divisor,$31,divisor     # E :
+       s8addq  mask,$31,mask           # E :
+       bne     compare,1b              # U : U L U L
+#else
+1:     cmpult  divisor,modulus,compare # E :
+       nop                             # E :
+       nop                             # E :
+       blt     divisor, 2f             # U : U L U L
+
+       addq    divisor,divisor,divisor # E :
+       addq    mask,mask,mask          # E :
+       unop                            # E :
+       bne     compare,1b              # U : U L U L
+#endif
+
+       /* ok, start to go right again.. */
+2:
+       /*
+        * Keep things nicely bundled... use a nop instead of not
+        * having an instruction for DIV_ONLY
+        */
+#ifdef DIV
+       DIV_ONLY(addq quotient,mask,tmp2) # E :
+#else
+       nop                             # E :
+#endif
+       srl     mask,1,mask             # U :
+       cmpule  divisor,modulus,compare # E :
+       subq    modulus,divisor,tmp1    # E :
+
+#ifdef DIV
+       DIV_ONLY(cmovne compare,tmp2,quotient)  # E : Latency 2, extra map slot
+       nop                             # E : as part of the cmovne
+       srl     divisor,1,divisor       # U :
+       nop                             # E : L U L U
+
+       nop                             # E :
+       cmovne  compare,tmp1,modulus    # E : Latency 2, extra map slot
+       nop                             # E : as part of the cmovne
+       bne     mask,2b                 # U : U L U L
+#else
+       srl     divisor,1,divisor       # U :
+       cmovne  compare,tmp1,modulus    # E : Latency 2, extra map slot
+       nop                             # E : as part of the cmovne
+       bne     mask,2b                 # U : U L L U
+#endif
+
+9:     ldq     $1, 0($30)              # L :
+       ldq     $2, 8($30)              # L :
+       nop                             # E :
+       nop                             # E : U U L L
+
+       ldq     $0,16($30)              # L :
+       ldq     tmp1,24($30)            # L :
+       nop                             # E :
+       nop                             # E :
+
+#ifdef DIV
+       DIV_ONLY(ldq tmp2,32($30))      # L :
+#else
+       nop                             # E :
+#endif
+       addq    $30,STACK,$30           # E :
+       ret     $31,($23),1             # L0 : L U U L
+       .end    ufunction
+
+/*
+ * Uhh.. Ugly signed division. I'd rather not have it at all, but
+ * it's needed in some circumstances. There are different ways to
+ * handle this, really. This does:
+ *     -a / b = a / -b = -(a / b)
+ *     -a % b = -(a % b)
+ *     a % -b = a % b
+ * which is probably not the best solution, but at least should
+ * have the property that (x/y)*y + (x%y) = x.
+ */
+.align 4
+.globl sfunction
+.ent   sfunction
+sfunction:
+       subq    $30,STACK,$30           # E :
+       .frame  $30,STACK,$23
+       .prologue 0
+       bis     $24,$25,$28             # E :
+       SLONGIFY($28)                   # E :
+       bge     $28,7b                  # U :
+
+       stq     $24,0($30)              # L :
+       subq    $31,$24,$28             # E :
+       stq     $25,8($30)              # L :
+       nop                             # E : U L U L
+
+       cmovlt  $24,$28,$24     /* abs($24) */ # E : Latency 2, extra map slot
+       nop                             # E : as part of the cmov
+       stq     $23,16($30)             # L :
+       subq    $31,$25,$28             # E : U L U L
+
+       stq     tmp1,24($30)            # L :
+       cmovlt  $25,$28,$25     /* abs($25) */ # E : Latency 2, extra map slot
+       nop                             # E :
+       bsr     $23,ufunction           # L0: L U L U
+
+       ldq     $24,0($30)              # L :
+       ldq     $25,8($30)              # L :
+       GETSIGN($28)                    # E :
+       subq    $31,$27,tmp1            # E : U U L L
+
+       SLONGIFY($28)                   # E :
+       ldq     $23,16($30)             # L :
+       cmovlt  $28,tmp1,$27            # E : Latency 2, extra map slot
+       nop                             # E : U L L U : as part of the cmov
+
+       ldq     tmp1,24($30)            # L :
+       nop                             # E : as part of the cmov
+       addq    $30,STACK,$30           # E :
+       ret     $31,($23),1             # L0 : L U U L
+       .end    sfunction
diff --git a/arch/alpha/lib/ev6-strcpy.S b/arch/alpha/lib/ev6-strcpy.S
new file mode 100644 (file)
index 0000000..8a6673d
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * arch/alpha/lib/strcpy.S
+ * Contributed by Richard Henderson (rth@tamu.edu)
+ *
+ * Copy a null-terminated string from SRC to DST.  Return a pointer
+ * to the null-terminator in the source.
+ */
+
+       .text
+
+       .align 4
+       .globl strcpy
+       .ent strcpy
+strcpy:
+       .frame $30, 0, $26
+       .prologue 0
+
+       mov     $16, $0         # set up return value
+       mov     $26, $23        # set up return address
+       br      __stxcpy        # do the copy
+       nop
+
+       .end strcpy
diff --git a/arch/alpha/lib/ev6-strncpy.S b/arch/alpha/lib/ev6-strncpy.S
new file mode 100644 (file)
index 0000000..053146b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * arch/alpha/lib/strncpy.S
+ * Contributed by Richard Henderson (rth@tamu.edu)
+ *
+ * Copy no more than COUNT bytes of the null-terminated string from
+ * SRC to DST.  If SRC does not cover all of COUNT, the balance is
+ * zeroed.
+ *
+ * Or, rather, if the kernel cared about that weird ANSI quirk.  This
+ * version has cropped that bit o' nastiness as well as assuming that
+ * __stxncpy is in range of a branch.
+ */
+
+       .set noat
+       .set noreorder
+
+       .text
+
+       .align 4
+       .globl strncpy
+       .ent strncpy
+strncpy:
+       .frame $30, 0, $26
+       .prologue 0
+
+       mov     $16, $0         # set return value now
+       beq     $18, 0f
+       mov     $26, $23        # set return address
+       br      __stxncpy       # do the work of the copy
+
+0:     ret
+       nop
+       nop
+       nop
+
+       .end strncpy
diff --git a/arch/alpha/lib/ev6-strncpy_from_user.S b/arch/alpha/lib/ev6-strncpy_from_user.S
new file mode 100644 (file)
index 0000000..8d44677
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * arch/alpha/lib/ev6-strncpy_from_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Just like strncpy except in the return value:
+ *
+ * -EFAULT       if an exception occurs before the terminator is copied.
+ * N             if the buffer filled.
+ *
+ * Otherwise the length of the string is returned.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * A bunch of instructions got moved and temp registers were changed
+ * to aid in scheduling.  Control flow was also re-arranged to eliminate
+ * branches, and to provide longer code sequences to enable better scheduling.
+ * A total rewrite (using byte load/stores for start & tail sequences)
+ * is desirable, but very difficult to do without a from-scratch rewrite.
+ * Save that for the future.
+ */
+
+
+#include <asm/errno.h>
+#include <alpha/regdef.h>
+
+
+/* Allow an exception for an insn; exit if we get one.  */
+#define EX(x,y...)                     \
+       99: x,##y;                      \
+       .section __ex_table,"a";        \
+       .gprel32 99b;                   \
+       lda $31, $exception-99b($0);    \
+       .previous
+
+
+       .set noat
+       .set noreorder
+       .text
+
+       .globl __strncpy_from_user
+       .ent __strncpy_from_user
+       .frame $30, 0, $26
+       .prologue 1
+
+       .align 4
+__strncpy_from_user:
+       ldgp    $29, 0($27)     # E E : becomes 2 instructions (for exceptions)
+       and     a0, 7, t3       # E : find dest misalignment
+       beq     a2, $zerolength # U :
+
+       /* Are source and destination co-aligned?  */
+       mov     a0, v0          # E : save the string start
+       xor     a0, a1, t4      # E :
+       EX( ldq_u t1, 0(a1) )   # L : Latency=3 load first quadword
+       ldq_u   t0, 0(a0)       # L : load first (partial) aligned dest quadword
+
+       addq    a2, t3, a2      # E : bias count by dest misalignment
+       subq    a2, 1, a3       # E :
+       addq    zero, 1, t10    # E :
+       and     t4, 7, t4       # E : misalignment between the two
+
+       and     a3, 7, t6       # E : number of tail bytes
+       sll     t10, t6, t10    # E : t10 = bitmask of last count byte
+       bne     t4, $unaligned  # U :
+       lda     t2, -1          # E : build a mask against false zero
+
+       /*
+        * We are co-aligned; take care of a partial first word.
+        * On entry to this basic block:
+        * t0 == the first destination word for masking back in
+        * t1 == the first source word.
+        */
+
+       srl     a3, 3, a2       # E : a2 = loop counter = (count - 1)/8
+       addq    a1, 8, a1       # E :
+       mskqh   t2, a1, t2      # U :   detection in the src word
+       nop
+
+       /* Create the 1st output word and detect 0's in the 1st input word.  */
+       mskqh   t1, a1, t3      # U :
+       mskql   t0, a1, t0      # U : assemble the first output word
+       ornot   t1, t2, t2      # E :
+       nop
+
+       cmpbge  zero, t2, t8    # E : bits set iff null found
+       or      t0, t3, t0      # E :
+       beq     a2, $a_eoc      # U :
+       bne     t8, $a_eos      # U : 2nd branch in a quad.  Bad.
+
+       /* On entry to this basic block:
+        * t0 == a source quad not containing a null.
+        * a0 - current aligned destination address
+        * a1 - current aligned source address
+        * a2 - count of quadwords to move.
+        * NOTE: Loop improvement - unrolling this is going to be
+        *      a huge win, since we're going to stall otherwise.
+        *      Fix this later.  For _really_ large copies, look
+        *      at using wh64 on a look-ahead basis.  See the code
+        *      in clear_user.S and copy_user.S.
+        * Presumably, since (a0) and (a1) do not overlap (by C definition)
+        * Lots of nops here:
+        *      - Separate loads from stores
+        *      - Keep it to 1 branch/quadpack so the branch predictor
+        *        can train.
+        */
+$a_loop:
+       stq_u   t0, 0(a0)       # L :
+       addq    a0, 8, a0       # E :
+       nop
+       subq    a2, 1, a2       # E :
+
+       EX( ldq_u t0, 0(a1) )   # L :
+       addq    a1, 8, a1       # E :
+       cmpbge  zero, t0, t8    # E : Stall 2 cycles on t0
+       beq     a2, $a_eoc      # U :
+
+       beq     t8, $a_loop     # U :
+       nop
+       nop
+       nop
+
+       /* Take care of the final (partial) word store.  At this point
+        * the end-of-count bit is set in t8 iff it applies.
+        *
+        * On entry to this basic block we have:
+        * t0 == the source word containing the null
+        * t8 == the cmpbge mask that found it.
+        */
+$a_eos:
+       negq    t8, t12         # E : find low bit set
+       and     t8, t12, t12    # E : 
+
+       /* We're doing a partial word store and so need to combine
+          our source and original destination words.  */
+       ldq_u   t1, 0(a0)       # L :
+       subq    t12, 1, t6      # E :
+
+       or      t12, t6, t8     # E :
+       zapnot  t0, t8, t0      # U : clear src bytes > null
+       zap     t1, t8, t1      # U : clear dst bytes <= null
+       or      t0, t1, t0      # E :
+
+       stq_u   t0, 0(a0)       # L :
+       br      $finish_up      # L0 :
+       nop
+       nop
+
+       /* Add the end-of-count bit to the eos detection bitmask.  */
+       .align 4
+$a_eoc:
+       or      t10, t8, t8
+       br      $a_eos
+       nop
+       nop
+
+
+/* The source and destination are not co-aligned.  Align the destination
+   and cope.  We have to be very careful about not reading too much and
+   causing a SEGV.  */
+
+       .align 4
+$u_head:
+       /* We know just enough now to be able to assemble the first
+          full source word.  We can still find a zero at the end of it
+          that prevents us from outputting the whole thing.
+
+          On entry to this basic block:
+          t0 == the first dest word, unmasked
+          t1 == the shifted low bits of the first source word
+          t6 == bytemask that is -1 in dest word bytes */
+
+       EX( ldq_u t2, 8(a1) )   # L : load second src word
+       addq    a1, 8, a1       # E :
+       mskql   t0, a0, t0      # U : mask trailing garbage in dst
+       extqh   t2, a1, t4      # U :
+
+       or      t1, t4, t1      # E : first aligned src word complete
+       mskqh   t1, a0, t1      # U : mask leading garbage in src
+       or      t0, t1, t0      # E : first output word complete
+       or      t0, t6, t6      # E : mask original data for zero test
+
+       cmpbge  zero, t6, t8    # E :
+       beq     a2, $u_eocfin   # U :
+       bne     t8, $u_final    # U : bad news - 2nd branch in a quad
+       lda     t6, -1          # E : mask out the bits we have
+
+       mskql   t6, a1, t6      # U :   already seen
+       stq_u   t0, 0(a0)       # L : store first output word
+       or      t6, t2, t2      # E :
+       cmpbge  zero, t2, t8    # E : find nulls in second partial
+
+       addq    a0, 8, a0               # E :
+       subq    a2, 1, a2               # E :
+       bne     t8, $u_late_head_exit   # U :
+       nop
+
+       /* Finally, we've got all the stupid leading edge cases taken care
+          of and we can set up to enter the main loop.  */
+
+       extql   t2, a1, t1      # U : position hi-bits of lo word
+       EX( ldq_u t2, 8(a1) )   # L : read next high-order source word
+       addq    a1, 8, a1       # E :
+       cmpbge  zero, t2, t8    # E :
+
+       beq     a2, $u_eoc      # U :
+       bne     t8, $u_eos      # U :
+       nop
+       nop
+
+       /* Unaligned copy main loop.  In order to avoid reading too much,
+          the loop is structured to detect zeros in aligned source words.
+          This has, unfortunately, effectively pulled half of a loop
+          iteration out into the head and half into the tail, but it does
+          prevent nastiness from accumulating in the very thing we want
+          to run as fast as possible.
+
+          On entry to this basic block:
+          t1 == the shifted high-order bits from the previous source word
+          t2 == the unshifted current source word
+
+          We further know that t2 does not contain a null terminator.  */
+
+       /*
+        * Extra nops here:
+        *      separate load quads from store quads
+        *      only one branch/quad to permit predictor training
+        */
+
+       .align 4
+$u_loop:
+       extqh   t2, a1, t0      # U : extract high bits for current word
+       addq    a1, 8, a1       # E :
+       extql   t2, a1, t3      # U : extract low bits for next time
+       addq    a0, 8, a0       # E :
+
+       or      t0, t1, t0      # E : current dst word now complete
+       EX( ldq_u t2, 0(a1) )   # L : load high word for next time
+       subq    a2, 1, a2       # E :
+       nop
+
+       stq_u   t0, -8(a0)      # L : save the current word
+       mov     t3, t1          # E :
+       cmpbge  zero, t2, t8    # E : test new word for eos
+       beq     a2, $u_eoc      # U :
+
+       beq     t8, $u_loop     # U :
+       nop
+       nop
+       nop
+
+       /* We've found a zero somewhere in the source word we just read.
+          If it resides in the lower half, we have one (probably partial)
+          word to write out, and if it resides in the upper half, we
+          have one full and one partial word left to write out.
+
+          On entry to this basic block:
+          t1 == the shifted high-order bits from the previous source word
+          t2 == the unshifted current source word.  */
+       .align 4
+$u_eos:
+       extqh   t2, a1, t0      # U :
+       or      t0, t1, t0      # E : first (partial) source word complete
+       cmpbge  zero, t0, t8    # E : is the null in this first bit?
+       nop
+
+       bne     t8, $u_final    # U :
+       stq_u   t0, 0(a0)       # L : the null was in the high-order bits
+       addq    a0, 8, a0       # E :
+       subq    a2, 1, a2       # E :
+
+       .align 4
+$u_late_head_exit:
+       extql   t2, a1, t0      # U :
+       cmpbge  zero, t0, t8    # E :
+       or      t8, t10, t6     # E :
+       cmoveq  a2, t6, t8      # E :
+
+       /* Take care of a final (probably partial) result word.
+          On entry to this basic block:
+          t0 == assembled source word
+          t8 == cmpbge mask that found the null.  */
+       .align 4
+$u_final:
+       negq    t8, t6          # E : isolate low bit set
+       and     t6, t8, t12     # E :
+       ldq_u   t1, 0(a0)       # L :
+       subq    t12, 1, t6      # E :
+
+       or      t6, t12, t8     # E :
+       zapnot  t0, t8, t0      # U : kill source bytes > null
+       zap     t1, t8, t1      # U : kill dest bytes <= null
+       or      t0, t1, t0      # E :
+
+       stq_u   t0, 0(a0)       # E :
+       br      $finish_up      # U :
+       nop
+       nop
+
+       .align 4
+$u_eoc:                                # end-of-count
+       extqh   t2, a1, t0      # U :
+       or      t0, t1, t0      # E :
+       cmpbge  zero, t0, t8    # E :
+       nop
+
+       .align 4
+$u_eocfin:                     # end-of-count, final word
+       or      t10, t8, t8     # E :
+       br      $u_final        # U :
+       nop
+       nop
+
+       /* Unaligned copy entry point.  */
+       .align 4
+$unaligned:
+
+       srl     a3, 3, a2       # U : a2 = loop counter = (count - 1)/8
+       and     a0, 7, t4       # E : find dest misalignment
+       and     a1, 7, t5       # E : find src misalignment
+       mov     zero, t0        # E :
+
+       /* Conditionally load the first destination word and a bytemask
+          with 0xff indicating that the destination byte is sacrosanct.  */
+
+       mov     zero, t6        # E :
+       beq     t4, 1f          # U :
+       ldq_u   t0, 0(a0)       # L :
+       lda     t6, -1          # E :
+
+       mskql   t6, a0, t6      # E :
+       nop
+       nop
+       nop
+
+       .align 4
+1:
+       subq    a1, t4, a1      # E : sub dest misalignment from src addr
+       /* If source misalignment is larger than dest misalignment, we need
+          extra startup checks to avoid SEGV.  */
+       cmplt   t4, t5, t12     # E :
+       extql   t1, a1, t1      # U : shift src into place
+       lda     t2, -1          # E : for creating masks later
+
+       beq     t12, $u_head    # U :
+       mskqh   t2, t5, t2      # U : begin src byte validity mask
+       cmpbge  zero, t1, t8    # E : is there a zero?
+       nop
+
+       extql   t2, a1, t2      # U :
+       or      t8, t10, t5     # E : test for end-of-count too
+       cmpbge  zero, t2, t3    # E :
+       cmoveq  a2, t5, t8      # E : Latency=2, extra map slot
+
+       nop                     # E : goes with cmov
+       andnot  t8, t3, t8      # E :
+       beq     t8, $u_head     # U :
+       nop
+
+       /* At this point we've found a zero in the first partial word of
+          the source.  We need to isolate the valid source data and mask
+          it into the original destination data.  (Incidentally, we know
+          that we'll need at least one byte of that original dest word.) */
+
+       ldq_u   t0, 0(a0)       # L :
+       negq    t8, t6          # E : build bitmask of bytes <= zero
+       mskqh   t1, t4, t1      # U :
+       and     t6, t8, t12     # E :
+
+       subq    t12, 1, t6      # E :
+       or      t6, t12, t8     # E :
+       zapnot  t2, t8, t2      # U : prepare source word; mirror changes
+       zapnot  t1, t8, t1      # U : to source validity mask
+
+       andnot  t0, t2, t0      # E : zero place for source to reside
+       or      t0, t1, t0      # E : and put it there
+       stq_u   t0, 0(a0)       # L :
+       nop
+
+       .align 4
+$finish_up:
+       zapnot  t0, t12, t4     # U : was last byte written null?
+       and     t12, 0xf0, t3   # E : binary search for the address of the
+       cmovne  t4, 1, t4       # E : Latency=2, extra map slot
+       nop                     # E : with cmovne
+
+       and     t12, 0xcc, t2   # E : last byte written
+       and     t12, 0xaa, t1   # E :
+       cmovne  t3, 4, t3       # E : Latency=2, extra map slot
+       nop                     # E : with cmovne
+
+       bic     a0, 7, t0
+       cmovne  t2, 2, t2       # E : Latency=2, extra map slot
+       nop                     # E : with cmovne
+       nop
+
+       cmovne  t1, 1, t1       # E : Latency=2, extra map slot
+       nop                     # E : with cmovne
+       addq    t0, t3, t0      # E :
+       addq    t1, t2, t1      # E :
+
+       addq    t0, t1, t0      # E :
+       addq    t0, t4, t0      # add one if we filled the buffer
+       subq    t0, v0, v0      # find string length
+       ret                     # L0 :
+
+       .align 4
+$zerolength:
+       nop
+       nop
+       nop
+       clr     v0
+
+$exception:
+       nop
+       nop
+       nop
+       ret
+
+       .end __strncpy_from_user
diff --git a/arch/alpha/lib/ev67-strcat.S b/arch/alpha/lib/ev67-strcat.S
new file mode 100644 (file)
index 0000000..c426fe3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * arch/alpha/lib/ev67-strcat.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Append a null-terminated string from SRC to DST.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ * Commentary: It seems bogus to walk the input string twice - once
+ * to determine the length, and then again while doing the copy.
+ * A significant (future) enhancement would be to only read the input
+ * string once.
+ */
+
+
+       .text
+
+       .align 4
+       .globl strcat
+       .ent strcat
+strcat:
+       .frame $30, 0, $26
+       .prologue 0
+
+       mov     $16, $0         # E : set up return value
+       /* Find the end of the string.  */
+       ldq_u   $1, 0($16)      # L : load first quadword (a0 may be misaligned)
+       lda     $2, -1          # E :
+       insqh   $2, $16, $2     # U :
+
+       andnot  $16, 7, $16     # E :
+       or      $2, $1, $1      # E :
+       cmpbge  $31, $1, $2     # E : bits set iff byte == 0
+       bne     $2, $found      # U :
+
+$loop: ldq     $1, 8($16)      # L :
+       addq    $16, 8, $16     # E :
+       cmpbge  $31, $1, $2     # E :
+       beq     $2, $loop       # U :
+
+$found:        cttz    $2, $3          # U0 :
+       addq    $16, $3, $16    # E :
+       /* Now do the append.  */
+       mov     $26, $23        # E :
+       br      __stxcpy        # L0 :
+
+       .end strcat
diff --git a/arch/alpha/lib/ev67-strchr.S b/arch/alpha/lib/ev67-strchr.S
new file mode 100644 (file)
index 0000000..b817f82
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * arch/alpha/lib/ev67-strchr.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Return the address of a given character within a null-terminated
+ * string, or null if it is not found.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+       .set noreorder
+       .set noat
+
+       .align 4
+       .globl strchr
+       .ent strchr
+strchr:
+       .frame sp, 0, ra
+       .prologue 0
+
+       ldq_u   t0, 0(a0)       # L : load first quadword Latency=3
+       and     a1, 0xff, t3    # E : 00000000000000ch
+       insbl   a1, 1, t5       # U : 000000000000ch00
+       insbl   a1, 7, a2       # U : ch00000000000000
+
+       insbl   t3, 6, a3       # U : 00ch000000000000
+       or      t5, t3, a1      # E : 000000000000chch
+       andnot  a0, 7, v0       # E : align our loop pointer
+       lda     t4, -1          # E : build garbage mask
+
+       mskqh   t4, a0, t4      # U : only want relevant part of first quad
+       or      a2, a3, a2      # E : chch000000000000
+       inswl   a1, 2, t5       # E : 00000000chch0000
+       inswl   a1, 4, a3       # E : 0000chch00000000
+
+       or      a1, a2, a1      # E : chch00000000chch
+       or      a3, t5, t5      # E : 0000chchchch0000
+       cmpbge  zero, t0, t2    # E : bits set iff byte == zero
+       cmpbge  zero, t4, t4    # E : bits set iff byte is garbage
+
+       /* This quad is _very_ serialized.  Lots of stalling happens */
+       or      t5, a1, a1      # E : chchchchchchchch
+       xor     t0, a1, t1      # E : make bytes == c zero
+       cmpbge  zero, t1, t3    # E : bits set iff byte == c
+       or      t2, t3, t0      # E : bits set iff char match or zero match
+
+       andnot  t0, t4, t0      # E : clear garbage bits
+       cttz    t3, a2          # U0 : speculative (in case we get a match)
+       nop                     # E :
+       bne     t0, $found      # U : Stall on t0
+
+       /*
+        * Yuk.  This loop is going to stall like crazy waiting for the
+        * data to be loaded.  Not much can be done about it unless it's
+        * unrolled multiple times - is that safe to do in kernel space?
+        * Or would exception handling recovery code do the trick here?
+        */
+$loop: ldq     t0, 8(v0)       # L : Latency=3
+       addq    v0, 8, v0       # E :
+       xor     t0, a1, t1      # E :
+       cmpbge  zero, t0, t2    # E : bits set iff byte == 0
+
+       cmpbge  zero, t1, t3    # E : bits set iff byte == c
+       or      t2, t3, t0      # E :
+       cttz    t3, a2          # U0 : speculative (in case we get a match)
+       beq     t0, $loop       # U :
+
+$found:        negq    t0, t1          # E : clear all but least set bit
+       and     t0, t1, t0      # E :
+       and     t0, t3, t1      # E : bit set iff byte was the char
+       addq    v0, a2, v0      # E : Add in the bit number from above
+
+       cmoveq  t1, $31, v0     # E : Two mapping slots, latency = 2
+       nop
+       nop
+       ret                     # L0 :
+
+       .end strchr
diff --git a/arch/alpha/lib/ev67-strlen.S b/arch/alpha/lib/ev67-strlen.S
new file mode 100644 (file)
index 0000000..5039280
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * arch/alpha/lib/ev67-strlen.S
+ * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
+ *
+ * Finds length of a 0-terminated string.  Optimized for the
+ * Alpha architecture:
+ *
+ *     - memory accessed as aligned quadwords only
+ *     - uses bcmpge to compare 8 bytes in parallel
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ */
+
+       .set noreorder
+       .set noat
+
+       .globl  strlen
+       .ent    strlen
+       .align 4
+strlen:
+       ldq_u   $1, 0($16)      # L : load first quadword ($16  may be misaligned)
+       lda     $2, -1($31)     # E :
+       insqh   $2, $16, $2     # U :
+       andnot  $16, 7, $0      # E :
+
+       or      $2, $1, $1      # E :
+       cmpbge  $31, $1, $2     # E : $2  <- bitmask: bit i == 1 <==> i-th byte == 0
+       nop                     # E :
+       bne     $2, $found      # U :
+
+$loop: ldq     $1, 8($0)       # L :
+       addq    $0, 8, $0       # E : addr += 8
+       cmpbge  $31, $1, $2     # E :
+       beq     $2, $loop       # U :
+
+$found:
+       cttz    $2, $3          # U0 :
+       addq    $0, $3, $0      # E :
+       subq    $0, $16, $0     # E :
+       ret     $31, ($26)      # L0 :
+
+       .end    strlen
diff --git a/arch/alpha/lib/ev67-strlen_user.S b/arch/alpha/lib/ev67-strlen_user.S
new file mode 100644 (file)
index 0000000..67f1e94
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * arch/alpha/lib/ev67-strlen_user.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Return the length of the string including the NULL terminator
+ * (strlen+1) or zero if an error occurred.
+ *
+ * In places where it is critical to limit the processing time,
+ * and the data is not trusted, strnlen_user() should be used.
+ * It will return a value greater than its second argument if
+ * that limit would be exceeded. This implementation is allowed
+ * to access memory beyond the limit, but will not cross a page
+ * boundary when doing so.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *      Compiler Writer's Guide for the Alpha 21264
+ *      abbreviated as 'CWG' in other comments here
+ *      ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *      E       - either cluster
+ *      U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *      L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+#include <alpha/regdef.h>
+
+
+/* Allow an exception for an insn; exit if we get one.  */
+#define EX(x,y...)                     \
+       99: x,##y;                      \
+       .section __ex_table,"a";        \
+       .gprel32 99b;                   \
+       lda v0, $exception-99b(zero);   \
+       .previous
+
+
+       .set noreorder
+       .set noat
+       .text
+
+       .globl __strlen_user
+       .ent __strlen_user
+       .frame sp, 0, ra
+
+       .align 4
+__strlen_user:
+       ldah    a1, 32767(zero) # do not use plain strlen_user() for strings
+                               # that might be almost 2 GB long; you should
+                               # be using strnlen_user() instead
+       nop
+       nop
+       nop
+
+       .globl __strnlen_user
+
+       .align 4
+__strnlen_user:
+       ldgp    $29,0($27)      # E E : we do exceptions -- we need the gp.
+                               /* Decomposes into lda/ldah */
+       .prologue 1
+       EX( ldq_u t0, 0(a0) )   # L : load first quadword (a0 may be misaligned)
+       lda     t1, -1(zero)    # E :
+
+       insqh   t1, a0, t1      # U :
+       andnot  a0, 7, v0       # E :
+       or      t1, t0, t0      # E :
+       subq    a0, 1, a0       # E : get our +1 for the return 
+
+       cmpbge  zero, t0, t1    # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0
+       subq    a1, 7, t2       # E :
+       subq    a0, v0, t0      # E :
+       bne     t1, $found      # U :
+
+       addq    t2, t0, t2      # E :
+       addq    a1, 1, a1       # E :
+       nop                     # E :
+       nop                     # E :
+
+       .align 4
+$loop: ble     t2, $limit      # U :
+       EX( ldq t0, 8(v0) )     # L :
+       nop                     # E :
+       nop                     # E :
+
+       cmpbge  zero, t0, t1    # E :
+       subq    t2, 8, t2       # E :
+       addq    v0, 8, v0       # E : addr += 8
+       beq     t1, $loop       # U :
+
+$found: cttz   t1, t2          # U0 :
+       addq    v0, t2, v0      # E :
+       subq    v0, a0, v0      # E :
+       ret                     # L0 :
+
+$exception:
+       nop
+       nop
+       nop
+       ret
+
+       .align 4                # currently redundant
+$limit:
+       nop
+       nop
+       subq    a1, t2, v0
+       ret
+
+       .end __strlen_user
diff --git a/arch/alpha/lib/ev67-strncat.S b/arch/alpha/lib/ev67-strncat.S
new file mode 100644 (file)
index 0000000..4ae716c
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * arch/alpha/lib/ev67-strncat.S
+ * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
+ *
+ * Append no more than COUNT characters from the null-terminated string SRC
+ * to the null-terminated string DST.  Always null-terminate the new DST.
+ *
+ * This differs slightly from the semantics in libc in that we never write
+ * past count, whereas libc may write to count+1.  This follows the generic
+ * implementation in lib/string.c and is, IMHO, more sensible.
+ *
+ * Much of the information about 21264 scheduling/coding comes from:
+ *     Compiler Writer's Guide for the Alpha 21264
+ *     abbreviated as 'CWG' in other comments here
+ *     ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
+ * Scheduling notation:
+ *     E       - either cluster
+ *     U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
+ *     L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
+ * Try not to change the actual algorithm if possible for consistency.
+ */
+
+
+       .text
+
+       .align 4
+       .globl strncat
+       .ent strncat
+strncat:
+       .frame $30, 0, $26
+       .prologue 0
+
+       mov     $16, $0         # set up return value
+       beq     $18, $zerocount # U :
+       /* Find the end of the string.  */
+       ldq_u   $1, 0($16)      # L : load first quadword ($16 may be misaligned)
+       lda     $2, -1($31)     # E :
+
+       insqh   $2, $0, $2      # U :
+       andnot  $16, 7, $16     # E :
+       nop                     # E :
+       or      $2, $1, $1      # E :
+
+       nop                     # E :
+       nop                     # E :
+       cmpbge  $31, $1, $2     # E : bits set iff byte == 0
+       bne     $2, $found      # U :
+
+$loop: ldq     $1, 8($16)      # L :
+       addq    $16, 8, $16     # E :
+       cmpbge  $31, $1, $2     # E :
+       beq     $2, $loop       # U :
+
+$found:        cttz    $2, $3          # U0 :
+       addq    $16, $3, $16    # E :
+       nop                     # E :
+       bsr     $23, __stxncpy  # L0 :/* Now do the append.  */
+
+       /* Worry about the null termination.  */
+
+       zapnot  $1, $27, $2     # U : was last byte a null?
+       cmplt   $27, $24, $5    # E : did we fill the buffer completely?
+       bne     $2, 0f          # U :
+       ret                     # L0 :
+
+0:     or      $5, $18, $2     # E :
+       nop
+       bne     $2, 2f          # U :
+       and     $24, 0x80, $3   # E : no zero next byte
+
+       nop                     # E :
+       bne     $3, 1f          # U :
+       /* Here there are bytes left in the current word.  Clear one.  */
+       addq    $24, $24, $24   # E : end-of-count bit <<= 1
+       nop                     # E :
+
+2:     zap     $1, $24, $1     # U :
+       nop                     # E :
+       stq_u   $1, 0($16)      # L :
+       ret                     # L0 :
+
+1:     /* Here we must clear the first byte of the next DST word */
+       stb     $31, 8($16)     # L :
+       nop                     # E :
+       nop                     # E :
+       ret                     # L0 :
+
+$zerocount:
+       nop                     # E :
+       nop                     # E :
+       nop                     # E :
+       ret                     # L0 :
+
+       .end strncat
index 76db09e765b15e11ead7276c3dc9c2da3be54ed2..9d0cc5c698a0d82a6b13ba1d3b49ce0dab781720 100644 (file)
@@ -42,12 +42,6 @@ const char *processor_modes[]=
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
-static inline void console_verbose(void)
-{
-       extern int console_loglevel;
-       console_loglevel = 15;
-}
-
 /*
  * Stack pointers should always be within the kernels view of
  * physical memory.  If it is not there, then we can't dump
index 92ddd01f5deaa271e6e179c096ac4fd67a4e0437..cf68787873d037aba773166c6d34f5a155e04fd5 100644 (file)
@@ -179,7 +179,7 @@ int get_irq_list(char *buf)
 
 #ifdef CONFIG_SMP
 unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile int global_irq_lock;
+unsigned volatile long global_irq_lock; /* pendantic: long for set_bit --RR */
 
 extern void show_stack(unsigned long* esp);
 
index 4871aa2ae39e12dfe8a7158db2fa21072055059b..eef85b801d3fdb3f62eb04e378b77a6cad634dae 100644 (file)
@@ -2172,7 +2172,7 @@ int get_cpuinfo(char * buffer)
                                "fpu_exception\t: %s\n"
                                "cpuid level\t: %d\n"
                                "wp\t\t: %s\n"
-                               "features\t:",
+                               "flags\t:",
                             c->fdiv_bug ? "yes" : "no",
                             c->hlt_works_ok ? "no" : "yes",
                             c->f00f_bug ? "yes" : "no",
index 57a07765ec49e410ee2cdc42efb059da8f3ce109..858e7dda0bc76489c9774c8962681ec6ce5e8153 100644 (file)
@@ -886,8 +886,10 @@ void __init smp_boot_cpus(void)
        /*
         * If we couldn't find a local APIC, then get out of here now!
         */
-       if (!verify_local_APIC()) {
-               printk(KERN_ERR "BIOS bug, local APIC at 0x%lX not detected!...\n", mp_lapic_addr);
+       if (APIC_INTEGRATED(apic_version[boot_cpu_id]) &&
+           !test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) {
+               printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+                       boot_cpu_id);
                printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
 #ifndef CONFIG_VISWS
                io_apic_irqs = 0;
@@ -897,6 +899,8 @@ void __init smp_boot_cpus(void)
                goto smp_done;
        }
 
+       verify_local_APIC();
+
        /*
         * If SMP should be disabled, then really disable it!
         */
index b8442137454d7d25ec9eeb75ae48eae16f38638c..f2077f2f274d909721eb3c39ee8be7d716eefbef 100644 (file)
@@ -62,20 +62,8 @@ struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
  */
 struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
 
-extern int console_loglevel;
 extern void bust_spinlocks(void);
 
-static inline void console_silent(void)
-{
-       console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
-       if (console_loglevel)
-               console_loglevel = 15;
-}
-
 asmlinkage void divide_error(void);
 asmlinkage void debug(void);
 asmlinkage void nmi(void);
index 30d4def40c8c7ab994420b78304afec6007c9c13..b3646e275c94a29f7e74a91599efc88db6000282 100644 (file)
@@ -181,7 +181,7 @@ int get_irq_list(char *buf)
 
 #ifdef CONFIG_SMP
 unsigned int global_irq_holder = NO_PROC_ID;
-volatile unsigned int global_irq_lock;
+volatile unsigned long global_irq_lock; /* long for set_bit --RR */
 
 extern void show_stack(unsigned long* esp);
 
index 445a99780dc759bc94d2356392ab2156fed26ec3..9b9bab2bdcbcb5d7fd9df92d73b648fff1fd837f 100644 (file)
@@ -27,8 +27,6 @@ volatile struct baboon *baboon;
 
 void baboon_irq(int, void *, struct pt_regs *);
 
-extern int console_loglevel;
-
 extern int macide_ack_intr(ide_hwif_t *);
 
 /*
index ef02d9bb98b91fa80776edb9388c2cfc9d524247..1a1a38e60149015e3a97225f612c2ac6ee0cbff2 100644 (file)
@@ -115,8 +115,6 @@ static void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
        via_init_clock(vector);
 }
 
-extern int console_loglevel;
-
 #if 0
 void mac_waitbut (void)
 {
index febba19824db9df97c789b2dd15cef372a71393a..061b01bd8ec9f2911cf136fb097befb34732c2f8 100644 (file)
@@ -211,8 +211,6 @@ static void scc_irq_disable(int);
  * console_loglevel determines NMI handler function
  */
 
-extern int console_loglevel;
-
 extern void mac_bang(int, void *, struct pt_regs *);
 
 void mac_nmi_handler(int, void *, struct pt_regs *);
index c405fc0dad094571cd9c0feaa716ec0a1ef8f521..87d155ee0a7bc9516aff358b097d046dbe2fd316 100644 (file)
@@ -35,7 +35,6 @@ void oss_nubus_irq(int, void *, struct pt_regs *);
 
 extern void via1_irq(int, void *, struct pt_regs *);
 extern void mac_scc_dispatch(int, void *, struct pt_regs *);
-extern int console_loglevel;
 
 /*
  * Initialize the OSS
index 86bbf72cc90cd670c780bfd8ba3fcde1833ef13b..d792ef9874bf1a772fc51451aad7c49c1f158a19 100644 (file)
@@ -32,8 +32,6 @@ volatile __u8 *psc;
 
 void psc_irq(int, void *, struct pt_regs *);
 
-extern int console_loglevel;
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
index af001907d828707b1947f6a037210af74dccaf22..ec0b2ce1937359f6079572fbb192fca199ad949a 100644 (file)
@@ -74,7 +74,6 @@ void via_irq_clear(int irq);
 
 extern void mac_bang(int, void *, struct pt_regs *);
 extern void mac_scc_dispatch(int, void *, struct pt_regs *);
-extern int console_loglevel;
 extern int oss_present;
 
 /*
index 1d8bb4b282f7a4dc95338f9c6cfdf6eabd78ae77..82cd94fad2bd6a6d4628068a1789a81f257d2413 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
-extern int console_loglevel;
-
-static inline void console_silent(void)
-{
-       console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
-       if (console_loglevel)
-               console_loglevel = 15;
-}
-
 /*
  * Machine specific interrupt handlers
  */
index 997aee0c79bbc1964dc9c09e1a418fc5267b2dca..c6777f938695b328d05481cead12ba1c7ed56235 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
 
-extern int console_loglevel;
-
-static inline void console_silent(void)
-{
-       console_loglevel = 0;
-}
-
-static inline void console_verbose(void)
-{
-       if (console_loglevel)
-               console_loglevel = 15;
-}
-
 extern asmlinkage void __xtlb_mod(void);
 extern asmlinkage void __xtlb_tlbl(void);
 extern asmlinkage void __xtlb_tlbs(void);
index 71fbe46651063f40856469289302fb5eb9d97c69..4af4f6565b9075c7c6d24084a6a1517d94e55873 100644 (file)
@@ -47,12 +47,6 @@ extern pgm_check_handler_t do_page_fault;
 
 asmlinkage int system_call(void);
 
-static inline void console_verbose(void)
-{
-        extern int console_loglevel;
-        console_loglevel = 15;
-}
-
 #define DO_ERROR(trapnr, signr, str, name, tsk) \
 asmlinkage void name(struct pt_regs * regs, long error_code) \
 { \
index db11c124707219300ca11dcb4de061b49e22068a..4aeaf8efa0c7e7eebbb11930465d00037a123287 100644 (file)
 #include <asm/atomic.h>
 #include <asm/processor.h>
 
-static inline void console_verbose(void)
-{
-       extern int console_loglevel;
-       console_loglevel = 15;
-}
-
 #define DO_ERROR(trapnr, signr, str, name, tsk) \
 asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
                          unsigned long r6, unsigned long r7, \
index cca4ec269e42cee7516905eb6d6bd45b41ec1f03..96c5b2b3961bbd368a834609e900c78a62075d31 100644 (file)
@@ -347,9 +347,10 @@ static void generic_plug_device(request_queue_t *q, kdev_t dev)
  */
 static inline void __generic_unplug_device(request_queue_t *q)
 {
-       if (!list_empty(&q->queue_head)) {
+       if (q->plugged) {
                q->plugged = 0;
-               q->request_fn(q);
+               if (!list_empty(&q->queue_head))
+                       q->request_fn(q);
        }
 }
 
@@ -383,6 +384,8 @@ static void blk_init_free_list(request_queue_t *q)
        spin_lock_init(&q->request_lock);
 }
 
+static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
+
 /**
  * blk_init_queue  - prepare a request queue for use with a block device
  * @q:    The &request_queue_t to be initialised
@@ -416,7 +419,6 @@ static void blk_init_free_list(request_queue_t *q)
  *    blk_init_queue() must be paired with a blk_cleanup-queue() call
  *    when the block device is deactivated (such as at module unload).
  **/
-static int __make_request(request_queue_t * q, int rw,  struct buffer_head * bh);
 void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
 {
        INIT_LIST_HEAD(&q->queue_head);
index a4108cf0ec42a94be0e0965e71b5ae69eae8e17a..f3c098b43a6d44a89a318ad53101e16d3fff70cd 100644 (file)
@@ -53,7 +53,6 @@ extern void (*adb_mouse_interrupt_hook)(unsigned char *, int);
 extern int adb_emulate_buttons;
 extern int adb_button2_keycode;
 extern int adb_button3_keycode;
-extern int console_loglevel;
 
 /*
  *    XXX: need to figure out what ADB mouse packets mean ... 
index c109c5965320e34b46c221120ac9f0d08f367de0..63f26cc0fdfb1c682ce5b4d8bf55bfe6f27cb0fe 100644 (file)
@@ -63,8 +63,8 @@
 #define PCI_DEVICE_ID_APPLICOM_PCIGENERIC     0x0001
 #define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB     0x0003
-#define MAX_PCI_DEVICE_NUM 3
 #endif
+#define MAX_PCI_DEVICE_NUM 3
 
 static char *applicom_pci_devnames[] = {
        "PCI board",
index 6adffb8a9273856dbcf3f42a4ec7a116216cab17..2b293c5ffc0df36c6fc9d8ef9f67d5b20dedff6c 100644 (file)
@@ -143,7 +143,7 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
        unsigned long end;
        int i;
 
-       DRM_DEBUG("dispatch_status = 0x%02x\n", dev_priv->dispatch_status);
+       DRM_DEBUG("dispatch_status = 0x%02lx\n", dev_priv->dispatch_status);
        end = jiffies + (HZ*3);
        while(1) {
                if(!test_and_set_bit(MGA_IN_DISPATCH,
@@ -154,7 +154,7 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
                        DRM_ERROR("irqs: %d wanted %d\n",
                                  atomic_read(&dev->total_irq),
                                  atomic_read(&dma->total_lost));
-                       DRM_ERROR("lockup: dispatch_status = 0x%02x,"
+                       DRM_ERROR("lockup: dispatch_status = 0x%02lx,"
                                  " jiffies = %lu, end = %lu\n",
                                  dev_priv->dispatch_status, jiffies, end);
                        return;
@@ -177,7 +177,7 @@ static inline void mga_dma_quiescent(drm_device_t *dev)
        sarea_priv->dirty |= MGA_DMA_FLUSH;
 
        clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status);
-       DRM_DEBUG("exit, dispatch_status = 0x%02x\n",
+       DRM_DEBUG("exit, dispatch_status = 0x%02lx\n",
                  dev_priv->dispatch_status);
 }
 
index 883eb75ca0311125cfc5ef14a4850d78007946a3..3937d97174ed560a18c19f7a8aa90e47817eb86f 100644 (file)
@@ -502,7 +502,7 @@ int mga_release(struct inode *inode, struct file *filp)
        if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)
            && dev->lock.pid == current->pid) {
                mga_reclaim_buffers(dev, priv->pid);
-               DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02x)\n",
+               DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02lx)\n",
                         current->pid,
                         _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock),
                         dev->dev_private ?
index e37cc2ef4ce17edfc28af5db73b47f8b4ff7bf45..59bb9c24773a415f71d9dbd1c07d26d89b15d65b 100644 (file)
@@ -38,7 +38,7 @@
 #define MGA_BUF_NEEDS_OVERFLOW 3
 
 typedef struct {
-       u32 buffer_status;
+       long buffer_status; /* long req'd for set_bit() --RR */
        int num_dwords;
        int max_dwords;
        u32 *current_dma_ptr;
@@ -62,7 +62,7 @@ typedef struct _drm_mga_freelist {
 #define MGA_IN_GETBUF    3
 
 typedef struct _drm_mga_private {
-       u32 dispatch_status;
+       long dispatch_status;   /* long req'd for set_bit() --RR */
        unsigned int next_prim_age;
        __volatile__ unsigned int last_prim_age;
        int reserved_map_idx;
index 90f16ca350eefb38a9cdee5f61b8dfc99df66a8b..8b156f69c83ab203f6dde939c6cb430c47eeeab0 100644 (file)
@@ -54,7 +54,7 @@ static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 };
 #define FLASHCOM_WATCHDOG_OFFSET 0x4
 #define FLASHCOM_ID 0x18
 
-static int mixcomwd_opened;
+static long mixcomwd_opened; /* long req'd for setbit --RR */
 
 static int watchdog_port;
 
index b2d959f369eaed1d2cb24b82fa16e4ed869714dc..7ceccdcbc44362bc631edb7bd065fcbb00315303 100644 (file)
@@ -152,7 +152,7 @@ struct moxa_str {
        unsigned short closing_wait;
        int count;
        int blocked_open;
-       int event;
+       long event; /* long req'd for set_bit --RR */
        int asyncflags;
        long session;
        long pgrp;
index 12c47eae2116cc3c191123fe556bbf8dacdebdcd..4c65963870a44a2206b728f4445cf08358e68ffa 100644 (file)
@@ -110,7 +110,7 @@ struct    Host
     struct UnixRup         UnixRups[MAX_RUP+LINKS_PER_UNIT];
        int                             timeout_id;     /* For calling 100 ms delays */
        int                             timeout_sem;/* For calling 100 ms delays */
-    int locks;
+    long locks; /* long req'd for set_bit --RR */
     char                   ____end_marker____;
 };
 #define Control      CardP->DpControl
index d00e3c4fe38291c14e17bc9c14cca804d1a41abf..c4511137c0785b9b22625f73b0c338b82a62582b 100644 (file)
@@ -77,7 +77,7 @@
 
 #define RS_EVENT_WRITE_WAKEUP  0
 
-DECLARE_TASK_QUEUE(tq_riscom);
+static DECLARE_TASK_QUEUE(tq_riscom);
 
 #define RISCOM_TYPE_NORMAL     1
 #define RISCOM_TYPE_CALLOUT    2
@@ -146,38 +146,38 @@ static inline int rc_paranoia_check(struct riscom_port const * port,
  */
 
 /* Get board number from pointer */
-extern inline int board_No (struct riscom_board const * bp)
+static inline int board_No (struct riscom_board const * bp)
 {
        return bp - rc_board;
 }
 
 /* Get port number from pointer */
-extern inline int port_No (struct riscom_port const * port)
+static inline int port_No (struct riscom_port const * port)
 {
        return RC_PORT(port - rc_port); 
 }
 
 /* Get pointer to board from pointer to port */
-extern inline struct riscom_board * port_Board(struct riscom_port const * port)
+static inline struct riscom_board * port_Board(struct riscom_port const * port)
 {
        return &rc_board[RC_BOARD(port - rc_port)];
 }
 
 /* Input Byte from CL CD180 register */
-extern inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg)
+static inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg)
 {
        return inb(bp->base + RC_TO_ISA(reg));
 }
 
 /* Output Byte to CL CD180 register */
-extern inline void rc_out(struct riscom_board const * bp, unsigned short reg,
+static inline void rc_out(struct riscom_board const * bp, unsigned short reg,
                          unsigned char val)
 {
        outb(val, bp->base + RC_TO_ISA(reg));
 }
 
 /* Wait for Channel Command Register ready */
-extern inline void rc_wait_CCR(struct riscom_board const * bp)
+static inline void rc_wait_CCR(struct riscom_board const * bp)
 {
        unsigned long delay;
 
@@ -193,7 +193,7 @@ extern inline void rc_wait_CCR(struct riscom_board const * bp)
  *  RISCom/8 probe functions.
  */
 
-extern inline int rc_check_io_range(struct riscom_board * const bp)
+static inline int rc_check_io_range(struct riscom_board * const bp)
 {
        int i;
        
@@ -206,7 +206,7 @@ extern inline int rc_check_io_range(struct riscom_board * const bp)
        return 0;
 }
 
-extern inline void rc_request_io_range(struct riscom_board * const bp)
+static inline void rc_request_io_range(struct riscom_board * const bp)
 {
        int i;
        
@@ -214,7 +214,7 @@ extern inline void rc_request_io_range(struct riscom_board * const bp)
                request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1, "RISCom/8" );
 }
 
-extern inline void rc_release_io_range(struct riscom_board * const bp)
+static inline void rc_release_io_range(struct riscom_board * const bp)
 {
        int i;
        
@@ -224,7 +224,7 @@ extern inline void rc_release_io_range(struct riscom_board * const bp)
 
        
 /* Must be called with enabled interrupts */
-extern inline void rc_long_delay(unsigned long delay)
+static inline void rc_long_delay(unsigned long delay)
 {
        unsigned long i;
        
@@ -326,7 +326,7 @@ static int __init rc_probe(struct riscom_board *bp)
  * 
  */
 
-extern inline void rc_mark_event(struct riscom_port * port, int event)
+static inline void rc_mark_event(struct riscom_port * port, int event)
 {
        /* 
          * I'm not quite happy with current scheme all serial
@@ -341,7 +341,7 @@ extern inline void rc_mark_event(struct riscom_port * port, int event)
        mark_bh(RISCOM8_BH);
 }
 
-extern inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
+static inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
                                               unsigned char const * what)
 {
        unsigned char channel;
@@ -359,7 +359,7 @@ extern inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
        return NULL;
 }
 
-extern inline void rc_receive_exc(struct riscom_board const * bp)
+static inline void rc_receive_exc(struct riscom_board const * bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
@@ -422,7 +422,7 @@ extern inline void rc_receive_exc(struct riscom_board const * bp)
        queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-extern inline void rc_receive(struct riscom_board const * bp)
+static inline void rc_receive(struct riscom_board const * bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
@@ -452,7 +452,7 @@ extern inline void rc_receive(struct riscom_board const * bp)
        queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-extern inline void rc_transmit(struct riscom_board const * bp)
+static inline void rc_transmit(struct riscom_board const * bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
@@ -521,7 +521,7 @@ extern inline void rc_transmit(struct riscom_board const * bp)
                rc_mark_event(port, RS_EVENT_WRITE_WAKEUP);
 }
 
-extern inline void rc_check_modem(struct riscom_board const * bp)
+static inline void rc_check_modem(struct riscom_board const * bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
@@ -634,7 +634,7 @@ static void rc_interrupt(int irq, void * dev_id, struct pt_regs * regs)
  */
 
 /* Called with disabled interrupts */
-extern inline int rc_setup_board(struct riscom_board * bp)
+static inline int rc_setup_board(struct riscom_board * bp)
 {
        int error;
 
@@ -657,7 +657,7 @@ extern inline int rc_setup_board(struct riscom_board * bp)
 }
 
 /* Called with disabled interrupts */
-extern inline void rc_shutdown_board(struct riscom_board *bp)
+static inline void rc_shutdown_board(struct riscom_board *bp)
 {
        if (!(bp->flags & RC_BOARD_ACTIVE))
                return;
@@ -1399,7 +1399,7 @@ static int rc_set_modem_info(struct riscom_port * port, unsigned int cmd,
        return 0;
 }
 
-extern inline void rc_send_break(struct riscom_port * port, unsigned long length)
+static inline void rc_send_break(struct riscom_port * port, unsigned long length)
 {
        struct riscom_board *bp = port_Board(port);
        unsigned long flags;
@@ -1417,7 +1417,7 @@ extern inline void rc_send_break(struct riscom_port * port, unsigned long length
        restore_flags(flags);
 }
 
-extern inline int rc_set_serial_info(struct riscom_port * port,
+static inline int rc_set_serial_info(struct riscom_port * port,
                                     struct serial_struct * newinfo)
 {
        struct serial_struct tmp;
@@ -1467,7 +1467,7 @@ extern inline int rc_set_serial_info(struct riscom_port * port,
        return 0;
 }
 
-extern inline int rc_get_serial_info(struct riscom_port * port,
+static inline int rc_get_serial_info(struct riscom_port * port,
                                     struct serial_struct * retinfo)
 {
        struct serial_struct tmp;
@@ -1820,7 +1820,7 @@ static void rc_release_drivers(void)
  * addresses in this case.
  *
  */ 
-void __init riscom8_setup(char *str, int * ints)
+static void __init riscom8_setup(char *str, int * ints)
 {
        int i;
 
@@ -1831,12 +1831,14 @@ void __init riscom8_setup(char *str, int * ints)
                        rc_board[i].base = 0;
        }
 }
+
+__setup("riscom8=", riscom8_setup);
 #endif
 
 /* 
  * This routine must be called by kernel at boot time 
  */
-int __init  riscom8_init(void)
+static int __init riscom8_init(void)
 {
        int i;
        int found = 0;
@@ -1859,22 +1861,24 @@ int __init  riscom8_init(void)
 }
 
 #ifdef MODULE
-int iobase  = 0;
-int iobase1 = 0;
-int iobase2 = 0;
-int iobase3 = 0;
+static int iobase;
+static int iobase1;
+static int iobase2;
+static int iobase3;
 MODULE_PARM(iobase, "i");
 MODULE_PARM(iobase1, "i");
 MODULE_PARM(iobase2, "i");
 MODULE_PARM(iobase3, "i");
+#endif /* MODULE */
 
 /*
  * You can setup up to 4 boards (current value of RC_NBOARD)
  * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
  *
  */
-int init_module(void) 
+static int __init riscom8_init_module (void)
 {
+#ifdef MODULE
        int i;
 
        if (iobase || iobase1 || iobase2 || iobase3) {
@@ -1890,11 +1894,12 @@ int init_module(void)
                rc_board[2].base = iobase2;
        if (iobase3)
                rc_board[3].base = iobase3;
-       
+#endif /* MODULE */
+
        return riscom8_init();
 }
        
-void cleanup_module(void)
+static void __exit riscom8_exit_module (void)
 {
        int i;
        
@@ -1904,4 +1909,7 @@ void cleanup_module(void)
                        rc_release_io_range(&rc_board[i]);
        
 }
-#endif /* MODULE */
+
+module_init(riscom8_init_module);
+module_exit(riscom8_exit_module);
+
index 3b2b9e78df6ec9af1d794748d670508455b94618..da6a8b1b60a6ee00247c7317a1f65b7c9a0bb47e 100644 (file)
@@ -71,7 +71,7 @@ struct riscom_port {
        struct tty_struct       * tty;
        int                     count;
        int                     blocked_open;
-       int                     event;
+       long                    event; /* long req'd for set_bit --RR */
        int                     timeout;
        int                     close_delay;
        long                    session;
index 3c05aa042306f33d38f0be420ece2852673207ff..71773fa6c8db8957ec4026707ad22c0a0079d66d 100644 (file)
@@ -27,7 +27,6 @@
 
 extern void wakeup_bdflush(int);
 extern void reset_vc(unsigned int);
-extern int console_loglevel;
 extern struct list_head super_blocks;
 
 /* Whether we react on sysrq keys or just ignore them */
index d2a5ae37ef878597d8ab5ccd95e06a4c4323db3d..f00c68ed450c8a9a7e12aee194f5b898251e3537 100644 (file)
@@ -1841,9 +1841,9 @@ static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
        memset(&pc, 0, sizeof (pc));
        pc.sense = &sense;
 
-       pc.c[0] = GPCMD_PLAY_AUDIO_10;
-       put_unaligned(cpu_to_be32(lba_start), (unsigned int *) &pc.c[2]);
-       put_unaligned(cpu_to_be16(lba_end - lba_start), (unsigned int *) &pc.c[7]);
+       pc.c[0] = GPCMD_PLAY_AUDIO_MSF;
+       lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
+       lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
 
        return cdrom_queue_packet_command(drive, &pc);
 }
index e03992b45defc081a108d13a0475736d3f79acc1..79f96fe188233d591a979cb58365e3841037e05b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: avm_pci.c,v 1.22.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: avm_pci.c,v 1.22.6.2 2000/11/29 16:00:14 kai Exp $
  *
  * avm_pci.c    low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
  *              Thanks to AVM, Berlin for informations
@@ -18,7 +18,7 @@
 #include <linux/interrupt.h>
 
 extern const char *CardType[];
-static const char *avm_pci_rev = "$Revision: 1.22.6.1 $";
+static const char *avm_pci_rev = "$Revision: 1.22.6.2 $";
 
 #define  AVM_FRITZ_PCI         1
 #define  AVM_FRITZ_PNP         2
@@ -758,7 +758,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static struct pci_dev *dev_avm __initdata;
+static struct pci_dev *dev_avm __initdata = NULL;
 
 int __init
 setup_avm_pcipnp(struct IsdnCard *card)
index 777a787af6897ec798eec635d72175b974bf1b64..c8a4896a9f0272a2e0245e020773ee82e36ae530 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bkm_a4t.c,v 1.13.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: bkm_a4t.c,v 1.13.6.2 2000/11/29 16:00:14 kai Exp $
  * bkm_a4t.c    low level stuff for T-Berkom A4T
  *              derived from the original file sedlbauer.c
  *              derived from the original file niccy.c
@@ -24,7 +24,7 @@
 
 extern const char *CardType[];
 
-const char *bkm_a4t_revision = "$Revision: 1.13.6.1 $";
+const char *bkm_a4t_revision = "$Revision: 1.13.6.2 $";
 
 
 static inline u_char
@@ -264,7 +264,7 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return (0);
 }
 
-static struct pci_dev *dev_a4t __initdata;
+static struct pci_dev *dev_a4t __initdata = NULL;
 
 int __init
 setup_bkm_a4t(struct IsdnCard *card)
index 86042a9badf91763a7ee2cfb7a0e46f509e69555..45011d356a7fc3f17b2ad35f3952ea4e301a72f0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bkm_a8.c,v 1.14.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: bkm_a8.c,v 1.14.6.2 2000/11/29 16:00:14 kai Exp $
  * bkm_a8.c     low level stuff for Scitel Quadro (4*S0, passive)
  *              derived from the original file sedlbauer.c
  *              derived from the original file niccy.c
@@ -27,7 +27,7 @@
 
 extern const char *CardType[];
 
-const char sct_quadro_revision[] = "$Revision: 1.14.6.1 $";
+const char sct_quadro_revision[] = "$Revision: 1.14.6.2 $";
 
 static const char *sct_quadro_subtypes[] =
 {
@@ -283,12 +283,12 @@ sct_alloc_io(u_int adr, u_int len)
        return(0);
 }
 
-static struct pci_dev *dev_a8 __initdata;
-static u16  sub_vendor_id __initdata;
-static u16  sub_sys_id __initdata;
-static u_char pci_bus __initdata;
-static u_char pci_device_fn __initdata;
-static u_char pci_irq __initdata;
+static struct pci_dev *dev_a8 __initdata = NULL;
+static u16  sub_vendor_id __initdata = 0;
+static u16  sub_sys_id __initdata = 0;
+static u_char pci_bus __initdata = 0;
+static u_char pci_device_fn __initdata = 0;
+static u_char pci_irq __initdata = 0;
 
 #endif /* CONFIG_PCI */
 
index f498a197c43e7dfb05740334b1ac0e633b51f225..499970ea202a96253dc88d4b5672ff4f6ffc4c50 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: config.c,v 2.57.6.2 2000/11/28 23:45:42 kai Exp $
+/* $Id: config.c,v 2.57.6.3 2000/11/29 17:48:59 kai Exp $
  *
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -340,14 +340,14 @@ struct IsdnCard cards[] =
        EMPTY_CARD,
 };
 
-static char HiSaxID[64] __devinitdata;
+static char HiSaxID[64] __devinitdata = { 0, };
 
 char *HiSax_id __devinitdata = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
-static int type[8] __devinitdata;
-static int protocol[8] __devinitdata;
-static int io[8] __devinitdata;
+static int type[8] __devinitdata = { 0, };
+static int protocol[8] __devinitdata = { 0, };
+static int io[8] __devinitdata = { 0, };
 #undef IO0_IO1
 #ifdef CONFIG_HISAX_16_3
 #define IO0_IO1
@@ -357,11 +357,11 @@ static int io[8] __devinitdata;
 #define IO0_IO1
 #endif
 #ifdef IO0_IO1
-static int io0[8] __devinitdata;
-static int io1[8] __devinitdata;
+static int io0[8] __devinitdata = { 0, };
+static int io1[8] __devinitdata = { 0, };
 #endif
-static int irq[8] __devinitdata;
-static int mem[8] __devinitdata;
+static int irq[8] __devinitdata = { 0, };
+static int mem[8] __devinitdata = { 0, };
 static char *id __devinitdata = HiSaxID;
 
 MODULE_AUTHOR("Karsten Keil");
index 43c9a27273061f760232f2c6d8f6270dea889a76..8967accde77660b455e554daca0b5b1037be8a35 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: diva.c,v 1.25.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: diva.c,v 1.25.6.2 2000/11/29 16:00:14 kai Exp $
  *
  * diva.c     low level stuff for Eicon.Diehl Diva Family ISDN cards
  *
@@ -24,7 +24,7 @@
 
 extern const char *CardType[];
 
-const char *Diva_revision = "$Revision: 1.25.6.1 $";
+const char *Diva_revision = "$Revision: 1.25.6.2 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -820,9 +820,9 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static         struct pci_dev *dev_diva __initdata;
-static         struct pci_dev *dev_diva_u __initdata;
-static         struct pci_dev *dev_diva201 __initdata;
+static struct pci_dev *dev_diva __initdata = NULL;
+static struct pci_dev *dev_diva_u __initdata = NULL;
+static struct pci_dev *dev_diva201 __initdata = NULL;
 
 int __init
 setup_diva(struct IsdnCard *card)
index 065ca9fea11fe7fca30a5691b3814a72daddcac8..11db6b9eedf4130c7fce6ffc44f7f09bf9c3512b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: gazel.c,v 2.11.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: gazel.c,v 2.11.6.2 2000/11/29 16:00:14 kai Exp $
  *
  * gazel.c     low level stuff for Gazel isdn cards
  *
@@ -19,7 +19,7 @@
 #include <linux/pci.h>
 
 extern const char *CardType[];
-const char *gazel_revision = "$Revision: 2.11.6.1 $";
+const char *gazel_revision = "$Revision: 2.11.6.2 $";
 
 #define R647      1
 #define R685      2
@@ -544,7 +544,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
        return (0);
 }
 
-static struct pci_dev *dev_tel __initdata;
+static struct pci_dev *dev_tel __initdata = NULL;
 
 static int
 setup_gazelpci(struct IsdnCardState *cs)
index 5a451ef1dfc388533105de751600effcc5c79a0c..b22ed23e73ab0c812fe4c6433d8c80bf820ae52c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: niccy.c,v 1.15.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: niccy.c,v 1.15.6.2 2000/11/29 16:00:14 kai Exp $
  *
  * niccy.c  low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
  *          compatible (SAGEM cybermodem)
@@ -22,7 +22,7 @@
 #include <linux/pci.h>
 
 extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.15.6.1 $";
+const char *niccy_revision = "$Revision: 1.15.6.2 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -235,7 +235,7 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static struct pci_dev *niccy_dev __initdata;
+static struct pci_dev *niccy_dev __initdata = NULL;
 
 int __init
 setup_niccy(struct IsdnCard *card)
index a3ca8aaa8ab80ff044cd1b92bf31415f09588fa7..4aaf9e1857a73fb07572afb3c2d910e3b65ed89a 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: nj_s.c,v 2.7 2000/11/24 17:05:38 kai Exp $
+// $Id: nj_s.c,v 2.7.6.1 2000/11/29 16:00:14 kai Exp $
 //
 // This file is (c) under GNU PUBLIC LICENSE
 //
@@ -14,7 +14,7 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_S_revision = "$Revision: 2.7 $";
+const char *NETjet_S_revision = "$Revision: 2.7.6.1 $";
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
@@ -140,7 +140,7 @@ NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static struct pci_dev *dev_netjet __initdata;
+static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_s(struct IsdnCard *card)
index 27964ca99e14102614ee7ab6551e3078789e5f23..a98724bd1a792469764455f2248653b30ac05f32 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: nj_u.c,v 2.8 2000/11/24 17:05:38 kai Exp $ 
+/* $Id: nj_u.c,v 2.8.6.1 2000/11/29 16:00:14 kai Exp $ 
  *
  * This file is (c) under GNU PUBLIC LICENSE
  *
@@ -15,7 +15,7 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_U_revision = "$Revision: 2.8 $";
+const char *NETjet_U_revision = "$Revision: 2.8.6.1 $";
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
@@ -142,7 +142,7 @@ NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static struct pci_dev *dev_netjet __initdata;
+static struct pci_dev *dev_netjet __initdata = NULL;
 
 int __init
 setup_netjet_u(struct IsdnCard *card)
index 3dc342c8d8ef6fe59578cc0193929bb5a312adc6..abe4d21986be71c4c607154d946c7641177567cc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.25.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: sedlbauer.c,v 1.25.6.2 2000/11/29 17:48:59 kai Exp $
  *
  * sedlbauer.c  low level stuff for Sedlbauer cards
  *              includes support for the Sedlbauer speed star (speed star II),
@@ -52,7 +52,7 @@
 
 extern const char *CardType[];
 
-const char *Sedlbauer_revision = "$Revision: 1.25.6.1 $";
+const char *Sedlbauer_revision = "$Revision: 1.25.6.2 $";
 
 const char *Sedlbauer_Types[] =
        {"None", "speed card/win", "speed star", "speed fax+", 
@@ -529,7 +529,7 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static         struct pci_dev *dev_sedl __devinitdata;
+static struct pci_dev *dev_sedl __devinitdata = NULL;
 
 int __devinit
 setup_sedlbauer(struct IsdnCard *card)
index 174f7fa93a70315d020a2c9d11165640b1e14fdd..83b640f8fe2a20f407e0b45a6c79218933bf8e49 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: telespci.c,v 2.16.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: telespci.c,v 2.16.6.2 2000/11/29 16:00:14 kai Exp $
  *
  * telespci.c     low level stuff for Teles PCI isdn cards
  *
@@ -18,7 +18,7 @@
 #include <linux/pci.h>
 
 extern const char *CardType[];
-const char *telespci_revision = "$Revision: 2.16.6.1 $";
+const char *telespci_revision = "$Revision: 2.16.6.2 $";
 
 #define ZORAN_PO_RQ_PEN        0x02000000
 #define ZORAN_PO_WR    0x00800000
@@ -275,7 +275,7 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return(0);
 }
 
-static struct pci_dev *dev_tel __initdata;
+static struct pci_dev *dev_tel __initdata = NULL;
 
 int __init
 setup_telespci(struct IsdnCard *card)
index 8b714ffbcf767f687682fd3564b4a705f7a21a6b..9afb73f90f5f90a02fbf2187c94c797d6b17c851 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: w6692.c,v 1.12.6.1 2000/11/28 12:02:46 kai Exp $
+/* $Id: w6692.c,v 1.12.6.2 2000/11/29 16:00:14 kai Exp $
  *
  * w6692.c   Winbond W6692 specific routines
  *
@@ -35,7 +35,7 @@ static const PCI_ENTRY id_list[] =
 
 extern const char *CardType[];
 
-const char *w6692_revision = "$Revision: 1.12.6.1 $";
+const char *w6692_revision = "$Revision: 1.12.6.2 $";
 
 #define DBUSY_TIMER_VALUE 80
 
@@ -957,7 +957,7 @@ w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 
 static int id_idx ;
 
-static struct pci_dev *dev_w6692 __initdata;
+static struct pci_dev *dev_w6692 __initdata = NULL;
 
 int __init 
 setup_w6692(struct IsdnCard *card)
index 662f4a7f5e06fe5530397026da3e4298df3a51f7..80616affaa4f67e70a1db32a733624d8fc0321c8 100644 (file)
@@ -255,8 +255,6 @@ int adb_button2_keycode = 0x7d;     /* right control key */
 int adb_button3_keycode = 0x7c; /* right option key */
 #endif
 
-extern int console_loglevel;
-
 extern struct kbd_struct kbd_table[];
 extern wait_queue_head_t keypress_wait;
 
index f4670f1dbb2c93813e0afa5b0672999db80e1e0d..c6e84f66f112ee1e1577210ebfced2dc7e8da112 100644 (file)
@@ -125,7 +125,6 @@ static int last_status;
 static int driver_running = 0;
 
 /* debug level 10 required for ADB logging (should be && debug_adb, ideally) */
-extern int console_loglevel;
 
 /* Check for MacII style ADB */
 static int macii_probe(void)
index 11c6474c79d76598747323b211bf998033a02ce7..886782f18f000c7819d8e0008a854df1cd259a24 100644 (file)
@@ -1319,6 +1319,24 @@ terratv_audio(struct bttv *btv, struct video_audio *v, int set)
        }
 }
 
+#ifndef MODULE
+
+static int __init bttv_card_setup(char *str)
+{
+       int i,number,res = 2;
+
+       for (i = 0; res == 2 && i < BTTV_MAX; i++) {
+               res = get_option(&str,&number);
+               if (res)
+                       card[i] = number;
+       }
+       return 1;
+}
+
+__setup("bttv_card=", bttv_card_setup);
+
+#endif /* not MODULE */
+
 /*
  * Local variables:
  * c-basic-offset: 8
index 6bc9c554ecb250c946c98c3e31822cbf5d5bf2ce..248bda8a02f0c0fdcf10a497d7e0fdf5b1715266 100644 (file)
@@ -3082,6 +3082,24 @@ void bttv_cleanup_module(void)
 module_init(bttv_init_module);
 module_exit(bttv_cleanup_module);
 
+#ifndef MODULE
+
+static int __init bttv_radio_setup(char *str)
+{
+       int i,number,res = 2;
+
+       for (i = 0; res == 2 && i < BTTV_MAX; i++) {
+               res = get_option(&str,&number);
+               if (res)
+                       radio[i] = number;
+       }
+       return 1;
+}
+
+__setup("bttv_radio=", bttv_radio_setup);
+
+#endif /* not MODULE */
+
 /*
  * Local variables:
  * c-basic-offset: 8
index 385beb49c64e63120498dbf46f459ec887106f5f..b6ae3f62c4f4cc87361def0d9295b26013bae395 100644 (file)
@@ -912,7 +912,7 @@ done:
        msp->thread = NULL;
 
        if(msp->notify != NULL)
-               up(msp->notify);
+               up_and_exit(msp->notify, 0);
        return 0;
 }
 
index 5ed1a1097ea7a688a578c7402d04f79624093b0e..da052eff57e6deab32118d391104befc640d61cc 100644 (file)
@@ -291,7 +291,7 @@ static int chip_thread(void *data)
        chip->thread = NULL;
        dprintk("%s: thread exiting\n", chip->c.name);
        if(chip->notify != NULL)
-               up(chip->notify);
+               up_and_exit(chip->notify,0);
 
        return 0;
 }
index 9023f0a81bbb2e3ddc49f39a037b869e76016fd0..c9747479a1f5c60561a4ce8b70713607a429a630 100644 (file)
@@ -23,6 +23,7 @@ if [ "$CONFIG_MTD" != "n" ]; then
    dep_tristate '  Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI
    if [ "$CONFIG_MTD_PMC551" != "n" ]; then
       bool '    PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX
+      bool '    PMC551 Debugging' CONFIG_MTD_PMC551_DEBUG
    fi
    dep_tristate '  Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD
    if [ "$CONFIG_MTD_MTDRAM" != "n" ]; then
index d6cce6474775066eb56e06aa146950d920adc4f4..6cb0de4e960d12a6d811b42ffc2fe41d4a96bb47 100644 (file)
@@ -437,7 +437,7 @@ static int cfi_amdext_erase_2_by_16 (struct mtd_info *mtd, struct erase_info *in
        adr = instr->addr - (chipnum << cfi->chipshift) * (cfi->interleave);
        len = instr->len;
 
-printk("erase : 0x%lx 0x%lx 0x%x 0x%x\n", adr, len, chipnum, mtd->size);
+       printk("erase : 0x%lx 0x%lx 0x%x 0x%lx\n", adr, len, chipnum, mtd->size);
 
        while(len) {
 //printk("erase : 0x%x 0x%x 0x%x 0x%x\n", chipnum, adr, len, cfi->chipshift);
index ce1b6fdd8292a3d7deead2488daac49f4f80afd8..584745359dbd611090168e5c0292478667abe4a6 100644 (file)
@@ -1,16 +1,7 @@
 /*======================================================================
 
-  $Id: doc1000.c,v 1.8 2000/07/03 10:01:38 dwmw2 Exp $
+  $Id: doc1000.c,v 1.11 2000/11/24 13:43:16 dwmw2 Exp $
 
-    A general driver for accessing PCMCIA card memory via Bulk
-    Memory Services.
-
-    This driver provides the equivalent of /dev/mem for a PCMCIA
-    card's attribute and common memory.  It includes character
-    and block devices.
-
-    Written by David Hinds, dhinds@allegro.stanford.edu
-    
 ======================================================================*/
 
 
@@ -295,10 +286,9 @@ int flashcard_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen
 static inline int byte_write (volatile u_char *addr, u_char byte)
 {
        register u_char status;
-       register u_short i;
-       
-       for (i = 0; i < max_tries; i++)
-       {
+       register u_short i = 0;
+       
+       do {
                status = readb(addr);
                if (status & CSR_WR_READY)
                {
@@ -306,7 +296,9 @@ static inline int byte_write (volatile u_char *addr, u_char byte)
                        writeb(byte, addr);
                        return 0;
                }
-       }
+               i++;
+       } while(i < max_tries);
+
                
        printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status);
        return -EIO;
@@ -314,11 +306,10 @@ static inline int byte_write (volatile u_char *addr, u_char byte)
 
 static inline int word_write (volatile u_char *addr, __u16 word)
 {
-       register u_short status = 0;
-       register u_short i;
+       register u_short status;
+       register u_short i = 0;
        
-       for (i = 0; i < max_tries; i++)
-       {
+       do {
                status = readw(addr);
                if ((status & CSR_WR_READY) == CSR_WR_READY)
                {
@@ -326,7 +317,8 @@ static inline int word_write (volatile u_char *addr, __u16 word)
                        writew(word, addr);
                        return 0;
                }
-       }
+               i++;
+       } while(i < max_tries);
                
        printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status);
        return -EIO;
@@ -362,24 +354,22 @@ static inline int check_erase(volatile u_char *addr)
 
 static inline int suspend_erase(volatile u_char *addr)
 {
-       __u16 status = 0;
-       u_long i;
+       __u16 status;
+       u_long i = 0;
        
        writew(IF_ERASE_SUSPEND, addr);
        writew(IF_READ_CSR, addr);
        
-       for (i = 0; i < max_tries; i++) 
-       {
+       do {
                status = readw(addr);
-               if ((status & CSR_WR_READY) == CSR_WR_READY) break;
-       }
-       if (i == max_tries)
-       {
-               printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
-           return -EIO;
-       }
-       
-       return 0;
+               if ((status & CSR_WR_READY) == CSR_WR_READY)
+                       return 0;
+               i++;
+       } while(i < max_tries);
+
+       printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status);
+       return -EIO;
+
 }
 
 static inline void resume_erase(volatile u_char *addr)
@@ -413,12 +403,11 @@ static inline void reset_block(volatile u_char *addr)
 
 static inline int check_write(volatile u_char *addr)
 {
-       u_short status = 0, i;
+       u_short status, i = 0;
        
        writew(IF_READ_CSR, addr);
        
-       for (i=0; i < max_tries; i++)
-       {
+       do {
                status = readw(addr);
                if (status & (CSR_WR_ERR | CSR_VPP_LOW))
                {
@@ -428,7 +417,9 @@ static inline int check_write(volatile u_char *addr)
                }
                if ((status & CSR_WR_READY) == CSR_WR_READY)
                        return 0;
-       }
+               i++;
+       } while (i < max_tries);
+
        printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status);
        return -EIO;
 }
@@ -519,7 +510,7 @@ static void flashcard_periodic(unsigned long data)
 
 }
 
-#if defined (MODULE) && LINUX_VERSION_CODE < 0x20300
+#if defined (MODULE) && LINUX_VERSION_CODE < 0x20211
 #define init_doc1000 init_module
 #define cleanup_doc1000 cleanup_module
 #endif
@@ -600,3 +591,7 @@ static void __init cleanup_doc1000(void)
        kfree(mymtd);
 }
 
+#if LINUX_VERSION_CODE >= 0x20211
+module_init(init_doc1000);
+module_exit(cleanup_doc1000);
+#endif
index 1cf4a5f160a0283783791d3e617cbd51ce605bfa..21ed0cecdafd8d23ce421a19539f4600201da654 100644 (file)
@@ -1,6 +1,10 @@
 /* This version ported to the Linux-MTD system by dwmw2@infradead.org
- * $Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $
- * Based on:
+ *
+ * - Based on Id: ftl.c,v 1.21 2000/08/01 13:07:49 dwmw2 Exp
+ * - With the Franz Galiana's set_bam_entry fix from v1.23
+ * - Perhaps it's about time I made a branch for the 2.4 series.
+
+ * Originally based on:
  */
 /*======================================================================
 
@@ -263,12 +267,13 @@ static struct block_device_operations ftl_blk_fops = {
 static int scan_header(partition_t *part)
 {
     erase_unit_header_t header;
-    loff_t offset;
+    loff_t offset, max_offset;
     int ret;
     part->header.FormattedSize = 0;
+    max_offset = (0x100000<part->mtd->size)?0x100000:part->mtd->size;
     /* Search first megabyte for a valid FTL header */
     for (offset = 0;
-        offset < 0x100000;
+        offset < max_offset;
         offset += part->mtd->erasesize?part->mtd->erasesize:0x2000) {
 
        ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret, 
@@ -280,7 +285,7 @@ static int scan_header(partition_t *part)
        if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
     }
 
-    if (offset == 0x100000) {
+    if (offset == max_offset) {
        printk(KERN_NOTICE "ftl_cs: FTL header not found.\n");
        return -ENOENT;
     }
@@ -998,7 +1003,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
 static int set_bam_entry(partition_t *part, u_int32_t log_addr,
                         u_int32_t virt_addr)
 {
-    u_int32_t bsize, blk;
+    u_int32_t bsize, blk, le_virt_addr;
 #ifdef PSYCHO_DEBUG
     u_int32_t old_addr;
 #endif
@@ -1035,6 +1040,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
        return -EIO;
     }
 #endif
+    le_virt_addr = cpu_to_le32(virt_addr);
     if (part->bam_index == eun) {
 #ifdef PSYCHO_DEBUG
        if (le32_to_cpu(part->bam_cache[blk]) != old_addr) {
@@ -1049,10 +1055,10 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
            return -EIO;
        }
 #endif
-       part->bam_cache[blk] = cpu_to_le32(virt_addr);
+       part->bam_cache[blk] = le_virt_addr;
     }
     ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t),
-                            &retlen, (u_char *)&part->bam_cache[blk]);
+                            &retlen, (u_char *)&le_virt_addr);
 
     if (ret) {
        printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n");
@@ -1410,8 +1416,6 @@ mod_init_t init_ftl(void)
 
     memset(myparts, 0, sizeof(myparts));
     
-    DEBUG(0, "$Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $\n");
-    
     if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) {
        printk(KERN_NOTICE "ftl_cs: unable to grab major "
               "device number!\n");
index fdc80cbcfd202435310d839b9f960f199697a3a4..ab9049356adeb09b8f97ed061bcf2576136974f3 100644 (file)
@@ -1,17 +1,17 @@
 /*
- * $Id: pmc551.c,v 1.8 2000/07/14 07:53:31 dwmw2 Exp $
+ * $Id: pmc551.c,v 1.11 2000/11/23 13:40:12 dwmw2 Exp $
  *
  * PMC551 PCI Mezzanine Ram Device
  *
  * Author:
- *       Mark Ferrell
+ *       Mark Ferrell <mferrell@mvista.com>
  *       Copyright 1999,2000 Nortel Networks
  *
- * License: 
+ * License:
  *      As part of this driver was derrived from the slram.c driver it falls
  *      under the same license, which is GNU General Public License v2
  *
- * Description: 
+ * Description:
  *      This driver is intended to support the PMC551 PCI Ram device from
  *      Ramix Inc.  The PMC551 is a PMC Mezzanine module for cPCI embeded
  *      systems.  The device contains a single SROM that initally programs the
  *      it as a block device allows us to use it as high speed swap or for a
  *      high speed disk device of some sort.  Which becomes very usefull on
  *      diskless systems in the embeded market I might add.
+ *      
+ * Notes:
+ *      Due to what I assume is more buggy SROM, the 64M PMC551 I have
+ *      available claims that all 4 of it's DRAM banks have 64M of ram 
+ *      configured (making a grand total of 256M onboard).  This is slightly
+ *      annoying since the BAR0 size reflects the aperture size, not the dram
+ *      size, and the V370PDC supplies no other method for memory size
+ *      discovery.  This problem is mostly only relivant when compiled as a
+ *      module, as the unloading of the module with an aperture size  smaller
+ *      then the ram will cause the driver to detect the onboard memory size
+ *      to be equal to the aperture size when the module is reloaded.  Soooo,
+ *      to help, the module supports an msize option to allow the
+ *      specification of the onboard memory, and an asize option, to allow the
+ *      specification of the aperture size.  The aperture must be equal to or
+ *      less then the memory size, the driver will correct this if you screw
+ *      it up.  This problem is not relivant for compiled in drivers as
+ *      compiled in drivers only init once.
  *
  * Credits:
  *       Saeed Karamooz <saeed@ramix.com> of Ramix INC. for the initial
@@ -31,7 +48,7 @@
  *       questions I had concerning operation of the device.
  *
  *       Most of the MTD code for this driver was originally written for the
- *       slram.o module in the MTD drivers package written by David Hinds 
+ *       slram.o module in the MTD drivers package written by David Hinds
  *       <dhinds@allegro.stanford.edu> which allows the mapping of system
  *       memory into an mtd device.  Since the PMC551 memory module is
  *       accessed in the same fashion as system memory, the slram.c code
@@ -44,9 +61,9 @@
  *       * Modified driver to utilize a sliding apature instead of mapping all
  *       memory into kernel space which turned out to be very wastefull.
  *       * Located a bug in the SROM's initialization sequence that made the
- *       memory unussable, added a fix to code to touch up the DRAM some.
+ *       memory unusable, added a fix to code to touch up the DRAM some.
  *
- * Bugs/FIXME's: 
+ * Bugs/FIXME's:
  *       * MUST fix the init function to not spin on a register
  *       waiting for it to set .. this does not safely handle busted devices
  *       that never reset the register correctly which will cause the system to
 #include <stdarg.h>
 #include <linux/pci.h>
 
+#ifndef CONFIG_PCI
+#error Enable PCI in your kernel config
+#endif
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/pmc551.h>
 #include <linux/mtd/compatmac.h>
@@ -347,14 +368,70 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
 #ifdef CONFIG_MTD_PMC551_BUGFIX
         u32 dram_data;
 #endif
-        u32 size, dcmd;
-        u16 cmd, i;
+        u32 size, dcmd, cfg, dtmp;
+        u16 cmd, tmp, i;
+       u8 bcmd, counter;
 
         /* Sanity Check */
         if(!dev) {
                 return -ENODEV;
         }
 
+       /*
+        * Attempt to reset the card
+        * FIXME: Stop Spinning registers
+        */
+       counter=0;
+       /* unlock registers */
+       pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 );
+       /* read in old data */
+       pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );
+       /* bang the reset line up and down for a few */
+       for(i=0;i<10;i++) {
+               counter=0;
+               bcmd &= ~0x80;
+               while(counter++ < 100) {
+                       pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
+               }
+               counter=0;
+               bcmd |= 0x80;
+               while(counter++ < 100) {
+                       pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
+               }
+       }
+       bcmd |= (0x40|0x20);
+       pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);
+
+        /* 
+        * Take care and turn off the memory on the device while we
+        * tweak the configurations
+        */
+        pci_read_config_word(dev, PCI_COMMAND, &cmd);
+        tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
+        pci_write_config_word(dev, PCI_COMMAND, tmp);
+
+       /*
+        * Disable existing aperture before probing memory size
+        */
+       pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);
+        dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN);
+       pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);
+       /*
+        * Grab old BAR0 config so that we can figure out memory size
+        * This is another bit of kludge going on.  The reason for the
+        * redundancy is I am hoping to retain the original configuration
+        * previously assigned to the card by the BIOS or some previous 
+        * fixup routine in the kernel.  So we read the old config into cfg,
+        * then write all 1's to the memory space, read back the result into
+        * "size", and then write back all the old config.
+        */
+       pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg );
+#ifndef CONFIG_MTD_PMC551_BUGFIX
+       pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 );
+       pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size );
+       pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
+       size=~(size&PCI_BASE_ADDRESS_MEM_MASK)+1;
+#else
         /*
          * Get the size of the memory by reading all the DRAM size values
          * and adding them up.
@@ -363,7 +440,6 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
          * row mux values.  We fix them here, but this will break other
          * memory configurations.
          */
-#ifdef CONFIG_MTD_PMC551_BUGFIX
         pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);
         size = PMC551_DRAM_BLK_GET_SIZE(dram_data);
         dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
@@ -387,7 +463,6 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
         dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);
         dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);
         pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);
-#endif /* CONFIG_MTD_PMC551_BUGFIX */
 
         /*
          * Oops .. something went wrong
@@ -395,34 +470,14 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
         if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {
                 return -ENODEV;
         }
+#endif /* CONFIG_MTD_PMC551_BUGFIX */
 
-        /*
-         * Set to be prefetchable
-         */
-        pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd );
-        dcmd |= 0x8;
-
-        /*
-         * Put it back the way it was
-         */
-        pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dcmd );
-        pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd );
-
-        /*
-         * Some screen fun
-         */
-        printk(KERN_NOTICE "pmc551: %dM (0x%x) of %sprefetchable memory at 0x%lx\n",
-               size/1024/1024, size, ((dcmd&0x8) == 0)?"non-":"",
-               PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK );
-
-        /*
-         * Turn on PCI memory and I/O bus access just for kicks
-         */
-        pci_write_config_word( dev, PCI_COMMAND,
-                               PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
+       if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
+                return -ENODEV;
+       }
 
         /*
-         * Config DRAM
+         * Precharge Dram
          */
         pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 );
         pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf );
@@ -431,11 +486,16 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
          * Wait untill command has gone through
          * FIXME: register spinning issue
          */
-        do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );
+        do {   pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );
+               if(counter++ > 100)break;
         } while ( (PCI_COMMAND_IO) & cmd );
 
         /*
-         * Must be held high for some duration of time to take effect??
+        * Turn on auto refresh 
+        * The loop is taken directly from Ramix's example code.  I assume that
+        * this must be held high for some duration of time, but I can find no
+        * documentation refrencing the reasons why.
+        * 
          */
         for ( i = 1; i<=8 ; i++) {
                 pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df);
@@ -444,7 +504,9 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
                  * Make certain command has gone through
                  * FIXME: register spinning issue
                  */
-                do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
+               counter=0;
+                do {   pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);
+                       if(counter++ > 100)break;
                 } while ( (PCI_COMMAND_IO) & cmd );
         }
 
@@ -455,7 +517,9 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
          * Wait until command completes
          * FIXME: register spinning issue
          */
-        do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd);
+       counter=0;
+        do {   pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd);
+               if(counter++ > 100)break;
         } while ( (PCI_COMMAND_IO) & cmd );
 
         pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd);
@@ -481,54 +545,97 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
                 cmd &= ~PCI_STATUS_DEVSEL_MASK;
                 pci_write_config_word( dev, PCI_STATUS, cmd );
         }
+        /*
+         * Set to be prefetchable and put everything back based on old cfg.
+        * it's possible that the reset of the V370PDC nuked the original
+        * settup
+         */
+        cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
+       pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );
+
+        /*
+         * Turn PCI memory and I/O bus access back on
+         */
+        pci_write_config_word( dev, PCI_COMMAND,
+                               PCI_COMMAND_MEMORY | PCI_COMMAND_IO );
+#ifdef CONFIG_MTD_PMC551_DEBUG
+        /*
+         * Some screen fun
+         */
+        printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n",
+              (size<1024)?size:(size<1048576)?size/1024:size/1024/1024,
+               (size<1024)?'B':(size<1048576)?'K':'M',
+              size, ((dcmd&(0x1<<3)) == 0)?"non-":"",
+               PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK );
 
         /*
          * Check to see the state of the memory
-         * FIXME: perhaps hide some of this around an #ifdef DEBUG as
-         * it doesn't effect or enhance cards functionality
          */
-        pci_read_config_dword( dev, 0x74, &dcmd );
-        printk(KERN_NOTICE "pmc551: DRAM_BLK3 Flags: %s,%s\n",
-               ((0x2&dcmd) == 0)?"RW":"RO",
-               ((0x1&dcmd) == 0)?"Off":"On" );
-
-        pci_read_config_dword( dev, 0x70, &dcmd );
-        printk(KERN_NOTICE "pmc551: DRAM_BLK2 Flags: %s,%s\n",
-               ((0x2&dcmd) == 0)?"RW":"RO",
-               ((0x1&dcmd) == 0)?"Off":"On" );
-
-        pci_read_config_dword( dev, 0x6C, &dcmd );
-        printk(KERN_NOTICE "pmc551: DRAM_BLK1 Flags: %s,%s\n",
-               ((0x2&dcmd) == 0)?"RW":"RO",
-               ((0x1&dcmd) == 0)?"Off":"On" );
-
-        pci_read_config_dword( dev, 0x68, &dcmd );
-        printk(KERN_NOTICE "pmc551: DRAM_BLK0 Flags: %s,%s\n",
-               ((0x2&dcmd) == 0)?"RW":"RO",
-               ((0x1&dcmd) == 0)?"Off":"On" );
-
-        pci_read_config_word( dev, 0x4, &cmd );
-        printk( KERN_NOTICE "pmc551: Memory Access %s\n",
-                ((0x2&cmd) == 0)?"off":"on" );
-        printk( KERN_NOTICE "pmc551: I/O Access %s\n",
-                ((0x1&cmd) == 0)?"off":"on" );
-
-        pci_read_config_word( dev, 0x6, &cmd );
-        printk( KERN_NOTICE "pmc551: Devsel %s\n",
+        pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd );
+        printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"
+                         "pmc551: DRAM_BLK0 Size: %d at %d\n"
+                         "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n",
+               (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+               (((0x1<<0)&dcmd) == 0)?"Off":"On",
+              PMC551_DRAM_BLK_GET_SIZE(dcmd),
+              ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+        pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd );
+        printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n"
+                         "pmc551: DRAM_BLK1 Size: %d at %d\n"
+                         "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n",
+               (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+               (((0x1<<0)&dcmd) == 0)?"Off":"On",
+              PMC551_DRAM_BLK_GET_SIZE(dcmd),
+              ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+        pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd );
+        printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n"
+                         "pmc551: DRAM_BLK2 Size: %d at %d\n"
+                         "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n",
+               (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+               (((0x1<<0)&dcmd) == 0)?"Off":"On",
+              PMC551_DRAM_BLK_GET_SIZE(dcmd),
+              ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+        pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd );
+        printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n"
+                         "pmc551: DRAM_BLK3 Size: %d at %d\n"
+                         "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n",
+               (((0x1<<1)&dcmd) == 0)?"RW":"RO",
+               (((0x1<<0)&dcmd) == 0)?"Off":"On",
+              PMC551_DRAM_BLK_GET_SIZE(dcmd),
+              ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) );
+
+        pci_read_config_word( dev, PCI_COMMAND, &cmd );
+        printk( KERN_DEBUG "pmc551: Memory Access %s\n",
+                (((0x1<<1)&cmd) == 0)?"off":"on" );
+        printk( KERN_DEBUG "pmc551: I/O Access %s\n",
+                (((0x1<<0)&cmd) == 0)?"off":"on" );
+
+        pci_read_config_word( dev, PCI_STATUS, &cmd );
+        printk( KERN_DEBUG "pmc551: Devsel %s\n",
                 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast":
                 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium":
                 ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" );
 
-        printk( KERN_NOTICE "pmc551: %sFast Back-to-Back\n",
+        printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n",
                 ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" );
 
+       pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );
+       printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n"
+                          "pmc551: System Control Register is %slocked to PCI access\n"
+                          "pmc551: System Control Register is %slocked to EEPROM access\n", 
+               (bcmd&0x1)?"software":"hardware",
+               (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un");
+#endif
         return size;
 }
 
 /*
  * Kernel version specific module stuffages
  */
-#if LINUX_VERSION_CODE < 0x20300
+#if LINUX_VERSION_CODE < 0x20211
 #ifdef MODULE
 #define init_pmc551 init_module
 #define cleanup_pmc551 cleanup_module
@@ -536,11 +643,27 @@ static u32 fixup_pmc551 (struct pci_dev *dev)
 #define __exit
 #endif
 
+#if defined(MODULE)
+MODULE_AUTHOR("Mark Ferrell <mferrell@mvista.com>");
+MODULE_DESCRIPTION(PMC551_VERSION);
+MODULE_PARM(msize, "i");
+MODULE_PARM_DESC(msize, "memory size, 6=32M, 7=64M, 8=128M, ect.. [32M-1024M]");
+MODULE_PARM(asize, "i");
+MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1M-1024M]");
+#endif
+/*
+ * Stuff these outside the ifdef so as to not bust compiled in driver support
+ */
+static int msize=0;
+#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
+static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE
+#else
+static int asize=0;
+#endif
 
 /*
  * PMC551 Card Initialization
  */
-//static int __init init_pmc551(void)
 int __init init_pmc551(void)
 {
         struct pci_dev *PCI_Device = NULL;
@@ -549,9 +672,23 @@ int __init init_pmc551(void)
         struct mtd_info *mtd;
         u32 length = 0;
 
+       if(msize) {
+               if (msize < 6 || msize > 11 ) {
+                       printk(KERN_NOTICE "pmc551: Invalid memory size\n");
+                       return -ENODEV;
+               }
+               msize = (512*1024)<<msize;
+       }
 
-        printk(KERN_NOTICE "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n");
-        printk(KERN_INFO "$Id: pmc551.c,v 1.8 2000/07/14 07:53:31 dwmw2 Exp $\n");
+       if(asize) {
+               if (asize < 1 || asize > 11 ) {
+                       printk(KERN_NOTICE "pmc551: Invalid aperture size\n");
+                       return -ENODEV;
+               }
+               asize = (512*1024)<<asize;
+       }
+
+        printk(KERN_INFO PMC551_VERSION);
 
         if(!pci_present()) {
                 printk(KERN_NOTICE "pmc551: PCI not enabled.\n");
@@ -583,6 +720,10 @@ int __init init_pmc551(void)
                         printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n");
                         break;
                 }
+               if(msize) {
+                       length = msize;
+                       printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length);
+               }
 
                 mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
                 if (!mtd) {
@@ -602,13 +743,44 @@ int __init init_pmc551(void)
                 mtd->priv = priv;
 
                 priv->dev = PCI_Device;
-                priv->aperture_size = PMC551_APERTURE_SIZE;
+               if(asize) {
+                       if(asize > length) {
+                               asize=length;
+                               printk(KERN_NOTICE "pmc551: reducing aperture size to fit memory [0x%x]\n",asize);
+                       } else {
+                               printk(KERN_NOTICE "pmc551: Using specified aperture size 0x%x\n", asize);
+                       }
+                       priv->aperture_size = asize;
+               } else {
+                       priv->aperture_size = length;
+               }
                 priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device)
                                        & PCI_BASE_ADDRESS_MEM_MASK),
                                       priv->aperture_size);
-                priv->mem_map0_base_val = (PMC551_APERTURE_VAL
-                                           | PMC551_PCI_MEM_MAP_REG_EN
-                                           | PMC551_PCI_MEM_MAP_ENABLE);
+               
+               /*
+                * Due to the dynamic nature of the code, we need to figure
+                * this out in order to stuff the register to set the proper
+                * aperture size.  If you know of an easier way to do this then
+                * PLEASE help yourself.
+                *
+                * Not with bloody floating point, you don't. Consider yourself
+                * duly LARTed. dwmw2.
+                */
+               {
+                       u32 size;
+                       u16 bits;
+                       size = priv->aperture_size>>20;
+                       for(bits=0;!(size&0x01)&&size>0;bits++,size=size>>1);
+                       //size=((u32)((log10(priv->aperture_size)/.30103)-19)<<4);
+                       priv->mem_map0_base_val = (PMC551_PCI_MEM_MAP_REG_EN
+                                               | PMC551_PCI_MEM_MAP_ENABLE
+                                               | size);
+#ifdef CONFIG_MTD_PMC551_DEBUG
+                       printk(KERN_NOTICE "pmc551: aperture set to %d[%d]\n", 
+                                       size, size>>4);
+#endif
+               }
                 priv->curr_mem_map0_val = priv->mem_map0_base_val;
 
                 pci_write_config_dword ( priv->dev,
@@ -641,7 +813,10 @@ int __init init_pmc551(void)
                        priv->aperture_size/1024/1024,
                        priv->start,
                        priv->start + priv->aperture_size);
-                printk(KERN_NOTICE "Total memory is %dM\n", length/1024/1024);
+                printk(KERN_NOTICE "Total memory is %d%c\n",
+                       (length<1024)?length:
+                               (length<1048576)?length/1024:length/1024/1024,
+                               (length<1024)?'B':(length<1048576)?'K':'M');
                priv->nextpmc551 = pmc551list;
                pmc551list = mtd;
                found++;
@@ -651,8 +826,8 @@ int __init init_pmc551(void)
                 printk(KERN_NOTICE "pmc551: not detected,\n");
                 return -ENODEV;
         } else {
-                return 0;
                printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found);
+                return 0;
        }
 }
 
@@ -669,7 +844,7 @@ static void __exit cleanup_pmc551(void)
                priv = (struct mypriv *)mtd->priv;
                pmc551list = priv->nextpmc551;
                
-               if(priv->start) 
+               if(priv->start)
                        iounmap(((struct mypriv *)mtd->priv)->start);
                
                kfree (mtd->priv);
@@ -681,10 +856,7 @@ static void __exit cleanup_pmc551(void)
        printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found);
 }
 
-#if LINUX_VERSION_CODE > 0x20300
+#if LINUX_VERSION_CODE >= 0x20211
 module_init(init_pmc551);
 module_exit(cleanup_pmc551);
 #endif
-
-
-
index b26b0630217d9c5b91214a1fb5636aaa6f5a291e..b66edcc44b3f407662187ab90a760e4346d64a10 100644 (file)
@@ -134,6 +134,7 @@ an MMIO register read.
 
 */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -141,18 +142,21 @@ an MMIO register read.
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 #include <linux/delay.h>
 #include <asm/io.h>
 
 
-#define RTL8139_VERSION "0.9.11"
-#define RTL8139_MODULE_NAME "8139too"
-#define RTL8139_DRIVER_NAME   RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION
-#define PFX RTL8139_MODULE_NAME ": "
+#define RTL8139_VERSION "0.9.12"
+#define MODNAME "8139too"
+#define RTL8139_DRIVER_NAME   MODNAME " Fast Ethernet driver " RTL8139_VERSION
+#define PFX MODNAME ": "
 
 
-/* define to 1 to enable PIO instead of MMIO */
-#undef USE_IO_OPS
+/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */
+#ifdef CONFIG_8139TOO_PIO
+#define USE_IO_OPS 1
+#endif
 
 /* define to 1 to enable copious debugging info */
 #undef RTL8139_DEBUG
@@ -502,12 +506,11 @@ struct rtl8139_private {
        int drv_flags;
        struct pci_dev *pci_dev;
        struct net_device_stats stats;
-       struct timer_list timer;        /* Media selection timer. */
        unsigned char *rx_ring;
        unsigned int cur_rx;    /* Index into the Rx buffer of next Rx pkt. */
        unsigned int tx_flag;
-       atomic_t cur_tx;
-       atomic_t dirty_tx;
+       unsigned int cur_tx;
+       unsigned int dirty_tx;
        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        struct ring_info tx_info[NUM_TX_DESC];
        unsigned char *tx_buf[NUM_TX_DESC];     /* Tx bounce buffers */
@@ -524,6 +527,9 @@ struct rtl8139_private {
        unsigned int mediasense:1;      /* Media sensing in progress. */
        spinlock_t lock;
        chip_t chipset;
+       pid_t thr_pid;
+       wait_queue_head_t thr_wait;
+       struct semaphore thr_exited;
 };
 
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
@@ -538,7 +544,7 @@ static int rtl8139_open (struct net_device *dev);
 static int mdio_read (struct net_device *dev, int phy_id, int location);
 static void mdio_write (struct net_device *dev, int phy_id, int location,
                        int val);
-static void rtl8139_timer (unsigned long data);
+static int rtl8139_thread (void *data);
 static void rtl8139_tx_timeout (struct net_device *dev);
 static void rtl8139_init_ring (struct net_device *dev);
 static int rtl8139_start_xmit (struct sk_buff *skb,
@@ -552,7 +558,6 @@ static inline u32 ether_crc (int length, unsigned char *data);
 static void rtl8139_set_rx_mode (struct net_device *dev);
 static void rtl8139_hw_start (struct net_device *dev);
 
-
 #ifdef USE_IO_OPS
 
 #define RTL_R8(reg)            inb (((unsigned long)ioaddr) + (reg))
@@ -648,6 +653,7 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
                DPRINTK ("EXIT, returning -ENOMEM\n");
                return -ENOMEM;
        }
+       SET_MODULE_OWNER(dev);
        tp = dev->priv;
 
        pio_start = pci_resource_start (pdev, 0);
@@ -867,7 +873,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        tp->pci_dev = pdev;
        tp->board = ent->driver_data;
        tp->mmio_addr = ioaddr;
-       tp->lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init (&tp->lock);
+       init_waitqueue_head (&tp->thr_wait);
+       init_MUTEX_LOCKED (&tp->thr_exited);
 
        pdev->driver_data = dev;
 
@@ -897,7 +905,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
        RTL_W8_F (HltClk, 'H'); /* 'R' would leave the clock running. */
 
        /* The lower four bits are the media type. */
-       option = (board_idx > 7) ? 0 : media[board_idx];
+       option = (board_idx >= ARRAY_SIZE(media)) ? 0 : media[board_idx];
        if (option > 0) {
                tp->full_duplex = (option & 0x200) ? 1 : 0;
                tp->default_port = option & 15;
@@ -1068,7 +1076,7 @@ static void mdio_sync (void *mdio_addr)
 
 static int mdio_read (struct net_device *dev, int phy_id, int location)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *mdio_addr = tp->mmio_addr + Config4;
        int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
        int retval = 0;
@@ -1111,7 +1119,7 @@ static int mdio_read (struct net_device *dev, int phy_id, int location)
 static void mdio_write (struct net_device *dev, int phy_id, int location,
                        int value)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *mdio_addr = tp->mmio_addr + Config4;
        int mii_cmd =
            (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
@@ -1154,7 +1162,7 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
 
 static int rtl8139_open (struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        int retval;
 #ifdef RTL8139_DEBUG
        void *ioaddr = tp->mmio_addr;
@@ -1162,12 +1170,9 @@ static int rtl8139_open (struct net_device *dev)
 
        DPRINTK ("ENTER\n");
 
-       MOD_INC_USE_COUNT;
-
        retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
        if (retval) {
                DPRINTK ("EXIT, returning %d\n", retval);
-               MOD_DEC_USE_COUNT;
                return retval;
        }
 
@@ -1186,13 +1191,13 @@ static int rtl8139_open (struct net_device *dev)
                                            tp->rx_ring, tp->rx_ring_dma);
 
                DPRINTK ("EXIT, returning -ENOMEM\n");
-               MOD_DEC_USE_COUNT;
                return -ENOMEM;
 
        }
 
        tp->full_duplex = tp->duplex_lock;
        tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
+       tp->twistie = 1;
 
        rtl8139_init_ring (dev);
        rtl8139_hw_start (dev);
@@ -1203,13 +1208,10 @@ static int rtl8139_open (struct net_device *dev)
                        dev->irq, RTL_R8 (MediaStatus),
                        tp->full_duplex ? "full" : "half");
 
-       /* Set the timer to switch to check for link beat and perhaps switch
-          to an alternate media type. */
-       init_timer (&tp->timer);
-       tp->timer.expires = jiffies + 3 * HZ;
-       tp->timer.data = (unsigned long) dev;
-       tp->timer.function = &rtl8139_timer;
-       add_timer (&tp->timer);
+       tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);
+       if (tp->thr_pid < 0)
+               printk (KERN_WARNING "%s: unable to start kernel thread\n",
+                       dev->name);
 
        DPRINTK ("EXIT, returning 0\n");
        return 0;
@@ -1219,7 +1221,7 @@ static int rtl8139_open (struct net_device *dev)
 /* Start the hardware at open or resume. */
 static void rtl8139_hw_start (struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        u32 i;
        u8 tmp;
@@ -1311,14 +1313,14 @@ static void rtl8139_hw_start (struct net_device *dev)
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void rtl8139_init_ring (struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        int i;
 
        DPRINTK ("ENTER\n");
 
        tp->cur_rx = 0;
-       atomic_set (&tp->cur_tx, 0);
-       atomic_set (&tp->dirty_tx, 0);
+       tp->cur_tx = 0;
+       tp->dirty_tx = 0;
 
        for (i = 0; i < NUM_TX_DESC; i++) {
                tp->tx_info[i].skb = NULL;
@@ -1330,7 +1332,10 @@ static void rtl8139_init_ring (struct net_device *dev)
 }
 
 
-#ifndef RTL_TUNE_TWISTER
+/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */
+static int next_tick = 3 * HZ;
+
+#ifndef CONFIG_8139TOO_TUNE_TWISTER
 static inline void rtl8139_tune_twister (struct net_device *dev,
                                  struct rtl8139_private *tp) {}
 #else
@@ -1338,6 +1343,7 @@ static void rtl8139_tune_twister (struct net_device *dev,
                                  struct rtl8139_private *tp)
 {
        int linkcase;
+       void *ioaddr = tp->mmio_addr;
 
        DPRINTK ("ENTER\n");
 
@@ -1421,15 +1427,13 @@ static void rtl8139_tune_twister (struct net_device *dev,
 
        DPRINTK ("EXIT\n");
 }
-#endif /* RTL_TUNE_TWISTER */
+#endif /* CONFIG_8139TOO_TUNE_TWISTER */
 
 
-static void rtl8139_timer (unsigned long data)
+static inline void rtl8139_thread_iter (struct net_device *dev,
+                                struct rtl8139_private *tp,
+                                void *ioaddr)
 {
-       struct net_device *dev = (struct net_device *) data;
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
-       void *ioaddr = tp->mmio_addr;
-       int next_tick = 60 * HZ;
        int mii_reg5;
 
        mii_reg5 = mdio_read (dev, tp->phys[0], 5);
@@ -1450,6 +1454,8 @@ static void rtl8139_timer (unsigned long data)
                }
        }
 
+       next_tick = HZ * 60;
+
        rtl8139_tune_twister (dev, tp);
 
        DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",
@@ -1462,9 +1468,33 @@ static void rtl8139_timer (unsigned long data)
        DPRINTK ("%s:  Chip config %2.2x %2.2x.\n",
                 dev->name, RTL_R8 (Config0),
                 RTL_R8 (Config1));
+}
+
+
+static int rtl8139_thread (void *data)
+{
+       struct net_device *dev = data;
+       struct rtl8139_private *tp = dev->priv;
+       unsigned long timeout;
 
-       tp->timer.expires = jiffies + next_tick;
-       add_timer (&tp->timer);
+       daemonize ();
+       sprintf (current->comm, "k8139d-%s", dev->name);
+
+       while (1) {
+               timeout = next_tick;
+               do {
+                       timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
+               } while (!signal_pending (current) && (timeout > 0));
+
+               if (signal_pending (current))
+                       break;
+
+               rtnl_lock ();
+               rtl8139_thread_iter (dev, tp, tp->mmio_addr);
+               rtnl_unlock ();
+       }
+
+       up_and_exit (&tp->thr_exited, 0);
 }
 
 
@@ -1472,8 +1502,8 @@ static void rtl8139_tx_clear (struct rtl8139_private *tp)
 {
        int i;
 
-       atomic_set (&tp->cur_tx, 0);
-       atomic_set (&tp->dirty_tx, 0);
+       tp->cur_tx = 0;
+       tp->dirty_tx = 0;
 
        /* Dump the unsent Tx packets. */
        for (i = 0; i < NUM_TX_DESC; i++) {
@@ -1494,11 +1524,10 @@ static void rtl8139_tx_clear (struct rtl8139_private *tp)
 
 static void rtl8139_tx_timeout (struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        int i;
        u8 tmp8;
-       unsigned long flags;
 
        DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
                 "media %2.2x.\n", dev->name,
@@ -1516,20 +1545,17 @@ static void rtl8139_tx_timeout (struct net_device *dev)
 
        /* Emit info to figure out what went wrong. */
        printk (KERN_DEBUG "%s: Tx queue start entry %d  dirty entry %d.\n",
-               dev->name, atomic_read (&tp->cur_tx),
-               atomic_read (&tp->dirty_tx));
+               dev->name, tp->cur_tx, tp->dirty_tx);
        for (i = 0; i < NUM_TX_DESC; i++)
                printk (KERN_DEBUG "%s:  Tx descriptor %d is %8.8lx.%s\n",
                        dev->name, i, RTL_R32 (TxStatus0 + (i * 4)),
-                       i == atomic_read (&tp->dirty_tx) % NUM_TX_DESC ?
+                       i == tp->dirty_tx % NUM_TX_DESC ?
                                " (queue head)" : "");
 
        /* Stop a shared interrupt from scavenging while we are. */
-       spin_lock_irqsave (&tp->lock, flags);
-       
+       spin_lock_irq (&tp->lock);
        rtl8139_tx_clear (tp);
-
-       spin_unlock_irqrestore (&tp->lock, flags);
+       spin_unlock_irq (&tp->lock);
 
        /* ...and finally, reset everything */
        rtl8139_hw_start (dev);
@@ -1539,27 +1565,37 @@ static void rtl8139_tx_timeout (struct net_device *dev)
 
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        int entry;
 
        /* Calculate the next Tx descriptor entry. */
-       entry = atomic_read (&tp->cur_tx) % NUM_TX_DESC;
+       entry = tp->cur_tx % NUM_TX_DESC;
 
        assert (tp->tx_info[entry].skb == NULL);
        assert (tp->tx_info[entry].mapping == 0);
 
        tp->tx_info[entry].skb = skb;
-       /* tp->tx_info[entry].mapping = 0; */
-       memcpy (tp->tx_buf[entry], skb->data, skb->len);
+       if ((long) skb->data & 3) {     /* Must use alignment buffer. */
+               /* tp->tx_info[entry].mapping = 0; */
+               memcpy (tp->tx_buf[entry], skb->data, skb->len);
+               RTL_W32 (TxAddr0 + (entry * 4),
+                        tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs));
+       } else {
+               tp->tx_info[entry].mapping =
+                   pci_map_single (tp->pci_dev, skb->data, skb->len,
+                                   PCI_DMA_TODEVICE);
+               RTL_W32 (TxAddr0 + (entry * 4), tp->tx_info[entry].mapping);
+       }
 
        /* Note: the chip doesn't have auto-pad! */
-       RTL_W32 (TxStatus0 + (entry * sizeof(u32)),
+       RTL_W32 (TxStatus0 + (entry * sizeof (u32)),
                 tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
        dev->trans_start = jiffies;
-       atomic_inc (&tp->cur_tx);
-       if ((atomic_read (&tp->cur_tx) - atomic_read (&tp->dirty_tx)) >= NUM_TX_DESC)
+       tp->cur_tx++;
+       mb();
+       if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
                netif_stop_queue (dev);
 
        DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",
@@ -1573,16 +1609,14 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
                                  struct rtl8139_private *tp,
                                  void *ioaddr)
 {
-       int cur_tx, dirty_tx, tx_left;
+       unsigned int dirty_tx, tx_left;
 
        assert (dev != NULL);
        assert (tp != NULL);
        assert (ioaddr != NULL);
 
-       dirty_tx = atomic_read (&tp->dirty_tx);
-
-       cur_tx = atomic_read (&tp->cur_tx);
-       tx_left = cur_tx - dirty_tx;
+       dirty_tx = tp->dirty_tx;
+       tx_left = tp->cur_tx - dirty_tx;
        while (tx_left > 0) {
                int entry = dirty_tx % NUM_TX_DESC;
                int txstatus;
@@ -1632,29 +1666,27 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
                }
                dev_kfree_skb_irq (tp->tx_info[entry].skb);
                tp->tx_info[entry].skb = NULL;
-               dirty_tx++;
-               if (dirty_tx < 0) { /* handle signed int overflow */
-                       atomic_sub (cur_tx, &tp->cur_tx); /* XXX racy? */
-                       dirty_tx = cur_tx - tx_left + 1;
-               }
-               if (netif_queue_stopped (dev))
-                       netif_wake_queue (dev);
-
-               cur_tx = atomic_read (&tp->cur_tx);
-               tx_left = cur_tx - dirty_tx;
 
+               dirty_tx++;
+               tx_left--;
        }
 
 #ifndef RTL8139_NDEBUG
-       if (atomic_read (&tp->cur_tx) - dirty_tx > NUM_TX_DESC) {
+       if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
                printk (KERN_ERR
                  "%s: Out-of-sync dirty pointer, %d vs. %d.\n",
-                    dev->name, dirty_tx, atomic_read (&tp->cur_tx));
+                    dev->name, dirty_tx, tp->cur_tx);
                dirty_tx += NUM_TX_DESC;
        }
 #endif /* RTL8139_NDEBUG */
 
-       atomic_set (&tp->dirty_tx, dirty_tx);
+       /* only wake the queue if we did work, and the queue is stopped */
+       if (tp->dirty_tx != dirty_tx) {
+               tp->dirty_tx = dirty_tx;
+               mb();
+               if (netif_queue_stopped (dev))
+                       netif_wake_queue (dev);
+       }
 }
 
 
@@ -1879,7 +1911,7 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
                               struct pt_regs *regs)
 {
        struct net_device *dev = (struct net_device *) dev_instance;
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        int boguscnt = max_interrupt_work;
        void *ioaddr = tp->mmio_addr;
        int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
@@ -1962,20 +1994,27 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
 
 static int rtl8139_close (struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
-       unsigned long flags;
+       int ret = 0;
 
        DPRINTK ("ENTER\n");
 
        netif_stop_queue (dev);
 
+       if (tp->thr_pid >= 0) {
+               ret = kill_proc (tp->thr_pid, SIGTERM, 1);
+               if (ret) {
+                       printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
+                       return ret;
+               }
+               down (&tp->thr_exited);
+       }
+
        DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n",
                        dev->name, RTL_R16 (IntrStatus));
 
-       del_timer_sync (&tp->timer);
-
-       spin_lock_irqsave (&tp->lock, flags);
+       spin_lock_irq (&tp->lock);
 
        /* Stop the chip's Tx and Rx DMA processes. */
        RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear));
@@ -1987,7 +2026,7 @@ static int rtl8139_close (struct net_device *dev)
        tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
        RTL_W32 (RxMissed, 0);
 
-       spin_unlock_irqrestore (&tp->lock, flags);
+       spin_unlock_irq (&tp->lock);
 
        synchronize_irq ();
        free_irq (dev->irq, dev);
@@ -2006,8 +2045,6 @@ static int rtl8139_close (struct net_device *dev)
        RTL_W8 (Config1, 0x03);
        RTL_W8 (HltClk, 'H');   /* 'R' would leave the clock running. */
 
-       MOD_DEC_USE_COUNT;
-
        DPRINTK ("EXIT\n");
        return 0;
 }
@@ -2015,9 +2052,8 @@ static int rtl8139_close (struct net_device *dev)
 
 static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        u16 *data = (u16 *) & rq->ifr_data;
-       unsigned long flags;
        int rc = 0;
 
        DPRINTK ("ENTER\n");
@@ -2028,9 +2064,7 @@ static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
                /* Fall Through */
 
        case SIOCDEVPRIVATE + 1:        /* Read the specified MII register. */
-               spin_lock_irqsave (&tp->lock, flags);
                data[3] = mdio_read (dev, data[0], data[1] & 0x1f);
-               spin_unlock_irqrestore (&tp->lock, flags);
                break;
 
        case SIOCDEVPRIVATE + 2:        /* Write the specified MII register */
@@ -2039,9 +2073,7 @@ static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
                        break;
                }
 
-               spin_lock_irqsave (&tp->lock, flags);
                mdio_write (dev, data[0], data[1] & 0x1f, data[2]);
-               spin_unlock_irqrestore (&tp->lock, flags);
                break;
 
        default:
@@ -2056,22 +2088,14 @@ static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 
 static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
 
        DPRINTK ("ENTER\n");
 
-       assert (tp != NULL);
-
        if (netif_running(dev)) {
-               unsigned long flags;
-
-               spin_lock_irqsave (&tp->lock, flags);
-
                tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
                RTL_W32 (RxMissed, 0);
-
-               spin_unlock_irqrestore (&tp->lock, flags);
        }
 
        DPRINTK ("EXIT\n");
@@ -2104,7 +2128,7 @@ static inline u32 ether_crc (int length, unsigned char *data)
 
 static void rtl8139_set_rx_mode (struct net_device *dev)
 {
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        u32 mc_filter[2];       /* Multicast hash filter */
        int i, rx_mode;
@@ -2160,7 +2184,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev)
 static void rtl8139_suspend (struct pci_dev *pdev)
 {
        struct net_device *dev = pdev->driver_data;
-       struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       struct rtl8139_private *tp = dev->priv;
        void *ioaddr = tp->mmio_addr;
        unsigned long flags;
 
@@ -2190,7 +2214,7 @@ static void rtl8139_resume (struct pci_dev *pdev)
 
 
 static struct pci_driver rtl8139_pci_driver = {
-       name:           RTL8139_MODULE_NAME,
+       name:           MODNAME,
        id_table:       rtl8139_pci_tbl,
        probe:          rtl8139_init_one,
        remove:         rtl8139_remove_one,
index 9bbaf963128d8abe58beda235d4bd158a05ec5e3..a4ec3fb54b6416c763e347c6ead204d8c8c3254f 100644 (file)
@@ -38,6 +38,7 @@
   Paul Gortmaker       : add kmod support for auto-loading of the 8390
                          module by all drivers that require it.
   Alan Cox             : Spinlocking work, added 'BUG_83C690'
+  Paul Gortmaker       : Separate out Tx timeout code from Tx path.
 
   Sources:
   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -105,6 +106,7 @@ int ei_debug = 1;
 /* Index to functions. */
 static void ei_tx_intr(struct net_device *dev);
 static void ei_tx_err(struct net_device *dev);
+static void ei_tx_timeout(struct net_device *dev);
 static void ei_receive(struct net_device *dev);
 static void ei_rx_overrun(struct net_device *dev);
 
@@ -161,6 +163,13 @@ int ei_open(struct net_device *dev)
                printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
                return -ENXIO;
        }
+       
+       /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout
+           wrapper that does e.g. media check & then calls ei_tx_timeout. */
+       if (dev->tx_timeout == NULL)
+                dev->tx_timeout = ei_tx_timeout;
+       if (dev->watchdog_timeo <= 0)
+                dev->watchdog_timeo = TX_TIMEOUT;
     
        /*
         *      Grab the page lock so we own the register set, then call
@@ -200,89 +209,66 @@ int ei_close(struct net_device *dev)
 }
 
 /**
- * ei_start_xmit - begin packet transmission
- * @skb: packet to be sent
- * @dev: network device to which packet is sent
+ * ei_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
  *
- * Sends a packet to an 8390 network device.
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
  */
-static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+
+void ei_tx_timeout(struct net_device *dev)
 {
        long e8390_base = dev->base_addr;
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
-       int length, send_length, output_page;
+       int txsr, isr, tickssofar = jiffies - dev->trans_start;
        unsigned long flags;
 
-       /*
-        *  If it has been too long since the last Tx, we assume the
-        *  board has died and kick it.
-        */
-       if (netif_queue_stopped(dev)) {
-               /* Do timeouts, just like the 8003 driver. */
-               int txsr;
-               int isr;
-               int tickssofar = jiffies - dev->trans_start;
-
-               /*
-                *      Need the page lock. Now see what went wrong. This bit is
-                *      fast.
-                */
-                               
-               spin_lock_irqsave(&ei_local->page_lock, flags);
-               txsr = inb(e8390_base+EN0_TSR);
-               if (tickssofar < TX_TIMEOUT ||  (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) 
-               {
-                       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-                       return 1;
-               }
-
-               ei_local->stat.tx_errors++;
-               isr = inb(e8390_base+EN0_ISR);
-               if (!netif_running(dev)) {
-                       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-                       printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name);
-                       return 1;
-               }
-
-               /*
-                * Note that if the Tx posted a TX_ERR interrupt, then the
-                * error will have been handled from the interrupt handler
-                * and not here. Error statistics are handled there as well.
-                */
+       ei_local->stat.tx_errors++;
 
-               printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
-                       dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
-                       (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       txsr = inb(e8390_base+EN0_TSR);
+       isr = inb(e8390_base+EN0_ISR);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
 
-               if (!isr && !ei_local->stat.tx_packets) 
-               {
-                       /* The 8390 probably hasn't gotten on the cable yet. */
-                       ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
-               }
+       printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+               dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
+               (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
 
-               /*
-                *      Play shuffle the locks, a reset on some chips takes a few
-                *      mS. We very rarely hit this point.
-                */
-                
-               spin_unlock_irqrestore(&ei_local->page_lock, flags);
+       if (!isr && !ei_local->stat.tx_packets) 
+       {
+               /* The 8390 probably hasn't gotten on the cable yet. */
+               ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
+       }
 
-               /* Ugly but a reset can be slow, yet must be protected */
+       /* Ugly but a reset can be slow, yet must be protected */
                
-               disable_irq_nosync(dev->irq);
-               spin_lock(&ei_local->page_lock);
+       disable_irq_nosync(dev->irq);
+       spin_lock(&ei_local->page_lock);
                
-               /* Try to restart the card.  Perhaps the user has fixed something. */
-               ei_reset_8390(dev);
-               NS8390_init(dev, 1);
+       /* Try to restart the card.  Perhaps the user has fixed something. */
+       ei_reset_8390(dev);
+       NS8390_init(dev, 1);
                
-               spin_unlock(&ei_local->page_lock);
-               enable_irq(dev->irq);
-               dev->trans_start = jiffies;
-       }
+       spin_unlock(&ei_local->page_lock);
+       enable_irq(dev->irq);
+       netif_wake_queue(dev);
+}
     
+/**
+ * ei_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = (struct ei_device *) dev->priv;
+       int length, send_length, output_page;
+       unsigned long flags;
+
        length = skb->len;
 
        /* Mask interrupts from the ethercard. 
@@ -1147,6 +1133,7 @@ static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
 EXPORT_SYMBOL(ei_open);
 EXPORT_SYMBOL(ei_close);
 EXPORT_SYMBOL(ei_interrupt);
+EXPORT_SYMBOL(ei_tx_timeout);
 EXPORT_SYMBOL(ethdev_init);
 EXPORT_SYMBOL(NS8390_init);
 
index 5c00406b48815a19ad62fa1fc9a6ca082d531719..7a4c1a1d6e491b7d36fdd5e2235070c2b3de076f 100644 (file)
@@ -50,7 +50,6 @@ static const char *version =
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/version.h>
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -220,8 +219,10 @@ static struct net_device_stats *cops_get_stats (struct net_device *dev);
 int __init cops_probe(struct net_device *dev)
 {
        int i;
-        int base_addr = dev ? dev->base_addr : 0;
-        
+        int base_addr = dev->base_addr;
+
+       SET_MODULE_OWNER(dev);
+
         if(base_addr == 0 && io)
                base_addr=io;
 
@@ -235,13 +236,9 @@ int __init cops_probe(struct net_device *dev)
         * Dayna cards don't autoprobe well at all, but if your card is
         * at IRQ 5 & IO 0x240 we find it every time. ;) JS
         */
-        for(i=0; cops_portlist[i]; i++) {
-               int ioaddr = cops_portlist[i];
-               if(check_region(ioaddr, COPS_IO_EXTENT))
-                        continue;
-                if(cops_probe1(dev, ioaddr) == 0)
+        for(i=0; cops_portlist[i]; i++)
+                if(cops_probe1(dev, cops_portlist[i]) == 0)
                         return 0;
-        }
        
         return -ENODEV;
 }
@@ -254,13 +251,17 @@ int __init cops_probe(struct net_device *dev)
 static int __init cops_probe1(struct net_device *dev, int ioaddr)
 {
         struct cops_local *lp;
-       static unsigned version_printed = 0;
-
+       static unsigned version_printed;
        int board = board_type;
+       int retval;
        
         if(cops_debug && version_printed++ == 0)
                printk("%s", version);
 
+       /* Grab the region so no one else tries to probe our ioports. */
+       if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name))
+               return -EBUSY;
+
         /*
          * Since this board has jumpered interrupts, allocate the interrupt
          * vector now. There is no point in waiting since no other device
@@ -273,13 +274,14 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
                case 0:
                        /* COPS AutoIRQ routine */
                        dev->irq = cops_irq(ioaddr, board);
-                       if(!dev->irq)
-                               return -EINVAL; /* No IRQ found on this port */
-                       break;
+                       if(!dev->irq) {
+                               retval = -EINVAL;       /* No IRQ found on this port */
+                               goto err_out;
+                       }
 
                case 1:
-                       return -EINVAL;
-                       break;
+                       retval = -EINVAL;
+                       goto err_out;
 
                /* Fixup for users that don't know that IRQ 2 is really
                 * IRQ 9, or don't know which one to set.
@@ -301,17 +303,22 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
        }
 
        /* Reserve any actual interrupt. */
-       if(dev->irq && request_irq(dev->irq, &cops_interrupt, 0, cardname, dev))
-               return -EINVAL;
+       if(dev->irq) {
+               retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev);
+               if (retval)
+                       goto err_out;
+       }
 
-       /* Grab the region so no one else tries to probe our ioports. */
-       request_region(ioaddr, COPS_IO_EXTENT, cardname);
-       dev->base_addr          = ioaddr;
+       dev->base_addr          = ioaddr;
 
        /* Initialize the private device structure. */
         dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL);
-        if(dev->priv == NULL)
-               return -ENOMEM;
+        if(dev->priv == NULL) {
+               if (dev->irq)
+                       free_irq(dev->irq, dev);
+               retval = -ENOMEM;
+               goto err_out;
+       }
 
         lp = (struct cops_local *)dev->priv;
         memset(lp, 0, sizeof(struct cops_local));
@@ -347,6 +354,10 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
 
        }
         return 0;
+
+err_out:
+       release_region(ioaddr, COPS_IO_EXTENT);
+       return retval;
 }
 
 static int __init cops_irq (int ioaddr, int board)
@@ -426,10 +437,6 @@ static int cops_open(struct net_device *dev)
        cops_jumpstart(dev);    /* Start the card up. */
 
        netif_start_queue(dev);
-#ifdef MODULE
-        MOD_INC_USE_COUNT;
-#endif
-
         return 0;
 }
 
@@ -990,10 +997,6 @@ static int cops_close(struct net_device *dev)
                del_timer(&cops_timer);
 
        netif_stop_queue(dev);
-#ifdef MODULE
-        MOD_DEC_USE_COUNT;
-#endif
-       
         return 0;
 }
 
@@ -1039,8 +1042,7 @@ void cleanup_module(void)
 {
         /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
        unregister_netdev(&cops0_dev);
-       if(cops0_dev.priv)
-                kfree(cops0_dev.priv);
+       kfree(cops0_dev.priv);
        if(cops0_dev.irq)
                free_irq(cops0_dev.irq, &cops0_dev);
         release_region(cops0_dev.base_addr, COPS_IO_EXTENT);
index 503c66167b8d7cba9dc31f1eb25f8abfacde732c..b7bca28da2c5b843e58a4f700ce7628a662d43d0 100644 (file)
@@ -62,22 +62,12 @@ static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt);
 static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 
-static int ipddp_open(struct net_device *dev)
-{
-        MOD_INC_USE_COUNT;
-        return 0;
-}
-
-static int ipddp_close(struct net_device *dev)
-{
-        MOD_DEC_USE_COUNT;
-        return 0;
-}
-
 static int __init ipddp_init(struct net_device *dev)
 {
        static unsigned version_printed = 0;
 
+       SET_MODULE_OWNER(dev);
+
        if (ipddp_debug && version_printed++ == 0)
                 printk("%s", version);
 
@@ -100,8 +90,6 @@ static int __init ipddp_init(struct net_device *dev)
                 return -ENOMEM;
         memset(dev->priv,0,sizeof(struct net_device_stats));
 
-       dev->open           = ipddp_open;
-        dev->stop          = ipddp_close;
         dev->get_stats      = ipddp_get_stats;
         dev->do_ioctl       = ipddp_ioctl;
 
@@ -298,7 +286,7 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
         }
 }
 
-static struct net_device dev_ipddp = { init: ipddp_init };
+static struct net_device dev_ipddp;
 
 MODULE_PARM(ipddp_mode, "i");
 
@@ -306,6 +294,7 @@ static int __init ipddp_init_module(void)
 {
        int err;
 
+       dev_ipddp.init = ipddp_init;
        err=dev_alloc_name(&dev_ipddp, "ipddp%d");
         if(err < 0)
                 return err;
index d9b81882412cc4be69495ab0685f6e6fcf9d1ac1..b55a37f28b97608f18e15d4303d5abf5b879aa2d 100644 (file)
@@ -206,11 +206,7 @@ static int io=0;
 static int irq=0;
 static int dma=0;
 
-#ifdef MODULE
 #include <linux/module.h>
-#include <linux/version.h>
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -710,22 +706,6 @@ static struct timer_list ltpc_timer;
 static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *ltpc_get_stats(struct net_device *dev);
 
-static int ltpc_open(struct net_device *dev)
-{
-#ifdef MODULE
-       MOD_INC_USE_COUNT;
-#endif
-       return 0;
-}
-
-static int ltpc_close(struct net_device *dev)
-{
-#ifdef MODULE
-       MOD_DEC_USE_COUNT;
-#endif
-       return 0;
-}
-
 static int read_30 ( struct net_device *dev)
 {
        lt_command c;
@@ -921,9 +901,6 @@ static int ltpc_init(struct net_device *dev)
        memset(dev->priv, 0, sizeof(struct ltpc_private));
        dev->get_stats = ltpc_get_stats;
 
-       dev->open = ltpc_open;
-       dev->stop = ltpc_close;
-
        /* add the ltpc-specific things */
        dev->do_ioctl = &ltpc_ioctl;
 
@@ -1008,7 +985,7 @@ static struct net_device_stats *ltpc_get_stats(struct net_device *dev)
 
 /* initialization stuff */
   
-int __init ltpc_probe_dma(int base)
+static int __init ltpc_probe_dma(int base)
 {
        int dma = 0;
        int timeout;
@@ -1087,6 +1064,8 @@ int __init ltpc_probe(struct net_device *dev)
        unsigned long flags;
        unsigned long f;
 
+       SET_MODULE_OWNER(dev);
+
        save_flags(flags);
 
        /* probe for the I/O port address */
@@ -1273,11 +1252,7 @@ static int __init ltpc_setup(char *str)
 __setup("ltpc=", ltpc_setup);
 #endif /* MODULE */
 
-static struct net_device dev_ltpc = {
-               "", 
-               0, 0, 0, 0,
-               0x0, 0,
-               0, 0, 0, NULL, ltpc_probe };
+static struct net_device dev_ltpc;
 
 #ifdef MODULE
 MODULE_PARM(debug, "i");
@@ -1295,6 +1270,7 @@ int __init init_module(void)
                       "ltpc: Autoprobing is not recommended for modules\n");
 
        /* Find a name for this unit */
+       dev_ltpc.init = ltpc_probe;
        err=dev_alloc_name(&dev_ltpc,"lt%d");
        
        if(err<0)
index b7718aba5ffa3024ecbea739d290be1a61c8f875..ee4ba5876a4c7ba1208d27d39b9fc4fdc3aa8cc5 100644 (file)
@@ -44,8 +44,6 @@ static int version_printed;
 #include <linux/etherdevice.h>
 #include "8390.h"
 
-extern int console_loglevel;
-
 int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
                                  int prom, struct nubus_dev *ndev);
 
index bf3a376a2d8a1c3670b922686f20eb7db55af7fd..1d974350cc775a3fb70561b0c92bc2d05c2fd0c5 100644 (file)
 static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *dummy_get_stats(struct net_device *dev);
 
-static int dummy_open(struct net_device *dev)
-{
-       MOD_INC_USE_COUNT;
-       return 0;
-}
-
-static int dummy_close(struct net_device *dev)
-{
-       MOD_DEC_USE_COUNT;
-       return 0;
-}
-
 /* fake multicast ability */
 static void set_multicast_list(struct net_device *dev)
 {
@@ -74,8 +62,6 @@ static int __init dummy_init(struct net_device *dev)
        memset(dev->priv, 0, sizeof(struct net_device_stats));
        dev->get_stats  = dummy_get_stats;
 
-       dev->open = dummy_open;
-       dev->stop = dummy_close;
        dev->set_multicast_list = set_multicast_list;
 
        /* Fill in the fields of the device structure with ethernet-generic values. */
@@ -107,12 +93,17 @@ static struct net_device_stats *dummy_get_stats(struct net_device *dev)
        return dev->priv;
 }
 
-static struct net_device dev_dummy = { init: dummy_init };
+static struct net_device dev_dummy;
 
 static int __init dummy_init_module(void)
 {
+       int err;
+
+       dev_dummy.init = dummy_init;
+       SET_MODULE_OWNER(&dev_dummy);
+
        /* Find a name for this unit */
-       int err=dev_alloc_name(&dev_dummy,"dummy%d");
+       err=dev_alloc_name(&dev_dummy,"dummy%d");
        if(err<0)
                return err;
        if (register_netdev(&dev_dummy) != 0)
index 112e0afbab4c3eca9418d85b1634e1f1911a01ec..e281511dcb5a5df2e4f0e4bac82ef32dd0fcb041 100644 (file)
@@ -201,6 +201,8 @@ static int __init eql_init(struct net_device *dev)
        /* static unsigned num_masters     = 0; */
        equalizer_t *eql = 0;
 
+       SET_MODULE_OWNER(dev);
+
        if ( version_printed++ == 0 && eql_debug > 0)
                printk(version);
        /*
@@ -259,8 +261,6 @@ static int eql_open(struct net_device *dev)
        equalizer_t *eql = (equalizer_t *) dev->priv;
        slave_queue_t *new_queue;
 
-       MOD_INC_USE_COUNT;
-
 #ifdef EQL_DEBUG
        if (eql_debug >= 5)
                printk ("%s: open\n", dev->name);
@@ -284,7 +284,6 @@ static int eql_open(struct net_device *dev)
 
                return 0;
        }
-       MOD_DEC_USE_COUNT;
        return -ENOMEM;
 }
 
@@ -310,7 +309,6 @@ static int eql_close(struct net_device *dev)
 
        eql_delete_slave_queue (eql->queue);
 
-       MOD_DEC_USE_COUNT;
        return 0;
 }
 
@@ -985,14 +983,12 @@ static void eql_timer(unsigned long param)
        }
 }
 
-static struct net_device dev_eql = 
-{
-       name:   "eql",
-       init:   eql_init,
-};
+static struct net_device dev_eql;
 
 static int __init eql_init_module(void)
 {
+       strcpy(dev_eql.name, "eql");
+       dev_eql.init = eql_init;
        if (register_netdev(&dev_eql) != 0) {
                printk("eql: register_netdev() returned non-zero.\n");
                return -EIO;
index b929c83a64e863878e6506110cdea1e573311490..08cee0485699d67d995edb6ec899f3b74d036cc2 100644 (file)
@@ -101,7 +101,8 @@ struct sixpack {
   int                  mtu;            /* Our mtu (to spot changes!)   */
   int                   buffsize;       /* Max buffers sizes            */
 
-  unsigned char                flags;          /* Flag values/ mode etc        */
+  unsigned long                flags;          /* Flag values/ mode etc        */
+                                       /* long req'd for set_bit --RR */
   unsigned char                mode;           /* 6pack mode                   */
 
 /* 6pack stuff */
index c24c278192c3398db36fda04611b269eeb2943a8..4a3d700cb18dc78f2352df27a2b208e106e4ec4b 100644 (file)
@@ -42,7 +42,8 @@ struct ax_disp {
        int                 buffsize;           /* Max buffers sizes            */
 
 
-       unsigned char       flags;              /* Flag values/ mode etc        */
+       unsigned long   flags;          /* Flag values/ mode etc        */
+                                       /* long req'd: used by set_bit --RR */
 #define AXF_INUSE      0               /* Channel in use               */
 #define AXF_ESCAPE     1               /* ESC received                 */
 #define AXF_ERROR      2               /* Parity, etc. error           */
index b476e290c6cb0280ff4013295f3b1847314965f3..1be9f6561fef290734ce6ff8f95b1511b9b7bd41 100644 (file)
@@ -406,7 +406,6 @@ static int shaper_open(struct net_device *dev)
                return -ENODEV;
        if(shaper->bitspersec==0)
                return -EINVAL;
-       MOD_INC_USE_COUNT;
        return 0;
 }
 
@@ -419,7 +418,6 @@ static int shaper_close(struct net_device *dev)
        struct shaper *shaper=dev->priv;
        shaper_flush(shaper);
        del_timer_sync(&shaper->timer);
-       MOD_DEC_USE_COUNT;
        return 0;
 }
 
@@ -618,34 +616,31 @@ static int shaper_ioctl(struct net_device *dev,  struct ifreq *ifr, int cmd)
        }
 }
 
-static struct shaper *shaper_alloc(struct net_device *dev)
+static void shaper_init_priv(struct net_device *dev)
 {
-       struct shaper *sh=kmalloc(sizeof(struct shaper), GFP_KERNEL);
-       if(sh==NULL)
-               return NULL;
-       memset(sh,0,sizeof(*sh));
+       struct shaper *sh = dev->priv;
+
        skb_queue_head_init(&sh->sendq);
        init_timer(&sh->timer);
        sh->timer.function=shaper_timer;
        sh->timer.data=(unsigned long)sh;
        init_waitqueue_head(&sh->wait_queue);
-       return sh;
 }
 
 /*
  *     Add a shaper device to the system
  */
  
-int __init shaper_probe(struct net_device *dev)
+static int __init shaper_probe(struct net_device *dev)
 {
        /*
         *      Set up the shaper.
         */
-       
-       dev->priv = shaper_alloc(dev);
-       if(dev->priv==NULL)
-               return -ENOMEM;
-               
+
+       SET_MODULE_OWNER(dev);
+
+       shaper_init_priv(dev);
+
        dev->open               = shaper_open;
        dev->stop               = shaper_close;
        dev->hard_start_xmit    = shaper_start_xmit;
@@ -685,89 +680,68 @@ int __init shaper_probe(struct net_device *dev)
        return 0;
 }
  
+static int shapers = 1;
 #ifdef MODULE
 
-static struct net_device dev_shape = 
-{
-       "",
-       0, 0, 0, 0,
-       0, 0,
-       0, 0, 0, NULL, shaper_probe 
-};
+MODULE_PARM(shapers, "i");
 
-int init_module(void)
-{
-       int err=dev_alloc_name(&dev_shape,"shaper%d");
-       if(err<0)
-               return err;
-       printk(SHAPER_BANNER);  
-       if (register_netdev(&dev_shape) != 0)
-               return -EIO;
-       printk("Traffic shaper initialised.\n");
-       return 0;
-}
+#else /* MODULE */
 
-void cleanup_module(void)
+static int __init set_num_shapers(char *str)
 {
-        struct shaper *sh=dev_shape.priv;
+       shapers = simple_strtol(str, NULL, 0);
+       return 1;
+}
 
-        /*
-        *      No need to check MOD_IN_USE, as sys_delete_module() checks.
-        *      To be unloadable we must be closed and detached so we don't
-        *      need to flush things.
-        */
-        
-       unregister_netdev(&dev_shape);
+__setup("shapers=", set_num_shapers);
 
-       /*
-        *      Free up the private structure, or leak memory :-)
-        */
-       kfree(sh);
-       dev_shape.priv = NULL;
-}
+#endif /* MODULE */
 
-#else
+static struct net_device *devs;
 
-static struct net_device dev_sh0 = 
+static int __init shaper_init(void)
 {
-       "shaper0",
-       0, 0, 0, 0,
-       0, 0,
-       0, 0, 0, NULL, shaper_probe 
-};
+       int i, err;
+       size_t alloc_size;
+       struct shaper *sp;
+       unsigned int shapers_registered = 0;
 
+       if (shapers < 1)
+               return -ENODEV;
 
-static struct net_device dev_sh1 = 
-{
-       "shaper1",
-       0, 0, 0, 0,
-       0, 0,
-       0, 0, 0, NULL, shaper_probe 
-};
+       alloc_size = (sizeof(*devs) * shapers) +
+                    (sizeof(struct shaper) * shapers);
+       devs = kmalloc(alloc_size, GFP_KERNEL);
+       if (!devs)
+               return -ENOMEM;
+       memset(devs, 0, alloc_size);
+       sp = (struct shaper *) &devs[shapers];
 
+       for (i = 0; i < shapers; i++) {
+               err = dev_alloc_name(&devs[i], "shaper%d");
+               if (err < 0)
+                       break;
+               devs[i].init = shaper_probe;
+               devs[i].priv = &sp[i];
+               if (register_netdev(&devs[i]))
+                       break;
+               shapers_registered++;
+       }
 
-static struct net_device dev_sh2 = 
-{
-       "shaper2",
-       0, 0, 0, 0,
-       0, 0,
-       0, 0, 0, NULL, shaper_probe 
-};
+       if (!shapers_registered) {
+               kfree(devs);
+               devs = NULL;
+       }
 
-static struct net_device dev_sh3 = 
-{
-       "shaper3",
-       0, 0, 0, 0,
-       0, 0,
-       0, 0, 0, NULL, shaper_probe 
-};
+       return (shapers_registered ? 0 : -ENODEV);
+}
 
-void shaper_init(void)
+static void __exit shaper_exit (void)
 {
-       register_netdev(&dev_sh0);
-       register_netdev(&dev_sh1);
-       register_netdev(&dev_sh2);
-       register_netdev(&dev_sh3);
+       kfree(devs);
+       devs = NULL;
 }
 
-#endif /* MODULE */
+module_init(shaper_init);
+module_exit(shaper_exit);
+
index 7420e569191f0ec41577d83a401e0603508afc05..6e8427a3b367dd22411b6295b02a4efe53c5fe5f 100644 (file)
@@ -549,7 +549,6 @@ sl_close(struct net_device *dev)
        sl->xleft    = 0;
        spin_unlock_bh(&sl->lock);
 
-       MOD_DEC_USE_COUNT;
        return 0;
 }
 
@@ -564,7 +563,6 @@ static int sl_open(struct net_device *dev)
 
        sl->flags &= (1 << SLF_INUSE);
        netif_start_queue(dev);
-       MOD_INC_USE_COUNT;
        return 0;
 }
 
@@ -647,6 +645,8 @@ static int sl_init(struct net_device *dev)
        dev->type               = ARPHRD_SLIP + sl->mode;
        dev->tx_queue_len       = 10;
 
+       SET_MODULE_OWNER(dev);
+
        dev_init_buffers(dev);
 
        /* New-style flags. */
index c9f064b1d5e27920b40a0168c8c0f81c94a5f758..bbd82fda55c832a91a656873dca9242662d37385 100644 (file)
@@ -91,7 +91,7 @@ struct slip {
   int                  xdata, xbits;   /* 6 bit slip controls          */
 #endif
 
-  unsigned int         flags;          /* Flag values/ mode etc        */
+  unsigned long                flags;          /* Flag values/ mode etc        */
 #define SLF_INUSE      0               /* Channel in use               */
 #define SLF_ESCAPE     1               /* ESC received                 */
 #define SLF_ERROR      2               /* Parity, etc. error           */
index 17d81a53456554533e9f64396f90e8b733cc366d..e23ad7a6ec60ada83c7634bdc95503fa4c43c26c 100644 (file)
@@ -237,6 +237,7 @@ subsequent_board:
                        printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
                                   "by a %s (%d) block.\n",
                                   dev->name, i, medianame[leaf->media], leaf->media,
+                                  leaf->type >= ARRAY_SIZE(block_name) ? "UNKNOWN" :
                                   block_name[leaf->type], leaf->type);
                }
                if (new_advertise)
index 8a80813aaabd80f805832a0579c3193561f398cd..0a44dcf9f225f28d0ee5de4bffcc0ec9cb5ad64c 100644 (file)
@@ -130,6 +130,7 @@ int tun_net_init(struct net_device *dev)
    
        DBG(KERN_INFO "%s: tun_net_init\n", tun->name);
 
+       SET_MODULE_OWNER(dev);
        dev->open = tun_net_open;
        dev->hard_start_xmit = tun_net_xmit;
        dev->stop = tun_net_close;
@@ -454,8 +455,6 @@ static int tun_chr_open(struct inode *inode, struct file * file)
        tun->dev.init = tun_net_init;
        tun->dev.priv = tun;
 
-       MOD_INC_USE_COUNT;
-       
        return 0;
 }
 
@@ -479,7 +478,6 @@ static int tun_chr_close(struct inode *inode, struct file *file)
        kfree(tun);
        file->private_data = NULL;
 
-       MOD_DEC_USE_COUNT;
        return 0;
 }
 
index 47b3d88fefcf5a6998265c85e39bce05dc1f878e..b07d83358d98b948927c3d6ed2e88727b016d376 100644 (file)
@@ -27,8 +27,6 @@
 extern void via_nubus_init(void);
 extern void oss_nubus_init(void);
 
-extern int console_loglevel;
-
 /* Constants */
 
 /* This is, of course, the size in bytelanes, rather than the size in
@@ -967,8 +965,9 @@ static int nubus_read_proc(char *buf, char **start, off_t off,
                                int count, int *eof, void *data)
 {
        int nprinted, len, begin = 0;
-       int slot;
-
+       int slot,size;
+       struct nubus_board* board;
+       
        len   = sprintf(buf, "Nubus devices found:\n");
        /* Walk the list of NuBus boards */
        for (board = nubus_boards; board != NULL; board = board->next)
@@ -987,7 +986,7 @@ static int nubus_read_proc(char *buf, char **start, off_t off,
        if (slot==16 || len+begin < off)
                *eof = 1;
        off -= begin;
-       *strat = buf + off;
+       *start = buf + off;
        len -= off;
        if (len>count)
                len = count;
index ed9fd9bffa9cb58f053970b3c0736a03725d1b85..99ed14b8fbd526ebfaa229230295d965e4c017f4 100644 (file)
@@ -540,15 +540,9 @@ static u32 pci_size(u32 base, unsigned long mask)
 static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
 {
        unsigned int pos, reg, next;
-       u32 l, sz, tmp;
-       u16 cmd;
+       u32 l, sz;
        struct resource *res;
 
-       /* Disable IO and memory while we fiddle */
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-       pci_write_config_word(dev, PCI_COMMAND, tmp);
-       
        for(pos=0; pos<howmany; pos = next) {
                next = pos+1;
                res = &dev->resource[pos];
@@ -611,7 +605,6 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
                }
                res->name = dev->name;
        }
-       pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
 void __init pci_read_bridge_bases(struct pci_bus *child)
index d9d8ae97d4abf1b5551c0259a867a023bb29f5af..bf9c82c5a742acb4b9f16add5f26f12c8642c984 100644 (file)
@@ -45,24 +45,28 @@ pbus_assign_resources_sorted(struct pci_bus *bus,
        head_io.next = head_mem.next = NULL;
        for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
                struct pci_dev *dev = pci_dev_b(ln);
+               u16 class = dev->class >> 8;
                u16 cmd;
 
                /* First, disable the device to avoid side
                   effects of possibly overlapping I/O and
                   memory ranges.
-                  Except the VGA - for obvious reason. :-)  */
-               if (dev->class >> 8 == PCI_CLASS_DISPLAY_VGA)
+                  Leave VGA enabled - for obvious reason. :-)
+                  Same with all sorts of bridges - they may
+                  have VGA behind them.  */
+               if (class == PCI_CLASS_DISPLAY_VGA
+                               || class == PCI_CLASS_NOT_DEFINED_VGA)
                        found_vga = 1;
-               else {
+               else if (class >> 8 != PCI_BASE_CLASS_BRIDGE) {
                        pci_read_config_word(dev, PCI_COMMAND, &cmd);
                        cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY
                                                | PCI_COMMAND_MASTER);
                        pci_write_config_word(dev, PCI_COMMAND, cmd);
                }
+
                /* Reserve some resources for CardBus.
                   Are these values reasonable? */
-               if (dev->class >> 8 == PCI_CLASS_BRIDGE_CARDBUS) {
+               if (class == PCI_CLASS_BRIDGE_CARDBUS) {
                        io_reserved += 8*1024;
                        mem_reserved += 32*1024*1024;
                        continue;
index 6013b2ec23c5b9d4694875a36b6986cd3ec2e5fb..7529c1db3dbad7e50e06c39b340eab97ba035c1d 100644 (file)
  *     themselves, but we'll see.  
  *     
  * History
+ *  (still kind of v0.14) Nov 23 - Alan Cox <alan@redhat.com>
+ *     Add clocking= for people with seriously warped hardware
  *  (still v0.14) Nov 10 2000 - Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
  *     add __init to maestro_ac97_init() and maestro_install()
  *  (still based on v0.14) Mar 29 2000 - Zach Brown <zab@redhat.com>
@@ -262,6 +264,10 @@ static int debug=0;
 static int dsps_order=0;
 /* wether or not we mess around with power management */
 static int use_pm=2; /* set to 1 for force */
+/* clocking for broken hardware - a few laptops seem to use a 50Khz clock
+       ie insmod with clocking=50000 or so */
+       
+static int clocking=48000;
 
 /* --------------------------------------------------------------------- */
 #define DRIVER_VERSION "0.14"
@@ -1200,7 +1206,10 @@ static u32 compute_rate(struct ess_state *s, u32 freq)
 {
        u32 clock = clock_freq[s->card->card_type];     
 
-       if (freq == 48000) return 0x10000;
+       freq = (freq * clocking)/48000;
+       
+       if (freq == 48000) 
+               return 0x10000;
 
        return ((freq / clock) <<16 )+  
                (((freq % clock) << 16) / clock);
@@ -3578,6 +3587,7 @@ MODULE_PARM(debug,"i");
 #endif
 MODULE_PARM(dsps_order,"i");
 MODULE_PARM(use_pm,"i");
+MODULE_PARM(clocking, "i");
 
 void cleanup_module(void) {
        M_printk("maestro: unloading\n");
index 50a045c1c4ada500f62a22eb82238d85bfc59062..d266b1353576ed690f643511cffc0e5be9a7c639 100644 (file)
@@ -454,11 +454,8 @@ static int soundcore_open(struct inode *, struct file *);
 
 static struct file_operations soundcore_fops=
 {
-/*     owner:  THIS_MODULE,  * this is a bug: if we have an owner, the kernel 
-                               generates a MOD_INC_USE_COUNT - thus
-                               the module cannot be unloaded since the device
-                               is never released here ! - solution: owner
-                               has to be NULL. Patch by Peter Wahl <Peter.Wahl@epost.de> */
+       /* We must have an owner or the module locking fails */
+       owner:  THIS_MODULE,
        open:   soundcore_open,
 };
 
index 0509f23471ac3bc211ef4fbabfa5151877ea7338..616058acc0afa81e50e19970b2ab754897e2e155 100644 (file)
@@ -1,11 +1,15 @@
 /*
- * bluetooth.c   Version 0.6
+ * bluetooth.c   Version 0.7
  *
  * Copyright (c) 2000 Greg Kroah-Hartman       <greg@kroah.com>
  * Copyright (c) 2000 Mark Douglas Corner      <mcorner@umich.edu>
  *
  * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
  *
+ * (11/29/2000) Version 0.7 gkh
+ *     Fixed problem with overrunning the tty flip buffer.
+ *     Removed unneeded NULL pointer initialization.
+ *
  * (10/05/2000) Version 0.6 gkh
  *     Fixed bug with urb->dev not being set properly, now that the usb
  *     core needs it.
@@ -211,8 +215,7 @@ static struct tty_driver    bluetooth_tty_driver;
 static struct tty_struct *     bluetooth_tty[BLUETOOTH_TTY_MINORS];
 static struct termios *                bluetooth_termios[BLUETOOTH_TTY_MINORS];
 static struct termios *                bluetooth_termios_locked[BLUETOOTH_TTY_MINORS];
-static struct usb_bluetooth    *bluetooth_table[BLUETOOTH_TTY_MINORS] = {NULL, };
-
+static struct usb_bluetooth    *bluetooth_table[BLUETOOTH_TTY_MINORS];
 
 
 static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function)
@@ -327,6 +330,11 @@ static int bluetooth_open (struct tty_struct *tty, struct file * filp)
        tty->driver_data = bluetooth;
        bluetooth->tty = tty;
 
+       /* force low_latency on so that our tty_push actually forces the data through, 
+        * otherwise it is scheduled, and with high data rates (like with OHCI) data
+        * can get lost. */
+       bluetooth->tty->low_latency = 1;
+       
        bluetooth->active = 1;
 
        /* Reset the packet position counters */
@@ -786,9 +794,14 @@ static void bluetooth_int_callback (struct urb *urb)
                return;
        }
 
-       if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos){
-               for (i = 0; i < bluetooth->int_packet_pos; ++i)
+       if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) {
+               for (i = 0; i < bluetooth->int_packet_pos; ++i) {
+                       /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */
+                       if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
+                               tty_flip_buffer_push(bluetooth->tty);
+                       }
                        tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0);
+               }
                tty_flip_buffer_push(bluetooth->tty);
 
                bluetooth->int_packet_pos = 0;
@@ -900,8 +913,13 @@ static void bluetooth_read_bulk_callback (struct urb *urb)
        }
 
        if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
-               for (i = 0; i < bluetooth->bulk_packet_pos; ++i)
+               for (i = 0; i < bluetooth->bulk_packet_pos; ++i) {
+                       /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
+                       if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) {
+                               tty_flip_buffer_push(bluetooth->tty);
+                       }
                        tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0);
+               }
                tty_flip_buffer_push(bluetooth->tty);
                bluetooth->bulk_packet_pos = 0;
        }       
index c77ba35e275cbc453233adcaf019fad6daa30f71..58061ec90074fc1ab60f0d21c99e7fc339c2cf83 100644 (file)
@@ -82,6 +82,7 @@ struct usblp {
        int                     readcount;              /* Counter for reads */
        int                     ifnum;                  /* Interface number */
        int                     minor;                  /* minor number of device */
+       unsigned int            quirks;                 /* quirks flags */
        unsigned char           used;                   /* True if open */
        unsigned char           bidir;                  /* interface is bidirectional */
        unsigned char           *device_id_string;      /* IEEE 1284 DEVICE ID string (ptr) */
@@ -90,6 +91,26 @@ struct usblp {
 
 static struct usblp *usblp_table[USBLP_MINORS];
 
+/* Quirks: various printer quirks are handled by this table & its flags. */
+
+struct quirk_printer_struct {
+       __u16 vendorId;
+       __u16 productId;
+       unsigned int quirks;
+};
+
+#define USBLP_QUIRK_BIDIR      0x1     /* reports bidir but requires unidirectional mode (no INs/reads) */
+#define USBLP_QUIRK_USB_INIT   0x2     /* needs vendor USB init string */
+
+static struct quirk_printer_struct quirk_printers[] = {
+       { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
+       { 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
+       { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
+       { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
+       { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
+       { 0, 0 }
+};
+
 /*
  * Functions for usblp control messages.
  */
@@ -325,8 +346,17 @@ static ssize_t usblp_write(struct file *file, const char *buffer, size_t count,
                        return -ENODEV;
 
                if (usblp->writeurb.status) {
-                       err = usblp_check_status(usblp, err);
-                       continue;
+                       if (usblp->quirks & USBLP_QUIRK_BIDIR) {
+                               if (usblp->writeurb.status != -EINPROGRESS)
+                                       err("usblp%d: error %d writing to printer",
+                                               usblp->minor, usblp->writeurb.status);
+                               err = usblp->writeurb.status;
+                               continue;
+                       }
+                       else {
+                               err = usblp_check_status(usblp, err);
+                               continue;
+                       }
                }
 
                writecount += usblp->writeurb.transfer_buffer_length;
@@ -393,13 +423,42 @@ static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t
        return count;
 }
 
+/*
+ * Checks for printers that have quirks, such as requiring unidirectional
+ * communication but reporting bidirectional; currently some HP printers
+ * have this flaw (HP 810, 880, 895, etc.), or needing an init string
+ * sent at each open (like some Epsons).
+ * Returns 1 if found, 0 if not found.
+ *
+ * HP recommended that we use the bidirectional interface but
+ * don't attempt any bulk IN transfers from the IN endpoint.
+ * Here's some more detail on the problem:
+ * The problem is not that it isn't bidirectional though. The problem
+ * is that if you request a device ID, or status information, while
+ * the buffers are full, the return data will end up in the print data
+ * buffer. For example if you make sure you never request the device ID
+ * while you are sending print data, and you don't try to query the
+ * printer status every couple of milliseconds, you will probably be OK.
+ */
+static unsigned int usblp_quirks (__u16 vendor, __u16 product)
+{
+       int i;
+
+       for (i = 0; quirk_printers[i].vendorId; i++) {
+               if (vendor == quirk_printers[i].vendorId &&
+                   product == quirk_printers[i].productId)
+                       return quirk_printers[i].quirks;
+       }
+       return 0;
+}
+
 static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
                         const struct usb_device_id *id)
 {
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *epread, *epwrite;
        struct usblp *usblp;
-       int minor, i, bidir = 0;
+       int minor, i, bidir = 0, quirks;
        int alts = dev->actconfig->interface[ifnum].act_altsetting;
        int length, err;
        char *buf;
@@ -453,10 +512,21 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
        }
        memset(usblp, 0, sizeof(struct usblp));
 
+       /* lookup quirks for this printer */
+       quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
+
+       if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
+               bidir = 0;
+               epread = NULL;
+               info ("Disabling reads from problem bidirectional printer on usblp%d",
+                       minor);
+       }
+
        usblp->dev = dev;
        usblp->ifnum = ifnum;
        usblp->minor = minor;
        usblp->bidir = bidir;
+       usblp->quirks = quirks;
 
        init_waitqueue_head(&usblp->wait);
 
index 6b5d6e7f0bd2f7f54f8ea43f972928724ef9ffb4..1a07a03d5f6ee0e0746e842e6235da7567ee06e3 100644 (file)
@@ -15,6 +15,9 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (12/29/2000) gkh
+ *     Small NULL pointer initialization cleanup which saves a bit of disk image
+ *
  * (11/01/2000) Adam J. Richter
  *     instead of using idVendor/idProduct pairs, usb serial drivers
  *     now identify their hardware interest with usb_device_id tables,
@@ -346,7 +349,7 @@ static struct tty_driver    serial_tty_driver;
 static struct tty_struct *     serial_tty[SERIAL_TTY_MINORS];
 static struct termios *                serial_termios[SERIAL_TTY_MINORS];
 static struct termios *                serial_termios_locked[SERIAL_TTY_MINORS];
-static struct usb_serial       *serial_table[SERIAL_TTY_MINORS] = {NULL, };
+static struct usb_serial       *serial_table[SERIAL_TTY_MINORS];       /* initially all NULL */
 
 LIST_HEAD(usb_serial_driver_list);
 
index e671ee3e491edaa24c59f6432546fccb4c59d1a2..ec039aaa24db5533551822d4047fbc9e9debfd60 100644 (file)
@@ -2,7 +2,7 @@
  * Universal Host Controller Interface driver for USB.
  *
  * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@sventech.com
+ * (C) Copyright 1999-2000 Johannes Erdfelt, johannes@erdfelt.com
  * (C) Copyright 1999 Randy Dunlap
  * (C) Copyright 1999 Georg Acher, acher@in.tum.de
  * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
@@ -2357,6 +2357,8 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign
        if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci) == 0) {
                uhci->irq = irq;
 
+               pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
                if (!uhci_start_root_hub(uhci))
                        return 0;
        }
@@ -2370,13 +2372,12 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign
        return retval;
 }
 
-static int __devinit
-uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
+static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        int i;
 
        /* disable legacy emulation */
-       pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+       pci_write_config_word(dev, USBLEGSUP, 0);
 
        if (pci_enable_device(dev) < 0)
                return -ENODEV;
@@ -2405,8 +2406,7 @@ uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
        return -ENODEV;
 }
 
-static void __devexit
-uhci_pci_remove (struct pci_dev *dev)
+static void __devexit uhci_pci_remove(struct pci_dev *dev)
 {
        struct uhci *uhci = dev->driver_data;
 
@@ -2423,14 +2423,12 @@ uhci_pci_remove (struct pci_dev *dev)
        release_uhci(uhci);
 }
 
-static void
-uhci_pci_suspend (struct pci_dev *dev)
+static void uhci_pci_suspend(struct pci_dev *dev)
 {
        reset_hc((struct uhci *) dev->driver_data);
 }
 
-static void
-uhci_pci_resume (struct pci_dev *dev)
+static void uhci_pci_resume(struct pci_dev *dev)
 {
        reset_hc((struct uhci *) dev->driver_data);
        start_hc((struct uhci *) dev->driver_data);
index 2cb333118617b07381a58e53a1a82c00376e1e1c..85b39cc1be215467780c050d628c0096f7b97e0e 100644 (file)
@@ -16,7 +16,7 @@
  * (C) Copyright 1999 Randy Dunlap
  * (C) Copyright 1999 Gregory P. Smith
  *
- * $Id: usb-uhci.c,v 1.249 2000/11/21 12:03:34 acher Exp $
+ * $Id: usb-uhci.c,v 1.251 2000/11/30 09:47:54 acher Exp $
  */
 
 #include <linux/config.h>
@@ -52,7 +52,7 @@
 /* This enables an extra UHCI slab for memory debugging */
 #define DEBUG_SLAB
 
-#define VERSTR "$Revision: 1.249 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.251 $ time " __TIME__ " " __DATE__
 
 #include <linux/usb.h>
 #include "usb-uhci.h"
@@ -582,6 +582,7 @@ _static int init_skel (uhci_t *s)
        
        fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
        insert_td (s, qh, td, 0);
+       qh->hw.qh.element &= ~UHCI_PTR_TERM; // remove TERM bit
        s->td1ms=td;
 
        dbg("allocating qh: bulk_chain");
@@ -2916,6 +2917,9 @@ _static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_
                return -1;
        }
 
+       /* Enable PIRQ */
+       pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
        s->irq = irq;
 
        if(uhci_start_usb (s) < 0) {
@@ -2944,14 +2948,14 @@ uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
                unsigned int io_addr = dev->resource[i].start;
                unsigned int io_size =
                dev->resource[i].end - dev->resource[i].start + 1;
-               if (!(dev->resource[i].flags & 1))
+               if (!(dev->resource[i].flags & IORESOURCE_IO))
                        continue;
 
                /* Is it already in use? */
                if (check_region (io_addr, io_size))
                        break;
                /* disable legacy emulation */
-               pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+               pci_write_config_word (dev, USBLEGSUP, 0);
        
                return alloc_uhci(dev, dev->irq, io_addr, io_size);
        }
index 05fcfcbe152decf1e44b7c5c2aaac663a694b160..626bf3cad35f3ac5cf29b34305676a7e244dae1e 100644 (file)
@@ -283,7 +283,6 @@ struct fb_info_aty128 {
     const struct aty128_meminfo *mem;   /* onboard mem info    */
     struct aty128fb_par default_par, current_par;
     struct display disp;
-    struct display_switch dispsw;       /* for cursor and font */
     struct { u8 red, green, blue, pad; } palette[256];
     union {
 #ifdef FBCON_HAS_CFB16
@@ -347,7 +346,7 @@ static void aty128fbcon_blank(int blank, struct fb_info *fb);
 static void aty128_encode_fix(struct fb_fix_screeninfo *fix,
                                struct aty128fb_par *par,
                                const struct fb_info_aty128 *info);
-static void aty128_set_disp(struct display *disp,
+static void aty128_set_dispsw(struct display *disp,
                        struct fb_info_aty128 *info, int bpp, int accel);
 static int aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
                                u_int *transp, struct fb_info *info);
@@ -1392,7 +1391,7 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
        display->inverse = 0;
 
        accel = var->accel_flags & FB_ACCELF_TEXT;
-        aty128_set_disp(display, info, par.crtc.bpp, accel);
+        aty128_set_dispsw(display, info, par.crtc.bpp, accel);
 
        if (accel)
            display->scrollmode = SCROLL_YNOMOVE;
@@ -1417,35 +1416,31 @@ aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
 
 
 static void
-aty128_set_disp(struct display *disp,
+aty128_set_dispsw(struct display *disp,
                        struct fb_info_aty128 *info, int bpp, int accel)
 {
     switch (bpp) {
 #ifdef FBCON_HAS_CFB8
     case 8:
-       info->dispsw = accel ? fbcon_aty128_8 : fbcon_cfb8;
-        disp->dispsw = &info->dispsw;
+       disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;
        break;
 #endif
 #ifdef FBCON_HAS_CFB16
     case 15:
     case 16:
-       info->dispsw = accel ? fbcon_aty128_16 : fbcon_cfb16;
-        disp->dispsw = &info->dispsw;
+       disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
        disp->dispsw_data = info->fbcon_cmap.cfb16;
        break;
 #endif
 #ifdef FBCON_HAS_CFB24
     case 24:
-       info->dispsw = accel ? fbcon_aty128_24 : fbcon_cfb24;
-        disp->dispsw = &info->dispsw;
+       disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24;
        disp->dispsw_data = info->fbcon_cmap.cfb24;
        break;
 #endif
 #ifdef FBCON_HAS_CFB32
     case 32:
-       info->dispsw = accel ? fbcon_aty128_32 : fbcon_cfb32;
-        disp->dispsw = &info->dispsw;
+       disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32;
        disp->dispsw_data = info->fbcon_cmap.cfb32;
        break;
 #endif
@@ -2135,7 +2130,7 @@ aty128fbcon_switch(int con, struct fb_info *fb)
     aty128_decode_var(&fb_display[con].var, &par, info);
     aty128_set_par(&par, info);
 
-    aty128_set_disp(&fb_display[con], info, par.crtc.bpp,
+    aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp,
         par.accel_flags & FB_ACCELF_TEXT);
 
     do_install_cmap(con, fb);
index 48b3b4ca28ffc0a1c6f643ce893599d46a05ada4..fb3b09bc95c9cae1245777c51ea1b62b4cefd9a5 100644 (file)
@@ -466,8 +466,8 @@ static void set_off_pitch(struct atyfb_par *par,
 static int encode_fix(struct fb_fix_screeninfo *fix,
                      const struct atyfb_par *par,
                      const struct fb_info_aty *info);
-static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
-                          int bpp, int accel);
+static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
+                            int bpp, int accel);
 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
                         u_int *transp, struct fb_info *fb);
 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -2826,8 +2826,8 @@ static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
 }
 
 
-static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
-                          int bpp, int accel)
+static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
+                            int bpp, int accel)
 {
            switch (bpp) {
 #ifdef FBCON_HAS_CFB8
@@ -2898,6 +2898,7 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
        oldbpp = display->var.bits_per_pixel;
        oldaccel = display->var.accel_flags;
        display->var = *var;
+       accel = var->accel_flags & FB_ACCELF_TEXT;
        if (oldxres != var->xres || oldyres != var->yres ||
            oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
            oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
@@ -2913,8 +2914,6 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
            display->line_length = fix.line_length;
            display->can_soft_blank = 1;
            display->inverse = 0;
-           accel = var->accel_flags & FB_ACCELF_TEXT;
-           atyfb_set_disp(display, info, par.crtc.bpp, accel);
            if (accel)
                display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
            else
@@ -2923,8 +2922,10 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
                (*info->fb_info.changevar)(con);
        }
        if (!info->fb_info.display_fg ||
-           info->fb_info.display_fg->vc_num == con)
+           info->fb_info.display_fg->vc_num == con) {
            atyfb_set_par(&par, info);
+           atyfb_set_dispsw(display, info, par.crtc.bpp, accel);
+       }
        if (oldbpp != var->bits_per_pixel) {
            if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
                return err;
@@ -4241,8 +4242,8 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
 
     atyfb_decode_var(&fb_display[con].var, &par, info);
     atyfb_set_par(&par, info);
-    atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
-                  par.accel_flags & FB_ACCELF_TEXT);
+    atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp,
+                    par.accel_flags & FB_ACCELF_TEXT);
 
     /* Install new colormap */
     do_install_cmap(con, fb);
index 558b6f44e0e52933bdf24bd947c66ba299a2fb84..20ab5c4e59e877d0b7adc223dc9513846f9d738a 100644 (file)
@@ -65,7 +65,6 @@ struct fb_par_platinum {
 struct fb_info_platinum {
        struct fb_info                  fb_info;
        struct display                  disp;
-       struct display_switch           dispsw;
        struct fb_par_platinum          default_par;
        struct fb_par_platinum          current_par;
 
@@ -140,8 +139,9 @@ static int platinum_var_to_par(const struct fb_var_screeninfo *var,
 static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
                               const struct fb_par_platinum *par,
                               const struct fb_info_platinum *info);
-static void platinum_set_disp(struct display *disp, struct fb_info_platinum *info,
-                             int cmode, int accel);
+static void platinum_set_dispsw(struct display *disp,
+                               struct fb_info_platinum *info, int cmode,
+                               int accel);
 static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
                              u_int *transp, struct fb_info *fb);
 static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -193,27 +193,25 @@ static int platinum_get_var(struct fb_var_screeninfo *var, int con,
        return 0;
 }
 
-static void platinum_set_disp(struct display *disp, struct fb_info_platinum *info,
-                             int cmode, int accel)
+static void platinum_set_dispsw(struct display *disp,
+                               struct fb_info_platinum *info, int cmode,
+                               int accel)
 {
        switch(cmode) {
 #ifdef FBCON_HAS_CFB8
            case CMODE_8:
-               info->dispsw = fbcon_cfb8;
-               disp->dispsw = &info->dispsw;
+               disp->dispsw = &fbcon_cfb8;
                break;
 #endif
 #ifdef FBCON_HAS_CFB16
            case CMODE_16:
-               info->dispsw = fbcon_cfb16;
-               disp->dispsw = &info->dispsw;
+               disp->dispsw = &fbcon_cfb16;
                disp->dispsw_data = info->fbcon_cmap.cfb16;
                break;
 #endif
 #ifdef FBCON_HAS_CFB32
            case CMODE_32:
-               info->dispsw = fbcon_cfb32;
-               disp->dispsw = &info->dispsw;
+               disp->dispsw = &fbcon_cfb32;
                disp->dispsw_data = info->fbcon_cmap.cfb32;
                break;
 #endif
@@ -271,7 +269,7 @@ static int platinum_set_var(struct fb_var_screeninfo *var, int con,
            display->line_length = fix.line_length;
            display->can_soft_blank = 1;
            display->inverse = 0;
-           platinum_set_disp(display, info, par.cmode, 0);
+           platinum_set_dispsw(display, info, par.cmode, 0);
            display->scrollmode = SCROLL_YREDRAW;
            if (info->fb_info.changevar)
              (*info->fb_info.changevar)(con);
@@ -341,7 +339,7 @@ static int platinum_switch(int con, struct fb_info *fb)
 
        platinum_var_to_par(&fb_display[con].var, &par, info);
        platinum_set_par(&par, info);
-       platinum_set_disp(&fb_display[con], info, par.cmode, 0);
+       platinum_set_dispsw(&fb_display[con], info, par.cmode, 0);
        do_install_cmap(con, fb);
 
        return 1;
index 4128c313ec9c349c2abc82770bf5dfce678956d7..d954dc02e85c4b3ae2f45714c17f94f95de1ba7e 100644 (file)
@@ -327,7 +327,6 @@ struct fb_info_tdfx {
   struct tdfxfb_par default_par;
   struct tdfxfb_par current_par;
   struct display disp;
-  struct display_switch dispsw;
 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)  
   union {
 #ifdef FBCON_HAS_CFB16
@@ -412,10 +411,10 @@ static int  tdfxfb_encode_var(struct fb_var_screeninfo* var,
 static int  tdfxfb_encode_fix(struct fb_fix_screeninfo* fix,
                              const struct tdfxfb_par* par,
                              const struct fb_info_tdfx* info);
-static void tdfxfb_set_disp(struct display* disp, 
-                           struct fb_info_tdfx* info,
-                           int bpp, 
-                           int accel);
+static void tdfxfb_set_dispsw(struct display* disp, 
+                             struct fb_info_tdfx* info,
+                             int bpp, 
+                             int accel);
 static int  tdfxfb_getcolreg(u_int regno,
                             u_int* red, 
                             u_int* green, 
@@ -1640,48 +1639,43 @@ static int tdfxfb_get_var(struct fb_var_screeninfo *var,
   return 0;
 }
  
-static void tdfxfb_set_disp(struct display *disp, 
-                           struct fb_info_tdfx *info,
-                           int bpp, 
-                           int accel) {
+static void tdfxfb_set_dispsw(struct display *disp, 
+                             struct fb_info_tdfx *info,
+                             int bpp, 
+                             int accel) {
 
   if (disp->dispsw && disp->conp) 
      fb_con.con_cursor(disp->conp, CM_ERASE);
   switch(bpp) {
 #ifdef FBCON_HAS_CFB8
   case 8:
-    info->dispsw = noaccel ? fbcon_cfb8 : fbcon_banshee8;
-    disp->dispsw = &info->dispsw;
+    disp->dispsw = noaccel ? &fbcon_cfb8 : &fbcon_banshee8;
     if (nohwcursor) fbcon_banshee8.cursor = NULL;
     break;
 #endif
 #ifdef FBCON_HAS_CFB16
   case 16:
-    info->dispsw = noaccel ? fbcon_cfb16 : fbcon_banshee16;
-    disp->dispsw = &info->dispsw;
+    disp->dispsw = noaccel ? &fbcon_cfb16 : &fbcon_banshee16;
     disp->dispsw_data = info->fbcon_cmap.cfb16;
     if (nohwcursor) fbcon_banshee16.cursor = NULL;
     break;
 #endif
 #ifdef FBCON_HAS_CFB24
   case 24:
-    info->dispsw = noaccel ? fbcon_cfb24 : fbcon_banshee24; 
-    disp->dispsw = &info->dispsw;
+    disp->dispsw = noaccel ? &fbcon_cfb24 : &fbcon_banshee24; 
     disp->dispsw_data = info->fbcon_cmap.cfb24;
     if (nohwcursor) fbcon_banshee24.cursor = NULL;
     break;
 #endif
 #ifdef FBCON_HAS_CFB32
   case 32:
-    info->dispsw = noaccel ? fbcon_cfb32 : fbcon_banshee32;
-    disp->dispsw = &info->dispsw;
+    disp->dispsw = noaccel ? &fbcon_cfb32 : &fbcon_banshee32;
     disp->dispsw_data = info->fbcon_cmap.cfb32;
     if (nohwcursor) fbcon_banshee32.cursor = NULL;
     break;
 #endif
   default:
-    info->dispsw = fbcon_dummy;
-    disp->dispsw = &info->dispsw;
+    disp->dispsw = &fbcon_dummy;
   }
    
 }
@@ -1735,7 +1729,7 @@ static int tdfxfb_set_var(struct fb_var_screeninfo *var,
         display->can_soft_blank = 1;
         display->inverse        = inverse;
         accel = var->accel_flags & FB_ACCELF_TEXT;
-        tdfxfb_set_disp(display, info, par.bpp, accel);
+        tdfxfb_set_dispsw(display, info, par.bpp, accel);
         
         if(nopan) display->scrollmode = SCROLL_YREDRAW;
        
@@ -2083,10 +2077,10 @@ static int tdfxfb_switch_con(int con,
    
    info->cursor.redraw=1;
    
-   tdfxfb_set_disp(&fb_display[con], 
-                  info, 
-                  par.bpp,
-                  par.accel_flags & FB_ACCELF_TEXT);
+   tdfxfb_set_dispsw(&fb_display[con], 
+                    info, 
+                    par.bpp,
+                    par.accel_flags & FB_ACCELF_TEXT);
    
    tdfxfb_install_cmap(&fb_display[con], fb);
    tdfxfb_updatevar(con, fb);
index fff4bb9a2904648275301f554471377f6b39444c..d8328e1b8b231b42647b2166c32fdfccbf3c972f 100644 (file)
@@ -871,10 +871,11 @@ int fsync_inode_buffers(struct inode *inode)
                else {
                        bh->b_inode = &tmp;
                        list_add(&bh->b_inode_buffers, &tmp.i_dirty_buffers);
-                       atomic_inc(&bh->b_count);
                        if (buffer_dirty(bh)) {
+                               atomic_inc(&bh->b_count);
                                spin_unlock(&lru_list_lock);
                                ll_rw_block(WRITE, 1, &bh);
+                               brelse(bh);
                                spin_lock(&lru_list_lock);
                        }
                }
@@ -883,6 +884,7 @@ int fsync_inode_buffers(struct inode *inode)
        while (!list_empty(&tmp.i_dirty_buffers)) {
                bh = BH_ENTRY(tmp.i_dirty_buffers.prev);
                remove_inode_queue(bh);
+               atomic_inc(&bh->b_count);
                spin_unlock(&lru_list_lock);
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh))
@@ -929,9 +931,9 @@ int osync_inode_buffers(struct inode *inode)
                        atomic_inc(&bh->b_count);
                        spin_unlock(&lru_list_lock);
                        wait_on_buffer(bh);
-                       brelse(bh);
                        if (!buffer_uptodate(bh))
                                err = -EIO;
+                       brelse(bh);
                        spin_lock(&lru_list_lock);
                        goto repeat;
                }
@@ -947,7 +949,6 @@ int osync_inode_buffers(struct inode *inode)
  * probably unmounting the fs, but that doesn't mean we have already
  * done a sync().  Just drop the buffers from the inode list.
  */
-
 void invalidate_inode_buffers(struct inode *inode)
 {
        struct list_head *list, *next;
index cf8fa51543b0ffe8a2171db199fe9bb8ba125d41..9e4a9b6b021156cab0413cdae351703a884208be 100644 (file)
@@ -256,7 +256,7 @@ error_return:
  * For other inodes, search forward from the parent directory\'s block
  * group to find a free inode.
  */
-struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
+struct inode * ext2_new_inode (const struct inode * dir, int mode)
 {
        struct super_block * sb;
        struct buffer_head * bh;
@@ -267,26 +267,22 @@ struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
        struct ext2_group_desc * gdp;
        struct ext2_group_desc * tmp;
        struct ext2_super_block * es;
+       int err;
 
        /* Cannot create files in a deleted directory */
-       if (!dir || !dir->i_nlink) {
-               *err = -EPERM;
-               return NULL;
-       }
+       if (!dir || !dir->i_nlink)
+               return ERR_PTR(-EPERM);
 
        sb = dir->i_sb;
        inode = new_inode(sb);
-       if (!inode) {
-               *err = -ENOMEM;
-               return NULL;
-       }
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
 
        lock_super (sb);
        es = sb->u.ext2_sb.s_es;
 repeat:
        gdp = NULL; i=0;
        
-       *err = -ENOSPC;
        if (S_ISDIR(mode)) {
                avefreei = le32_to_cpu(es->s_free_inodes_count) /
                        sb->u.ext2_sb.s_groups_count;
@@ -365,18 +361,14 @@ repeat:
                }
        }
 
-       if (!gdp) {
-               unlock_super (sb);
-               iput(inode);
-               return NULL;
-       }
+       err = -ENOSPC;
+       if (!gdp)
+               goto fail;
+
+       err = -EIO;
        bitmap_nr = load_inode_bitmap (sb, i);
-       if (bitmap_nr < 0) {
-               unlock_super (sb);
-               iput(inode);
-               *err = -EIO;
-               return NULL;
-       }
+       if (bitmap_nr < 0)
+               goto fail;
 
        bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
        if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
@@ -397,11 +389,11 @@ repeat:
                        ext2_error (sb, "ext2_new_inode",
                                    "Free inodes count corrupted in group %d",
                                    i);
-                       if (sb->s_flags & MS_RDONLY) {
-                               unlock_super (sb);
-                               iput (inode);
-                               return NULL;
-                       }
+                       /* Is it really ENOSPC? */
+                       err = -ENOSPC;
+                       if (sb->s_flags & MS_RDONLY)
+                               goto fail;
+
                        gdp->bg_free_inodes_count = 0;
                        mark_buffer_dirty(bh2);
                }
@@ -412,10 +404,8 @@ repeat:
                ext2_error (sb, "ext2_new_inode",
                            "reserved inode or inode > inodes count - "
                            "block_group = %d,inode=%d", i, j);
-               unlock_super (sb);
-               iput (inode);
-               *err = -EIO;
-               return NULL;
+               err = -EIO;
+               goto fail;
        }
        gdp->bg_free_inodes_count =
                cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
@@ -464,13 +454,15 @@ repeat:
                sb->dq_op->drop(inode);
                inode->i_nlink = 0;
                iput(inode);
-               *err = -EDQUOT;
-               return NULL;
+               return ERR_PTR(-EDQUOT);
        }
        ext2_debug ("allocating inode %lu\n", inode->i_ino);
-
-       *err = 0;
        return inode;
+
+fail:
+       unlock_super(sb);
+       iput(inode);
+       return ERR_PTR(err);
 }
 
 unsigned long ext2_count_free_inodes (struct super_block * sb)
index 1eaaac4072738b32e88bc6e61dcc99853ff6fe0c..59d3ef492a2ffeccfdd4ea15c7ae1f2d80476da8 100644 (file)
@@ -361,11 +361,9 @@ static int ext2_delete_entry (struct inode * dir,
  */
 static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
 {
-       struct inode * inode;
-       int err;
-
-       inode = ext2_new_inode (dir, mode, &err);
-       if (!inode)
+       struct inode * inode = ext2_new_inode (dir, mode);
+       int err = PTR_ERR(inode);
+       if (IS_ERR(inode))
                return err;
 
        inode->i_op = &ext2_file_inode_operations;
@@ -387,11 +385,10 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
 
 static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
 {
-       struct inode * inode;
-       int err;
+       struct inode * inode = ext2_new_inode (dir, mode);
+       int err = PTR_ERR(inode);
 
-       inode = ext2_new_inode (dir, mode, &err);
-       if (!inode)
+       if (IS_ERR(inode))
                return err;
 
        inode->i_uid = current->fsuid;
@@ -421,8 +418,9 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
        if (dir->i_nlink >= EXT2_LINK_MAX)
                return -EMLINK;
 
-       inode = ext2_new_inode (dir, S_IFDIR, &err);
-       if (!inode)
+       inode = ext2_new_inode (dir, S_IFDIR);
+       err = PTR_ERR(inode);
+       if (IS_ERR(inode))
                return err;
 
        inode->i_op = &ext2_dir_inode_operations;
@@ -628,7 +626,9 @@ static int ext2_symlink (struct inode * dir, struct dentry *dentry, const char *
        if (l > dir->i_sb->s_blocksize)
                return -ENAMETOOLONG;
 
-       if (!(inode = ext2_new_inode (dir, S_IFLNK, &err)))
+       inode = ext2_new_inode (dir, S_IFLNK);
+       err = PTR_ERR(inode);
+       if (IS_ERR(inode))
                return err;
 
        inode->i_mode = S_IFLNK | S_IRWXUGO;
index 24016206dfec3ca6447cb983fe946959e0642571..abbc04f1c58e05de1443fea97c98d7d8e5e7fa14 100644 (file)
@@ -77,7 +77,13 @@ static kmem_cache_t * inode_cachep;
 
 #define alloc_inode() \
         ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL))
-#define destroy_inode(inode) kmem_cache_free(inode_cachep, (inode))
+static void destroy_inode(struct inode *inode) 
+{
+       if (!list_empty(&inode->i_dirty_buffers))
+               BUG();
+       kmem_cache_free(inode_cachep, (inode));
+}
+
 
 /*
  * These are initializations that only need to be done
@@ -348,6 +354,9 @@ int generic_osync_inode(struct inode *inode, int datasync)
  
 void clear_inode(struct inode *inode)
 {
+       if (!list_empty(&inode->i_dirty_buffers))
+               invalidate_inode_buffers(inode);
+       
        if (inode->i_data.nrpages)
                BUG();
        if (!(inode->i_state & I_FREEING))
@@ -407,6 +416,7 @@ static int invalidate_list(struct list_head *head, struct super_block * sb, stru
                inode = list_entry(tmp, struct inode, i_list);
                if (inode->i_sb != sb)
                        continue;
+               invalidate_inode_buffers(inode);
                if (!atomic_read(&inode->i_count)) {
                        list_del(&inode->i_hash);
                        INIT_LIST_HEAD(&inode->i_hash);
index 6423b0eb7a10bce3461ae22ad6924613154dfdf9..6f0957dce489322dd0996a9888a6216899ec59fa 100644 (file)
@@ -163,7 +163,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
                                        return 0;
                                memcpy((void *) tmpde + slop, bh->b_data, offset);
                        }
-                       de = tmpde;                             
+                       de = tmpde;
                }
 
                if (de->flags[-high_sierra] & 0x80) {
index d75edccf67f8f5db5e7ec7fa030f429de2e53d95..5d50c37a687ee39b9090507e3b32b355cf083bea 100644 (file)
@@ -754,8 +754,9 @@ root_found:
        s->u.isofs_sb.s_gid = opt.gid;
        s->u.isofs_sb.s_utf8 = opt.utf8;
        /*
-        * It would be incredibly stupid to allow people to mark every file on the disk
-        * as suid, so we merely allow them to set the default permissions.
+        * It would be incredibly stupid to allow people to mark every file
+        * on the disk as suid, so we merely allow them to set the default
+        * permissions.
         */
        s->u.isofs_sb.s_mode = opt.mode & 0777;
 
@@ -1017,10 +1018,7 @@ static int isofs_read_level3_size(struct inode * inode)
        unsigned long block, offset;
        int i = 0;
        int more_entries = 0;
-       struct iso_directory_record * tmpde = kmalloc(256, GFP_KERNEL);
-
-       if (!tmpde)
-               return -ENOMEM;
+       struct iso_directory_record * tmpde = NULL;
 
        inode->i_size = 0;
        inode->u.isofs_i.i_next_section_ino = 0;
@@ -1054,6 +1052,11 @@ static int isofs_read_level3_size(struct inode * inode)
                /* Make sure we have a full directory entry */
                if (offset >= bufsize) {
                        int slop = bufsize - offset + de_len;
+                       if (!tmpde) {
+                               tmpde = kmalloc(256, GFP_KERNEL);
+                               if (!tmpde)
+                                       goto out_nomem;
+                       }
                        memcpy(tmpde, de, slop);
                        offset &= bufsize - 1;
                        block++;
@@ -1080,14 +1083,23 @@ static int isofs_read_level3_size(struct inode * inode)
                        goto out_toomany;
        } while(more_entries);
 out:
-       kfree(tmpde);
-       if (bh) brelse(bh);
+       if (tmpde)
+               kfree(tmpde);
+       if (bh)
+               brelse(bh);
        return 0;
 
+out_nomem:
+       if (bh)
+               brelse(bh);
+       return -ENOMEM;
+
 out_noread:
        printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block);
-       kfree(tmpde);
-       return 1;
+       if (tmpde)
+               kfree(tmpde);
+       return -EIO;
+
 out_toomany:
        printk(KERN_INFO "isofs_read_level3_size: "
                "More than 100 file sections ?!?, aborting...\n"
@@ -1102,22 +1114,39 @@ static void isofs_read_inode(struct inode * inode)
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
        int high_sierra = sb->u.isofs_sb.s_high_sierra;
-       struct buffer_head * bh;
-       struct iso_directory_record * raw_inode;
-       unsigned char *pnt;
+       struct buffer_head * bh = NULL;
+       struct iso_directory_record * de;
+       struct iso_directory_record * tmpde = NULL;
+       unsigned int de_len;
+       unsigned long offset;
        int volume_seq_no, i;
 
        bh = bread(inode->i_dev, block, bufsize);
-       if (!bh) {
-               printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
-               goto fail;
-       }
+       if (!bh)
+               goto out_badread;
+
+       offset = (inode->i_ino & (bufsize - 1));
+       de = (struct iso_directory_record *) (bh->b_data + offset);
+       de_len = *(unsigned char *) de;
 
-       pnt = ((unsigned char *) bh->b_data
-              + (inode->i_ino & (bufsize - 1)));
-       raw_inode = ((struct iso_directory_record *) pnt);
+       if (offset + de_len > bufsize) {
+               int frag1 = bufsize - offset;
 
-       if (raw_inode->flags[-high_sierra] & 2) {
+               tmpde = kmalloc(de_len, GFP_KERNEL);
+               if (tmpde == NULL) {
+                       printk(KERN_INFO "isofs_read_inode: out of memory\n");
+                       goto fail;
+               }
+               memcpy(tmpde, bh->b_data + offset, frag1);
+               brelse(bh);
+               bh = bread(inode->i_dev, ++block, bufsize);
+               if (!bh)
+                       goto out_badread;
+               memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1);
+               de = tmpde;
+       }
+
+       if (de->flags[-high_sierra] & 2) {
                inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
                inode->i_nlink = 1; /* Set to 1.  We know there are 2, but
                                       the find utility tries to optimize
@@ -1132,10 +1161,10 @@ static void isofs_read_inode(struct inode * inode)
                /* If there are no periods in the name,
                 * then set the execute permission bit
                 */
-               for(i=0; i< raw_inode->name_len[0]; i++)
-                       if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
+               for(i=0; i< de->name_len[0]; i++)
+                       if(de->name[i]=='.' || de->name[i]==';')
                                break;
-               if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
+               if(i == de->name_len[0] || de->name[i] == ';')
                        inode->i_mode |= S_IXUGO; /* execute permission */
        }
        inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
@@ -1143,84 +1172,77 @@ static void isofs_read_inode(struct inode * inode)
        inode->i_blocks = inode->i_blksize = 0;
 
 
-       inode->u.isofs_i.i_section_size = isonum_733 (raw_inode->size);
-       if(raw_inode->flags[-high_sierra] & 0x80) {
+       inode->u.isofs_i.i_section_size = isonum_733 (de->size);
+       if(de->flags[-high_sierra] & 0x80) {
                if(isofs_read_level3_size(inode)) goto fail;
        } else {
-               inode->i_size = isonum_733 (raw_inode->size);
+               inode->i_size = isonum_733 (de->size);
        }
 
        /* There are defective discs out there - we do this to protect
           ourselves.  A cdrom will never contain more than 800Mb 
           .. but a DVD may be up to 1Gig (Ulrich Habel) */
-       if((inode->i_size < 0 || inode->i_size > 1073741824) &&
+
+       if ((inode->i_size < 0 || inode->i_size > 1073741824) &&
            inode->i_sb->u.isofs_sb.s_cruft == 'n') {
-         printk(KERN_WARNING "Warning: defective CD-ROM.  Enabling \"cruft\" mount option.\n");
-         inode->i_sb->u.isofs_sb.s_cruft = 'y';
+               printk(KERN_WARNING "Warning: defective CD-ROM.  "
+                      "Enabling \"cruft\" mount option.\n");
+               inode->i_sb->u.isofs_sb.s_cruft = 'y';
        }
 
-/* Some dipshit decided to store some other bit of information in the high
-   byte of the file length.  Catch this and holler.  WARNING: this will make
-   it impossible for a file to be > 16Mb on the CDROM!!!*/
+       /*
+        * Some dipshit decided to store some other bit of information
+        * in the high byte of the file length.  Catch this and holler.
+        * WARNING: this will make it impossible for a file to be > 16MB
+        * on the CDROM.
+        */
 
-       if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
-          inode->i_size & 0xff000000){
-/*       printk("Illegal format on cdrom.  Pester manufacturer.\n"); */
-         inode->i_size &= 0x00ffffff;
+       if (inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
+           inode->i_size & 0xff000000) {
+               inode->i_size &= 0x00ffffff;
        }
 
-       if (raw_inode->interleave[0]) {
+       if (de->interleave[0]) {
                printk("Interleaved files not (yet) supported.\n");
                inode->i_size = 0;
        }
 
        /* I have no idea what file_unit_size is used for, so
           we will flag it for now */
-       if(raw_inode->file_unit_size[0] != 0){
-               printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
+       if (de->file_unit_size[0] != 0) {
+               printk("File unit size != 0 for ISO file (%ld).\n",
+                      inode->i_ino);
        }
 
        /* I have no idea what other flag bits are used for, so
           we will flag it for now */
 #ifdef DEBUG
-       if((raw_inode->flags[-high_sierra] & ~2)!= 0){
+       if((de->flags[-high_sierra] & ~2)!= 0){
                printk("Unusual flag settings for ISO file (%ld %x).\n",
-                      inode->i_ino, raw_inode->flags[-high_sierra]);
+                      inode->i_ino, de->flags[-high_sierra]);
        }
 #endif
 
-#ifdef DEBUG
-       printk("Get inode %x: %d %d: %d\n",inode->i_ino, block,
-              ((int)pnt) & 0x3ff, inode->i_size);
-#endif
-
        inode->i_mtime = inode->i_atime = inode->i_ctime =
-         iso_date(raw_inode->date, high_sierra);
+               iso_date(de->date, high_sierra);
 
-       inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
-                                          isonum_711 (raw_inode->ext_attr_length));
+       inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) +
+                                          isonum_711 (de->ext_attr_length));
 
-/* Now test for possible Rock Ridge extensions which will override some of
-   these numbers in the inode structure. */
+       /*
+        * Now test for possible Rock Ridge extensions which will override
+        * some of these numbers in the inode structure.
+        */
 
        if (!high_sierra) {
-         parse_rock_ridge_inode(raw_inode, inode);
-         /* hmm..if we want uid or gid set, override the rock ridge setting */
-        test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
-         test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);
+               parse_rock_ridge_inode(de, inode);
+               /* if we want uid/gid set, override the rock ridge setting */
+               test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid);
+               test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid);
        }
 
-#ifdef DEBUG
-       printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
-#endif
-
        /* get the volume sequence number */
-       volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
-
-       /*
-        * All done with buffer ... no more references to buffer memory!
-        */
-       brelse(bh);
+       volume_seq_no = isonum_723 (de->volume_sequence_number) ;
 
        /*
         * Disable checking if we see any volume number other than 0 or 1.
@@ -1230,8 +1252,10 @@ static void isofs_read_inode(struct inode * inode)
         */
        if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&
            (volume_seq_no != 0) && (volume_seq_no != 1)) {
-         printk(KERN_WARNING "Warning: defective CD-ROM (volume sequence number). Enabling \"cruft\" mount option.\n");
-         inode->i_sb->u.isofs_sb.s_cruft = 'y';
+               printk(KERN_WARNING "Warning: defective CD-ROM "
+                      "(volume sequence number %d). "
+                      "Enabling \"cruft\" mount option.\n", volume_seq_no);
+               inode->i_sb->u.isofs_sb.s_cruft = 'y';
        }
 
        /* Install the inode operations vector */
@@ -1242,25 +1266,32 @@ static void isofs_read_inode(struct inode * inode)
        } else
 #endif IGNORE_WRONG_MULTI_VOLUME_SPECS
        {
-         if (S_ISREG(inode->i_mode)) {
-           inode->i_fop = &generic_ro_fops;
-           inode->i_data.a_ops = &isofs_aops;
-         } else if (S_ISDIR(inode->i_mode)) {
-           inode->i_op = &isofs_dir_inode_operations;
-           inode->i_fop = &isofs_dir_operations;
-         } else if (S_ISLNK(inode->i_mode)) {
-           inode->i_op = &page_symlink_inode_operations;
-           inode->i_data.a_ops = &isofs_symlink_aops;
-         } else
-           /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
-           init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev));
+               if (S_ISREG(inode->i_mode)) {
+                       inode->i_fop = &generic_ro_fops;
+                       inode->i_data.a_ops = &isofs_aops;
+               } else if (S_ISDIR(inode->i_mode)) {
+                       inode->i_op = &isofs_dir_inode_operations;
+                       inode->i_fop = &isofs_dir_operations;
+               } else if (S_ISLNK(inode->i_mode)) {
+                       inode->i_op = &page_symlink_inode_operations;
+                       inode->i_data.a_ops = &isofs_symlink_aops;
+               } else
+                       /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
+                       init_special_inode(inode, inode->i_mode,
+                                          kdev_t_to_nr(inode->i_rdev));
        }
+ out:
+       if (tmpde)
+               kfree(tmpde);
+       if (bh)
+               brelse(bh);
        return;
 
-      fail:
-       /* With a data error we return this information */
+ out_badread:
+       printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
+ fail:
        make_bad_inode(inode);
-       return;
+       goto out;
 }
 
 #ifdef LEAK_CHECK
index 24872970aed2621e27c8b318fe5e2ababdc97b74..3f44d90335fa2ada6f101376bde60d2b62438c2e 100644 (file)
@@ -161,13 +161,14 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry)
        struct inode *inode;
        struct page *page;
 
-#ifdef DEBUG
-       printk("lookup: %x %s\n",dir->i_ino, dentry->d_name.name);
-#endif
        dentry->d_op = dir->i_sb->s_root->d_op;
 
        page = alloc_page(GFP_USER);
-       ino = isofs_find_entry(dir, dentry, page_address(page), 1024 + page_address(page));
+       if (!page)
+               return ERR_PTR(-ENOMEM);
+
+       ino = isofs_find_entry(dir, dentry, page_address(page),
+                              1024 + page_address(page));
        __free_page(page);
 
        inode = NULL;
index a2511444d66932f6276c0d0d915eef75cff1d513..4ac4bc0ced4363d44ca8c74518a29399a25555ba 100644 (file)
@@ -72,7 +72,7 @@
       cont_size = 0; \
       cont_offset = 0; \
       goto LABEL; \
-    };    \
+    }    \
     printk("Unable to read rock-ridge attributes\n");    \
   }}
 
@@ -120,22 +120,16 @@ int find_rock_ridge_relocation(struct iso_directory_record * de,
        CHECK_SP(goto out);
        break;
       case SIG('C','L'):
-#ifdef DEBUG
-       printk("RR: CL\n");
-#endif
        if (flag == 0) {
          retval = isonum_733(rr->u.CL.location);
          goto out;
-       };
+       }
        break;
       case SIG('P','L'):
-#ifdef DEBUG
-       printk("RR: PL\n");
-#endif
        if (flag != 0) {
          retval = isonum_733(rr->u.PL.location);
          goto out;
-       };
+       }
        break;
       case SIG('C','E'):
        CHECK_CE; /* This tells is if there is a continuation record */
@@ -143,8 +137,8 @@ int find_rock_ridge_relocation(struct iso_directory_record * de,
       default:
        break;
       }
-    };
-  };
+    }
+  }
   MAYBE_CONTINUE(repeat, inode);
   return retval;
  out:
@@ -203,24 +197,21 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
        if (rr->u.NM.flags & ~1) {
          printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
          break;
-       };
+       }
        if((strlen(retname) + rr->len - 5) >= 254) {
          truncate = 1;
          break;
-       };
+       }
        strncat(retname, rr->u.NM.name, rr->len - 5);
        retnamlen += rr->len - 5;
        break;
       case SIG('R','E'):
-#ifdef DEBUG
-       printk("RR: RE (%x)\n", inode->i_ino);
-#endif
        if (buffer) kfree(buffer);
        return -1;
       default:
        break;
       }
-    };
+    }
   }
   MAYBE_CONTINUE(repeat,inode);
   return retnamlen; /* If 0, this file did not have a NM field */
@@ -266,10 +257,10 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
        break;
       case SIG('E','R'):
        inode->i_sb->u.isofs_sb.s_rock = 1;
-       printk(KERN_DEBUG"ISO 9660 Extensions: ");
+       printk(KERN_DEBUG "ISO 9660 Extensions: ");
        { int p;
          for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
-       };
+       }
          printk("\n");
        break;
       case SIG('P','X'):
@@ -294,7 +285,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
          } else {
            inode->i_rdev = MKDEV(high, low);
          }
-       };
+       }
        break;
       case SIG('T','F'):
        /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
@@ -334,7 +325,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
             break;
           default:
             printk("Symlink component flag not implemented\n");
-          };
+          }
           slen -= slp->len + 2;
           oldslp = slp;
           slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
@@ -348,19 +339,16 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
           /*
            * If this component record isn't continued, then append a '/'.
            */
-          if(   (!rootflag)
-                && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
+          if (!rootflag && (oldslp->flags & 1) == 0)
+                  inode->i_size += 1;
         }
        }
        symlink_len = inode->i_size;
        break;
       case SIG('R','E'):
-       printk("Attempt to read inode for relocated directory\n");
+       printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
        goto out;
       case SIG('C','L'):
-#ifdef DEBUG
-       printk("RR CL (%x)\n",inode->i_ino);
-#endif
        inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
        reloc = iget(inode->i_sb,
                     (inode->u.isofs_i.i_first_extent <<
@@ -381,7 +369,7 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
       default:
        break;
       }
-    };
+    }
   }
   MAYBE_CONTINUE(repeat,inode);
   return 0;
index 12cd2d30493d6c75dbffacecd30ebb7aebf3c337..b966c512bc490a8b343473cd2da8064a914f43a4 100644 (file)
@@ -98,7 +98,7 @@ isonum_733 (char * p)
 
 int iso_date(char * p, int flag)
 {
-       int year, month, day, hour ,minute, second, tz;
+       int year, month, day, hourminute, second, tz;
        int crtime, days, i;
 
        year = p[0] - 70;
index 211b01530295de5f76f950bfafce777447ee1271..592851be615d5505190b95b43a240a20b974618f 100644 (file)
@@ -50,7 +50,7 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 
        nlmclnt_next_cookie(&argp->cookie);
        argp->state   = nsm_local_state;
-       memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry), sizeof(struct nfs_fh));
+       memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
        lock->caller  = system_utsname.nodename;
        lock->oh.data = req->a_owner;
        lock->oh.len  = sprintf(req->a_owner, "%d@%s",
index 7a6d868e253cb56212b8a1fbacd91a33c7cf77c6..e65b593946c62a00e8b0ab6f402c318b5595ff28 100644 (file)
@@ -1623,7 +1623,7 @@ int fcntl_setlk64(unsigned int fd, unsigned int cmd, struct flock64 *l)
                if (error < 0)
                        goto out_putf;
        }
-       error = posix_lock_file(filp, file_lock, cmd == F_SETLKW);
+       error = posix_lock_file(filp, file_lock, cmd == F_SETLKW64);
 
 out_putf:
        fput(filp);
index c0d1abc36e57ee6f581648a3b98406fc1c95a495..37644f4a10151224a80870149ede15fa3a9ae3e9 100644 (file)
@@ -152,18 +152,10 @@ char * getname(const char * filename)
  * for filesystem access without changing the "normal" uids which
  * are used for other things..
  */
-int permission(struct inode * inode,int mask)
+int vfs_permission(struct inode * inode,int mask)
 {
        int mode = inode->i_mode;
 
-       if (inode->i_op && inode->i_op->permission) {
-               int retval;
-               lock_kernel();
-               retval = inode->i_op->permission(inode, mask);
-               unlock_kernel();
-               return retval;
-       }
-
        if ((mask & S_IWOTH) && IS_RDONLY(inode) &&
                 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
                return -EROFS; /* Nobody gets write access to a read-only fs */
@@ -188,6 +180,18 @@ int permission(struct inode * inode,int mask)
        return -EACCES;
 }
 
+int permission(struct inode * inode,int mask)
+{
+       if (inode->i_op && inode->i_op->permission) {
+               int retval;
+               lock_kernel();
+               retval = inode->i_op->permission(inode, mask);
+               unlock_kernel();
+               return retval;
+       }
+       return vfs_permission(inode, mask);
+}
+
 /*
  * get_write_access() gets write permission for a file.
  * put_write_access() releases this write permission.
index c66d870d9f22cb480e48f99f13efd857bf18ea80..4821de8d346aa03285ca6b64a7ac548621bda4be 100644 (file)
@@ -63,6 +63,7 @@ struct inode_operations nfs_dir_inode_operations = {
        rmdir:          nfs_rmdir,
        mknod:          nfs_mknod,
        rename:         nfs_rename,
+       permission:     nfs_permission,
        revalidate:     nfs_revalidate,
        setattr:        nfs_notify_change,
 };
@@ -97,6 +98,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
 {
        struct file     *file = desc->file;
        struct inode    *inode = file->f_dentry->d_inode;
+       struct rpc_cred *cred = nfs_file_cred(file);
        void            *buffer = kmap(page);
        int             plus = NFS_USE_READDIRPLUS(inode);
        int             error;
@@ -104,7 +106,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
        dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index);
 
  again:
-       error = NFS_PROTO(inode)->readdir(file, desc->entry->cookie, buffer,
+       error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, buffer,
                                          NFS_SERVER(inode)->dtsize, plus);
        /* We requested READDIRPLUS, but the server doesn't grok it */
        if (desc->plus && error == -ENOTSUPP) {
@@ -308,6 +310,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
 {
        struct file     *file = desc->file;
        struct inode    *inode = file->f_dentry->d_inode;
+       struct rpc_cred *cred = nfs_file_cred(file);
        struct page     *page = NULL;
        u32             *p;
        int             status = -EIO;
@@ -324,7 +327,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                goto out;
        }
        p = kmap(page);
-       status = NFS_PROTO(inode)->readdir(file, desc->target, p,
+       status = NFS_PROTO(inode)->readdir(inode, cred, desc->target, p,
                                           NFS_SERVER(inode)->dtsize, 0);
        if (status >= 0) {
                p = desc->decode(p, desc->entry, 0);
@@ -483,16 +486,15 @@ static inline int nfs_neg_need_reval(struct dentry *dentry)
  */
 static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
 {
-       struct dentry *dir = dentry->d_parent;
-       struct inode *dir_i = dir->d_inode;
-       struct inode * inode = dentry->d_inode;
+       struct inode *dir;
+       struct inode *inode;
        int error;
        struct nfs_fh fhandle;
        struct nfs_fattr fattr;
 
        lock_kernel();
-       dir = dentry->d_parent;
-       dir_i = dir->d_inode;
+       dir = dentry->d_parent->d_inode;
+       inode = dentry->d_inode;
        /*
         * If we don't have an inode, let's look at the parent
         * directory mtime to get a hint about how often we
@@ -506,7 +508,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
 
        if (is_bad_inode(inode)) {
                dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n",
-                       dir->d_name.name, dentry->d_name.name);
+                       dentry->d_parent->d_name.name, dentry->d_name.name);
                goto out_bad;
        }
 
@@ -514,15 +516,14 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
                goto out_valid;
 
        if (IS_ROOT(dentry)) {
-               __nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+               __nfs_revalidate_inode(NFS_SERVER(inode), inode);
                goto out_valid_renew;
        }
 
        /*
         * Do a new lookup and check the dentry attributes.
         */
-       error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name, &fhandle,
-                                        &fattr);
+       error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
        if (error)
                goto out_bad;
 
@@ -533,10 +534,10 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
                goto out_bad;
 
        /* Filehandle matches? */
-       if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
+       if (memcmp(NFS_FH(inode), fhandle.data, sizeof(struct nfs_fh)))
                goto out_bad;
 
-       /* Ok, remeber that we successfully checked it.. */
+       /* Ok, remember that we successfully checked it.. */
        nfs_refresh_inode(inode, &fattr);
 
  out_valid_renew:
@@ -551,7 +552,7 @@ out_bad:
                goto out_valid;
        d_drop(dentry);
        /* Purge readdir caches. */
-       nfs_zap_caches(dir_i);
+       nfs_zap_caches(dir);
        if (inode && S_ISDIR(inode->i_mode))
                nfs_zap_caches(inode);
        unlock_kernel();
@@ -575,30 +576,6 @@ static int nfs_dentry_delete(struct dentry *dentry)
 
 }
 
-static kmem_cache_t *nfs_fh_cachep;
-
-__inline__ struct nfs_fh *nfs_fh_alloc(void)
-{
-       return kmem_cache_alloc(nfs_fh_cachep, SLAB_KERNEL);
-}
-
-__inline__ void nfs_fh_free(struct nfs_fh *p)
-{
-       kmem_cache_free(nfs_fh_cachep, p);
-}
-
-/*
- * Called when the dentry is being freed to release private memory.
- */
-static void nfs_dentry_release(struct dentry *dentry)
-{
-       if (dentry->d_fsdata) {
-               lock_kernel();
-               nfs_fh_free(dentry->d_fsdata);
-               unlock_kernel();
-       }
-}
-
 /*
  * Called when the dentry loses inode.
  * We use it to clean up silly-renamed files.
@@ -616,35 +593,27 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 struct dentry_operations nfs_dentry_operations = {
        d_revalidate:   nfs_lookup_revalidate,
        d_delete:       nfs_dentry_delete,
-       d_release:      nfs_dentry_release,
        d_iput:         nfs_dentry_iput,
 };
 
-static struct dentry *nfs_lookup(struct inode *dir_i, struct dentry * dentry)
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
 {
-       struct dentry *dir = dentry->d_parent;
        struct inode *inode;
        int error;
        struct nfs_fh fhandle;
        struct nfs_fattr fattr;
 
        dfprintk(VFS, "NFS: lookup(%s/%s)\n",
-               dir->d_name.name, dentry->d_name.name);
+               dentry->d_parent->d_name.name, dentry->d_name.name);
 
        error = -ENAMETOOLONG;
-       if (dentry->d_name.len > NFS_SERVER(dir_i)->namelen)
+       if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
                goto out;
 
        error = -ENOMEM;
-       if (!dentry->d_fsdata) {
-               dentry->d_fsdata = nfs_fh_alloc();
-               if (!dentry->d_fsdata)
-                       goto out;
-       }
        dentry->d_op = &nfs_dentry_operations;
 
-       error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name, &fhandle,
-                                        &fattr);
+       error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
        inode = NULL;
        if (error == -ENOENT)
                goto no_entry;
@@ -686,16 +655,15 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
  * that the operation succeeded on the server, but an error in the
  * reply path made it appear to have failed.
  */
-static int nfs_create(struct inode *dir_i, struct dentry *dentry, int mode)
+static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
-       struct dentry *dir = dentry->d_parent;
        struct iattr attr;
        struct nfs_fattr fattr;
        struct nfs_fh fhandle;
        int error;
 
        dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
-               dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+               dir->i_dev, dir->i_ino, dentry->d_name.name);
 
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
@@ -706,8 +674,8 @@ static int nfs_create(struct inode *dir_i, struct dentry *dentry, int mode)
         * select the appropriate create strategy. Currently open_namei
         * does not pass the create flags.
         */
-       nfs_zap_caches(dir_i);
-       error = NFS_PROTO(dir_i)->create(dir, &dentry->d_name,
+       nfs_zap_caches(dir);
+       error = NFS_PROTO(dir)->create(dir, &dentry->d_name,
                                         &attr, 0, &fhandle, &fattr);
        if (!error && fhandle.size != 0)
                error = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -719,22 +687,21 @@ static int nfs_create(struct inode *dir_i, struct dentry *dentry, int mode)
 /*
  * See comments for nfs_proc_create regarding failed operations.
  */
-static int nfs_mknod(struct inode *dir_i, struct dentry *dentry, int mode, int rdev)
+static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
 {
-       struct dentry *dir = dentry->d_parent;
        struct iattr attr;
        struct nfs_fattr fattr;
        struct nfs_fh fhandle;
        int error;
 
        dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
-               dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+               dir->i_dev, dir->i_ino, dentry->d_name.name);
 
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       nfs_zap_caches(dir_i);
-       error = NFS_PROTO(dir_i)->mknod(dir, &dentry->d_name, &attr, rdev,
+       nfs_zap_caches(dir);
+       error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
                                        &fhandle, &fattr);
        if (!error && fhandle.size != 0)
                error = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -746,16 +713,15 @@ static int nfs_mknod(struct inode *dir_i, struct dentry *dentry, int mode, int r
 /*
  * See comments for nfs_proc_create regarding failed operations.
  */
-static int nfs_mkdir(struct inode *dir_i, struct dentry *dentry, int mode)
+static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-       struct dentry *dir = dentry->d_parent;
        struct iattr attr;
        struct nfs_fattr fattr;
        struct nfs_fh fhandle;
        int error;
 
        dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
-               dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+               dir->i_dev, dir->i_ino, dentry->d_name.name);
 
        attr.ia_valid = ATTR_MODE;
        attr.ia_mode = mode | S_IFDIR;
@@ -769,8 +735,8 @@ static int nfs_mkdir(struct inode *dir_i, struct dentry *dentry, int mode)
         */
        d_drop(dentry);
 #endif
-       nfs_zap_caches(dir_i);
-       error = NFS_PROTO(dir_i)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
+       nfs_zap_caches(dir);
+       error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
                                        &fattr);
        if (!error && fhandle.size != 0)
                error = nfs_instantiate(dentry, &fhandle, &fattr);
@@ -779,25 +745,23 @@ static int nfs_mkdir(struct inode *dir_i, struct dentry *dentry, int mode)
        return error;
 }
 
-static int nfs_rmdir(struct inode *dir_i, struct dentry *dentry)
+static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
-       struct dentry *dir = dentry->d_parent;
        int error;
 
        dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
-               dir_i->i_dev, dir_i->i_ino, dentry->d_name.name);
+               dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-       nfs_zap_caches(dir_i);
-       error = NFS_PROTO(dir_i)->rmdir(dir, &dentry->d_name);
+       nfs_zap_caches(dir);
+       error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
 
        return error;
 }
 
-static int nfs_sillyrename(struct inode *dir_i, struct dentry *dentry)
+static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
 {
-       struct dentry *dir = dentry->d_parent;
        static unsigned int sillycounter;
-       const int      i_inosize  = sizeof(dir_i->i_ino)*2;
+       const int      i_inosize  = sizeof(dir->i_ino)*2;
        const int      countersize = sizeof(sillycounter)*2;
        const int      slen       = strlen(".nfs") + i_inosize + countersize;
        char           silly[slen+1];
@@ -848,10 +812,10 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
                        goto out;
        } while(sdentry->d_inode != NULL); /* need negative lookup */
 
-       nfs_zap_caches(dir_i);
+       nfs_zap_caches(dir);
        qsilly.name = silly;
        qsilly.len  = strlen(silly);
-       error = NFS_PROTO(dir_i)->rename(dir, &dentry->d_name, dir, &qsilly);
+       error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, dir, &qsilly);
        if (!error) {
                nfs_renew_times(dentry);
                d_move(dentry, sdentry);
@@ -872,8 +836,7 @@ out:
  */
 static int nfs_safe_remove(struct dentry *dentry)
 {
-       struct dentry *dir = dentry->d_parent;
-       struct inode *dir_i = dir->d_inode;
+       struct inode *dir = dentry->d_parent->d_inode;
        struct inode *inode = dentry->d_inode;
        int error = -EBUSY, rehash = 0;
                
@@ -902,10 +865,10 @@ static int nfs_safe_remove(struct dentry *dentry)
                goto out_delete;
        }
 
-       nfs_zap_caches(dir_i);
+       nfs_zap_caches(dir);
        if (inode)
                NFS_CACHEINV(inode);
-       error = NFS_PROTO(dir_i)->remove(dir, &dentry->d_name);
+       error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
        if (error < 0)
                goto out;
 
@@ -943,9 +906,8 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 }
 
 static int
-nfs_symlink(struct inode *dir_i, struct dentry *dentry, const char *symname)
+nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
-       struct dentry *dir = dentry->d_parent;
        struct iattr attr;
        struct nfs_fattr sym_attr;
        struct nfs_fh sym_fh;
@@ -954,10 +916,10 @@ nfs_symlink(struct inode *dir_i, struct dentry *dentry, const char *symname)
        int error;
 
        dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
-               dir_i->i_dev, dir_i->i_ino, dentry->d_name.name, symname);
+               dir->i_dev, dir->i_ino, dentry->d_name.name, symname);
 
        error = -ENAMETOOLONG;
-       maxlen = (NFS_PROTO(dir_i)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;
+       maxlen = (NFS_PROTO(dir)->version==2) ? NFS2_MAXPATHLEN : NFS3_MAXPATHLEN;
        if (strlen(symname) > maxlen)
                goto out;
 
@@ -976,15 +938,15 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
        qsymname.name = symname;
        qsymname.len  = strlen(symname);
 
-       nfs_zap_caches(dir_i);
-       error = NFS_PROTO(dir_i)->symlink(dir, &dentry->d_name, &qsymname,
+       nfs_zap_caches(dir);
+       error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname,
                                          &attr, &sym_fh, &sym_attr);
        if (!error && sym_fh.size != 0 && (sym_attr.valid & NFS_ATTR_FATTR)) {
                error = nfs_instantiate(dentry, &sym_fh, &sym_attr);
        } else {
                if (error == -EEXIST)
                        printk("nfs_proc_symlink: %s/%s already exists??\n",
-                              dir->d_name.name, dentry->d_name.name);
+                              dentry->d_parent->d_name.name, dentry->d_name.name);
                d_drop(dentry);
        }
 
@@ -993,9 +955,8 @@ out:
 }
 
 static int 
-nfs_link(struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
+nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
 {
-       struct dentry *dir = dentry->d_parent;
        struct inode *inode = old_dentry->d_inode;
        int error;
 
@@ -1009,9 +970,9 @@ nfs_link(struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
         * we can't use the existing dentry.
         */
        d_drop(dentry);
-       nfs_zap_caches(dir_i);
+       nfs_zap_caches(dir);
        NFS_CACHEINV(inode);
-       error = NFS_PROTO(dir_i)->link(old_dentry, dir, &dentry->d_name);
+       error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
        return error;
 }
 
@@ -1116,10 +1077,8 @@ go_ahead:
 
        nfs_zap_caches(new_dir);
        nfs_zap_caches(old_dir);
-       error = NFS_PROTO(old_dir)->rename(old_dentry->d_parent,
-                                          &old_dentry->d_name,
-                                          new_dentry->d_parent,
-                                          &new_dentry->d_name);
+       error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
+                                          new_dir, &new_dentry->d_name);
 out:
        if (rehash)
                d_rehash(rehash);
@@ -1132,22 +1091,33 @@ out:
        return error;
 }
 
-int nfs_init_fhcache(void)
+int
+nfs_permission(struct inode *inode, int mask)
 {
-       nfs_fh_cachep = kmem_cache_create("nfs_fh",
-                                         sizeof(struct nfs_fh),
-                                         0, SLAB_HWCACHE_ALIGN,
-                                         NULL, NULL);
-       if (nfs_fh_cachep == NULL)
-               return -ENOMEM;
+       int                     error = vfs_permission(inode, mask);
 
-       return 0;
-}
+       if (!NFS_PROTO(inode)->access)
+               goto out;
+       /*
+        * Trust UNIX mode bits except:
+        *
+        * 1) When override capabilities may have been invoked
+        * 2) When root squashing may be involved
+        * 3) When ACLs may overturn a negative answer */
+       if (!capable(CAP_DAC_OVERRIDE) && !capable(CAP_DAC_READ_SEARCH)
+           && (current->fsuid != 0) && (current->fsgid != 0)
+           && error != -EACCES)
+               goto out;
 
-void nfs_destroy_fhcache(void)
-{
-       if (kmem_cache_destroy(nfs_fh_cachep))
-               printk(KERN_INFO "nfs_fh: not all structures were freed\n");
+       error = NFS_PROTO(inode)->access(inode, mask, 0);
+
+       if (error == -EACCES && NFS_CLIENT(inode)->cl_droppriv &&
+           current->uid != 0 && current->gid != 0 &&
+           (current->fsuid != current->uid || current->fsgid != current->gid))
+               error = NFS_PROTO(inode)->access(inode, mask, 1);
+
+ out:
+       return error;
 }
 
 /*
index c30fc5062f20871b624d660f7b334df40be1584d..d5c92ba3be8542bf9d9da21863aadd7c190538ae 100644 (file)
@@ -52,6 +52,7 @@ struct file_operations nfs_file_operations = {
 };
 
 struct inode_operations nfs_file_inode_operations = {
+       permission:     nfs_permission,
        revalidate:     nfs_revalidate,
        setattr:        nfs_notify_change,
 };
@@ -90,13 +91,14 @@ static ssize_t
 nfs_file_read(struct file * file, char * buf, size_t count, loff_t *ppos)
 {
        struct dentry * dentry = file->f_dentry;
+       struct inode * inode = dentry->d_inode;
        ssize_t result;
 
        dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
                (unsigned long) count, (unsigned long) *ppos);
 
-       result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+       result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
        if (!result)
                result = generic_file_read(file, buf, count, ppos);
        return result;
@@ -106,12 +108,13 @@ static int
 nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 {
        struct dentry *dentry = file->f_dentry;
+       struct inode *inode = dentry->d_inode;
        int     status;
 
        dfprintk(VFS, "nfs: mmap(%s/%s)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
-       status = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+       status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
        if (!status)
                status = generic_file_mmap(file, vma);
        return status;
@@ -179,7 +182,7 @@ static int nfs_sync_page(struct page *page)
        struct address_space *mapping;
        struct inode    *inode;
        unsigned long   index = page_index(page);
-       unsigned int    rpages, wpages;
+       unsigned int    rpages;
        int             result;
 
        mapping = page->mapping;
@@ -192,14 +195,8 @@ static int nfs_sync_page(struct page *page)
        rpages = NFS_SERVER(inode)->rpages;
        result = nfs_pagein_inode(inode, index, rpages);
        if (result < 0)
-               goto out_bad;
-       wpages = NFS_SERVER(inode)->wpages;
-       result = nfs_sync_file(inode, NULL, index, wpages, FLUSH_STABLE);
-       if (result < 0)
-               goto out_bad;
+               return result;
        return 0;
- out_bad:
-       return result;
 }
 
 struct address_space_operations nfs_file_aops = {
@@ -227,7 +224,7 @@ nfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
        result = -EBUSY;
        if (IS_SWAPFILE(inode))
                goto out_swapfile;
-       result = nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+       result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
        if (result)
                goto out;
 
index 5b582024ef94d421470743cacef9ccb1c4bff206..a205c3ad4a281230971a333275d32e6a8ad94d80 100644 (file)
@@ -39,7 +39,7 @@
 #define NFSDBG_FACILITY                NFSDBG_VFS
 #define NFS_PARANOIA 1
 
-static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *);
+static struct inode * __nfs_fhget(struct super_block *, struct nfs_fh *, struct nfs_fattr *);
 void nfs_zap_caches(struct inode *);
 static void nfs_invalidate_inode(struct inode *);
 
@@ -222,13 +222,10 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh)
                return NULL;
        }
 
-       inode = __nfs_fhget(sb, &fattr);
+       inode = __nfs_fhget(sb, rootfh, &fattr);
        return inode;
 }
 
-extern struct nfs_fh *nfs_fh_alloc(void);
-extern void nfs_fh_free(struct nfs_fh *p);
-
 /*
  * The way this works is that the mount process passes a structure
  * in the data argument which contains the server's IP address
@@ -242,7 +239,7 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
        struct nfs_server       *server;
        struct rpc_xprt         *xprt = NULL;
        struct rpc_clnt         *clnt = NULL;
-       struct nfs_fh           *root = &data->root, *root_fh, fh;
+       struct nfs_fh           *root = &data->root, fh;
        struct inode            *root_inode = NULL;
        unsigned int            authflavor;
        struct sockaddr_in      srvaddr;
@@ -365,16 +362,10 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
         * Keep the super block locked while we try to get 
         * the root fh attributes.
         */
-       root_fh = nfs_fh_alloc();
-       if (!root_fh)
-               goto out_no_fh;
-       memcpy((u8*)root_fh, (u8*)root, sizeof(*root));
-
        /* Did getting the root inode fail? */
        if (!(root_inode = nfs_get_root(sb, root))
            && (data->flags & NFS_MOUNT_VER3)) {
                data->flags &= ~NFS_MOUNT_VER3;
-               nfs_fh_free(root_fh);
                rpciod_down();
                rpc_shutdown_client(server->client);
                goto nfsv3_try_again;
@@ -387,7 +378,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
                goto out_no_root;
 
        sb->s_root->d_op = &nfs_dentry_operations;
-       sb->s_root->d_fsdata = root_fh;
 
        /* Get some general file system info */
         if (server->rpc_ops->statfs(server, root, &fsinfo) >= 0) {
@@ -462,8 +452,6 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
 out_no_root:
        printk("nfs_read_super: get root inode failed\n");
        iput(root_inode);
-       nfs_fh_free(root_fh);
-out_no_fh:
        rpciod_down();
        goto out_shutdown;
 
@@ -507,7 +495,7 @@ nfs_statfs(struct super_block *sb, struct statfs *buf)
        struct nfs_fsinfo res;
        int error;
 
-       error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root), &res);
+       error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root->d_inode), &res);
        buf->f_type = NFS_SUPER_MAGIC;
        if (error < 0)
                goto out_err;
@@ -531,43 +519,6 @@ nfs_statfs(struct super_block *sb, struct statfs *buf)
        return 0;
 }
 
-/*
- * Free all unused dentries in an inode's alias list.
- *
- * Subtle note: we have to be very careful not to cause
- * any IO operations with the stale dentries, as this
- * could cause file corruption. But since the dentry
- * count is 0 and all pending IO for a dentry has been
- * flushed when the count went to 0, we're safe here.
- * Also returns the number of unhashed dentries
- */
-static int
-nfs_free_dentries(struct inode *inode)
-{
-       struct list_head *tmp, *head;
-       int unhashed;
-
-       if (S_ISDIR(inode->i_mode)) {
-               struct dentry *dentry = d_find_alias(inode);
-               if (dentry) {
-                       shrink_dcache_parent(dentry);
-                       dput(dentry);
-               }
-       }
-       d_prune_aliases(inode);
-       spin_lock(&dcache_lock);
-       head = &inode->i_dentry;
-       tmp = head;
-       unhashed = 0;
-       while ((tmp = tmp->next) != head) {
-               struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
-               if (list_empty(&dentry->d_hash))
-                       unhashed++;
-       }
-       spin_unlock(&dcache_lock);
-       return unhashed;
-}
-
 /*
  * Invalidate the local caches
  */
@@ -600,7 +551,7 @@ nfs_invalidate_inode(struct inode *inode)
  * Fill in inode information from the fattr.
  */
 static void
-nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
+nfs_fill_inode(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr)
 {
        /*
         * Check whether the mode has been set, as we only want to
@@ -638,6 +589,7 @@ nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
                NFS_CACHE_ISIZE(inode) = fattr->size;
                NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
                NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
+               memcpy(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh));
        }
        nfs_refresh_inode(inode, fattr);
 }
@@ -652,42 +604,34 @@ static int
 nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque)
 {
        struct nfs_fattr *fattr = (struct nfs_fattr *)opaque;
+
        if (NFS_FSID(inode) != fattr->fsid)
                return 0;
        if (NFS_FILEID(inode) != fattr->fileid)
                return 0;
+
        return 1;
 }
 
 static int
-nfs_inode_is_stale(struct inode *inode, struct nfs_fattr *fattr)
+nfs_inode_is_stale(struct inode *inode, struct nfs_fh *fh, struct nfs_fattr *fattr)
 {
-       int unhashed;
-       int is_stale = 0;
+       /* Empty inodes are not stale */
+       if (!inode->i_mode)
+               return 0;
 
-       if (inode->i_mode &&
-           (fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
-               is_stale = 1;
+       if ((fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
+               return 1;
 
        if (is_bad_inode(inode))
-               is_stale = 1;
+               return 1;
 
-       /*
-        * If the inode seems stale, free up cached dentries.
-        */
-       unhashed = nfs_free_dentries(inode);
-
-       /* Assume we're holding an i_count
-        *
-        * NB: sockets sometimes have volatile file handles
-        *     don't invalidate their inodes even if all dentries are
-        *     unhashed.
-        */
-       if (unhashed && atomic_read(&inode->i_count) == unhashed + 1
-           && !S_ISSOCK(inode->i_mode) && !S_ISFIFO(inode->i_mode))
-               is_stale = 1;
+       /* Has the filehandle changed? If so is the old one stale? */
+       if (memcmp(&inode->u.nfs_i.fh, fh, sizeof(inode->u.nfs_i.fh)) != 0 &&
+           __nfs_revalidate_inode(NFS_SERVER(inode),inode) < 0)
+               return 1;
 
-       return is_stale;
+       return 0;
 }
 
 /*
@@ -709,9 +653,6 @@ nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
                dentry->d_parent->d_name.name, dentry->d_name.name,
                (long long)fattr->fileid);
 
-       /* Install the file handle in the dentry */
-       memcpy(dentry->d_fsdata, fhandle, sizeof(struct nfs_fh));
-
 #ifdef CONFIG_NFS_SNAPSHOT
        /*
         * Check for NetApp snapshot dentries, and get an 
@@ -725,14 +666,14 @@ nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
                        goto out;
                inode->i_ino = nfs_fattr_to_ino_t(fattr);
                nfs_read_inode(inode);
-               nfs_fill_inode(inode, fattr);
+               nfs_fill_inode(inode, fhandle, fattr);
                inode->u.nfs_i.flags |= NFS_IS_SNAPSHOT;
                dprintk("NFS: nfs_fhget(snapshot ino=%ld)\n", inode->i_ino);
        out:
                return inode;
        }
 #endif
-       return __nfs_fhget(sb, fattr);
+       return __nfs_fhget(sb, fhandle, fattr);
 }
 
 /*
@@ -744,7 +685,7 @@ nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
  * server has reused a fileid (i_ino) and we have a stale inode.
  */
 static struct inode *
-__nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
+__nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 {
        struct inode *inode = NULL;
        unsigned long ino;
@@ -770,11 +711,12 @@ __nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
                 * as the inode may have become a different object.
                 * (We can probably handle modes changes here, too.)
                 */
-               if (!nfs_inode_is_stale(inode,fattr))
+               if (!nfs_inode_is_stale(inode, fh, fattr))
                        break;
 
-               dprintk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
-                      inode->i_ino, atomic_read(&inode->i_count));
+               dprintk("__nfs_fhget: inode (%x/%Ld) still busy, i_count=%d\n",
+                       inode->i_dev, (long long)NFS_FILEID(inode),
+                       atomic_read(&inode->i_count));
                nfs_zap_caches(inode);
                remove_inode_hash(inode);
                iput(inode);
@@ -783,9 +725,10 @@ __nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
        if (!inode)
                goto out_no_inode;
 
-       nfs_fill_inode(inode, fattr);
-       dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n",
-               inode->i_dev, inode->i_ino, atomic_read(&inode->i_count));
+       nfs_fill_inode(inode, fh, fattr);
+       dprintk("NFS: __nfs_fhget(%x/%Ld ct=%d)\n",
+               inode->i_dev, (long long)NFS_FILEID(inode),
+               atomic_read(&inode->i_count));
 
 out:
        return inode;
@@ -820,7 +763,7 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
        if (error)
                goto out;
 
-       error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
+       error = NFS_PROTO(inode)->setattr(inode, &fattr, attr);
        if (error)
                goto out;
        /*
@@ -872,7 +815,8 @@ nfs_wait_on_inode(struct inode *inode, int flag)
 int
 nfs_revalidate(struct dentry *dentry)
 {
-       return nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+       struct inode *inode = dentry->d_inode;
+       return nfs_revalidate_inode(NFS_SERVER(inode), inode);
 }
 
 /*
@@ -913,15 +857,13 @@ int nfs_release(struct inode *inode, struct file *filp)
  * the cached attributes have to be refreshed.
  */
 int
-__nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
+__nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
-       struct inode    *inode = dentry->d_inode;
        int              status = 0;
        struct nfs_fattr fattr;
 
-       dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
-               dentry->d_parent->d_name.name, dentry->d_name.name,
-               inode->i_ino);
+       dfprintk(PAGECACHE, "NFS: revalidating (%x/%Ld)\n",
+               inode->i_dev, (long long)NFS_FILEID(inode));
 
        lock_kernel();
        if (!inode || is_bad_inode(inode)) {
@@ -942,46 +884,21 @@ __nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
        }
        NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;
 
-       status = NFS_PROTO(inode)->getattr(dentry, &fattr);
+       status = NFS_PROTO(inode)->getattr(inode, &fattr);
        if (status) {
-               struct dentry *dir = dentry->d_parent;
-               struct inode *dir_i = dir->d_inode;
-               int error;
-               u32 *fh;
-               struct nfs_fh fhandle;
-               dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s getattr failed, ino=%ld, error=%d\n",
-                        dir->d_name.name, dentry->d_name.name,
-                        inode->i_ino, status);
-               if (status != -ESTALE)
-                       goto out;
-               /*
-                * A "stale filehandle" error ... show the current fh
-                * and find out what the filehandle should be.
-                */
-               fh = (u32 *) NFS_FH(dentry)->data;
-               dfprintk(PAGECACHE, "NFS: bad fh %08x%08x%08x%08x%08x%08x%08x%08x\n",
-                       fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]);
-               error = NFS_PROTO(dir_i)->lookup(dir, &dentry->d_name,
-                                                &fhandle, &fattr);
-               if (error) {
-                       dfprintk(PAGECACHE, "NFS: lookup failed, error=%d\n", error);
-                       goto out;
-               }
-               fh = (u32 *) fhandle.data;
-               dfprintk(PAGECACHE, "            %08x%08x%08x%08x%08x%08x%08x%08x\n",
-                       fh[0],fh[1],fh[2],fh[3],fh[4],fh[5],fh[6],fh[7]);
+               dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) getattr failed, error=%d\n",
+                        inode->i_dev, (long long)NFS_FILEID(inode), status);
                goto out;
        }
 
        status = nfs_refresh_inode(inode, &fattr);
        if (status) {
-               dfprintk(PAGECACHE, "nfs_revalidate_inode: %s/%s refresh failed, ino=%ld, error=%d\n",
-                       dentry->d_parent->d_name.name,
-                       dentry->d_name.name, inode->i_ino, status);
+               dfprintk(PAGECACHE, "nfs_revalidate_inode: (%x/%Ld) refresh failed, error=%d\n",
+                        inode->i_dev, (long long)NFS_FILEID(inode), status);
                goto out;
        }
-       dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
-               dentry->d_parent->d_name.name, dentry->d_name.name);
+       dfprintk(PAGECACHE, "NFS: (%x/%Ld) revalidation complete\n",
+               inode->i_dev, (long long)NFS_FILEID(inode));
 out:
        NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
        wake_up(&inode->i_wait);
@@ -1165,8 +1082,6 @@ out_changed:
  */
 static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, FS_ODD_RENAME);
 
-extern int nfs_init_fhcache(void);
-extern void nfs_destroy_fhcache(void);
 extern int nfs_init_nfspagecache(void);
 extern void nfs_destroy_nfspagecache(void);
 extern int nfs_init_readpagecache(void);
@@ -1180,10 +1095,6 @@ init_nfs_fs(void)
 {
        int err;
 
-       err = nfs_init_fhcache();
-       if (err)
-               return err;
-
        err = nfs_init_nfspagecache();
        if (err)
                return err;
@@ -1218,7 +1129,6 @@ cleanup_module(void)
 {
        nfs_destroy_readpagecache();
        nfs_destroy_nfspagecache();
-       nfs_destroy_fhcache();
 #ifdef CONFIG_PROC_FS
        rpc_proc_unregister("nfs");
 #endif
index d75e9eda00ec3434603d808f88e915bfafe5d203..86cfd1b811ef96af8696905a7067e519c138e0de 100644 (file)
@@ -37,34 +37,34 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * One function for each procedure in the NFS protocol.
  */
 static int
-nfs3_proc_getattr(struct dentry *dentry, struct nfs_fattr *fattr)
+nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
 {
        int     status;
 
        dprintk("NFS call  getattr\n");
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_GETATTR,
-                         NFS_FH(dentry), fattr, 0);
+       status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
+                         NFS_FH(inode), fattr, 0);
        dprintk("NFS reply getattr\n");
        return status;
 }
 
 static int
-nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
+nfs3_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
                        struct iattr *sattr)
 {
-       struct nfs3_sattrargs   arg = { NFS_FH(dentry), sattr, 0, 0 };
+       struct nfs3_sattrargs   arg = { NFS_FH(inode), sattr, 0, 0 };
        int     status;
 
        dprintk("NFS call  setattr\n");
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_SETATTR, &arg, fattr, 0);
+       status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0);
        dprintk("NFS reply setattr\n");
        return status;
 }
 
 static int
-nfs3_proc_lookup(struct dentry *dir, struct qstr *name,
+nfs3_proc_lookup(struct inode *dir, struct qstr *name,
                 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_fattr        dir_attr;
@@ -75,20 +75,20 @@ nfs3_proc_lookup(struct dentry *dir, struct qstr *name,
        dprintk("NFS call  lookup %s\n", name->name);
        dir_attr.valid = 0;
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_LOOKUP, &arg, &res, 0);
+       status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0);
        if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR))
-               status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_GETATTR,
+               status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR,
                         fhandle, fattr, 0);
        dprintk("NFS reply lookup: %d\n", status);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       nfs_refresh_inode(dir, &dir_attr);
        return status;
 }
 
 static int
-nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
+nfs3_proc_access(struct inode *inode, int mode, int ruid)
 {
        struct nfs_fattr        fattr;
-       struct nfs3_accessargs  arg = { NFS_FH(dentry), 0 };
+       struct nfs3_accessargs  arg = { NFS_FH(inode), 0 };
        struct nfs3_accessres   res = { &fattr, 0 };
        int     status, flags;
 
@@ -97,7 +97,7 @@ nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
 
        if (mode & MAY_READ)
                arg.access |= NFS3_ACCESS_READ;
-       if (S_ISDIR(dentry->d_inode->i_mode)) {
+       if (S_ISDIR(inode->i_mode)) {
                if (mode & MAY_WRITE)
                        arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
                if (mode & MAY_EXEC)
@@ -109,8 +109,8 @@ nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
                        arg.access |= NFS3_ACCESS_EXECUTE;
        }
        flags = (ruid) ? RPC_CALL_REALUID : 0;
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_ACCESS, &arg, &res, flags);
-       nfs_refresh_inode(dentry->d_inode, &fattr);
+       status = rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS, &arg, &res, flags);
+       nfs_refresh_inode(inode, &fattr);
        dprintk("NFS reply access\n");
 
        if (status == 0 && (arg.access & res.access) != arg.access)
@@ -119,29 +119,28 @@ nfs3_proc_access(struct dentry *dentry, int mode, int ruid)
 }
 
 static int
-nfs3_proc_readlink(struct dentry *dentry, void *buffer, unsigned int buflen)
+nfs3_proc_readlink(struct inode *inode, void *buffer, unsigned int buflen)
 {
        struct nfs_fattr        fattr;
-       struct nfs3_readlinkargs args = { NFS_FH(dentry), buffer, buflen };
+       struct nfs3_readlinkargs args = { NFS_FH(inode), buffer, buflen };
        struct nfs3_readlinkres res = { &fattr, buffer, buflen };
        int                     status;
 
        dprintk("NFS call  readlink\n");
        fattr.valid = 0;
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_READLINK,
+       status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK,
                          &args, &res, 0);
-       nfs_refresh_inode(dentry->d_inode, &fattr);
+       nfs_refresh_inode(inode, &fattr);
        dprintk("NFS reply readlink: %d\n", status);
        return status;
 }
 
 static int
-nfs3_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
+nfs3_proc_read(struct inode *inode, struct rpc_cred *cred,
+              struct nfs_fattr *fattr, int flags,
               loff_t offset, unsigned int count, void *buffer, int *eofp)
 {
-       struct dentry           *dentry = file->f_dentry;
-       struct rpc_cred         *cred = nfs_file_cred(file);
-       struct nfs_readargs     arg = { NFS_FH(dentry), offset, count, 1,
+       struct nfs_readargs     arg = { NFS_FH(inode), offset, count, 1,
                                        {{buffer, count}, {0,0}, {0,0}, {0,0},
                                         {0,0}, {0,0}, {0,0}, {0,0}} };
        struct nfs_readres      res = { fattr, count, 0 };
@@ -150,20 +149,19 @@ nfs3_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
 
        dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
        fattr->valid = 0;
-       status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags);
+       status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
        dprintk("NFS reply read: %d\n", status);
        *eofp = res.eof;
        return status;
 }
 
 static int
-nfs3_proc_write(struct file *file, struct nfs_fattr *fattr, int flags,
+nfs3_proc_write(struct inode *inode, struct rpc_cred *cred,
+               struct nfs_fattr *fattr, int flags,
                loff_t offset, unsigned int count,
                void *buffer, struct nfs_writeverf *verf)
 {
-       struct dentry           *dentry = file->f_dentry;
-       struct rpc_cred         *cred = nfs_file_cred(file);
-       struct nfs_writeargs    arg = { NFS_FH(dentry), offset, count,
+       struct nfs_writeargs    arg = { NFS_FH(inode), offset, count,
                                        NFS_FILE_SYNC, 1,
                                        {{buffer, count}, {0,0}, {0,0}, {0,0},
                                         {0,0}, {0,0}, {0,0}, {0,0}} };
@@ -177,7 +175,7 @@ nfs3_proc_write(struct file *file, struct nfs_fattr *fattr, int flags,
                rpcflags |= NFS_RPC_SWAPFLAGS;
        arg.stable = (flags & NFS_RW_SYNC) ? NFS_FILE_SYNC : NFS_UNSTABLE;
 
-       status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, rpcflags);
+       status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
 
        dprintk("NFS reply read: %d\n", status);
        return status < 0? status : res.count;
@@ -188,7 +186,7 @@ nfs3_proc_write(struct file *file, struct nfs_fattr *fattr, int flags,
  * For now, we don't implement O_EXCL.
  */
 static int
-nfs3_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs3_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
                 int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_fattr        dir_attr;
@@ -208,8 +206,8 @@ nfs3_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
 again:
        dir_attr.valid = 0;
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_CREATE, &arg, &res, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0);
+       nfs_refresh_inode(dir, &dir_attr);
 
        /* If the server doesn't support the exclusive creation semantics,
         * try again with simple 'guarded' mode. */
@@ -242,7 +240,7 @@ exit:
                 * not sure this buys us anything (and I'd have
                 * to revamp the NFSv3 XDR code) */
                fattr->valid = 0;
-               status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_SETATTR,
+               status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
                                                &arg, fattr, 0);
                dprintk("NFS reply setattr (post-create): %d\n", status);
        }
@@ -251,7 +249,7 @@ exit:
 }
 
 static int
-nfs3_proc_remove(struct dentry *dir, struct qstr *name)
+nfs3_proc_remove(struct inode *dir, struct qstr *name)
 {
        struct nfs_fattr        dir_attr;
        struct nfs3_diropargs   arg = { NFS_FH(dir), name->name, name->len };
@@ -260,8 +258,8 @@ nfs3_proc_remove(struct dentry *dir, struct qstr *name)
 
        dprintk("NFS call  remove %s\n", name->name);
        dir_attr.valid = 0;
-       status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+       nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply remove: %d\n", status);
        return status;
 }
@@ -276,7 +274,7 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr
        if (!arg)
                return -ENOMEM;
        res = (struct nfs_fattr*)(arg + 1);
-       arg->fh = NFS_FH(dir);
+       arg->fh = NFS_FH(dir->d_inode);
        arg->name = name->name;
        arg->len = name->len;
        res->valid = 0;
@@ -299,8 +297,8 @@ nfs3_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
 }
 
 static int
-nfs3_proc_rename(struct dentry *old_dir, struct qstr *old_name,
-                struct dentry *new_dir, struct qstr *new_name)
+nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
+                struct inode *new_dir, struct qstr *new_name)
 {
        struct nfs_fattr        old_dir_attr, new_dir_attr;
        struct nfs3_renameargs  arg = { NFS_FH(old_dir),
@@ -313,18 +311,18 @@ nfs3_proc_rename(struct dentry *old_dir, struct qstr *old_name,
        dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
        old_dir_attr.valid = 0;
        new_dir_attr.valid = 0;
-       status = rpc_call(NFS_CLIENT(old_dir->d_inode), NFS3PROC_RENAME, &arg, &res, 0);
-       nfs_refresh_inode(old_dir->d_inode, &old_dir_attr);
-       nfs_refresh_inode(new_dir->d_inode, &new_dir_attr);
+       status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0);
+       nfs_refresh_inode(old_dir, &old_dir_attr);
+       nfs_refresh_inode(new_dir, &new_dir_attr);
        dprintk("NFS reply rename: %d\n", status);
        return status;
 }
 
 static int
-nfs3_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name)
+nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
        struct nfs_fattr        dir_attr, fattr;
-       struct nfs3_linkargs    arg = { NFS_FH(dentry), NFS_FH(dir),
+       struct nfs3_linkargs    arg = { NFS_FH(inode), NFS_FH(dir),
                                        name->name, name->len };
        struct nfs3_linkres     res = { &dir_attr, &fattr };
        int                     status;
@@ -332,15 +330,15 @@ nfs3_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name)
        dprintk("NFS call  link %s\n", name->name);
        dir_attr.valid = 0;
        fattr.valid = 0;
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFS3PROC_LINK, &arg, &res, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
-       nfs_refresh_inode(dentry->d_inode, &fattr);
+       status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0);
+       nfs_refresh_inode(dir, &dir_attr);
+       nfs_refresh_inode(inode, &fattr);
        dprintk("NFS reply link: %d\n", status);
        return status;
 }
 
 static int
-nfs3_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
+nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
                  struct iattr *sattr, struct nfs_fh *fhandle,
                  struct nfs_fattr *fattr)
 {
@@ -353,14 +351,14 @@ nfs3_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
        dir_attr.valid = 0;
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_SYMLINK, &arg, &res, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0);
+       nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply symlink: %d\n", status);
        return status;
 }
 
 static int
-nfs3_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
                struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_fattr        dir_attr;
@@ -372,14 +370,14 @@ nfs3_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
        dprintk("NFS call  mkdir %s\n", name->name);
        dir_attr.valid = 0;
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_MKDIR, &arg, &res, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
+       nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply mkdir: %d\n", status);
        return status;
 }
 
 static int
-nfs3_proc_rmdir(struct dentry *dir, struct qstr *name)
+nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
 {
        struct nfs_fattr        dir_attr;
        struct nfs3_diropargs   arg = { NFS_FH(dir), name->name, name->len };
@@ -387,8 +385,8 @@ nfs3_proc_rmdir(struct dentry *dir, struct qstr *name)
 
        dprintk("NFS call  rmdir %s\n", name->name);
        dir_attr.valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0);
+       nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply rmdir: %d\n", status);
        return status;
 }
@@ -403,16 +401,15 @@ nfs3_proc_rmdir(struct dentry *dir, struct qstr *name)
  * readdirplus.
  */
 static int
-nfs3_proc_readdir(struct file *file, u64 cookie, void *entry,
+nfs3_proc_readdir(struct inode *dir, struct rpc_cred *cred,
+                 u64 cookie, void *entry,
                  unsigned int size, int plus)
 {
-       struct dentry           *dir = file->f_dentry;
-       struct rpc_cred         *cred = nfs_file_cred(file);
        struct nfs_fattr        dir_attr;
        struct nfs3_readdirargs arg = { NFS_FH(dir), cookie, {0, 0}, 0, 0, 0 };
        struct nfs3_readdirres  res = { &dir_attr, 0, 0, 0, 0 };
        struct rpc_message      msg = { NFS3PROC_READDIR, &arg, &res, cred };
-       u32                     *verf = NFS_COOKIEVERF(dir->d_inode);
+       u32                     *verf = NFS_COOKIEVERF(dir);
        int                     status;
 
        arg.buffer  = entry;
@@ -432,14 +429,14 @@ nfs3_proc_readdir(struct file *file, u64 cookie, void *entry,
                        plus? "plus" : "", (unsigned int) cookie);
 
        dir_attr.valid = 0;
-       status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+       nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply readdir: %d\n", status);
        return status;
 }
 
 static int
-nfs3_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
                dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
 {
        struct nfs_fattr        dir_attr;
@@ -459,8 +456,8 @@ nfs3_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
        dprintk("NFS call  mknod %s %x\n", name->name, rdev);
        dir_attr.valid = 0;
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFS3PROC_MKNOD, &arg, &res, 0);
-       nfs_refresh_inode(dir->d_inode, &dir_attr);
+       status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
+       nfs_refresh_inode(dir, &dir_attr);
        dprintk("NFS reply mknod: %d\n", status);
        return status;
 }
index be935c0838aa6aa3fb93fc0593f84e5f54708109..17bb39f36ca80445995f936ce1f4d7c58eb76992 100644 (file)
@@ -64,34 +64,34 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * One function for each procedure in the NFS protocol.
  */
 static int
-nfs_proc_getattr(struct dentry *dentry, struct nfs_fattr *fattr)
+nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
 {
        int     status;
 
        dprintk("NFS call  getattr\n");
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_GETATTR,
-                               NFS_FH(dentry), fattr, 0);
+       status = rpc_call(NFS_CLIENT(inode), NFSPROC_GETATTR,
+                               NFS_FH(inode), fattr, 0);
        dprintk("NFS reply getattr\n");
        return status;
 }
 
 static int
-nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
+nfs_proc_setattr(struct inode *inode, struct nfs_fattr *fattr,
                 struct iattr *sattr)
 {
-       struct nfs_sattrargs    arg = { NFS_FH(dentry), sattr };
+       struct nfs_sattrargs    arg = { NFS_FH(inode), sattr };
        int     status;
 
        dprintk("NFS call  setattr\n");
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_SETATTR, &arg, fattr, 0);
+       status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0);
        dprintk("NFS reply setattr\n");
        return status;
 }
 
 static int
-nfs_proc_lookup(struct dentry *dir, struct qstr *name,
+nfs_proc_lookup(struct inode *dir, struct qstr *name,
                struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_diropargs    arg = { NFS_FH(dir), name->name, name->len };
@@ -100,32 +100,31 @@ nfs_proc_lookup(struct dentry *dir, struct qstr *name,
 
        dprintk("NFS call  lookup %s\n", name->name);
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_LOOKUP, &arg, &res, 0);
+       status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0);
        dprintk("NFS reply lookup: %d\n", status);
        return status;
 }
 
 static int
-nfs_proc_readlink(struct dentry *dentry, void *buffer, unsigned int bufsiz)
+nfs_proc_readlink(struct inode *inode, void *buffer, unsigned int bufsiz)
 {
-       struct nfs_readlinkargs args = { NFS_FH(dentry), buffer, bufsiz };
+       struct nfs_readlinkargs args = { NFS_FH(inode), buffer, bufsiz };
        struct nfs_readlinkres  res = { buffer, bufsiz };
        int                     status;
 
        dprintk("NFS call  readlink\n");
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_READLINK,
+       status = rpc_call(NFS_CLIENT(inode), NFSPROC_READLINK,
                                        &args, &res, 0);
        dprintk("NFS reply readlink: %d\n", status);
        return status;
 }
 
 static int
-nfs_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
+nfs_proc_read(struct inode *inode, struct rpc_cred *cred,
+             struct nfs_fattr *fattr, int flags,
              loff_t offset, unsigned int count, void *buffer, int *eofp)
 {
-       struct dentry           *dentry = file->f_dentry;
-       struct rpc_cred         *cred = nfs_file_cred(file);
-       struct nfs_readargs     arg = { NFS_FH(dentry), offset, count, 1,
+       struct nfs_readargs     arg = { NFS_FH(inode), offset, count, 1,
                                       {{ buffer, count }, {0,0}, {0,0}, {0,0},
                                        {0,0}, {0,0}, {0,0}, {0,0}} };
        struct nfs_readres      res = { fattr, count, 0};
@@ -134,7 +133,7 @@ nfs_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
 
        dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
        fattr->valid = 0;
-       status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags);
+       status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 
        dprintk("NFS reply read: %d\n", status);
        *eofp = res.eof;
@@ -142,13 +141,12 @@ nfs_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
 }
 
 static int
-nfs_proc_write(struct file *file, struct nfs_fattr *fattr, int how,
+nfs_proc_write(struct inode *inode, struct rpc_cred *cred,
+              struct nfs_fattr *fattr, int how,
               loff_t offset, unsigned int count,
               void *buffer, struct nfs_writeverf *verf)
 {
-       struct dentry           *dentry = file->f_dentry;
-       struct rpc_cred         *cred = nfs_file_cred(file);
-       struct nfs_writeargs    arg = {NFS_FH(dentry), offset, count,
+       struct nfs_writeargs    arg = {NFS_FH(inode), offset, count,
                                        NFS_FILE_SYNC, 1,
                                        {{buffer, count}, {0,0}, {0,0}, {0,0},
                                         {0,0}, {0,0}, {0,0}, {0,0}}};
@@ -160,7 +158,7 @@ nfs_proc_write(struct file *file, struct nfs_fattr *fattr, int how,
        fattr->valid = 0;
        if (how & NFS_RW_SWAP)
                flags |= NFS_RPC_SWAPFLAGS;
-       status = rpc_call_sync(NFS_CLIENT(dentry->d_inode), &msg, flags);
+       status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 
        dprintk("NFS reply write: %d\n", status);
        verf->committed = NFS_FILE_SYNC;      /* NFSv2 always syncs data */
@@ -168,7 +166,7 @@ nfs_proc_write(struct file *file, struct nfs_fattr *fattr, int how,
 }
 
 static int
-nfs_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
                int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_createargs   arg = { NFS_FH(dir), name->name,
@@ -178,7 +176,7 @@ nfs_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
 
        fattr->valid = 0;
        dprintk("NFS call  create %s\n", name->name);
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0);
+       status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
        dprintk("NFS reply create: %d\n", status);
        return status;
 }
@@ -187,7 +185,7 @@ nfs_proc_create(struct dentry *dir, struct qstr *name, struct iattr *sattr,
  * In NFSv2, mknod is grafted onto the create call.
  */
 static int
-nfs_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
               dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_createargs   arg = { NFS_FH(dir), name->name,
@@ -207,26 +205,26 @@ nfs_proc_mknod(struct dentry *dir, struct qstr *name, struct iattr *sattr,
        }
 
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0);
+       status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
 
        if (status == -EINVAL && S_ISFIFO(mode)) {
                sattr->ia_mode = mode;
                fattr->valid = 0;
-               status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_CREATE, &arg, &res, 0);
+               status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
        }
        dprintk("NFS reply mknod: %d\n", status);
        return status;
 }
   
 static int
-nfs_proc_remove(struct dentry *dir, struct qstr *name)
+nfs_proc_remove(struct inode *dir, struct qstr *name)
 {
        struct nfs_diropargs    arg = { NFS_FH(dir), name->name, name->len };
        struct rpc_message      msg = { NFSPROC_REMOVE, &arg, NULL, NULL };
        int                     status;
 
        dprintk("NFS call  remove %s\n", name->name);
-       status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
+       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 
        dprintk("NFS reply remove: %d\n", status);
        return status;
@@ -240,7 +238,7 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *
        arg = (struct nfs_diropargs *)kmalloc(sizeof(*arg), GFP_KERNEL);
        if (!arg)
                return -ENOMEM;
-       arg->fh = NFS_FH(dir);
+       arg->fh = NFS_FH(dir->d_inode);
        arg->name = name->name;
        arg->len = name->len;
        msg->rpc_proc = NFSPROC_REMOVE;
@@ -258,8 +256,8 @@ nfs_proc_unlink_done(struct dentry *dir, struct rpc_message *msg)
 }
 
 static int
-nfs_proc_rename(struct dentry *old_dir, struct qstr *old_name,
-               struct dentry *new_dir, struct qstr *new_name)
+nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
+               struct inode *new_dir, struct qstr *new_name)
 {
        struct nfs_renameargs   arg = { NFS_FH(old_dir), old_name->name,
                                        old_name->len,
@@ -268,26 +266,26 @@ nfs_proc_rename(struct dentry *old_dir, struct qstr *old_name,
        int                     status;
 
        dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
-       status = rpc_call(NFS_CLIENT(old_dir->d_inode), NFSPROC_RENAME, &arg, NULL, 0);
+       status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0);
        dprintk("NFS reply rename: %d\n", status);
        return status;
 }
 
 static int
-nfs_proc_link(struct dentry *dentry, struct dentry *dir, struct qstr *name)
+nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
-       struct nfs_linkargs     arg = { NFS_FH(dentry), NFS_FH(dir),
+       struct nfs_linkargs     arg = { NFS_FH(inode), NFS_FH(dir),
                                        name->name, name->len };
        int                     status;
 
        dprintk("NFS call  link %s\n", name->name);
-       status = rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_LINK, &arg, NULL, 0);
+       status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0);
        dprintk("NFS reply link: %d\n", status);
        return status;
 }
 
 static int
-nfs_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
+nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
                 struct iattr *sattr, struct nfs_fh *fhandle,
                 struct nfs_fattr *fattr)
 {
@@ -297,13 +295,13 @@ nfs_proc_symlink(struct dentry *dir, struct qstr *name, struct qstr *path,
 
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_SYMLINK, &arg, NULL, 0);
+       status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
        dprintk("NFS reply symlink: %d\n", status);
        return status;
 }
 
 static int
-nfs_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
+nfs_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
               struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_createargs   arg = { NFS_FH(dir), name->name, name->len,
@@ -313,19 +311,19 @@ nfs_proc_mkdir(struct dentry *dir, struct qstr *name, struct iattr *sattr,
 
        dprintk("NFS call  mkdir %s\n", name->name);
        fattr->valid = 0;
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_MKDIR, &arg, &res, 0);
+       status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
        dprintk("NFS reply mkdir: %d\n", status);
        return status;
 }
 
 static int
-nfs_proc_rmdir(struct dentry *dir, struct qstr *name)
+nfs_proc_rmdir(struct inode *dir, struct qstr *name)
 {
        struct nfs_diropargs    arg = { NFS_FH(dir), name->name, name->len };
        int                     status;
 
        dprintk("NFS call  rmdir %s\n", name->name);
-       status = rpc_call(NFS_CLIENT(dir->d_inode), NFSPROC_RMDIR, &arg, NULL, 0);
+       status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0);
        dprintk("NFS reply rmdir: %d\n", status);
        return status;
 }
@@ -338,11 +336,10 @@ nfs_proc_rmdir(struct dentry *dir, struct qstr *name)
  * from nfs_readdir by calling the decode_entry function directly.
  */
 static int
-nfs_proc_readdir(struct file *file, __u64 cookie, void *entry, 
+nfs_proc_readdir(struct inode *dir, struct rpc_cred *cred,
+                __u64 cookie, void *entry, 
                 unsigned int size, int plus)
 {
-       struct dentry           *dir = file->f_dentry;
-       struct rpc_cred         *cred = nfs_file_cred(file);
        struct nfs_readdirargs  arg;
        struct nfs_readdirres   res;
        struct rpc_message      msg = { NFSPROC_READDIR, &arg, &res, cred };
@@ -356,7 +353,7 @@ nfs_proc_readdir(struct file *file, __u64 cookie, void *entry,
        res.bufsiz = size;
 
        dprintk("NFS call  readdir %d\n", (unsigned int)cookie);
-       status = rpc_call_sync(NFS_CLIENT(dir->d_inode), &msg, 0);
+       status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 
        dprintk("NFS reply readdir: %d\n", status);
        return status;
index 76fc2f437bb15f22c1dddd4587614e61340af78f..219f4c207a88402b09f48b219ef4d925f247ca70 100644 (file)
@@ -36,7 +36,7 @@
 
 struct nfs_read_data {
        struct rpc_task         task;
-       struct dentry           *dentry;
+       struct inode            *inode;
        struct rpc_cred         *cred;
        struct nfs_readargs     args;   /* XDR argument struct */
        struct nfs_readres      res;    /* ... and result struct */
@@ -82,10 +82,10 @@ static void nfs_readdata_release(struct rpc_task *task)
  * Read a page synchronously.
  */
 static int
-nfs_readpage_sync(struct file *file, struct page *page)
+nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
 {
        struct dentry   *dentry = file->f_dentry;
-       struct inode    *inode = dentry->d_inode;
+       struct rpc_cred *cred = nfs_file_cred(file);
        struct nfs_fattr fattr;
        loff_t          offset = page_offset(page);
        char            *buffer;
@@ -112,8 +112,8 @@ nfs_readpage_sync(struct file *file, struct page *page)
                        (long long)offset, rsize, buffer);
 
                lock_kernel();
-               result = NFS_PROTO(inode)->read(file, &fattr, flags, offset,
-                                               rsize, buffer, &eof);
+               result = NFS_PROTO(inode)->read(inode, cred, &fattr, flags,
+                                               offset, rsize, buffer, &eof);
                unlock_kernel();
                nfs_refresh_inode(inode, &fattr);
 
@@ -180,7 +180,7 @@ nfs_find_read(struct inode *inode, struct page *page)
 static inline void
 nfs_mark_request_read(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_dentry->d_inode;
+       struct inode *inode = req->wb_inode;
 
        spin_lock(&nfs_wreq_lock);
        if (list_empty(&req->wb_list)) {
@@ -196,9 +196,8 @@ nfs_mark_request_read(struct nfs_page *req)
 }
 
 static int
-nfs_readpage_async(struct file *file, struct page *page)
+nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
 {
-       struct inode    *inode = file->f_dentry->d_inode;
        struct nfs_page *req, *new = NULL;
        int             result;
 
@@ -228,7 +227,7 @@ nfs_readpage_async(struct file *file, struct page *page)
                }
 
                result = -ENOMEM;
-               new = nfs_create_request(file, page, 0, PAGE_CACHE_SIZE);
+               new = nfs_create_request(file, inode, page, 0, PAGE_CACHE_SIZE);
                if (!new)
                        break;
        }
@@ -264,9 +263,9 @@ nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
                data->args.nriov++;
        }
        req = nfs_list_entry(data->pages.next);
-       data->dentry      = req->wb_dentry;
+       data->inode       = req->wb_inode;
        data->cred        = req->wb_cred;
-       data->args.fh     = NFS_FH(req->wb_dentry);
+       data->args.fh     = NFS_FH(req->wb_inode);
        data->args.offset = page_offset(req->wb_page) + req->wb_offset;
        data->args.count  = count;
        data->res.fattr   = &data->fattr;
@@ -292,9 +291,8 @@ nfs_async_read_error(struct list_head *head)
 }
 
 static int
-nfs_pagein_one(struct list_head *head, struct dentry *dentry)
+nfs_pagein_one(struct list_head *head, struct inode *inode)
 {
-       struct inode            *inode = dentry->d_inode;
        struct rpc_task         *task;
        struct rpc_clnt         *clnt = NFS_CLIENT(inode);
        struct nfs_read_data    *data;
@@ -328,9 +326,9 @@ nfs_pagein_one(struct list_head *head, struct dentry *dentry)
        msg.rpc_cred = data->cred;
 
        /* Start the async call */
-       dprintk("NFS: %4d initiated read call (req %s/%s count %d nriov %d.\n",
+       dprintk("NFS: %4d initiated read call (req %x/%Ld count %d nriov %d.\n",
                task->tk_pid,
-               dentry->d_parent->d_name.name, dentry->d_name.name,
+               inode->i_dev, (long long)NFS_FILEID(inode),
                data->args.count, data->args.nriov);
 
        rpc_clnt_sigmask(clnt, &oldset);
@@ -355,7 +353,7 @@ nfs_pagein_list(struct inode *inode, struct list_head *head)
        while (!list_empty(head)) {
                pages += nfs_coalesce_requests(head, &one_request, rpages);
                req = nfs_list_entry(one_request.next);
-               error = nfs_pagein_one(&one_request, req->wb_dentry);
+               error = nfs_pagein_one(&one_request, req->wb_inode);
                if (error < 0)
                        break;
        }
@@ -429,8 +427,7 @@ static void
 nfs_readpage_result(struct rpc_task *task)
 {
        struct nfs_read_data    *data = (struct nfs_read_data *) task->tk_calldata;
-       struct dentry           *dentry = data->dentry;
-       struct inode            *inode = dentry->d_inode;
+       struct inode            *inode = data->inode;
        int                     count = data->res.count;
 
        dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
@@ -451,9 +448,9 @@ nfs_readpage_result(struct rpc_task *task)
                kunmap(page);
                UnlockPage(page);
 
-               dprintk("NFS: read (%s/%s %d@%Ld)\n",
-                        req->wb_dentry->d_parent->d_name.name,
-                        req->wb_dentry->d_name.name,
+               dprintk("NFS: read (%x/%Ld %d@%Ld)\n",
+                        req->wb_inode->i_dev,
+                        (long long)NFS_FILEID(req->wb_inode),
                         req->wb_bytes,
                         (long long)(page_offset(page) + req->wb_offset));
                nfs_unlock_request(req);
@@ -473,9 +470,19 @@ nfs_readpage_result(struct rpc_task *task)
 int
 nfs_readpage(struct file *file, struct page *page)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode;
        int             error;
 
+       if (!file) {
+               struct address_space *mapping = page->mapping;
+               if (!mapping)
+                       BUG();
+               inode = (struct inode *)mapping->host;
+       } else
+               inode = file->f_dentry->d_inode;
+       if (!inode)
+               BUG();
+
        dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
                page, PAGE_CACHE_SIZE, page->index);
        /*
@@ -491,11 +498,11 @@ nfs_readpage(struct file *file, struct page *page)
 
        error = -1;
        if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE)
-               error = nfs_readpage_async(file, page);
+               error = nfs_readpage_async(file, inode, page);
        if (error >= 0)
                goto out;
 
-       error = nfs_readpage_sync(file, page);
+       error = nfs_readpage_sync(file, inode, page);
        if (error < 0 && IS_SWAPFILE(inode))
                printk("Aiee.. nfs swap-in of page failed!\n");
 out:
index 4960526b4705b63724eaa84a101ea79400d0ff74..eba7a859a75020808dc4794f09763655ddf96f67 100644 (file)
@@ -27,9 +27,8 @@
 /* Symlink caching in the page cache is even more simplistic
  * and straight-forward than readdir caching.
  */
-static int nfs_symlink_filler(struct dentry *dentry, struct page *page)
+static int nfs_symlink_filler(struct inode *inode, struct page *page)
 {
-       struct inode *inode = dentry->d_inode;
        void *buffer = kmap(page);
        int error;
 
@@ -38,7 +37,7 @@ static int nfs_symlink_filler(struct dentry *dentry, struct page *page)
         * XDR response verification will NULL terminate it.
         */
        lock_kernel();
-       error = NFS_PROTO(inode)->readlink(dentry, buffer,
+       error = NFS_PROTO(inode)->readlink(inode, buffer,
                                           PAGE_CACHE_SIZE - sizeof(u32)-4);
        unlock_kernel();
        if (error < 0)
@@ -55,15 +54,14 @@ error:
        return -EIO;
 }
 
-static char *nfs_getlink(struct dentry *dentry, struct page **ppage)
+static char *nfs_getlink(struct inode *inode, struct page **ppage)
 {
-       struct inode *inode = dentry->d_inode;
        struct page *page;
        u32 *p;
 
        /* Caller revalidated the directory inode already. */
        page = read_cache_page(&inode->i_data, 0,
-                               (filler_t *)nfs_symlink_filler, dentry);
+                               (filler_t *)nfs_symlink_filler, inode);
        if (IS_ERR(page))
                goto read_failed;
        if (!Page_Uptodate(page))
@@ -81,8 +79,9 @@ read_failed:
 
 static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
+       struct inode *inode = dentry->d_inode;
        struct page *page = NULL;
-       int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(dentry,&page));
+       int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(inode,&page));
        if (page) {
                kunmap(page);
                page_cache_release(page);
@@ -92,8 +91,9 @@ static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
 
 static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
+       struct inode *inode = dentry->d_inode;
        struct page *page = NULL;
-       int res = vfs_follow_link(nd, nfs_getlink(dentry,&page));
+       int res = vfs_follow_link(nd, nfs_getlink(inode,&page));
        if (page) {
                kunmap(page);
                page_cache_release(page);
index 2309549931abf9cc0e921f0e9d2267fb242ebaa9..b634bc0f55b4f42f4e128fbbb83b2742d16c0ccf 100644 (file)
@@ -77,7 +77,7 @@ static atomic_t       nfs_nr_requests = ATOMIC_INIT(0);
  */
 struct nfs_write_data {
        struct rpc_task         task;
-       struct dentry           *dentry;
+       struct inode            *inode;
        struct rpc_cred         *cred;
        struct nfs_writeargs    args;           /* argument struct */
        struct nfs_writeres     res;            /* result struct */
@@ -89,7 +89,8 @@ struct nfs_write_data {
 /*
  * Local function declarations
  */
-static struct nfs_page * nfs_update_request(struct file*, struct page *page,
+static struct nfs_page * nfs_update_request(struct file*, struct inode *,
+                                           struct page *,
                                            unsigned int, unsigned int);
 static void    nfs_strategy(struct inode *inode);
 static void    nfs_writeback_done(struct rpc_task *);
@@ -167,11 +168,11 @@ nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
  * Offset is the data offset within the page.
  */
 static int
-nfs_writepage_sync(struct file *file, struct page *page,
+nfs_writepage_sync(struct file *file, struct inode *inode, struct page *page,
                   unsigned int offset, unsigned int count)
 {
        struct dentry   *dentry = file->f_dentry;
-       struct inode    *inode = dentry->d_inode;
+       struct rpc_cred *cred = nfs_file_cred(file);
        loff_t          base;
        unsigned int    wsize = NFS_SERVER(inode)->wsize;
        int             result, refresh = 0, written = 0, flags;
@@ -193,7 +194,7 @@ nfs_writepage_sync(struct file *file, struct page *page,
                if (count < wsize && !IS_SWAPFILE(inode))
                        wsize = count;
 
-               result = NFS_PROTO(inode)->write(file, &fattr, flags,
+               result = NFS_PROTO(inode)->write(inode, cred, &fattr, flags,
                                                 base, wsize, buffer, &verf);
                nfs_write_attributes(inode, &fattr);
 
@@ -229,18 +230,18 @@ io_error:
 }
 
 static int
-nfs_writepage_async(struct file *file, struct page *page,
+nfs_writepage_async(struct file *file, struct inode *inode, struct page *page,
                    unsigned int offset, unsigned int count)
 {
        struct nfs_page *req;
        int             status;
 
-       req = nfs_update_request(file, page, offset, count);
+       req = nfs_update_request(file, inode, page, offset, count);
        status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
        if (status < 0)
                goto out;
        nfs_release_request(req);
-       nfs_strategy(file->f_dentry->d_inode);
+       nfs_strategy(inode);
  out:
        return status;
 }
@@ -251,11 +252,25 @@ nfs_writepage_async(struct file *file, struct page *page,
 int
 nfs_writepage(struct file *file, struct page *page)
 {
-       struct inode *inode = file->f_dentry->d_inode;
-       unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+       struct inode *inode;
+       unsigned long end_index;
        unsigned offset = PAGE_CACHE_SIZE;
        int err;
 
+       if (!file) {
+               struct address_space *mapping = page->mapping;
+               if (!mapping)
+                       BUG();
+               inode = (struct inode *)mapping->host;
+       } else
+               inode = file->f_dentry->d_inode;
+       if (!inode)
+               BUG();
+       end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+
+       /* Ensure we've flushed out any previous writes */
+       nfs_wb_page(inode,page);
+
        /* easy case */
        if (page->index < end_index)
                goto do_it;
@@ -266,11 +281,11 @@ nfs_writepage(struct file *file, struct page *page)
                return -EIO;
 do_it:
        if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
-               err = nfs_writepage_async(file, page, 0, offset);
+               err = nfs_writepage_async(file, inode, page, 0, offset);
                if (err >= 0)
                        goto out_ok;
        }
-       err = nfs_writepage_sync(file, page, 0, offset); 
+       err = nfs_writepage_sync(file, inode, page, 0, offset); 
        if ( err == offset)
                goto out_ok;
        return err; 
@@ -315,6 +330,8 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
                return;
        if (!NFS_WBACK_BUSY(req))
                printk(KERN_ERR "NFS: unlocked request attempted hashed!\n");
+       if (list_empty(&inode->u.nfs_i.writeback))
+               atomic_inc(&inode->i_count);
        inode->u.nfs_i.npages++;
        list_add(&req->wb_hash, &inode->u.nfs_i.writeback);
        req->wb_count++;
@@ -334,12 +351,14 @@ nfs_inode_remove_request(struct nfs_page *req)
        }
        if (!NFS_WBACK_BUSY(req))
                printk(KERN_ERR "NFS: unlocked request attempted unhashed!\n");
-       inode = req->wb_dentry->d_inode;
+       inode = req->wb_inode;
        list_del(&req->wb_hash);
        INIT_LIST_HEAD(&req->wb_hash);
        inode->u.nfs_i.npages--;
        if ((inode->u.nfs_i.npages == 0) != list_empty(&inode->u.nfs_i.writeback))
                printk(KERN_ERR "NFS: desynchronized value of nfs_i.npages.\n");
+       if (list_empty(&inode->u.nfs_i.writeback))
+               iput(inode);
        if (!nfs_have_writebacks(inode) && !nfs_have_read(inode))
                inode_remove_flushd(inode);
        spin_unlock(&nfs_wreq_lock);
@@ -422,7 +441,7 @@ void nfs_list_remove_request(struct nfs_page *req)
 static inline void
 nfs_mark_request_dirty(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_dentry->d_inode;
+       struct inode *inode = req->wb_inode;
 
        spin_lock(&nfs_wreq_lock);
        if (list_empty(&req->wb_list)) {
@@ -443,7 +462,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
 static inline int
 nfs_dirty_request(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_dentry->d_inode;
+       struct inode *inode = req->wb_inode;
        return !list_empty(&req->wb_list) && req->wb_list_head == &inode->u.nfs_i.dirty;
 }
 
@@ -454,7 +473,7 @@ nfs_dirty_request(struct nfs_page *req)
 static inline void
 nfs_mark_request_commit(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_dentry->d_inode;
+       struct inode *inode = req->wb_inode;
 
        spin_lock(&nfs_wreq_lock);
        if (list_empty(&req->wb_list)) {
@@ -477,11 +496,10 @@ nfs_mark_request_commit(struct nfs_page *req)
  * when we reach the hard limit on the number of dirty pages.
  * It should be safe to sleep here.
  */
-struct nfs_page *nfs_create_request(struct file *file, struct page *page,
+struct nfs_page *nfs_create_request(struct file *file, struct inode *inode,
+                                   struct page *page,
                                    unsigned int offset, unsigned int count)
 {
-       struct dentry           *dentry = file->f_dentry;
-       struct inode            *inode = dentry->d_inode;
        struct nfs_reqlist      *cache = NFS_REQUESTLIST(inode);
        struct nfs_page         *req = NULL;
        long                    timeout;
@@ -533,9 +551,15 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page,
        req->wb_offset  = offset;
        req->wb_bytes   = count;
        req->wb_file    = file;
-       get_file(file);
-       req->wb_dentry  = dentry;
-       req->wb_cred    = nfs_file_cred(file);
+
+       /* If we have a struct file, use its cached credentials
+        * else cache the current process' credentials. */
+       if (file) {
+               get_file(file);
+               req->wb_cred    = nfs_file_cred(file);
+       } else
+               req->wb_cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+       req->wb_inode   = inode;
        req->wb_count   = 1;
 
        /* register request's existence */
@@ -554,7 +578,7 @@ struct nfs_page *nfs_create_request(struct file *file, struct page *page,
 void
 nfs_release_request(struct nfs_page *req)
 {
-       struct inode            *inode = req->wb_dentry->d_inode;
+       struct inode            *inode = req->wb_inode;
        struct nfs_reqlist      *cache = NFS_REQUESTLIST(inode);
        struct page             *page = req->wb_page;
 
@@ -576,7 +600,11 @@ nfs_release_request(struct nfs_page *req)
        if (NFS_WBACK_BUSY(req))
                printk(KERN_ERR "NFS: Request released while still locked!\n");
 
-       fput(req->wb_file);
+       /* Release struct file or cached credential */
+       if (req->wb_file)
+               fput(req->wb_file);
+       else
+               rpcauth_releasecred(NFS_CLIENT(inode)->cl_auth, req->wb_cred);
        page_cache_release(page);
        nfs_page_free(req);
        /* wake up anyone waiting to allocate a request */
@@ -599,7 +627,7 @@ nfs_release_request(struct nfs_page *req)
 static int
 nfs_wait_on_request(struct nfs_page *req)
 {
-       struct inode    *inode = req->wb_dentry->d_inode;
+       struct inode    *inode = req->wb_inode;
         struct rpc_clnt        *clnt = NFS_CLIENT(inode);
 
        if (!NFS_WBACK_BUSY(req))
@@ -814,10 +842,9 @@ int nfs_coalesce_requests(struct list_head *src, struct list_head *dst, unsigned
  * Note: Should always be called with the Page Lock held!
  */
 static struct nfs_page *
-nfs_update_request(struct file* file, struct page *page,
+nfs_update_request(struct file* file, struct inode *inode, struct page *page,
                   unsigned int offset, unsigned int bytes)
 {
-       struct inode            *inode = file->f_dentry->d_inode;
        struct nfs_page         *req, *new = NULL;
        unsigned long           rqend, end;
 
@@ -857,7 +884,7 @@ nfs_update_request(struct file* file, struct page *page,
                 */
                if (inode->u.nfs_i.npages >= MAX_REQUEST_SOFT)
                        nfs_wb_file(inode, file);
-               new = nfs_create_request(file, page, offset, bytes);
+               new = nfs_create_request(file, inode, page, offset, bytes);
                if (!new)
                        return ERR_PTR(-ENOMEM);
                /* If the region is locked, adjust the timeout */
@@ -995,7 +1022,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
         * page synchronously.
         */
        if (NFS_SERVER(inode)->wsize < PAGE_SIZE)
-               return nfs_writepage_sync(file, page, offset, count);
+               return nfs_writepage_sync(file, inode, page, offset, count);
 
        /*
         * Try to find an NFS request corresponding to this page
@@ -1004,7 +1031,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsign
         * it out now.
         */
        do {
-               req = nfs_update_request(file, page, offset, count);
+               req = nfs_update_request(file, inode, page, offset, count);
                status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
                if (status != -EBUSY)
                        break;
@@ -1068,9 +1095,9 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
                data->args.nriov++;
        }
        req = nfs_list_entry(data->pages.next);
-       data->dentry = req->wb_dentry;
+       data->inode = req->wb_inode;
        data->cred = req->wb_cred;
-       data->args.fh     = NFS_FH(req->wb_dentry);
+       data->args.fh     = NFS_FH(req->wb_inode);
        data->args.offset = page_offset(req->wb_page) + req->wb_offset;
        data->args.count  = count;
        data->res.fattr   = &data->fattr;
@@ -1088,9 +1115,8 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
  * that has been written but not committed.
  */
 static int
-nfs_flush_one(struct list_head *head, struct dentry *dentry, int how)
+nfs_flush_one(struct list_head *head, struct inode *inode, int how)
 {
-       struct inode            *inode = dentry->d_inode;
        struct rpc_clnt         *clnt = NFS_CLIENT(inode);
        struct nfs_write_data   *data;
        struct rpc_task         *task;
@@ -1134,10 +1160,10 @@ nfs_flush_one(struct list_head *head, struct dentry *dentry, int how)
        msg.rpc_resp = &data->res;
        msg.rpc_cred = data->cred;
 
-       dprintk("NFS: %4d initiated write call (req %s/%s count %d nriov %d)\n",
+       dprintk("NFS: %4d initiated write call (req %x/%Ld count %d nriov %d)\n",
                task->tk_pid, 
-               dentry->d_parent->d_name.name,
-               dentry->d_name.name,
+               inode->i_dev,
+               (long long)NFS_FILEID(inode),
                data->args.count, data->args.nriov);
 
        rpc_clnt_sigmask(clnt, &oldset);
@@ -1167,7 +1193,7 @@ nfs_flush_list(struct inode *inode, struct list_head *head, int how)
        while (!list_empty(head)) {
                pages += nfs_coalesce_requests(head, &one_request, wpages);
                req = nfs_list_entry(one_request.next);
-               error = nfs_flush_one(&one_request, req->wb_dentry, how);
+               error = nfs_flush_one(&one_request, req->wb_inode, how);
                if (error < 0)
                        break;
        }
@@ -1193,8 +1219,7 @@ nfs_writeback_done(struct rpc_task *task)
        struct nfs_write_data   *data = (struct nfs_write_data *) task->tk_calldata;
        struct nfs_writeargs    *argp = &data->args;
        struct nfs_writeres     *resp = &data->res;
-       struct dentry           *dentry = data->dentry;
-       struct inode            *inode = dentry->d_inode;
+       struct inode            *inode = data->inode;
        struct nfs_page         *req;
        struct page             *page;
 
@@ -1249,9 +1274,9 @@ nfs_writeback_done(struct rpc_task *task)
 
                kunmap(page);
 
-               dprintk("NFS: write (%s/%s %d@%Ld)",
-                       req->wb_dentry->d_parent->d_name.name,
-                       req->wb_dentry->d_name.name,
+               dprintk("NFS: write (%x/%Ld %d@%Ld)",
+                       req->wb_inode->i_dev,
+                       (long long)NFS_FILEID(req->wb_inode),
                        req->wb_bytes,
                        (long long)(page_offset(page) + req->wb_offset));
 
@@ -1292,7 +1317,6 @@ static void
 nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
 {
        struct nfs_page         *first, *last;
-       struct dentry           *dentry;
        struct inode            *inode;
        loff_t                  start, end, len;
 
@@ -1303,8 +1327,7 @@ nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
        INIT_LIST_HEAD(head);
        first = nfs_list_entry(data->pages.next);
        last = nfs_list_entry(data->pages.prev);
-       dentry = first->wb_dentry;
-       inode = dentry->d_inode;
+       inode = first->wb_inode;
 
        /*
         * Determine the offset range of requests in the COMMIT call.
@@ -1317,9 +1340,9 @@ nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
        if (end >= inode->i_size || len < 0 || len > (~((u32)0) >> 1))
                len = 0;
 
-       data->dentry      = dentry;
+       data->inode       = inode;
        data->cred        = first->wb_cred;
-       data->args.fh     = NFS_FH(dentry);
+       data->args.fh     = NFS_FH(inode);
        data->args.offset = start;
        data->res.count   = data->args.count = (u32)len;
        data->res.fattr   = &data->fattr;
@@ -1352,7 +1375,7 @@ nfs_commit_list(struct list_head *head, int how)
        /* Set up the argument struct */
        nfs_commit_rpcsetup(head, data);
        req = nfs_list_entry(data->pages.next);
-       clnt = NFS_CLIENT(req->wb_dentry->d_inode);
+       clnt = NFS_CLIENT(req->wb_inode);
 
        rpc_init_task(task, clnt, nfs_commit_done, flags);
        task->tk_calldata = data;
@@ -1389,8 +1412,7 @@ nfs_commit_done(struct rpc_task *task)
        struct nfs_write_data   *data = (struct nfs_write_data *)task->tk_calldata;
        struct nfs_writeres     *resp = &data->res;
        struct nfs_page         *req;
-       struct dentry           *dentry = data->dentry;
-       struct inode            *inode = dentry->d_inode;
+       struct inode            *inode = data->inode;
 
         dprintk("NFS: %4d nfs_commit_done (status %d)\n",
                                 task->tk_pid, task->tk_status);
@@ -1400,9 +1422,9 @@ nfs_commit_done(struct rpc_task *task)
                req = nfs_list_entry(data->pages.next);
                nfs_list_remove_request(req);
 
-               dprintk("NFS: commit (%s/%s %d@%Ld)",
-                       req->wb_dentry->d_parent->d_name.name,
-                       req->wb_dentry->d_name.name,
+               dprintk("NFS: commit (%x/%Ld %d@%Ld)",
+                       req->wb_inode->i_dev,
+                       (long long)NFS_FILEID(req->wb_inode),
                        req->wb_bytes,
                        (long long)(page_offset(req->wb_page) + req->wb_offset));
                if (task->tk_status < 0) {
index 49d2160a62c2fddef4c5b979fe6b2cb821a00624..c18a5f01c1dea5c7ad57c217b9b3ac6d1d33f23c 100644 (file)
@@ -557,7 +557,8 @@ ntfs_bmap(struct inode *ino,int block)
 #endif
 
 /* It's fscking broken. */
-
+/* FIXME: [bm]map code is disabled until ntfs_get_block gets sorted! */
+/*
 static int ntfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
 {
        BUG();
@@ -573,6 +574,7 @@ static struct file_operations ntfs_file_operations = {
 };
 
 static struct inode_operations ntfs_inode_operations;
+*/
 
 static struct file_operations ntfs_dir_operations = {
        read:           generic_read_dir,
@@ -587,6 +589,7 @@ static struct inode_operations ntfs_dir_inode_operations = {
 #endif
 };
 
+/*
 static int ntfs_writepage(struct file *file, struct page *page)
 {
        return block_write_full_page(page,ntfs_get_block);
@@ -612,6 +615,8 @@ struct address_space_operations ntfs_aops = {
        commit_write: generic_commit_write,
        bmap: _ntfs_bmap
 };
+*/
+
 /* ntfs_read_inode is called by the Virtual File System (the kernel layer that
  * deals with filesystems) when iget is called requesting an inode not already
  * present in the inode table. Typically filesystems have separate
@@ -664,7 +669,10 @@ static void ntfs_read_inode(struct inode* inode)
        else
        {
                inode->i_size=data->size;
-               can_mmap=!data->resident && !data->compressed;
+               /* FIXME: once ntfs_get_block is implemented, uncomment the
+                * next line and remove the can_mmap = 0; */
+               /* can_mmap=!data->resident && !data->compressed;*/
+               can_mmap = 0;
        }
        /* get the file modification times from the standard information */
        si=ntfs_find_attr(ino,vol->at_standard_information,NULL);
@@ -687,12 +695,17 @@ static void ntfs_read_inode(struct inode* inode)
        }
        else
        {
-               if (can_mmap) {
+               /* As long as ntfs_get_block() is just a call to BUG() do not
+                * define any [bm]map ops or we get the BUG() whenever someone
+                * runs mc or mpg123 on an ntfs partition!
+                * FIXME: Uncomment the below code when ntfs_get_block is
+                * implemented. */
+               /* if (can_mmap) {
                        inode->i_op = &ntfs_inode_operations;
                        inode->i_fop = &ntfs_file_operations;
                        inode->i_mapping->a_ops = &ntfs_aops;
                        inode->u.ntfs_i.mmu_private = inode->i_size;
-               } else {
+               } else */ {
                        inode->i_op=&ntfs_inode_operations_nobmap;
                        inode->i_fop=&ntfs_file_operations_nommap;
                }
@@ -931,8 +944,7 @@ static int __init init_ntfs_fs(void)
        /* Comment this if you trust klogd. There are reasons not to trust it
         */
 #if defined(DEBUG) && !defined(MODULE)
-       extern int console_loglevel;
-       console_loglevel=15;
+       console_verbose();
 #endif
        printk(KERN_NOTICE "NTFS version " NTFS_VERSION "\n");
        SYSCTL(1);
index 649abd02d3519f36cae41713df9205986f9f6751..78e0f58c39b2e818afd0e3b24b72c65ab1e9a14c 100644 (file)
  * bit 0 is the LSB of addr; bit 64 is the LSB of (addr+1).
  */
 
-#define BITOPS_NO_BRANCH
-
-extern __inline__ void set_bit(unsigned long nr, volatile void * addr)
+extern __inline__ void
+set_bit(unsigned long nr, volatile void * addr)
 {
-#ifndef BITOPS_NO_BRANCH
-       unsigned long oldbit;
-#endif
        unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+       int *m = ((int *) addr) + (nr >> 5);
 
-#ifndef BITOPS_NO_BRANCH
-       __asm__ __volatile__(
-       "1:     ldl_l %0,%4\n"
-       "       and %0,%3,%2\n"
-       "       bne %2,2f\n"
-       "       xor %0,%3,%0\n"
-       "       stl_c %0,%1\n"
-       "       beq %0,3f\n"
-       "2:\n"
-       ".subsection 2\n"
-       "3:     br 1b\n"
-       ".previous"
-       :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
-       :"Ir" (1UL << (nr & 31)), "m" (*m));
-#else
        __asm__ __volatile__(
        "1:     ldl_l %0,%3\n"
        "       bis %0,%2,%0\n"
@@ -55,58 +36,28 @@ extern __inline__ void set_bit(unsigned long nr, volatile void * addr)
        ".previous"
        :"=&r" (temp), "=m" (*m)
        :"Ir" (1UL << (nr & 31)), "m" (*m));
-#endif
 }
 
 /*
  * WARNING: non atomic version.
  */
-extern __inline__ void __set_bit(unsigned long nr, volatile void * addr)
+extern __inline__ void
+__set_bit(unsigned long nr, volatile void * addr)
 {
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
-       /*
-        * Asm and C produces the same thing so let
-        * the compiler to do its good work.
-        */
-#if 0
-       int tmp;
+       int *m = ((int *) addr) + (nr >> 5);
 
-       __asm__ __volatile__(
-       "ldl %0,%3\n\t"
-       "bis %0,%2,%0\n\t"
-       "stl %0,%1"
-       : "=&r" (tmp), "=m" (*m)
-       : "Ir" (1UL << (nr & 31)), "m" (*m));
-#else
        *m |= 1UL << (nr & 31);
-#endif
 }
 
 #define smp_mb__before_clear_bit()     smp_mb()
 #define smp_mb__after_clear_bit()      smp_mb()
-extern __inline__ void clear_bit(unsigned long nr, volatile void * addr)
+
+extern __inline__ void
+clear_bit(unsigned long nr, volatile void * addr)
 {
-#ifndef BITOPS_NO_BRANCH
-       unsigned long oldbit;
-#endif
        unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+       int *m = ((int *) addr) + (nr >> 5);
 
-#ifndef BITOPS_NO_BRANCH
-       __asm__ __volatile__(
-       "1:     ldl_l %0,%4\n"
-       "       and %0,%3,%2\n"
-       "       beq %2,2f\n"
-       "       xor %0,%3,%0\n"
-       "       stl_c %0,%1\n"
-       "       beq %0,3f\n"
-       "2:\n"
-       ".subsection 2\n"
-       "3:     br 1b\n"
-       ".previous"
-       :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
-       :"Ir" (1UL << (nr & 31)), "m" (*m));
-#else
        __asm__ __volatile__(
        "1:     ldl_l %0,%3\n"
        "       and %0,%2,%0\n"
@@ -117,13 +68,13 @@ extern __inline__ void clear_bit(unsigned long nr, volatile void * addr)
        ".previous"
        :"=&r" (temp), "=m" (*m)
        :"Ir" (~(1UL << (nr & 31))), "m" (*m));
-#endif
 }
 
-extern __inline__ void change_bit(unsigned long nr, volatile void * addr)
+extern __inline__ void
+change_bit(unsigned long nr, volatile void * addr)
 {
        unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+       int *m = ((int *) addr) + (nr >> 5);
 
        __asm__ __volatile__(
        "1:     ldl_l %0,%3\n"
@@ -137,12 +88,12 @@ extern __inline__ void change_bit(unsigned long nr, volatile void * addr)
        :"Ir" (1UL << (nr & 31)), "m" (*m));
 }
 
-extern __inline__ int test_and_set_bit(unsigned long nr,
-                                      volatile void * addr)
+extern __inline__ int
+test_and_set_bit(unsigned long nr, volatile void *addr)
 {
        unsigned long oldbit;
        unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+       int *m = ((int *) addr) + (nr >> 5);
 
        __asm__ __volatile__(
        "1:     ldl_l %0,%4\n"
@@ -151,10 +102,10 @@ extern __inline__ int test_and_set_bit(unsigned long nr,
        "       xor %0,%3,%0\n"
        "       stl_c %0,%1\n"
        "       beq %0,3f\n"
+       "2:\n"
 #ifdef CONFIG_SMP
        "       mb\n"
 #endif
-       "2:\n"
        ".subsection 2\n"
        "3:     br 1b\n"
        ".previous"
@@ -167,32 +118,23 @@ extern __inline__ int test_and_set_bit(unsigned long nr,
 /*
  * WARNING: non atomic version.
  */
-extern __inline__ int __test_and_set_bit(unsigned long nr,
-                                        volatile void * addr)
+extern __inline__ int
+__test_and_set_bit(unsigned long nr, volatile void * addr)
 {
-       unsigned long oldbit;
-       unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
-
-       __asm__ __volatile__(
-       "       ldl %0,%4\n"
-       "       and %0,%3,%2\n"
-       "       bne %2,1f\n"
-       "       xor %0,%3,%0\n"
-       "       stl %0,%1\n"
-       "1:\n"
-       :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
-       :"Ir" (1UL << (nr & 31)), "m" (*m));
+       unsigned long mask = 1 << (nr & 0x1f);
+       int *m = ((int *) addr) + (nr >> 5);
+       int old = *m;
 
-       return oldbit != 0;
+       *m = old | mask;
+       return (old & mask) != 0;
 }
 
-extern __inline__ int test_and_clear_bit(unsigned long nr,
-                                        volatile void * addr)
+extern __inline__ int
+test_and_clear_bit(unsigned long nr, volatile void * addr)
 {
        unsigned long oldbit;
        unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+       int *m = ((int *) addr) + (nr >> 5);
 
        __asm__ __volatile__(
        "1:     ldl_l %0,%4\n"
@@ -201,10 +143,10 @@ extern __inline__ int test_and_clear_bit(unsigned long nr,
        "       xor %0,%3,%0\n"
        "       stl_c %0,%1\n"
        "       beq %0,3f\n"
+       "2:\n"
 #ifdef CONFIG_SMP
        "       mb\n"
 #endif
-       "2:\n"
        ".subsection 2\n"
        "3:     br 1b\n"
        ".previous"
@@ -217,32 +159,23 @@ extern __inline__ int test_and_clear_bit(unsigned long nr,
 /*
  * WARNING: non atomic version.
  */
-extern __inline__ int __test_and_clear_bit(unsigned long nr,
-                                          volatile void * addr)
+extern __inline__ int
+__test_and_clear_bit(unsigned long nr, volatile void * addr)
 {
-       unsigned long oldbit;
-       unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+       unsigned long mask = 1 << (nr & 0x1f);
+       int *m = ((int *) addr) + (nr >> 5);
+       int old = *m;
 
-       __asm__ __volatile__(
-       "       ldl %0,%4\n"
-       "       and %0,%3,%2\n"
-       "       beq %2,1f\n"
-       "       xor %0,%3,%0\n"
-       "       stl %0,%1\n"
-       "1:\n"
-       :"=&r" (temp), "=m" (*m), "=&r" (oldbit)
-       :"Ir" (1UL << (nr & 31)), "m" (*m));
-
-       return oldbit != 0;
+       *m = old & ~mask;
+       return (old & mask) != 0;
 }
 
-extern __inline__ int test_and_change_bit(unsigned long nr,
-                                         volatile void * addr)
+extern __inline__ int
+test_and_change_bit(unsigned long nr, volatile void * addr)
 {
        unsigned long oldbit;
        unsigned long temp;
-       unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
+       int *m = ((int *) addr) + (nr >> 5);
 
        __asm__ __volatile__(
        "1:     ldl_l %0,%4\n"
@@ -262,7 +195,8 @@ extern __inline__ int test_and_change_bit(unsigned long nr,
        return oldbit != 0;
 }
 
-extern __inline__ int test_bit(int nr, volatile void * addr)
+extern __inline__ int
+test_bit(int nr, volatile void * addr)
 {
        return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
 }
@@ -289,7 +223,7 @@ extern inline unsigned long ffz_b(unsigned long x)
 extern inline unsigned long ffz(unsigned long word)
 {
 #if defined(__alpha_cix__) && defined(__alpha_fix__)
-       /* Whee.  EV6 can calculate it directly.  */
+       /* Whee.  EV67 can calculate it directly.  */
        unsigned long result;
        __asm__("cttz %1,%0" : "=r"(result) : "r"(~word));
        return result;
@@ -325,7 +259,7 @@ extern inline int ffs(int word)
  */
 
 #if defined(__alpha_cix__) && defined(__alpha_fix__)
-/* Whee.  EV6 can calculate it directly.  */
+/* Whee.  EV67 can calculate it directly.  */
 extern __inline__ unsigned long hweight64(unsigned long w)
 {
        unsigned long result;
@@ -347,7 +281,8 @@ extern __inline__ unsigned long hweight64(unsigned long w)
 /*
  * Find next zero bit in a bitmap reasonably efficiently..
  */
-extern inline unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
+extern inline unsigned long
+find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
 {
        unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
        unsigned long result = offset & ~63UL;
index edc376a049b71c6a858291c5a51f380ca86471b1..91b55ea3e754108b07ccf64052e582923e373bb6 100644 (file)
@@ -3,6 +3,44 @@
 
 #include <asm/types.h>
 
+#ifdef __GNUC__
+
+static __inline __u32 __attribute__((__const)) __arch__swab32(__u32 x)
+{
+       /*
+        * Unfortunately, we can't use the 6 instruction sequence
+        * on ev6 since the latency of the UNPKBW is 3, which is
+        * pretty hard to hide.  Just in case a future implementation
+        * has a lower latency, here's the sequence (also by Mike Burrows)
+        *
+        * UNPKBW a0, v0       v0: 00AA00BB00CC00DD
+        * SLL v0, 24, a0      a0: BB00CC00DD000000
+        * BIS v0, a0, a0      a0: BBAACCBBDDCC00DD
+        * EXTWL a0, 6, v0     v0: 000000000000BBAA
+        * ZAP a0, 0xf3, a0    a0: 00000000DDCC0000
+        * ADDL a0, v0, v0     v0: ssssssssDDCCBBAA
+        */
+
+       __u64 t0, t1, t2, t3;
+
+       __asm__("inslh %1, 7, %0"       /* t0 : 0000000000AABBCC */
+               : "=r"(t0) : "r"(x));
+       __asm__("inswl %1, 3, %0"       /* t1 : 000000CCDD000000 */
+               : "=r"(t1) : "r"(x));
+
+       t1 |= t0;                       /* t1 : 000000CCDDAABBCC */
+       t2 = t1 >> 16;                  /* t2 : 0000000000CCDDAA */
+       t0 = t1 & 0xFF00FF00;           /* t0 : 00000000DD00BB00 */
+       t3 = t2 & 0x00FF00FF;           /* t3 : 0000000000CC00AA */
+       t1 = t0 + t3;                   /* t1 : ssssssssDDCCBBAA */
+
+       return t1;
+}
+
+#define __arch__swab32 __arch__swab32
+
+#endif /* __GNUC__ */
+
 #define __BYTEORDER_HAS_U64__
 
 #include <linux/byteorder/little_endian.h>
index b02a78594624cc3d3ade1c548379e8c048f5b3d0..acd1b9a03bdfde2d1bc8daba89cfab24456646c9 100644 (file)
@@ -131,17 +131,19 @@ rdfpcr(void)
        unsigned long tmp, ret;
 
 #if defined(__alpha_cix__) || defined(__alpha_fix__)
-       __asm__ ("ftoit $f0,%0\n\t"
-                "mf_fpcr $f0\n\t"
-                "ftoit $f0,%1\n\t"
-                "itoft %0,$f0"
-                : "=r"(tmp), "=r"(ret));
+       __asm__ __volatile__ (
+               "ftoit $f0,%0\n\t"
+               "mf_fpcr $f0\n\t"
+               "ftoit $f0,%1\n\t"
+               "itoft %0,$f0"
+               : "=r"(tmp), "=r"(ret));
 #else
-       __asm__ ("stt $f0,%0\n\t"
-                "mf_fpcr $f0\n\t"
-                "stt $f0,%1\n\t"
-                "ldt $f0,%0"
-                : "=m"(tmp), "=m"(ret));
+       __asm__ __volatile__ (
+               "stt $f0,%0\n\t"
+               "mf_fpcr $f0\n\t"
+               "stt $f0,%1\n\t"
+               "ldt $f0,%0"
+               : "=m"(tmp), "=m"(ret));
 #endif
 
        return ret;
@@ -153,11 +155,12 @@ wrfpcr(unsigned long val)
        unsigned long tmp;
 
 #if defined(__alpha_cix__) || defined(__alpha_fix__)
-       __asm__ __volatile__ ("ftoit $f0,%0\n\t"
-                "itoft %1,$f0\n\t"
-                "mt_fpcr $f0\n\t"
-                "itoft %0,$f0"
-                : "=&r"(tmp) : "r"(val));
+       __asm__ __volatile__ (
+               "ftoit $f0,%0\n\t"
+               "itoft %1,$f0\n\t"
+               "mt_fpcr $f0\n\t"
+               "itoft %0,$f0"
+               : "=&r"(tmp) : "r"(val));
 #else
        __asm__ __volatile__ (
                "stt $f0,%0\n\t"
index 54341fff11e9a5eae4707994d39982c3de0fcc14..b3f6e81412f179408c08ca06a12029ef269e0e91 100644 (file)
 #define _PAGE_FOW      0x0004  /* used for page protection (fault on write) */
 #define _PAGE_FOE      0x0008  /* used for page protection (fault on exec) */
 #define _PAGE_ASM      0x0010
+#if defined(CONFIG_ALPHA_EV6) && !defined(CONFIG_SMP)
+#define _PAGE_MBE      0x0080  /* MB disable bit for EV6.  */
+#else
+#define _PAGE_MBE      0x0000
+#endif
 #define _PAGE_KRE      0x0100  /* xxx - see below on the "accessed" bit */
 #define _PAGE_URE      0x0200  /* xxx */
 #define _PAGE_KWE      0x1000  /* used to do the dirty bit in software */
 #define _PFN_MASK      0xFFFFFFFF00000000
 
 #define _PAGE_TABLE    (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS)
-#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS)
+#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_MBE)
 
 /*
- * All the normal masks have the "page accessed" bits on, as any time they are used,
- * the page is accessed. They are cleared only by the page-out routines
+ * All the normal masks have the "page accessed" bits on, as any time they
+ * are used, the page is accessed.  They are cleared only by the page-out
+ * routines. 
  */
 #define PAGE_NONE      __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE)
 #define PAGE_SHARED    __pgprot(_PAGE_VALID | __ACCESS_BITS)
 #define PAGE_COPY      __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
 #define PAGE_READONLY  __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
-#define PAGE_KERNEL    __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
+#define PAGE_KERNEL    __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE | _PAGE_MBE)
 
-#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
+#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_MBE | (x))
 
 #define _PAGE_P(x) _PAGE_NORMAL((x) | (((x) & _PAGE_FOW)?0:_PAGE_FOW))
 #define _PAGE_S(x) _PAGE_NORMAL(x)
@@ -189,6 +195,7 @@ extern unsigned long __zero_page(void);
  * Conversion functions:  convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
+
 #define mk_pte(page, pgprot)                                           \
 ({                                                                     \
        pte_t pte;                                                      \
@@ -199,7 +206,7 @@ extern unsigned long __zero_page(void);
 })
 
 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
+{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | (pgprot_val(pgprot) & ~_PAGE_MBE); return pte; }
 
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
index 3860288ad10d454986d867e9ca6f2b9cfd361e57..9ccc2821c5d7c3afedbb4854b4202ad14495127e 100644 (file)
@@ -42,7 +42,7 @@ typedef struct {
 #include <asm/smp.h>
 
 extern unsigned char global_irq_holder;
-extern unsigned volatile int global_irq_lock;
+extern unsigned volatile long global_irq_lock; /* long for set_bit -RR */
 
 static inline int irqs_running (void)
 {
index 8272b8f29a54024508436e1c26cd8c548872aeb9..8bf9bd75c53aa92a106dfd744bed8a3592e810a7 100644 (file)
@@ -82,8 +82,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #ifndef __ASSEMBLY__
 
-extern int console_loglevel;
-
 /*
  * Tell the user there is some problem. Beep too, so we can
  * see^H^H^Hhear bugs in early bootup as well!
index 7c1a4d1096f8cee7612309b09f1f2c3fe10d6211..1dabc1bdfeab8735a883392b3da5357a32f02c13 100644 (file)
@@ -49,7 +49,7 @@ typedef struct {
 #include <asm/smp.h>
 
 extern unsigned int global_irq_holder;
-extern volatile unsigned int global_irq_lock;
+extern volatile unsigned long global_irq_lock;
 
 static inline int irqs_running (void)
 {
index aa406533f2b6f8fb7f96125cfd1ab869379ebee8..53d486ef13a2dd4b3d3f69d6d3e0b3153a72bc5f 100644 (file)
@@ -76,8 +76,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #ifndef __ASSEMBLY__
 
-extern int console_loglevel;
-
 /*
  * Tell the user there is some problem.
  */
index 7457cd114baff6b47b4f0980f3b609f2850f7c44..d18b71dc73578f4cbf97941e5bcb4c50a27a6b48 100644 (file)
@@ -207,7 +207,7 @@ typedef struct _agp_file_private {
        struct _agp_file_private *next;
        struct _agp_file_private *prev;
        pid_t my_pid;
-       u32 access_flags;
+       long access_flags;      /* long req'd for set_bit --RR */
 } agp_file_private;
 
 struct agp_front_data {
index 847ae567ed1e8d9d0688d1883416d8269c1bdde3..dd9fdcfaf910bfb02fd3e5a9094529eac82b7dfc 100644 (file)
@@ -552,7 +552,7 @@ extern int ext2_sync_file (struct file *, struct dentry *, int);
 extern int ext2_fsync_inode (struct inode *, int);
 
 /* ialloc.c */
-extern struct inode * ext2_new_inode (const struct inode *, int, int *);
+extern struct inode * ext2_new_inode (const struct inode *, int);
 extern void ext2_free_inode (struct inode *);
 extern unsigned long ext2_count_free_inodes (struct super_block *);
 extern void ext2_check_inodes_bitmap (struct super_block *);
index ff0098c64d08576e305bef1df66d90f166fc5874..869716d7bf9d029d3c83697fd1c735c1f25ea825 100644 (file)
@@ -1065,6 +1065,7 @@ extern void sync_supers(kdev_t);
 extern int bmap(struct inode *, int);
 extern int notify_change(struct dentry *, struct iattr *);
 extern int permission(struct inode *, int);
+extern int vfs_permission(struct inode *, int);
 extern int get_write_access(struct inode *);
 extern int deny_write_access(struct file *);
 static inline void put_write_access(struct inode * inode)
index 4e1b281be11e14e4b8d2050905ae02f3c6cb8efb..ee3e8906c5d6e26efd2ba2fab2423256f9935e9b 100644 (file)
@@ -69,6 +69,19 @@ extern int session_of_pgrp(int pgrp);
 asmlinkage int printk(const char * fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
 
+extern int console_loglevel;
+
+static inline void console_silent(void)
+{
+       console_loglevel = 0;
+}
+
+static inline void console_verbose(void)
+{
+       if (console_loglevel)
+               console_loglevel = 15;
+}
+
 #if DEBUG
 #define pr_debug(fmt,arg...) \
        printk(KERN_DEBUG fmt,##arg)
index c8bdd1cd7e30d151563bfd11b10059f09558ba4e..4ce69eee899ae35a03000fade7bc2250e0749123 100644 (file)
@@ -91,8 +91,9 @@ struct cfi_private {
                                  must be of the same type. */
        int numchips;
        unsigned long chipshift; /* Because they're of the same type */
-       struct flchip chips[0];  /* per-chip data structure for each chip */
        const char *im_name;     /* inter_module name for cmdset_setup */
+       struct flchip chips[0];  /* per-chip data structure for each chip */
+       /* do not add extra fields after "chips" */
 };
 
 #define MAX_CFI_CHIPS 8 /* Entirely arbitrary to avoid realloc() */
index 05c506516953b0d2890b06be25bd793e408c68a9..144eb922a76eaf4004f892b243e73dc7e59324f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: pmc551.h,v 1.2 2000/03/31 14:40:42 dwmw2 Exp $
+ * $Id: pmc551.h,v 1.3 2000/10/30 20:03:23 major Exp $
  *
  * PMC551 PCI Mezzanine Ram Device
  *
@@ -17,6 +17,9 @@
 
 #include <linux/mtd/mtd.h>
 
+#define PMC551_VERSION "$Id: pmc551.h,v 1.3 2000/10/30 20:03:23 major Exp $\n"\
+       "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n"
+
 /*
  * Our personal and private information
  */
@@ -54,68 +57,25 @@ static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_cha
 #define PMC551_PCI_MEM_MAP1    0x54
 #define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK       0x3ff00000
 #define PMC551_PCI_MEM_MAP_APERTURE_MASK       0x000000f0
-#define PMC551_PCI_MEM_MAP_1MB_APERTURE                0x00000000
-#define PMC551_PCI_MEM_MAP_2MB_APERTURE                0x00000010
-#define PMC551_PCI_MEM_MAP_REG_EN              0x00000002
-#define PMC551_PCI_MEM_MAP_ENABLE              0x00000001
-
-#define PMC551_SDRAM_MA                0x60
-#define PMC551_SDRAM_CMD       0x62
-#define PMC551_DRAM_CFG                0x64
-
-#define PMC551_DRAM_BLK0       0x68
-#define PMC551_DRAM_BLK1       0x6c
-#define PMC551_DRAM_BLK2       0x70
-#define PMC551_DRAM_BLK3       0x74
-#define PMC551_DRAM_BLK_GET_SIZE(x) ((512 * 1024) << ((x >> 4) & 0xf))
-#define PMC551_DRAM_BLK_SET_COL_MUX(x,v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
-#define PMC551_DRAM_BLK_SET_ROW_MUX(x,v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
-
-
-/* Use a 1MB apeture into the card. */
-#define PMC551_APERTURE_SIZE   0x00100000
-#define PMC551_ADDR_HIGH_MASK  0x3ff00000
-#define PMC551_ADDR_LOW_MASK   0x000fffff
-#define PMC551_APERTURE_VAL    PMC551_PCI_MEM_MAP_1MB_APERTURE
-/*
- * Define the PCI ID's if the kernel doesn't define them for us
- */
-#ifndef PCI_VENDOR_ID_V3_SEMI
-#define PCI_VENDOR_ID_V3_SEMI             0x11b0
-#endif
-
-#ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC
-#define PCI_DEVICE_ID_V3_SEMI_V370PDC     0x0200  
-#endif
-
-
-#define PMC551_PCI_MEM_MAP0    0x50
-#define PMC551_PCI_MEM_MAP1    0x54
-#define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK       0x3ff00000
-#define PMC551_PCI_MEM_MAP_APERTURE_MASK       0x000000f0
-#define PMC551_PCI_MEM_MAP_1MB_APERTURE                0x00000000
-#define PMC551_PCI_MEM_MAP_2MB_APERTURE                0x00000010
 #define PMC551_PCI_MEM_MAP_REG_EN              0x00000002
 #define PMC551_PCI_MEM_MAP_ENABLE              0x00000001
 
 #define PMC551_SDRAM_MA                0x60
 #define PMC551_SDRAM_CMD       0x62
 #define PMC551_DRAM_CFG                0x64
+#define PMC551_SYS_CTRL_REG    0x78
 
 #define PMC551_DRAM_BLK0       0x68
 #define PMC551_DRAM_BLK1       0x6c
 #define PMC551_DRAM_BLK2       0x70
 #define PMC551_DRAM_BLK3       0x74
-#define PMC551_DRAM_BLK_GET_SIZE(x) ((512 * 1024) << ((x >> 4) & 0xf))
+#define PMC551_DRAM_BLK_GET_SIZE(x) (524288<<((x>>4)&0x0f))
 #define PMC551_DRAM_BLK_SET_COL_MUX(x,v) (((x) & ~0x00007000) | (((v) & 0x7) << 12))
 #define PMC551_DRAM_BLK_SET_ROW_MUX(x,v) (((x) & ~0x00000f00) | (((v) & 0xf) << 8))
 
 
-/* Use a 1MB apeture into the card. */
-#define PMC551_APERTURE_SIZE   0x00100000
 #define PMC551_ADDR_HIGH_MASK  0x3ff00000
 #define PMC551_ADDR_LOW_MASK   0x000fffff
-#define PMC551_APERTURE_VAL    PMC551_PCI_MEM_MAP_1MB_APERTURE
 
 #endif /* __MTD_PMC551_H__ */
 
index b61722b1527f48702247259b46f77c34b18d80e5..26734dce1f755f504a640eafceec6c172d087348 100644 (file)
@@ -63,8 +63,7 @@
  */
 #define NFS_SUPER_MAGIC                        0x6969
 
-#define NFS_FH(dentry)                 ((struct nfs_fh *) ((dentry)->d_fsdata))
-#define NFS_DSERVER(dentry)            (&(dentry)->d_sb->u.nfs_sb.s_server)
+#define NFS_FH(inode)                  (&(inode)->u.nfs_i.fh)
 #define NFS_SERVER(inode)              (&(inode)->i_sb->u.nfs_sb.s_server)
 #define NFS_CLIENT(inode)              (NFS_SERVER(inode)->client)
 #define NFS_PROTO(inode)               (NFS_SERVER(inode)->rpc_ops)
@@ -143,9 +142,10 @@ extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
                                struct nfs_fattr *);
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_revalidate(struct dentry *);
+extern int nfs_permission(struct inode *, int);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
-extern int __nfs_revalidate_inode(struct nfs_server *, struct dentry *);
+extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_notify_change(struct dentry *, struct iattr *);
 
 /*
@@ -264,12 +264,11 @@ extern int  nfs3_mount(struct sockaddr_in *, char *, struct nfs_fh *);
  * inline functions
  */
 static inline int
-nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
+nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
-       struct inode *inode = dentry->d_inode;
        if (time_before(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))
                return 0;
-       return __nfs_revalidate_inode(server, dentry);
+       return __nfs_revalidate_inode(server, inode);
 }
 
 static inline loff_t
index 2e10b196346a817300b9a6533846cbec6b322fb8..f14f3d8d9c8e38b6b45440f8d461d3b4f3658dcc 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/types.h>
 #include <linux/list.h>
+#include <linux/nfs.h>
 
 /*
  * nfs fs inode data in memory
@@ -14,6 +15,11 @@ struct nfs_inode_info {
        __u64 fsid;
        __u64 fileid;
 
+       /*
+        * NFS file handle
+        */
+       struct nfs_fh           fh;
+
        /*
         * Various flags
         */
@@ -72,6 +78,7 @@ struct nfs_inode_info {
 /*
  * Legal inode flag values
  */
+#define NFS_INO_STALE          0x0001          /* possible stale inode */
 #define NFS_INO_ADVISE_RDPLUS   0x0002          /* advise readdirplus */
 #define NFS_INO_REVALIDATING   0x0004          /* revalidating attrs */
 #define NFS_IS_SNAPSHOT                0x0010          /* a snapshot file */
index f6c35dc01d2f8acea7fc43ab81a93ba87711d235..2f37a4b1949138c8328746a1f0f904551e7dc3d8 100644 (file)
@@ -26,7 +26,7 @@ struct nfs_page {
                                wb_list,        /* Defines state of page: */
                                *wb_list_head;  /*      read/write/commit */
        struct file             *wb_file;
-       struct dentry           *wb_dentry;
+       struct inode            *wb_inode;
        struct rpc_cred         *wb_cred;
        struct page             *wb_page;       /* page to read in/write out */
        wait_queue_head_t       wb_wait;        /* wait queue */
@@ -41,6 +41,7 @@ struct nfs_page {
 #define NFS_WBACK_BUSY(req)    (test_bit(PG_BUSY,&(req)->wb_flags))
 
 extern struct nfs_page *nfs_create_request(struct file *file,
+                                           struct inode *inode,
                                            struct page *page,
                                            unsigned int offset,
                                            unsigned int count);
index 9863c06af0b9795388b989c31eb427ca3352c387..1ee4dd6167e175bc95d82267bc68d49cdcee36d7 100644 (file)
@@ -316,39 +316,41 @@ struct nfs_rpc_ops {
 
        int     (*getroot) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fattr *);
-       int     (*getattr) (struct dentry *, struct nfs_fattr *);
-       int     (*setattr) (struct dentry *, struct nfs_fattr *,
+       int     (*getattr) (struct inode *, struct nfs_fattr *);
+       int     (*setattr) (struct inode *, struct nfs_fattr *,
                            struct iattr *);
-       int     (*lookup)  (struct dentry *, struct qstr *,
+       int     (*lookup)  (struct inode *, struct qstr *,
                            struct nfs_fh *, struct nfs_fattr *);
-       int     (*access)  (struct dentry *, int , int);
-       int     (*readlink)(struct dentry *, void *, unsigned int);
-       int     (*read)    (struct file *, struct nfs_fattr *,
+       int     (*access)  (struct inode *, int , int);
+       int     (*readlink)(struct inode *, void *, unsigned int);
+       int     (*read)    (struct inode *, struct rpc_cred *,
+                           struct nfs_fattr *,
                            int, loff_t, unsigned int,
                            void *buffer, int *eofp);
-       int     (*write)   (struct file *, struct nfs_fattr *,
+       int     (*write)   (struct inode *, struct rpc_cred *,
+                           struct nfs_fattr *,
                            int, loff_t, unsigned int,
                            void *buffer, struct nfs_writeverf *verfp);
-       int     (*commit)  (struct dentry *, struct nfs_fattr *,
+       int     (*commit)  (struct inode *, struct nfs_fattr *,
                            unsigned long, unsigned int);
-       int     (*create)  (struct dentry *, struct qstr *, struct iattr *,
+       int     (*create)  (struct inode *, struct qstr *, struct iattr *,
                            int, struct nfs_fh *, struct nfs_fattr *);
-       int     (*remove)  (struct dentry *, struct qstr *);
+       int     (*remove)  (struct inode *, struct qstr *);
        int     (*unlink_setup)  (struct rpc_message *,
                            struct dentry *, struct qstr *);
        void    (*unlink_done) (struct dentry *, struct rpc_message *);
-       int     (*rename)  (struct dentry *, struct qstr *,
-                           struct dentry *, struct qstr *);
-       int     (*link)    (struct dentry *, struct dentry *, struct qstr *);
-       int     (*symlink) (struct dentry *, struct qstr *, struct qstr *,
+       int     (*rename)  (struct inode *, struct qstr *,
+                           struct inode *, struct qstr *);
+       int     (*link)    (struct inode *, struct inode *, struct qstr *);
+       int     (*symlink) (struct inode *, struct qstr *, struct qstr *,
                            struct iattr *, struct nfs_fh *,
                            struct nfs_fattr *);
-       int     (*mkdir)   (struct dentry *, struct qstr *, struct iattr *,
+       int     (*mkdir)   (struct inode *, struct qstr *, struct iattr *,
                            struct nfs_fh *, struct nfs_fattr *);
-       int     (*rmdir)   (struct dentry *, struct qstr *);
-       int     (*readdir) (struct file *, u64 cookie, void *, unsigned int,
-                           int);
-       int     (*mknod)   (struct dentry *, struct qstr *, struct iattr *,
+       int     (*rmdir)   (struct inode *, struct qstr *);
+       int     (*readdir) (struct inode *, struct rpc_cred *,
+                           u64, void *, unsigned int, int);
+       int     (*mknod)   (struct inode *, struct qstr *, struct iattr *,
                            dev_t, struct nfs_fh *, struct nfs_fattr *);
        int     (*statfs)  (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fsinfo *);
index 64aeef3891233e7e77b3f4c0d62b826aa3b44f23..6c82d1d77fa06f442a123ef7f4f61e947a20b1f1 100644 (file)
 #define PCI_DEVICE_ID_ELSA_MICROLINK   0x1000
 #define PCI_DEVICE_ID_ELSA_QS3000      0x3000
 
-#define PCI_VENDOR_ID_ELSA             0x1048
-#define PCI_DEVICE_ID_ELSA_MICROLINK   0x1000
-#define PCI_DEVICE_ID_ELSA_QS3000      0x3000
-
 #define PCI_VENDOR_ID_SGS              0x104a
 #define PCI_DEVICE_ID_SGS_2000         0x0008
 #define PCI_DEVICE_ID_SGS_1764         0x0009
index f2d0766ef7c8b058e1bc98384526062e31c151f6..c4e6eb3bd2ca90ad1f85c66e277e573fde2c9f58 100644 (file)
@@ -193,7 +193,7 @@ static inline void siginitset(sigset_t *set, unsigned long mask)
                memset(&set->sig[1], 0, sizeof(long)*(_NSIG_WORDS-1));
                break;
        case 2: set->sig[1] = 0;
-       case 1:
+       case 1: ;
        }
 }
 
@@ -205,7 +205,7 @@ static inline void siginitsetinv(sigset_t *set, unsigned long mask)
                memset(&set->sig[1], -1, sizeof(long)*(_NSIG_WORDS-1));
                break;
        case 2: set->sig[1] = -1;
-       case 1:
+       case 1: ;
        }
 }
 
index f933d2923ccc4e56dd6e314752ea7d905273a44f..d7d56607515e199a8032de084be96c6cac0d1469 100644 (file)
@@ -51,8 +51,8 @@
 extern int con3215_activate(void);
 #endif
 
-#ifdef CONFIG_MAC
-extern void nubus_init(void);
+#ifdef CONFIG_NUBUS
+#include <linux/nubus.h>
 #endif
 
 #ifdef CONFIG_ISAPNP
@@ -80,8 +80,6 @@ extern void nubus_init(void);
 extern char _stext, _etext;
 extern char *linux_banner;
 
-extern int console_loglevel;
-
 static int init(void *);
 
 extern void init_IRQ(void);
@@ -682,7 +680,7 @@ static void __init do_basic_setup(void)
 #ifdef CONFIG_DIO
        dio_init();
 #endif
-#ifdef CONFIG_MAC
+#ifdef CONFIG_NUBUS
        nubus_init();
 #endif
 #ifdef CONFIG_ISAPNP
index f1e18e3e8856ba6dba82fac1155c146fade55b71..195e9116c3f3cc262f256f97507571666041fffc 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1406,7 +1406,7 @@ static int shm_swapout(struct page * page, struct file *file)
         */
        page_cache_free(page);
 
-       return 1;               /* We might have slept */
+       return 0;
 }
 
 /*
index 3045d7ac60c97ccba89ed7e4e1d4bcfbf3b97991..c60bafe8cdd6fed16a7a661c849b8b203cad084d 100644 (file)
@@ -22,7 +22,7 @@ extern struct task_struct *child_reaper;
 
 int getrusage(struct task_struct *, int, struct rusage *);
 
-static void release(struct task_struct * p)
+static void release_task(struct task_struct * p)
 {
        if (p != current) {
 #ifdef CONFIG_SMP
@@ -31,15 +31,15 @@ static void release(struct task_struct * p)
                 * runqueue (active on some other CPU still)
                 */
                for (;;) {
-                       spin_lock_irq(&runqueue_lock);
+                       task_lock(p);
                        if (!p->has_cpu)
                                break;
-                       spin_unlock_irq(&runqueue_lock);
+                       task_unlock(p);
                        do {
                                barrier();
                        } while (p->has_cpu);
                }
-               spin_unlock_irq(&runqueue_lock);
+               task_unlock(p);
 #endif
                atomic_dec(&p->user->processes);
                free_uid(p->user);
@@ -550,7 +550,7 @@ repeat:
                                        do_notify_parent(p, SIGCHLD);
                                        write_unlock_irq(&tasklist_lock);
                                } else
-                                       release(p);
+                                       release_task(p);
                                goto end_wait4;
                        default:
                                continue;
index 100adaeb3687d70960abf391d45b5e7cf57cb6c4..9a41f0ecb49f5030e3cffdb48590d94d9dd05b26 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/kmod.h>
 #endif
 
-extern int console_loglevel;
 extern void set_device_ro(kdev_t dev,int flag);
 
 extern void *sys_call_table;
@@ -175,6 +174,7 @@ EXPORT_SYMBOL(invalidate_inode_pages);
 EXPORT_SYMBOL(truncate_inode_pages);
 EXPORT_SYMBOL(fsync_dev);
 EXPORT_SYMBOL(permission);
+EXPORT_SYMBOL(vfs_permission);
 EXPORT_SYMBOL(inode_setattr);
 EXPORT_SYMBOL(inode_change_ok);
 EXPORT_SYMBOL(write_inode_now);
index 119edeb8134bf1d3d32226b815b37808003d6e97..faf9a80e1002dab37ebdbb52fc0405037b509f9a 100644 (file)
@@ -197,7 +197,7 @@ static inline int preemption_goodness(struct task_struct * prev, struct task_str
 
 /*
  * This is ugly, but reschedule_idle() is very timing-critical.
- * We `are called with the runqueue spinlock held and we must
+ * We are called with the runqueue spinlock held and we must
  * not claim the tasklist_lock.
  */
 static FASTCALL(void reschedule_idle(struct task_struct * p));
@@ -272,8 +272,10 @@ send_now_idle:
        }
        tsk = target_tsk;
        if (tsk) {
-               if (oldest_idle != -1ULL)
+               if (oldest_idle != -1ULL) {
+                       best_cpu = tsk->processor;
                        goto send_now_idle;
+               }
                tsk->need_resched = 1;
                if (tsk->processor != this_cpu)
                        smp_send_reschedule(tsk->processor);
@@ -452,7 +454,7 @@ static inline void __schedule_tail(struct task_struct *prev)
                goto needs_resched;
 
 out_unlock:
-       task_unlock(prev);
+       task_unlock(prev);      /* Synchronise here with release_task() if prev is TASK_ZOMBIE */
        return;
 
        /*
index 5591ee2bcf4a6117cb35665282a4b386115b7da6..3fdf03c342c455e8bd5122249049bc579164217c 100644 (file)
@@ -41,7 +41,7 @@
 
 /* External variables not in a header file. */
 extern int panic_timeout;
-extern int console_loglevel, C_A_D;
+extern int C_A_D;
 extern int bdf_prm[], bdflush_min[], bdflush_max[];
 extern int sysctl_overcommit_memory;
 extern int max_threads;
index 5d205c3c8d4974bf5575fb3bf1d46a197ecb3d0b..e7f05ffd3fa62ed09f3705821e92ac9d58747f42 100644 (file)
@@ -1490,9 +1490,11 @@ static int filemap_write_page(struct file *file,
 extern void wakeup_bdflush(int);
 int filemap_swapout(struct page * page, struct file *file)
 {
-       filemap_write_page(file, page, 0);
+       int error;
+
+       error = filemap_write_page(file, page, 0);
        wakeup_bdflush(0);
-       return 1;       /* We might have slept */
+       return error;
 }
 
 /* Called with mm->page_table_lock held to protect against other
index 014d76ed89c17b38d10e56e701eb0032de226017..a3a2de242be47acb9dac60f949c820870a8978b7 100644 (file)
@@ -176,7 +176,7 @@ out_failed:
                UnlockPage(page);
                deactivate_page(page);
                page_cache_release(page);
-               return error;
+               return 1;       /* We released page_table_lock */
        }
 
        /*
@@ -620,6 +620,7 @@ dirty_page_rescan:
                        spin_unlock(&pagemap_lru_lock);
 
                        writepage(NULL, page);
+                       UnlockPage(page);
                        page_cache_release(page);
 
                        /* And re-start the thing.. */
index 173506c3d44911adb38317f9483dd83a982cc544..ca7433f9bf9b5dae685bbe4850d4b6e68fc18502 100644 (file)
@@ -417,7 +417,7 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask)
 }
 
 /**
- *     skb_copy        -       copy and expand sk_buff
+ *     skb_copy_expand -       copy and expand sk_buff
  *     @skb: buffer to copy
  *     @newheadroom: new free bytes at head
  *     @newtailroom: new free bytes at tail
index 7b73fb6426ca24a060468dc2f615471bf068243d..26cc633483e227f734c6fec56fba0f5ace7482ab 100644 (file)
@@ -135,7 +135,7 @@ static spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED;
 static ipx_interface *ipx_primary_net;
 static ipx_interface *ipx_internal_net;
 
-#define IPX_REFCNT_DEBUG
+#undef IPX_REFCNT_DEBUG
 #ifdef IPX_REFCNT_DEBUG
 atomic_t ipx_sock_nr;
 #endif
index d5aac6238bf2afb9bbb34280257f42f29203090b..eb4c33cc144f32a9c63e31b612899f1253f4edfb 100644 (file)
@@ -85,7 +85,7 @@
 $type_constant = "\\\%([-_\\w]+)";
 $type_func = "(\\w+)\\(\\)";
 $type_param = "\\\@(\\w+)";
-$type_struct = "\\\&((struct\\s*)?\\w+)";
+$type_struct = "\\\&((struct\\s*)?[_\\w]+)";
 $type_env = "(\\\$\\w+)";
 
 
@@ -326,7 +326,8 @@ sub output_sgml {
     print "<refnamediv>\n";
     print " <refname>".$args{'function'}."</refname>\n";
     print " <refpurpose>\n";
-    print "  ".$args{'purpose'}."\n";
+    print "  ";
+    output_highlight ($args{'purpose'});
     print " </refpurpose>\n";
     print "</refnamediv>\n";