## Automatically generated incremental diff
## From:   linux-2.5.3-pre5
## To:     linux-2.5.3-pre6
## Robot:  $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $

diff -urN linux-2.5.3-pre5/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- linux-2.5.3-pre5/Documentation/DocBook/Makefile	Mon Jan 28 13:46:14 2002
+++ linux/Documentation/DocBook/Makefile	Mon Jan 28 13:46:19 2002
@@ -1,7 +1,8 @@
 BOOKS	:= wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
 	   kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
 	   kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
-	   deviceiobook.sgml procfs-guide.sgml tulip-user.sgml
+	   deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
+	   writing_usb_driver.sgml
 
 PS	:=	$(patsubst %.sgml, %.ps, $(BOOKS))
 PDF	:=	$(patsubst %.sgml, %.pdf, $(BOOKS))
@@ -63,6 +64,9 @@
 		<via-audio.tmpl >via-audio.sgml
 
 tulip-user.sgml: tulip-user.tmpl
+	$(TOPDIR)/scripts/docgen <$< >$@
+
+writing_usb_driver.sgml: writing_usb_driver.tmpl
 	$(TOPDIR)/scripts/docgen <$< >$@
 
 sis900.sgml: sis900.tmpl $(TOPDIR)/drivers/net/sis900.c
diff -urN linux-2.5.3-pre5/Documentation/DocBook/writing_usb_driver.tmpl linux/Documentation/DocBook/writing_usb_driver.tmpl
--- linux-2.5.3-pre5/Documentation/DocBook/writing_usb_driver.tmpl	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/writing_usb_driver.tmpl	Mon Jan 28 13:46:19 2002
@@ -0,0 +1,469 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+
+<book id="USBDeviceDriver">
+ <bookinfo>
+  <title>Writing USB Device Drivers</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Greg</firstname>
+    <surname>Kroah-Hartman</surname>
+    <affiliation>
+     <address>
+      <email>greg@kroah.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2001-2002</year>
+   <holder>Greg Kroah-Hartman</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+
+   <para>
+     This documentation is based on an article published in 
+     Linux Journal Magazine, October 2001, Issue 90.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="intro">
+      <title>Introduction</title>
+  <para>
+      The Linux USB subsystem has grown from supporting only two different
+      types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
+      different types of devices in the 2.4 kernel. Linux currently supports
+      almost all USB class devices (standard types of devices like keyboards,
+      mice, modems, printers and speakers) and an ever-growing number of
+      vendor-specific devices (such as USB to serial converters, digital
+      cameras, Ethernet devices and MP3 players). For a full list of the
+      different USB devices currently supported, see Resources.
+  </para>
+  <para>
+      The remaining kinds of USB devices that do not have support on Linux are
+      almost all vendor-specific devices. Each vendor decides to implement a
+      custom protocol to talk to their device, so a custom driver usually needs
+      to be created. Some vendors are open with their USB protocols and help
+      with the creation of Linux drivers, while others do not publish them, and
+      developers are forced to reverse-engineer. See Resources for some links
+      to handy reverse-engineering tools.
+  </para>
+  <para>
+      Because each different protocol causes a new driver to be created, I have
+      written a generic USB driver skeleton, modeled after the pci-skeleton.c
+      file in the kernel source tree upon which many PCI network drivers have
+      been based. This USB skeleton can be found at drivers/usb/usb-skeleton.c
+      in the kernel source tree. In this article I will walk through the basics
+      of the skeleton driver, explaining the different pieces and what needs to
+      be done to customize it to your specific device.
+  </para>
+  </chapter>
+
+  <chapter id="basics">
+      <title>Linux USB Basics</title>
+  <para>
+      If you are going to write a Linux USB driver, please become familiar with
+      the USB protocol specification. It can be found, along with many other
+      useful documents, at the USB home page (see Resources). An excellent
+      introduction to the Linux USB subsystem can be found at the USB Working
+      Devices List (see Resources). It explains how the Linux USB subsystem is
+      structured and introduces the reader to the concept of USB urbs, which
+      are essential to USB drivers.
+  </para>
+  <para>
+      The first thing a Linux USB driver needs to do is register itself with
+      the Linux USB subsystem, giving it some information about which devices
+      the driver supports and which functions to call when a device supported
+      by the driver is inserted or removed from the system. All of this
+      information is passed to the USB subsystem in the usb_driver structure.
+      The skeleton driver declares a usb_driver as:
+  </para>
+  <programlisting>
+static struct usb_driver skel_driver = {
+        name:        "skeleton",
+        probe:       skel_probe,
+        disconnect:  skel_disconnect,
+        fops:        &amp;skel_fops,
+        minor:       USB_SKEL_MINOR_BASE,
+        id_table:    skel_table,
+};
+  </programlisting>
+  <para>
+      The variable name is a string that describes the driver. It is used in
+      informational messages printed to the system log. The probe and
+      disconnect function pointers are called when a device that matches the
+      information provided in the id_table variable is either seen or removed.
+  </para>
+  <para>
+      The fops and minor variables are optional. Most USB drivers hook into
+      another kernel subsystem, such as the SCSI, network or TTY subsystem.
+      These types of drivers register themselves with the other kernel
+      subsystem, and any user-space interactions are provided through that
+      interface. But for drivers that do not have a matching kernel subsystem,
+      such as MP3 players or scanners, a method of interacting with user space
+      is needed. The USB subsystem provides a way to register a minor device
+      number and a set of file_operations function pointers that enable this
+      user-space interaction. The skeleton driver needs this kind of interface,
+      so it provides a minor starting number and a pointer to its
+      file_operations functions.
+  </para>
+  <para>
+      The USB driver is then registered with a call to usb_register, usually in
+      the driver's init function, as shown here:
+  </para>
+  <programlisting>
+static int __init usb_skel_init(void)
+{
+        int result;
+
+        /* register this driver with the USB subsystem */
+        result = usb_register(&amp;skel_driver);
+        if (result &lt; 0) {
+                err(&quot;usb_register failed for the &quot;__FILE__ &quot;driver.&quot;
+                    &quot;Error number %d&quot;, result);
+                return -1;
+        }
+
+        return 0;
+}
+module_init(usb_skel_init);
+  </programlisting>
+  <para>
+      When the driver is unloaded from the system, it needs to unregister
+      itself with the USB subsystem. This is done with the usb_unregister
+      function:
+  </para>
+  <programlisting>
+static void __exit usb_skel_exit(void)
+{
+        /* deregister this driver with the USB subsystem */
+        usb_deregister(&amp;skel_driver);
+}
+module_exit(usb_skel_exit);
+  </programlisting>
+  <para>
+     To enable the linux-hotplug system to load the driver automatically when
+     the device is plugged in, you need to create a MODULE_DEVICE_TABLE. The
+     following code tells the hotplug scripts that this module supports a
+     single device with a specific vendor and product ID:
+  </para>
+  <programlisting>
+/* table of devices that work with this driver */
+static struct usb_device_id skel_table [] = {
+        { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
+        { }                      /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, skel_table);
+  </programlisting>
+  <para>
+     There are other macros that can be used in describing a usb_device_id for
+     drivers that support a whole class of USB drivers. See usb.h for more
+     information on this.
+  </para>
+  </chapter>
+
+  <chapter id="device">
+      <title>Device operation</title>
+  <para>
+     When a device is plugged into the USB bus that matches the device ID
+     pattern that your driver registered with the USB core, the probe function
+     is called. The usb_device structure, interface number and the interface ID
+     are passed to the function:
+  </para>
+  <programlisting>
+static void * skel_probe(struct usb_device *dev,
+unsigned int ifnum, const struct usb_device_id *id)
+  </programlisting>
+  <para>
+     The driver now needs to verify that this device is actually one that it
+     can accept. If not, or if any error occurs during initialization, a NULL
+     value is returned from the probe function. Otherwise a pointer to a
+     private data structure containing the driver's state for this device is
+     returned. That pointer is stored in the usb_device structure, and all
+     callbacks to the driver pass that pointer.
+  </para>
+  <para>
+     In the skeleton driver, we determine what end points are marked as bulk-in
+     and bulk-out. We create buffers to hold the data that will be sent and
+     received from the device, and a USB urb to write data to the device is
+     initialized. Also, we register the device with the devfs subsystem,
+     allowing users of devfs to access our device. That registration looks like
+     the following:
+  </para>
+  <programlisting>
+/* initialize the devfs node for this device and register it */
+sprintf(name, &quot;skel%d&quot;, skel->minor);
+skel->devfs = devfs_register (usb_devfs_handle,
+                              name,
+                              DEVFS_FL_DEFAULT,
+                              USB_MAJOR,
+                              USB_SKEL_MINOR_BASE + skel->minor,
+                              S_IFCHR | S_IRUSR | S_IWUSR |
+                              S_IRGRP | S_IWGRP | S_IROTH,
+                              &amp;skel_fops,
+                              NULL);
+  </programlisting>
+  <para>
+     If the devfs_register function fails, we do not care, as the devfs
+     subsystem will report this to the user.
+  </para>
+  <para>
+     Conversely, when the device is removed from the USB bus, the disconnect
+     function is called with the device pointer. The driver needs to clean any
+     private data that has been allocated at this time and to shut down any
+     pending urbs that are in the USB system. The driver also unregisters
+     itself from the devfs subsystem with the call:
+  </para>
+  <programlisting>
+/* remove our devfs node */
+devfs_unregister(skel->devfs);
+  </programlisting>
+  <para>
+     Now that the device is plugged into the system and the driver is bound to
+     the device, any of the functions in the file_operations structure that
+     were passed to the USB subsystem will be called from a user program trying
+     to talk to the device. The first function called will be open, as the
+     program tries to open the device for I/O. Within the skeleton driver's
+     open function we increment the driver's usage count if it is a module with
+     a call to MODULE_INC_USE_COUNT. With this macro call, if the driver is
+     compiled as a module, the driver cannot be unloaded until a corresponding
+     MODULE_DEC_USE_COUNT macro is called.  We also increment our private usage
+     count and save off a pointer to our internal structure in the file
+     structure. This is done so that future calls to file operations will
+     enable the driver to determine which device the user is addressing. All of
+     this is done with the following code:
+  </para>
+  <programlisting>
+/* increment our usage count for the module */
+MOD_INC_USE_COUNT;
+++skel->open_count;
+
+/* save our object in the file's private structure */
+file->private_data = skel;
+  </programlisting>
+  <para>
+     After the open function is called, the read and write functions are called
+     to receive and send data to the device. In the skel_write function, we
+     receive a pointer to some data that the user wants to send to the device
+     and the size of the data. The function determines how much data it can
+     send to the device based on the size of the write urb it has created (this
+     size depends on the size of the bulk out end point that the device has).
+     Then it copies the data from user space to kernel space, points the urb to
+     the data and submits the urb to the USB subsystem.  This can be shown in
+     he following code:
+  </para>
+  <programlisting>
+/* we can only write as much as 1 urb will hold */
+bytes_written = (count > skel->bulk_out_size) ? skel->bulk_out_size : count;
+
+/* copy the data from user space into our urb */
+copy_from_user(skel->write_urb->transfer_buffer, buffer, bytes_written);
+
+/* set up our urb */
+usb_fill_bulk_urb(skel->write_urb,
+                  skel->dev,
+                  usb_sndbulkpipe(skel->dev, skel->bulk_out_endpointAddr),
+                  skel->write_urb->transfer_buffer,
+                  bytes_written,
+                  skel_write_bulk_callback,
+                  skel);
+
+/* send the data out the bulk port */
+result = usb_submit_urb(skel->write_urb);
+if (result) {
+        err(&quot;Failed submitting write urb, error %d&quot;, result);
+}
+  </programlisting>
+  <para>
+     When the write urb is filled up with the proper information using the
+     FILL_BULK_URB function, we point the urb's completion callback to call our
+     own skel_write_bulk_callback function. This function is called when the
+     urb is finished by the USB subsystem. The callback function is called in
+     interrupt context, so caution must be taken not to do very much processing
+     at that time. Our implementation of skel_write_bulk_callback merely
+     reports if the urb was completed successfully or not and then returns.
+  </para>
+  <para>
+     The read function works a bit differently from the write function in that
+     we do not use an urb to transfer data from the device to the driver.
+     Instead we call the usb_bulk_msg function, which can be used to send or
+     receive data from a device without having to create urbs and handle
+     urb completion callback functions. We call the usb_bulk_msg function,
+     giving it a buffer into which to place any data received from the device
+     and a timeout value. If the timeout period expires without receiving any
+     data from the device, the function will fail and return an error message.
+     This can be shown with the following code:
+  </para>
+  <programlisting>
+/* do an immediate bulk read to get data from the device */
+retval = usb_bulk_msg (skel->dev,
+                       usb_rcvbulkpipe (skel->dev,
+                       skel->bulk_in_endpointAddr),
+                       skel->bulk_in_buffer,
+                       skel->bulk_in_size,
+                       &amp;count, HZ*10);
+/* if the read was successful, copy the data to user space */
+if (!retval) {
+        if (copy_to_user (buffer, skel->bulk_in_buffer, count))
+                retval = -EFAULT;
+        else
+                retval = count;
+}
+  </programlisting>
+  <para>
+     The usb_bulk_msg function can be very useful for doing single reads or
+     writes to a device; however, if you need to read or write constantly to a
+     device, it is recommended to set up your own urbs and submit them to the
+     USB subsystem.
+  </para>
+  <para>
+     When the user program releases the file handle that it has been using to
+     talk to the device, the release function in the driver is called.  In this
+     function we decrement the module usage count with a call to
+     MOD_DEC_USE_COUNT (to match our previous call to MOD_INC_USE_COUNT).  We
+     also determine if there are any other programs that are currently talking
+     to the device (a device may be opened by more than one program at one
+     time). If this is the last user of the device, then we shut down any
+     possible pending writes that might be currently occurring.  This is all
+     done with:
+  </para>
+  <programlisting>
+/* decrement our usage count for the device */
+--skel->open_count;
+if (skel->open_count &lt;= 0) {
+        /* shutdown any bulk writes that might be going on */
+        usb_unlink_urb (skel->write_urb);
+        skel->open_count = 0;
+}
+/* decrement our usage count for the module */
+MOD_DEC_USE_COUNT;
+  </programlisting>
+  <para>
+     One of the more difficult problems that USB drivers must be able to handle
+     smoothly is the fact that the USB device may be removed from the system at
+     any point in time, even if a program is currently talking to it. It needs
+     to be able to shut down any current reads and writes and notify the
+     user-space programs that the device is no longer there.  The following
+     code is an example of how to do this: </para>
+  <programlisting>
+/* if the device is not opened, then we clean right now */
+if (skel->open_count) {
+        minor_table[skel->minor] = NULL;
+        if (skel->bulk_in_buffer != NULL)
+                kfree (skel->bulk_in_buffer);
+        if (skel->bulk_out_buffer != NULL)
+                kfree (skel->bulk_out_buffer);
+        if (skel->write_urb != NULL)
+                usb_free_urb (skel->write_urb);
+        kfree (skel);
+} else {
+        skel->dev = NULL;
+        up (&amp;skel->sem);
+}
+  </programlisting>
+  <para>
+     If a program currently has an open handle to the device, we only null the
+     usb_device structure in our local structure, as it has now gone away. For
+     every read, write, release and other functions that expect a device to be
+     present, the driver first checks to see if this usb_device structure is
+     still present. If not, it releases that the device has disappeared, and a
+     -ENODEV error is returned to the user-space program.  When the release
+     function is eventually called, it determines if there is no usb_device
+     structure and if not, it does the cleanup that the skel_disconnect
+     function normally does if there are no open files on the device (see
+     Listing 5).
+  </para>
+  <programlisting>
+if (skel->dev == NULL) {
+        /* the device was unplugged before the file was released */
+        minor_table[skel->minor] = NULL;
+        if (skel->bulk_in_buffer != NULL)
+                kfree (skel->bulk_in_buffer);
+        if (skel->bulk_out_buffer != NULL)
+                kfree (skel->bulk_out_buffer);
+        if (skel->write_urb != NULL)
+                usb_free_urb (skel->write_urb);
+        kfree (skel);
+        goto exit;
+}
+  </programlisting>
+  </chapter>
+
+  <chapter id="iso">
+      <title>Isochronous Data</title>
+  <para>
+     This usb-skeleton driver does not have any examples of interrupt or
+     isochronous data being sent to or from the device. Interrupt data is sent
+     almost exactly as bulk data is, with a few minor exceptions.  Isochronous
+     data works differently with continuous streams of data being sent to or
+     from the device. The audio and video camera drivers are very good examples
+     of drivers that handle isochronous data and will be useful if you also
+     need to do this.
+  </para>
+  </chapter>
+  
+  <chapter id="Conclusion">
+      <title>Conclusion</title>
+  <para>
+     Writing Linux USB device drivers is not a difficult task as the
+     usb-skeleton driver shows. This driver, combined with the other current
+     USB drivers, should provide enough examples to help a beginning author
+     create a working driver in a minimal amount of time. The linux-usb-devel
+     mailing list archives also contain a lot of helpful information.
+  </para>
+  </chapter>
+
+  <chapter id="resources">
+      <title>Resources</title>
+  <para>
+     The Linux USB Project: <ulink url="http://www.linux-usb.org">http://www.linux-usb.org/</ulink>
+  </para>
+  <para>
+     Linux Hotplug Project: <ulink url="http://linux-hotplug.sourceforge.net">http://linux-hotplug.sourceforge.net/</ulink>
+  </para>
+  <para>
+     Linux USB Working Devices List: <ulink url="http://www.qbik.ch/usb/devices">http://www.qbik.ch/usb/devices/</ulink>
+  </para>
+  <para>
+     linux-usb-devel Mailing List Archives: <ulink url="http://marc.theaimsgroup.com/?l=linux-usb-devel">http://marc.theaimsgroup.com/?l=linux-usb-devel</ulink>
+  </para>
+  <para>
+     Programming Guide for Linux USB Device Drivers: <ulink url="http://usb.cs.tum.edu/usbdoc">http://usb.cs.tum.edu/usbdoc</ulink>
+  </para>
+  <para>
+     USB Home Page: <ulink url="http://www.usb.org">http://www.usb.org</ulink>
+  </para>
+  </chapter>
+
+</book>
diff -urN linux-2.5.3-pre5/Documentation/scsi-generic.txt linux/Documentation/scsi-generic.txt
--- linux-2.5.3-pre5/Documentation/scsi-generic.txt	Tue May  1 16:04:56 2001
+++ linux/Documentation/scsi-generic.txt	Mon Jan 28 13:46:19 2002
@@ -1,793 +1,101 @@
-            Notes on Linux's SG driver version 2.1.39
-            -----------------------------------------
-                                                        20010329
-
+            Notes on Linux SCSI Generic (sg) driver
+            ---------------------------------------
+                                                        20020126
 Introduction
 ============
 The SCSI Generic driver (sg) is one of the four "high level" SCSI device
 drivers along with sd, st and sr (disk, tape and CDROM respectively). Sg
 is more generalized (but lower level) than its siblings and tends to be
 used on SCSI devices that don't fit into the already serviced categories.
-Thus sg is used for scanners, cd writers and reading audio cds digitally
+Thus sg is used for scanners, CD writers and reading audio CDs digitally
 amongst other things.
 
-These are notes on the Linux SCSI generic packet device driver (sg)
-describing version 2.1.39 . The original driver was written by Lawrence
-Foard and remained in place with minimal changes since circa 1992.
-Version 2 of this driver remains backward compatible (binary and
-source **) with the original. It adds scatter gather, command queuing,
-per file descriptor sequencing, asynchronous notification and better
-error reporting.
-
-This is an abridged version of the sg documentation that is targeted
-at the linux/Documentation directory. The full document can be found
-at http://www.torque.net/sg/p/scsi-generic_long.txt .
-
-The Linux 2.4 series kernels have now been released. Lk 2.4 contains
-an upgraded "version 3" sg driver which is described in a supplementary
-document at http://www.torque.net/sg/p/scsi-generic_v3.txt .
-
-The interface and usage of the original sg driver have been documented
-by Heiko Eissfeldt in a HOWTO called SCSI-Programming-HOWTO. My copy
-of the document is version 1.5 dated 7th May 1996. It can found at
-ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO-SCSI-Programming-HOWTO .
-A copy of this document can be found at:
-http://www.torque.net/sg/p/original/HOWTO-SCSI-Programming-HOWTO.txt .
-
-** It is possible to write applications that perform differently
-depending on whether they are using the original or this version of
-the sg device driver. The author is not aware of any useful
-pre-existing applications that have problems with version 2.
-
-
-Architecture
-============
-The SCSI generic packet device driver (sg) is a character based device.
-It is one of the four high level device driver in the SCSI sub-system;
-the others are sd (for direct-access devices - disks), st (for tapes)
-and sr (for data cdroms). Sd and sr are block devices while st (like sg)
-is a character device.
-
-The unifying layer of the SCSI sub-system is the so-called mid-level.
-Below that are the "low level" drivers which are the drivers for the
-various adapters supported by Linux. Also at this level are pseudo
-adapter drivers such as ide-scsi which converts the SCSI protocol to
-ATAPI (which are similar to one another) for use by IDE devices.
-
-Since sg is a character device it supports the traditional Unix
-system calls of open(), close(), read(), write() and ioctl(). Two other
-related system calls: poll() and fcntl() are added to this list and
-how they interact with the sg device driver is documented later.
-
-An SG device is accessed by write()ing SCSI commands plus any associated
-outgoing data to it; the resulting status codes and any incoming data are
-then obtained by a read() call. The device can be opened O_NONBLOCK
-(non-blocking) and poll() used to monitor its progress. The device may be
-opened O_EXCL which excludes other "sg" users from this device (but not
-"sd", "st" or "sr" users). The buffer given to the write() call is made
-up as follows:
-        - struct sg_header image (see below)
-        - scsi command (6, 10 or 12 bytes long)
-        - data to be written to the device (if any)
-
-The buffer received from the corresponding read() call contains:
-        - struct sg_header image (check status/errors + sense_buffer)
-        - data read back from device (if any)
-
-The given SCSI command has its LUN field overwritten by the LUN value of
-the associated sg device that has been open()ed.
-
-SCSI commands are only attempted once (i.e. there are no internal
-retries). If appropriate (e.g. a SCSI READ) the data buffer is copied back
-to user space irrespective of the values of the various SCSI related
-error/status codes. [Some adapters that use an old error interface in
-the SCSI mid level ignore the retry count and retry certain errors.]
-
-
-sg_header
-=========
-This is the name of the control structure that conveys information
-about the length of data to be read/written by the associated SCSI
-command. It also conveys error and status information from the
-read() call. An instance of this structure is the first thing that
-is placed in the data buffers of both write() and read().
-
-In its original form it looked like this:
-struct sg_header {
-    int pack_len;
-    int reply_len;
-    int pack_id;
-    int result;
-    unsigned int twelve_byte:1;
-    unsigned int other_flags:31;
-    unsigned char sense_buffer[16];
-}; /* this structure is 36 bytes long */
-
-The 'pack_len' is bizarre and ends up having the 'reply_len' put in it
-(perhaps it had a use at some stage). Even though it looks like an
-input variable, it is not read by sg internally (only written).
-
-The 'reply_len' is the length of the data the corresponding read()
-will/should request (including the sg_header).
-
-The 'pack_id' is not acted upon by the sg device driver but is conveyed
-back to the corresponding read() so it can be used for sequencing by an
-application.
-
-The 'result' is also bizarre, turning certain types of host codes to 0 (no
-error), EBUSY or EIO. With better error reporting now available, the
-'result' is best ignored.
-
-The 'twelve_byte' field overrides the internal SCSI command length detection
-algorithm for group 6 and 7 commands (ie when 1st byte >= 0xc0) and forces
-a command length of 12 bytes.
-The command length detection algorithm is as follows:
-Group:  0    1    2    3    4    5    6    7
-Length: 6   10   10   12   12   12   10   10
-
-'other_flags' was originally documented as "not used" but some current
-applications assume it has 0 placed in it.
-
-The 'sense_buffer' is the first 16 bytes of SCSI sense buffer that is
-returned when the target returns a SCSI status code of CHECK_CONDITION
-or COMMAND_TERMINATED [or (driver_status & DRIVER_SENSE) is true]. This
-buffer should be at least 18 bytes long and arguably 32 bytes; unfortunately
-this is unlikely to happen in the 2.2.x series of kernels.
-
-
-The new sg_header offered in this driver is:
-#define SG_MAX_SENSE 16
-struct sg_header
-{
-    int pack_len;    /* [o] reply_len (ie useless) ignored as input */
-    int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
-    int pack_id;     /* [io] id number of packet (use ints >= 0) */
-    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
-    unsigned int twelve_byte:1;
-        /* [i] Force 12 byte command length for group 6 & 7 commands  */
-    unsigned int target_status:5;   /* [o] scsi status from target */
-    unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
-    unsigned int driver_status:8;   /* [o] driver status+suggestion */
-    unsigned int other_flags:10;    /* unused */
-    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
-           when target_status is CHECK_CONDITION or
-           when target_status is COMMAND_TERMINATED or
-           when (driver_status & DRIVER_SENSE) is true. */
-};      /* This structure is 36 bytes long on i386 */
-
-Firstly the new header is binary compatible with the original. This is
-important for keeping existing apps working without recompilation.
-
-Only those elements (or fields) that are new or in some way different
-from the original are documented below.
-
-'pack_id' becomes input to a read() when ioctl(sg_fd, SG_SET_FORCE_PACK_ID,
-&one) is active. A 'pack_id' of -1 is interpreted as fetch the oldest
-waiting packet; any other value will cause the read() to wait (or yield
-EAGAIN) until a packet with that 'pack_id' becomes available. In all cases
-the value of 'pack_id' available after a read() is the value given to that
-variable in the prior, corresponding write().
-
-The SCSI command length can now be given directly using the SG_NEXT_CMD_LEN
-ioctl().
-
-The 'target_status' field is always output and is the (masked and shifted
-1 bit right) SCSI status code from the target device. The allowable
-values are (found in <scsi/scsi.h>):
-/* N.B. 1 bit offset from usual SCSI status values */
-#define GOOD                 0x00
-#define CHECK_CONDITION      0x01
-#define CONDITION_GOOD       0x02
-#define BUSY                 0x04
-#define INTERMEDIATE_GOOD    0x08
-#define INTERMEDIATE_C_GOOD  0x0a
-#define RESERVATION_CONFLICT 0x0c
-#define COMMAND_TERMINATED   0x11
-#define QUEUE_FULL           0x14
-When the 'target_status' is CHECK_CONDITION or COMMAND_TERMINATED the
-'sense_buffer' is output. Note that when (driver_status & DRIVER_SENSE)
-is true then the 'sense_buffer' is also output (this seems to occur when
-the ide-scsi emulation is used). When the 'sense_buffer' is output the
-SCSI Sense Key can be found at (sense_buffer[2] & 0x0f) .
-
-The 'host_status' field is always output and has the following values
-whose "defines" are not visible outside the kernel. A copy of these
-defines can be found in sg_err.h (see the utilities section):
-#define DID_OK          0x00 /* NO error                                */
-#define DID_NO_CONNECT  0x01 /* Couldn't connect before timeout period  */
-#define DID_BUS_BUSY    0x02 /* BUS stayed busy through time out period */
-#define DID_TIME_OUT    0x03 /* TIMED OUT for other reason              */
-#define DID_BAD_TARGET  0x04 /* BAD target, device not responding?      */
-#define DID_ABORT       0x05 /* Told to abort for some other reason     */
-#define DID_PARITY      0x06 /* Parity error                            */
-#define DID_ERROR       0x07 /* Internal error [DMA underrun on aic7xxx]*/
-#define DID_RESET       0x08 /* Reset by somebody.                      */
-#define DID_BAD_INTR    0x09 /* Got an interrupt we weren't expecting.  */
-#define DID_PASSTHROUGH 0x0a /* Force command past mid-layer            */
-#define DID_SOFT_ERROR  0x0b /* The low level driver wants a retry      */
-
-The 'driver_status' field is always output. When ('driver_status' &
-DRIVER_SENSE) is true the 'sense_buffer' is also output. A copy of these
-defines can be found in sg_err.h (see the utilities section):
-#define DRIVER_OK           0x00 /* Typically no suggestion */
-#define DRIVER_BUSY         0x01
-#define DRIVER_SOFT         0x02
-#define DRIVER_MEDIA        0x03
-#define DRIVER_ERROR        0x04
-#define DRIVER_INVALID      0x05
-#define DRIVER_TIMEOUT      0x06
-#define DRIVER_HARD         0x07
-#define DRIVER_SENSE        0x08 /* Implies sense_buffer output */
-/* above status 'or'ed with one of the following suggestions */
-#define SUGGEST_RETRY       0x10
-#define SUGGEST_ABORT       0x20
-#define SUGGEST_REMAP       0x30
-#define SUGGEST_DIE         0x40
-#define SUGGEST_SENSE       0x80
-
-'other_flags' still remains as a 10 bit field (reduced from 31 bits), so
-code that places 0 in it will still be happy. It is not used.
-
-
-System Calls
-============
-What follows are descriptions of the characteristics of the standard
-Unix operating system calls when applied to a SCSI generic device
-using this version of the device driver.
-
-open(const char * filename, int flags)
---------------------------------------
-The filename should be an 'sg' device such as
-/dev/sg[0,1,2,...]
-/dev/sg[a-z]             <<< now deprecated >>>
-or a symbolic link to one of these. [Devfs has its own sub-directory for
-sg devices with entries like: /dev/scsi/host1/bus2/target3/lun4/generic .]
-It seems as though SCSI devices are allocated to sg minor numbers in the
-same order as they appear in 'cat /proc/scsi/scsi'. Sg is a "character"
-based Linux device driver.  This means it has an open/close/read/write/ioctl
-type interface.
-
-Flags can be either O_RDONLY or O_RDWR or-ed with either
-O_EXCL          waits for other opens on sg device to be closed before
-                proceeding. If O_NONBLOCK is set then yields EBUSY when
-                someone else has the sg device open. The combination of
-                O_RDONLY and O_EXCL is disallowed.
-O_NONBLOCK      Sets non-blocking mode. Calls that would otherwise block
-                yield EAGAIN (eg read() ) or EBUSY (eg open() ).
-
-The original version of sg did not allow the O_RDONLY (yielding a EACCES
-error). This version allows it for accessing ioctls (e.g. doing an sg
-device scan with the SG_GET_SCSI_ID ioctl) but write()s will not be
-allowed. These flags are found in <fcntl.h> .
-
-By default, sequencing is per file descriptor in this version of sg. This
-means, for example that 2 processes can independently manipulate the same
-sg device at the same time. This may or may not make sense depending on
-the application: 2 processes (logically) reading from the same direct access
-device (ie a disk) is ok while running 2 instances of cd writing software
-on the same device at the same time probably wouldn't be a good idea. The
-previous version of sg supported only per device sequencing and this can
-still be selected with the SG_SET_MERGE_FD,1 ioctl().
-
-The driver will attempt to reserve SG_DEF_RESERVED_SIZE bytes (32KBytes in
-the current sg.h) on open(). The size of this reserved buffer can
-subsequently be modified with the SG_SET_RESERVED_SIZE ioctl(). In both
-cases these are requests subject to various dynamic constraints. The actual
-amount of memory obtained can be found by the SG_GET_RESERVED_SIZE ioctl().
-The reserved buffer will be used if:
-    -  it is not already in use (eg when command queuing is in use)
-    -  a write() does not call for a buffer size larger than the
-       reserved size.
-
-Returns a file descriptor if >= 0 , otherwise -1 implies an error.
-
-Error codes (value in 'errno' after -1 returned):
-EACCES          Either the user doesn't have appropriate permissions on
-                'filename' or attempted to use both O_RDONLY and O_EXCL
-EBUSY           O_NONBLOCK set and some user of this sg device has O_EXCL
-                set while someone is already using this device
-EINTR           while waiting for an "exclusive" lock to clear, a signal
-                is received, just try again ...
-ENODEV          sg not compiled into kernel or the kernel cannot find the
-                sg module (or it can't initialize itself (low memory??))
-ENOENT          given filename not found
-ENOMEM          An attempt to get memory to store this open's context
-                failed (this was _not_ a request to reserve DMA memory)
-ENXIO           either there is no attached device corresponding to given
-                filename or scsi sub-system is currently processing some
-                error (eg doing a device reset) or the sg driver/module
-                removed or corrupted
-
-
-write(int sg_fd, const void * buffer, size_t count)
----------------------------------------------------
-Even though sg is a character-based device driver it sends and receives
-packets to/from the associated scsi device. Write() is used to send a
-packet containing 2 mandatory parts and 1 optional part. The mandatory
-parts are:
-  - a control block (an instance of struct sg_header)
-  - a SCSI command (6, 10 or 12 bytes long)
-The optional part is:
-  - outgoing data (eg if a SCSI write command is being sent)
-These should appear as one contiguous string in the buffer given to
-write() in the above order with no pad characters.
-
-If a write() accepts this packet then at some later time the user should
-call a read() to get the result of the SCSI command. The previous sg
-driver enforced a strict write()/read()/write()/read() regime so that a
-second write() would block until first read() was finished. This sg
-driver relaxes that condition and thereby allows command queuing
-(limit is SG_MAX_QUEUE (16) outstanding packets per file descriptor).
-However, for backward compatibility, command queuing is turned off
-by default (#define SG_DEF_COMMAND_Q 0 in sg.h). This can be changed
-via the SG_SET_COMMAND_Q ioctl() [or by recompiling after changing
-the above define to 1].
-
-In this sg driver a write() should return more or less immediately.
-
-Returns number of bytes written if > 0 , otherwise -1 implies an error.
-
-Error codes (value in 'errno' after -1 returned):
-EACCES          opened with RD_ONLY flag
-EAGAIN          SCSI mid-level out of command blocks (rare), try again.
-                This is more likely to happen when queuing commands,
-                so wait a bit (eg usleep(10000) ) before trying again
-EDOM            a) command queuing off: a packet is already queued
-                b) command queuing on: too many packets queued
-                   (SG_MAX_QUEUE exceeded)
-EFAULT          'buffer' for 'count' bytes is an invalid memory range
-EIO             a) incoming buffer too short. It should be at least
-                   (6 + sizeof(struct sg_header))==42 bytes long
-                b) SCSI command length given in SG_NEXT_CMD_LEN too long
-                c) reply_len negative
-ENOMEM          can't get memory for DMA. Take evasive action ...
-ENXIO           either scsi sub-system is currently processing some error
-                (eg doing a device reset) or the sg driver/module removed
-                or corrupted
-
-
-read(int sg_fd, void * buffer, size_t count)
---------------------------------------------
-Read() is used to receive a packet containing 1 mandatory part and 1
-optional part. The mandatory part is:
-  - a control block (an instance of struct sg_header)
-The optional part is:
-  - incoming data (eg if a SCSI read command was sent by earlier write() )
-The buffer given to a read() and its corresponding count should be
-sufficient to accommodate this packet to avoid truncation. Truncation occurs
-if count < sg_header::replylen .
-
-By default, read() will return the oldest packet queued up. If the
-SG_SET_FORCE_PACK_ID,1 ioctl() is active then read() will attempt to
-fetch the packet whose pack_id (given earlier to write()) matches the
-sg_header::pack_id given to this read(). If not available it will either
-wait or yield EAGAIN. As a special case, -1 in sg_header::pack_id given
-to read() will match the oldest packet.
-
-Returns number of bytes read if > 0 , otherwise -1 implies an error.
-Unfortunately the return value in the non-error case is simply the
-same as the count argument. It is not the actual number of bytes
-DMA-ed by the SCSI device. This driver is currently unable to provide
-such an underrun indication.
-
-If the SCSI device reports an error then a REQUEST SENSE is automatically
-done and the output is placed in the sense_buffer array which is in the
-control block. This action is sometimes called "auto-sense".
-
-Error codes (value in 'errno' after -1 returned):
-EAGAIN          either no waiting packet or requested packet is not
-                available while O_NONBLOCK flag was set
-EFAULT          'buffer' for 'count' bytes is an invalid memory range
-EINTR           while waiting for a packet, a signal is received, just
-                try again ...
-EIO             if the 'count' given to read() is < sizeof(struct sg_header)
-                and the 'result' element in sg_header is non-zero. Not a
-                recommended error reporting technique
-ENXIO           either scsi sub-system is currently processing some error
-                (eg doing a device reset) or the sg driver/module removed
-                or corrupted
-
-
-close(int sg_fd)
-----------------
-Preferably a close() should be done after all issued write()s have had
-their corresponding read() calls completed. Unfortunately this is not
-always possible. The semantics of close() in Unix are to return more
-or less immediately (ie not wait on any event) so the driver needs to
-arrange for an orderly cleanup of those packets that are still "in
-flight".
-
-A process that has an open file descriptor to an sg device may be aborted
-(eg by a kill signal). In this case, the kernel automatically calls close
-(which is called 'sg_release()' in the version 2 driver) to facilitate
-the cleanup mentioned above.
-
-A problem persists in version 2.1.39 if the sg driver is a module and is
-removed while packets are still "in flight".
-
-Returns 0 if successful, otherwise -1 implies an error.
-
-Error codes (value in 'errno' after -1 returned):
-ENXIO           sg driver/module removed or corrupted
-
-ioctl(int sg_fd, int command, ...)  [sg specific]
--------------------------------------------------
-Ken Thompson (or perhaps some other Unix luminary) described ioctl() as
-the "garbage bin of Unix". This driver compounds the situation by adding
-more ...
-If a ioctl command is not recognized by sg (and the various lower levels
-that it may pass the command on to) then the error EINVAL occurs. If an
-invalid address is given (in the 3rd argument) then the error EFAULT occurs.
-
-Those commands with an appended "+" are new in version 2.
-
-Those commands with an appended "W" are only accessible from file
-descriptors opened with O_RDWR. They will yield EACCES otherwise.
-
-SG_GET_TIMEOUT:
-Ignores its 3rd argument and _returns_ the timeout value (which will be
->= 0 ). The unit of this timeout is "jiffies" which are currently 10
-millisecond intervals on i386 (less on an alpha). Linux supplies
-a manifest constant HZ which is the number of "jiffies" in 1 second.
-
-SG_SET_TIMEOUT:
-Assumes 3rd argument points to an int containing the new timeout value
-for this file descriptor. The unit is a "jiffy". Packets that are
-already "in flight" will not be affected. The default value is set
-on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). This default is
-currently 1 minute and may not be long enough for formats. Negative
-values will yield an EIO error.
-
-SG_EMULATED_HOST:
-Assumes 3rd argument points to an int and outputs a flag indicating
-whether the host (adapter) is connected to a real SCSI bus or is an
-emulated one (eg ide-scsi device driver). A value of 1 means emulated
-while 0 is not.
-
-SG_SET_TRANSFORM  W:
-Only is meaningful when SG_EMULATED host has yielded 1 (i.e. the low-level
-is the ide-scsi device driver); otherwise an EINVAL error occurs. The
-default state is to _not_ transform SCSI commands to the corresponding
-ATAPI commands but pass them straight through as is. [Only certain classes
-of SCSI commands need to be transformed to their ATAPI equivalents.]
-The third argument is interpreted as an integer. When it is non-zero then
-a flag is set inside the ide-scsi driver that transforms subsequent
-commands sent to this driver. When zero is passed as the 3rd argument to
-this ioctl then the flag within the ide-scsi driver is cleared and
-subsequent commands are not transformed. Beware, this state will affect
-all devices (and hence all related sg file descriptors) associated with
-this ide-scsi "bus".
-
-SG_GET_TRANSFORM:
-Third argument is ignored. Only is meaningful when SG_EMULATED host has
-yielded 1 (ie the low-level is the ide-scsi device driver); otherwise
-an EINVAL error occurs. Returns 0 to indicate _not_ transforming SCSI
-to ATAPI commands (default). Returns 1 when it is transforming them.
-
-SG_SET_FORCE_LOW_DMA +:
-Assumes 3rd argument points to an int containing 0 or 1. 0 (default)
-means sg decides whether to use memory above 16 Mbyte level (on i386)
-based on the host adapter being used by this SCSI device. Typically
-PCI SCSI adapters will indicate they can DMA to the whole 32 bit address
-space.
-If 1 is given then the host adapter is overridden and only memory below
-the 16MB level is used for DMA. A requirement for this should be
-extremely rare. If the "reserved" buffer allocated on open() is not in
-use then it will be de-allocated and re-allocated under the 16MB level
-(and the latter operation could fail yielding ENOMEM).
-Only the current file descriptor is affected.
-
-SG_GET_LOW_DMA +:
-Assumes 3rd argument points to an int and places 0 or 1 in it. 0
-indicates the whole 32 bit address space is being used for DMA transfers
-on this file descriptor. 1 indicates the memory below the 16MB level
-(on i386) is being used (and this may be the case because the host
-adapters setting has been overridden by SG_SET_FORCE_LOW_DMA,1 .
-
-SG_GET_SCSI_ID +:
-Assumes 3rd argument is pointing to an object of type Sg_scsi_id (see
-sg.h) and populates it. That structure contains ints for host_no,
-channel, scsi_id, lun, scsi_type, allowable commands per lun and
-queue_depth. Most of this information is available from other sources
-(eg SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER) but tends to be
-awkward to collect.
-Allowable commands per lun and queue_depth give an insight to the
-command queuing capabilities of the adapters and the device. The latter
-overrides the former (logically) and the former is only of interest
-if it is equal to queue_depth which probably indicates the device
-does not support queueing commands (e.g. most scanners).
-
-SG_SET_FORCE_PACK_ID +:
-Assumes 3rd argument is pointing to an int. 0 (default) instructs read()
-to return the oldest (written) packet if multiple packets are
-waiting to be read (when command queuing is being used).
-1 instructs read() to view the sg_header::pack_id as input and return the
-oldest packet matching that pack_id or wait until it arrives (or yield
-EAGAIN if O_NONBLOCK is in force). As a special case the pack_id of -1
-given to read() in the mode will match the oldest packet.
-Only the current file descriptor is affected by this command.
-
-SG_GET_PACK_ID +:
-Assumes 3rd argument points to an int and places the pack_id of the
-oldest (written) packet in it. If no packet is waiting to be read then
-yields -1.
-
-SG_GET_NUM_WAITING +:
-Assumes 3rd argument points to an int and places the number of packets
-waiting to be read in it.
-
-SG_GET_SG_TABLESIZE +:
-Assumes 3rd argument points to an int and places the maximum number of
-scatter gather elements supported by the host adapter. 0 indicates that
-the adapter does support scatter gather.
-
-SG_SET_RESERVED_SIZE +W:
-Assumes 3rd argument is pointing to an int. That value will be used to
-request a new reserved buffer of that size. The previous reserved buffer
-is freed (if it is not in use; if it was in use -EBUSY is returned).
-A new reserved buffer is then allocated and its actual size can be found by
-calling the SG_GET_RESERVED_SIZE ioctl(). The reserved buffer is then used
-for DMA purposes by subsequent write() commands if it is not already in
-use and if the write() is not calling for a buffer size larger than that
-reserved. The reserved buffer may well be a series of kernel buffers if the
-adapter supports scatter-gather. Large buffers can be requested (eg 1 MB).
-
-SG_GET_RESERVED_SIZE +:
-Assumes 3rd argument points to an int and places the size in bytes of
-the reserved buffer from open() or the most recent SG_SET_RESERVED_SIZE
-ioctl() call on this fd.  The result can be 0 if memory is very tight. In
-this case it may not be wise to attempt something like burning a CD on
-this file descriptor.
-
-SG_SET_MERGE_FD +W:
-Assumes 3rd argument is pointing to an int. 0 (the default) causes all
-subsequent sequencing to be per file descriptor. 1 causes all subsequent
-sequencing to be per device. If this command tries to change the current
-state and there is one or more _other_ file descriptors using this sg
-device then an EBUSY error occurs. Per device sequencing was the original
-semantics and allowed, for example different processes to "share" the
-device, one perhaps write()ing with the other one read()ing. This command
-is supplied if anyone needs those semantics. Per file descriptor
-sequencing, perhaps with the use of the O_EXCL flag, seems more sensible.
-
-SG_GET_MERGE_FD +:
-Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
-sequencing is per file descriptor. 1 implies sequencing is per device
-(original sg driver's semantics).
-
-SG_SET_COMMAND_Q +:
-Assumes 3rd argument is pointing to an int. 0 (current default, set by
-SG_DEF_COMMAND_Q in sg.h) disables command queuing. Attempts to write()
-a packet while one is already queued will result in a EDOM error.
-1 turns command queuing on.
-Changing the queuing state only affects write()s done after the change.
-Only the current file descriptor is affected by this command.
-
-SG_GET_COMMAND_Q +:
-Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
-that command queuing is off on this file descriptor. 1 implies command
-queuing is on.
-
-SG_SET_UNDERRUN_FLAG +:
-Assumes 3rd argument is pointing to an int. 0 (current default, set by
-SG_DEF_UNDERRUN_FLAG in sg.h) requests underruns be ignored. 1 requests
-that underruns be flagged. [The only low level driver that acts on this
-at the moment is the aic7xxx which yields a DID_ERROR error on underrun.]
-Only the current file descriptor is affected by this command (unless
-"per device" sequencing has been selected).
-
-SG_GET_UNDERRUN_FLAG +:
-Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
-that underruns are not being reported. 1 implies that underruns are being
-reported (see SG_SET_UNDERRUN_FLAG for more details).
-
-SG_NEXT_CMD_LEN +:
-Assumes 3rd argument is pointing to an int. The value of the int (if > 0)
-will be used as the SCSI command length of the next SCSI command sent to
-a write() on this fd. After that write() the SCSI command length logic is
-reset to use automatic length detection (ie depending on SCSI command group
-and the 'twelve_byte' field). If the current SCSI command length maximum of
-12 is exceeded then the affected write() will yield an EDOM error.
-Giving this ioctl() a value of 0 will set automatic length detection for
-the next write(). N.B. Only the following write() on this fd is affected by
-this ioctl().
-
-SG_GET_VERSION_NUM +:
-Assumes 3rd argument points to an int. The version number is then placed
-in that int. A sg version such as 2.1.36 will yield "20136" from this ioctl.
-
-SG_SCSI_RESET +:
-Assumes 3rd argument points to an int. Unfortunately doesn't currently
-do much (may in the future after other issues are resolved). Yields an
-EBUSY error if the SCSI bus or the associated device is being reset
-when this ioctl() is called, otherwise returns 0.
-N.B. In some recent distributions there is a patch to the SCSI mid level
-code that activates this ioctl. Check your distribution.
-
-SG_SET_DEBUG +:
-Assumes 3rd argument is pointing to an int. 0 (default) turns debugging
-off. Values > 0 cause the SCSI sense buffer to be decoded and output
-to the console/log when a SCSI device error occurs. Values > 8 cause
-the current sg device driver's state to be output to the console/log
-(this is a "one off" effect).
-If you need a _lot_ of the SCSI sub-system debug information (mainly from
-the mid-level) then try 'echo "scsi dump 0" > /proc/scsi/scsi' and lots of
-debug will appear in your console/log.
-
-
-poll(struct pollfd * udfds, unsigned int nfds, int timeout_ms)
---------------------------------------------------------------
-This is a native call in Linux 2.2 but most of its capabilities are available
-through the older select() call. Given a choice poll() should probably be
-used. Typically poll() is used when a sg scsi device is open()ed O_NONBLOCK
-for polling; and optionally with asynchronous notification as well using
-the fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal.
-Only if something drastically is wrong (eg file handle gone stale) will
-POLLERR ever be set. POLLPRI, POLLHUP and POLLNVAL are never set.
-POLLIN is set when there is one or more packets waiting to be read.
-When POLLIN is set it implies that a read() will not block (nor yield
-EAGAIN in non-blocking mode) but return a packet immediately.
-POLLOUT (aka POLLWRNORM) is set when write() is able to accept a packet
-(ie will _not_ yield an EDOM error). The setting of POLLOUT is affected
-by the SG_SET_COMMAND_Q state: if the state is on then POLLOUT will remain
-set until the number of queued packets reaches SG_MAX_QUEUE, if the
-state is off then POLLOUT is only set when no packets are queued.
-Note that a packet can be queued after write()ing but not available to be
-read(); this typically happens when a SCSI read command is issued while
-the data is being retrieved.
-Poll() is per file descriptor unless SG_SET_MERGE_FD is set in which case
-it is per device.
-
-
-fcntl(int sg_fd, int cmd) or fcntl(int sg_fd, int cmd, long arg)
-----------------------------------------------------------------
-There are several uses for this system call in association with a sg
-file descriptor. The following pseudo code shows code that is useful for
-scanning the sg devices, taking care not to be caught in a wait for
-an O_EXCL lock by another process, and when the appropriate device is
-found, switching to normal blocked io. A working example of this logic
-is in the sg_scan utility program.
-
-open("/dev/sg0", O_RDONLY | O_NONBLOCK)
-/* check device, EBUSY means some other process has O_EXCL lock on it */
-/* when the device you want is found then ... */
-flags = fcntl(sg_fd, F_GETFL)
-fcntl(sg_fd, F_SETFL, flags & (~ O_NONBLOCK))
-/* since, for simple apps, it is easier to use normal blocked io */
-
-
-Some work has to be done in Linux to set up for asynchronous notification.
-This is a non-blocking mode of operation in which, when the driver receives
-data back from a device so that a read() can be done, it sends a SIGPOLL
-(aka SIGIO) signal to the owning process. A working example of this logic
-is in the sg_poll test program.
-
-sigemptyset(&sig_set)
-sigaddset(&sig_set, SIGPOLL)
-sigaction(SIGPOLL, &s_action, 0)
-fcntl(sg_fd, F_SETOWN, getpid())
-flags = fcntl(sg_fd, F_GETFL);
-fcntl(sg_fd, F_SETFL, flags | O_ASYNC)
-
-
-Utility and Test Programs
-=========================
-See the README file in the sg_utils<date>.tgz tarball. Look on the
-http://www.torque.net/sg website for the latest version.
-
-Briefly, that tarball contains the following utilities:
-sg_dd512        'dd' like program that assumes 512 byte blocks size
-sg_dd2048       'dd' like program that assumes 2048 byte blocks size
-sg_dd2352       'dd' like program that assumes 2352 byte blocks size
-sgq_dd512       like 'sg_dd512' but does command queuing on "if"
-sgp_dd          probably the most flexible 'dd' variant. It uses POSIX
-                threads, block size set by "bs=..." plus other options.
-sg_scan         outputs information (optionally Inquiry) on SCSI devices
-sg_rbuf         tests SCSI bus transfer speed (without physical IO)
-sg_whoami       outputs info (optionally capacity) of given SCSI device
-sginfo          outputs "mode" information about SCSI devices (it is a
-                  re-port of the scsiinfo program onto the sg interface)
-
-It also contains the following test programs:
-sg_debug        outputs sg driver state to console/log file
-sg_poll         tests asynchronous notification
-sg_runt_ex      example run time selection program for application authors
-sg_simple1      example program first time users
-sg_simple2      like sg_simple1 but with more primitive error processing
-sg_inquiry      does a SCSI Inquiry command (from original HOWTO)
-sg_tst_med      checks presence of media (from original HOWTO)
-
-There are also 2 source files (sg_err.[hc]) for outputting and categorizing
-SCSI 2 errors and warnings. This code is used by most of the above
-utility and test programs.
-
-The following programs: sg_dd512, sg_dd2048, sg_dd2352, sg_scan, sg_runt_ex,
-sg_rbuf, sg_tst_med, sg_inquiry and sginfo, can be compiled either for this
-new sg driver _or_ the original sg driver (in 2.0 or 2.2 series kernels).
-sg_runt_ex can be run on 2.0, 2.2 or 2.3 series kernels even if it is
-compiled on a different series (eg compiled on 2.0, run on 2.2).
-
-
-Header files
-============
-User applications need to find the correct "sg.h" header file matching
-their kernel in order to write code using the sg device driver. This is
-sometimes more difficult than it should be. The correct "sg.h" will usually
-be found at /usr/src/linux/include/scsi/sg.h . Another important header
-file is "scsi.h" which will be in the same directory.
-
-When "#include <scsi/sg.h>" is written in an application then this refers
-to the file /usr/include/scsi/sg.h . A problem sometimes arises because
-the files in the /usr/include/scsi directory are controlled by the GNU
-library people who maintain glibc. Unfortunately these 2 versions of
-the sg.h header file are not always in sync. [This was the case in Redhat
-6.0 and 6.1 .] Glibc 2.1.3 and later versions should get this right.
-
-If this is a problem, the user may need to copy sg.h (and scsi.h) from
-the kernel source includes to /usr/include scsi. If the user can change
-the effected source code then another approach is to rely on the fact that
-/usr/src/linux is a symbolic link to /usr/src/linux/include/linux and
-change the sg.h include to look like:
-    #include <linux/../scsi/sg.h>
-This solution is used by the author of cdparanoia (Monty) in his application.
-
-[Former scsi generic documents suggested adding a symbolic link to
-bypass this problem but that is not popular with the glibc maintainers.
-I would like to thank Andreas Jaeger <aj@suse.de> for his contributions
-on this subject.]
-
-
-Extra information in scsi-generic_long.txt
-==========================================
-This document is an abridged form of a more comprehensive document called
-scsi-generic_long.txt (see www.torque.net/sg/p/scsi-generic_long.txt).
-
-The longer document contains additional sections on:
-   - memory issues
-   - ioctl()s in common with sd, st + sr
-   - distinguishing the original from the new driver
-   - SG_BIG_BUFF and friends
-   - shortcomings
-   - future directions
-   - an appendix with some SCSI 2 information in it
-
-
-References
-==========
-http://www.t10.org      Very important site for SCSI related information.
-                        Contains SCSI 2 and 3 draft standards.
-http://www.andante.org/scsi.html
-                        This is Eric Youngdale's site. Eric is primarily
-                        responsible for the Linux SCSI architecture and
-                        its mid-level implementation.
-http://www.kernel.dk    Jens Axboe's site for Linux cdrom matters including
-                        the SCSI "sr" driver.
-http://www.torque.net/sg
-                        My site with sg related information.
-newsgroup:linux-scsi@vger.kernel.org
-                        Newsgroup for Linux related SCSI matters
-/usr/src/linux/MAINTAINERS
-                        This is a file in the Linux kernel source that
-                        contains up to date information about who maintains
-                        what and where information can be found. Links to
-                        SCSI adapter information are also here.
-
-
-Conclusion
-==========
-The SCSI generic packet device driver attempts to make as few assumptions
-as possible about the device it is connected to while giving applications
-using it as much flexibility as possible on the SCSI command level. Sg
-needs to hide the "messy" kernel related details while protecting
-the integrity of the kernel against sg "abuse". Some of these aims are
-contradictory and some compromises need to be made. For example: should
-a sg based application be able to reset a SCSI bus when that could cause
-collateral damage to a disk holding the root file system? There is no
-easy answer to this and many other related questions.
-
-If you have any suggestion about sg (or improving (the accuracy of) this
-document) please contact me.
+Rather than document the driver's interface here, version information
+is provided plus pointers (i.e. URLs) where to find documentation
+and examples.
+
+
+Major versions of the sg driver
+===============================
+There are three major versions of sg found in the linux kernel (lk):
+      - sg version 1 (original) from 1992 to early 1999 (lk 2.2.5) . 
+	It is based in the sg_header interface structure.
+      - sg version 2 from lk 2.2.6 in the 2.2 series. It is based on
+	an extended version of the sg_header interface structure.
+      - sg version 3 found in the lk 2.4 series (and the lk 2.5 series).
+	It adds the sg_io_hdr interface structure.
+
+
+Sg driver documentation
+=======================
+The most recent documentation of the sg driver is kept at the Linux
+Documentation Project's (LDP) site: 
+http://www.linuxdoc.org/HOWTO/SCSI-Generic-HOWTO
+This describes the sg version 3 driver found in the lk 2.4 series.
+The LDP renders documents in single and multiple page HTML, postscript
+and pdf. This document can also be found at:
+http://www.torque.net/sg/p/sg_v3_ho.html
+
+Documentation for the version 2 sg driver found in the lk 2.2 series can
+be found at http://www.torque.net/sg/p/scsi-generic.txt . A larger version
+is at:  http://www.torque.net/sg/p/scsi-generic_long.txt .
+
+The original documentation for the sg driver (prior to lk 2.2.6) can be
+found at http://www.torque.net/sg/p/original/SCSI-Programming-HOWTO.txt
+and in the LDP archives.
+
+A changelog with brief notes can be found in the
+/usr/src/linux/include/scsi/sg.h file. Note that the glibc maintainers copy 
+and edit this file (removing its changelog for example) before placing it 
+in /usr/include/scsi/sg.h . Driver debugging information and other notes 
+can be found at the top of the /usr/src/linux/drivers/scsi/sg.c file.
+
+A more general description of the Linux SCSI subsystem of which sg is a 
+part can be found at http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO .
+
+
+Example code and utilities
+==========================
+There are two packages of sg utilities:
+  - sg3_utils   for the sg version 3 driver found in lk 2.4
+  - sg_utils    for the sg version 2 (and original) driver found in lk 2.2
+                and earlier
+Both packages will work in the lk 2.4 series however sg3_utils offers more
+capabilities. They can be found at: http://www.torque.net/sg and 
+freshmeat.net
+
+Another approach is to look at the applications that use the sg driver.
+These include cdrecord, cdparanoia, SANE and cdrdao.
+
+
+Mapping of Linux kernel versions to sg driver versions
+======================================================
+Here is a list of linux kernels in the 2.4 series that had new version
+of the sg driver:
+      lk 2.4.0 : sg version 3.1.17
+      lk 2.4.7 : sg version 3.1.19 
+      lk 2.4.10 : sg version 3.1.20  **
+      lk 2.4.17 : sg version 3.1.22 
+
+** There were 3 changes to sg version 3.1.20 by third parties in the
+   next six linux kernel versions.
+
+For reference here is a list of linux kernels in the 2.2 series that had 
+new version of the sg driver:
+      lk 2.2.0 : original sg version [with no version number]
+      lk 2.2.6 : sg version 2.1.31
+      lk 2.2.8 : sg version 2.1.32
+      lk 2.2.10 : sg version 2.1.34 [SG_GET_VERSION_NUM ioctl first appeared]
+      lk 2.2.14 : sg version 2.1.36
+      lk 2.2.16 : sg version 2.1.38
+      lk 2.2.17 : sg version 2.1.39
+      lk 2.2.20 : sg version 2.1.40
+
+The lk 2.5 development series has recently commenced and it currently
+contains sg version 3.5.23 which is functionally equivalent to sg
+version 3.1.22 found in lk 2.4.17 .
 
 
 Douglas Gilbert
+26th January 2002
 dgilbert@interlog.com
diff -urN linux-2.5.3-pre5/Documentation/scsi.txt linux/Documentation/scsi.txt
--- linux-2.5.3-pre5/Documentation/scsi.txt	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/scsi.txt	Mon Jan 28 13:46:19 2002
@@ -1,30 +1,44 @@
+SCSI subsystem documentation
+============================
+The Linux Documentation Project (LDP) maintains a document describing
+the SCSI subsystem in the Linux kernel (lk) 2.4 series. See:
+http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO . The LDP has single
+and multiple page HTML renderings as well as postscript and pdf.
+It can also be found at http://www.torque.net/scsi/SCSI-2.4-HOWTO .
 
-	The scsi support in the linux kernel can be modularized in a
-number of different ways depending upon the needs of the end user.  To
-understand  your options, we should first define a few terms.
-
-	The scsi-core contains the core of scsi support.  Without it
-you can do nothing with any of the other scsi drivers.  The scsi core
-support can be a module (scsi_mod.o), or it can be built into the kernel.
-If the core is a module, it must be the first scsi module loaded, and
-if you unload the modules, it will have to be the last one unloaded.
-
-	The individual upper and lower level drivers can be loaded in any
-order once the scsi core is present in the kernel (either compiled in
-or loaded as a module).  The disk driver (sd_mod.o), cdrom driver (sr_mod.o),
-tape driver (st.o) and scsi generics driver (sg.o) represent the upper level
-drivers to support the various assorted devices which can be controlled.
-You can for example load the tape driver to use the tape drive, and then
-unload it once you have no further need for the driver (and release the
-associated memory).
-
-	The lower level drivers are the ones that support the
-individual cards that are supported for the hardware platform that you
-are running under.  Examples are aha1542.o to drive Adaptec 1542
-cards.  Rather than list the drivers which *can* be modularized, it is
-easier to list the ones which cannot, since the list only contains a
-few entries.  The drivers which have NOT been modularized are:
 
-	NCR5380 boards of one kind or another including PAS16,
-		Trantor T128/128F/228, 
+Notes on using modules in the SCSI subsystem
+============================================
+The scsi support in the linux kernel can be modularized in a number of 
+different ways depending upon the needs of the end user.  To understand
+your options, we should first define a few terms.
+
+The scsi-core (also known as the "mid level") contains the core of scsi 
+support.  Without it you can do nothing with any of the other scsi drivers.
+The scsi core support can be a module (scsi_mod.o), or it can be built into
+the kernel. If the core is a module, it must be the first scsi module 
+loaded, and if you unload the modules, it will have to be the last one 
+unloaded.  In practice the modprobe and rmmod commands (and "autoclean")
+will enforce the correct ordering of loading and unloading modules in
+the SCSI subsystem.
+
+The individual upper and lower level drivers can be loaded in any order 
+once the scsi core is present in the kernel (either compiled in or loaded
+as a module).  The disk driver (sd_mod.o), cdrom driver (sr_mod.o),
+tape driver ** (st.o) and scsi generics driver (sg.o) represent the upper 
+level drivers to support the various assorted devices which can be 
+controlled.  You can for example load the tape driver to use the tape drive, 
+and then unload it once you have no further need for the driver (and release
+the associated memory).
+
+The lower level drivers are the ones that support the individual cards that
+are supported for the hardware platform that you are running under. Those
+individual cards are often called Host Bus Adapters (HBAs). For example the
+aic7xxx.o driver is used to control all recent SCSI controller cards from 
+Adaptec. Almost all lower level drivers can be built either as modules or 
+built into the kernel.
+
+
+** There is a variant of the st driver for controlling OnStream tape
+   devices. Its module name is osst.o .
 
diff -urN linux-2.5.3-pre5/Makefile linux/Makefile
--- linux-2.5.3-pre5/Makefile	Mon Jan 28 13:46:15 2002
+++ linux/Makefile	Mon Jan 28 13:46:19 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
 SUBLEVEL = 3
-EXTRAVERSION =-pre5
+EXTRAVERSION =-pre6
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -131,7 +131,8 @@
 
 DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o
 DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
-DRIVERS-y += drivers/char/char.o \
+DRIVERS-y += drivers/base/base.o \
+	drivers/char/char.o \
 	drivers/block/block.o \
 	drivers/misc/misc.o \
 	drivers/net/net.o \
diff -urN linux-2.5.3-pre5/arch/alpha/Config.help linux/arch/alpha/Config.help
--- linux-2.5.3-pre5/arch/alpha/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/alpha/Config.help	Mon Jan 28 13:46:19 2002
@@ -92,11 +92,83 @@
   Access).  This option is for configuring high-end multiprocessor
   server machines.  If in doubt, say N.
 
+CONFIG_ALPHA_GENERIC
+  This is the system type of your hardware.  A "generic" kernel will
+  run on any supported Alpha system. However, if you configure a
+  kernel for your specific system, it will be faster and smaller.
+
+  To find out what type of Alpha system you have, you may want to
+  check out the Linux/Alpha FAQ, accessible on the WWW from
+  <http://www.alphalinux.org/>. In summary:
+
+  Alcor/Alpha-XLT     AS 600
+  Alpha-XL            XL-233, XL-266
+  AlphaBook1          Alpha laptop
+  Avanti              AS 200, AS 205, AS 250, AS 255, AS 300, AS 400
+  Cabriolet           AlphaPC64, AlphaPCI64
+  DP264               DP264
+  EB164               EB164 21164 evaluation board
+  EB64+               EB64+ 21064 evaluation board
+  EB66                EB66 21066 evaluation board
+  EB66+               EB66+ 21066 evaluation board
+  Jensen              DECpc 150, DEC 2000 model 300,
+                      DEC 2000 model 500
+  LX164               AlphaPC164-LX
+  Miata               Personal Workstation 433a, 433au, 500a,
+                      500au, 600a, or 600au
+  Mikasa              AS 1000
+  Noname              AXPpci33, UDB (Multia)
+  Noritake            AS 1000A, AS 600A, AS 800
+  PC164               AlphaPC164
+  Rawhide             AS 1200, AS 4000, AS 4100
+  Ruffian             RPX164-2, AlphaPC164-UX, AlphaPC164-BX
+  SX164               AlphaPC164-SX
+  Sable               AS 2000, AS 2100
+  Shark		      DS 20L
+  Takara              Takara
+  Titan               Privateer
+  Wildfire            AlphaServer GS 40/80/160/320
+
+  If you don't know what to do, choose "generic".
+
+CONFIG_ALPHA_ALCOR
+  For systems using the Digital ALCOR chipset: 5 chips (4, 64-bit data
+  slices (Data Switch, DSW) - 208-pin PQFP and 1 control (Control, I/O
+  Address, CIA) - a 383 pin plastic PGA).  It provides a DRAM
+  controller (256-bit memory bus) and a PCI interface.  It also does
+  all the work required to support an external Bcache and to maintain
+  memory coherence when a PCI device DMAs into (or out of) memory.
+
+CONFIG_ALPHA_XL
+  XL-233 and XL-266-based Alpha systems.
+
+CONFIG_ALPHA_BOOK1
+  Dec AlphaBook1/Burns Alpha-based laptops.
+
 CONFIG_ALPHA_AVANTI
   Avanti AS 200, AS 205, AS 250, AS 255, AS 300, and AS 400-based
   Alphas. Info at
   <http://www.unix-ag.org/Linux-Alpha/Architectures/Avanti.html>.
 
+CONFIG_ALPHA_CABRIOLET
+  Cabriolet AlphaPC64, AlphaPCI64 systems.  Derived from EB64+ but now
+  baby-AT with Flash boot ROM, no on-board SCSI or Ethernet. 3 ISA
+  slots, 4 PCI slots (one pair are on a shared slot), uses plug-in
+  Bcache SIMMs.  Requires power supply with 3.3V output.
+
+CONFIG_ALPHA_DP264
+  Various 21264 systems with the tsunami core logic chipset.
+  API Networks: 264DP, UP2000(+), CS20;
+  Compaq: DS10(E,L), XP900, XP1000, DS20(E), ES40.
+
+CONFIG_ALPHA_EB164
+  EB164 21164 evaluation board from DEC.  Uses 21164 and ALCOR.  Has
+  ISA and PCI expansion (3 ISA slots, 2 64-bit PCI slots (one is
+  shared with an ISA slot) and 2 32-bit PCI slots.  Uses plus-in
+  Bcache SIMMs. I/O sub-system provides SuperI/O (2S, 1P, FD), KBD,
+  MOUSE (PS2 style), RTC/NVRAM.  Boot ROM is Flash.  PC-AT-sized
+  motherboard.  Requires power supply with 3.3V output.
+
 CONFIG_ALPHA_EB64P
   Uses 21064 or 21064A and APECs.  Has ISA and PCI expansion (3 ISA,
   2 PCI, one pair are on a shared slot). Supports 36-bit DRAM SIMs.
@@ -105,6 +177,43 @@
   SuperI/O (2S, 1P, FD), RTC/NVRAM. Boot ROM is EPROM.  PC-AT size.
   Runs from standard PC power supply.
 
+CONFIG_ALPHA_EB66
+  A Digital DS group board.  Uses 21066 or 21066A.  I/O sub-system is
+  identical to EB64+.  Baby PC-AT size.  Runs from standard PC power
+  supply.  The EB66 schematic was published as a marketing poster
+  advertising the 21066 as "the first microprocessor in the world with
+  embedded PCI".
+
+CONFIG_ALPHA_EB66P
+  Later variant of the EB66 board.
+
+CONFIG_ALPHA_EIGER
+  Apparently an obscure OEM single-board computer based on the
+  Typhoon/Tsunami chipset family. Information on it is scanty.
+
+CONFIG_ALPHA_JENSEN
+  DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one
+  of the first-generation Alpha systems. A number of these systems
+  seem to be available on the second- hand market. The Jensen is a
+  floor-standing tower system which originally used a 150MHz 21064 It
+  used programmable logic to interface a 486 EISA I/O bridge to the
+  CPU.
+
+CONFIG_ALPHA_LX164
+  A technical overview of this board is available at
+  <http://www.unix-ag.org/Linux-Alpha/Architectures/LX164.html>.
+
+CONFIG_ALPHA_MIATA
+  The Digital PersonalWorkStation (PWS 433a, 433au, 500a, 500au, 600a,
+  or 600au).  There is an Installation HOWTO for this hardware at
+  <http://members.brabant.chello.nl/~s.vandereijk/miata.html>.
+
+CONFIG_ALPHA_MIKASA
+  AlphaServer 1000-based Alpha systems.
+
+CONFIG_ALPHA_NAUTILUS
+  Alpha systems based on the AMD 751 & ALI 1543C chipsets.
+
 CONFIG_ALPHA_NONAME
   The AXPpci33 (aka NoName), is based on the EB66 (includes the Multia
   UDB).  This design was produced by Digital's Technical OEM (TOEM)
@@ -114,6 +223,28 @@
   2 versions, with either PS/2 or large DIN connectors for the
   keyboard.
 
+CONFIG_ALPHA_NORITAKE
+  AlphaServer 1000A, AlphaServer 600A, and AlphaServer 800-based
+  systems.
+
+CONFIG_ALPHA_RAWHIDE
+  AlphaServer 1200, AlphaServer 4000 and AlphaServer 4100 machines.
+  See HOWTO at
+  <http://www.alphalinux.org/docs/rawhide/4100_install.shtml>.
+
+CONFIG_ALPHA_RUFFIAN
+  Samsung APC164UX.  There is a page on known problems and workarounds
+  at <http://www.alphalinux.org/faq/FAQ-11.html>.
+
+CONFIG_ALPHA_SABLE
+  Digital AlphaServer 2000 and 2100-based systems.
+
+CONFIG_ALPHA_TAKARA
+  Alpha 11164-based OEM single-board computer.
+
+CONFIG_ALPHA_WILDFIRE
+  AlphaServer GS 40/80/160/320 SMP based on the EV67 core.
+
 CONFIG_ALPHA_PRIMO
   Say Y if you have an AS 1000 5/xxx or an AS 1000A 5/xxx.
 
@@ -236,6 +367,29 @@
   When compiled this way, there will be modules called pcmcia_core.o
   and ds.o.  If you want to compile it as a module, say M here and
   read <file:Documentation/modules.txt>.
+
+CONFIG_KCORE_ELF
+  If you enabled support for /proc file system then the file
+  /proc/kcore will contain the kernel core image. This can be used
+  in gdb:
+
+  $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
+
+  You have two choices here: ELF and A.OUT. Selecting ELF will make
+  /proc/kcore appear in ELF core format as defined by the Executable
+  and Linking Format specification. Selecting A.OUT will choose the
+  old "a.out" format which may be necessary for some old versions
+  of binutils or on some architectures.
+
+  This is especially useful if you have compiled the kernel with the
+  "-g" option to preserve debugging information. It is mainly used
+  for examining kernel data structures on the live kernel so if you
+  don't understand what this means or are not a kernel hacker, just
+  leave it at its default value ELF.
+
+CONFIG_KCORE_AOUT
+  Not necessary unless you're using a very out-of-date binutils
+  version.  You probably want KCORE_ELF.
 
 CONFIG_BINFMT_ELF
   ELF (Executable and Linkable Format) is a format for libraries and
diff -urN linux-2.5.3-pre5/arch/arm/Config.help linux/arch/arm/Config.help
--- linux-2.5.3-pre5/arch/arm/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/arm/Config.help	Mon Jan 28 13:46:19 2002
@@ -170,6 +170,29 @@
   and ds.o.  If you want to compile it as a module, say M here and
   read <file:Documentation/modules.txt>.
 
+CONFIG_KCORE_ELF
+  If you enabled support for /proc file system then the file
+  /proc/kcore will contain the kernel core image. This can be used
+  in gdb:
+
+  $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
+
+  You have two choices here: ELF and A.OUT. Selecting ELF will make
+  /proc/kcore appear in ELF core format as defined by the Executable
+  and Linking Format specification. Selecting A.OUT will choose the
+  old "a.out" format which may be necessary for some old versions
+  of binutils or on some architectures.
+
+  This is especially useful if you have compiled the kernel with the
+  "-g" option to preserve debugging information. It is mainly used
+  for examining kernel data structures on the live kernel so if you
+  don't understand what this means or are not a kernel hacker, just
+  leave it at its default value ELF.
+
+CONFIG_KCORE_AOUT
+  Not necessary unless you're using a very out-of-date binutils
+  version.  You probably want KCORE_ELF.
+
 CONFIG_BINFMT_ELF
   ELF (Executable and Linkable Format) is a format for libraries and
   executables used across different architectures and operating
@@ -251,6 +274,26 @@
 
   Say Y.
 
+CONFIG_ARCH_ANAKIN
+  The Anakin is a StrongArm based SA110 - 2 DIN Vehicle Telematics Platform.
+  64MB SDRAM - 4 Mb Flash - Compact Flash Interface - 1 MB VRAM
+
+  On board peripherals:
+        * Front display: 400x234 16 bit TFT touchscreen
+        * External independent second screen interface
+        * CAN controller SJA1000
+        * USB host controller
+        * 6 channel video codec with hardware overlay
+        * Smartcard reader
+        * IrDa
+
+  Modules interfaced over the Multi Media Extension slots:
+        * A communication card
+                Wavecom GPRS modem
+                uBlock GPS
+                Bosch DAB module
+        * An audio card ( 4 * 40W, AC97 Codec, I2S)
+
 CONFIG_ARCH_CAMELOT
   This enables support for Altera's Excalibur XA10 development board.
   If you would like to build your kernel to run on one of these boards
@@ -453,6 +496,12 @@
   want), say M here and read <file:Documentation/modules.txt>.  The
   module will be called isdn.o. If unsure, say N.
 
+CONFIG_ARCH_ARCA5K
+  This selects what ARM system you wish to build the kernel for. It
+  also selects to some extent the CPU type. If you are unsure what
+  to set this option to, please consult any information supplied with
+  your system.
+
 CONFIG_ARCH_A5K
   Say Y here to to support the Acorn A5000.  Linux can support the
   internal IDE disk and CD-ROM interface, serial and parallel port,
@@ -465,6 +514,16 @@
   floppy disks.  Picture and more detailed specifications at
   <http://www.computingmuseum.com/museum/archi.htm>.
 
+CONFIG_ARCH_EBSA110
+  This is an evaluation board for the StrongARM processor available
+  from Digital. It has limited hardware on-board, including an onboard
+  Ethernet interface, two PCMCIA sockets, two serial ports and a
+  parallel port.
+
+CONFIG_ARCH_RPC
+  On the Acorn Risc-PC, Linux can support the internal IDE disk and
+  CD-ROM interface, serial and parallel port, and the floppy drive.
+
 CONFIG_PAGESIZE_16
   Say Y here if your Archimedes or A5000 system has only 2MB of
   memory, otherwise say N.  The resulting kernel will not run on a
@@ -486,6 +545,16 @@
   in host ("central function") mode.
 
   Saying N will reduce the size of the Footbridge kernel.
+
+CONFIG_ARCH_L7200
+  Say Y here if you intend to run this kernel on a LinkUp Systems
+  L7200 Software Development Board which uses an ARM720T processor.
+  Information on this board can be obtained at:
+
+  <http://www.linkupsys.com/>
+
+  If you have any questions or comments about the Linux kernel port
+  to this board, send e-mail to sjhill@cotw.com.
 
 CONFIG_ARCH_NETWINDER
   Say Y here if you intend to run this kernel on the Rebel.COM
diff -urN linux-2.5.3-pre5/arch/cris/Config.help linux/arch/cris/Config.help
--- linux-2.5.3-pre5/arch/cris/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/cris/Config.help	Mon Jan 28 13:46:19 2002
@@ -196,6 +196,12 @@
   want), say M here and read <file:Documentation/modules.txt>.  The
   module will be called isdn.o. If unsure, say N.
 
+CONFIG_ETRAX100LX
+  Support version 1 of the Etrax 100LX.
+
+CONFIG_ETRAX100LX_V2
+  Support version 2 of the Etrax 100LX.
+
 CONFIG_SVINTO_SIM
   Support the xsim ETRAX Simulator.
 
@@ -205,6 +211,34 @@
 CONFIG_ETRAX_FLASH_BUSWIDTH
   Width in bytes of the Flash bus (1, 2 or 4). Is usually 2.
 
+CONFIG_ETRAX_PA_LEDS
+  The Etrax network driver is responsible for flashing LED's when
+  packets arrive and are sent.  It uses macros defined in
+  <file:include/asm-cris/io.h>, and those macros are defined after what
+  YOU choose in this option.  The actual bits used are configured
+  separately.  Select this if the LEDs are on port PA.  Some products
+  put the leds on PB or a memory-mapped latch (CSP0) instead.
+
+CONFIG_ETRAX_PB_LEDS
+  The Etrax network driver is responsible for flashing LED's when
+  packets arrive and are sent.  It uses macros defined in
+  <file:include/asm-cris/io.h>, and those macros are defined after what
+  YOU choose in this option.  The actual bits used are configured
+  separately.  Select this if the LEDs are on port PB.  Some products
+  put the leds on PA or a memory-mapped latch (CSP0) instead.
+
+CONFIG_ETRAX_CSP0_LEDS
+  The Etrax network driver is responsible for flashing LED's when
+  packets arrive and are sent. It uses macros defined in
+  <file:include/asm-cris/io.h>, and those macros are defined after what
+  YOU choose in this option.  The actual bits used are configured
+  separately.  Select this if the LEDs are on a memory-mapped latch
+  using chip select CSP0, this is mapped at 0x90000000.
+  Some products put the leds on PA or PB instead.
+
+CONFIG_ETRAX_NO_LEDS
+  Select this option if you don't have any LED at all.
+
 CONFIG_ETRAX_LED1G
   Bit to use for the first green LED.
   Most Axis products use bit 2 here.
@@ -381,4 +415,33 @@
 CONFIG_ETRAX_WATCHDOG
   Enable the built-in watchdog timer support on Etrax100 embedded
   network computers.
+
+CONFIG_ETRAX_DEBUG_PORT0
+  Choose a serial port for the ETRAX debug console.  Default to
+  port 0.
+
+CONFIG_ETRAX_DEBUG_PORT1
+  Use serial port 1 for the console.
+
+CONFIG_ETRAX_DEBUG_PORT2
+  Use serial port 2 for the console.
+
+CONFIG_ETRAX_DEBUG_PORT3
+  Use serial port 3 for the console.
+
+CONFIG_ETRAX_DEBUG_PORT_NULL
+  Disable serial-port debugging.
+
+CONFIG_ETRAX_RESCUE_SER0
+  Select one of the four serial ports as a rescue port.  The default
+  is port 0.
+
+CONFIG_ETRAX_RESCUE_SER1
+  Use serial port 1 as the rescue port.
+
+CONFIG_ETRAX_RESCUE_SER2
+  Use serial port 2 as the rescue port.
+
+CONFIG_ETRAX_RESCUE_SER3
+  Use serial port 3 as the rescue port.
 
diff -urN linux-2.5.3-pre5/arch/i386/Config.help linux/arch/i386/Config.help
--- linux-2.5.3-pre5/arch/i386/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/i386/Config.help	Mon Jan 28 13:46:20 2002
@@ -188,6 +188,20 @@
   information about which PCI hardware does work under Linux and which
   doesn't.
 
+CONFIG_PCI_GOBIOS
+  On PCI systems, the BIOS can be used to detect the PCI devices and
+  determine their configuration. However, some old PCI motherboards
+  have BIOS bugs and may crash if this is done. Also, some embedded
+  PCI-based systems don't have any BIOS at all. Linux can also try to
+  detect the PCI hardware directly without using the BIOS.
+
+  With this option, you can specify how Linux should detect the PCI
+  devices. If you choose "BIOS", the BIOS will be used, if you choose
+  "Direct", the BIOS won't be used, and if you choose "Any", the
+  kernel will try the direct access method and falls back to the BIOS
+  if that doesn't work. If unsure, go with the default, which is
+  "Any".
+
 CONFIG_HOTPLUG_PCI
   Say Y here if you have a motherboard with a PCI Hotplug controller.
   This allows you to add and remove PCI cards while the machine is
@@ -263,6 +277,29 @@
   and ds.o.  If you want to compile it as a module, say M here and
   read <file:Documentation/modules.txt>.
 
+CONFIG_KCORE_ELF
+  If you enabled support for /proc file system then the file
+  /proc/kcore will contain the kernel core image. This can be used
+  in gdb:
+
+  $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
+
+  You have two choices here: ELF and A.OUT. Selecting ELF will make
+  /proc/kcore appear in ELF core format as defined by the Executable
+  and Linking Format specification. Selecting A.OUT will choose the
+  old "a.out" format which may be necessary for some old versions
+  of binutils or on some architectures.
+
+  This is especially useful if you have compiled the kernel with the
+  "-g" option to preserve debugging information. It is mainly used
+  for examining kernel data structures on the live kernel so if you
+  don't understand what this means or are not a kernel hacker, just
+  leave it at its default value ELF.
+
+CONFIG_KCORE_AOUT
+  Not necessary unless you're using a very out-of-date binutils
+  version.  You probably want KCORE_ELF.
+
 CONFIG_BINFMT_ELF
   ELF (Executable and Linkable Format) is a format for libraries and
   executables used across different architectures and operating
@@ -332,6 +369,55 @@
   You may say M here for module support and later load the module when
   you have use for it; the module is called binfmt_misc.o. If you
   don't know what to answer at this point, say Y.
+
+CONFIG_M386
+  This is the processor type of your CPU. This information is used for
+  optimizing purposes. In order to compile a kernel that can run on
+  all x86 CPU types (albeit not optimally fast), you can specify
+  "386" here.
+
+  The kernel will not necessarily run on earlier architectures than
+  the one you have chosen, e.g. a Pentium optimized kernel will run on
+  a PPro, but not necessarily on a i486.
+
+  Here are the settings recommended for greatest speed:
+   - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI
+     486DLC/DLC2, UMC 486SX-S and NexGen Nx586.  Only "386" kernels
+     will run on a 386 class machine.
+   - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or
+     SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S.
+   - "586" for generic Pentium CPUs, possibly lacking the TSC
+     (time stamp counter) register.
+   - "Pentium-Classic" for the Intel Pentium.
+   - "Pentium-MMX" for the Intel Pentium MMX.
+   - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II.
+   - "Pentium-III" for the Intel Pentium III
+     and Celerons based on the Coppermine core.
+   - "Pentium-4" for the Intel Pentium 4.
+   - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
+   - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
+   - "Crusoe" for the Transmeta Crusoe series.
+   - "Winchip-C6" for original IDT Winchip.
+   - "Winchip-2" for IDT Winchip 2.
+   - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
+   - "CyrixIII" for VIA Cyrix III or VIA C3.
+
+  If you don't know what to do, choose "386".
+
+CONFIG_M486
+  Select this for a x486 processor, ether Intel or one of the
+  compatible processors from AMD, Cyrix, IBM, or Intel.  Includes DX,
+  DX2, and DX4 variants; also SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or
+  U5S.
+
+CONFIG_M586
+  Select this for an x586 or x686 processor such as the AMD K5, the
+  Intel 5x86 or 6x86, or the Intel 6x86MX.  This choice does not
+  assume the RDTSC instruction.
+
+CONFIG_M586TSC
+  Select this for a Pentium Classic processor with the RDTSC (Read
+  Time Stamp Counter) instruction for benchmarking.
 
 CONFIG_VGA_CONSOLE
   Saying Y here will allow you to use Linux in text mode through a
diff -urN linux-2.5.3-pre5/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.5.3-pre5/arch/i386/defconfig	Mon Jan 28 13:46:15 2002
+++ linux/arch/i386/defconfig	Mon Jan 28 13:46:20 2002
@@ -70,6 +70,10 @@
 CONFIG_SMP=y
 # CONFIG_MULTIQUAD is not set
 CONFIG_HAVE_DEC_LOCK=y
+
+#
+# General options
+#
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_LOCAL_APIC=y
 CONFIG_PCI=y
diff -urN linux-2.5.3-pre5/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- linux-2.5.3-pre5/arch/i386/kernel/apic.c	Mon Jan 28 13:46:15 2002
+++ linux/arch/i386/kernel/apic.c	Mon Jan 28 13:46:20 2002
@@ -88,8 +88,12 @@
 		apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
 	if (maxlvt >= 4)
 		apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
-	apic_write(APIC_ESR, 0);
-	v = apic_read(APIC_ESR);
+	v = GET_APIC_VERSION(apic_read(APIC_LVR));
+	if (APIC_INTEGRATED(v)) {	/* !82489DX */
+		if (maxlvt > 3)
+			apic_write(APIC_ESR, 0);
+		apic_read(APIC_ESR);
+	}
 }
 
 void __init connect_bsp_APIC(void)
@@ -916,6 +920,26 @@
 
 	/* and update all other cpus */
 	smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1);
+}
+
+void __init disable_APIC_timer(void)
+{
+	if (using_apic_timer) {
+		unsigned long v;
+
+		v = apic_read(APIC_LVTT);
+		apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
+	}
+}
+
+void enable_APIC_timer(void)
+{
+	if (using_apic_timer) {
+		unsigned long v;
+
+		v = apic_read(APIC_LVTT);
+		apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
+	}
 }
 
 /*
diff -urN linux-2.5.3-pre5/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- linux-2.5.3-pre5/arch/i386/kernel/entry.S	Thu Dec 27 08:44:30 2001
+++ linux/arch/i386/kernel/entry.S	Mon Jan 28 13:46:20 2002
@@ -77,7 +77,7 @@
 exec_domain	= 16
 need_resched	= 20
 tsk_ptrace	= 24
-processor	= 52
+cpu		= 32
 
 ENOSYS = 38
 
diff -urN linux-2.5.3-pre5/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- linux-2.5.3-pre5/arch/i386/kernel/mtrr.c	Fri Nov 30 08:26:04 2001
+++ linux/arch/i386/kernel/mtrr.c	Mon Jan 28 13:46:20 2002
@@ -378,10 +378,8 @@
 static int arr3_protected;
 
 /*  Put the processor into a state where MTRRs can be safely set  */
-static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
+static void set_mtrr_prepare_save (struct set_mtrr_context *ctxt)
 {
-    unsigned long tmp;
-
     /*  Disable interrupts locally  */
     __save_flags (ctxt->flags); __cli ();
 
@@ -404,16 +402,27 @@
     }
 
     if ( mtrr_if == MTRR_IF_INTEL ) {
-	/*  Disable MTRRs, and set the default type to uncached  */
+	/*  Save MTRR state */
 	rdmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
+    } else {
+	/* Cyrix ARRs - everything else were excluded at the top */
+	ctxt->ccr3 = getCx86 (CX86_CCR3);
+    }
+}   /*  End Function set_mtrr_prepare_save  */
+
+static void set_mtrr_cache_disable (struct set_mtrr_context *ctxt)
+{
+    if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR )
+	 return;
+
+    if ( mtrr_if == MTRR_IF_INTEL ) {
+	/*  Disable MTRRs, and set the default type to uncached  */
 	wrmsr (MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
     } else {
 	/* Cyrix ARRs - everything else were excluded at the top */
-	tmp = getCx86 (CX86_CCR3);
-	setCx86 (CX86_CCR3, (tmp & 0x0f) | 0x10);
-	ctxt->ccr3 = tmp;
+	setCx86 (CX86_CCR3, (ctxt->ccr3 & 0x0f) | 0x10);
     }
-}   /*  End Function set_mtrr_prepare  */
+}   /*  End Function set_mtrr_cache_disable  */
 
 /*  Restore the processor after a set_mtrr_prepare  */
 static void set_mtrr_done (struct set_mtrr_context *ctxt)
@@ -674,7 +683,10 @@
 {
     struct set_mtrr_context ctxt;
 
-    if (do_safe) set_mtrr_prepare (&ctxt);
+    if (do_safe) {
+	set_mtrr_prepare_save (&ctxt);
+	set_mtrr_cache_disable (&ctxt);
+	}
     if (size == 0)
     {
 	/* The invalid bit is kept in the mask, so we simply clear the
@@ -726,7 +738,10 @@
 	}
     }
 
-    if (do_safe) set_mtrr_prepare (&ctxt);
+    if (do_safe) {
+	set_mtrr_prepare_save (&ctxt);
+	set_mtrr_cache_disable (&ctxt);
+    }
     base <<= PAGE_SHIFT;
     setCx86(arr,    ((unsigned char *) &base)[3]);
     setCx86(arr+1,  ((unsigned char *) &base)[2]);
@@ -750,7 +765,10 @@
     u32 regs[2];
     struct set_mtrr_context ctxt;
 
-    if (do_safe) set_mtrr_prepare (&ctxt);
+    if (do_safe) {
+	set_mtrr_prepare_save (&ctxt);
+	set_mtrr_cache_disable (&ctxt);
+    }
     /*
      *	Low is MTRR0 , High MTRR 1
      */
@@ -788,7 +806,10 @@
     struct set_mtrr_context ctxt;
     unsigned long low, high;
 
-    if (do_safe) set_mtrr_prepare( &ctxt );
+    if (do_safe) {
+	set_mtrr_prepare_save (&ctxt);
+	set_mtrr_cache_disable (&ctxt);
+    }
     if (size == 0)
     {
         /*  Disable  */
@@ -985,6 +1006,7 @@
 
 
 static atomic_t undone_count;
+static volatile int wait_barrier_cache_disable = FALSE;
 static volatile int wait_barrier_execute = FALSE;
 static volatile int wait_barrier_cache_enable = FALSE;
 
@@ -1003,18 +1025,21 @@
 {
     struct set_mtrr_data *data = info;
     struct set_mtrr_context ctxt;
-
-    set_mtrr_prepare (&ctxt);
+    set_mtrr_prepare_save (&ctxt);
     /*  Notify master that I've flushed and disabled my cache  */
     atomic_dec (&undone_count);
-    while (wait_barrier_execute) barrier ();
+    while (wait_barrier_cache_disable) { rep_nop(); barrier(); }
+    set_mtrr_cache_disable (&ctxt);
+    /*  Notify master that I've flushed and disabled my cache  */
+    atomic_dec (&undone_count);
+    while (wait_barrier_execute) { rep_nop(); barrier(); }
     /*  The master has cleared me to execute  */
     (*set_mtrr_up) (data->smp_reg, data->smp_base, data->smp_size,
 		    data->smp_type, FALSE);
     /*  Notify master CPU that I've executed the function  */
     atomic_dec (&undone_count);
     /*  Wait for master to clear me to enable cache and return  */
-    while (wait_barrier_cache_enable) barrier ();
+    while (wait_barrier_cache_enable) { rep_nop(); barrier(); }
     set_mtrr_done (&ctxt);
 }   /*  End Function ipi_handler  */
 
@@ -1028,6 +1053,7 @@
     data.smp_base = base;
     data.smp_size = size;
     data.smp_type = type;
+    wait_barrier_cache_disable = TRUE;
     wait_barrier_execute = TRUE;
     wait_barrier_cache_enable = TRUE;
     atomic_set (&undone_count, smp_num_cpus - 1);
@@ -1035,15 +1061,22 @@
     if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
 	panic ("mtrr: timed out waiting for other CPUs\n");
     /* Flush and disable the local CPU's cache */
-    set_mtrr_prepare (&ctxt);
+    set_mtrr_prepare_save (&ctxt);
+    /*  Wait for all other CPUs to flush and disable their caches  */
+    while (atomic_read (&undone_count) > 0) { rep_nop(); barrier(); }
+    /* Set up for completion wait and then release other CPUs to change MTRRs*/
+    atomic_set (&undone_count, smp_num_cpus - 1);
+    wait_barrier_cache_disable = FALSE;
+    set_mtrr_cache_disable (&ctxt);
+
     /*  Wait for all other CPUs to flush and disable their caches  */
-    while (atomic_read (&undone_count) > 0) barrier ();
+    while (atomic_read (&undone_count) > 0) { rep_nop(); barrier(); }
     /* Set up for completion wait and then release other CPUs to change MTRRs*/
     atomic_set (&undone_count, smp_num_cpus - 1);
     wait_barrier_execute = FALSE;
     (*set_mtrr_up) (reg, base, size, type, FALSE);
     /*  Now wait for other CPUs to complete the function  */
-    while (atomic_read (&undone_count) > 0) barrier ();
+    while (atomic_read (&undone_count) > 0) { rep_nop(); barrier(); }
     /*  Now all CPUs should have finished the function. Release the barrier to
 	allow them to re-enable their caches and return from their interrupt,
 	then enable the local cache and return  */
@@ -1887,7 +1920,9 @@
     struct set_mtrr_context ctxt;
     int i;
 
-    set_mtrr_prepare (&ctxt); /* flush cache and enable MAPEN */
+    /* flush cache and enable MAPEN */
+    set_mtrr_prepare_save (&ctxt);
+    set_mtrr_cache_disable (&ctxt);
 
      /* the CCRs are not contiguous */
     for(i=0; i<4; i++) setCx86(CX86_CCR0 + i, ccr_state[i]);
@@ -1924,7 +1959,9 @@
     int i;
 #endif
 
-    set_mtrr_prepare (&ctxt); /* flush cache and enable MAPEN */
+    /* flush cache and enable MAPEN */
+    set_mtrr_prepare_save (&ctxt);
+    set_mtrr_cache_disable (&ctxt);
 
     /* Save all CCRs locally */
     ccr[0] = getCx86 (CX86_CCR0);
@@ -2073,7 +2110,8 @@
 {
     struct set_mtrr_context ctxt;
 
-    set_mtrr_prepare (&ctxt);
+    set_mtrr_prepare_save (&ctxt);
+    set_mtrr_cache_disable (&ctxt);
 
     if(boot_cpu_data.x86_model==4)
     	centaur_mcr0_init();
@@ -2190,7 +2228,8 @@
     /*  Note that this is not ideal, since the cache is only flushed/disabled
 	for this CPU while the MTRRs are changed, but changing this requires
 	more invasive changes to the way the kernel boots  */
-    set_mtrr_prepare (&ctxt);
+    set_mtrr_prepare_save (&ctxt);
+    set_mtrr_cache_disable (&ctxt);
     mask = set_mtrr_state (&smp_mtrr_state, &ctxt);
     set_mtrr_done (&ctxt);
     /*  Use the atomic bitops to update the global mask  */
diff -urN linux-2.5.3-pre5/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- linux-2.5.3-pre5/arch/i386/kernel/process.c	Mon Jan 28 13:46:15 2002
+++ linux/arch/i386/kernel/process.c	Mon Jan 28 13:46:20 2002
@@ -689,15 +689,17 @@
 	asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->gs));
 
 	/*
-	 * Restore %fs and %gs.
+	 * Restore %fs and %gs if needed.
 	 */
-	loadsegment(fs, next->fs);
-	loadsegment(gs, next->gs);
+	if (unlikely(prev->fs | prev->gs | next->fs | next->gs)) {
+		loadsegment(fs, next->fs);
+		loadsegment(gs, next->gs);
+	}
 
 	/*
 	 * Now maybe reload the debug registers
 	 */
-	if (next->debugreg[7]){
+	if (unlikely(next->debugreg[7])) {
 		loaddebug(next, 0);
 		loaddebug(next, 1);
 		loaddebug(next, 2);
@@ -707,7 +709,7 @@
 		loaddebug(next, 7);
 	}
 
-	if (prev->ioperm || next->ioperm) {
+	if (unlikely(prev->ioperm || next->ioperm)) {
 		if (next->ioperm) {
 			/*
 			 * 4 cachelines copy ... not good, but not that
diff -urN linux-2.5.3-pre5/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.5.3-pre5/arch/i386/kernel/setup.c	Mon Jan 28 13:46:15 2002
+++ linux/arch/i386/kernel/setup.c	Mon Jan 28 13:46:20 2002
@@ -2803,9 +2803,10 @@
 	load_TR(nr);
 	load_LDT(&init_mm);
 
-	/*
-	 * Clear all 6 debug registers:
-	 */
+	/* Clear %fs and %gs. */
+	asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
+
+	/* Clear all 6 debug registers: */
 
 #define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) );
 
diff -urN linux-2.5.3-pre5/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- linux-2.5.3-pre5/arch/i386/kernel/smpboot.c	Mon Jan 28 13:46:15 2002
+++ linux/arch/i386/kernel/smpboot.c	Mon Jan 28 13:46:20 2002
@@ -435,6 +435,7 @@
 	 */
  	smp_store_cpu_info(cpuid);
 
+	disable_APIC_timer();
 	/*
 	 * Allow the master to continue.
 	 */
@@ -462,16 +463,15 @@
 	 * things done here to the most necessary things.
 	 */
 	cpu_init();
-	init_idle();
 	smp_callin();
 	while (!atomic_read(&smp_commenced))
 		rep_nop();
+	enable_APIC_timer();
 	/*
 	 * low-memory mappings have been cleared, flush them from
 	 * the local TLBs too.
 	 */
 	local_flush_tlb();
-	idle_startup_done();
 
 	return cpu_idle();
 }
@@ -805,7 +805,7 @@
 	if (!idle)
 		panic("No idle process for CPU %d", cpu);
 
-	idle->cpu = cpu;
+	init_idle(idle, cpu);
 
 	map_cpu_to_boot_apicid(cpu, apicid);
 
@@ -924,6 +924,7 @@
 }
 
 cycles_t cacheflush_time;
+unsigned long cache_decay_ticks;
 
 static void smp_tune_scheduling (void)
 {
@@ -957,9 +958,13 @@
 		cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth;
 	}
 
+	cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000;
+
 	printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
 		(long)cacheflush_time/(cpu_khz/1000),
 		((long)cacheflush_time*100/(cpu_khz/1000)) % 100);
+	printk("task migration cache decay timeout: %ld msecs.\n",
+		(cache_decay_ticks + 1) * 1000 / HZ);
 }
 
 /*
diff -urN linux-2.5.3-pre5/arch/ia64/Config.help linux/arch/ia64/Config.help
--- linux-2.5.3-pre5/arch/ia64/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/ia64/Config.help	Mon Jan 28 13:46:20 2002
@@ -449,6 +449,45 @@
   want), say M here and read <file:Documentation/modules.txt>.  The
   module will be called isdn.o. If unsure, say N.
 
+CONFIG_ITANIUM
+  Select your IA64 processor type.  The default is Intel Itanium.
+
+CONFIG_MCKINLEY
+  Select this to configure for a McKinley processor.
+
+CONFIG_IA64_GENERIC
+  This selects the system type of your hardware.  A "generic" kernel
+  will run on any supported IA-64 system.  However, if you configure
+  a kernel for your specific system, it will be faster and smaller.
+
+  To find out what type of IA-64 system you have, you may want to
+  check the IA-64 Linux web site at <http://www.linux-ia64.org/>.
+  As of the time of this writing, most hardware is DIG compliant,
+  so the "DIG-compliant" option is usually the right choice.
+
+  HP-simulator   For the HP simulator
+                 (<http://software.hp.com/ia64linux/>).
+  SN1-simulator  For the SGI SN1 simulator.
+  DIG-compliant  For DIG ("Developer's Interface Guide") compliant
+                 system.
+
+  If you don't know what to do, choose "generic".
+
+CONFIG_IA64_PAGE_SIZE_4KB
+  This lets you select the page size of the kernel.  For best IA-64
+  performance, a page size of 8KB or 16KB is recommended.  For best
+  IA-32 compatibility, a page size of 4KB should be selected (the vast
+  majority of IA-32 binaries work perfectly fine with a larger page
+  size).  For Itanium systems, do NOT chose a page size larger than
+  16KB.
+
+  4KB                For best IA-32 compatibility
+  8KB                For best IA-64 performance
+  16KB               For best IA-64 performance
+  64KB               Not for Itanium.
+
+  If you don't know what to do, choose 8KB.
+
 CONFIG_ITANIUM_BSTEP_SPECIFIC
   Select this option to build a kernel for an Itanium prototype system
   with a B-step CPU.  You have a B-step CPU if the "revision" field in
diff -urN linux-2.5.3-pre5/arch/m68k/Config.help linux/arch/m68k/Config.help
--- linux-2.5.3-pre5/arch/m68k/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/m68k/Config.help	Mon Jan 28 13:46:20 2002
@@ -143,6 +143,29 @@
   and ds.o.  If you want to compile it as a module, say M here and
   read <file:Documentation/modules.txt>.
 
+CONFIG_KCORE_ELF
+  If you enabled support for /proc file system then the file
+  /proc/kcore will contain the kernel core image. This can be used
+  in gdb:
+
+  $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
+
+  You have two choices here: ELF and A.OUT. Selecting ELF will make
+  /proc/kcore appear in ELF core format as defined by the Executable
+  and Linking Format specification. Selecting A.OUT will choose the
+  old "a.out" format which may be necessary for some old versions
+  of binutils or on some architectures.
+
+  This is especially useful if you have compiled the kernel with the
+  "-g" option to preserve debugging information. It is mainly used
+  for examining kernel data structures on the live kernel so if you
+  don't understand what this means or are not a kernel hacker, just
+  leave it at its default value ELF.
+
+CONFIG_KCORE_AOUT
+  Not necessary unless you're using a very out-of-date binutils
+  version.  You probably want KCORE_ELF.
+
 CONFIG_BINFMT_ELF
   ELF (Executable and Linkable Format) is a format for libraries and
   executables used across different architectures and operating
@@ -980,6 +1003,28 @@
   inserted in and removed from the running kernel whenever you want).
   The module will be called busmouse.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
+
+CONFIG_WATCHDOG
+  If you say Y here (and to one of the following options) and create a
+  character special file /dev/watchdog with major number 10 and minor
+  number 130 using mknod ("man mknod"), you will get a watchdog, i.e.:
+  subsequently opening the file and then failing to write to it for
+  longer than 1 minute will result in rebooting the machine. This
+  could be useful for a networked machine that needs to come back
+  online as fast as possible after a lock-up. There's both a watchdog
+  implementation entirely in software (which can sometimes fail to
+  reboot the machine) and a driver for hardware watchdog boards, which
+  are more robust and can also keep track of the temperature inside
+  your computer. For details, read <file:Documentation/watchdog.txt>
+  in the kernel source.
+
+  The watchdog is usually used together with the watchdog daemon
+  which is available from
+  <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
+  also monitor NFS connections and can reboot the machine when the process
+  table is full.
+
+  If unsure, say N.
 
 CONFIG_WATCHDOG_NOWAYOUT
   The default watchdog behaviour (which you get if you say N here) is
diff -urN linux-2.5.3-pre5/arch/ppc/8xx_io/Config.help linux/arch/ppc/8xx_io/Config.help
--- linux-2.5.3-pre5/arch/ppc/8xx_io/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/ppc/8xx_io/Config.help	Mon Jan 28 13:46:20 2002
@@ -12,6 +12,16 @@
   Enable Ethernet support via the Motorola MPC8xx serial
   commmunications controller.
 
+CONFIG_SCC1_ENET
+  Use MPC8xx serial communications controller 1 to drive Ethernet
+  (default).
+
+CONFIG_SCC2_ENET
+  Use MPC8xx serial communications controller 2 to drive Ethernet.
+
+CONFIG_SCC3_ENET
+  Use MPC8xx serial communications controller 3 to drive Ethernet.
+
 CONFIG_ENET_BIG_BUFFERS
   Allocate large buffers for MPC8xx Etherenet.  Increases throughput
   and decreases the likelihood of dropped packets, but costs memory.
diff -urN linux-2.5.3-pre5/arch/ppc/Config.help linux/arch/ppc/Config.help
--- linux-2.5.3-pre5/arch/ppc/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/ppc/Config.help	Mon Jan 28 13:46:20 2002
@@ -668,6 +668,17 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.
 
+CONFIG_6xx
+  There are four types of PowerPC chips supported.  The more common
+  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
+  versions (821, 823, 850, 855, 860, 8260), the IBM embedded versions
+  (403 and 405) and the high end 64 bit Power processors (Power 3,
+  Power 4).  Unless you are building a kernel for one of the embedded
+  processor systems, or a 64 bit IBM RS/6000, choose 6xx.  Note that
+  the kernel runs in 32-bit mode even on 64-bit chips.  Also note that
+  because the 82xx family has a 603e core, specific support for that
+  chipset is asked later on.
+
 CONFIG_8260
   The MPC8260 CPM (Communications Processor Module) is a typical
   embedded CPU made by Motorola.  Selecting this option means that
@@ -676,6 +687,17 @@
 
   If in doubt, say N.
 
+CONFIG_OAK
+  Select Oak if you have an IBM 403GCX "Oak" Evaluation Board.
+
+  Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board.
+
+  More information on these boards is available at:
+  <http://www.chips.ibm.com/products/powerpc/tools/evk_pn.html#GCX>.
+
+CONFIG_WALNUT
+  Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board.
+
 CONFIG_PPC601_SYNC_FIX
   Some versions of the PPC601 (the first PowerPC chip) have bugs which
   mean that extra synchronization instructions are required near
@@ -706,6 +728,16 @@
   Select APUS if configuring for a PowerUP Amiga.  More information is
   available at: <http://linux-apus.sourceforge.net/>.
 
+CONFIG_GEMINI
+  Select Gemini if configuring for a Synergy Microsystems' Gemini
+  series Single Board Computer.  More information is available at:
+  <http://www.synergymicro.com/PressRel/97_10_15.html>.
+
+CONFIG_APUS
+  Select APUS if configuring for a PowerUP Amiga.
+  More information is available at:
+  <http://linux-apus.sourceforge.net/>.
+
 CONFIG_ALTIVEC
   This option enables kernel support for the Altivec extensions to the
   PowerPC processor. The kernel currently supports saving and restoring
@@ -770,6 +802,178 @@
   on and off appropriately on power-management and lid-open/lid-closed
   events; also, the PowerBook button device will be enabled so you can
   change the screen brightness.
+
+CONFIG_RPXLITE
+  Single-board computers based around the PowerPC MPC8xx chips and
+  intended for embedded applications.  The following types are
+  supported:
+
+  RPX-Lite:
+    Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
+
+  RPX-Classic:
+    Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on 
+    the MPC 860
+
+  BSE-IP: 
+    Bright Star Engineering ip-Engine.
+
+  TQM823L:
+  TQM850L:
+  TQM855L:
+  TQM860L:
+    MPC8xx based family of mini modules, half credit card size,
+    up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
+    2 x CAN bus interface, ...
+      Manufacturer: TQ Components, www.tq-group.de
+      Date of Release: October (?) 1999
+      End of Life: not yet :-)
+      URL:
+      - module: <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>
+      - starter kit: <http://www.denx.de/PDF/STK8xxLHWM201.pdf>
+      - images: <http://www.denx.de/embedded-ppc-en.html>
+
+  FPS850L:
+    FingerPrint Sensor System (based on TQM850L)
+      Manufacturer: IKENDI AG, <http://www.ikendi.com/>
+      Date of Release: November 1999
+      End of life: end 2000 ?
+      URL: see TQM850L
+
+  SPD823TS:
+    MPC823 based board used in the "Tele Server" product
+    Manufacturer: Speech Design, <http://www.speech-design.de/>
+    Date of Release: Mid 2000 (?)
+    End of life: -
+    URL: <http://www.speech-design.de/>
+         select "English", then "Teleteam Solutions", then "TeleServer"
+
+  IVMS8:
+    MPC860 based board used in the "Integrated Voice Mail System",
+    Small Version (8 voice channels)
+    Manufacturer: Speech Design, <http://www.speech-design.de/>
+    Date of Release: December 2000 (?)
+    End of life: -
+    URL: <http://www.speech-design.de/>
+
+  IVML24:
+    MPC860 based board used in the "Integrated Voice Mail System", 
+    Large Version (24 voice channels)
+    Manufacturer: Speech Design, <http://www.speech-design.de/>
+    Date of Release: March 2001  (?)
+    End of life: -
+    URL: <http://www.speech-design.de/>
+
+  SM850:
+    Service Module (based on TQM850L)
+    Manufacturer: Dependable Computer Systems, <http://www.decomsys.com/>
+    Date of Release: end 2000 (?)
+    End of life: mid 2001 (?)
+    URL: <http://www.tz-mikroelektronik.de/ServiceModule/index.html>
+
+  HERMES:
+    Hermes-Pro ISDN/LAN router with integrated 8 x hub
+    Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik
+      <http://www.multidata.de/>
+    Date of Release: 2000 (?)
+    End of life: -
+    URL: <http://www.multidata.de/english/products/hpro.htm>
+
+  IP860:	
+    VMEBus IP (Industry Pack) carrier board with MPC860
+    Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+    Date of Release: ?
+    End of life: -
+    URL: <http://www.microsys.de/html/ip860.html>
+
+  PCU_E:
+    PCU = Peripheral Controller Unit, Extended
+    Manufacturer: Siemens AG, ICN (Information and Communication Networks)
+    	<http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
+    Date of Release: April 2001
+    End of life: August 2001
+    URL: n. a.
+
+CONFIG_RPXCLASSIC
+  The RPX-Classic is a single-board computer based on the Motorola
+  MPC860.  It features 16MB of DRAM and a variable amount of flash,
+  I2C EEPROM, thermal monitoring, a PCMCIA slot, a DIP switch and two
+  LEDs.  Variants with Ethernet ports exist.  Say Y here to support it
+  directly.
+
+CONFIG_BSEIP
+  Say Y here to support the Bright Star Engineering ipEngine SBC.
+  This is a credit-card-sized device featuring a MPC823 processor,
+  26MB DRAM, 4MB flash, Ethernet, a 16K-gate FPGA, USB, an LCD/video
+  controller, and two RS232 ports.
+
+CONFIG_TQM823L
+  Say Y here to support the TQM823L, one of an MPC8xx-based family of
+  mini SBCs (half credit-card size) from TQ Components first released
+  in late 1999.  Technical references are at
+  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+  <http://www.denx.de/embedded-ppc-en.html>.
+
+CONFIG_TQM850L
+  Say Y here to support the TQM850L, one of an MPC8xx-based family of
+  mini SBCs (half credit-card size) from TQ Components first released
+  in late 1999.  Technical references are at
+  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+  <http://www.denx.de/embedded-ppc-en.html>.
+
+CONFIG_TQM855L
+  Say Y here to support the TQM855L, one of an MPC8xx-based family of
+  mini SBCs (half credit-card size) from TQ Components first released
+  in late 1999.  Technical references are at
+  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+  <http://www.denx.de/embedded-ppc-en.html>.
+
+CONFIG_TQM860L
+  Say Y here to support the TQM860L, one of an MPC8xx-based family of
+  mini SBCs (half credit-card size) from TQ Components first released
+  in late 1999.  Technical references are at
+  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
+  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
+  <http://www.denx.de/embedded-ppc-en.html>.
+
+CONFIG_TQM860
+  Say Y here to support the TQM860, one of an MPC8xx-based family of
+  SBCs (credit-card size) from TQ Components first released in 
+  mid-1999 and discontinued mid-2000.
+
+CONFIG_SM850
+  Say Y here to support the Service Module 850 from Dependable
+  Computer Systems, an SBC based on the TQM850L module by TQ
+  Components.  This board is no longer in production.  The
+  manufacturer's website is at <http://www.decomsys.com/>.
+
+CONFIG_SPD823TS
+  Say Y here to support the Speech Design 823 Tele-Server from Speech
+  Design, released in 2000.  The manufacturer's website is at
+  <http://www.speech-design.de/>.
+
+CONFIG_IVMS8
+  Say Y here to support the Integrated Voice-Mail Small 8-channel SBC
+  from Speech Design, released March 2001.  The manufacturer's website
+  is at <http://www.speech-design.de/>.
+
+CONFIG_IVML24
+  Say Y here to support the Integrated Voice-Mail Large 24-channel SBC
+  from Speech Design, released March 2001.  The manufacturer's website
+  is at <http://www.speech-design.de/>.
+
+CONFIG_MBX
+  MBX is a line of Motorola single-board computer based around the
+  MPC821 and MPC860 processors, and intended for embedded-controller
+  applications.  Say Y here to support these boards directly.
+
+CONFIG_WINCEPT
+  The Wincept 100/110 is a Motorola single-board computer based on the
+  MPC821 PowerPC, introduced in 1998 and designed to be used in
+  thin-client machines.  Say Y to support it directly.
 
 CONFIG_EST8260
   EST8260:
diff -urN linux-2.5.3-pre5/arch/sh/Config.help linux/arch/sh/Config.help
--- linux-2.5.3-pre5/arch/sh/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/arch/sh/Config.help	Mon Jan 28 13:46:20 2002
@@ -82,6 +82,20 @@
   information about which PCI hardware does work under Linux and which
   doesn't.
 
+CONFIG_PCI_GOBIOS
+  On PCI systems, the BIOS can be used to detect the PCI devices and
+  determine their configuration. However, some old PCI motherboards
+  have BIOS bugs and may crash if this is done. Also, some embedded
+  PCI-based systems don't have any BIOS at all. Linux can also try to
+  detect the PCI hardware directly without using the BIOS.
+
+  With this option, you can specify how Linux should detect the PCI
+  devices. If you choose "BIOS", the BIOS will be used, if you choose
+  "Direct", the BIOS won't be used, and if you choose "Any", the
+  kernel will try the direct access method and falls back to the BIOS
+  if that doesn't work. If unsure, go with the default, which is
+  "Any".
+
 CONFIG_MCA
   MicroChannel Architecture is found in some IBM PS/2 machines and
   laptops.  It is a bus system similar to PCI or ISA. See
@@ -136,6 +150,29 @@
   and ds.o.  If you want to compile it as a module, say M here and
   read <file:Documentation/modules.txt>.
 
+CONFIG_KCORE_ELF
+  If you enabled support for /proc file system then the file
+  /proc/kcore will contain the kernel core image. This can be used
+  in gdb:
+
+  $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
+
+  You have two choices here: ELF and A.OUT. Selecting ELF will make
+  /proc/kcore appear in ELF core format as defined by the Executable
+  and Linking Format specification. Selecting A.OUT will choose the
+  old "a.out" format which may be necessary for some old versions
+  of binutils or on some architectures.
+
+  This is especially useful if you have compiled the kernel with the
+  "-g" option to preserve debugging information. It is mainly used
+  for examining kernel data structures on the live kernel so if you
+  don't understand what this means or are not a kernel hacker, just
+  leave it at its default value ELF.
+
+CONFIG_KCORE_AOUT
+  Not necessary unless you're using a very out-of-date binutils
+  version.  You probably want KCORE_ELF.
+
 CONFIG_BINFMT_ELF
   ELF (Executable and Linkable Format) is a format for libraries and
   executables used across different architectures and operating
@@ -658,6 +695,102 @@
   primary IDE drive (only tested for SanDisk).
 
   If in doubt, select 'N'.
+
+CONFIG_SH_GENERIC
+  Select Generic if configuring for a generic SuperH system.
+  The "generic" option compiles in *all* the possible hardware
+  support and relies on the sh_mv= kernel commandline option to choose
+  at runtime which routines to use.  "MV" stands for "machine vector";
+  each of the machines below is described by a machine vector.
+
+  Select SolutionEngine if configuring for a Hitachi SH7709
+  or SH7750/7750S evalutation board.
+
+  Select Overdrive if configuring for a ST407750 Overdrive board.
+  More information at
+  <http://linuxsh.sourceforge.net/docs/7750overdrive.php3>.
+
+  Select HP620 if configuring for a HP Jornada HP620.
+  More information (hardware only) at
+  <http://www.hp.com/jornada/>.
+
+  Select HP680 if configuring for a HP Jornada HP680.
+  More information (hardware only) at
+  <http://www.hp.com/jornada/products/680/>.
+
+  Select HP690 if configuring for a HP Jornada HP690.
+  More information (hardware only) at
+  <http://www.hp.com/jornada/products/680/>.
+
+  Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
+  More information at
+  <http://sources.redhat.com/ecos/hardware.html#SuperH>.
+
+  Select DMIDA if configuring for a DataMyte 4000 Industrial
+  Digital Assistant. More information at <http://www.dmida.com/>.
+
+  Select EC3104 if configuring for a system with an Eclipse
+  International EC3104 chip, e.g. the Harris AD2000 or Compaq Aero 8000.
+
+  Select Dreamcast if configuring for a SEGA Dreamcast.
+  More information at
+  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
+  Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+
+  Select BareCPU if you know what this means, and it applies
+  to your system.
+
+CONFIG_SH_SOLUTION_ENGINE
+  Select SolutionEngine if configuring for a Hitachi SH7709
+  or SH7750 evalutation board.
+
+CONFIG_SH_7751_SOLUTION_ENGINE
+  Select 7751 SolutionEngine if configuring for a Hitachi SH7751
+  evalutation board.
+
+CONFIG_SH_HP620
+  Select HP620 if configuring for a HP jornada HP620.
+  More information (hardware only) at
+  <http://www.hp.com/jornada/>.
+
+CONFIG_SH_HP680
+  Select HP680 if configuring for a HP Jornada HP680.
+  More information (hardware only) at
+  <http://www.hp.com/jornada/products/680/>.
+
+CONFIG_SH_HP690
+  Select HP690 if configuring for a HP Jornada HP690.
+  More information (hardware only)
+  at <http://www.hp.com/jornada/products/680/>.
+
+CONFIG_SH_CQREEK
+  Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
+  More information at
+  <http://sources.redhat.com/ecos/hardware.html#SuperH>.
+
+CONFIG_SH_DMIDA
+  Select DMIDA if configuring for a DataMyte 4000 Industrial
+  Digital Assistant. More information at <http://www.dmida.com/>.
+
+CONFIG_SH_EC3104
+  Select EC3104 if configuring for a system with an Eclipse
+  International EC3104 chip, e.g. the Harris AD2000.
+
+CONFIG_SH_DREAMCAST
+  Select Dreamcast if configuring for a SEGA Dreamcast.
+  More information at
+  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
+  Dreamcast project is at <http://linuxdc.sourceforge.net/>.
+
+CONFIG_SH_UNKNOWN
+  "Bare CPU" aka "unknown" means an SH-based system which is not one
+  of the specific ones mentioned above, which means you need to enter
+  all sorts of stuff like CONFIG_MEMORY_START because the config
+  system doesn't already know what it is.  You get a machine vector
+  without any platform-specific code in it, so things like the RTC may
+  not work.
+
+  This option is for the early stages of porting to a new machine.
 
 CONFIG_CPU_SUBTYPE_SH7707
   Select the type of SuperH processor you have. This information is
diff -urN linux-2.5.3-pre5/arch/sparc/config.in linux/arch/sparc/config.in
--- linux-2.5.3-pre5/arch/sparc/config.in	Mon Jan 28 13:46:15 2002
+++ linux/arch/sparc/config.in	Mon Jan 28 13:46:20 2002
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.112 2002/01/15 06:25:50 davem Exp $
+# $Id: config.in,v 1.113 2002/01/24 22:14:44 davem Exp $
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
diff -urN linux-2.5.3-pre5/arch/sparc/defconfig linux/arch/sparc/defconfig
--- linux-2.5.3-pre5/arch/sparc/defconfig	Mon Jan 28 13:46:15 2002
+++ linux/arch/sparc/defconfig	Mon Jan 28 13:46:20 2002
@@ -5,6 +5,14 @@
 CONFIG_HIGHMEM=y
 
 #
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
@@ -43,10 +51,6 @@
 # CONFIG_SUN4 is not set
 # CONFIG_PCI is not set
 CONFIG_SUN_OPENPROMFS=m
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
 CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
diff -urN linux-2.5.3-pre5/arch/sparc64/config.in linux/arch/sparc64/config.in
--- linux-2.5.3-pre5/arch/sparc64/config.in	Mon Jan 28 13:46:15 2002
+++ linux/arch/sparc64/config.in	Mon Jan 28 13:46:20 2002
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.157 2002/01/15 06:57:41 davem Exp $
+# $Id: config.in,v 1.158 2002/01/24 22:14:44 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
diff -urN linux-2.5.3-pre5/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.5.3-pre5/arch/sparc64/defconfig	Mon Jan 28 13:46:15 2002
+++ linux/arch/sparc64/defconfig	Mon Jan 28 13:46:20 2002
@@ -3,6 +3,14 @@
 #
 
 #
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
@@ -46,10 +54,6 @@
 CONFIG_RTC=y
 # CONFIG_PCI_NAMES is not set
 CONFIG_SUN_OPENPROMFS=m
-CONFIG_NET=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
 CONFIG_KCORE_ELF=y
 CONFIG_SPARC32_COMPAT=y
 CONFIG_BINFMT_ELF32=y
@@ -104,6 +108,7 @@
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 CONFIG_FB_SBUS=y
@@ -416,6 +421,7 @@
 #
 # CONFIG_IEEE1394_VIDEO1394 is not set
 CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
 # CONFIG_IEEE1394_VERBOSEDEBUG is not set
 
@@ -748,6 +754,7 @@
 # USB Host Controller Drivers
 #
 CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_OHCI_HCD is not set
 CONFIG_USB_UHCI=y
 # CONFIG_USB_UHCI_ALT is not set
 CONFIG_USB_OHCI=y
diff -urN linux-2.5.3-pre5/drivers/Makefile linux/drivers/Makefile
--- linux-2.5.3-pre5/drivers/Makefile	Sun Nov 11 10:09:32 2001
+++ linux/drivers/Makefile	Mon Jan 28 13:46:20 2002
@@ -10,7 +10,7 @@
 		message/i2o message/fusion scsi md ieee1394 pnp isdn atm \
 		fc4 net/hamradio i2c acpi bluetooth
 
-subdir-y :=	parport char block net sound misc media cdrom hotplug
+subdir-y :=	base parport char block net sound misc media cdrom hotplug
 subdir-m :=	$(subdir-y)
 
 
diff -urN linux-2.5.3-pre5/drivers/base/Makefile linux/drivers/base/Makefile
--- linux-2.5.3-pre5/drivers/base/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/base/Makefile	Mon Jan 28 13:46:20 2002
@@ -0,0 +1,7 @@
+O_TARGET	:= base.o
+
+obj-y		:= core.o interface.o fs.o
+
+export-objs	:= core.o interface.o fs.o 
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.5.3-pre5/drivers/base/core.c linux/drivers/base/core.c
--- linux-2.5.3-pre5/drivers/base/core.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/base/core.c	Mon Jan 28 13:46:20 2002
@@ -0,0 +1,212 @@
+/*
+ * drivers/base/core.c - core driver model code (device registration, etc)
+ * 
+ * Copyright (c) 2002 Patrick Mochel
+ *		 2002 Open Source Development Lab
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define DBG(x...) printk(x)
+#else
+# define DBG(x...)
+#endif
+
+static struct iobus device_root = {
+	bus_id: "root",
+	name:	"Logical System Root",
+};
+
+int (*platform_notify)(struct device * dev) = NULL;
+int (*platform_notify_remove)(struct device * dev) = NULL;
+
+extern int device_make_dir(struct device * dev);
+extern void device_remove_dir(struct device * dev);
+
+extern int iobus_make_dir(struct iobus * iobus);
+extern void iobus_remove_dir(struct iobus * iobus);
+
+static spinlock_t device_lock;
+
+/**
+ * device_register - register a device
+ * @dev:	pointer to the device structure
+ *
+ * First, make sure that the device has a parent, create
+ * a directory for it, then add it to the parent's list of
+ * children.
+ */
+int device_register(struct device *dev)
+{
+	int error;
+
+	if (!dev || !strlen(dev->bus_id))
+		return -EINVAL;
+	BUG_ON(!dev->parent);
+
+	spin_lock(&device_lock);
+	INIT_LIST_HEAD(&dev->node);
+	spin_lock_init(&dev->lock);
+	atomic_set(&dev->refcount,2);
+
+	get_iobus(dev->parent);
+	list_add_tail(&dev->node,&dev->parent->devices);
+	spin_unlock(&device_lock);
+
+	DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
+	    dev->bus_id, dev->name, parent->bus_id);
+
+	if ((error = device_make_dir(dev)))
+		goto register_done;
+
+	/* notify platform of device entry */
+	if (platform_notify)
+		platform_notify(dev);
+
+ register_done:
+	put_device(dev);
+	if (error)
+		put_iobus(dev->parent);
+	return error;
+}
+
+/**
+ * put_device - clean up device
+ * @dev:	device in question
+ *
+ * Decrement reference count for device.
+ * If it hits 0, we need to clean it up.
+ * However, we may be here in interrupt context, and it may
+ * take some time to do proper clean up (removing files, calling
+ * back down to device to clean up everything it has).
+ * So, we remove it from its parent's list and add it to the list of
+ * devices to be cleaned up.
+ */
+void put_device(struct device * dev)
+{
+	if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
+		return;
+	list_del_init(&dev->node);
+	spin_unlock(&device_lock);
+
+	DBG("DEV: Unregistering device. ID = '%s', name = '%s'\n",
+	    dev->bus_id,dev->name);
+
+	/* remove the driverfs directory */
+	device_remove_dir(dev);
+
+	if (dev->subordinate)
+		iobus_remove_dir(dev->subordinate);
+
+	/* Notify the platform of the removal, in case they
+	 * need to do anything...
+	 */
+	if (platform_notify_remove)
+		platform_notify_remove(dev);
+
+	/* Tell the driver to clean up after itself.
+	 * Note that we likely didn't allocate the device,
+	 * so this is the driver's chance to free that up...
+	 */
+	if (dev->driver && dev->driver->remove)
+		dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
+
+	put_iobus(dev->parent);
+}
+
+int iobus_register(struct iobus *bus)
+{
+	int error;
+
+	if (!bus || !strlen(bus->bus_id))
+		return -EINVAL;
+	
+	spin_lock(&device_lock);
+	atomic_set(&bus->refcount,2);
+	spin_lock_init(&bus->lock);
+	INIT_LIST_HEAD(&bus->node);
+	INIT_LIST_HEAD(&bus->devices);
+	INIT_LIST_HEAD(&bus->children);
+
+	if (bus != &device_root) {
+		if (!bus->parent)
+			bus->parent = &device_root;
+		get_iobus(bus->parent);
+		list_add_tail(&bus->node,&bus->parent->children);
+	}
+	spin_unlock(&device_lock);
+
+	DBG("DEV: registering bus. ID = '%s' name = '%s' parent = %p\n",
+	    bus->bus_id,bus->name,bus->parent);
+
+	error = iobus_make_dir(bus);
+
+	put_iobus(bus);
+	if (error && bus->parent)
+		put_iobus(bus->parent);
+	return error;
+}
+
+/**
+ * iobus_unregister - remove bus and children from device tree
+ * @bus:	pointer to bus structure
+ *
+ * Remove device from parent's list of children and decrement
+ * reference count on controlling device. That should take care of
+ * the rest of the cleanup.
+ */
+void put_iobus(struct iobus * iobus)
+{
+	if (!atomic_dec_and_lock(&iobus->refcount,&device_lock))
+		return;
+	list_del_init(&iobus->node);
+	spin_unlock(&device_lock);
+
+	if (!list_empty(&iobus->devices) ||
+	    !list_empty(&iobus->children))
+		BUG();
+
+	put_iobus(iobus->parent);
+	/* unregister itself */
+	put_device(iobus->self);
+}
+
+static int __init device_init_root(void)
+{
+	/* initialize parent bus lists */
+	return iobus_register(&device_root);
+}
+
+int __init device_driver_init(void)
+{
+	int error = 0;
+
+	DBG("DEV: Initialising Device Tree\n");
+
+	spin_lock_init(&device_lock);
+
+	error = init_driverfs_fs();
+
+	if (error) {
+		panic("DEV: could not initialise driverfs\n");
+		return error;
+	}
+
+	error = device_init_root();
+	if (error) {
+		printk(KERN_ERR "%s: device root init failed!\n", __FUNCTION__);
+		return error;
+	}
+
+	DBG("DEV: Done Initialising\n");
+	return error;
+}
+
+EXPORT_SYMBOL(device_register);
+EXPORT_SYMBOL(iobus_register);
+EXPORT_SYMBOL(device_driver_init);
diff -urN linux-2.5.3-pre5/drivers/base/fs.c linux/drivers/base/fs.c
--- linux-2.5.3-pre5/drivers/base/fs.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/base/fs.c	Mon Jan 28 13:46:20 2002
@@ -0,0 +1,131 @@
+/*
+ * drivers/base/fs.c - driver model interface to driverfs 
+ *
+ * Copyright (c) 2002 Patrick Mochel
+ *		 2002 Open Source Development Lab
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+
+extern struct driver_file_entry * device_default_files[];
+
+/**
+ * device_create_file - create a driverfs file for a device
+ * @dev:	device requesting file
+ * @entry:	entry describing file
+ *
+ * Allocate space for file entry, copy descriptor, and create.
+ */
+int device_create_file(struct device * dev, struct driver_file_entry * entry)
+{
+	struct driver_file_entry * new_entry;
+	int error = -ENOMEM;
+
+	if (!dev)
+		return -EINVAL;
+	get_device(dev);
+
+	new_entry = kmalloc(sizeof(*new_entry),GFP_KERNEL);
+	if (!new_entry)
+		goto done;
+
+	memcpy(new_entry,entry,sizeof(*entry));
+	error = driverfs_create_file(new_entry,&dev->dir);
+	if (error)
+		kfree(new_entry);
+ done:
+	put_device(dev);
+	return error;
+}
+
+/**
+ * device_remove_file - remove a device's file by name
+ * @dev:	device requesting removal
+ * @name:	name of the file
+ *
+ */
+void device_remove_file(struct device * dev, const char * name)
+{
+	if (dev) {
+		get_device(dev);
+		driverfs_remove_file(&dev->dir,name);
+		put_device(dev);
+	}
+}
+
+/**
+ * device_remove_dir - remove a device's directory
+ * @dev:	device in question
+ */
+void device_remove_dir(struct device * dev)
+{
+	if (dev)
+		driverfs_remove_dir(&dev->dir);
+}
+
+/**
+ * device_make_dir - create a driverfs directory
+ * @name:	name of directory
+ * @parent:	dentry for the parent directory
+ *
+ * Do the initial creation of the device's driverfs directory
+ * and populate it with the one default file.
+ *
+ * This is just a helper for device_register(), as we
+ * don't export this function. (Yes, that means we don't allow
+ * devices to create subdirectories).
+ */
+int device_make_dir(struct device * dev)
+{
+	struct driver_dir_entry * parent = NULL;
+	struct driver_file_entry * entry;
+	int error;
+	int i;
+
+	INIT_LIST_HEAD(&dev->dir.files);
+	dev->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
+	dev->dir.name = dev->bus_id;
+
+	if (dev->parent)
+		parent = &dev->parent->dir;
+
+	if ((error = driverfs_create_dir(&dev->dir,parent)))
+		return error;
+
+	for (i = 0; (entry = *(device_default_files + i)); i++) {
+		if ((error = device_create_file(dev,entry))) {
+			device_remove_dir(dev);
+			return error;
+		}
+	}
+	return 0;
+}
+
+void iobus_remove_dir(struct iobus * iobus)
+{
+	if (iobus)
+		driverfs_remove_dir(&iobus->dir);
+}
+
+int iobus_make_dir(struct iobus * iobus)
+{
+	struct driver_dir_entry * parent = NULL;
+	int error;
+
+	INIT_LIST_HEAD(&iobus->dir.files);
+	iobus->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
+	iobus->dir.name = iobus->bus_id;
+
+	if (iobus->parent)
+		parent = &iobus->parent->dir;
+
+	error = driverfs_create_dir(&iobus->dir,parent);
+	return error;
+}
+
+EXPORT_SYMBOL(device_create_file);
+EXPORT_SYMBOL(device_remove_file);
+
diff -urN linux-2.5.3-pre5/drivers/base/interface.c linux/drivers/base/interface.c
--- linux-2.5.3-pre5/drivers/base/interface.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/base/interface.c	Mon Jan 28 13:46:20 2002
@@ -0,0 +1,174 @@
+/*
+ * drivers/base/interface.c - common driverfs interface that's exported to 
+ * 	the world for all devices.
+ * Copyright (c) 2002 Patrick Mochel
+ *		 2002 Open Source Development Lab
+ */
+
+#include <linux/device.h>
+
+/**
+ * device_read_status - report some device information
+ * @page:	page-sized buffer to write into
+ * @count:	number of bytes requested
+ * @off:	offset into buffer
+ * @data:	device-specific data
+ *
+ * Report some human-readable information about the device.
+ * This includes the name, the bus id, and the current power state.
+ */
+static ssize_t device_read_status(struct device * dev, char * page, size_t count, loff_t off)
+{
+	char *str = page;
+
+	if (off)
+		return 0;
+
+	str += sprintf(str,"Name:       %s\n",dev->name);
+	str += sprintf(str,"Bus ID:     %s\n",dev->bus_id);
+
+	return (str - page);
+}
+
+/**
+ * device_write_status - forward a command to a driver
+ * @buf:	encoded command
+ * @count:	number of bytes in buffer
+ * @off:	offset into buffer to start with
+ * @data:	device-specific data
+ *
+ * Send a comamnd to a device driver.
+ * The following actions are supported:
+ * probe - scan slot for device
+ * remove - detach driver from slot
+ * suspend <state> <stage> - perform <stage> for entering <state>
+ * resume <stage> - perform <stage> for waking device up.
+ * (See Documentation/driver-model.txt for the theory of an n-stage
+ * suspend sequence).
+ */
+static ssize_t device_write_status(struct device * dev, const char* buf, size_t count, loff_t off)
+{
+	char command[20];
+	int num;
+	int arg = 0;
+	int error = 0;
+
+	if (off)
+		return 0;
+
+	/* everything involves dealing with the driver. */
+	if (!dev->driver)
+		return 0;
+
+	num = sscanf(buf,"%10s %d",command,&arg);
+
+	if (!num)
+		return 0;
+
+	if (!strcmp(command,"probe")) {
+		if (dev->driver->probe)
+			error = dev->driver->probe(dev);
+
+	} else if (!strcmp(command,"remove")) {
+		if (dev->driver->remove)
+			error = dev->driver->remove(dev,REMOVE_NOTIFY);
+	} else
+		error = -EFAULT;
+	return error < 0 ? error : count;
+}
+
+static struct driver_file_entry device_status_entry = {
+	name:		"status",
+	mode:		S_IWUSR | S_IRUGO,
+	show:		device_read_status,
+	store:		device_write_status,
+};
+
+static ssize_t
+device_read_power(struct device * dev, char * page, size_t count, loff_t off)
+{
+	char	* str = page;
+
+	if (off)
+		return 0;
+
+	str += sprintf(str,"State:      %d\n",dev->current_state);
+
+	return (str - page);
+}
+
+static ssize_t
+device_write_power(struct device * dev, const char * buf, size_t count, loff_t off)
+{
+	char	str_command[20];
+	char	str_stage[20];
+	int	num_args;
+	u32	state;
+	u32	int_stage;
+	int	error = 0;
+
+	if (off)
+		return 0;
+
+	if (!dev->driver)
+		goto done;
+
+	num_args = sscanf(buf,"%s %s %u",str_command,str_stage,&state);
+
+	error = -EINVAL;
+
+	if (!num_args)
+		goto done;
+
+	if (!strnicmp(str_command,"suspend",7)) {
+		if (num_args != 3)
+			goto done;
+		if (!strnicmp(str_stage,"notify",6))
+			int_stage = SUSPEND_NOTIFY;
+		else if (!strnicmp(str_stage,"save",4))
+			int_stage = SUSPEND_SAVE_STATE;
+		else if (!strnicmp(str_stage,"disable",7))
+			int_stage = SUSPEND_DISABLE;
+		else if (!strnicmp(str_stage,"powerdown",8))
+			int_stage = SUSPEND_POWER_DOWN;
+		else
+			goto done;
+
+		if (dev->driver->suspend)
+			error = dev->driver->suspend(dev,state,int_stage);
+		else
+			error = 0;
+	} else if (!strnicmp(str_command,"resume",6)) {
+		if (num_args != 2)
+			goto done;
+
+		if (!strnicmp(str_stage,"poweron",7))
+			int_stage = RESUME_POWER_ON;
+		else if (!strnicmp(str_stage,"restore",7))
+			int_stage = RESUME_RESTORE_STATE;
+		else if (!strnicmp(str_stage,"enable",6))
+			int_stage = RESUME_ENABLE;
+		else
+			goto done;
+
+		if (dev->driver->resume)
+			error = dev->driver->resume(dev,int_stage);
+		else
+			error = 0;
+	}
+ done:
+	return error < 0 ? error : count;
+}
+
+static struct driver_file_entry device_power_entry = {
+	name:		"power",
+	mode:		S_IWUSR | S_IRUGO,
+	show:		device_read_power,
+	store:		device_write_power,
+};
+
+struct driver_file_entry * device_default_files[] = {
+	&device_status_entry,
+	&device_power_entry,
+	NULL,
+};
diff -urN linux-2.5.3-pre5/drivers/char/Config.help linux/drivers/char/Config.help
--- linux-2.5.3-pre5/drivers/char/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/drivers/char/Config.help	Mon Jan 28 13:46:20 2002
@@ -818,6 +818,28 @@
 
   If unsure, say N.
 
+CONFIG_WATCHDOG
+  If you say Y here (and to one of the following options) and create a
+  character special file /dev/watchdog with major number 10 and minor
+  number 130 using mknod ("man mknod"), you will get a watchdog, i.e.:
+  subsequently opening the file and then failing to write to it for
+  longer than 1 minute will result in rebooting the machine. This
+  could be useful for a networked machine that needs to come back
+  online as fast as possible after a lock-up. There's both a watchdog
+  implementation entirely in software (which can sometimes fail to
+  reboot the machine) and a driver for hardware watchdog boards, which
+  are more robust and can also keep track of the temperature inside
+  your computer. For details, read <file:Documentation/watchdog.txt>
+  in the kernel source.
+
+  The watchdog is usually used together with the watchdog daemon
+  which is available from
+  <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
+  also monitor NFS connections and can reboot the machine when the process
+  table is full.
+
+  If unsure, say N.
+
 CONFIG_WATCHDOG_NOWAYOUT
   The default watchdog behaviour (which you get if you say N here) is
   to stop the timer if the process managing it closes the file
diff -urN linux-2.5.3-pre5/drivers/char/console.c linux/drivers/char/console.c
--- linux-2.5.3-pre5/drivers/char/console.c	Tue Jan  1 11:45:42 2002
+++ linux/drivers/char/console.c	Mon Jan 28 13:46:20 2002
@@ -2349,14 +2349,18 @@
 
 static void con_flush_chars(struct tty_struct *tty)
 {
-	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
+	struct vt_struct *vt;
 
 	if (in_interrupt())	/* from flush_to_ldisc */
 		return;
 
 	pm_access(pm_con);
+	
+	/* if we race with con_close(), vt may be null */
 	acquire_console_sem();
-	set_cursor(vt->vc_num);
+	vt = (struct vt_struct *)tty->driver_data;
+	if (vt)
+		set_cursor(vt->vc_num);
 	release_console_sem();
 }
 
diff -urN linux-2.5.3-pre5/drivers/char/ftape/Config.help linux/drivers/char/ftape/Config.help
--- linux-2.5.3-pre5/drivers/char/ftape/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/drivers/char/ftape/Config.help	Mon Jan 28 13:46:20 2002
@@ -79,6 +79,78 @@
   interface. Accessing `/proc/ftape' while the module is unloaded will
   result in a kernel Oops. This cannot be fixed from inside ftape.
 
+CONFIG_FT_NORMAL_DEBUG
+  This option controls the amount of debugging output the ftape driver
+  is ABLE to produce; it does not increase or diminish the debugging
+  level itself. If unsure, leave this at its default setting,
+  i.e. choose "Normal".
+
+  Ftape can print lots of debugging messages to the system console
+  resp. kernel log files. Reducing the amount of possible debugging
+  output reduces the size of the kernel module by some KB, so it might
+  be a good idea to use "None" for emergency boot floppies.
+
+  If you want to save memory then the following strategy is
+  recommended: leave this option at its default setting "Normal" until
+  you know that the driver works as expected, afterwards reconfigure
+  the kernel, this time specifying "Reduced" or "None" and recompile
+  and install the kernel as usual. Note that choosing "Excessive"
+  debugging output does not increase the amount of debugging output
+  printed to the console but only makes it possible to produce
+  "Excessive" debugging output.
+
+  Please read <file:Documentation/ftape.txt> for a short description
+  how to control the amount of debugging output.
+
+CONFIG_FT_FULL_DEBUG
+  Extremely verbose output for driver debugging purposes.
+
+CONFIG_FT_NO_TRACE
+  Reduced tape driver debugging output.
+
+CONFIG_FT_NO_TRACE_AT_ALL
+  Suppress all debugging output from the tape drive.
+
+CONFIG_FT_STD_FDC
+  Only change this setting if you have a special controller. If you
+  didn't plug any add-on card into your computer system but just
+  plugged the floppy tape cable into the already existing floppy drive
+  controller then you don't want to change the default setting,
+  i.e. choose "Standard".
+
+  Choose "MACH-2" if you have a Mountain Mach-2 controller.
+  Choose "FC-10/FC-20" if you have a Colorado FC-10 or FC-20
+  controller.
+  Choose "Alt/82078" if you have another controller that is located at
+  an IO base address different from the standard floppy drive
+  controller's base address of `0x3f0', or uses an IRQ (interrupt)
+  channel different from `6', or a DMA channel different from
+  `2'. This is necessary for any controller card that is based on
+  Intel's 82078 FDC such as Seagate's, Exabyte's and Iomega's "high
+  speed" controllers.
+
+  If you choose something other than "Standard" then please make
+  sure that the settings for the IO base address and the IRQ and DMA
+  channel in the configuration menus below are correct. Use the manual
+  of your tape drive to determine the correct settings!
+
+  If you are already successfully using your tape drive with another
+  operating system then you definitely should use the same settings
+  for the IO base, the IRQ and DMA channel that have proven to work
+  with that other OS.
+
+  Note that this menu lets you specify only the default setting for
+  the hardware setup. The hardware configuration can be changed at
+  boot time (when ftape is compiled into the kernel, i.e. if you
+  have said Y to "Floppy tape drive") or module load time (i.e. if you
+  have said M to "Floppy tape drive").
+
+  Please read also the file <file:Documentation/ftape.txt> which
+  contains a short description of the parameters that can be set at
+  boot or load time. If you want to use your floppy tape drive on a
+  PCI-bus based system, please read the file
+  <file:drivers/char/ftape/README.PCI>.
+
 CONFIG_FT_FDC_BASE
   You don't need to specify a value if the following default
   settings for the base IO address are correct:
diff -urN linux-2.5.3-pre5/drivers/hotplug/pcihp_skeleton.c linux/drivers/hotplug/pcihp_skeleton.c
--- linux-2.5.3-pre5/drivers/hotplug/pcihp_skeleton.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/hotplug/pcihp_skeleton.c	Mon Jan 28 13:46:20 2002
@@ -0,0 +1,432 @@
+/*
+ * PCI Hot Plug Controller Skeleton Driver - 0.1
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (c) 2001 IBM Corp.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver is to be used as a skeleton driver to be show how to interface
+ * with the pci hotplug core easily.
+ *
+ * Send feedback to <greg@kroah.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include "pci_hotplug.h"
+
+
+#define SLOT_MAGIC	0x67267322
+struct slot {
+	u32 magic;
+	u8 number;
+	struct hotplug_slot *hotplug_slot;
+	struct list_head slot_list;
+};
+
+static LIST_HEAD(slot_list);
+
+#if !defined(CONFIG_HOTPLUG_PCI_SKELETON_MODULE)
+	#define MY_NAME	"pcihp_skeleton"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+#define dbg(format, arg...)					\
+	do {							\
+		if (debug)					\
+			printk (KERN_DEBUG "%s: " format "\n",	\
+				MY_NAME , ## arg); 		\
+	} while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
+
+
+
+/* local variables */
+static int debug;
+static int num_slots;
+
+#define DRIVER_VERSION	"0.1"
+#define DRIVER_AUTHOR	"Greg Kroah-Hartman <greg@kroah.com>"
+#define DRIVER_DESC	"Hot Plug PCI Controller Skeleton Driver"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+
+static int enable_slot		(struct hotplug_slot *slot);
+static int disable_slot		(struct hotplug_slot *slot);
+static int set_attention_status (struct hotplug_slot *slot, u8 value);
+static int hardware_test	(struct hotplug_slot *slot, u32 value);
+static int get_power_status	(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
+static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
+static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
+
+static struct hotplug_slot_ops skel_hotplug_slot_ops = {
+	owner:			THIS_MODULE,
+	enable_slot:		enable_slot,
+	disable_slot:		disable_slot,
+	set_attention_status:	set_attention_status,
+	hardware_test:		hardware_test,
+	get_power_status:	get_power_status,
+	get_attention_status:	get_attention_status,
+	get_latch_status:	get_latch_status,
+	get_adapter_status:	get_adapter_status,
+};
+
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static inline int slot_paranoia_check (struct slot *slot, const char *function)
+{
+	if (!slot) {
+		dbg("%s - slot == NULL", function);
+		return -1;
+	}
+	if (slot->magic != SLOT_MAGIC) {
+		dbg("%s - bad magic number for slot", function);
+		return -1;
+	}
+	if (!slot->hotplug_slot) {
+		dbg("%s - slot->hotplug_slot == NULL!", function);
+		return -1;
+	}
+	return 0;
+}
+
+static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function)
+{ 
+	struct slot *slot;
+
+	if (!hotplug_slot) {
+		dbg("%s - hotplug_slot == NULL\n", function);
+		return NULL;
+	}
+
+	slot = (struct slot *)hotplug_slot->private;
+	if (slot_paranoia_check (slot, function))
+                return NULL;
+	return slot;
+}               
+
+
+static int enable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	/*
+	 * Fill in code here to enable the specified slot
+	 */
+
+	return retval;
+}
+
+
+static int disable_slot (struct hotplug_slot *hotplug_slot)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	/*
+	 * Fill in code here to disable the specified slot
+	 */
+
+	return retval;
+}
+
+static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	switch (status) {
+		case 0:
+			/*
+			 * Fill in code here to turn light off
+			 */
+			break;
+
+		case 1:
+		default:
+			/*
+			 * Fill in code here to turn light on
+			 */
+			break;
+	}
+
+	return retval;
+}
+
+static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg ("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	err ("No hardware tests are defined for this driver");
+	retval = -ENODEV;
+
+	/* Or you can specify a test if you want to */
+	
+	return retval;
+}
+
+static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current power status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current attention status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current latch status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+	int retval = 0;
+	
+	if (slot == NULL)
+		return -ENODEV;
+	
+	dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name);
+
+	/*
+	 * Fill in logic to get the current adapter status of the specific
+	 * slot and store it in the *value location.
+	 */
+
+	return retval;
+}
+
+#define SLOT_NAME_SIZE	10
+static void make_slot_name (struct slot *slot)
+{
+	/*
+	 * Stupid way to make a filename out of the slot name.
+	 * replace this if your hardware provides a better way to name slots.
+	 */
+	snprintf (slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", slot->number);
+}
+
+static int init_slots (void)
+{
+	struct slot *slot;
+	struct hotplug_slot *hotplug_slot;
+	struct hotplug_slot_info *info;
+	char *name;
+	int retval = 0;
+	int i;
+
+	/*
+	 * Create a structure for each slot, and register that slot
+	 * with the pci_hotplug subsystem.
+	 */
+	for (i = 0; i < num_slots; ++i) {
+		slot = kmalloc (sizeof (struct slot), GFP_KERNEL);
+		if (!slot)
+			return -ENOMEM;
+		memset(slot, 0, sizeof(struct slot));
+
+		hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);
+		if (!hotplug_slot) {
+			kfree (slot);
+			return -ENOMEM;
+		}
+		memset(hotplug_slot, 0, sizeof (struct hotplug_slot));
+		slot->hotplug_slot = hotplug_slot;
+
+		info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+		if (!info) {
+			kfree (hotplug_slot);
+			kfree (slot);
+			return -ENOMEM;
+		}
+		memset(info, 0, sizeof (struct hotplug_slot_info));
+		hotplug_slot->info = info;
+
+		name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL);
+		if (!name) {
+			kfree (info);
+			kfree (hotplug_slot);
+			kfree (slot);
+			return -ENOMEM;
+		}
+		hotplug_slot->name = name;
+
+		slot->magic = SLOT_MAGIC;
+		slot->number = i;
+
+		hotplug_slot->private = slot;
+		make_slot_name (slot);
+		hotplug_slot->ops = &skel_hotplug_slot_ops;
+		
+		/*
+		 * Initilize the slot info structure with some known
+		 * good values.
+		 */
+		info->power_status = get_skel_power_status(slot);
+		info->attention_status = get_skel_attention_status(slot);
+		info->latch_status = get_skel_latch_status(slot);
+		info->adapter_status = get_skel_adapter_status(slot);
+		
+		dbg ("registering slot %d\n", i);
+		retval = pci_hp_register (slot->hotplug_slot);
+		if (retval) {
+			err ("pci_hp_register failed with error %d\n", retval);
+			kfree (info);
+			kfree (name);
+			kfree (hotplug_slot);
+			kfree (slot);
+			return retval;
+		}
+
+		/* add slot to our internal list */
+		list_add (&slot->slot_list, &slot_list);
+	}
+
+	return retval;
+}
+		
+static void cleanup_slots (void)
+{
+	struct list_head *tmp;
+	struct slot *slot;
+
+	/*
+	 * Unregister all of our slots with the pci_hotplug subsystem,
+	 * and free up all memory that we had allocated.
+	 */
+	list_for_each (tmp, &slot_list) {
+		slot = list_entry (tmp, struct slot, slot_list);
+		list_del (&slot->slot_list);
+		pci_hp_deregister (slot->hotplug_slot);
+		kfree (slot->hotplug_slot->info);
+		kfree (slot->hotplug_slot->name);
+		kfree (slot->hotplug_slot);
+		kfree (slot);
+	}
+
+	return;
+}
+		
+static int __init pcihp_skel_init(void)
+{
+	int retval;
+
+	/*
+	 * Do specific initialization stuff for your driver here
+	 * Like initilizing your controller hardware (if any) and
+	 * determining the number of slots you have in the system
+	 * right now.
+	 */
+	num_slots = 5;
+
+	retval = init_slots();
+	if (retval)
+		return retval;
+
+	info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+	return 0;
+}
+
+static void __exit pcihp_skel_exit(void)
+{
+	/*
+	 * Clean everything up.
+	 */
+	cleanup_slots();
+}
+
+module_init(pcihp_skel_init);
+module_exit(pcihp_skel_exit);
+
diff -urN linux-2.5.3-pre5/drivers/ide/Config.help linux/drivers/ide/Config.help
--- linux-2.5.3-pre5/drivers/ide/Config.help	Mon Jan 28 13:46:15 2002
+++ linux/drivers/ide/Config.help	Mon Jan 28 13:46:20 2002
@@ -752,6 +752,21 @@
 
   If unsure, say N.
 
+CONFIG_IDE_8xx_PCCARD
+  Select how the IDE devices are connected to the MPC8xx system:
+
+  8xx_PCCARD uses the 8xx internal PCMCIA interface in combination
+             with a PC Card (e.g. ARGOSY portable Hard Disk Adapter),
+             ATA PC Card HDDs or ATA PC Flash Cards (example: TQM8xxL
+             systems)
+
+  8xx_DIRECT is used for directly connected IDE devices using the 8xx
+             internal PCMCIA interface (example: IVMS8 systems)
+
+  EXT_DIRECT is used for IDE devices directly connected to the 8xx
+             bus using some glue logic, but _not_ the 8xx internal
+             PCMCIA interface (example: IDIF860 systems)
+
 CONFIG_BLK_DEV_IDEDISK_FUJITSU
   Enable vendor-specific code for Fujitsu IDE disks.  Unless you are
   the IDE maintainer, you probably do not want to mess with this.
diff -urN linux-2.5.3-pre5/drivers/ieee1394/video1394.c linux/drivers/ieee1394/video1394.c
--- linux-2.5.3-pre5/drivers/ieee1394/video1394.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/ieee1394/video1394.c	Mon Jan 28 13:46:21 2002
@@ -844,7 +844,7 @@
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
 }
 
-static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d, 
+static int do_iso_mmap(struct vm_area_struct *vma, struct ti_ohci *ohci, struct dma_iso_ctx *d, 
 		       const char *adr, unsigned long size)
 {
         unsigned long start=(unsigned long) adr;
@@ -865,7 +865,7 @@
         pos=(unsigned long) d->buf;
         while (size > 0) {
                 page = kvirt_to_pa(pos);
-                if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+                if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
                         return -EAGAIN;
                 start+=PAGE_SIZE;
                 pos+=PAGE_SIZE;
diff -urN linux-2.5.3-pre5/drivers/isdn/Config.help linux/drivers/isdn/Config.help
--- linux-2.5.3-pre5/drivers/isdn/Config.help	Mon Jan 28 13:46:16 2002
+++ linux/drivers/isdn/Config.help	Mon Jan 28 13:46:21 2002
@@ -363,6 +363,16 @@
   This enables the driver for ST5481 based USB ISDN adapters,
   e.g. the BeWan Gazel 128 USB
 
+CONFIG_HISAX_FRITZ_PCIPNP
+  This enables the driver for the AVM Fritz!Card PCI, Fritz!Card PCI v2 
+  and Fritz!Card PnP.
+  (the latter also needs you to select "ISA Plug and Play support"
+  from the menu "Plug and Play configuration")
+
+CONFIG_HISAX_FRITZ_CLASSIC
+  This enables the driver for the AVM Fritz!Card classic, formerly
+  known as AVM A1.
+
 CONFIG_ISDN_DRV_PCBIT
   This enables support for the PCBIT ISDN-card.  This card is
   manufactured in Portugal by Octal.  For running this card,
diff -urN linux-2.5.3-pre5/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- linux-2.5.3-pre5/drivers/isdn/isdn_common.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/isdn/isdn_common.c	Mon Jan 28 13:46:21 2002
@@ -2169,11 +2169,6 @@
 {
 	char buf[11];
 
-	sprintf (buf, "isdn%d", k);
-	dev->devfs_handle_isdnX[k] =
-	    devfs_register (devfs_handle, buf, DEVFS_FL_DEFAULT,
-			    ISDN_MAJOR, k,0600 | S_IFCHR,
-			    &isdn_fops, NULL);
 	sprintf (buf, "isdnctrl%d", k);
 	dev->devfs_handle_isdnctrlX[k] =
 	    devfs_register (devfs_handle, buf, DEVFS_FL_DEFAULT,
diff -urN linux-2.5.3-pre5/drivers/mtd/chips/Config.help linux/drivers/mtd/chips/Config.help
--- linux-2.5.3-pre5/drivers/mtd/chips/Config.help	Mon Jan 28 13:46:16 2002
+++ linux/drivers/mtd/chips/Config.help	Mon Jan 28 13:46:21 2002
@@ -46,6 +46,22 @@
   If your flash chips are interleaved in fours - i.e. you have four
   flash chips addressed by each bus cycle, then say 'Y'.
 
+CONFIG_MTD_CFI_NOSWAP
+  This option defines the way in which the CPU attempts to arrange
+  data bits when writing the 'magic' commands to the chips. Saying
+  'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't
+  enabled, means that the CPU will not do any swapping; the chips
+  are expected to be wired to the CPU in 'host-endian' form. 
+  Specific arrangements are possible with the BIG_ENDIAN_BYTE and
+  LITTLE_ENDIAN_BYTE, if the bytes are reversed.
+
+  If you have a LART, on which the data (and address) lines were
+  connected in a fashion which ensured that the nets were as short
+  as possible, resulting in a bit-shuffling which seems utterly
+  random to the untrained eye, you need the LART_ENDIAN_BYTE option.
+
+  Yes, there really exists something sicker than PDP-endian :)
+
 CONFIG_MTD_CFI_INTELEXT
   The Common Flash Interface defines a number of different command
   sets which a CFI-compliant chip may claim to implement. This code
diff -urN linux-2.5.3-pre5/drivers/net/wireless/wavelan_cs.c linux/drivers/net/wireless/wavelan_cs.c
--- linux-2.5.3-pre5/drivers/net/wireless/wavelan_cs.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/net/wireless/wavelan_cs.c	Mon Jan 28 13:46:22 2002
@@ -797,7 +797,7 @@
   wavepoint_history *wavepoint=NULL;                /* WavePoint table entry */
   net_local *lp=(net_local *)dev->priv;              /* Device info */
 
-#if 0
+#ifdef I_NEED_THIS_FEATURE
   /* Some people don't need this, some other may need it */
   nwid=nwid^ntohs(beacon->domain_id);
 #endif
@@ -1417,7 +1417,7 @@
 	  printk("2430.5");
 	  break;
 	default:
-	  printk("???");
+	  printk("unknown");
 	}
     }
 
@@ -1732,7 +1732,7 @@
 	 memcmp(dac, dac_verify, 2 * 2))
 	{
 #ifdef DEBUG_IOCTL_ERROR
-	  printk(KERN_INFO "Wavelan: wv_set_frequency : unable to write new frequency to EEprom (??)\n");
+	  printk(KERN_INFO "Wavelan: wv_set_frequency : unable to write new frequency to EEprom (?)\n");
 #endif
 	  return -EOPNOTSUPP;
 	}
@@ -1981,7 +1981,7 @@
 
     case SIOCGIWFREQ:
       /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
-       * (does it work for everybody ??? - especially old cards...) */
+       * (does it work for everybody ? - especially old cards...) */
       if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
 	   (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
 	{
@@ -3163,7 +3163,7 @@
    */
 
   /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
-   * (does it work for everybody ??? - especially old cards...) */
+   * (does it work for everybody ? - especially old cards...) */
   /* Note : WFREQSEL verify that it is able to read from EEprom
    * a sensible frequency (address 0x00) + that MMR_FEE_STATUS_ID
    * is 0xA (Xilinx version) or 0xB (Ariadne version).
@@ -4718,7 +4718,7 @@
 	 * obliged to close nicely the wavelan here. David, could you
 	 * close the device before suspending them ? And, by the way,
 	 * could you, on resume, add a "route add -net ..." after the
-	 * ifconfig up ??? Thanks... */
+	 * ifconfig up ? Thanks... */
 
 	/* Stop receiving new messages and wait end of transmission */
 	wv_ru_stop(dev);
@@ -4745,7 +4745,7 @@
 	if(link->state & DEV_CONFIG)
 	  {
       	    CardServices(RequestConfiguration, link->handle, &link->conf);
-      	    if(link->open)	/* If RESET -> True, If RESUME -> False ??? */
+      	    if(link->open)	/* If RESET -> True, If RESUME -> False ? */
 	      {
 		wv_hw_reset(dev);
 		netif_device_attach(dev);
diff -urN linux-2.5.3-pre5/drivers/pci/Makefile linux/drivers/pci/Makefile
--- linux-2.5.3-pre5/drivers/pci/Makefile	Sun Sep  9 10:50:48 2001
+++ linux/drivers/pci/Makefile	Mon Jan 28 13:46:22 2002
@@ -13,7 +13,7 @@
 
 export-objs := pci.o
 
-obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
+obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o pci-driver.o
 obj-$(CONFIG_PROC_FS) += proc.o
 
 ifndef CONFIG_SPARC64
diff -urN linux-2.5.3-pre5/drivers/pci/pci-driver.c linux/drivers/pci/pci-driver.c
--- linux-2.5.3-pre5/drivers/pci/pci-driver.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/pci-driver.c	Mon Jan 28 13:46:22 2002
@@ -0,0 +1,36 @@
+/*
+ * drivers/pci/pci-driver.c - default PCI driver.
+ *
+ */
+
+#include <linux/pci.h>
+
+static int pci_device_suspend(struct device * dev, u32 stage, u32 state)
+{
+	struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
+	int error = 0;
+
+	if (pci_dev->driver) {
+		if (stage == SUSPEND_SAVE_STATE && pci_dev->driver->save_state)
+			error = pci_dev->driver->save_state(pci_dev,state);
+		else if (stage == SUSPEND_POWER_DOWN && pci_dev->driver->suspend)
+			error = pci_dev->driver->suspend(pci_dev,state);
+	}
+	return error;
+}
+
+static int pci_device_resume(struct device * dev, u32 stage)
+{
+	struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
+
+	if (pci_dev->driver) {
+		if (stage == RESUME_POWER_ON && pci_dev->driver->resume)
+			pci_dev->driver->resume(pci_dev);
+	}
+	return 0;
+}
+
+struct device_driver pci_device_driver = {
+	suspend:	pci_device_suspend,
+	resume:		pci_device_resume,
+};
diff -urN linux-2.5.3-pre5/drivers/pci/pci.c linux/drivers/pci/pci.c
--- linux-2.5.3-pre5/drivers/pci/pci.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/pci/pci.c	Mon Jan 28 13:46:22 2002
@@ -38,6 +38,8 @@
 LIST_HEAD(pci_root_buses);
 LIST_HEAD(pci_devices);
 
+extern struct device_driver pci_device_driver;
+
 /**
  * pci_find_slot - locate PCI device from a given PCI slot
  * @bus: number of PCI bus on which desired PCI device resides
@@ -1369,6 +1371,7 @@
 	dev0.bus = bus;
 	dev0.sysdata = bus->sysdata;
 	dev0.dev.parent = &bus->iobus;
+	dev0.dev.driver = &pci_device_driver;
 
 	/* Go find them, Rover! */
 	for (devfn = 0; devfn < 0x100; devfn += 8) {
diff -urN linux-2.5.3-pre5/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- linux-2.5.3-pre5/drivers/sbus/sbus.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/sbus/sbus.c	Mon Jan 28 13:46:22 2002
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.98 2002/01/05 01:13:43 davem Exp $
+/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $
  * sbus.c:  SBus support routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -284,7 +284,7 @@
 extern void firetruck_init(void);
 extern void rs_init(void);
 
-void __init sbus_init(void)
+static int __init sbus_init(void)
 {
 	int nd, this_sbus, sbus_devs, topnd, iommund;
 	unsigned int sbus_clock;
@@ -297,7 +297,8 @@
 #endif
 
 #ifdef CONFIG_SUN4
-	return sun4_dvma_init();
+	sun4_dvma_init();
+	return 0;
 #endif
 
 	topnd = prom_getchild(prom_root_node);
@@ -316,7 +317,7 @@
 				firetruck_init();
 #endif
 			}
-			return;
+			return 0;
 #else
 			prom_printf("YEEE, UltraSparc sbus not found\n");
 			prom_halt();
@@ -337,7 +338,7 @@
                                 prom_printf("Neither SBUS nor PCI found.\n");
                                 prom_halt();
                         }
-                        return;
+                        return 0;
 #else
 			/* No reason to run further - the data access trap will occur. */
 			panic("sbus not found");
@@ -508,6 +509,8 @@
 		clock_probe();
 	}
 #endif
+
+	return 0;
 }
 
 subsys_initcall(sbus_init);
diff -urN linux-2.5.3-pre5/drivers/usb/hcd/Config.help linux/drivers/usb/hcd/Config.help
--- linux-2.5.3-pre5/drivers/usb/hcd/Config.help	Mon Jan 28 13:46:16 2002
+++ linux/drivers/usb/hcd/Config.help	Mon Jan 28 13:46:23 2002
@@ -21,3 +21,18 @@
   The module will be called ehci-hcd.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+OHCI (most USB hosts except VIA, Intel PIIX) support
+CONFIG_USB_OHCI_HCD
+  The Open Host Controller Interface (OHCI) is a standard for accessing
+  USB 1.1 host controller hardware.  It does more in hardware than Intel's
+  UHCI specification.  If your USB host controller follows the OHCI spec,
+  say Y.  On most non-x86 systems, and on x86 hardware that's not using a
+  USB controller from Intel or VIA, this is appropriate.  If your host
+  controller doesn't use PCI, this is probably appropriate.  For a PCI
+  based system where you're not sure, the "lspci -v" entry will list the
+  right "prog-if" for your USB controller(s):  EHCI, OHCI, or UHCI.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ohci-hcd.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
diff -urN linux-2.5.3-pre5/drivers/usb/hcd/ehci-hcd.c linux/drivers/usb/hcd/ehci-hcd.c
--- linux-2.5.3-pre5/drivers/usb/hcd/ehci-hcd.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/usb/hcd/ehci-hcd.c	Mon Jan 28 13:46:23 2002
@@ -86,7 +86,7 @@
 // #define EHCI_VERBOSE_DEBUG
 // #define have_iso
 
-#ifdef	DEBUG
+#ifdef	CONFIG_DEBUG_SLAB
 #	define	EHCI_SLAB_FLAGS		(SLAB_POISON)
 #else
 #	define	EHCI_SLAB_FLAGS		0
diff -urN linux-2.5.3-pre5/drivers/usb/hcd.c linux/drivers/usb/hcd.c
--- linux-2.5.3-pre5/drivers/usb/hcd.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/usb/hcd.c	Mon Jan 28 13:46:23 2002
@@ -1175,6 +1175,8 @@
 			dbg ("%s: wait for giveback urb %p",
 				hcd->bus_name, urb);
 		}
+	} else if ((urb->transfer_flags & USB_ASYNC_UNLINK) && retval == 0) {
+		return -EINPROGRESS;
 	}
 	goto bye;
 done:
diff -urN linux-2.5.3-pre5/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- linux-2.5.3-pre5/drivers/usb/uhci.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/usb/uhci.c	Mon Jan 28 13:46:23 2002
@@ -813,7 +813,9 @@
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
 
 	/* 3 errors */
-	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+	status = TD_CTRL_ACTIVE | (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
 
 	/*
 	 * Build the TD for the control request
@@ -892,7 +894,7 @@
 	qh->urbp = urbp;
 
 	/* Low speed or small transfers gets a different queue and treatment */
-	if (urb->pipe & TD_CTRL_LS) {
+	if (urb->dev->speed == USB_SPEED_LOW) {
 		uhci_insert_tds_in_qh(qh, urb, 0);
 		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
 	} else {
@@ -1059,7 +1061,7 @@
 	uhci_insert_tds_in_qh(urbp->qh, urb, 0);
 
 	/* Low speed or small transfers gets a different queue and treatment */
-	if (urb->pipe & TD_CTRL_LS)
+	if (urb->dev->speed == USB_SPEED_LOW)
 		uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb);
 	else
 		uhci_insert_qh(uhci, uhci->skel_hs_control_qh, urb);
@@ -1083,7 +1085,9 @@
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
 
-	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOC;
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
 
 	td = uhci_alloc_td(uhci, urb->dev);
 	if (!td)
@@ -1218,7 +1222,7 @@
 		return -EINVAL;
 
 	/* Can't have low speed bulk transfers */
-	if (urb->pipe & TD_CTRL_LS)
+	if (urb->dev->speed == USB_SPEED_LOW)
 		return -EINVAL;
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
diff -urN linux-2.5.3-pre5/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- linux-2.5.3-pre5/drivers/usb/usb-ohci.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/usb/usb-ohci.c	Mon Jan 28 13:46:23 2002
@@ -1234,7 +1234,7 @@
 			| usb_pipeendpoint (pipe) << 7
 			| (usb_pipeisoc (pipe)? 0x8000: 0)
 			| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) 
-			| usb_pipeslow (pipe) << 13
+			| (usb_dev->speed == USB_SPEED_LOW) << 13
 			| usb_maxpacket (usb_dev, pipe, usb_pipeout (pipe)) << 16);
   
   	if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
diff -urN linux-2.5.3-pre5/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- linux-2.5.3-pre5/drivers/usb/usb-uhci.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/usb/usb-uhci.c	Mon Jan 28 13:46:23 2002
@@ -723,8 +723,11 @@
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
 
 	/* 3 errors */
-	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE |
-		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+	status = TD_CTRL_ACTIVE
+		| (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD)
+		| (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
 
 	/*  Build the TD for the control request, try forever, 8 bytes of data */
 	fill_td (td, status, destination | (7 << 21), urb_priv->setup_packet_dma);
@@ -799,7 +802,7 @@
 
 	//uhci_show_queue(qh);
 	/* Start it up... put low speed first */
-	if (urb->pipe & TD_CTRL_LS)
+	if (urb->dev->speed == USB_SPEED_LOW)
 		insert_qh (s, s->control_chain, qh, 0);
 	else
 		insert_qh (s, s->bulk_chain, qh, 0);
@@ -876,8 +879,11 @@
 	destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
 
 	/* 3 errors */
-	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE |
-		((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27);
+	status = TD_CTRL_ACTIVE
+		| ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD)
+		| (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
 
 	/* Build the TDs for the bulk request */
 	len = urb->transfer_buffer_length;
@@ -1472,8 +1478,11 @@
 	if (alloc_td (s, &td, UHCI_PTR_DEPTH))
 		return -ENOMEM;
 
-	status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
-		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOC
+		| (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD)
+		| (3 << 27);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
 
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid (urb->pipe) |
 		(((urb->transfer_buffer_length - 1) & 0x7ff) << 21);
@@ -2506,8 +2515,11 @@
 					desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
 									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
 				}
-				desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+				desc->hw.td.status= cpu_to_le32(TD_CTRL_ACTIVE | TD_CTRL_IOC |
 					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27));
+				if (urb->dev->speed == USB_SPEED_LOW)
+					desc->hw.td.status |=
+					    __constant_cpu_to_le32 (TD_CTRL_LS);
 				mb();
 			}
 			else {
diff -urN linux-2.5.3-pre5/drivers/usb/usb.c linux/drivers/usb/usb.c
--- linux-2.5.3-pre5/drivers/usb/usb.c	Mon Jan 28 13:46:16 2002
+++ linux/drivers/usb/usb.c	Mon Jan 28 13:46:23 2002
@@ -324,8 +324,9 @@
 	unsigned int	pipe = urb->pipe;
 	long		bustime;
 
-	bustime = usb_calc_bus_time (usb_pipeslow(pipe), usb_pipein(pipe),
-			usb_pipeisoc(pipe), usb_maxpacket(dev, pipe, usb_pipeout(pipe)));
+	bustime = usb_calc_bus_time (dev->speed == USB_SPEED_LOW,
+			usb_pipein(pipe), usb_pipeisoc(pipe),
+			usb_maxpacket(dev, pipe, usb_pipeout(pipe)));
 	if (usb_pipeisoc(pipe))
 		bustime = NS_TO_US(bustime) / urb->number_of_packets;
 	else
@@ -2513,6 +2514,53 @@
 	return err;
 }
 
+/**
+ * usb_make_path - returns device path in the hub tree
+ * @dev: the device whose path is being constructed
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ *
+ * Returns length of the string (>= 0) or out of memory status (< 0).
+ */
+int usb_make_path(struct usb_device *dev, char *buf, size_t size)
+{
+	struct usb_device *pdev = dev->parent;
+	char *tmp;
+	char *port;
+	int i;
+
+	if (!(port = kmalloc(size, GFP_KERNEL)))
+		return -ENOMEM;
+	if (!(tmp = kmalloc(size, GFP_KERNEL))) {
+		kfree(port);
+		return -ENOMEM;
+	}
+
+	*port = 0;
+	while (pdev) {
+		for (i = 0; i < pdev->maxchild; i++)
+			if (pdev->children[i] == dev)
+				break;
+
+		if (pdev->children[i] != dev) {
+			kfree(port);
+			kfree(tmp);
+			return -ENODEV;
+		}
+
+		strcpy(tmp, port);
+		snprintf(port, size, strlen(port) ? "%d.%s" : "%d", i + 1, tmp);
+
+		dev = pdev;
+		pdev = dev->parent;
+	}
+
+	snprintf(buf, size, "usb%d:%s", dev->bus->busnum, port);
+	kfree(port);
+	kfree(tmp);
+	return strlen(buf);
+}
+
 /*
  * By the time we get here, the device has gotten a new device ID
  * and is in the default state. We need to identify the thing and
@@ -2762,5 +2810,6 @@
 EXPORT_SYMBOL(usb_set_configuration);
 EXPORT_SYMBOL(usb_set_interface);
 
+EXPORT_SYMBOL(usb_make_path);
 EXPORT_SYMBOL(usb_devfs_handle);
 MODULE_LICENSE("GPL");
diff -urN linux-2.5.3-pre5/fs/adfs/dir.c linux/fs/adfs/dir.c
--- linux-2.5.3-pre5/fs/adfs/dir.c	Mon Sep 18 15:14:06 2000
+++ linux/fs/adfs/dir.c	Mon Jan 28 13:46:25 2002
@@ -146,9 +146,9 @@
 	if (ret)
 		goto out;
 
-	if (inode->u.adfs_i.parent_id != dir.parent_id) {
+	if (ADFS_I(inode)->parent_id != dir.parent_id) {
 		adfs_error(sb, "parent directory changed under me! (%lx but got %lx)\n",
-			   inode->u.adfs_i.parent_id, dir.parent_id);
+			   ADFS_I(inode)->parent_id, dir.parent_id);
 		ret = -EIO;
 		goto free_out;
 	}
diff -urN linux-2.5.3-pre5/fs/adfs/inode.c linux/fs/adfs/inode.c
--- linux-2.5.3-pre5/fs/adfs/inode.c	Sun Dec 30 10:53:53 2001
+++ linux/fs/adfs/inode.c	Mon Jan 28 13:46:25 2002
@@ -65,7 +65,7 @@
 static int adfs_prepare_write(struct file *file, struct page *page, unsigned int from, unsigned int to)
 {
 	return cont_prepare_write(page, from, to, adfs_get_block,
-		&page->mapping->host->u.adfs_i.mmu_private);
+		&ADFS_I(page->mapping->host)->mmu_private);
 }
 
 static int _adfs_bmap(struct address_space *mapping, long block)
@@ -87,8 +87,8 @@
 {
 	unsigned int type;
 
-	if (inode->u.adfs_i.stamped)
-		type = (inode->u.adfs_i.loadaddr >> 8) & 0xfff;
+	if (ADFS_I(inode)->stamped)
+		type = (ADFS_I(inode)->loadaddr >> 8) & 0xfff;
 	else
 		type = (unsigned int) -1;
 
@@ -101,7 +101,7 @@
 static umode_t
 adfs_atts2mode(struct super_block *sb, struct inode *inode)
 {
-	unsigned int filetype, attr = inode->u.adfs_i.attr;
+	unsigned int filetype, attr = ADFS_I(inode)->attr;
 	umode_t mode, rmask;
 
 	if (attr & ADFS_NDA_DIRECTORY) {
@@ -151,7 +151,7 @@
 
 	/* FIXME: should we be able to alter a link? */
 	if (S_ISLNK(inode->i_mode))
-		return inode->u.adfs_i.attr;
+		return ADFS_I(inode)->attr;
 
 	if (S_ISDIR(inode->i_mode))
 		attr = ADFS_NDA_DIRECTORY;
@@ -183,11 +183,11 @@
 {
 	unsigned int high, low;
 
-	if (inode->u.adfs_i.stamped == 0)
+	if (ADFS_I(inode)->stamped == 0)
 		return CURRENT_TIME;
 
-	high = inode->u.adfs_i.loadaddr << 24;
-	low  = inode->u.adfs_i.execaddr;
+	high = ADFS_I(inode)->loadaddr << 24;
+	low  = ADFS_I(inode)->execaddr;
 
 	high |= low >> 8;
 	low  &= 255;
@@ -216,14 +216,14 @@
 {
 	unsigned int high, low;
 
-	if (inode->u.adfs_i.stamped) {
+	if (ADFS_I(inode)->stamped) {
 		/* convert 32-bit seconds to 40-bit centi-seconds */
 		low  = (secs & 255) * 100;
 		high = (secs / 256) * 100 + (low >> 8) + 0x336e996a;
 
-		inode->u.adfs_i.loadaddr = (high >> 24) |
-				(inode->u.adfs_i.loadaddr & ~0xff);
-		inode->u.adfs_i.execaddr = (low & 255) | (high << 8);
+		ADFS_I(inode)->loadaddr = (high >> 24) |
+				(ADFS_I(inode)->loadaddr & ~0xff);
+		ADFS_I(inode)->execaddr = (low & 255) | (high << 8);
 	}
 }
 
@@ -263,11 +263,11 @@
 	 * for this file.  This will need special handling
 	 * for cross-directory renames.
 	 */
-	inode->u.adfs_i.parent_id = obj->parent_id;
-	inode->u.adfs_i.loadaddr  = obj->loadaddr;
-	inode->u.adfs_i.execaddr  = obj->execaddr;
-	inode->u.adfs_i.attr      = obj->attr;
-	inode->u.adfs_i.stamped	  = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
+	ADFS_I(inode)->parent_id = obj->parent_id;
+	ADFS_I(inode)->loadaddr  = obj->loadaddr;
+	ADFS_I(inode)->execaddr  = obj->execaddr;
+	ADFS_I(inode)->attr      = obj->attr;
+	ADFS_I(inode)->stamped	  = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
 
 	inode->i_mode	 = adfs_atts2mode(sb, inode);
 	inode->i_mtime	 =
@@ -281,7 +281,7 @@
 		inode->i_op	= &adfs_file_inode_operations;
 		inode->i_fop	= &adfs_file_operations;
 		inode->i_mapping->a_ops = &adfs_aops;
-		inode->u.adfs_i.mmu_private = inode->i_size;
+		ADFS_I(inode)->mmu_private = inode->i_size;
 	}
 
 	insert_inode_hash(inode);
@@ -335,7 +335,7 @@
 	if (ia_valid & ATTR_CTIME)
 		inode->i_ctime = attr->ia_ctime;
 	if (ia_valid & ATTR_MODE) {
-		inode->u.adfs_i.attr = adfs_mode2atts(sb, inode);
+		ADFS_I(inode)->attr = adfs_mode2atts(sb, inode);
 		inode->i_mode = adfs_atts2mode(sb, inode);
 	}
 
@@ -362,10 +362,10 @@
 	lock_kernel();
 	obj.file_id	= inode->i_ino;
 	obj.name_len	= 0;
-	obj.parent_id	= inode->u.adfs_i.parent_id;
-	obj.loadaddr	= inode->u.adfs_i.loadaddr;
-	obj.execaddr	= inode->u.adfs_i.execaddr;
-	obj.attr	= inode->u.adfs_i.attr;
+	obj.parent_id	= ADFS_I(inode)->parent_id;
+	obj.loadaddr	= ADFS_I(inode)->loadaddr;
+	obj.execaddr	= ADFS_I(inode)->execaddr;
+	obj.attr	= ADFS_I(inode)->attr;
 	obj.size	= inode->i_size;
 
 	adfs_dir_update(sb, &obj);
diff -urN linux-2.5.3-pre5/fs/adfs/super.c linux/fs/adfs/super.c
--- linux-2.5.3-pre5/fs/adfs/super.c	Fri Jan  4 09:42:12 2002
+++ linux/fs/adfs/super.c	Mon Jan 28 13:46:25 2002
@@ -232,7 +232,51 @@
 	return 0;
 }
 
+static kmem_cache_t *adfs_inode_cachep;
+
+static struct inode *adfs_alloc_inode(struct super_block *sb)
+{
+	struct adfs_inode_info *ei;
+	ei = (struct adfs_inode_info *)kmem_cache_alloc(adfs_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void adfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct adfs_inode_info *ei = (struct adfs_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
+					     sizeof(struct adfs_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (adfs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(adfs_inode_cachep))
+		printk(KERN_INFO "adfs_inode_cache: not all structures were freed\n");
+}
+
 static struct super_operations adfs_sops = {
+	alloc_inode:	adfs_alloc_inode,
+	destroy_inode:	adfs_destroy_inode,
 	write_inode:	adfs_write_inode,
 	put_super:	adfs_put_super,
 	statfs:		adfs_statfs,
@@ -435,12 +479,23 @@
 
 static int __init init_adfs_fs(void)
 {
-	return register_filesystem(&adfs_fs_type);
+	int err = init_inodecache();
+	if (err)
+		goto out1;
+	err = register_filesystem(&adfs_fs_type);
+	if (err)
+		goto out;
+	return 0;
+out:
+	destroy_inodecache();
+out1:
+	return err;
 }
 
 static void __exit exit_adfs_fs(void)
 {
 	unregister_filesystem(&adfs_fs_type);
+	destroy_inodecache();
 }
 
 EXPORT_NO_SYMBOLS;
diff -urN linux-2.5.3-pre5/fs/bfs/bfs_defs.h linux/fs/bfs/bfs_defs.h
--- linux-2.5.3-pre5/fs/bfs/bfs_defs.h	Sun Feb  6 18:43:21 2000
+++ linux/fs/bfs/bfs_defs.h	Mon Jan 28 13:46:25 2002
@@ -9,9 +9,6 @@
 #define su_sbh		u.bfs_sb.si_sbh
 #define su_bfs_sb	u.bfs_sb.si_bfs_sb
 
-#define iu_dsk_ino	u.bfs_i.i_dsk_ino
-#define iu_sblock	u.bfs_i.i_sblock
-#define iu_eblock	u.bfs_i.i_eblock
-
 #define printf(format, args...) \
-	printk(KERN_ERR "BFS-fs: " __FUNCTION__ "(): " format, ## args)
+	printk(KERN_ERR "BFS-fs: %s(): " format, __FUNCTION__, ## args)
+
diff -urN linux-2.5.3-pre5/fs/bfs/dir.c linux/fs/bfs/dir.c
--- linux-2.5.3-pre5/fs/bfs/dir.c	Fri Jan  4 09:42:12 2002
+++ linux/fs/bfs/dir.c	Mon Jan 28 13:46:25 2002
@@ -39,7 +39,7 @@
 
 	while (f->f_pos < dir->i_size) {
 		offset = f->f_pos & (BFS_BSIZE-1);
-		block = dir->iu_sblock + (f->f_pos >> BFS_BSIZE_BITS);
+		block = BFS_I(dir)->i_sblock + (f->f_pos >> BFS_BSIZE_BITS);
 		bh = sb_bread(dir->i_sb, block);
 		if (!bh) {
 			f->f_pos += BFS_BSIZE - offset;
@@ -97,8 +97,10 @@
 	inode->i_fop = &bfs_file_operations;
 	inode->i_mapping->a_ops = &bfs_aops;
 	inode->i_mode = mode;
-	inode->i_ino = inode->iu_dsk_ino = ino;
-	inode->iu_sblock = inode->iu_eblock = 0;
+	inode->i_ino = ino;
+	BFS_I(inode)->i_dsk_ino = ino;
+	BFS_I(inode)->i_sblock = 0;
+	BFS_I(inode)->i_eblock = 0;
 	insert_inode_hash(inode);
         mark_inode_dirty(inode);
 	dump_imap("create",s);
@@ -262,8 +264,8 @@
 	if (namelen > BFS_NAMELEN)
 		return -ENAMETOOLONG;
 
-	sblock = dir->iu_sblock;
-	eblock = dir->iu_eblock;
+	sblock = BFS_I(dir)->i_sblock;
+	eblock = BFS_I(dir)->i_eblock;
 	for (block=sblock; block<=eblock; block++) {
 		bh = sb_bread(dir->i_sb, block);
 		if(!bh) 
@@ -313,7 +315,7 @@
 	block = offset = 0;
 	while (block * BFS_BSIZE + offset < dir->i_size) {
 		if (!bh) {
-			bh = sb_bread(dir->i_sb, dir->iu_sblock + block);
+			bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block);
 			if (!bh) {
 				block++;
 				continue;
diff -urN linux-2.5.3-pre5/fs/bfs/file.c linux/fs/bfs/file.c
--- linux-2.5.3-pre5/fs/bfs/file.c	Thu Dec 27 08:17:43 2001
+++ linux/fs/bfs/file.c	Mon Jan 28 13:46:25 2002
@@ -60,14 +60,15 @@
 	long phys;
 	int err;
 	struct super_block *sb = inode->i_sb;
+	struct bfs_inode_info *bi = BFS_I(inode);
 	struct buffer_head *sbh = sb->su_sbh;
 
 	if (block < 0 || block > sb->su_blocks)
 		return -EIO;
 
-	phys = inode->iu_sblock + block;
+	phys = bi->i_sblock + block;
 	if (!create) {
-		if (phys <= inode->iu_eblock) {
+		if (phys <= bi->i_eblock) {
 			dprintf("c=%d, b=%08lx, phys=%08lx (granted)\n", create, block, phys);
 			map_bh(bh_result, sb, phys);
 		}
@@ -76,7 +77,7 @@
 
 	/* if the file is not empty and the requested block is within the range
 	   of blocks allocated for this file, we can grant it */
-	if (inode->i_size && phys <= inode->iu_eblock) {
+	if (inode->i_size && phys <= bi->i_eblock) {
 		dprintf("c=%d, b=%08lx, phys=%08lx (interim block granted)\n", 
 				create, block, phys);
 		map_bh(bh_result, sb, phys);
@@ -88,12 +89,12 @@
 
 	/* if the last data block for this file is the last allocated block, we can
 	   extend the file trivially, without moving it anywhere */
-	if (inode->iu_eblock == sb->su_lf_eblk) {
+	if (bi->i_eblock == sb->su_lf_eblk) {
 		dprintf("c=%d, b=%08lx, phys=%08lx (simple extension)\n", 
 				create, block, phys);
 		map_bh(bh_result, sb, phys);
-		sb->su_freeb -= phys - inode->iu_eblock;
-		sb->su_lf_eblk = inode->iu_eblock = phys;
+		sb->su_freeb -= phys - bi->i_eblock;
+		sb->su_lf_eblk = bi->i_eblock = phys;
 		mark_inode_dirty(inode);
 		mark_buffer_dirty(sbh);
 		err = 0;
@@ -102,9 +103,9 @@
 
 	/* Ok, we have to move this entire file to the next free block */
 	phys = sb->su_lf_eblk + 1;
-	if (inode->iu_sblock) { /* if data starts on block 0 then there is no data */
-		err = bfs_move_blocks(inode->i_sb, inode->iu_sblock, 
-				inode->iu_eblock, phys);
+	if (bi->i_sblock) { /* if data starts on block 0 then there is no data */
+		err = bfs_move_blocks(inode->i_sb, bi->i_sblock, 
+				bi->i_eblock, phys);
 		if (err) {
 			dprintf("failed to move ino=%08lx -> fs corruption\n", inode->i_ino);
 			goto out;
@@ -113,13 +114,13 @@
 		err = 0;
 
 	dprintf("c=%d, b=%08lx, phys=%08lx (moved)\n", create, block, phys);
-	inode->iu_sblock = phys;
+	bi->i_sblock = phys;
 	phys += block;
-	sb->su_lf_eblk = inode->iu_eblock = phys;
+	sb->su_lf_eblk = bi->i_eblock = phys;
 
 	/* this assumes nothing can write the inode back while we are here
 	 * and thus update inode->i_blocks! (XXX)*/
-	sb->su_freeb -= inode->iu_eblock - inode->iu_sblock + 1 - inode->i_blocks;
+	sb->su_freeb -= bi->i_eblock - bi->i_sblock + 1 - inode->i_blocks;
 	mark_inode_dirty(inode);
 	mark_buffer_dirty(sbh);
 	map_bh(bh_result, sb, phys);
diff -urN linux-2.5.3-pre5/fs/bfs/inode.c linux/fs/bfs/inode.c
--- linux-2.5.3-pre5/fs/bfs/inode.c	Fri Jan  4 09:42:12 2002
+++ linux/fs/bfs/inode.c	Mon Jan 28 13:46:25 2002
@@ -77,9 +77,9 @@
 	inode->i_atime = di->i_atime;
 	inode->i_mtime = di->i_mtime;
 	inode->i_ctime = di->i_ctime;
-	inode->iu_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
-	inode->iu_sblock = di->i_sblock;
-	inode->iu_eblock = di->i_eblock;
+	BFS_I(inode)->i_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
+	BFS_I(inode)->i_sblock = di->i_sblock;
+	BFS_I(inode)->i_eblock = di->i_eblock;
 
 	brelse(bh);
 }
@@ -121,8 +121,8 @@
 	di->i_atime = inode->i_atime;
 	di->i_mtime = inode->i_mtime;
 	di->i_ctime = inode->i_ctime;
-	di->i_sblock = inode->iu_sblock;
-	di->i_eblock = inode->iu_eblock;
+	di->i_sblock = BFS_I(inode)->i_sblock;
+	di->i_eblock = BFS_I(inode)->i_eblock;
 	di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
 
 	mark_buffer_dirty(bh);
@@ -172,8 +172,8 @@
 	/* if this was the last file, make the previous 
 	   block "last files last block" even if there is no real file there,
 	   saves us 1 gap */
-	if (s->su_lf_eblk == inode->iu_eblock) {
-		s->su_lf_eblk = inode->iu_sblock - 1;
+	if (s->su_lf_eblk == BFS_I(inode)->i_eblock) {
+		s->su_lf_eblk = BFS_I(inode)->i_sblock - 1;
 		mark_buffer_dirty(s->su_sbh);
 	}
 	unlock_kernel();
@@ -206,7 +206,51 @@
 	s->s_dirt = 0;
 }
 
+static kmem_cache_t * bfs_inode_cachep;
+
+static struct inode *bfs_alloc_inode(struct super_block *sb)
+{
+	struct bfs_inode_info *bi;
+	bi = kmem_cache_alloc(bfs_inode_cachep, SLAB_KERNEL);
+	if (!bi)
+		return NULL;
+	return &bi->vfs_inode;
+}
+
+static void bfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(bfs_inode_cachep, BFS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct bfs_inode_info *bi = foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&bi->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
+					     sizeof(struct bfs_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (bfs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(bfs_inode_cachep))
+		printk(KERN_INFO "bfs_inode_cache: not all structures were freed\n");
+}
+
 static struct super_operations bfs_sops = {
+	alloc_inode:	bfs_alloc_inode,
+	destroy_inode:	bfs_destroy_inode,
 	read_inode:	bfs_read_inode,
 	write_inode:	bfs_write_inode,
 	delete_inode:	bfs_delete_inode,
@@ -293,14 +337,14 @@
 	s->su_lf_ioff = 0;
 	for (i=BFS_ROOT_INO; i<=s->su_lasti; i++) {
 		inode = iget(s,i);
-		if (inode->iu_dsk_ino == 0)
+		if (BFS_I(inode)->i_dsk_ino == 0)
 			s->su_freei++;
 		else {
 			set_bit(i, s->su_imap);
 			s->su_freeb -= inode->i_blocks;
-			if (inode->iu_eblock > s->su_lf_eblk) {
-				s->su_lf_eblk = inode->iu_eblock;
-				s->su_lf_sblk = inode->iu_sblock;
+			if (BFS_I(inode)->i_eblock > s->su_lf_eblk) {
+				s->su_lf_eblk = BFS_I(inode)->i_eblock;
+				s->su_lf_sblk = BFS_I(inode)->i_sblock;
 				s->su_lf_ioff = BFS_INO2OFF(i);
 			}
 		}
@@ -322,12 +366,23 @@
 
 static int __init init_bfs_fs(void)
 {
-	return register_filesystem(&bfs_fs_type);
+	int err = init_inodecache();
+	if (err)
+		goto out1;
+        err = register_filesystem(&bfs_fs_type);
+	if (err)
+		goto out;
+	return 0;
+out:
+	destroy_inodecache();
+out1:
+	return err;
 }
 
 static void __exit exit_bfs_fs(void)
 {
 	unregister_filesystem(&bfs_fs_type);
+	destroy_inodecache();
 }
 
 module_init(init_bfs_fs)
diff -urN linux-2.5.3-pre5/fs/buffer.c linux/fs/buffer.c
--- linux-2.5.3-pre5/fs/buffer.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/buffer.c	Mon Jan 28 13:46:25 2002
@@ -724,6 +724,7 @@
 	wakeup_bdflush();
 	try_to_free_pages(zone, GFP_NOFS, 0);
 	run_task_queue(&tq_disk);
+	__set_current_state(TASK_RUNNING);
 	yield();
 }
 
diff -urN linux-2.5.3-pre5/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- linux-2.5.3-pre5/fs/ext2/ialloc.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/ext2/ialloc.c	Mon Jan 28 13:46:25 2002
@@ -392,6 +392,7 @@
 		ei->i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL);
 	ei->i_faddr = 0;
 	ei->i_frag_no = 0;
+	ei->i_frag_size = 0;
 	ei->i_osync = 0;
 	ei->i_file_acl = 0;
 	ei->i_dir_acl = 0;
diff -urN linux-2.5.3-pre5/fs/ext2/inode.c linux/fs/ext2/inode.c
--- linux-2.5.3-pre5/fs/ext2/inode.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/ext2/inode.c	Mon Jan 28 13:46:25 2002
@@ -963,6 +963,7 @@
 	ei->i_frag_size = raw_inode->i_fsize;
 	ei->i_osync = 0;
 	ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
+	ei->i_dir_acl = 0;
 	if (S_ISREG(inode->i_mode))
 		inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
 	else
diff -urN linux-2.5.3-pre5/fs/fat/buffer.c linux/fs/fat/buffer.c
--- linux-2.5.3-pre5/fs/fat/buffer.c	Sun Dec 16 12:23:00 2001
+++ linux/fs/fat/buffer.c	Mon Jan 28 13:46:25 2002
@@ -4,19 +4,10 @@
  *
  */
 
-#include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/blkdev.h>
 #include <linux/msdos_fs.h>
 #include <linux/fat_cvf.h>
-
-#if 0
-#  define PRINTK(x) printk x
-#else
-#  define PRINTK(x)
-#endif
 
 struct buffer_head *fat_bread(struct super_block *sb, int block)
 {
diff -urN linux-2.5.3-pre5/fs/fat/cache.c linux/fs/fat/cache.c
--- linux-2.5.3-pre5/fs/fat/cache.c	Mon Jan 14 09:38:36 2002
+++ linux/fs/fat/cache.c	Mon Jan 28 13:46:25 2002
@@ -8,11 +8,8 @@
  *  May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
  */
 
+#include <linux/fs.h>
 #include <linux/msdos_fs.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
 #include <linux/fat_cvf.h>
 
 #if 0
diff -urN linux-2.5.3-pre5/fs/fat/cvf.c linux/fs/fat/cvf.c
--- linux-2.5.3-pre5/fs/fat/cvf.c	Tue Jul 24 14:23:53 2001
+++ linux/fs/fat/cvf.c	Mon Jan 28 13:46:25 2002
@@ -8,15 +8,13 @@
  *
  */
  
-#include<linux/sched.h>
-#include<linux/fs.h>
-#include<linux/msdos_fs.h>
-#include<linux/msdos_fs_sb.h>
-#include<linux/string.h>
-#include<linux/fat_cvf.h>
-#include<linux/config.h>
+#include <linux/fs.h>
+#include <linux/msdos_fs.h>
+#include <linux/msdos_fs_sb.h>
+#include <linux/fat_cvf.h>
+#include <linux/config.h>
 #ifdef CONFIG_KMOD
-#include<linux/kmod.h>
+#include <linux/kmod.h>
 #endif
 
 #define MAX_CVF_FORMATS 3
diff -urN linux-2.5.3-pre5/fs/fat/dir.c linux/fs/fat/dir.c
--- linux-2.5.3-pre5/fs/fat/dir.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/fat/dir.c	Mon Jan 28 13:46:25 2002
@@ -13,17 +13,10 @@
  *  Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de>
  */
 
-#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/msdos_fs.h>
-#include <linux/nls.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/ioctl.h>
 #include <linux/dirent.h>
-#include <linux/mm.h>
-#include <linux/ctype.h>
 
 #include <asm/uaccess.h>
 
diff -urN linux-2.5.3-pre5/fs/fat/fatfs_syms.c linux/fs/fat/fatfs_syms.c
--- linux-2.5.3-pre5/fs/fat/fatfs_syms.c	Fri Oct 12 13:48:42 2001
+++ linux/fs/fat/fatfs_syms.c	Mon Jan 28 13:46:25 2002
@@ -39,10 +39,13 @@
 EXPORT_SYMBOL(fat_truncate);
 EXPORT_SYMBOL(fat_brelse);
 
+int __init fat_init_inodecache(void);
+void __exit fat_destroy_inodecache(void);
 static int __init init_fat_fs(void)
 {
 	fat_hash_init();
-	return 0;
+	return fat_init_inodecache();
 }
 
 module_init(init_fat_fs)
+module_exit(fat_destroy_inodecache)
diff -urN linux-2.5.3-pre5/fs/fat/file.c linux/fs/fat/file.c
--- linux-2.5.3-pre5/fs/fat/file.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/fat/file.c	Mon Jan 28 13:46:25 2002
@@ -8,17 +8,8 @@
 
 #include <linux/sched.h>
 #include <linux/locks.h>
-#include <linux/fs.h>
 #include <linux/msdos_fs.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/pagemap.h>
 #include <linux/fat_cvf.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
 
 #define PRINTK(x)
 #define Printk(x) printk x
diff -urN linux-2.5.3-pre5/fs/fat/inode.c linux/fs/fat/inode.c
--- linux-2.5.3-pre5/fs/fat/inode.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/fat/inode.c	Mon Jan 28 13:46:25 2002
@@ -11,23 +11,14 @@
  */
 
 #include <linux/module.h>
-#include <linux/msdos_fs.h>
-#include <linux/nls.h>
-#include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <linux/major.h>
-#include <linux/blkdev.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
 #include <linux/locks.h>
-#include <linux/fat_cvf.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
+#include <linux/msdos_fs.h>
+#include <linux/fat_cvf.h>
 
-#include <asm/uaccess.h>
+//#include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
 extern struct cvf_format default_cvf;
@@ -103,8 +94,7 @@
 {
 	spin_lock(&fat_inode_lock);
 	MSDOS_I(inode)->i_location = 0;
-	list_del(&MSDOS_I(inode)->i_fat_hash);
-	INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
+	list_del_init(&MSDOS_I(inode)->i_fat_hash);
 	spin_unlock(&fat_inode_lock);
 }
 
@@ -118,11 +108,11 @@
 	spin_lock(&fat_inode_lock);
 	list_for_each(walk, p) {
 		i = list_entry(walk, struct msdos_inode_info, i_fat_hash);
-		if (i->i_fat_inode->i_sb != sb)
+		if (i->vfs_inode.i_sb != sb)
 			continue;
 		if (i->i_location != i_pos)
 			continue;
-		inode = igrab(i->i_fat_inode);
+		inode = igrab(&i->vfs_inode);
 		if (inode)
 			break;
 	}
@@ -172,7 +162,7 @@
 	lock_kernel();
 	spin_lock(&fat_inode_lock);
 	fat_cache_inval_inode(inode);
-	list_del(&MSDOS_I(inode)->i_fat_hash);
+	list_del_init(&MSDOS_I(inode)->i_fat_hash);
 	spin_unlock(&fat_inode_lock);
 	unlock_kernel();
 }
@@ -397,9 +387,7 @@
 	struct super_block *sb = inode->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-	INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
 	MSDOS_I(inode)->i_location = 0;
-	MSDOS_I(inode)->i_fat_inode = inode;
 	inode->i_uid = sbi->options.fs_uid;
 	inode->i_gid = sbi->options.fs_gid;
 	inode->i_version++;
@@ -533,7 +521,53 @@
 	return 3;
 }
 
+static kmem_cache_t *fat_inode_cachep;
+
+static struct inode *fat_alloc_inode(struct super_block *sb)
+{
+	struct msdos_inode_info *ei;
+	ei = (struct msdos_inode_info *)kmem_cache_alloc(fat_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void fat_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct msdos_inode_info *ei = (struct msdos_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR) {
+		INIT_LIST_HEAD(&ei->i_fat_hash);
+		inode_init_once(&ei->vfs_inode);
+	}
+}
+ 
+int __init fat_init_inodecache(void)
+{
+	fat_inode_cachep = kmem_cache_create("fat_inode_cache",
+					     sizeof(struct msdos_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (fat_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+void __exit fat_destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(fat_inode_cachep))
+		printk(KERN_INFO "fat_inode_cache: not all structures were freed\n");
+}
+
 static struct super_operations fat_sops = { 
+	alloc_inode:	fat_alloc_inode,
+	destroy_inode:	fat_destroy_inode,
 	write_inode:	fat_write_inode,
 	delete_inode:	fat_delete_inode,
 	put_super:	fat_put_super,
@@ -872,9 +906,7 @@
 	struct super_block *sb = inode->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 
-	INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
 	MSDOS_I(inode)->i_location = 0;
-	MSDOS_I(inode)->i_fat_inode = inode;
 	inode->i_uid = sbi->options.fs_uid;
 	inode->i_gid = sbi->options.fs_gid;
 	inode->i_version++;
diff -urN linux-2.5.3-pre5/fs/fat/misc.c linux/fs/fat/misc.c
--- linux-2.5.3-pre5/fs/fat/misc.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/fat/misc.c	Mon Jan 28 13:46:25 2002
@@ -8,11 +8,6 @@
 
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
 
 #if 0
 #  define PRINTK(x)	printk x
diff -urN linux-2.5.3-pre5/fs/hfs/inode.c linux/fs/hfs/inode.c
--- linux-2.5.3-pre5/fs/hfs/inode.c	Fri Jan  4 09:37:49 2002
+++ linux/fs/hfs/inode.c	Mon Jan 28 13:46:25 2002
@@ -233,7 +233,7 @@
 static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 {
 	return cont_prepare_write(page,from,to,hfs_get_block,
-		&page->mapping->host->u.hfs_i.mmu_private);
+		&HFS_I(page->mapping->host)->mmu_private);
 }
 static int hfs_bmap(struct address_space *mapping, long block)
 {
@@ -322,7 +322,13 @@
 		inode->i_uid = hsb->s_uid;
 		inode->i_gid = hsb->s_gid;
 
-		memset(HFS_I(inode), 0, sizeof(struct hfs_inode_info));
+		HFS_I(inode)->mmu_private = 0;
+		HFS_I(inode)->fork = NULL;
+		HFS_I(inode)->convert = 0;
+		HFS_I(inode)->file_type = 0;
+		HFS_I(inode)->dir_size = 0;
+		HFS_I(inode)->default_layout = NULL;
+		HFS_I(inode)->layout = NULL;
 		HFS_I(inode)->magic = HFS_INO_MAGIC;
 		HFS_I(inode)->entry = entry;
 		HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
@@ -372,7 +378,7 @@
 		inode->i_op = &hfs_file_inode_operations;
 		inode->i_fop = &hfs_file_operations;
 		inode->i_mapping->a_ops = &hfs_aops;
-		inode->u.hfs_i.mmu_private = inode->i_size;
+		HFS_I(inode)->mmu_private = inode->i_size;
 	} else { /* Directory */
 		struct hfs_dir *hdir = &entry->u.dir;
 
@@ -432,7 +438,7 @@
 		inode->i_op = &hfs_file_inode_operations;
 		inode->i_fop = &hfs_file_operations;
 		inode->i_mapping->a_ops = &hfs_aops;
-		inode->u.hfs_i.mmu_private = inode->i_size;
+		HFS_I(inode)->mmu_private = inode->i_size;
 	} else { /* Directory */
 		struct hfs_dir *hdir = &entry->u.dir;
 
@@ -478,7 +484,7 @@
 		inode->i_op = &hfs_file_inode_operations;
 		inode->i_fop = &hfs_file_operations;
 		inode->i_mapping->a_ops = &hfs_aops;
-		inode->u.hfs_i.mmu_private = inode->i_size;
+		HFS_I(inode)->mmu_private = inode->i_size;
 	} else { /* Directory */
 		struct hfs_dir *hdir = &entry->u.dir;
 
diff -urN linux-2.5.3-pre5/fs/hfs/super.c linux/fs/hfs/super.c
--- linux-2.5.3-pre5/fs/hfs/super.c	Fri Jan  4 09:42:12 2002
+++ linux/fs/hfs/super.c	Mon Jan 28 13:46:25 2002
@@ -39,9 +39,53 @@
 static int hfs_statfs(struct super_block *, struct statfs *);
 static void hfs_write_super(struct super_block *);
 
+static kmem_cache_t * hfs_inode_cachep;
+
+static struct inode *hfs_alloc_inode(struct super_block *sb)
+{
+	struct hfs_inode_info *ei;
+	ei = (struct hfs_inode_info *)kmem_cache_alloc(hfs_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void hfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(hfs_inode_cachep, HFS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct hfs_inode_info *ei = (struct hfs_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	hfs_inode_cachep = kmem_cache_create("hfs_inode_cache",
+					     sizeof(struct hfs_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (hfs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(hfs_inode_cachep))
+		printk(KERN_INFO "hfs_inode_cache: not all structures were freed\n");
+}
+
 /*================ Global variables ================*/
 
 static struct super_operations hfs_super_operations = { 
+	alloc_inode:	hfs_alloc_inode,
+	destroy_inode:	hfs_destroy_inode,
 	read_inode:	hfs_read_inode,
 	put_inode:	hfs_put_inode,
 	put_super:	hfs_put_super,
@@ -472,13 +516,25 @@
 
 static int __init init_hfs_fs(void)
 {
+	int err = init_inodecache();
+	if (err)
+		goto out1;
         hfs_cat_init();
-	return register_filesystem(&hfs_fs);
+	err = register_filesystem(&hfs_fs);
+	if (err)
+		goto out;
+	return 0;
+out:
+	hfs_cat_free();
+	destroy_inodecache();
+out1:
+	return err;
 }
 
 static void __exit exit_hfs_fs(void) {
 	hfs_cat_free();
 	unregister_filesystem(&hfs_fs);
+	destroy_inodecache();
 }
 
 module_init(init_hfs_fs)
diff -urN linux-2.5.3-pre5/fs/isofs/compress.c linux/fs/isofs/compress.c
--- linux-2.5.3-pre5/fs/isofs/compress.c	Tue Nov  6 08:34:40 2001
+++ linux/fs/isofs/compress.c	Mon Jan 28 13:46:25 2002
@@ -72,8 +72,8 @@
 	unsigned long bufmask  = bufsize - 1;
 	int err = -EIO;
 	int i;
-	unsigned int header_size = inode->u.isofs_i.i_format_parm[0];
-	unsigned int zisofs_block_shift = inode->u.isofs_i.i_format_parm[1];
+	unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
+	unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
 	/* unsigned long zisofs_block_size = 1UL << zisofs_block_shift; */
 	unsigned int zisofs_block_page_shift = zisofs_block_shift-PAGE_CACHE_SHIFT;
 	unsigned long zisofs_block_pages = 1UL << zisofs_block_page_shift;
diff -urN linux-2.5.3-pre5/fs/isofs/inode.c linux/fs/isofs/inode.c
--- linux-2.5.3-pre5/fs/isofs/inode.c	Fri Jan  4 09:42:12 2002
+++ linux/fs/isofs/inode.c	Mon Jan 28 13:46:25 2002
@@ -78,7 +78,51 @@
 static void isofs_read_inode(struct inode *);
 static int isofs_statfs (struct super_block *, struct statfs *);
 
+static kmem_cache_t *isofs_inode_cachep;
+
+static struct inode *isofs_alloc_inode(struct super_block *sb)
+{
+	struct iso_inode_info *ei;
+	ei = (struct iso_inode_info *)kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void isofs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct iso_inode_info *ei = (struct iso_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
+					     sizeof(struct iso_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (isofs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(isofs_inode_cachep))
+		printk(KERN_INFO "iso_inode_cache: not all structures were freed\n");
+}
+
 static struct super_operations isofs_sops = {
+	alloc_inode:	isofs_alloc_inode,
+	destroy_inode:	isofs_destroy_inode,
 	read_inode:	isofs_read_inode,
 	put_super:	isofs_put_super,
 	statfs:		isofs_statfs,
@@ -871,6 +915,7 @@
 	unsigned int firstext;
 	unsigned long nextino;
 	int section, rv;
+	struct iso_inode_info *ei = ISOFS_I(inode);
 
 	lock_kernel();
 
@@ -883,9 +928,9 @@
 	b_off = iblock;
 	
 	offset    = 0;
-	firstext  = inode->u.isofs_i.i_first_extent;
-	sect_size = inode->u.isofs_i.i_section_size >> ISOFS_BUFFER_BITS(inode);
-	nextino   = inode->u.isofs_i.i_next_section_ino;
+	firstext  = ei->i_first_extent;
+	sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode);
+	nextino   = ei->i_next_section_ino;
 	section   = 0;
 
 	while ( nblocks ) {
@@ -912,9 +957,9 @@
 				ninode = iget(inode->i_sb, nextino);
 				if (!ninode)
 					goto abort;
-				firstext  = ninode->u.isofs_i.i_first_extent;
-				sect_size = ninode->u.isofs_i.i_section_size;
-				nextino   = ninode->u.isofs_i.i_next_section_ino;
+				firstext  = ISOFS_I(ninode)->i_first_extent;
+				sect_size = ISOFS_I(ninode)->i_section_size;
+				nextino   = ISOFS_I(ninode)->i_next_section_ino;
 				iput(ninode);
 				
 				if (++section > 100) {
@@ -1020,9 +1065,10 @@
 	int i = 0;
 	int more_entries = 0;
 	struct iso_directory_record * tmpde = NULL;
+	struct iso_inode_info *ei = ISOFS_I(inode);
 
 	inode->i_size = 0;
-	inode->u.isofs_i.i_next_section_ino = 0;
+	ei->i_next_section_ino = 0;
 
 	block = f_pos >> ISOFS_BUFFER_BITS(inode);
 	offset = f_pos & (bufsize-1);
@@ -1074,7 +1120,7 @@
 
 		inode->i_size += isonum_733(de->size);
 		if (i == 1)
-			inode->u.isofs_i.i_next_section_ino = f_pos;
+			ei->i_next_section_ino = f_pos;
 
 		more_entries = de->flags[-high_sierra] & 0x80;
 
@@ -1121,6 +1167,7 @@
 	unsigned int de_len;
 	unsigned long offset;
 	int volume_seq_no, i;
+	struct iso_inode_info *ei = ISOFS_I(inode);
 
 	bh = sb_bread(inode->i_sb, block);
 	if (!bh)
@@ -1148,7 +1195,7 @@
 	}
 
 	/* Assume it is a normal-format file unless told otherwise */
-	inode->u.isofs_i.i_file_format = isofs_file_normal;
+	ei->i_file_format = isofs_file_normal;
 
 	if (de->flags[-high_sierra] & 2) {
 		inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
@@ -1175,11 +1222,15 @@
 	inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
 	inode->i_blocks = inode->i_blksize = 0;
 
+	ei->i_format_parm[0] = 0;
+	ei->i_format_parm[1] = 0;
+	ei->i_format_parm[2] = 0;
 
-	inode->u.isofs_i.i_section_size = isonum_733 (de->size);
+	ei->i_section_size = isonum_733 (de->size);
 	if(de->flags[-high_sierra] & 0x80) {
 		if(isofs_read_level3_size(inode)) goto fail;
 	} else {
+		ei->i_next_section_ino = 0;
 		inode->i_size = isonum_733 (de->size);
 	}
 
@@ -1233,7 +1284,7 @@
 	inode->i_mtime = inode->i_atime = inode->i_ctime =
 		iso_date(de->date, high_sierra);
 
-	inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) +
+	ei->i_first_extent = (isonum_733 (de->extent) +
 					   isonum_711 (de->ext_attr_length));
 
 	/* Set the number of blocks for stat() - should be done before RR */
@@ -1279,7 +1330,7 @@
 	{
 		if (S_ISREG(inode->i_mode)) {
 			inode->i_fop = &generic_ro_fops;
-			switch ( inode->u.isofs_i.i_file_format ) {
+			switch ( ei->i_file_format ) {
 #ifdef CONFIG_ZISOFS
 			case isofs_file_compressed:
 				inode->i_data.a_ops = &zisofs_aops;
@@ -1348,14 +1399,26 @@
 
 static int __init init_iso9660_fs(void)
 {
+	int err = init_inodecache();
+	if (err)
+		goto out;
 #ifdef CONFIG_ZISOFS
-	int err;
-
 	err = zisofs_init();
-	if ( err )
-		return err;
+	if (err)
+		goto out1;
+#endif
+	err = register_filesystem(&iso9660_fs_type);
+	if (err)
+		goto out2;
+	return 0;
+out2:
+#ifdef CONFIG_ZISOFS
+	zisofs_cleanup();
+out1:
 #endif
-        return register_filesystem(&iso9660_fs_type);
+	destroy_inodecache();
+out:
+	return err;
 }
 
 static void __exit exit_iso9660_fs(void)
@@ -1364,6 +1427,7 @@
 #ifdef CONFIG_ZISOFS
 	zisofs_cleanup();
 #endif
+	destroy_inodecache();
 }
 
 EXPORT_NO_SYMBOLS;
diff -urN linux-2.5.3-pre5/fs/isofs/namei.c linux/fs/isofs/namei.c
--- linux-2.5.3-pre5/fs/isofs/namei.c	Sat Dec 29 17:30:07 2001
+++ linux/fs/isofs/namei.c	Mon Jan 28 13:46:25 2002
@@ -65,7 +65,7 @@
 	unsigned int block, f_pos, offset;
 	struct buffer_head * bh = NULL;
 
-	if (!dir->u.isofs_i.i_first_extent)
+	if (!ISOFS_I(dir)->i_first_extent)
 		return 0;
   
 	f_pos = 0;
diff -urN linux-2.5.3-pre5/fs/isofs/rock.c linux/fs/isofs/rock.c
--- linux-2.5.3-pre5/fs/isofs/rock.c	Mon Dec 31 18:27:26 2001
+++ linux/fs/isofs/rock.c	Mon Jan 28 13:46:25 2002
@@ -365,9 +365,9 @@
 	printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
 	goto out;
       case SIG('C','L'):
-	inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
+	ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
 	reloc = iget(inode->i_sb,
-		     (inode->u.isofs_i.i_first_extent <<
+		     (ISOFS_I(inode)->i_first_extent <<
 		      inode -> i_sb -> u.isofs_sb.s_log_zone_size));
 	if (!reloc)
 		goto out;
@@ -394,10 +394,10 @@
 				      printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift);
 			      } else {
 				/* Note: we don't change i_blocks here */
-				      inode->u.isofs_i.i_file_format = isofs_file_compressed;
+				      ISOFS_I(inode)->i_file_format = isofs_file_compressed;
 				/* Parameters to compression algorithm (header size, block size) */
-				      inode->u.isofs_i.i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
-				      inode->u.isofs_i.i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
+				      ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
+				      ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
 				      inode->i_size = isonum_733(rr->u.ZF.real_size);
 			      }
 		      } else {
diff -urN linux-2.5.3-pre5/fs/isofs/util.c linux/fs/isofs/util.c
--- linux-2.5.3-pre5/fs/isofs/util.c	Thu Oct 25 13:53:53 2001
+++ linux/fs/isofs/util.c	Mon Jan 28 13:46:25 2002
@@ -3,6 +3,7 @@
  */
 
 #include <linux/time.h>
+#include <linux/fs.h>
 #include <linux/iso_fs.h>
 
 /* 
diff -urN linux-2.5.3-pre5/fs/jffs/inode-v23.c linux/fs/jffs/inode-v23.c
--- linux-2.5.3-pre5/fs/jffs/inode-v23.c	Fri Jan  4 09:42:12 2002
+++ linux/fs/jffs/inode-v23.c	Mon Jan 28 13:46:25 2002
@@ -357,7 +357,7 @@
 	inode->i_nlink = raw_inode->nlink;
 	inode->i_uid = raw_inode->uid;
 	inode->i_gid = raw_inode->gid;
-	inode->i_rdev = 0;
+	inode->i_rdev = NODEV;
 	inode->i_size = raw_inode->dsize;
 	inode->i_atime = raw_inode->atime;
 	inode->i_mtime = raw_inode->mtime;
diff -urN linux-2.5.3-pre5/fs/jffs/jffs_fm.c linux/fs/jffs/jffs_fm.c
--- linux-2.5.3-pre5/fs/jffs/jffs_fm.c	Thu Oct  4 15:13:18 2001
+++ linux/fs/jffs/jffs_fm.c	Mon Jan 28 13:46:25 2002
@@ -46,7 +46,7 @@
 	}
 	DJM(no_jffs_fmcontrol++);
 
-	mtd = get_mtd_device(NULL, MINOR(dev));
+	mtd = get_mtd_device(NULL, minor(dev));
 
 	if (!mtd) {
 		kfree(fmc);
diff -urN linux-2.5.3-pre5/fs/jffs2/dir.c linux/fs/jffs2/dir.c
--- linux-2.5.3-pre5/fs/jffs2/dir.c	Thu Jan 10 16:23:46 2002
+++ linux/fs/jffs2/dir.c	Mon Jan 28 13:46:25 2002
@@ -42,6 +42,7 @@
 #include <linux/jffs2.h>
 #include <linux/jffs2_fs_i.h>
 #include <linux/jffs2_fs_sb.h>
+#include <linux/sched.h>
 #include "nodelist.h"
 
 static int jffs2_readdir (struct file *, void *, filldir_t);
diff -urN linux-2.5.3-pre5/fs/jffs2/malloc.c linux/fs/jffs2/malloc.c
--- linux-2.5.3-pre5/fs/jffs2/malloc.c	Fri Sep 14 14:04:07 2001
+++ linux/fs/jffs2/malloc.c	Mon Jan 28 13:46:25 2002
@@ -49,6 +49,7 @@
 
 /* These are initialised to NULL in the kernel startup code.
    If you're porting to other operating systems, beware */
+static kmem_cache_t *jffs2_inode_cachep;
 static kmem_cache_t *full_dnode_slab;
 static kmem_cache_t *raw_dirent_slab;
 static kmem_cache_t *raw_inode_slab;
@@ -80,6 +81,31 @@
 	}
 }
 
+struct inode *jffs2_alloc_inode(struct super_block *sb)
+{
+	struct jffs2_inode_info *ei;
+	ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+void jffs2_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR) {
+		init_MUTEX(&ei->sem);
+		inode_init_once(&ei->vfs_inode);
+	}
+}
+
 int __init jffs2_create_slab_caches(void)
 {
 	full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), 0, JFFS2_SLAB_POISON, NULL, NULL);
@@ -106,6 +132,13 @@
 	if (!node_frag_slab)
 		goto err;
 
+	jffs2_inode_cachep = kmem_cache_create("jffs2_inode_cache",
+					     sizeof(struct jffs2_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (!jffs2_inode_cachep)
+		goto err;
+
 	inode_cache_slab = kmem_cache_create("jffs2_inode_cache", sizeof(struct jffs2_inode_cache), 0, JFFS2_SLAB_POISON, NULL, NULL);
 
 	if (inode_cache_slab)
@@ -131,6 +164,8 @@
 		kmem_cache_destroy(node_frag_slab);
 	if(inode_cache_slab)
 		kmem_cache_destroy(inode_cache_slab);
+	if(jffs2_inode_cachep)
+		kmem_cache_destroy(jffs2_inode_cachep);
 
 }
 
diff -urN linux-2.5.3-pre5/fs/jffs2/readinode.c linux/fs/jffs2/readinode.c
--- linux-2.5.3-pre5/fs/jffs2/readinode.c	Thu Jan 10 16:23:46 2002
+++ linux/fs/jffs2/readinode.c	Mon Jan 28 13:46:25 2002
@@ -259,9 +259,13 @@
 	f = JFFS2_INODE_INFO(inode);
 	c = JFFS2_SB_INFO(inode->i_sb);
 
-	memset(f, 0, sizeof(*f));
+	f->highest_version = 0;
+	f->fraglist = NULL;
+	f->metadata = NULL;
+	f->dents = NULL;
+	f->flags = 0;
+	f->usercompr = 0;
 	D2(printk(KERN_DEBUG "getting inocache\n"));
-	init_MUTEX(&f->sem);
 	f->inocache = jffs2_get_ino_cache(c, inode->i_ino);
 	D2(printk(KERN_DEBUG "jffs2_read_inode(): Got inocache at %p\n", f->inocache));
 
@@ -437,7 +441,7 @@
 	case S_IFSOCK:
 	case S_IFIFO:
 		inode->i_op = &jffs2_file_inode_operations;
-		init_special_inode(inode, inode->i_mode, kdev_t_to_nr(MKDEV(rdev>>8, rdev&0xff)));
+		init_special_inode(inode, inode->i_mode, kdev_t_to_nr(mk_kdev(rdev>>8, rdev&0xff)));
 		break;
 
 	default:
diff -urN linux-2.5.3-pre5/fs/jffs2/super.c linux/fs/jffs2/super.c
--- linux-2.5.3-pre5/fs/jffs2/super.c	Fri Jan  4 09:42:12 2002
+++ linux/fs/jffs2/super.c	Mon Jan 28 13:46:25 2002
@@ -59,9 +59,13 @@
 static int jffs2_statfs (struct super_block *, struct statfs *);
 int jffs2_remount_fs (struct super_block *, int *, char *);
 extern void jffs2_clear_inode (struct inode *);
-
+extern void jffs2_destroy_inode (struct inode *);
+extern struct inode *jffs2_alloc_inode (struct super_block *);
+ 
 static struct super_operations jffs2_super_operations =
 {
+	alloc_inode:	jffs2_alloc_inode,
+	destroy_inode:	jffs2_destroy_inode,
 	read_inode:	jffs2_read_inode,
 //	delete_inode:	jffs2_delete_inode,
 	put_super:	jffs2_put_super,
@@ -208,7 +212,7 @@
 	c = JFFS2_SB_INFO(sb);
 	memset(c, 0, sizeof(*c));
 	
-	c->mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
+	c->mtd = get_mtd_device(NULL, minor(sb->s_dev));
 	if (!c->mtd) {
 		D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev)));
 		return NULL;
@@ -350,12 +354,6 @@
 	if (sizeof(struct jffs2_sb_info) > sizeof (((struct super_block *)NULL)->u)) {
 		printk(KERN_ERR "JFFS2 error: struct jffs2_sb_info (%d bytes) doesn't fit in the super_block union (%d bytes)\n", 
 		       sizeof(struct jffs2_sb_info), sizeof (((struct super_block *)NULL)->u));
-		return -EIO;
-	}
-
-	if (sizeof(struct jffs2_inode_info) > sizeof (((struct inode *)NULL)->u)) {
-		printk(KERN_ERR "JFFS2 error: struct jffs2_inode_info (%d bytes) doesn't fit in the inode union (%d bytes)\n", 
-		       sizeof(struct jffs2_inode_info), sizeof (((struct inode *)NULL)->u));
 		return -EIO;
 	}
 #endif
diff -urN linux-2.5.3-pre5/fs/jffs2/write.c linux/fs/jffs2/write.c
--- linux-2.5.3-pre5/fs/jffs2/write.c	Thu Jan 10 16:23:46 2002
+++ linux/fs/jffs2/write.c	Mon Jan 28 13:46:25 2002
@@ -73,8 +73,13 @@
 	/* Alloc jffs2_inode_info when that's split in 2.5 */
 
 	f = JFFS2_INODE_INFO(inode);
-	memset(f, 0, sizeof(*f));
-	init_MUTEX_LOCKED(&f->sem);
+	down(&f->sem);
+	f->highest_version = 0;
+	f->fraglist = NULL;
+	f->metadata = NULL;
+	f->dents = NULL;
+	f->flags = 0;
+	f->usercompr = 0;
 	f->inocache = ic;
 	inode->i_nlink = f->inocache->nlink = 1;
 	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
diff -urN linux-2.5.3-pre5/fs/msdos/namei.c linux/fs/msdos/namei.c
--- linux-2.5.3-pre5/fs/msdos/namei.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/msdos/namei.c	Mon Jan 28 13:46:25 2002
@@ -12,10 +12,6 @@
 
 #include <linux/sched.h>
 #include <linux/msdos_fs.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include <asm/uaccess.h>
 
 #define MSDOS_DEBUG 0
 #define PRINTK(x)
diff -urN linux-2.5.3-pre5/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- linux-2.5.3-pre5/fs/ntfs/fs.c	Tue Dec 25 15:39:20 2001
+++ linux/fs/ntfs/fs.c	Mon Jan 28 13:46:25 2002
@@ -68,7 +68,7 @@
 	int error;
 	ntfs_io io;
 	ntfs_attribute *attr;
-	ntfs_inode *ino = NTFS_LINO2NINO(filp->f_dentry->d_inode);
+	ntfs_inode *ino = NTFS_I(filp->f_dentry->d_inode);
 
 	/* Inode is not properly initialized. */
 	if (!ino)
@@ -107,7 +107,7 @@
 {
 	int err;
 	struct inode *vfs_ino = filp->f_dentry->d_inode;
-	ntfs_inode *ntfs_ino = NTFS_LINO2NINO(vfs_ino);
+	ntfs_inode *ntfs_ino = NTFS_I(vfs_ino);
 	ntfs_attribute *data;
 	ntfs_io io;
 	struct ntfs_getuser_update_vm_s param;
@@ -296,7 +296,7 @@
 		ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Looking for next "
 				"file using ntfs_getdir_unsorted(), f_pos "
 				"0x%Lx.\n", (loff_t)(cb.ph << 16) | cb.pl);
-		err = ntfs_getdir_unsorted(NTFS_LINO2NINO(dir), &cb.ph, &cb.pl,
+		err = ntfs_getdir_unsorted(NTFS_I(dir), &cb.ph, &cb.pl,
 				ntfs_printcb, &cb);
 	} while (!err && !cb.ret_code && cb.ph < 0x7fff);
 	filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
@@ -541,7 +541,7 @@
 	/* ntfs_getdir will place the directory entry into item, and the first
 	 * long long is the MFT record number. */
 	walk.type = BY_NAME;
-	walk.dir = NTFS_LINO2NINO(dir);
+	walk.dir = NTFS_I(dir);
 	walk.result = item;
 	if (ntfs_getdir_byname(&walk))
 		res = iget(dir->i_sb, NTFS_GETU32(item));
@@ -582,8 +582,10 @@
 	}
 	ntfs_debug(DEBUG_OTHER, "ntfs_create %s\n", d->d_name.name);
 	vol = NTFS_INO2VOL(dir);
-	ino = NTFS_LINO2NINO(r);
-	error = ntfs_alloc_file(NTFS_LINO2NINO(dir), ino, (char*)d->d_name.name,
+	ino = NTFS_I(r);
+	ino->u.index.recordsize = 0;
+	ino->u.index.clusters_per_record = 0;
+	error = ntfs_alloc_file(NTFS_I(dir), ino, (char*)d->d_name.name,
 				d->d_name.len);
 	if (error) {
 		ntfs_error("ntfs_alloc_file FAILED: error = %i", error);
@@ -595,7 +597,7 @@
 	error = ntfs_update_inode(ino);
 	if (error)
 		goto fail;
-	error = ntfs_update_inode(NTFS_LINO2NINO(dir));
+	error = ntfs_update_inode(NTFS_I(dir));
 	if (error)
 		goto fail;
 	r->i_uid = vol->uid;
@@ -643,8 +645,8 @@
 	if (!r)
 		goto out;
 	vol = NTFS_INO2VOL(dir);
-	ino = NTFS_LINO2NINO(r);
-	error = ntfs_mkdir(NTFS_LINO2NINO(dir), d->d_name.name, d->d_name.len,
+	ino = NTFS_I(r);
+	error = ntfs_mkdir(NTFS_I(dir), d->d_name.name, d->d_name.len,
 			   ino);
 	if (error)
 		goto out;
@@ -710,9 +712,9 @@
 	case FILE_Mft:
 		if (!vol->mft_ino || ((vol->ino_flags & 1) == 0))
 			goto sys_file_error;
-		ntfs_memcpy(&inode->u.ntfs_i, vol->mft_ino, sizeof(ntfs_inode));
+		ntfs_memcpy(NTFS_I(inode), vol->mft_ino, sizeof(ntfs_inode));
 		ino = vol->mft_ino;
-		vol->mft_ino = &inode->u.ntfs_i;
+		vol->mft_ino = NTFS_I(inode);
 		vol->ino_flags &= ~1;
 		ntfs_free(ino);
 		ino = vol->mft_ino;
@@ -721,9 +723,9 @@
 	case FILE_MftMirr:
 		if (!vol->mftmirr || ((vol->ino_flags & 2) == 0))
 			goto sys_file_error;
-		ntfs_memcpy(&inode->u.ntfs_i, vol->mftmirr, sizeof(ntfs_inode));
+		ntfs_memcpy(NTFS_I(inode), vol->mftmirr, sizeof(ntfs_inode));
 		ino = vol->mftmirr;
-		vol->mftmirr = &inode->u.ntfs_i;
+		vol->mftmirr = NTFS_I(inode);
 		vol->ino_flags &= ~2;
 		ntfs_free(ino);
 		ino = vol->mftmirr;
@@ -732,9 +734,9 @@
 	case FILE_BitMap:
 		if (!vol->bitmap || ((vol->ino_flags & 4) == 0))
 			goto sys_file_error;
-		ntfs_memcpy(&inode->u.ntfs_i, vol->bitmap, sizeof(ntfs_inode));
+		ntfs_memcpy(NTFS_I(inode), vol->bitmap, sizeof(ntfs_inode));
 		ino = vol->bitmap;
-		vol->bitmap = &inode->u.ntfs_i;
+		vol->bitmap = NTFS_I(inode);
 		vol->ino_flags &= ~4;
 		ntfs_free(ino);
 		ino = vol->bitmap;
@@ -746,10 +748,10 @@
 		ntfs_debug(DEBUG_OTHER, "Opening system file %i!\n",
 				inode->i_ino);
 	default:
-		ino = &inode->u.ntfs_i;
-		if (!ino || ntfs_init_inode(ino, NTFS_INO2VOL(inode),
-								inode->i_ino))
-		{
+		ino = NTFS_I(inode);
+		ino->u.index.recordsize = 0;
+		ino->u.index.clusters_per_record = 0;
+		if (ntfs_init_inode(ino, NTFS_INO2VOL(inode), inode->i_ino)) {
 			ntfs_debug(DEBUG_OTHER, "NTFS: Error loading inode "
 					"0x%x\n", (unsigned int)inode->i_ino);
 			return;
@@ -803,7 +805,7 @@
 {
 	lock_kernel();
 	ntfs_debug(DEBUG_LINUX, "ntfs_write_inode 0x%x\n", ino->i_ino);
-	ntfs_update_inode(NTFS_LINO2NINO(ino));
+	ntfs_update_inode(NTFS_I(ino));
 	unlock_kernel();
 }
 #endif
@@ -823,7 +825,7 @@
 	case FILE_Mft:
 		if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) {
 			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
-			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
+			ntfs_memcpy(ino, NTFS_I(inode), sizeof(ntfs_inode));
 			vol->mft_ino = ino;
 			vol->ino_flags |= 1;
 			goto unl_out;
@@ -832,7 +834,7 @@
 	case FILE_MftMirr:
 		if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) {
 			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
-			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
+			ntfs_memcpy(ino, NTFS_I(inode), sizeof(ntfs_inode));
 			vol->mftmirr = ino;
 			vol->ino_flags |= 2;
 			goto unl_out;
@@ -841,7 +843,7 @@
 	case FILE_BitMap:
 		if (vol->bitmap && ((vol->ino_flags & 4) == 0)) {
 			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
-			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
+			ntfs_memcpy(ino, NTFS_I(inode), sizeof(ntfs_inode));
 			vol->bitmap = ino;
 			vol->ino_flags |= 4;
 			goto unl_out;
@@ -850,7 +852,7 @@
 	default:
 		/* Nothing. Just clear the inode and exit. */
 	}
-	ntfs_clear_inode(&inode->u.ntfs_i);
+	ntfs_clear_inode(NTFS_I(inode));
 unl_out:
 	unlock_kernel();
 	return;
@@ -914,7 +916,51 @@
 }
 
 /* Define the super block operation that are implemented */
+
+static kmem_cache_t * ntfs_inode_cachep;
+
+static struct inode *__ntfs_alloc_inode(struct super_block *sb)
+{
+	struct ntfs_i *ei;
+	ei = (struct ntfs_i *)kmem_cache_alloc(ntfs_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void ntfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(ntfs_inode_cachep, ntfs_i(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct ntfs_i *ei = (struct ntfs_i *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	ntfs_inode_cachep = kmem_cache_create("ntfs_inode_cache",
+					     sizeof(struct ntfs_i),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (ntfs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(ntfs_inode_cachep))
+		printk(KERN_INFO "ntfs_inode_cache: not all structures were freed\n");
+}
 static struct super_operations ntfs_super_operations = {
+	alloc_inode:	__ntfs_alloc_inode,
+	destroy_inode:	ntfs_destroy_inode,
 	read_inode:	ntfs_read_inode,
 #ifdef CONFIG_NTFS_RW
 	write_inode:	ntfs_write_inode,
@@ -1112,6 +1158,7 @@
 
 static int __init init_ntfs_fs(void)
 {
+	int err;
 	/* Comment this if you trust klogd. There are reasons not to trust it */
 #if defined(DEBUG) && !defined(MODULE)
 	console_verbose();
@@ -1131,8 +1178,18 @@
 			"]\n");
 	SYSCTL(1);
 	ntfs_debug(DEBUG_OTHER, "registering %s\n", ntfs_fs_type.name);
-	/* Add this filesystem to the kernel table of filesystems. */
-	return register_filesystem(&ntfs_fs_type);
+	err = init_inodecache();
+	if (err)
+		goto out1;
+	err = register_filesystem(&ntfs_fs_type);
+	if (err)
+		goto out;
+	return 0;
+out:
+	destroy_inodecache();
+out1:
+	SYSCTL(0);
+	return err;
 }
 
 static void __exit exit_ntfs_fs(void)
@@ -1140,6 +1197,7 @@
 	SYSCTL(0);
 	ntfs_debug(DEBUG_OTHER, "unregistering %s\n", ntfs_fs_type.name);
 	unregister_filesystem(&ntfs_fs_type);
+	destroy_inodecache();
 }
 
 EXPORT_NO_SYMBOLS;
diff -urN linux-2.5.3-pre5/fs/ntfs/macros.h linux/fs/ntfs/macros.h
--- linux-2.5.3-pre5/fs/ntfs/macros.h	Sat Sep  8 12:24:40 2001
+++ linux/fs/ntfs/macros.h	Mon Jan 28 13:46:25 2002
@@ -14,17 +14,14 @@
 #define NTFS_SB(vol)		((struct super_block*)(vol)->sb)
 #define NTFS_SB2VOL(sb)         (&(sb)->u.ntfs_sb)
 #define NTFS_INO2VOL(ino)	(&((ino)->i_sb->u.ntfs_sb))
-#define NTFS_LINO2NINO(ino)     ((struct ntfs_inode_info*)(&((ino)->u.ntfs_i)))
+static inline struct ntfs_i *ntfs_i(struct inode *inode)
+{
+	return list_entry(inode, struct ntfs_i, vfs_inode);
+}
+#define NTFS_I(ino)     (&ntfs_i(ino)->n)
 static inline struct inode *VFS_I(struct ntfs_inode_info *ntfs_ino)
 {
-	struct inode *i = (struct inode*)((char*)ntfs_ino -
-			((char*)&(((struct inode*)NULL)->u.ntfs_i) -
-			(char*)NULL));
-#ifdef DEBUG
-	if ((char*)NTFS_LINO2NINO(i) != (char*)ntfs_ino)
-		BUG();
-#endif
-	return i;
+	return &list_entry(ntfs_ino, struct ntfs_i, n)->vfs_inode;
 }
 
 #define IS_MAGIC(a,b)		(*(int*)(a) == *(int*)(b))
diff -urN linux-2.5.3-pre5/fs/ntfs/unistr.c linux/fs/ntfs/unistr.c
--- linux-2.5.3-pre5/fs/ntfs/unistr.c	Tue Aug 28 06:57:18 2001
+++ linux/fs/ntfs/unistr.c	Mon Jan 28 13:46:25 2002
@@ -20,6 +20,7 @@
  */
 
 #include <linux/string.h>
+#include <linux/fs.h>
 #include <asm/byteorder.h>
 
 #include "unistr.h"
diff -urN linux-2.5.3-pre5/fs/reiserfs/super.c linux/fs/reiserfs/super.c
--- linux-2.5.3-pre5/fs/reiserfs/super.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/reiserfs/super.c	Mon Jan 28 13:46:25 2002
@@ -153,7 +153,7 @@
  
 static int init_inodecache(void)
 {
-	reiserfs_inode_cachep = kmem_cache_create("reiserfs_inode_cache",
+	reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache",
 					     sizeof(struct reiserfs_inode_info),
 					     0, SLAB_HWCACHE_ALIGN,
 					     init_once, NULL);
diff -urN linux-2.5.3-pre5/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- linux-2.5.3-pre5/fs/smbfs/dir.c	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/dir.c	Mon Jan 28 13:46:25 2002
@@ -228,7 +228,7 @@
 	lock_kernel();
 	server = server_from_dentry(dentry);
 	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
-		unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
+		unsigned long age = jiffies - SMB_I(dir)->oldmtime;
 		if (age > 2*HZ)
 			smb_invalid_dir_cache(dir);
 	}
@@ -454,9 +454,10 @@
 		goto out_no_inode;
 
 	if (have_id) {
-		inode->u.smbfs_i.fileid = fileid;
-		inode->u.smbfs_i.access = SMB_O_RDWR;
-		inode->u.smbfs_i.open = server->generation;
+		struct smb_inode_info *ei = SMB_I(inode);
+		ei->fileid = fileid;
+		ei->access = SMB_O_RDWR;
+		ei->open = server->generation;
 	}
 	d_instantiate(dentry, inode);
 out:
diff -urN linux-2.5.3-pre5/fs/smbfs/file.c linux/fs/smbfs/file.c
--- linux-2.5.3-pre5/fs/smbfs/file.c	Thu Jan  3 13:33:50 2002
+++ linux/fs/smbfs/file.c	Mon Jan 28 13:46:25 2002
@@ -43,7 +43,7 @@
 	 *       (should be ok with writepage_sync)
 	 */
 	smb_lock_server(server);
-	result = smb_proc_flush(server, dentry->d_inode->u.smbfs_i.fileid);
+	result = smb_proc_flush(server, SMB_I(dentry->d_inode)->fileid);
 	smb_unlock_server(server);
 	return result;
 }
@@ -126,7 +126,7 @@
 
 	offset += page->index << PAGE_CACHE_SHIFT;
 	VERBOSE("file ino=%ld, fileid=%d, count=%d@%ld, wsize=%d\n",
-		inode->i_ino, inode->u.smbfs_i.fileid, count, offset, wsize);
+		inode->i_ino, SMB_I(inode)->fileid, count, offset, wsize);
 
 	do {
 		if (count < wsize)
@@ -152,7 +152,7 @@
 		 * Update the inode now rather than waiting for a refresh.
 		 */
 		inode->i_mtime = inode->i_atime = CURRENT_TIME;
-		inode->u.smbfs_i.flags |= SMB_F_LOCALWRITE;
+		SMB_I(inode)->flags |= SMB_F_LOCALWRITE;
 		if (offset > inode->i_size)
 			inode->i_size = offset;
 	} while (count);
@@ -337,7 +337,7 @@
 	result = smb_open(dentry, smb_mode);
 	if (result)
 		goto out;
-	inode->u.smbfs_i.openers++;
+	SMB_I(inode)->openers++;
 out:
 	unlock_kernel();
 	return 0;
@@ -347,7 +347,7 @@
 smb_file_release(struct inode *inode, struct file * file)
 {
 	lock_kernel();
-	if (!--inode->u.smbfs_i.openers) {
+	if (!--SMB_I(inode)->openers) {
 		/* We must flush any dirty pages now as we won't be able to
 		   write anything after close. mmap can trigger this.
 		   "openers" should perhaps include mmap'ers ... */
diff -urN linux-2.5.3-pre5/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- linux-2.5.3-pre5/fs/smbfs/inode.c	Thu Jan  3 13:33:50 2002
+++ linux/fs/smbfs/inode.c	Mon Jan 28 13:46:25 2002
@@ -49,8 +49,52 @@
 static int  smb_statfs(struct super_block *, struct statfs *);
 static int  smb_show_options(struct seq_file *, struct vfsmount *);
 
+static kmem_cache_t *smb_inode_cachep;
+
+static struct inode *smb_alloc_inode(struct super_block *sb)
+{
+	struct smb_inode_info *ei;
+	ei = (struct smb_inode_info *)kmem_cache_alloc(smb_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+static void smb_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(smb_inode_cachep, SMB_I(inode));
+}
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct smb_inode_info *ei = (struct smb_inode_info *) foo;
+	unsigned long flagmask = SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR;
+
+	if ((flags & flagmask) == SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+static int init_inodecache(void)
+{
+	smb_inode_cachep = kmem_cache_create("smb_inode_cache",
+					     sizeof(struct smb_inode_info),
+					     0, SLAB_HWCACHE_ALIGN,
+					     init_once, NULL);
+	if (smb_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(smb_inode_cachep))
+		printk(KERN_INFO "smb_inode_cache: not all structures were freed\n");
+}
+
 static struct super_operations smb_sops =
 {
+	alloc_inode:	smb_alloc_inode,
+	destroy_inode:	smb_destroy_inode,
 	put_inode:	force_delete,
 	delete_inode:	smb_delete_inode,
 	put_super:	smb_put_super,
@@ -71,7 +115,12 @@
 	if (!result)
 		return result;
 	result->i_ino = fattr->f_ino;
-	memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i));
+	SMB_I(result)->open = 0;
+	SMB_I(result)->fileid = 0;
+	SMB_I(result)->access = 0;
+	SMB_I(result)->flags = 0;
+	SMB_I(result)->closed = 0;
+	SMB_I(result)->openers = 0;
 	smb_set_inode_attr(result, fattr);
 	if (S_ISREG(result->i_mode)) {
 		result->i_op = &smb_file_inode_operations;
@@ -105,7 +154,7 @@
 	fattr->f_blksize= inode->i_blksize;
 	fattr->f_blocks	= inode->i_blocks;
 
-	fattr->attr	= inode->u.smbfs_i.attr;
+	fattr->attr	= SMB_I(inode)->attr;
 	/*
 	 * Keep the attributes in sync with the inode permissions.
 	 */
@@ -122,6 +171,8 @@
 void
 smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
 {
+	struct smb_inode_info *ei = SMB_I(inode);
+
 	/*
 	 * A size change should have a different mtime, or same mtime
 	 * but different size.
@@ -140,11 +191,12 @@
 	inode->i_size	= fattr->f_size;
 	inode->i_mtime	= fattr->f_mtime;
 	inode->i_atime	= fattr->f_atime;
-	inode->u.smbfs_i.attr = fattr->attr;
+	ei->attr = fattr->attr;
+
 	/*
 	 * Update the "last time refreshed" field for revalidation.
 	 */
-	inode->u.smbfs_i.oldmtime = jiffies;
+	ei->oldmtime = jiffies;
 
 	if (inode->i_mtime != last_time || inode->i_size != last_sz) {
 		VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
@@ -237,9 +289,9 @@
 	/*
 	 * Check whether we've recently refreshed the inode.
 	 */
-	if (time_before(jiffies, inode->u.smbfs_i.oldmtime + SMB_MAX_AGE(s))) {
+	if (time_before(jiffies, SMB_I(inode)->oldmtime + SMB_MAX_AGE(s))) {
 		VERBOSE("up-to-date, ino=%ld, jiffies=%lu, oldtime=%lu\n",
-			inode->i_ino, jiffies, inode->u.smbfs_i.oldmtime);
+			inode->i_ino, jiffies, SMB_I(inode)->oldmtime);
 		goto out;
 	}
 
@@ -579,8 +631,8 @@
 		error = smb_open(dentry, O_WRONLY);
 		if (error)
 			goto out;
-		error = smb_proc_trunc(server, inode->u.smbfs_i.fileid,
-					 attr->ia_size);
+		error = smb_proc_trunc(server, SMB_I(inode)->fileid,
+				       attr->ia_size);
 		if (error)
 			goto out;
 		error = vmtruncate(inode, attr->ia_size);
@@ -658,6 +710,7 @@
 
 static int __init init_smb_fs(void)
 {
+	int err;
 	DEBUG1("registering ...\n");
 
 #ifdef DEBUG_SMB_MALLOC
@@ -666,13 +719,24 @@
 	smb_current_vmalloced = 0;
 #endif
 
-	return register_filesystem(&smb_fs_type);
+	err = init_inodecache();
+	if (err)
+		goto out1;
+	err = register_filesystem(&smb_fs_type);
+	if (err)
+		goto out;
+	return 0;
+out:
+	destroy_inodecache();
+out1:
+	return err;
 }
 
 static void __exit exit_smb_fs(void)
 {
 	DEBUG1("unregistering ...\n");
 	unregister_filesystem(&smb_fs_type);
+	destroy_inodecache();
 #ifdef DEBUG_SMB_MALLOC
 	printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced);
 	printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced);
diff -urN linux-2.5.3-pre5/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- linux-2.5.3-pre5/fs/smbfs/proc.c	Sun Oct  7 16:47:43 2001
+++ linux/fs/smbfs/proc.c	Mon Jan 28 13:46:25 2002
@@ -940,6 +940,7 @@
 smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
 {
 	struct inode *ino = dentry->d_inode;
+	struct smb_inode_info *ei = SMB_I(ino);
 	int mode, read_write = 0x42, read_only = 0x40;
 	int res;
 	char *p;
@@ -990,12 +991,12 @@
 	}
 	/* We should now have data in vwv[0..6]. */
 
-	ino->u.smbfs_i.fileid = WVAL(server->packet, smb_vwv0);
-	ino->u.smbfs_i.attr   = WVAL(server->packet, smb_vwv1);
+	ei->fileid = WVAL(server->packet, smb_vwv0);
+	ei->attr   = WVAL(server->packet, smb_vwv1);
 	/* smb_vwv2 has mtime */
 	/* smb_vwv4 has size  */
-	ino->u.smbfs_i.access = (WVAL(server->packet, smb_vwv6) & SMB_ACCMASK);
-	ino->u.smbfs_i.open = server->generation;
+	ei->access = (WVAL(server->packet, smb_vwv6) & SMB_ACCMASK);
+	ei->open = server->generation;
 
 out:
 	return res;
@@ -1010,6 +1011,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	int result;
+	__u16 access;
 
 	result = -ENOENT;
 	if (!inode) {
@@ -1040,11 +1042,10 @@
 	 * Check whether the access is compatible with the desired mode.
 	 */
 	result = 0;
-	if (inode->u.smbfs_i.access != wish && 
-	    inode->u.smbfs_i.access != SMB_O_RDWR)
-	{
+	access = SMB_I(inode)->access;
+	if (access != wish && access != SMB_O_RDWR) {
 		PARANOIA("%s/%s access denied, access=%x, wish=%x\n",
-			 DENTRY_PATH(dentry), inode->u.smbfs_i.access, wish);
+			 DENTRY_PATH(dentry), access, wish);
 		result = -EACCES;
 	}
 out:
@@ -1073,6 +1074,7 @@
 static int 
 smb_proc_close_inode(struct smb_sb_info *server, struct inode * ino)
 {
+	struct smb_inode_info *ei = SMB_I(ino);
 	int result = 0;
 	if (smb_is_open(ino))
 	{
@@ -1080,7 +1082,7 @@
 		 * We clear the open flag in advance, in case another
  		 * process observes the value while we block below.
 		 */
-		ino->u.smbfs_i.open = 0;
+		ei->open = 0;
 
 		/*
 		 * Kludge alert: SMB timestamps are accurate only to
@@ -1096,22 +1098,21 @@
 		 * update the time stamps to sync mtime and atime.
 		 */
 		if ((server->opt.protocol >= SMB_PROTOCOL_LANMAN2) &&
-		    !(ino->u.smbfs_i.access == SMB_O_RDONLY))
+		    !(ei->access == SMB_O_RDONLY))
 		{
 			struct smb_fattr fattr;
 			smb_get_inode_attr(ino, &fattr);
 			smb_proc_setattr_ext(server, ino, &fattr);
 		}
 
-		result = smb_proc_close(server, ino->u.smbfs_i.fileid,
-						ino->i_mtime);
+		result = smb_proc_close(server, ei->fileid, ino->i_mtime);
 		/*
 		 * Force a revalidation after closing ... some servers
 		 * don't post the size until the file has been closed.
 		 */
 		if (server->opt.protocol < SMB_PROTOCOL_NT1)
-			ino->u.smbfs_i.oldmtime = 0;
-		ino->u.smbfs_i.closed = jiffies;
+			ei->oldmtime = 0;
+		ei->closed = jiffies;
 	}
 	return result;
 }
@@ -1160,7 +1161,7 @@
 	smb_lock_server(server);
 	smb_setup_header(server, SMBread, 5, 0);
 	buf = server->packet;
-	WSET(buf, smb_vwv0, inode->u.smbfs_i.fileid);
+	WSET(buf, smb_vwv0, SMB_I(inode)->fileid);
 	WSET(buf, smb_vwv1, count);
 	DSET(buf, smb_vwv2, offset);
 	WSET(buf, smb_vwv4, 0);
@@ -1193,7 +1194,7 @@
 
 out:
 	VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
-		inode->i_ino, inode->u.smbfs_i.fileid, count, result);
+		inode->i_ino, SMB_I(inode)->fileid, count, result);
 	smb_unlock_server(server);
 	return result;
 }
@@ -1204,10 +1205,10 @@
 	struct smb_sb_info *server = server_from_inode(inode);
 	int result;
 	__u8 *p;
-	__u16 fileid = inode->u.smbfs_i.fileid;
+	__u16 fileid = SMB_I(inode)->fileid;
 
 	VERBOSE("ino=%ld, fileid=%d, count=%d@%ld, packet_size=%d\n",
-		inode->i_ino, inode->u.smbfs_i.fileid, count, offset,
+		inode->i_ino, SMB_I(inode)->fileid, count, offset,
 		server->packet_size);
 
 	smb_lock_server(server);
@@ -2291,10 +2292,10 @@
 	 */
 	if (server->mnt->flags & SMB_MOUNT_WIN95 &&
 	    inode &&
-	    inode->u.smbfs_i.flags & SMB_F_LOCALWRITE &&
+	    SMB_I(inode)->flags & SMB_F_LOCALWRITE &&
 	    smb_is_open(inode))
 	{
-		__u16 fileid = inode->u.smbfs_i.fileid;
+		__u16 fileid = SMB_I(inode)->fileid;
 		fattr->f_size = smb_proc_seek(server, fileid, 2, 0);
 	}
 
@@ -2395,7 +2396,7 @@
 
       retry:
 	smb_setup_header(server, SMBsetattrE, 7, 0);
-	WSET(server->packet, smb_vwv0, inode->u.smbfs_i.fileid);
+	WSET(server->packet, smb_vwv0, SMB_I(inode)->fileid);
 	/* We don't change the creation time */
 	WSET(server->packet, smb_vwv1, 0);
 	WSET(server->packet, smb_vwv2, 0);
@@ -2511,8 +2512,7 @@
 	/* setting the time on a Win95 server fails (tridge) */
 	if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 && 
 	    !(server->mnt->flags & SMB_MOUNT_WIN95)) {
-		if (smb_is_open(inode) &&
-		    inode->u.smbfs_i.access != SMB_O_RDONLY)
+		if (smb_is_open(inode) && SMB_I(inode)->access != SMB_O_RDONLY)
 			result = smb_proc_setattr_ext(server, inode, fattr);
 		else
 			result = smb_proc_setattr_trans2(server, dentry, fattr);
diff -urN linux-2.5.3-pre5/fs/sysv/ChangeLog linux/fs/sysv/ChangeLog
--- linux-2.5.3-pre5/fs/sysv/ChangeLog	Mon Jan 28 13:46:17 2002
+++ linux/fs/sysv/ChangeLog	Mon Jan 28 13:46:25 2002
@@ -1,3 +1,7 @@
+2002-01-24  David S. Miller  <davem@redhat.com>
+
+	* inode.c: Include linux/init.h
+
 Mon Jan 21 2001  Alexander Viro  <viro@math.psu.edu>
 	* ialloc.c (sysv_new_inode): zero SYSV_I(inode)->i_data out.
 	* i_vnode renamed to vfs_inode.  Sorry, but let's keep that
diff -urN linux-2.5.3-pre5/fs/sysv/inode.c linux/fs/sysv/inode.c
--- linux-2.5.3-pre5/fs/sysv/inode.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/sysv/inode.c	Mon Jan 28 13:46:25 2002
@@ -27,6 +27,7 @@
 #include <linux/smp_lock.h>
 #include <linux/highuid.h>
 #include <linux/slab.h>
+#include <linux/init.h>
 #include <asm/byteorder.h>
 
 /* This is only called on sync() and umount(), when s_dirt=1. */
diff -urN linux-2.5.3-pre5/fs/ufs/super.c linux/fs/ufs/super.c
--- linux-2.5.3-pre5/fs/ufs/super.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/ufs/super.c	Mon Jan 28 13:46:25 2002
@@ -652,13 +652,15 @@
 	uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
 	uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
 
-	if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192 
-	  && uspi->s_bsize != 32768) {
-		printk("ufs_read_super: fs_bsize %u != {4096, 8192, 32768}\n", uspi->s_bsize);
+	/* block size must be a power-of-two between 4k and 32k */
+	if ((uspi->s_bsize & (uspi->s_bsize-1)) ||
+	    (uspi->s_bsize < 4096 || uspi->s_bsize > 32768)) {
+		printk("ufs_read_super: fs_bsize %u != {4096, 8192, 16384, 32768}\n", uspi->s_bsize);
 		goto failed;
 	}
-	if (uspi->s_fsize != 512 && uspi->s_fsize != 1024 
-	  && uspi->s_fsize != 2048 && uspi->s_fsize != 4096) {
+	/* fragment size must be a power-of-two between 512 and 4096 bytes */
+	if ((uspi->s_fsize & (uspi->s_fsize-1)) ||
+	    (uspi->s_fsize < 512 || uspi->s_fsize > 4096)) {
 		printk("ufs_read_super: fs_fsize %u != {512, 1024, 2048. 4096}\n", uspi->s_fsize);
 		goto failed;
 	}
diff -urN linux-2.5.3-pre5/fs/vfat/namei.c linux/fs/vfat/namei.c
--- linux-2.5.3-pre5/fs/vfat/namei.c	Mon Jan 28 13:46:17 2002
+++ linux/fs/vfat/namei.c	Mon Jan 28 13:46:25 2002
@@ -19,13 +19,7 @@
 
 #include <linux/sched.h>
 #include <linux/msdos_fs.h>
-#include <linux/nls.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
 #include <linux/ctype.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
 #include <linux/slab.h>
 
 #define DEBUG_LEVEL 0
diff -urN linux-2.5.3-pre5/include/asm-i386/apic.h linux/include/asm-i386/apic.h
--- linux-2.5.3-pre5/include/asm-i386/apic.h	Mon Jan 14 13:27:06 2002
+++ linux/include/asm-i386/apic.h	Mon Jan 28 13:46:25 2002
@@ -79,6 +79,8 @@
 extern void setup_apic_nmi_watchdog (void);
 extern inline void nmi_watchdog_tick (struct pt_regs * regs);
 extern int APIC_init_uniprocessor (void);
+extern void disable_APIC_timer(void);
+extern void enable_APIC_timer(void);
 
 extern struct pm_dev *apic_pm_register(pm_dev_t, unsigned long, pm_callback);
 extern void apic_pm_unregister(struct pm_dev*);
diff -urN linux-2.5.3-pre5/include/asm-i386/bitops.h linux/include/asm-i386/bitops.h
--- linux-2.5.3-pre5/include/asm-i386/bitops.h	Mon Jan 14 13:27:05 2002
+++ linux/include/asm-i386/bitops.h	Mon Jan 28 13:46:25 2002
@@ -292,6 +292,34 @@
 }
 
 /**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+static __inline__ int find_first_bit(void * addr, unsigned size)
+{
+	int d0, d1;
+	int res;
+
+	/* This looks at memory. Mark it volatile to tell gcc not to move it around */
+	__asm__ __volatile__(
+		"xorl %%eax,%%eax\n\t"
+		"repe; scasl\n\t"
+		"jz 1f\n\t"
+		"leal -4(%%edi),%%edi\n\t"
+		"bsfl (%%edi),%%eax\n"
+		"1:\tsubl %%ebx,%%edi\n\t"
+		"shll $3,%%edi\n\t"
+		"addl %%edi,%%eax"
+		:"=a" (res), "=&c" (d0), "=&D" (d1)
+		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
+	return res;
+}
+
+/**
  * find_next_zero_bit - find the first zero bit in a memory region
  * @addr: The address to base the search on
  * @offset: The bitnumber to start searching at
@@ -304,7 +332,7 @@
 	
 	if (bit) {
 		/*
-		 * Look for zero in first byte
+		 * Look for zero in the first 32 bits.
 		 */
 		__asm__("bsfl %1,%0\n\t"
 			"jne 1f\n\t"
@@ -325,6 +353,39 @@
 }
 
 /**
+ * find_next_bit - find the first set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+static __inline__ int find_next_bit (void * addr, int size, int offset)
+{
+	unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+	int set = 0, bit = offset & 31, res;
+
+	if (bit) {
+		/*
+		 * Look for nonzero in the first 32 bits:
+		 */
+		__asm__("bsfl %1,%0\n\t"
+			"jne 1f\n\t"
+			"movl $32, %0\n"
+			"1:"
+			: "=r" (set)
+			: "r" (*p >> bit));
+		if (set < (32 - bit))
+			return set + offset;
+		set = 32 - bit;
+		p++;
+	}
+	/*
+	 * No set bit yet, search remaining full words for a bit
+	 */
+	res = find_first_bit (p, size - 32 * (p - (unsigned long *) addr));
+	return (offset + set + res);
+}
+
+/**
  * ffz - find first zero in word.
  * @word: The word to search
  *
@@ -335,6 +396,20 @@
 	__asm__("bsfl %1,%0"
 		:"=r" (word)
 		:"r" (~word));
+	return word;
+}
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long __ffs(unsigned long word)
+{
+	__asm__("bsfl %1,%0"
+		:"=r" (word)
+		:"rm" (word));
 	return word;
 }
 
diff -urN linux-2.5.3-pre5/include/asm-i386/mmu_context.h linux/include/asm-i386/mmu_context.h
--- linux-2.5.3-pre5/include/asm-i386/mmu_context.h	Mon Jan 28 13:46:17 2002
+++ linux/include/asm-i386/mmu_context.h	Mon Jan 28 13:46:25 2002
@@ -16,17 +16,19 @@
 # error update this function.
 #endif
 
-static inline int sched_find_first_zero_bit(unsigned long *b)
+static inline int sched_find_first_bit(unsigned long *b)
 {
-	unsigned int rt;
-
-	rt = b[0] & b[1] & b[2] & b[3];
-	if (unlikely(rt != 0xffffffff))
-		return find_first_zero_bit(b, MAX_RT_PRIO);
-
-	if (b[4] != ~0)
-		return ffz(b[4]) + MAX_RT_PRIO;
-	return ffz(b[5]) + 32 + MAX_RT_PRIO;
+	if (unlikely(b[0]))
+		return __ffs(b[0]);
+	if (unlikely(b[1]))
+		return __ffs(b[1]) + 32;
+	if (unlikely(b[2]))
+		return __ffs(b[2]) + 64;
+	if (unlikely(b[3]))
+		return __ffs(b[3]) + 96;
+	if (b[4])
+		return __ffs(b[4]) + 128;
+	return __ffs(b[5]) + 32 + 128;
 }
 /*
  * possibly do the LDT unload here?
@@ -49,13 +51,13 @@
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
 {
-	if (prev != next) {
+	if (likely(prev != next)) {
 		/* stop flush ipis for the previous mm */
 		clear_bit(cpu, &prev->cpu_vm_mask);
 		/*
 		 * Re-load LDT if necessary
 		 */
-		if (prev->context.segments != next->context.segments)
+		if (unlikely(prev->context.segments != next->context.segments))
 			load_LDT(next);
 #ifdef CONFIG_SMP
 		cpu_tlbstate[cpu].state = TLBSTATE_OK;
diff -urN linux-2.5.3-pre5/include/linux/adfs_fs.h linux/include/linux/adfs_fs.h
--- linux-2.5.3-pre5/include/linux/adfs_fs.h	Mon Jan 14 13:28:11 2002
+++ linux/include/linux/adfs_fs.h	Mon Jan 28 13:46:25 2002
@@ -41,6 +41,7 @@
 #define ADFS_SUPER_MAGIC	 0xadf5
 
 #ifdef __KERNEL__
+#include <linux/adfs_fs_i.h>
 /*
  * Calculate the boot block checksum on an ADFS drive.  Note that this will
  * appear to be correct if the sector contains all zeros, so also check that
@@ -57,6 +58,11 @@
 	} while (p != ptr);
 
 	return (result & 0xff) != ptr[511];
+}
+
+static inline struct adfs_inode_info *ADFS_I(struct inode *inode)
+{
+	return list_entry(inode, struct adfs_inode_info, vfs_inode);
 }
 
 #endif
diff -urN linux-2.5.3-pre5/include/linux/adfs_fs_i.h linux/include/linux/adfs_fs_i.h
--- linux-2.5.3-pre5/include/linux/adfs_fs_i.h	Sun Feb 13 10:45:13 2000
+++ linux/include/linux/adfs_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -18,6 +18,7 @@
 	unsigned int	filetype;	/* RISC OS file type		*/
 	unsigned int	attr;		/* RISC OS permissions		*/
 	int		stamped:1;	/* RISC OS file has date/time	*/
+	struct inode vfs_inode;
 };
 
 #endif
diff -urN linux-2.5.3-pre5/include/linux/bfs_fs.h linux/include/linux/bfs_fs.h
--- linux-2.5.3-pre5/include/linux/bfs_fs.h	Tue Nov 28 22:43:39 2000
+++ linux/include/linux/bfs_fs.h	Mon Jan 28 13:46:25 2002
@@ -6,6 +6,8 @@
 #ifndef _LINUX_BFS_FS_H
 #define _LINUX_BFS_FS_H
 
+#include <linux/bfs_fs_i.h>
+
 #define BFS_BSIZE_BITS		9
 #define BFS_BSIZE		(1<<BFS_BSIZE_BITS)
 
@@ -86,6 +88,11 @@
 /* dir.c */
 extern struct inode_operations bfs_dir_inops;
 extern struct file_operations bfs_dir_operations;
+
+static inline struct bfs_inode_info *BFS_I(struct inode *inode)
+{
+	return list_entry(inode, struct bfs_inode_info, vfs_inode);
+}
 
 #endif /* __KERNEL__ */
 #endif	/* _LINUX_BFS_FS_H */
diff -urN linux-2.5.3-pre5/include/linux/bfs_fs_i.h linux/include/linux/bfs_fs_i.h
--- linux-2.5.3-pre5/include/linux/bfs_fs_i.h	Tue Nov 28 22:43:39 2000
+++ linux/include/linux/bfs_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -13,6 +13,7 @@
 	unsigned long i_dsk_ino; /* inode number from the disk, can be 0 */
 	unsigned long i_sblock;
 	unsigned long i_eblock;
+	struct inode vfs_inode;
 };
 
 #endif	/* _LINUX_BFS_FS_I */
diff -urN linux-2.5.3-pre5/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.5.3-pre5/include/linux/fs.h	Mon Jan 28 13:46:17 2002
+++ linux/include/linux/fs.h	Mon Jan 28 13:46:25 2002
@@ -287,17 +287,9 @@
 
 
 #include <linux/pipe_fs_i.h>
-#include <linux/ntfs_fs_i.h>
-#include <linux/msdos_fs_i.h>
 /* #include <linux/umsdos_fs_i.h> */
-#include <linux/iso_fs_i.h>
 #include <linux/romfs_fs_i.h>
-#include <linux/smb_fs_i.h>
-#include <linux/hfs_fs_i.h>
-#include <linux/adfs_fs_i.h>
-#include <linux/bfs_fs_i.h>
 #include <linux/proc_fs_i.h>
-#include <linux/jffs2_fs_i.h>
 #include <linux/cramfs_fs_sb.h>
 
 /*
@@ -461,18 +453,10 @@
 	unsigned int		i_attr_flags;
 	__u32			i_generation;
 	union {
-		struct ntfs_inode_info		ntfs_i;
-		struct msdos_inode_info		msdos_i;
 		/* struct umsdos_inode_info	umsdos_i; */
-		struct iso_inode_info		isofs_i;
 		struct romfs_inode_info		romfs_i;
-		struct smb_inode_info		smbfs_i;
-		struct hfs_inode_info		hfs_i;
-		struct adfs_inode_info		adfs_i;
-		struct bfs_inode_info		bfs_i;
 		struct proc_inode_info		proc_i;
 		struct socket			socket_i;
-		struct jffs2_inode_info		jffs2_i;
 		void				*generic_ip;
 	} u;
 };
diff -urN linux-2.5.3-pre5/include/linux/hfs_fs.h linux/include/linux/hfs_fs.h
--- linux-2.5.3-pre5/include/linux/hfs_fs.h	Tue Feb 13 14:13:44 2001
+++ linux/include/linux/hfs_fs.h	Mon Jan 28 13:46:25 2002
@@ -317,7 +317,12 @@
 extern int hfs_mac2triv(char *, const struct hfs_name *);
 extern void hfs_tolower(unsigned char *, int);
 
-#define	HFS_I(X)	(&((X)->u.hfs_i))
+#include <linux/hfs_fs_i.h>
+
+static inline struct hfs_inode_info *HFS_I(struct inode *inode)
+{
+	return list_entry(inode, struct hfs_inode_info, vfs_inode);
+}
 #define	HFS_SB(X)	(&((X)->u.hfs_sb))
 
 static inline void hfs_nameout(struct inode *dir, struct hfs_name *out,
diff -urN linux-2.5.3-pre5/include/linux/hfs_fs_i.h linux/include/linux/hfs_fs_i.h
--- linux-2.5.3-pre5/include/linux/hfs_fs_i.h	Tue Feb 13 14:13:44 2001
+++ linux/include/linux/hfs_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -39,6 +39,7 @@
 
         /* for dentry cleanup */
         void (*d_drop_op)(struct dentry *, const ino_t);
+	struct inode vfs_inode;
 };
 
 #endif
diff -urN linux-2.5.3-pre5/include/linux/init_task.h linux/include/linux/init_task.h
--- linux-2.5.3-pre5/include/linux/init_task.h	Mon Jan 28 13:46:17 2002
+++ linux/include/linux/init_task.h	Mon Jan 28 13:46:25 2002
@@ -53,7 +53,7 @@
     mm:			NULL,						\
     active_mm:		&init_mm,					\
     run_list:		LIST_HEAD_INIT(tsk.run_list),			\
-    time_slice:		NICE_TO_TIMESLICE(DEF_USER_NICE),		\
+    time_slice:		HZ,						\
     next_task:		&tsk,						\
     prev_task:		&tsk,						\
     p_opptr:		&tsk,						\
diff -urN linux-2.5.3-pre5/include/linux/isdn.h linux/include/linux/isdn.h
--- linux-2.5.3-pre5/include/linux/isdn.h	Mon Jan 28 13:46:17 2002
+++ linux/include/linux/isdn.h	Mon Jan 28 13:46:25 2002
@@ -631,7 +631,6 @@
 #ifdef CONFIG_DEVFS_FS
 	devfs_handle_t devfs_handle_isdninfo;
 	devfs_handle_t devfs_handle_isdnctrl;
-	devfs_handle_t devfs_handle_isdnX[ISDN_MAX_CHANNELS];
 	devfs_handle_t devfs_handle_isdnctrlX[ISDN_MAX_CHANNELS];
 #ifdef CONFIG_ISDN_PPP
 	devfs_handle_t devfs_handle_ipppX[ISDN_MAX_CHANNELS];
diff -urN linux-2.5.3-pre5/include/linux/iso_fs.h linux/include/linux/iso_fs.h
--- linux-2.5.3-pre5/include/linux/iso_fs.h	Mon Jan 14 13:27:30 2002
+++ linux/include/linux/iso_fs.h	Mon Jan 28 13:46:25 2002
@@ -170,6 +170,12 @@
 
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
+#include <linux/iso_fs_i.h>
+
+static inline struct iso_inode_info *ISOFS_I(struct inode *inode)
+{
+	return list_entry(inode, struct iso_inode_info, vfs_inode);
+}
 
 static inline int isonum_711(char *p)
 {
diff -urN linux-2.5.3-pre5/include/linux/iso_fs_i.h linux/include/linux/iso_fs_i.h
--- linux-2.5.3-pre5/include/linux/iso_fs_i.h	Thu Oct 25 18:00:44 2001
+++ linux/include/linux/iso_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -16,6 +16,7 @@
 	unsigned char i_format_parm[3];
 	unsigned long i_next_section_ino;
 	off_t i_section_size;
+	struct inode vfs_inode;
 };
 
 #endif
diff -urN linux-2.5.3-pre5/include/linux/jffs2_fs_i.h linux/include/linux/jffs2_fs_i.h
--- linux-2.5.3-pre5/include/linux/jffs2_fs_i.h	Fri Sep 14 14:04:07 2001
+++ linux/include/linux/jffs2_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -50,12 +50,16 @@
 	//	struct jffs2_raw_node_ref *lastnode;
 	__u16 flags;
 	__u8 usercompr;
+	struct inode vfs_inode;
 };
 
 #ifdef JFFS2_OUT_OF_KERNEL
 #define JFFS2_INODE_INFO(i) ((struct jffs2_inode_info *) &(i)->u)
 #else
-#define JFFS2_INODE_INFO(i) (&i->u.jffs2_i)
+static inline struct jffs2_inode_info *JFFS2_INODE_INFO(struct inode *inode)
+{
+	return list_entry(inode, struct jffs2_inode_info, vfs_inode);
+}
 #endif
 
 #endif /* _JFFS2_FS_I */
diff -urN linux-2.5.3-pre5/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- linux-2.5.3-pre5/include/linux/msdos_fs.h	Mon Jan 28 13:46:17 2002
+++ linux/include/linux/msdos_fs.h	Mon Jan 28 13:46:25 2002
@@ -4,9 +4,7 @@
 /*
  * The MS-DOS filesystem constants/structures
  */
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/fd.h>
+#include <linux/msdos_fs_i.h>
 
 #include <asm/byteorder.h>
 
@@ -56,7 +54,10 @@
 	/* valid file mode bits */
 
 #define MSDOS_SB(s) (&((s)->u.msdos_sb))
-#define MSDOS_I(i) (&((i)->u.msdos_i))
+static inline struct msdos_inode_info *MSDOS_I(struct inode *inode)
+{
+	return list_entry(inode, struct msdos_inode_info, vfs_inode);
+}
 
 #define MSDOS_NAME 11 /* maximum name length */
 #define MSDOS_LONGNAME 256 /* maximum name length */
diff -urN linux-2.5.3-pre5/include/linux/msdos_fs_i.h linux/include/linux/msdos_fs_i.h
--- linux-2.5.3-pre5/include/linux/msdos_fs_i.h	Thu Feb 10 12:17:00 2000
+++ linux/include/linux/msdos_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -12,8 +12,8 @@
 	int i_attrs;	/* unused attribute bits */
 	int i_ctime_ms;	/* unused change time in milliseconds */
 	int i_location;	/* on-disk position of directory entry or 0 */
-	struct inode *i_fat_inode;	/* struct inode of this one */
 	struct list_head i_fat_hash;	/* hash by i_location */
+	struct inode vfs_inode;
 };
 
 #endif
diff -urN linux-2.5.3-pre5/include/linux/netfilter_ipv4.h linux/include/linux/netfilter_ipv4.h
--- linux-2.5.3-pre5/include/linux/netfilter_ipv4.h	Mon Jan 14 13:30:49 2002
+++ linux/include/linux/netfilter_ipv4.h	Mon Jan 28 13:46:25 2002
@@ -73,4 +73,81 @@
 /* 2.4 firewalling went 64 through 67. */
 #define SO_ORIGINAL_DST 80
 
+
+/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue 
+ *
+ * Ideally this would be ins some netfilter_utility module, but creating this
+ * module for just one function doesn't make sense. -HW */
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/route.h>
+#include <linux/ip.h>
+
+static inline int route_me_harder(struct sk_buff **pskb)
+{
+	struct iphdr *iph = (*pskb)->nh.iph;
+	struct rtable *rt;
+	struct rt_key key = { dst:iph->daddr,
+			      src:iph->saddr,
+			      oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
+			      tos:RT_TOS(iph->tos)|RTO_CONN,
+#ifdef CONFIG_IP_ROUTE_FWMARK
+			      fwmark:(*pskb)->nfmark
+#endif
+			    };
+	struct net_device *dev_src = NULL;
+	int err;
+
+	/* accomodate ip_route_output_slow(), which expects the key src to be
+	   0 or a local address; however some non-standard hacks like
+	   ipt_REJECT.c:send_reset() can cause packets with foreign
+           saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
+	if(key.src && !(dev_src = ip_dev_find(key.src)))
+		key.src = 0;
+
+	if ((err=ip_route_output_key(&rt, &key)) != 0) {
+		printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n",
+			NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
+			(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
+			RT_TOS(iph->tos)|RTO_CONN,
+#ifdef CONFIG_IP_ROUTE_FWMARK
+			(*pskb)->nfmark,
+#else
+			0UL,
+#endif
+			err);
+		goto out;
+	}
+
+	/* Drop old route. */
+	dst_release((*pskb)->dst);
+
+	(*pskb)->dst = &rt->u.dst;
+
+	/* Change in oif may mean change in hh_len. */
+	if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
+		struct sk_buff *nskb;
+
+		nskb = skb_realloc_headroom(*pskb,
+					    (*pskb)->dst->dev->hard_header_len);
+		if (!nskb) {
+			err = -ENOMEM;
+			goto out;
+		}
+		if ((*pskb)->sk)
+			skb_set_owner_w(nskb, (*pskb)->sk);
+		kfree_skb(*pskb);
+		*pskb = nskb;
+	}
+
+out:
+	if (dev_src)
+		dev_put(dev_src);
+
+	return err;
+}
+
 #endif /*__LINUX_IP_NETFILTER_H*/
diff -urN linux-2.5.3-pre5/include/linux/ntfs_fs_i.h linux/include/linux/ntfs_fs_i.h
--- linux-2.5.3-pre5/include/linux/ntfs_fs_i.h	Mon Jan 14 13:27:05 2002
+++ linux/include/linux/ntfs_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -88,4 +88,10 @@
 	} u;	
 };
 
+/* this is a kludge */
+struct ntfs_i {
+	struct ntfs_inode_info n;
+	struct inode vfs_inode;
+};
+
 #endif
diff -urN linux-2.5.3-pre5/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.5.3-pre5/include/linux/sched.h	Mon Jan 28 13:46:17 2002
+++ linux/include/linux/sched.h	Mon Jan 28 13:46:25 2002
@@ -140,8 +140,7 @@
 typedef struct task_struct task_t;
 
 extern void sched_init(void);
-extern void init_idle(void);
-extern void idle_startup_done(void);
+extern void init_idle(task_t *idle, int cpu);
 extern void show_state(void);
 extern void cpu_init (void);
 extern void trap_init(void);
@@ -151,6 +150,8 @@
 extern void scheduler_tick(struct task_struct *p);
 extern void sched_task_migrated(struct task_struct *p);
 extern void smp_migrate_task(int cpu, task_t *task);
+extern unsigned long cache_decay_ticks;
+
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
 extern signed long FASTCALL(schedule_timeout(signed long timeout));
@@ -256,7 +257,6 @@
 
 	unsigned int time_slice;
 
-	#define MAX_SLEEP_AVG (2*HZ)
 	unsigned long sleep_avg;
 	unsigned long sleep_timestamp;
 
@@ -418,11 +418,22 @@
 #define DEF_USER_NICE		0
 
 /*
- * Default timeslice is 90 msecs, maximum is 180 msecs.
+ * Default timeslice is 150 msecs, maximum is 300 msecs.
  * Minimum timeslice is 10 msecs.
+ *
+ * These are the 'tuning knobs' of the scheduler:
  */
 #define MIN_TIMESLICE		( 10 * HZ / 1000)
-#define MAX_TIMESLICE		(180 * HZ / 1000)
+#define MAX_TIMESLICE		(300 * HZ / 1000)
+#define CHILD_FORK_PENALTY	95
+#define PARENT_FORK_PENALTY	100
+#define EXIT_WEIGHT		3
+#define PRIO_INTERACTIVE_RATIO	20
+#define PRIO_CPU_HOG_RATIO	60
+#define PRIO_BONUS_RATIO	70
+#define INTERACTIVE_DELTA	3
+#define MAX_SLEEP_AVG		(2*HZ)
+#define STARVATION_LIMIT	(2*HZ)
 
 #define USER_PRIO(p)		((p)-MAX_RT_PRIO)
 #define MAX_USER_PRIO		(USER_PRIO(MAX_PRIO))
diff -urN linux-2.5.3-pre5/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- linux-2.5.3-pre5/include/linux/smb_fs.h	Tue Oct  2 17:03:34 2001
+++ linux/include/linux/smb_fs.h	Mon Jan 28 13:46:25 2002
@@ -10,6 +10,7 @@
 #define _LINUX_SMB_FS_H
 
 #include <linux/smb.h>
+#include <linux/smb_fs_i.h>
 
 /*
  * ioctl commands
@@ -28,6 +29,10 @@
 #include <linux/smb_mount.h>
 #include <asm/unaligned.h>
 
+static inline struct smb_inode_info *SMB_I(struct inode *inode)
+{
+	return list_entry(inode, struct smb_inode_info, vfs_inode);
+}
 
 /* macro names are short for word, double-word, long value (?) */
 #define WVAL(buf,pos) \
@@ -157,7 +162,7 @@
 static inline int
 smb_is_open(struct inode *i)
 {
-	return (i->u.smbfs_i.open == server_from_inode(i)->generation);
+	return (SMB_I(i)->open == server_from_inode(i)->generation);
 }
 
 
diff -urN linux-2.5.3-pre5/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h
--- linux-2.5.3-pre5/include/linux/smb_fs_i.h	Mon Jan 14 13:27:05 2002
+++ linux/include/linux/smb_fs_i.h	Mon Jan 28 13:46:25 2002
@@ -30,6 +30,8 @@
 	unsigned long oldmtime;	/* last time refreshed */
 	unsigned long closed;	/* timestamp when closed */
 	unsigned openers;	/* number of fileid users */
+
+	struct inode vfs_inode;	/* must be at the end */
 };
 
 #endif
diff -urN linux-2.5.3-pre5/include/linux/usb.h linux/include/linux/usb.h
--- linux-2.5.3-pre5/include/linux/usb.h	Mon Jan 28 13:46:17 2002
+++ linux/include/linux/usb.h	Mon Jan 28 13:46:25 2002
@@ -881,6 +881,7 @@
 	char *buf, size_t size);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+extern int usb_make_path(struct usb_device *dev, char *buf, size_t size);
 
 /*
  * timeouts, in seconds, used for sending/receiving control messages
@@ -1096,7 +1097,7 @@
  *  - endpoint number (4 bits)
  *  - current Data0/1 state (1 bit) [Historical; now gone]
  *  - direction (1 bit)
- *  - speed (1 bit)
+ *  - speed (1 bit) [Historical and specific to USB 1.1; now gone.]
  *  - max packet size (2 bits: 8, 16, 32 or 64) [Historical; now gone.]
  *  - pipe type (2 bits: control, interrupt, bulk, isochronous)
  *
@@ -1107,25 +1108,22 @@
  * Let's not fall in that trap. We'll just encode it as a simple
  * unsigned int. The encoding is:
  *
- *  - max size:		bits 0-1	(00 = 8, 01 = 16, 10 = 32, 11 = 64) [Historical; now gone.]
- *  - direction:	bit 7		(0 = Host-to-Device [Out], 1 = Device-to-Host [In])
+ *  - max size:		bits 0-1	[Historical; now gone.]
+ *  - direction:	bit 7		(0 = Host-to-Device [Out],
+ *					 1 = Device-to-Host [In])
  *  - device:		bits 8-14
  *  - endpoint:		bits 15-18
  *  - Data0/1:		bit 19		[Historical; now gone. ]
- *  - speed:		bit 26		(0 = Full, 1 = Low Speed)
- *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk)
+ *  - lowspeed:		bit 26		[Historical; now gone. ]
+ *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt,
+ *					 10 = control, 11 = bulk)
  *
  * Why? Because it's arbitrary, and whatever encoding we select is really
  * up to us. This one happens to share a lot of bit positions with the UHCI
  * specification, so that much of the uhci driver can just mask the bits
  * appropriately.
- *
- * NOTE:  there's no encoding (yet?) for a "high speed" endpoint; treat them
- * like full speed devices.
  */
 
-// FIXME 2.5 get rid of usb_pipeslow(), just use dev->speed
-
 #define PIPE_ISOCHRONOUS		0
 #define PIPE_INTERRUPT			1
 #define PIPE_CONTROL			2
@@ -1139,9 +1137,7 @@
 #define usb_pipeout(pipe)	((((pipe) >> 7) & 1) ^ 1)
 #define usb_pipein(pipe)	(((pipe) >> 7) & 1)
 #define usb_pipedevice(pipe)	(((pipe) >> 8) & 0x7f)
-#define usb_pipe_endpdev(pipe)	(((pipe) >> 8) & 0x7ff)
 #define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf)
-#define usb_pipeslow(pipe)	(((pipe) >> 26) & 1)
 #define usb_pipetype(pipe)	(((pipe) >> 30) & 3)
 #define usb_pipeisoc(pipe)	(usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
 #define usb_pipeint(pipe)	(usb_pipetype((pipe)) == PIPE_INTERRUPT)
@@ -1163,13 +1159,7 @@
 
 static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
 {
-	return (dev->devnum << 8) | (endpoint << 15) |
-		((dev->speed == USB_SPEED_LOW) << 26);
-}
-
-static inline unsigned int __default_pipe(struct usb_device *dev)
-{
-	return ((dev->speed == USB_SPEED_LOW) << 26);
+	return (dev->devnum << 8) | (endpoint << 15);
 }
 
 /* Create various pipes... */
@@ -1181,8 +1171,8 @@
 #define usb_rcvbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
 #define usb_sndintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
 #define usb_rcvintpipe(dev,endpoint)	((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_snddefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev))
-#define usb_rcvdefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN)
+#define usb_snddefctrl(dev)		((PIPE_CONTROL << 30))
+#define usb_rcvdefctrl(dev)		((PIPE_CONTROL << 30) | USB_DIR_IN)
 
 /* -------------------------------------------------------------------------- */
 
diff -urN linux-2.5.3-pre5/include/net/route.h linux/include/net/route.h
--- linux-2.5.3-pre5/include/net/route.h	Mon Jan 14 13:28:11 2002
+++ linux/include/net/route.h	Mon Jan 28 13:46:25 2002
@@ -30,6 +30,7 @@
 #include <linux/in_route.h>
 #include <linux/rtnetlink.h>
 #include <linux/route.h>
+#include <linux/ip.h>
 #include <linux/cache.h>
 
 #ifndef __KERNEL__
diff -urN linux-2.5.3-pre5/init/main.c linux/init/main.c
--- linux-2.5.3-pre5/init/main.c	Mon Jan 28 13:46:17 2002
+++ linux/init/main.c	Mon Jan 28 13:46:25 2002
@@ -274,27 +274,14 @@
 
 #else
 
-static unsigned long __initdata wait_init_idle;
-
-void __init idle_startup_done(void)
-{
-	clear_bit(smp_processor_id(), &wait_init_idle);
-	while (wait_init_idle) {
-		cpu_relax();
-		barrier();
-	}
-}
-
 /* Called by boot processor to activate the rest. */
 static void __init smp_init(void)
 {
 	/* Get other processors into their bootup holding patterns. */
 	smp_boot_cpus();
-	wait_init_idle = cpu_online_map;
 
 	smp_threads_ready=1;
 	smp_commence();
-	idle_startup_done();
 }
 
 #endif
@@ -391,7 +378,7 @@
 	check_bugs();
 	printk("POSIX conformance testing by UNIFIX\n");
 
-	init_idle();
+	init_idle(current, smp_processor_id());
 	/* 
 	 *	We count on the initial thread going ok 
 	 *	Like idlers init is an unlocked kernel thread, which will
diff -urN linux-2.5.3-pre5/kernel/Makefile linux/kernel/Makefile
--- linux-2.5.3-pre5/kernel/Makefile	Thu Nov 29 16:53:45 2001
+++ linux/kernel/Makefile	Mon Jan 28 13:46:25 2002
@@ -10,12 +10,12 @@
 O_TARGET := kernel.o
 
 export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
-		printk.o device.o
+		printk.o 
 
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
 	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o context.o device.o
+	    signal.o sys.o kmod.o context.o 
 
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
diff -urN linux-2.5.3-pre5/kernel/device.c linux/kernel/device.c
--- linux-2.5.3-pre5/kernel/device.c	Mon Jan 28 13:46:17 2002
+++ linux/kernel/device.c	Wed Dec 31 16:00:00 1969
@@ -1,527 +0,0 @@
-/*
- * device.c
- *
- * Copyright (c) Patrick Mochel <mochel@osdl.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Please see Documentation/driver-model.txt for more explanation.
- */
-
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/pagemap.h>
-#include <linux/module.h>
-#include <linux/stat.h>
-#include <linux/driverfs_fs.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/spinlock.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-# define DBG(x...) printk(x)
-#else
-# define DBG(x...)
-#endif
-
-static struct iobus device_root = {
-	bus_id: "root",
-	name:	"Logical System Root",
-};
-
-int (*platform_notify)(struct device * dev) = NULL;
-int (*platform_notify_remove)(struct device * dev) = NULL;
-
-static spinlock_t device_lock;
-
-static ssize_t device_read_status(struct device *, char *, size_t, loff_t);
-static ssize_t device_write_status(struct device *,const char *, size_t, loff_t);
-
-static struct driver_file_entry device_status_entry = {
-	name:		"status",
-	mode:		S_IWUSR | S_IRUGO,
-	show:		device_read_status,
-	store:		device_write_status,
-};
-
-static ssize_t device_read_power(struct device *, char *, size_t, loff_t);
-static ssize_t device_write_power(struct device *, const char *, size_t, loff_t);
-
-static struct driver_file_entry device_power_entry = {
-	name:		"power",
-	mode:		S_IWUSR | S_IRUGO,
-	show:		device_read_power,
-	store:		device_write_power,
-};
-
-/**
- * device_create_file - create a driverfs file for a device
- * @dev:	device requesting file
- * @entry:	entry describing file
- *
- * Allocate space for file entry, copy descriptor, and create.
- */
-int device_create_file(struct device * dev, struct driver_file_entry * entry)
-{
-	struct driver_file_entry * new_entry;
-	int error = -ENOMEM;
-
-	if (!dev)
-		return -EINVAL;
-	get_device(dev);
-
-	new_entry = kmalloc(sizeof(*new_entry),GFP_KERNEL);
-	if (!new_entry)
-		goto done;
-
-	memcpy(new_entry,entry,sizeof(*entry));
-	error = driverfs_create_file(new_entry,&dev->dir);
-	if (error)
-		kfree(new_entry);
- done:
-	put_device(dev);
-	return error;
-}
-
-/**
- * device_remove_file - remove a device's file by name
- * @dev:	device requesting removal
- * @name:	name of the file
- *
- */
-void device_remove_file(struct device * dev, const char * name)
-{
-	if (dev) {
-		get_device(dev);
-		driverfs_remove_file(&dev->dir,name);
-		put_device(dev);
-	}
-}
-
-/**
- * device_remove_dir - remove a device's directory
- * @dev:	device in question
- */
-void device_remove_dir(struct device * dev)
-{
-	if (dev)
-		driverfs_remove_dir(&dev->dir);
-}
-
-/**
- * device_make_dir - create a driverfs directory
- * @name:	name of directory
- * @parent:	dentry for the parent directory
- *
- * Do the initial creation of the device's driverfs directory
- * and populate it with the one default file.
- *
- * This is just a helper for device_register(), as we
- * don't export this function. (Yes, that means we don't allow
- * devices to create subdirectories).
- */
-static int device_make_dir(struct device * dev)
-{
-	struct driver_dir_entry * parent = NULL;
-	int error;
-
-	INIT_LIST_HEAD(&dev->dir.files);
-	dev->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
-	dev->dir.name = dev->bus_id;
-
-	if (dev->parent)
-		parent = &dev->parent->dir;
-
-	error = driverfs_create_dir(&dev->dir,parent);
-
-	if (error)
-		return error;
-
-	error = device_create_file(dev,&device_status_entry);
-	if (error) {
-		device_remove_dir(dev);
-		goto done;
-	}
-	error = device_create_file(dev,&device_power_entry);
-	if (error) 
-		device_remove_dir(dev);
- done:
-	return error;
-}
-
-void iobus_remove_dir(struct iobus * iobus)
-{
-	if (iobus)
-		driverfs_remove_dir(&iobus->dir);
-}
-
-static int iobus_make_dir(struct iobus * iobus)
-{
-	struct driver_dir_entry * parent = NULL;
-	int error;
-
-	INIT_LIST_HEAD(&iobus->dir.files);
-	iobus->dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
-	iobus->dir.name = iobus->bus_id;
-
-	if (iobus->parent)
-		parent = &iobus->parent->dir;
-
-	error = driverfs_create_dir(&iobus->dir,parent);
-	return error;
-}
-
-/**
- * device_register - register a device
- * @dev:	pointer to the device structure
- *
- * First, make sure that the device has a parent, create
- * a directory for it, then add it to the parent's list of
- * children.
- */
-int device_register(struct device *dev)
-{
-	int error;
-
-	if (!dev || !strlen(dev->bus_id))
-		return -EINVAL;
-	BUG_ON(!dev->parent);
-
-	spin_lock(&device_lock);
-	INIT_LIST_HEAD(&dev->node);
-	spin_lock_init(&dev->lock);
-	atomic_set(&dev->refcount,2);
-
-	get_iobus(dev->parent);
-	list_add_tail(&dev->node,&dev->parent->devices);
-	spin_unlock(&device_lock);
-
-	DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
-	    dev->bus_id, dev->name, parent->bus_id);
-
-	if ((error = device_make_dir(dev)))
-		goto register_done;
-
-	/* notify platform of device entry */
-	if (platform_notify)
-		platform_notify(dev);
-
- register_done:
-	put_device(dev);
-	if (error)
-		put_iobus(dev->parent);
-	return error;
-}
-
-/**
- * put_device - clean up device
- * @dev:	device in question
- *
- * Decrement reference count for device.
- * If it hits 0, we need to clean it up.
- * However, we may be here in interrupt context, and it may
- * take some time to do proper clean up (removing files, calling
- * back down to device to clean up everything it has).
- * So, we remove it from its parent's list and add it to the list of
- * devices to be cleaned up.
- */
-void put_device(struct device * dev)
-{
-	if (!atomic_dec_and_lock(&dev->refcount,&device_lock))
-		return;
-	list_del_init(&dev->node);
-	spin_unlock(&device_lock);
-
-	DBG("DEV: Unregistering device. ID = '%s', name = '%s'\n",
-	    dev->bus_id,dev->name);
-
-	/* remove the driverfs directory */
-	device_remove_dir(dev);
-
-	if (dev->subordinate)
-		iobus_remove_dir(dev->subordinate);
-
-	/* Notify the platform of the removal, in case they
-	 * need to do anything...
-	 */
-	if (platform_notify_remove)
-		platform_notify_remove(dev);
-
-	/* Tell the driver to clean up after itself.
-	 * Note that we likely didn't allocate the device,
-	 * so this is the driver's chance to free that up...
-	 */
-	if (dev->driver && dev->driver->remove)
-		dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
-
-	put_iobus(dev->parent);
-}
-
-int iobus_register(struct iobus *bus)
-{
-	int error;
-
-	if (!bus || !strlen(bus->bus_id))
-		return -EINVAL;
-	
-	spin_lock(&device_lock);
-	atomic_set(&bus->refcount,2);
-	spin_lock_init(&bus->lock);
-	INIT_LIST_HEAD(&bus->node);
-	INIT_LIST_HEAD(&bus->devices);
-	INIT_LIST_HEAD(&bus->children);
-
-	if (bus != &device_root) {
-		if (!bus->parent)
-			bus->parent = &device_root;
-		get_iobus(bus->parent);
-		list_add_tail(&bus->node,&bus->parent->children);
-	}
-	spin_unlock(&device_lock);
-
-	DBG("DEV: registering bus. ID = '%s' name = '%s' parent = %p\n",
-	    bus->bus_id,bus->name,bus->parent);
-
-	error = iobus_make_dir(bus);
-
-	put_iobus(bus);
-	if (error && bus->parent)
-		put_iobus(bus->parent);
-	return error;
-}
-
-/**
- * iobus_unregister - remove bus and children from device tree
- * @bus:	pointer to bus structure
- *
- * Remove device from parent's list of children and decrement
- * reference count on controlling device. That should take care of
- * the rest of the cleanup.
- */
-void put_iobus(struct iobus * iobus)
-{
-	if (!atomic_dec_and_lock(&iobus->refcount,&device_lock))
-		return;
-	list_del_init(&iobus->node);
-	spin_unlock(&device_lock);
-
-	if (!list_empty(&iobus->devices) ||
-	    !list_empty(&iobus->children))
-		BUG();
-
-	put_iobus(iobus->parent);
-	/* unregister itself */
-	put_device(iobus->self);
-}
-
-/**
- * device_read_status - report some device information
- * @page:	page-sized buffer to write into
- * @count:	number of bytes requested
- * @off:	offset into buffer
- * @data:	device-specific data
- *
- * Report some human-readable information about the device.
- * This includes the name, the bus id, and the current power state.
- */
-static ssize_t device_read_status(struct device * dev, char * page, size_t count, loff_t off)
-{
-	char *str = page;
-
-	if (off)
-		return 0;
-
-	str += sprintf(str,"Name:       %s\n",dev->name);
-	str += sprintf(str,"Bus ID:     %s\n",dev->bus_id);
-
-	return (str - page);
-}
-
-/**
- * device_write_status - forward a command to a driver
- * @buf:	encoded command
- * @count:	number of bytes in buffer
- * @off:	offset into buffer to start with
- * @data:	device-specific data
- *
- * Send a comamnd to a device driver.
- * The following actions are supported:
- * probe - scan slot for device
- * remove - detach driver from slot
- * suspend <state> <stage> - perform <stage> for entering <state>
- * resume <stage> - perform <stage> for waking device up.
- * (See Documentation/driver-model.txt for the theory of an n-stage
- * suspend sequence).
- */
-static ssize_t device_write_status(struct device * dev, const char* buf, size_t count, loff_t off)
-{
-	char command[20];
-	int num;
-	int arg = 0;
-	int error = 0;
-
-	if (off)
-		return 0;
-
-	/* everything involves dealing with the driver. */
-	if (!dev->driver)
-		return 0;
-
-	num = sscanf(buf,"%10s %d",command,&arg);
-
-	if (!num)
-		return 0;
-
-	if (!strcmp(command,"probe")) {
-		if (dev->driver->probe)
-			error = dev->driver->probe(dev);
-
-	} else if (!strcmp(command,"remove")) {
-		if (dev->driver->remove)
-			error = dev->driver->remove(dev,REMOVE_NOTIFY);
-	} else
-		error = -EFAULT;
-	return error < 0 ? error : count;
-}
-
-static ssize_t
-device_read_power(struct device * dev, char * page, size_t count, loff_t off)
-{
-	char	* str = page;
-
-	if (off)
-		return 0;
-
-	str += sprintf(str,"State:      %d\n",dev->current_state);
-
-	return (str - page);
-}
-
-static ssize_t
-device_write_power(struct device * dev, const char * buf, size_t count, loff_t off)
-{
-	char	str_command[20];
-	char	str_stage[20];
-	int	num_args;
-	u32	state;
-	u32	int_stage;
-	int	error = 0;
-
-	if (off)
-		return 0;
-
-	if (!dev->driver)
-		goto done;
-
-	num_args = sscanf(buf,"%s %s %u",str_command,str_stage,&state);
-
-	error = -EINVAL;
-
-	if (!num_args)
-		goto done;
-
-	if (!strnicmp(str_command,"suspend",7)) {
-		if (num_args != 3)
-			goto done;
-		if (!strnicmp(str_stage,"notify",6))
-			int_stage = SUSPEND_NOTIFY;
-		else if (!strnicmp(str_stage,"save",4))
-			int_stage = SUSPEND_SAVE_STATE;
-		else if (!strnicmp(str_stage,"disable",7))
-			int_stage = SUSPEND_DISABLE;
-		else if (!strnicmp(str_stage,"powerdown",8))
-			int_stage = SUSPEND_POWER_DOWN;
-		else
-			goto done;
-
-		if (dev->driver->suspend)
-			error = dev->driver->suspend(dev,state,int_stage);
-		else
-			error = 0;
-	} else if (!strnicmp(str_command,"resume",6)) {
-		if (num_args != 2)
-			goto done;
-
-		if (!strnicmp(str_stage,"poweron",7))
-			int_stage = RESUME_POWER_ON;
-		else if (!strnicmp(str_stage,"restore",7))
-			int_stage = RESUME_RESTORE_STATE;
-		else if (!strnicmp(str_stage,"enable",6))
-			int_stage = RESUME_ENABLE;
-		else
-			goto done;
-
-		if (dev->driver->resume)
-			error = dev->driver->resume(dev,int_stage);
-		else
-			error = 0;
-	}
- done:
-	return error < 0 ? error : count;
-}
-
-static int __init device_init_root(void)
-{
-	/* initialize parent bus lists */
-	return iobus_register(&device_root);
-}
-
-int __init device_driver_init(void)
-{
-	int error = 0;
-
-	DBG("DEV: Initialising Device Tree\n");
-
-	spin_lock_init(&device_lock);
-
-	error = init_driverfs_fs();
-
-	if (error) {
-		panic("DEV: could not initialise driverfs\n");
-		return error;
-	}
-
-	error = device_init_root();
-	if (error) {
-		printk(KERN_ERR "%s: device root init failed!\n", __FUNCTION__);
-		return error;
-	}
-
-	DBG("DEV: Done Initialising\n");
-	return error;
-}
-
-void __exit device_driver_exit(void)
-{
-
-}
-
-static int __init device_setup(char *str)
-{
-	return 0;
-}
-
-__setup("device=",device_setup);
-
-EXPORT_SYMBOL(device_register);
-EXPORT_SYMBOL(device_create_file);
-EXPORT_SYMBOL(device_remove_file);
-EXPORT_SYMBOL(iobus_register);
-EXPORT_SYMBOL(device_driver_init);
diff -urN linux-2.5.3-pre5/kernel/exit.c linux/kernel/exit.c
--- linux-2.5.3-pre5/kernel/exit.c	Mon Jan 28 13:46:17 2002
+++ linux/kernel/exit.c	Mon Jan 28 13:46:25 2002
@@ -59,6 +59,9 @@
 	current->time_slice += p->time_slice;
 	if (current->time_slice > MAX_TIMESLICE)
 		current->time_slice = MAX_TIMESLICE;
+	if (p->sleep_avg < current->sleep_avg)
+		current->sleep_avg = (current->sleep_avg * EXIT_WEIGHT +
+				p->sleep_avg) / (EXIT_WEIGHT + 1);
 	__restore_flags(flags);
 
 	p->pid = 0;
diff -urN linux-2.5.3-pre5/kernel/fork.c linux/kernel/fork.c
--- linux-2.5.3-pre5/kernel/fork.c	Mon Jan 28 13:46:17 2002
+++ linux/kernel/fork.c	Mon Jan 28 13:46:25 2002
@@ -647,11 +647,10 @@
 	{
 		int i;
 
-		p->cpu = smp_processor_id();
-
 		/* ?? should we just memset this ?? */
 		for(i = 0; i < smp_num_cpus; i++)
-			p->per_cpu_utime[i] = p->per_cpu_stime[i] = 0;
+			p->per_cpu_utime[cpu_logical_map(i)] =
+				p->per_cpu_stime[cpu_logical_map(i)] = 0;
 		spin_lock_init(&p->sigmask_lock);
 	}
 #endif
diff -urN linux-2.5.3-pre5/kernel/sched.c linux/kernel/sched.c
--- linux-2.5.3-pre5/kernel/sched.c	Mon Jan 28 13:46:17 2002
+++ linux/kernel/sched.c	Mon Jan 28 13:46:25 2002
@@ -41,7 +41,7 @@
  */
 struct runqueue {
 	spinlock_t lock;
-	unsigned long nr_running, nr_switches;
+	unsigned long nr_running, nr_switches, expired_timestamp;
 	task_t *curr, *idle;
 	prio_array_t *active, *expired, arrays[2];
 	int prev_nr_running[NR_CPUS];
@@ -70,8 +70,7 @@
 	return __rq;
 }
 
-static inline void unlock_task_rq(runqueue_t *rq, task_t *p,
-							unsigned long *flags)
+static inline void unlock_task_rq(runqueue_t *rq, unsigned long *flags)
 {
 	spin_unlock_irqrestore(&rq->lock, *flags);
 }
@@ -83,13 +82,13 @@
 	array->nr_active--;
 	list_del_init(&p->run_list);
 	if (list_empty(array->queue + p->prio))
-		__set_bit(p->prio, array->bitmap);
+		__clear_bit(p->prio, array->bitmap);
 }
 
 static inline void enqueue_task(struct task_struct *p, prio_array_t *array)
 {
 	list_add_tail(&p->run_list, array->queue + p->prio);
-	__clear_bit(p->prio, array->bitmap);
+	__set_bit(p->prio, array->bitmap);
 	array->nr_active++;
 	p->array = array;
 }
@@ -109,12 +108,30 @@
  * being a CPU hog.
  *
  */
-#define PRIO_INTERACTIVE	(MAX_RT_PRIO + MAX_USER_PRIO/4)
-#define PRIO_CPU_HOG		(MAX_RT_PRIO + MAX_USER_PRIO*3/4)
 
-#define TASK_INTERACTIVE(p) (((p)->prio <= PRIO_INTERACTIVE) ||		\
-	(((p)->prio < PRIO_CPU_HOG) &&					\
-		((p)->prio <= NICE_TO_PRIO((p)->__nice)-3)))
+#define PRIO_INTERACTIVE \
+		(MAX_RT_PRIO + MAX_USER_PRIO*PRIO_INTERACTIVE_RATIO/100)
+#define PRIO_CPU_HOG \
+		(MAX_RT_PRIO + MAX_USER_PRIO*PRIO_CPU_HOG_RATIO/100)
+
+#define TASK_INTERACTIVE(p) \
+	(((p)->prio <= PRIO_INTERACTIVE) || \
+	(((p)->prio < PRIO_CPU_HOG) && \
+		((p)->prio <= NICE_TO_PRIO((p)->__nice) - INTERACTIVE_DELTA)))
+
+/*
+ * We place interactive tasks back into the active array, if possible.
+ *
+ * To guarantee that this does not starve expired tasks we ignore the
+ * interactivity of a task if the first expired task had to wait more
+ * than a 'reasonable' amount of time. This deadline timeout is
+ * load-dependent, as the frequency of array switched decreases with
+ * increasing number of running tasks:
+ */
+#define EXPIRED_STARVING(rq) \
+		((rq)->expired_timestamp && \
+		(jiffies - (rq)->expired_timestamp >= \
+			STARVATION_LIMIT * ((rq)->nr_running) + 1))
 
 static inline int effective_prio(task_t *p)
 {
@@ -122,18 +139,19 @@
 
 	/*
 	 * Here we scale the actual sleep average [0 .... MAX_SLEEP_AVG]
-	 * into the 19 ... -18 bonus/penalty range.
+	 * into the -14 ... +14 bonus/penalty range.
 	 *
-	 * We take off the 10% from the full 0...39 priority range so that:
+	 * We use 70% of the full 0...39 priority range so that:
 	 *
-	 * 1) nice +19 CPU hogs do not preempt nice 0 CPU hogs just yet.
+	 * 1) nice +19 CPU hogs do not preempt nice 0 CPU hogs.
 	 * 2) nice -20 interactive tasks do not get preempted by
 	 *    nice 0 interactive tasks.
 	 *
-	 * Both properties are important to certain applications.
+	 * Both properties are important to certain workloads.
 	 */
-	bonus = MAX_USER_PRIO*9/10 * p->sleep_avg / MAX_SLEEP_AVG -
-							MAX_USER_PRIO*9/10/2;
+	bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 -
+			MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2;
+
 	prio = NICE_TO_PRIO(p->__nice) - bonus;
 	if (prio < MAX_RT_PRIO)
 		prio = MAX_RT_PRIO;
@@ -202,10 +220,10 @@
 	}
 	rq = lock_task_rq(p, &flags);
 	if (unlikely(rq->curr == p)) {
-		unlock_task_rq(rq, p, &flags);
+		unlock_task_rq(rq, &flags);
 		goto repeat;
 	}
-	unlock_task_rq(rq, p, &flags);
+	unlock_task_rq(rq, &flags);
 }
 
 /*
@@ -260,7 +278,7 @@
 			resched_task(rq->curr);
 		success = 1;
 	}
-	unlock_task_rq(rq, p, &flags);
+	unlock_task_rq(rq, &flags);
 	return success;
 }
 
@@ -275,10 +293,13 @@
 
 	p->state = TASK_RUNNING;
 	if (!rt_task(p)) {
-		p->sleep_avg = (p->sleep_avg * 4) / 5;
+		p->sleep_avg = p->sleep_avg * CHILD_FORK_PENALTY / 100;
 		p->prio = effective_prio(p);
+
+		current->sleep_avg = current->sleep_avg * PARENT_FORK_PENALTY / 100;
 	}
 	spin_lock_irq(&rq->lock);
+	p->cpu = smp_processor_id();
 	activate_task(p, rq);
 	spin_unlock_irq(&rq->lock);
 }
@@ -295,14 +316,14 @@
 
 	prepare_to_switch();
 
-	if (!mm) {
+	if (unlikely(!mm)) {
 		next->active_mm = oldmm;
 		atomic_inc(&oldmm->mm_count);
 		enter_lazy_tlb(oldmm, next, smp_processor_id());
 	} else
 		switch_mm(oldmm, mm, next, smp_processor_id());
 
-	if (!prev->mm) {
+	if (unlikely(!prev->mm)) {
 		prev->active_mm = NULL;
 		mmdrop(oldmm);
 	}
@@ -325,7 +346,7 @@
 	unsigned long i, sum = 0;
 
 	for (i = 0; i < smp_num_cpus; i++)
-		sum += cpu_rq(i)->nr_running;
+		sum += cpu_rq(cpu_logical_map(i))->nr_running;
 
 	return sum;
 }
@@ -335,11 +356,34 @@
 	unsigned long i, sum = 0;
 
 	for (i = 0; i < smp_num_cpus; i++)
-		sum += cpu_rq(i)->nr_switches;
+		sum += cpu_rq(cpu_logical_map(i))->nr_switches;
 
 	return sum;
 }
 
+#if CONFIG_SMP
+/*
+ * Lock the busiest runqueue as well, this_rq is locked already.
+ * Recalculate nr_running if we have to drop the runqueue lock.
+ */
+static inline unsigned int double_lock_balance(runqueue_t *this_rq,
+	runqueue_t *busiest, int this_cpu, int idle, unsigned int nr_running)
+{
+	if (unlikely(!spin_trylock(&busiest->lock))) {
+		if (busiest < this_rq) {
+			spin_unlock(&this_rq->lock);
+			spin_lock(&busiest->lock);
+			spin_lock(&this_rq->lock);
+			/* Need to recalculate nr_running */
+			if (idle || (this_rq->nr_running > this_rq->prev_nr_running[this_cpu]))
+				nr_running = this_rq->nr_running;
+			else
+				nr_running = this_rq->prev_nr_running[this_cpu];
+		} else
+			spin_lock(&busiest->lock);
+	}
+	return nr_running;
+}
 /*
  * Current runqueue is empty, or rebalance tick: if there is an
  * inbalance (current runqueue is too short) then pull from
@@ -350,8 +394,8 @@
  */
 static void load_balance(runqueue_t *this_rq, int idle)
 {
-	int imbalance, nr_running, load, prev_max_load,
-		max_load, idx, i, this_cpu = smp_processor_id();
+	int imbalance, nr_running, load, max_load,
+		idx, i, this_cpu = smp_processor_id();
 	task_t *next = this_rq->idle, *tmp;
 	runqueue_t *busiest, *rq_src;
 	prio_array_t *array;
@@ -383,20 +427,18 @@
 		nr_running = this_rq->nr_running;
 	else
 		nr_running = this_rq->prev_nr_running[this_cpu];
-	prev_max_load = 1000000000;
 
 	busiest = NULL;
-	max_load = 0;
+	max_load = 1;
 	for (i = 0; i < smp_num_cpus; i++) {
-		rq_src = cpu_rq(i);
+		rq_src = cpu_rq(cpu_logical_map(i));
 		if (idle || (rq_src->nr_running < this_rq->prev_nr_running[i]))
 			load = rq_src->nr_running;
 		else
 			load = this_rq->prev_nr_running[i];
 		this_rq->prev_nr_running[i] = rq_src->nr_running;
 
-		if ((load > max_load) && (load < prev_max_load) &&
-						(rq_src != this_rq)) {
+		if ((load > max_load) && (rq_src != this_rq)) {
 			busiest = rq_src;
 			max_load = load;
 		}
@@ -407,37 +449,22 @@
 
 	imbalance = (max_load - nr_running) / 2;
 
-	/*
-	 * It needs an at least ~25% imbalance to trigger balancing.
-	 *
-	 * prev_max_load makes sure that we do not try to balance
-	 * ad infinitum - certain tasks might be impossible to be
-	 * pulled into this runqueue.
-	 */
+	/* It needs an at least ~25% imbalance to trigger balancing. */
 	if (!idle && (imbalance < (max_load + 3)/4))
 		return;
-	prev_max_load = max_load;
 
-	/*
-	 * Ok, lets do some actual balancing:
-	 */
-
-	if (busiest < this_rq) {
-		spin_unlock(&this_rq->lock);
-		spin_lock(&busiest->lock);
-		spin_lock(&this_rq->lock);
-	} else
-		spin_lock(&busiest->lock);
+	nr_running = double_lock_balance(this_rq, busiest, this_cpu, idle, nr_running);
 	/*
 	 * Make sure nothing changed since we checked the
 	 * runqueue length.
 	 */
-	if (busiest->nr_running <= nr_running + 1)
+	if (busiest->nr_running <= this_rq->nr_running + 1)
 		goto out_unlock;
 
 	/*
-	 * We first consider expired tasks. Those will likely not run
-	 * in the near future, thus switching CPUs has the least effect
+	 * We first consider expired tasks. Those will likely not be
+	 * executed in the near future, and they are most likely to
+	 * be cache-cold, thus switching CPUs has the least effect
 	 * on them.
 	 */
 	if (busiest->expired->nr_active)
@@ -452,7 +479,7 @@
 	 */
 	idx = MAX_RT_PRIO;
 skip_bitmap:
-	idx = find_next_zero_bit(array->bitmap, MAX_PRIO, idx);
+	idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
 	if (idx == MAX_PRIO) {
 		if (array == busiest->expired) {
 			array = busiest->active;
@@ -462,10 +489,23 @@
 	}
 
 	head = array->queue + idx;
-	curr = head->next;
+	curr = head->prev;
 skip_queue:
 	tmp = list_entry(curr, task_t, run_list);
-	if ((tmp == busiest->curr) || !(tmp->cpus_allowed & (1 << this_cpu))) {
+
+	/*
+	 * We do not migrate tasks that are:
+	 * 1) running (obviously), or
+	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
+	 * 3) are cache-hot on their current CPU.
+	 */
+
+#define CAN_MIGRATE_TASK(p,rq,this_cpu)					\
+	((jiffies - (p)->sleep_timestamp > cache_decay_ticks) &&	\
+		((p) != (rq)->curr) &&					\
+			(tmp->cpus_allowed & (1 << (this_cpu))))
+
+	if (!CAN_MIGRATE_TASK(tmp, busiest, this_cpu)) {
 		curr = curr->next;
 		if (curr != head)
 			goto skip_queue;
@@ -515,17 +555,21 @@
 	spin_unlock(&this_rq()->lock);
 }
 
+#endif
+
 /*
  * This function gets called by the timer code, with HZ frequency.
  * We call it with interrupts disabled.
  */
 void scheduler_tick(task_t *p)
 {
-	unsigned long now = jiffies;
 	runqueue_t *rq = this_rq();
+#if CONFIG_SMP
+	unsigned long now = jiffies;
 
 	if (p == rq->idle)
 		return idle_tick();
+#endif
 	/* Task might have expired already, but not scheduled off yet */
 	if (p->array != rq->active) {
 		p->need_resched = 1;
@@ -562,11 +606,19 @@
 		p->need_resched = 1;
 		p->prio = effective_prio(p);
 		p->time_slice = NICE_TO_TIMESLICE(p->__nice);
-		enqueue_task(p, TASK_INTERACTIVE(p) ? rq->active : rq->expired);
+
+		if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) {
+			if (!rq->expired_timestamp)
+				rq->expired_timestamp = jiffies;
+			enqueue_task(p, rq->expired);
+		} else
+			enqueue_task(p, rq->active);
 	}
 out:
+#if CONFIG_SMP
 	if (!(now % BUSY_REBALANCE_TICK))
 		load_balance(rq, 0);
+#endif
 	spin_unlock(&rq->lock);
 }
 
@@ -589,21 +641,29 @@
 	spin_lock_irq(&rq->lock);
 
 	switch (prev->state) {
+	case TASK_RUNNING:
+		prev->sleep_timestamp = jiffies;
+		break;
 	case TASK_INTERRUPTIBLE:
 		if (unlikely(signal_pending(prev))) {
 			prev->state = TASK_RUNNING;
+			prev->sleep_timestamp = jiffies;
 			break;
 		}
 	default:
 		deactivate_task(prev, rq);
-	case TASK_RUNNING:
 	}
+#if CONFIG_SMP
 pick_next_task:
+#endif
 	if (unlikely(!rq->nr_running)) {
+#if CONFIG_SMP
 		load_balance(rq, 1);
 		if (rq->nr_running)
 			goto pick_next_task;
+#endif
 		next = rq->idle;
+		rq->expired_timestamp = 0;
 		goto switch_tasks;
 	}
 
@@ -615,13 +675,15 @@
 		rq->active = rq->expired;
 		rq->expired = array;
 		array = rq->active;
+		rq->expired_timestamp = 0;
 	}
 
-	idx = sched_find_first_zero_bit(array->bitmap);
+	idx = sched_find_first_bit(array->bitmap);
 	queue = array->queue + idx;
 	next = list_entry(queue->next, task_t, run_list);
 
 switch_tasks:
+	prefetch(next);
 	prev->need_resched = 0;
 
 	if (likely(prev != next)) {
@@ -803,9 +865,9 @@
 	if (new_mask & (1UL << smp_processor_id()))
 		return;
 #if CONFIG_SMP
-	smp_migrate_task(ffz(~new_mask), current);
-
 	current->state = TASK_UNINTERRUPTIBLE;
+	smp_migrate_task(__ffs(new_mask), current);
+
 	schedule();
 #endif
 }
@@ -830,9 +892,8 @@
 		goto out_unlock;
 	}
 	array = p->array;
-	if (array) {
+	if (array)
 		dequeue_task(p, array);
-	}
 	p->__nice = nice;
 	p->prio = NICE_TO_PRIO(nice);
 	if (array) {
@@ -846,7 +907,7 @@
 			resched_task(rq->curr);
 	}
 out_unlock:
-	unlock_task_rq(rq, p, &flags);
+	unlock_task_rq(rq, &flags);
 }
 
 #ifndef __alpha__
@@ -966,7 +1027,7 @@
 		activate_task(p, task_rq(p));
 
 out_unlock:
-	unlock_task_rq(rq, p, &flags);
+	unlock_task_rq(rq, &flags);
 out_unlock_tasklist:
 	read_unlock_irq(&tasklist_lock);
 
@@ -1051,12 +1112,22 @@
 	 */
 	spin_lock_irq(&rq->lock);
 	array = current->array;
-	dequeue_task(current, array);
-	if (likely(!rt_task(current)))
-		if (current->prio < MAX_PRIO-1)
-			current->prio++;
-	enqueue_task(current, array);
-	spin_unlock_irq(&rq->lock);
+	/*
+	 * If the task has reached maximum priority (or is a RT task)
+	 * then just requeue the task to the end of the runqueue:
+	 */
+	if (likely(current->prio == MAX_PRIO-1 || rt_task(current))) {
+		list_del(&current->run_list);
+		list_add_tail(&current->run_list, array->queue + current->prio);
+	} else {
+		list_del(&current->run_list);
+		if (list_empty(array->queue + current->prio))
+			__clear_bit(current->prio, array->bitmap);
+		current->prio++;
+		list_add_tail(&current->run_list, array->queue + current->prio);
+		__set_bit(current->prio, array->bitmap);
+	}
+	spin_unlock(&rq->lock);
 
 	schedule();
 
@@ -1108,7 +1179,7 @@
 	p = find_process_by_pid(pid);
 	if (p)
 		jiffies_to_timespec(p->policy & SCHED_FIFO ?
-					 0 : NICE_TO_TIMESLICE(p->prio), &t);
+					 0 : NICE_TO_TIMESLICE(p->__nice), &t);
 	read_unlock(&tasklist_lock);
 	if (p)
 		retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
@@ -1123,7 +1194,7 @@
 	static const char * stat_nam[] = { "R", "S", "D", "Z", "T", "W" };
 
 	printk("%-13.13s ", p->comm);
-	state = p->state ? ffz(~p->state) + 1 : 0;
+	state = p->state ? __ffs(p->state) + 1 : 0;
 	if (((unsigned) state) < sizeof(stat_nam)/sizeof(char *))
 		printk(stat_nam[state]);
 	else
@@ -1231,22 +1302,23 @@
 		spin_unlock(&rq2->lock);
 }
 
-void __init init_idle(void)
+void __init init_idle(task_t *idle, int cpu)
 {
-	runqueue_t *this_rq = this_rq(), *rq = current->array->rq;
+	runqueue_t *idle_rq = cpu_rq(cpu), *rq = idle->array->rq;
 	unsigned long flags;
 
 	__save_flags(flags);
 	__cli();
-	double_rq_lock(this_rq, rq);
+	double_rq_lock(idle_rq, rq);
 
-	this_rq->curr = this_rq->idle = current;
-	deactivate_task(current, rq);
-	current->array = NULL;
-	current->prio = MAX_PRIO;
-	current->state = TASK_RUNNING;
-	double_rq_unlock(this_rq, rq);
-	current->need_resched = 1;
+	idle_rq->curr = idle_rq->idle = idle;
+	deactivate_task(idle, rq);
+	idle->array = NULL;
+	idle->prio = MAX_PRIO;
+	idle->state = TASK_RUNNING;
+	idle->cpu = cpu;
+	double_rq_unlock(idle_rq, rq);
+	idle->need_resched = 1;
 	__restore_flags(flags);
 }
 
@@ -1274,10 +1346,10 @@
 			array->lock = &rq->lock;
 			for (k = 0; k < MAX_PRIO; k++) {
 				INIT_LIST_HEAD(array->queue + k);
-				__set_bit(k, array->bitmap);
+				__clear_bit(k, array->bitmap);
 			}
-			// zero delimiter for bitsearch
-			__clear_bit(MAX_PRIO, array->bitmap);
+			// delimiter for bitsearch
+			__set_bit(MAX_PRIO, array->bitmap);
 		}
 	}
 	/*
diff -urN linux-2.5.3-pre5/mm/page_alloc.c linux/mm/page_alloc.c
--- linux-2.5.3-pre5/mm/page_alloc.c	Mon Jan  7 12:55:16 2002
+++ linux/mm/page_alloc.c	Mon Jan 28 13:46:25 2002
@@ -394,6 +394,7 @@
 		return NULL;
 
 	/* Yield for kswapd, and try again */
+	__set_current_state(TASK_RUNNING);
 	yield();
 	goto rebalance;
 }
diff -urN linux-2.5.3-pre5/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- linux-2.5.3-pre5/net/ipv4/icmp.c	Mon Jan 14 10:10:43 2002
+++ linux/net/ipv4/icmp.c	Mon Jan 28 13:46:25 2002
@@ -181,8 +181,7 @@
  *	all layers. All Socketless IP sends will soon be gone.
  */
 	
-struct inode icmp_inode;
-struct socket *icmp_socket = &icmp_inode.u.socket_i;
+struct socket *icmp_socket;
 
 /* ICMPv4 socket is only a bit non-reenterable (unlike ICMPv6,
    which is strongly non-reenterable). A bit later it will be made
@@ -979,20 +978,9 @@
 
 void __init icmp_init(struct net_proto_family *ops)
 {
-	int err;
+	int err = sock_create(PF_INET, SOCK_RAW, IPPROTO_ICMP, &icmp_socket);
 
-	icmp_inode.i_mode = S_IFSOCK;
-	icmp_inode.i_sock = 1;
-	icmp_inode.i_uid = 0;
-	icmp_inode.i_gid = 0;
-	init_waitqueue_head(&icmp_inode.i_wait);
-	init_waitqueue_head(&icmp_inode.u.socket_i.wait);
-
-	icmp_socket->inode = &icmp_inode;
-	icmp_socket->state = SS_UNCONNECTED;
-	icmp_socket->type=SOCK_RAW;
-
-	if ((err=ops->create(icmp_socket, IPPROTO_ICMP))<0)
+	if (err < 0)
 		panic("Failed to create the ICMP control socket.\n");
 	icmp_socket->sk->allocation=GFP_ATOMIC;
 	icmp_socket->sk->sndbuf = SK_WMEM_MAX*2;
diff -urN linux-2.5.3-pre5/net/ipv4/netfilter/ip_nat_standalone.c linux/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.5.3-pre5/net/ipv4/netfilter/ip_nat_standalone.c	Mon Jan 28 13:46:17 2002
+++ linux/net/ipv4/netfilter/ip_nat_standalone.c	Mon Jan 28 13:46:26 2002
@@ -166,46 +166,6 @@
 	return ip_nat_fn(hooknum, pskb, in, out, okfn);
 }
 
-static int route_me_harder(struct sk_buff **pskb)
-{
-	struct iphdr *iph = (*pskb)->nh.iph;
-	struct rtable *rt;
-	struct rt_key key = { dst:iph->daddr,
-			      src:iph->saddr,
-			      oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
-			      tos:RT_TOS(iph->tos)|RTO_CONN,
-#ifdef CONFIG_IP_ROUTE_FWMARK
-			      fwmark:(*pskb)->nfmark
-#endif
-			    };
-
-	if (ip_route_output_key(&rt, &key) != 0) {
-		printk("route_me_harder: No more route.\n");
-		return -EINVAL;
-	}
-
-	/* Drop old route. */
-	dst_release((*pskb)->dst);
-
-	(*pskb)->dst = &rt->u.dst;
-
-	/* Change in oif may mean change in hh_len. */
-	if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
-		struct sk_buff *nskb;
-
-		nskb = skb_realloc_headroom(*pskb,
-					    (*pskb)->dst->dev
-					    ->hard_header_len);
-		if (!nskb)
-			return -ENOMEM;
-		if ((*pskb)->sk)
-			skb_set_owner_w(nskb, (*pskb)->sk);
-		kfree_skb(*pskb);
-		*pskb = nskb;
-	}
-	return 0;
-}
-
 static unsigned int
 ip_nat_local_fn(unsigned int hooknum,
 		struct sk_buff **pskb,
diff -urN linux-2.5.3-pre5/net/ipv4/netfilter/ip_queue.c linux/net/ipv4/netfilter/ip_queue.c
--- linux-2.5.3-pre5/net/ipv4/netfilter/ip_queue.c	Sun Sep 30 12:26:08 2001
+++ linux/net/ipv4/netfilter/ip_queue.c	Mon Jan 28 13:46:26 2002
@@ -216,32 +216,6 @@
 	kfree(q);
 }
 
-/* With a chainsaw... */
-static int route_me_harder(struct sk_buff *skb)
-{
-	struct iphdr *iph = skb->nh.iph;
-	struct rtable *rt;
-
-	struct rt_key key = {
-				dst:iph->daddr, src:iph->saddr,
-				oif:skb->sk ? skb->sk->bound_dev_if : 0,
-				tos:RT_TOS(iph->tos)|RTO_CONN,
-#ifdef CONFIG_IP_ROUTE_FWMARK
-				fwmark:skb->nfmark
-#endif
-			};
-
-	if (ip_route_output_key(&rt, &key) != 0) {
-		printk("route_me_harder: No more route.\n");
-		return -EINVAL;
-	}
-
-	/* Drop old route. */
-	dst_release(skb->dst);
-	skb->dst = &rt->u.dst;
-	return 0;
-}
-
 static int ipq_mangle_ipv4(ipq_verdict_msg_t *v, ipq_queue_element_t *e)
 {
 	int diff;
@@ -287,7 +261,7 @@
 		if (!(iph->tos == e->rt_info.tos
 		      && iph->daddr == e->rt_info.daddr
 		      && iph->saddr == e->rt_info.saddr))
-			return route_me_harder(e->skb);
+			return route_me_harder(&e->skb);
 	}
 	return 0;
 }
diff -urN linux-2.5.3-pre5/net/ipv4/netfilter/ipfwadm_core.c linux/net/ipv4/netfilter/ipfwadm_core.c
--- linux-2.5.3-pre5/net/ipv4/netfilter/ipfwadm_core.c	Mon Jan 28 13:46:17 2002
+++ linux/net/ipv4/netfilter/ipfwadm_core.c	Mon Jan 28 13:46:26 2002
@@ -20,7 +20,7 @@
  *	license in recognition of the original copyright.
  *				-- Alan Cox.
  *
- *	$Id: ipfwadm_core.c,v 1.10 2002/01/23 13:20:54 davem Exp $
+ *	$Id: ipfwadm_core.c,v 1.11 2002/01/24 15:50:31 davem Exp $
  *
  *	Ported from BSD to Linux,
  *		Alan Cox 22/Nov/1994.
diff -urN linux-2.5.3-pre5/net/ipv4/netfilter/iptable_mangle.c linux/net/ipv4/netfilter/iptable_mangle.c
--- linux-2.5.3-pre5/net/ipv4/netfilter/iptable_mangle.c	Mon Jan 28 13:46:17 2002
+++ linux/net/ipv4/netfilter/iptable_mangle.c	Mon Jan 28 13:46:26 2002
@@ -129,34 +129,6 @@
 	return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
 }
 
-/* FIXME: change in oif may mean change in hh_len.  Check and realloc
-   --RR */
-static int
-route_me_harder(struct sk_buff *skb)
-{
-	struct iphdr *iph = skb->nh.iph;
-	struct rtable *rt;
-	struct rt_key key = { dst:iph->daddr,
-			      src:iph->saddr,
-			      oif:skb->sk ? skb->sk->bound_dev_if : 0,
-			      tos:RT_TOS(iph->tos)|RTO_CONN,
-#ifdef CONFIG_IP_ROUTE_FWMARK
-			      fwmark:skb->nfmark
-#endif
-			    };
-
-	if (ip_route_output_key(&rt, &key) != 0) {
-		printk("route_me_harder: No more route.\n");
-		return -EINVAL;
-	}
-
-	/* Drop old route. */
-	dst_release(skb->dst);
-
-	skb->dst = &rt->u.dst;
-	return 0;
-}
-
 static unsigned int
 ipt_local_hook(unsigned int hook,
 		   struct sk_buff **pskb,
@@ -190,7 +162,7 @@
 		|| (*pskb)->nh.iph->daddr != daddr
 		|| (*pskb)->nfmark != nfmark
 		|| (*pskb)->nh.iph->tos != tos))
-		return route_me_harder(*pskb) == 0 ? ret : NF_DROP;
+		return route_me_harder(pskb) == 0 ? ret : NF_DROP;
 
 	return ret;
 }
diff -urN linux-2.5.3-pre5/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- linux-2.5.3-pre5/net/ipv4/tcp_ipv4.c	Mon Jan 28 13:46:17 2002
+++ linux/net/ipv4/tcp_ipv4.c	Mon Jan 28 13:46:26 2002
@@ -69,8 +69,7 @@
 #define ICMP_MIN_LENGTH 8
 
 /* Socket used for sending RSTs */ 	
-static struct inode tcp_inode;
-static struct socket *tcp_socket=&tcp_inode.u.socket_i;
+static struct socket *tcp_socket;
 
 void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, 
 		       struct sk_buff *skb);
@@ -2194,20 +2193,8 @@
 
 void __init tcp_v4_init(struct net_proto_family *ops)
 {
-	int err;
-
-	tcp_inode.i_mode = S_IFSOCK;
-	tcp_inode.i_sock = 1;
-	tcp_inode.i_uid = 0;
-	tcp_inode.i_gid = 0;
-	init_waitqueue_head(&tcp_inode.i_wait);
-	init_waitqueue_head(&tcp_inode.u.socket_i.wait);
-
-	tcp_socket->inode = &tcp_inode;
-	tcp_socket->state = SS_UNCONNECTED;
-	tcp_socket->type=SOCK_RAW;
-
-	if ((err=ops->create(tcp_socket, IPPROTO_TCP))<0)
+	int err = sock_create(PF_INET, SOCK_RAW, IPPROTO_TCP, &tcp_socket);
+	if (err < 0)
 		panic("Failed to create the TCP control socket.\n");
 	tcp_socket->sk->allocation=GFP_ATOMIC;
 	tcp_socket->sk->protinfo.af_inet.ttl = MAXTTL;
diff -urN linux-2.5.3-pre5/net/ipv6/proc.c linux/net/ipv6/proc.c
--- linux-2.5.3-pre5/net/ipv6/proc.c	Sun Jul  9 22:30:41 2000
+++ linux/net/ipv6/proc.c	Mon Jan 28 13:46:26 2002
@@ -7,7 +7,7 @@
  *		PROC file system.  This is very similar to the IPv4 version,
  *		except it reports the sockets in the INET6 address family.
  *
- * Version:	$Id: proc.c,v 1.15 2000/07/07 22:29:42 davem Exp $
+ * Version:	$Id: proc.c,v 1.16 2002/01/24 15:45:51 davem Exp $
  *
  * Authors:	David S. Miller (davem@caip.rutgers.edu)
  *
@@ -37,7 +37,7 @@
 	return res;
 }
 
-int afinet6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+int afinet6_get_info(char *buffer, char **start, off_t offset, int length)
 {
 	int len = 0;
 	len += sprintf(buffer+len, "TCP6: inuse %d\n",
