Merge master.kernel.org:/pub/scm/linux/kernel/git/paulus/ppc64-2.6 
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index dc27659..c8bce82 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -90,7 +90,7 @@
 
 It also defines this helper for defining device attributes: 
 
-#define DEVICE_ATTR(_name,_mode,_show,_store)      \
+#define DEVICE_ATTR(_name, _mode, _show, _store)      \
 struct device_attribute dev_attr_##_name = {            \
         .attr = {.name  = __stringify(_name) , .mode   = _mode },      \
         .show   = _show,                                \
@@ -99,14 +99,14 @@
 
 For example, declaring
 
-static DEVICE_ATTR(foo,0644,show_foo,store_foo);
+static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
 
 is equivalent to doing:
 
 static struct device_attribute dev_attr_foo = {
        .attr	= {
 		.name = "foo",
-		.mode = 0644,
+		.mode = S_IWUSR | S_IRUGO,
 	},
 	.show = show_foo,
 	.store = store_foo,
@@ -121,8 +121,8 @@
 show and store methods of the attribute owners. 
 
 struct sysfs_ops {
-        ssize_t (*show)(struct kobject *, struct attribute *,char *);
-        ssize_t (*store)(struct kobject *,struct attribute *,const char *);
+        ssize_t (*show)(struct kobject *, struct attribute *, char *);
+        ssize_t (*store)(struct kobject *, struct attribute *, const char *);
 };
 
 [ Subsystems should have already defined a struct kobj_type as a
@@ -137,7 +137,7 @@
 
 To illustrate:
 
-#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
 #define to_dev(d) container_of(d, struct device, kobj)
 
 static ssize_t
@@ -148,7 +148,7 @@
         ssize_t ret = 0;
 
         if (dev_attr->show)
-                ret = dev_attr->show(dev,buf);
+                ret = dev_attr->show(dev, buf);
         return ret;
 }
 
@@ -216,16 +216,16 @@
 
 static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
-        return sprintf(buf,"%s\n",dev->name);
+	return snprintf(buf, PAGE_SIZE, "%s\n", dev->name);
 }
 
 static ssize_t store_name(struct device * dev, const char * buf)
 {
-	sscanf(buf,"%20s",dev->name);
-	return strlen(buf);
+	sscanf(buf, "%20s", dev->name);
+	return strnlen(buf, PAGE_SIZE);
 }
 
-static DEVICE_ATTR(name,S_IRUGO,show_name,store_name);
+static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
 
 
 (Note that the real implementation doesn't allow userspace to set the 
@@ -290,7 +290,7 @@
 
 Declaring:
 
-DEVICE_ATTR(_name,_str,_mode,_show,_store);
+DEVICE_ATTR(_name, _str, _mode, _show, _store);
 
 Creation/Removal:
 
@@ -310,7 +310,7 @@
 
 Declaring:
 
-BUS_ATTR(_name,_mode,_show,_store)
+BUS_ATTR(_name, _mode, _show, _store)
 
 Creation/Removal:
 
@@ -331,7 +331,7 @@
 
 Declaring:
 
-DRIVER_ATTR(_name,_mode,_show,_store)
+DRIVER_ATTR(_name, _mode, _show, _store)
 
 Creation/Removal:
 
diff --git a/Documentation/hwmon/lm78 b/Documentation/hwmon/lm78
index 357086e..fd5dc7a 100644
--- a/Documentation/hwmon/lm78
+++ b/Documentation/hwmon/lm78
@@ -2,16 +2,11 @@
 ==================
 
 Supported chips:
-  * National Semiconductor LM78
+  * National Semiconductor LM78 / LM78-J
     Prefix: 'lm78'
     Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
-  * National Semiconductor LM78-J
-    Prefix: 'lm78-j'
-    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
-    Datasheet: Publicly available at the National Semiconductor website
-               http://www.national.com/
   * National Semiconductor LM79
     Prefix: 'lm79'
     Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
diff --git a/Documentation/hwmon/w83792d b/Documentation/hwmon/w83792d
new file mode 100644
index 0000000..8171c28
--- /dev/null
+++ b/Documentation/hwmon/w83792d
@@ -0,0 +1,174 @@
+Kernel driver w83792d
+=====================
+
+Supported chips:
+  * Winbond W83792D
+    Prefix: 'w83792d'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/PDFresult.asp?Pname=1035
+
+Author: Chunhao Huang
+Contact: DZShen <DZShen@Winbond.com.tw>
+
+
+Module Parameters
+-----------------
+
+* init int
+  (default 1)
+  Use 'init=0' to bypass initializing the chip.
+  Try this if your computer crashes when you load the module.
+
+* force_subclients=bus,caddr,saddr,saddr
+  This is used to force the i2c addresses for subclients of
+  a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
+  to force the subclients of chip 0x2f on bus 0 to i2c addresses
+  0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for the Winbond W83792AD/D.
+
+Detection of the chip can sometimes be foiled because it can be in an
+internal state that allows no clean access (Bank with ID register is not
+currently selected). If you know the address of the chip, use a 'force'
+parameter; this will put it into a more well-behaved state first.
+
+The driver implements three temperature sensors, seven fan rotation speed
+sensors, nine voltage sensors, and two automatic fan regulation
+strategies called: Smart Fan I (Thermal Cruise mode) and Smart Fan II.
+Automatic fan control mode is possible only for fan1-fan3. Fan4-fan7 can run
+synchronized with selected fan (fan1-fan3). This functionality and manual PWM
+control for fan4-fan7 is not yet implemented.
+
+Temperatures are measured in degrees Celsius and measurement resolution is 1
+degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
+the temperature gets higher than the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
+128) to give the readings more range or accuracy.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+Alarms are provided as output from "realtime status register". Following bits
+are defined:
+
+bit - alarm on:
+0  - in0
+1  - in1
+2  - temp1
+3  - temp2
+4  - temp3
+5  - fan1
+6  - fan2
+7  - fan3
+8  - in2
+9  - in3
+10 - in4
+11 - in5
+12 - in6
+13 - VID change
+14 - chassis
+15 - fan7
+16 - tart1
+17 - tart2
+18 - tart3
+19 - in7
+20 - in8
+21 - fan4
+22 - fan5
+23 - fan6
+
+Tart will be asserted while target temperature cannot be achieved after 3 minutes
+of full speed rotation of corresponding fan.
+
+In addition to the alarms described above, there is a CHAS alarm on the chips
+which triggers if your computer case is open (This one is latched, contrary
+to realtime alarms).
+
+The chips only update values each 3 seconds; reading them more often will
+do no harm, but will return 'old' values.
+
+
+W83792D PROBLEMS
+----------------
+Known problems:
+	- This driver is only for Winbond W83792D C version device, there
+	  are also some motherboards with B version W83792D device. The
+	  calculation method to in6-in7(measured value, limits) is a little
+	  different between C and B version. C or B version can be identified
+	  by CR[0x49h].
+	- The function of vid and vrm has not been finished, because I'm NOT
+	  very familiar with them. Adding support is welcome.
+ 	- The function of chassis open detection needs more tests.
+	- If you have ASUS server board and chip was not found: Then you will
+	  need to upgrade to latest (or beta) BIOS. If it does not help please
+	  contact us.
+
+Fan control
+-----------
+
+Manual mode
+-----------
+
+Works as expected. You just need to specify desired PWM/DC value (fan speed)
+in appropriate pwm# file.
+
+Thermal cruise
+--------------
+
+In this mode, W83792D provides the Smart Fan system to automatically control
+fan speed to keep the temperatures of CPU and the system within specific
+range. At first a wanted temperature and interval must be set. This is done
+via thermal_cruise# file. The tolerance# file serves to create T +- tolerance
+interval. The fan speed will be lowered as long as the current temperature
+remains below the thermal_cruise# +- tolerance# value. Once the temperature
+exceeds the high limit (T+tolerance), the fan will be turned on with a
+specific speed set by pwm# and automatically controlled its PWM duty cycle
+with the temperature varying. Three conditions may occur:
+
+(1) If the temperature still exceeds the high limit, PWM duty
+cycle will increase slowly.
+
+(2) If the temperature goes below the high limit, but still above the low
+limit (T-tolerance), the fan speed will be fixed at the current speed because
+the temperature is in the target range.
+
+(3) If the temperature goes below the low limit, PWM duty cycle will decrease
+slowly to 0 or a preset stop value until the temperature exceeds the low
+limit. (The preset stop value handling is not yet implemented in driver)
+
+Smart Fan II
+------------
+
+W83792D also provides a special mode for fan. Four temperature points are
+available. When related temperature sensors detects the temperature in preset
+temperature region (sf2_point@_fan# +- tolerance#) it will cause fans to run
+on programmed value from sf2_level@_fan#. You need to set four temperatures
+for each fan.
+
+
+/sys files
+----------
+
+pwm[1-3] - this file stores PWM duty cycle or DC value (fan speed) in range:
+	0 (stop) to 255 (full)
+pwm[1-3]_enable - this file controls mode of fan/temperature control:
+            * 0 Disabled
+            * 1 Manual mode
+            * 2 Smart Fan II
+            * 3 Thermal Cruise
+pwm[1-3]_mode - Select PWM of DC mode
+            * 0 DC
+            * 1 PWM
+thermal_cruise[1-3] - Selects the desired temperature for cruise (degC)
+tolerance[1-3] - Value in degrees of Celsius (degC) for +- T
+sf2_point[1-4]_fan[1-3] - four temperature points for each fan for Smart Fan II
+sf2_level[1-3]_fan[1-3] - three PWM/DC levels for each fan for Smart Fan II
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
index b020028..96fec56 100644
--- a/Documentation/i2c/chips/max6875
+++ b/Documentation/i2c/chips/max6875
@@ -4,22 +4,13 @@
 Supported chips:
   * Maxim MAX6874, MAX6875
     Prefix: 'max6875'
-    Addresses scanned: 0x50, 0x52
+    Addresses scanned: None (see below)
     Datasheet:
         http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
 
 Author: Ben Gardner <bgardner@wabtec.com>
 
 
-Module Parameters
------------------
-
-* allow_write int
-  Set to non-zero to enable write permission:
-  *0: Read only
-   1: Read and write
-
-
 Description
 -----------
 
@@ -33,34 +24,85 @@
 
 The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
 and outputs:
-
              vin     gpi    vout
 MAX6874        6       4       8
 MAX6875        4       3       5
 
-MAX6874 chips can have four different addresses (as opposed to only two for
-the MAX6875). The additional addresses (0x54 and 0x56) are not probed by
-this driver by default, but the probe module parameter can be used if
-needed.
-
-See the datasheet for details on how to program the EEPROM.
+See the datasheet for more information.
 
 
 Sysfs entries
 -------------
 
-eeprom_user   - 512 bytes of user-defined EEPROM space. Only writable if
-                allow_write was set and register 0x43 is 0.
-
-eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
-                loaded into register space until a power cycle or device reset.
-
-reg_config    - 70 bytes of register space. Any changes take affect immediately.
+eeprom        - 512 bytes of user-defined EEPROM space.
 
 
 General Remarks
 ---------------
 
-A typical application will require that the EEPROMs be programmed once and
-never altered afterwards.
+Valid addresses for the MAX6875 are 0x50 and 0x52.
+Valid addresses for the MAX6874 are 0x50, 0x52, 0x54 and 0x56.
+The driver does not probe any address, so you must force the address.
+
+Example:
+$ modprobe max6875 force=0,0x50
+
+The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
+addresses.  For example, for address 0x50, it also reserves 0x51.
+The even-address instance is called 'max6875', the odd one is 'max6875 subclient'.
+
+
+Programming the chip using i2c-dev
+----------------------------------
+
+Use the i2c-dev interface to access and program the chips.
+Reads and writes are performed differently depending on the address range.
+
+The configuration registers are at addresses 0x00 - 0x45.
+Use i2c_smbus_write_byte_data() to write a register and
+i2c_smbus_read_byte_data() to read a register.
+The command is the register number.
+
+Examples:
+To write a 1 to register 0x45:
+  i2c_smbus_write_byte_data(fd, 0x45, 1);
+
+To read register 0x45:
+  value = i2c_smbus_read_byte_data(fd, 0x45);
+
+
+The configuration EEPROM is at addresses 0x8000 - 0x8045.
+The user EEPROM is at addresses 0x8100 - 0x82ff.
+
+Use i2c_smbus_write_word_data() to write a byte to EEPROM.
+
+The command is the upper byte of the address: 0x80, 0x81, or 0x82.
+The data word is the lower part of the address or'd with data << 8.
+  cmd = address >> 8;
+  val = (address & 0xff) | (data << 8);
+
+Example:
+To write 0x5a to address 0x8003:
+  i2c_smbus_write_word_data(fd, 0x80, 0x5a03);
+
+
+Reading data from the EEPROM is a little more complicated.
+Use i2c_smbus_write_byte_data() to set the read address and then
+i2c_smbus_read_byte() or i2c_smbus_read_i2c_block_data() to read the data.
+
+Example:
+To read data starting at offset 0x8100, first set the address:
+  i2c_smbus_write_byte_data(fd, 0x81, 0x00);
+
+And then read the data
+  value = i2c_smbus_read_byte(fd);
+
+  or
+
+  count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
+
+The block read should read 16 bytes.
+0x84 is the block read command.
+
+See the datasheet for more details.
 
diff --git a/Documentation/i2c/functionality b/Documentation/i2c/functionality
index 8a78a95..41ffefb 100644
--- a/Documentation/i2c/functionality
+++ b/Documentation/i2c/functionality
@@ -115,7 +115,7 @@
 If you try to access an adapter from a userspace program, you will have
 to use the /dev interface. You will still have to check whether the
 functionality you need is supported, of course. This is done using
-the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2c_detect
+the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
 program, is below:
 
   int file;
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index a7adbdd..4849dfd 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -1,4 +1,4 @@
-Revision 4, 2004-03-30
+Revision 5, 2005-07-29
 Jean Delvare <khali@linux-fr.org>
 Greg KH <greg@kroah.com>
 
@@ -17,20 +17,22 @@
 
 Technical changes:
 
-* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
-  <linux/i2c-sensor.h>. Includes typically look like that:
+* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
+  Includes typically look like that:
   #include <linux/module.h>
   #include <linux/init.h>
   #include <linux/slab.h>
   #include <linux/i2c.h>
-  #include <linux/i2c-sensor.h>
-  #include <linux/i2c-vid.h>	/* if you need VRM support */
+  #include <linux/hwmon.h>	/* for hardware monitoring drivers */
+  #include <linux/hwmon-sysfs.h>
+  #include <linux/hwmon-vid.h>	/* if you need VRM support */
   #include <asm/io.h>		/* if you have I/O operations */
   Please respect this inclusion order. Some extra headers may be
   required for a given driver (e.g. "lm75.h").
 
-* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
-  becomes I2C_CLIENT_ISA_END.
+* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
+  are no more handled by the i2c core.
+  SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
 
 * [Client data] Get rid of sysctl_id. Try using standard names for
   register values (for example, temp_os becomes temp_max). You're
@@ -66,13 +68,15 @@
   if (!(adapter->class & I2C_CLASS_HWMON))
           return 0;
   ISA-only drivers of course don't need this.
+  Call i2c_probe() instead of i2c_detect().
 
 * [Detect] As mentioned earlier, the flags parameter is gone.
   The type_name and client_name strings are replaced by a single
   name string, which will be filled with a lowercase, short string
   (typically the driver name, e.g. "lm75").
   In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
-  useless.
+  useless. Same for isa-only drivers, as the test would always be
+  true. Only hybrid drivers (which are quite rare) still need it.
   The errorN labels are reduced to the number needed. If that number
   is 2 (i2c-only drivers), it is advised that the labels are named
   exit and exit_free. For i2c+isa drivers, labels should be named
@@ -86,6 +90,8 @@
   device_create_file. Move the driver initialization before any
   sysfs file creation.
   Drop client->id.
+  Drop any 24RF08 corruption prevention you find, as this is now done
+  at the i2c-core level, and doing it twice voids it.
 
 * [Init] Limits must not be set by the driver (can be done later in
   user-space). Chip should not be reset default (although a module
@@ -93,7 +99,8 @@
   limited to the strictly necessary steps.
 
 * [Detach] Get rid of data, remove the call to
-  i2c_deregister_entry.
+  i2c_deregister_entry. Do not log an error message if
+  i2c_detach_client fails, as i2c-core will now do it for you.
 
 * [Update] Don't access client->data directly, use
   i2c_get_clientdata(client) instead.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 91664be..0772757 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -148,15 +148,15 @@
 detection algorithm.
 
 You do not have to use this parameter interface; but don't try to use
-function i2c_probe() (or i2c_detect()) if you don't.
+function i2c_probe() if you don't.
 
 NOTE: If you want to write a `sensors' driver, the interface is slightly
       different! See below.
 
 
 
-Probing classes (i2c)
----------------------
+Probing classes
+---------------
 
 All parameters are given as lists of unsigned 16-bit integers. Lists are
 terminated by I2C_CLIENT_END.
@@ -171,12 +171,18 @@
    ignore: insmod parameter.
      A list of pairs. The first value is a bus number (-1 for any I2C bus), 
      the second is the I2C address. These addresses are never probed. 
-     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+     This parameter overrules the 'normal_i2c' list only.
    force: insmod parameter. 
      A list of pairs. The first value is a bus number (-1 for any I2C bus),
      the second is the I2C address. A device is blindly assumed to be on
      the given address, no probing is done. 
 
+Additionally, kind-specific force lists may optionally be defined if
+the driver supports several chip kinds. They are grouped in a
+NULL-terminated list of pointers named forces, those first element if the
+generic force list mentioned above. Each additional list correspond to an
+insmod parameter of the form force_<kind>.
+
 Fortunately, as a module writer, you just have to define the `normal_i2c' 
 parameter. The complete declaration could look like this:
 
@@ -186,66 +192,17 @@
 
   /* Magic definition of all other variables and things */
   I2C_CLIENT_INSMOD;
+  /* Or, if your driver supports, say, 2 kind of devices: */
+  I2C_CLIENT_INSMOD_2(foo, bar);
+
+If you use the multi-kind form, an enum will be defined for you:
+  enum chips { any_chip, foo, bar, ... }
+You can then (and certainly should) use it in the driver code.
 
 Note that you *have* to call the defined variable `normal_i2c',
 without any prefix!
 
 
-Probing classes (sensors)
--------------------------
-
-If you write a `sensors' driver, you use a slightly different interface.
-As well as I2C addresses, we have to cope with ISA addresses. Also, we
-use a enum of chip types. Don't forget to include `sensors.h'.
-
-The following lists are used internally. They are all lists of integers.
-
-   normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
-     A list of I2C addresses which should normally be examined.
-   normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
-     A list of ISA addresses which should normally be examined.
-   probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
-     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the address. These
-     addresses are also probed, as if they were in the 'normal' list.
-   ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
-     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the I2C address. These
-     addresses are never probed. This parameter overrules 'normal' and 
-     'probe', but not the 'force' lists.
-
-Also used is a list of pointers to sensors_force_data structures:
-   force_data: insmod parameters. A list, ending with an element of which
-     the force field is NULL.
-     Each element contains the type of chip and a list of pairs.
-     The first value is a bus number (SENSORS_ISA_BUS for the ISA bus, 
-     -1 for any I2C bus), the second is the address. 
-     These are automatically translated to insmod variables of the form
-     force_foo.
-
-So we have a generic insmod variabled `force', and chip-specific variables
-`force_CHIPNAME'.
-
-Fortunately, as a module writer, you just have to define the `normal_i2c' 
-and `normal_isa' parameters, and define what chip names are used. 
-The complete declaration could look like this:
-  /* Scan i2c addresses 0x37, and 0x48 to 0x4f */
-  static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
-                                         0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-  /* Scan ISA address 0x290 */
-  static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
-
-  /* Define chips foo and bar, as well as all module parameters and things */
-  SENSORS_INSMOD_2(foo,bar);
-
-If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2
-you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want to
-bother with chip types, you can use SENSORS_INSMOD_0.
-
-A enum is automatically defined as follows:
-  enum chips { any_chip, chip1, chip2, ... }
-
-
 Attaching to an adapter
 -----------------------
 
@@ -264,17 +221,10 @@
     return i2c_probe(adapter,&addr_data,&foo_detect_client);
   }
 
-For `sensors' drivers, use the i2c_detect function instead:
-  
-  int foo_attach_adapter(struct i2c_adapter *adapter)
-  { 
-    return i2c_detect(adapter,&addr_data,&foo_detect_client);
-  }
-
 Remember, structure `addr_data' is defined by the macros explained above,
 so you do not have to define it yourself.
 
-The i2c_probe or i2c_detect function will call the foo_detect_client
+The i2c_probe function will call the foo_detect_client
 function only for those i2c addresses that actually have a device on
 them (unless a `force' parameter was used). In addition, addresses that
 are already in use (by some other registered client) are skipped.
@@ -283,19 +233,18 @@
 The detect client function
 --------------------------
 
-The detect client function is called by i2c_probe or i2c_detect.
-The `kind' parameter contains 0 if this call is due to a `force'
-parameter, and -1 otherwise (for i2c_detect, it contains 0 if
-this call is due to the generic `force' parameter, and the chip type
-number if it is due to a specific `force' parameter).
+The detect client function is called by i2c_probe. The `kind' parameter
+contains -1 for a probed detection, 0 for a forced detection, or a positive
+number for a forced detection with a chip type forced.
 
 Below, some things are only needed if this is a `sensors' driver. Those
 parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
 markers. 
 
-This function should only return an error (any value != 0) if there is
-some reason why no more detection should be done anymore. If the
-detection just fails for this address, return 0.
+Returning an error different from -ENODEV in a detect function will cause
+the detection to stop: other addresses and adapters won't be scanned.
+This should only be done on fatal or internal errors, such as a memory
+shortage or i2c_attach_client failing.
 
 For now, you can ignore the `flags' parameter. It is there for future use.
 
@@ -320,11 +269,10 @@
     const char *type_name = "";
     int is_isa = i2c_is_isa_adapter(adapter);
 
-    if (is_isa) {
+    /* Do this only if the chip can additionally be found on the ISA bus
+       (hybrid chip). */
 
-      /* If this client can't be on the ISA bus at all, we can stop now
-         (call `goto ERROR0'). But for kicks, we will assume it is all
-         right. */
+    if (is_isa) {
 
       /* Discard immediately if this ISA range is already used */
       if (check_region(address,FOO_EXTENT))
@@ -495,15 +443,13 @@
     /* SENSORS ONLY END */
 
     /* Try to detach the client from i2c space */
-    if ((err = i2c_detach_client(client))) {
-      printk("foo.o: Client deregistration failed, client not detached.\n");
+    if ((err = i2c_detach_client(client)))
       return err;
-    }
 
-    /* SENSORS ONLY START */
+    /* HYBRID SENSORS CHIP ONLY START */
     if i2c_is_isa_client(client)
       release_region(client->addr,LM78_EXTENT);
-    /* SENSORS ONLY END */
+    /* HYBRID SENSORS CHIP ONLY END */
 
     kfree(client); /* Frees client data too, if allocated at the same time */
     return 0;
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 2616a58..9a15865 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -872,7 +872,13 @@
 	Assignments to $(targets) are without $(obj)/ prefix.
 	if_changed may be used in conjunction with custom commands as
 	defined in 6.7 "Custom kbuild commands".
+
 	Note: It is a typical mistake to forget the FORCE prerequisite.
+	Another common pitfall is that whitespace is sometimes
+	significant; for instance, the below will fail (note the extra space
+	after the comma):
+		target: source(s) FORCE
+	#WRONG!#	$(call if_changed, ld/objcopy/gzip)
 
     ld
 	Link target. Often LDFLAGS_$@ is used to set specific options to ld.
diff --git a/MAINTAINERS b/MAINTAINERS
index 5899ec1..7e1f671 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -933,6 +933,13 @@
 W:	http://www.kernel.org/pub/linux/utils/net/hdlc/
 S:	Maintained
 
+HARDWARE MONITORING
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	lm-sensors@lm-sensors.org
+W:	http://www.lm-sensors.nu/
+S:	Maintained
+
 HARMONY SOUND DRIVER
 P:	Kyle McMartin
 M:	kyle@parisc-linux.org
@@ -1014,7 +1021,7 @@
 M:	wli@holomorphy.com
 S:	Maintained
 
-I2C AND SENSORS DRIVERS
+I2C SUBSYSTEM
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
 P:	Jean Delvare
diff --git a/Makefile b/Makefile
index 2d68adb..63e5c9f 100644
--- a/Makefile
+++ b/Makefile
@@ -109,10 +109,9 @@
 .PHONY: $(MAKECMDGOALS)
 
 $(filter-out _all,$(MAKECMDGOALS)) _all:
-	$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT)		\
-	KBUILD_SRC=$(CURDIR)	     KBUILD_VERBOSE=$(KBUILD_VERBOSE)	\
-	KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)"	\
-        -f $(CURDIR)/Makefile $@
+	$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
+	KBUILD_SRC=$(CURDIR) \
+	KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
 
 # Leave processing to above invocation of make
 skip-makefile := 1
@@ -233,7 +232,7 @@
   KBUILD_MODULES := 1
 endif
 
-export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
+export KBUILD_MODULES KBUILD_BUILTIN
 export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
 
 # Beautify output
@@ -309,6 +308,9 @@
 # Look for make include files relative to root of kernel src
 MAKEFLAGS += --include-dir=$(srctree)
 
+# We need some generic definitions
+include  $(srctree)/scripts/Kbuild.include
+
 # For maximum performance (+ possibly random breakage, uncomment
 # the following)
 
@@ -348,7 +350,7 @@
 
 CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
-CFLAGS 		:= -Wall -Wstrict-prototypes -Wno-trigraphs \
+CFLAGS 		:= -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
 	  	   -fno-strict-aliasing -fno-common \
 		   -ffreestanding
 AFLAGS		:= -D__ASSEMBLY__
@@ -367,11 +369,6 @@
 # even be read-only.
 export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
 
-# The temporary file to save gcc -MD generated dependencies must not
-# contain a comma
-comma := ,
-depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
-
 # Files to ignore in find ... statements
 
 RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg \) -prune -o
@@ -551,6 +548,26 @@
 # images. Default is /boot, but you can set it to other values
 export	INSTALL_PATH ?= /boot
 
+# If CONFIG_LOCALVERSION_AUTO is set, we automatically perform some tests
+# and try to determine if the current source tree is a release tree, of any sort,
+# or if is a pure development tree.
+#
+# A 'release tree' is any tree with a git TAG associated
+# with it.  The primary goal of this is to make it safe for a native
+# git/CVS/SVN user to build a release tree (i.e, 2.6.9) and also to
+# continue developing against the current Linus tree, without having the Linus
+# tree overwrite the 2.6.9 tree when installed.
+#
+# Currently, only git is supported.
+# Other SCMs can edit scripts/setlocalversion and add the appropriate
+# checks as needed.
+
+
+ifdef CONFIG_LOCALVERSION_AUTO
+	localversion-auto := $(shell $(PERL) $(srctree)/scripts/setlocalversion $(srctree))
+	LOCALVERSION := $(LOCALVERSION)$(localversion-auto)
+endif
+
 #
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
 # relocations required by build roots.  This is not defined in the
@@ -691,8 +708,10 @@
 
 # Update vmlinux version before link
 # Use + in front of this rule to silent warning about make -j1
+# First command is ':' to allow us to use + in front of this rule
 cmd_ksym_ld = $(cmd_vmlinux__)
 define rule_ksym_ld
+	: 
 	+$(call cmd,vmlinux_version)
 	$(call cmd,vmlinux__)
 	$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
@@ -722,6 +741,16 @@
 # Needs to visit scripts/ before $(KALLSYMS) can be used.
 $(KALLSYMS): scripts ;
 
+# Generate some data for debugging strange kallsyms problems
+debug_kallsyms: .tmp_map$(last_kallsyms)
+
+.tmp_map%: .tmp_vmlinux% FORCE
+	($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
+
+.tmp_map3: .tmp_map2
+
+.tmp_map2: .tmp_map1
+
 endif # ifdef CONFIG_KALLSYMS
 
 # vmlinux image - including updated kernel symbols
@@ -757,7 +786,7 @@
 prepare2:
 ifneq ($(KBUILD_SRC),)
 	@echo '  Using $(srctree) as source for kernel'
-	$(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \
+	$(Q)if [ -f $(srctree)/.config ]; then \
 		echo "  $(srctree) is not clean, please run 'make mrproper'";\
 		echo "  in the '$(srctree)' directory.";\
 		/bin/false; \
@@ -769,7 +798,8 @@
 # prepare1 creates a makefile if using a separate output directory
 prepare1: prepare2 outputmakefile
 
-prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
+prepare0: prepare1 include/linux/version.h include/asm \
+                   include/config/MARKER
 ifneq ($(KBUILD_MODULES),)
 	$(Q)rm -rf $(MODVERDIR)
 	$(Q)mkdir -p $(MODVERDIR)
@@ -875,7 +905,7 @@
 
 .PHONY: _modinst_
 _modinst_:
-	@if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \
+	@if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
 		echo "Warning: you may need to install module-init-tools"; \
 		echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
 		sleep 1; \
@@ -1159,37 +1189,49 @@
 __srctree = $(srctree)/
 endif
 
+ALLSOURCE_ARCHS := $(ARCH)
+
 define all-sources
 	( find $(__srctree) $(RCS_FIND_IGNORE) \
 	       \( -name include -o -name arch \) -prune -o \
 	       -name '*.[chS]' -print; \
-	  find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \
-	       -name '*.[chS]' -print; \
+	  for ARCH in $(ALLSOURCE_ARCHS) ; do \
+	       find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
+	            -name '*.[chS]' -print; \
+	  done ; \
 	  find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
 	       -name '*.[chS]' -print; \
 	  find $(__srctree)include $(RCS_FIND_IGNORE) \
 	       \( -name config -o -name 'asm-*' \) -prune \
 	       -o -name '*.[chS]' -print; \
-	  find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
-	       -name '*.[chS]' -print; \
+	  for ARCH in $(ALLSOURCE_ARCHS) ; do \
+	       find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
+	            -name '*.[chS]' -print; \
+	  done ; \
 	  find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
 	       -name '*.[chS]' -print )
 endef
 
 quiet_cmd_cscope-file = FILELST cscope.files
-      cmd_cscope-file = $(all-sources) > cscope.files
+      cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
 
 quiet_cmd_cscope = MAKE    cscope.out
-      cmd_cscope = cscope -k -b -q
+      cmd_cscope = cscope -b
 
 cscope: FORCE
 	$(call cmd,cscope-file)
 	$(call cmd,cscope)
 
 quiet_cmd_TAGS = MAKE   $@
-cmd_TAGS = $(all-sources) | etags -
+define cmd_TAGS
+	rm -f $@; \
+	ETAGSF=`etags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
+	$(all-sources) | xargs etags $$ETAGSF -a
+endef
 
-# 	Exuberant ctags works better with -I
+TAGS: FORCE
+	$(call cmd,TAGS)
+
 
 quiet_cmd_tags = MAKE   $@
 define cmd_tags
@@ -1198,9 +1240,6 @@
 	$(all-sources) | xargs ctags $$CTAGSF -a
 endef
 
-TAGS: FORCE
-	$(call cmd,TAGS)
-
 tags: FORCE
 	$(call cmd,tags)
 
@@ -1268,82 +1307,11 @@
   include $(cmd_files)
 endif
 
-# Execute command and generate cmd file
-if_changed = $(if $(strip $? \
-		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
-			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
-	@set -e; \
-	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
-	$(cmd_$(1)); \
-	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
-
-
-# execute the command and also postprocess generated .d dependencies
-# file
-if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
-		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
-			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
-	$(Q)set -e; \
-	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
-	$(cmd_$(1)); \
-	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
-	rm -f $(depfile); \
-	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
-
-# Usage: $(call if_changed_rule,foo)
-# will check if $(cmd_foo) changed, or any of the prequisites changed,
-# and if so will execute $(rule_foo)
-
-if_changed_rule = $(if $(strip $? \
-		               $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\
-			       $(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\
-	               $(Q)$(rule_$(1)))
-
-# If quiet is set, only print short version of command
-
-cmd = @$(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
-
-# filechk is used to check if the content of a generated file is updated.
-# Sample usage:
-# define filechk_sample
-#	echo $KERNELRELEASE
-# endef
-# version.h : Makefile
-#	$(call filechk,sample)
-# The rule defined shall write to stdout the content of the new file.
-# The existing file will be compared with the new one.
-# - If no file exist it is created
-# - If the content differ the new file is used
-# - If they are equal no change, and no timestamp update
-
-define filechk
-	@set -e;				\
-	echo '  CHK     $@';			\
-	mkdir -p $(dir $@);			\
-	$(filechk_$(1)) < $< > $@.tmp;		\
-	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
-		rm -f $@.tmp;			\
-	else					\
-		echo '  UPD     $@';		\
-		mv -f $@.tmp $@;		\
-	fi
-endef
-
-# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=dir
-# Usage:
-# $(Q)$(MAKE) $(build)=dir
-build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
-
 # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
 # Usage:
 # $(Q)$(MAKE) $(clean)=dir
 clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
 
-#	$(call descend,<dir>,<target>)
-#	Recursively call a sub-make in <dir> with target <target>
-# Usage is deprecated, because make does not see this as an invocation of make.
-descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
-
 endif	# skip-makefile
 
 FORCE:
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index cfd0d3e..688a595 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -17,6 +17,12 @@
 
 #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
 
+/* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c
+   There is no easy way to link multiple scoop devices into one
+   single entity for the pxa2xx_pcmcia device */
+int scoop_num;
+struct scoop_pcmcia_dev *scoop_devs;
+
 struct  scoop_dev {
 	void  *base;
 	spinlock_t scoop_lock;
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 86b862f..06ea730 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -60,6 +60,15 @@
 	.io_out		= CORGI_SCOOP_IO_OUT,
 };
 
+static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = {
+{
+	.dev        = &corgiscoop_device.dev,
+	.irq        = CORGI_IRQ_GPIO_CF_IRQ,
+	.cd_irq     = CORGI_IRQ_GPIO_CF_CD,
+	.cd_irq_str = "PCMCIA0 CD",
+},
+};
+
 struct platform_device corgiscoop_device = {
 	.name		= "sharp-scoop",
 	.id		= -1,
@@ -241,6 +250,9 @@
  	pxa_set_udc_info(&udc_info);
 	pxa_set_mci_info(&corgi_mci_platform_data);
 
+	scoop_num = 1;
+	scoop_devs = &corgi_pcmcia_scoop[0];
+
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 0e4f6fa..47cfb8b 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -62,6 +62,15 @@
 	.resource	= poodle_scoop_resources,
 };
 
+static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = {
+{
+	.dev        = &poodle_scoop_device.dev,
+	.irq        = POODLE_IRQ_GPIO_CF_IRQ,
+	.cd_irq     = POODLE_IRQ_GPIO_CF_CD,
+	.cd_irq_str = "PCMCIA0 CD",
+},
+};
+
 
 /* LoCoMo device */
 static struct resource locomo_resources[] = {
@@ -147,6 +156,9 @@
 
 	set_pxa_fb_info(&poodle_fb_info);
 
+	scoop_num = 1;
+	scoop_devs = &poodle_pcmcia_scoop[0];
+
 	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	if (ret) {
 		printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 79044d9..66bf5bb 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -110,34 +110,24 @@
 	s3c24xx_init_irq();
 }
 
-
-static int n30_usbstart_thread(void *unused)
-{
-	/* Turn off suspend on both USB ports, and switch the
-	 * selectable USB port to USB device mode. */
-	writel(readl(S3C2410_MISCCR) & ~0x00003008, S3C2410_MISCCR);
-
-	/* Turn off the D+ pull up for 3 seconds so that the USB host
-	 * at the other end will do a rescan of the USB bus.  */
-	s3c2410_gpio_setpin(S3C2410_GPB3, 0);
-
-	msleep_interruptible(3*HZ);
-
-	s3c2410_gpio_setpin(S3C2410_GPB3, 1);
-
-	return 0;
-}
-
+/* GPB3 is the line that controls the pull-up for the USB D+ line */
 
 void __init n30_init(void)
 {
 	s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
 
-	kthread_run(n30_usbstart_thread, NULL, "n30_usbstart");
+	/* Turn off suspend on both USB ports, and switch the
+	 * selectable USB port to USB device mode. */
+
+	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+			      S3C2410_MISCCR_USBSUSPND0 |
+			      S3C2410_MISCCR_USBSUSPND1, 0x0);
 }
 
 MACHINE_START(N30, "Acer-N30")
-	/* Maintainer: Christer Weinigel <christer@weinigel.se>, Ben Dooks <ben-linux@fluff.org> */
+	/* Maintainer: Christer Weinigel <christer@weinigel.se>,
+				Ben Dooks <ben-linux@fluff.org>
+	*/
 	.phys_ram	= S3C2410_SDRAM_PA,
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index 97022ed..7ce5e55 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -114,7 +114,7 @@
 prepare: include/asm-$(ARCH)/asm-offsets.h
 
 archclean:
-	$(call descend arch/$(ARCH)/boot, subdirclean)
+	$(Q)$(MAKE) $(clean)=arch/m68knommu/boot
 
 include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \
 				   include/asm include/linux/version.h \
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index d27b825..b0fdaee 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -673,7 +673,7 @@
 
 ifdef CONFIG_LASAT
 rom.bin rom.sw: vmlinux
-	$(call descend,arch/mips/lasat/image,$@)
+	$(Q)$(MAKE) $(build)=arch/mips/lasat/image $@
 endif
 
 #
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 17846f4..73ec6ae 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -178,8 +178,6 @@
 
 endmenu
 
-source "drivers/firmware/Kconfig"
-
 source "mm/Kconfig"
 
 config GENERIC_ISA_DMA
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index ab53832..17e9669 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -156,7 +156,9 @@
 		device_release_driver(dev);
 		err = count;
 	}
-	return err;
+	if (err)
+		return err;
+	return count;
 }
 static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
 
@@ -358,7 +360,7 @@
 	if (bus) {
 		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
 		device_attach(dev);
-		klist_add_tail(&bus->klist_devices, &dev->knode_bus);
+		klist_add_tail(&dev->knode_bus, &bus->klist_devices);
 		error = device_add_attrs(bus, dev);
 		if (!error) {
 			sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
@@ -446,7 +448,7 @@
 		}
 
 		driver_attach(drv);
-		klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
+		klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
 		module_add_driver(drv->owner, drv);
 
 		driver_add_attrs(bus, drv);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 0154a16..d164c32 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -299,10 +299,8 @@
 
 	pr_debug("device class '%s': release.\n", cd->class_id);
 
-	if (cd->devt_attr) {
-		kfree(cd->devt_attr);
-		cd->devt_attr = NULL;
-	}
+	kfree(cd->devt_attr);
+	cd->devt_attr = NULL;
 
 	if (cls->release)
 		cls->release(cd);
@@ -452,10 +450,29 @@
 	INIT_LIST_HEAD(&class_dev->node);
 }
 
+static char *make_class_name(struct class_device *class_dev)
+{
+	char *name;
+	int size;
+
+	size = strlen(class_dev->class->name) +
+		strlen(kobject_name(&class_dev->kobj)) + 2;
+
+	name = kmalloc(size, GFP_KERNEL);
+	if (!name)
+		return ERR_PTR(-ENOMEM);
+
+	strcpy(name, class_dev->class->name);
+	strcat(name, ":");
+	strcat(name, kobject_name(&class_dev->kobj));
+	return name;
+}
+
 int class_device_add(struct class_device *class_dev)
 {
 	struct class * parent = NULL;
 	struct class_interface * class_intf;
+	char *class_name = NULL;
 	int error;
 
 	class_dev = class_device_get(class_dev);
@@ -500,9 +517,13 @@
 	}
 
 	class_device_add_attrs(class_dev);
-	if (class_dev->dev)
+	if (class_dev->dev) {
+		class_name = make_class_name(class_dev);
 		sysfs_create_link(&class_dev->kobj,
 				  &class_dev->dev->kobj, "device");
+		sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+				  class_name);
+	}
 
 	/* notify any interfaces this device is now here */
 	if (parent) {
@@ -519,6 +540,7 @@
 	if (error && parent)
 		class_put(parent);
 	class_device_put(class_dev);
+	kfree(class_name);
 	return error;
 }
 
@@ -584,6 +606,7 @@
 {
 	struct class * parent = class_dev->class;
 	struct class_interface * class_intf;
+	char *class_name = NULL;
 
 	if (parent) {
 		down(&parent->sem);
@@ -594,8 +617,11 @@
 		up(&parent->sem);
 	}
 
-	if (class_dev->dev)
+	if (class_dev->dev) {
+		class_name = make_class_name(class_dev);
 		sysfs_remove_link(&class_dev->kobj, "device");
+		sysfs_remove_link(&class_dev->dev->kobj, class_name);
+	}
 	if (class_dev->devt_attr)
 		class_device_remove_file(class_dev, class_dev->devt_attr);
 	class_device_remove_attrs(class_dev);
@@ -605,6 +631,7 @@
 
 	if (parent)
 		class_put(parent);
+	kfree(class_name);
 }
 
 void class_device_unregister(struct class_device *class_dev)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index efe03a0..c8a33df 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -249,7 +249,7 @@
 	if ((error = bus_add_device(dev)))
 		goto BusError;
 	if (parent)
-		klist_add_tail(&parent->klist_children, &dev->knode_parent);
+		klist_add_tail(&dev->knode_parent, &parent->klist_children);
 
 	/* notify platform of device entry */
 	if (platform_notify)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 16323f9..d5bbce3 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -42,7 +42,7 @@
 {
 	pr_debug("bound device '%s' to driver '%s'\n",
 		 dev->bus_id, dev->driver->name);
-	klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
+	klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
 	sysfs_create_link(&dev->driver->kobj, &dev->kobj,
 			  kobject_name(&dev->kobj));
 	sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 214b964..3431eb6 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -288,6 +288,27 @@
 	up(&sysdev_drivers_lock);
 }
 
+static void __sysdev_resume(struct sys_device *dev)
+{
+	struct sysdev_class *cls = dev->cls;
+	struct sysdev_driver *drv;
+
+	/* First, call the class-specific one */
+	if (cls->resume)
+		cls->resume(dev);
+
+	/* Call auxillary drivers next. */
+	list_for_each_entry(drv, &cls->drivers, entry) {
+		if (drv->resume)
+			drv->resume(dev);
+	}
+
+	/* Call global drivers. */
+	list_for_each_entry(drv, &sysdev_drivers, entry) {
+		if (drv->resume)
+			drv->resume(dev);
+	}
+}
 
 /**
  *	sysdev_suspend - Suspend all system devices.
@@ -305,38 +326,93 @@
 int sysdev_suspend(pm_message_t state)
 {
 	struct sysdev_class * cls;
+	struct sys_device *sysdev, *err_dev;
+	struct sysdev_driver *drv, *err_drv;
+	int ret;
 
 	pr_debug("Suspending System Devices\n");
 
 	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
 				    kset.kobj.entry) {
-		struct sys_device * sysdev;
 
 		pr_debug("Suspending type '%s':\n",
 			 kobject_name(&cls->kset.kobj));
 
 		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-			struct sysdev_driver * drv;
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* Call global drivers first. */
 			list_for_each_entry(drv, &sysdev_drivers, entry) {
-				if (drv->suspend)
-					drv->suspend(sysdev, state);
+				if (drv->suspend) {
+					ret = drv->suspend(sysdev, state);
+					if (ret)
+						goto gbl_driver;
+				}
 			}
 
 			/* Call auxillary drivers next. */
 			list_for_each_entry(drv, &cls->drivers, entry) {
-				if (drv->suspend)
-					drv->suspend(sysdev, state);
+				if (drv->suspend) {
+					ret = drv->suspend(sysdev, state);
+					if (ret)
+						goto aux_driver;
+				}
 			}
 
 			/* Now call the generic one */
-			if (cls->suspend)
-				cls->suspend(sysdev, state);
+			if (cls->suspend) {
+				ret = cls->suspend(sysdev, state);
+				if (ret)
+					goto cls_driver;
+			}
 		}
 	}
 	return 0;
+	/* resume current sysdev */
+cls_driver:
+	drv = NULL;
+	printk(KERN_ERR "Class suspend failed for %s\n",
+		kobject_name(&sysdev->kobj));
+
+aux_driver:
+	if (drv)
+		printk(KERN_ERR "Class driver suspend failed for %s\n",
+				kobject_name(&sysdev->kobj));
+	list_for_each_entry(err_drv, &cls->drivers, entry) {
+		if (err_drv == drv)
+			break;
+		if (err_drv->resume)
+			err_drv->resume(sysdev);
+	}
+	drv = NULL;
+
+gbl_driver:
+	if (drv)
+		printk(KERN_ERR "sysdev driver suspend failed for %s\n",
+				kobject_name(&sysdev->kobj));
+	list_for_each_entry(err_drv, &sysdev_drivers, entry) {
+		if (err_drv == drv)
+			break;
+		if (err_drv->resume)
+			err_drv->resume(sysdev);
+	}
+	/* resume other sysdevs in current class */
+	list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+		if (err_dev == sysdev)
+			break;
+		pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+		__sysdev_resume(err_dev);
+	}
+
+	/* resume other classes */
+	list_for_each_entry_continue(cls, &system_subsys.kset.list,
+					kset.kobj.entry) {
+		list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+			pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+			__sysdev_resume(err_dev);
+		}
+	}
+	return ret;
 }
 
 
@@ -362,25 +438,9 @@
 			 kobject_name(&cls->kset.kobj));
 
 		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
-			struct sysdev_driver * drv;
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
-			/* First, call the class-specific one */
-			if (cls->resume)
-				cls->resume(sysdev);
-
-			/* Call auxillary drivers next. */
-			list_for_each_entry(drv, &cls->drivers, entry) {
-				if (drv->resume)
-					drv->resume(sysdev);
-			}
-
-			/* Call global drivers. */
-			list_for_each_entry(drv, &sysdev_drivers, entry) {
-				if (drv->resume)
-					drv->resume(sysdev);
-			}
-
+			__sysdev_resume(sysdev);
 		}
 	}
 	return 0;
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 879036d..6b73636 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -408,48 +408,6 @@
 	  "real" root file system, etc. See <file:Documentation/initrd.txt>
 	  for details.
 
-config INITRAMFS_SOURCE
-	string "Initramfs source file(s)"
-	default ""
-	help
-	  This can be either a single cpio archive with a .cpio suffix or a
-	  space-separated list of directories and files for building the
-	  initramfs image.  A cpio archive should contain a filesystem archive
-	  to be used as an initramfs image.  Directories should contain a
-	  filesystem layout to be included in the initramfs image.  Files
-	  should contain entries according to the format described by the
-	  "usr/gen_init_cpio" program in the kernel tree.
-
-	  When multiple directories and files are specified then the
-	  initramfs image will be the aggregate of all of them.
-
-	  See <file:Documentation/early-userspace/README for more details.
-
-	  If you are not sure, leave it blank.
-
-config INITRAMFS_ROOT_UID
-	int "User ID to map to 0 (user root)"
-	depends on INITRAMFS_SOURCE!=""
-	default "0"
-	help
-	  This setting is only meaningful if the INITRAMFS_SOURCE is
-	  contains a directory.  Setting this user ID (UID) to something
-	  other than "0" will cause all files owned by that UID to be
-	  owned by user root in the initial ramdisk image.
-
-	  If you are not sure, leave it set to "0".
-
-config INITRAMFS_ROOT_GID
-	int "Group ID to map to 0 (group root)"
-	depends on INITRAMFS_SOURCE!=""
-	default "0"
-	help
-	  This setting is only meaningful if the INITRAMFS_SOURCE is
-	  contains a directory.  Setting this group ID (GID) to something
-	  other than "0" will cause all files owned by that GID to be
-	  owned by group root in the initial ramdisk image.
-
-	  If you are not sure, leave it set to "0".
 
 #XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64
 #for instance.
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index f0c1084..888dad5 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -493,6 +493,8 @@
 
 static sector_t floppy_sizes[256];
 
+static char floppy_device_name[] = "floppy";
+
 /*
  * The driver is trying to determine the correct media format
  * while probing is set. rw_interrupt() clears it after a
@@ -4191,18 +4193,24 @@
 
 static int have_no_fdc = -ENODEV;
 
+static ssize_t floppy_cmos_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *p;
+	int drive;
+
+	p = container_of(dev, struct platform_device,dev);
+	drive = p->id;
+	return sprintf(buf, "%X\n", UDP->cmos);
+}
+DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
+
 static void floppy_device_release(struct device *dev)
 {
 	complete(&device_release);
 }
 
-static struct platform_device floppy_device = {
-	.name		= "floppy",
-	.id		= 0,
-	.dev		= {
-			.release = floppy_device_release,
-			}
-};
+static struct platform_device floppy_device[N_DRIVE];
 
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
@@ -4370,20 +4378,26 @@
 		goto out_flush_work;
 	}
 
-	err = platform_device_register(&floppy_device);
-	if (err)
-		goto out_flush_work;
-
 	for (drive = 0; drive < N_DRIVE; drive++) {
 		if (!(allowed_drive_mask & (1 << drive)))
 			continue;
 		if (fdc_state[FDC(drive)].version == FDC_NONE)
 			continue;
+
+		floppy_device[drive].name = floppy_device_name;
+		floppy_device[drive].id = drive;
+		floppy_device[drive].dev.release = floppy_device_release;
+
+		err = platform_device_register(&floppy_device[drive]);
+		if (err)
+			goto out_flush_work;
+
+		device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
 		/* to be cleaned up... */
 		disks[drive]->private_data = (void *)(long)drive;
 		disks[drive]->queue = floppy_queue;
 		disks[drive]->flags |= GENHD_FL_REMOVABLE;
-		disks[drive]->driverfs_dev = &floppy_device.dev;
+		disks[drive]->driverfs_dev = &floppy_device[drive].dev;
 		add_disk(disks[drive]);
 	}
 
@@ -4603,10 +4617,11 @@
 		    fdc_state[FDC(drive)].version != FDC_NONE) {
 			del_gendisk(disks[drive]);
 			unregister_devfs_entries(drive);
+			device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+			platform_device_unregister(&floppy_device[drive]);
 		}
 		put_disk(disks[drive]);
 	}
-	platform_device_unregister(&floppy_device);
 	devfs_remove("floppy");
 
 	del_timer_sync(&fd_timeout);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index df5f2b0..a1de06d 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -175,7 +175,7 @@
 
 config MOXA_SMARTIO
 	tristate "Moxa SmartIO support"
-	depends on SERIAL_NONSTANDARD && (BROKEN || !SPARC32)
+	depends on SERIAL_NONSTANDARD
 	help
 	  Say Y here if you have a Moxa SmartIO multiport serial card.
 
@@ -735,7 +735,7 @@
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32
+	depends on RTC!=y && !IA64 && !ARM && !PPC64 && !M32R && !SPARC32 && !SPARC64
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index f022f09..d0ef1ae 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -63,7 +63,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/segment.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index cd4fe8b..63fff7c 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -938,10 +938,9 @@
 
 	/*
 	 * XXX Interrupt pin #7 in Espresso is shared between RTC and
-	 * PCI Slot 2 INTA# (and some INTx# in Slot 1). SA_INTERRUPT here
-	 * is asking for trouble with add-on boards. Change to SA_SHIRQ.
+	 * PCI Slot 2 INTA# (and some INTx# in Slot 1).
 	 */
-	if (request_irq(rtc_irq, rtc_interrupt, SA_INTERRUPT, "rtc", (void *)&rtc_port)) {
+	if (request_irq(rtc_irq, rtc_interrupt, SA_SHIRQ, "rtc", (void *)&rtc_port)) {
 		/*
 		 * Standard way for sparc to print irq's is to use
 		 * __irq_itoa(). I think for EBus it's ok to use %d.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 140d5f8..138dc50 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -12,12 +12,20 @@
 	  of a system. Most modern motherboards include such a device. It
 	  can include temperature sensors, voltage sensors, fan speed
 	  sensors and various additional features such as the ability to
-	  control the speed of the fans.
+	  control the speed of the fans.  If you want this support you
+	  should say Y here and also to the specific driver(s) for your
+	  sensors chip(s) below.
+
+	  This support can also be built as a module.  If so, the module
+	  will be called hwmon.
+
+config HWMON_VID
+	tristate
+	default n
 
 config SENSORS_ADM1021
 	tristate "Analog Devices ADM1021 and compatibles"
 	depends on HWMON && I2C
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Analog Devices ADM1021
 	  and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
@@ -30,7 +38,7 @@
 config SENSORS_ADM1025
 	tristate "Analog Devices ADM1025 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for Analog Devices ADM1025
 	  and Philips NE1619 sensor chips.
@@ -41,7 +49,7 @@
 config SENSORS_ADM1026
 	tristate "Analog Devices ADM1026 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for Analog Devices ADM1026
 	  sensor chip.
@@ -52,7 +60,6 @@
 config SENSORS_ADM1031
 	tristate "Analog Devices ADM1031 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Analog Devices ADM1031
 	  and ADM1030 sensor chips.
@@ -63,7 +70,7 @@
 config SENSORS_ADM9240
 	tristate "Analog Devices ADM9240 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for Analog Devices ADM9240,
 	  Dallas DS1780, National Semiconductor LM81 sensor chips.
@@ -74,7 +81,7 @@
 config SENSORS_ASB100
 	tristate "Asus ASB100 Bach"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for the ASB100 Bach sensor
 	  chip found on some Asus mainboards.
@@ -85,7 +92,7 @@
 config SENSORS_ATXP1
 	tristate "Attansic ATXP1 VID controller"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for the Attansic ATXP1 VID
 	  controller.
@@ -99,7 +106,6 @@
 config SENSORS_DS1621
 	tristate "Dallas Semiconductor DS1621 and DS1625"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Dallas Semiconductor
 	  DS1621 and DS1625 sensor chips.
@@ -110,7 +116,6 @@
 config SENSORS_FSCHER
 	tristate "FSC Hermes"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Fujitsu Siemens
 	  Computers Hermes sensor chips.
@@ -121,7 +126,6 @@
 config SENSORS_FSCPOS
 	tristate "FSC Poseidon"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Fujitsu Siemens
 	  Computers Poseidon sensor chips.
@@ -132,7 +136,6 @@
 config SENSORS_GL518SM
 	tristate "Genesys Logic GL518SM"
 	depends on HWMON && I2C
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Genesys Logic GL518SM
 	  sensor chips.
@@ -143,7 +146,7 @@
 config SENSORS_GL520SM
 	tristate "Genesys Logic GL520SM"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for Genesys Logic GL520SM
 	  sensor chips.
@@ -154,7 +157,8 @@
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
 	depends on HWMON && I2C
-	select I2C_SENSOR
+	select I2C_ISA
+	select HWMON_VID
 	help
 	  If you say yes here you get support for ITE IT87xx sensor chips
 	  and clones: SiS960.
@@ -165,7 +169,6 @@
 config SENSORS_LM63
 	tristate "National Semiconductor LM63"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for the National Semiconductor
 	  LM63 remote diode digital temperature sensor with integrated fan
@@ -178,7 +181,6 @@
 config SENSORS_LM75
 	tristate "National Semiconductor LM75 and compatibles"
 	depends on HWMON && I2C
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor LM75
 	  sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
@@ -194,7 +196,6 @@
 config SENSORS_LM77
 	tristate "National Semiconductor LM77"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor LM77
 	  sensor chips.
@@ -205,7 +206,8 @@
 config SENSORS_LM78
 	tristate "National Semiconductor LM78 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select I2C_ISA
+	select HWMON_VID
 	help
 	  If you say yes here you get support for National Semiconductor LM78,
 	  LM78-J and LM79.
@@ -216,7 +218,6 @@
 config SENSORS_LM80
 	tristate "National Semiconductor LM80"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor
 	  LM80 sensor chips.
@@ -227,7 +228,6 @@
 config SENSORS_LM83
 	tristate "National Semiconductor LM83"
 	depends on HWMON && I2C
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor
 	  LM83 sensor chips.
@@ -238,7 +238,7 @@
 config SENSORS_LM85
 	tristate "National Semiconductor LM85 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for National Semiconductor LM85
 	  sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
@@ -249,7 +249,7 @@
 config SENSORS_LM87
 	tristate "National Semiconductor LM87"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
+	select HWMON_VID
 	help
 	  If you say yes here you get support for National Semiconductor LM87
 	  sensor chips.
@@ -260,7 +260,6 @@
 config SENSORS_LM90
 	tristate "National Semiconductor LM90 and compatibles"
 	depends on HWMON && I2C
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor LM90,
 	  LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
@@ -275,7 +274,6 @@
 config SENSORS_LM92
 	tristate "National Semiconductor LM92 and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor LM92
 	  and Maxim MAX6635 sensor chips.
@@ -286,7 +284,6 @@
 config SENSORS_MAX1619
 	tristate "Maxim MAX1619 sensor chip"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for MAX1619 sensor chip.
 
@@ -296,8 +293,8 @@
 config SENSORS_PC87360
 	tristate "National Semiconductor PC87360 family"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	select I2C_ISA
+	select HWMON_VID
 	help
 	  If you say yes here you get access to the hardware monitoring
 	  functions of the National Semiconductor PC8736x Super-I/O chips.
@@ -311,7 +308,6 @@
 config SENSORS_SIS5595
 	tristate "Silicon Integrated Systems Corp. SiS5595"
 	depends on HWMON && I2C && PCI && EXPERIMENTAL
-	select I2C_SENSOR
 	select I2C_ISA
 	help
 	  If you say yes here you get support for the integrated sensors in
@@ -323,7 +319,6 @@
 config SENSORS_SMSC47M1
 	tristate "SMSC LPC47M10x and compatibles"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	select I2C_ISA
 	help
 	  If you say yes here you get support for the integrated fan
@@ -336,7 +331,6 @@
 config SENSORS_SMSC47B397
 	tristate "SMSC LPC47B397-NC"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	select I2C_ISA
 	help
 	  If you say yes here you get support for the SMSC LPC47B397-NC
@@ -348,7 +342,6 @@
 config SENSORS_VIA686A
 	tristate "VIA686A"
 	depends on HWMON && I2C && PCI
-	select I2C_SENSOR
 	select I2C_ISA
 	help
 	  If you say yes here you get support for the integrated sensors in
@@ -360,7 +353,8 @@
 config SENSORS_W83781D
 	tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
 	depends on HWMON && I2C
-	select I2C_SENSOR
+	select I2C_ISA
+	select HWMON_VID
 	help
 	  If you say yes here you get support for the Winbond W8378x series
 	  of sensor chips: the W83781D, W83782D, W83783S and W83627HF,
@@ -369,10 +363,18 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83781d.
 
+config SENSORS_W83792D
+	tristate "Winbond W83792D"
+	depends on HWMON && I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Winbond W83792D chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called w83792d.
+
 config SENSORS_W83L785TS
 	tristate "Winbond W83L785TS-S"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for the Winbond W83L785TS-S
 	  sensor chip, which is used on the Asus A7N8X, among other
@@ -384,8 +386,8 @@
 config SENSORS_W83627HF
 	tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	select I2C_ISA
+	select HWMON_VID
 	help
 	  If you say yes here you get support for the Winbond W836X7 series
 	  of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
@@ -396,7 +398,6 @@
 config SENSORS_W83627EHF
 	tristate "Winbond W83627EHF"
 	depends on HWMON && I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	select I2C_ISA
 	help
 	  If you say yes here you get preliminary support for the hardware
@@ -404,6 +405,9 @@
 	  Only fan and temperature inputs are supported at the moment, while
 	  the chip does much more than that.
 
+	  This driver also supports the W83627EHG, which is the lead-free
+	  version of the W83627EHF.
+
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83627ehf.
 
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 2781403..381f1bf 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -2,9 +2,13 @@
 # Makefile for sensor chip drivers.
 #
 
+obj-$(CONFIG_HWMON)		+= hwmon.o
+obj-$(CONFIG_HWMON_VID)		+= hwmon-vid.o
+
 # asb100, then w83781d go first, as they can override other drivers' addresses.
 obj-$(CONFIG_SENSORS_ASB100)	+= asb100.o
 obj-$(CONFIG_SENSORS_W83627HF)	+= w83627hf.o
+obj-$(CONFIG_SENSORS_W83792D)	+= w83792d.o
 obj-$(CONFIG_SENSORS_W83781D)	+= w83781d.o
 
 obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index d2c774c..e928cdb 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -24,7 +24,8 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 
 /* Addresses to scan */
@@ -32,10 +33,9 @@
 					0x29, 0x2a, 0x2b,
 					0x4c, 0x4d, 0x4e, 
 					I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
+I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
 
 /* adm1021 constants specified below */
 
@@ -89,6 +89,7 @@
 /* Each client has this additional data */
 struct adm1021_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	enum chips type;
 
 	struct semaphore update_lock;
@@ -185,7 +186,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, adm1021_detect);
+	return i2c_probe(adapter, &addr_data, adm1021_detect);
 }
 
 static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -196,15 +197,6 @@
 	int err = 0;
 	const char *type_name = "";
 
-	/* Make sure we aren't probing the ISA bus!! This is just a safety check
-	   at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
-	if (i2c_is_isa_adapter(adapter)) {
-		dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
-		return 0;
-	}
-#endif
-
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto error0;
 
@@ -295,6 +287,12 @@
 		adm1021_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto error2;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_temp1_max);
 	device_create_file(&new_client->dev, &dev_attr_temp1_min);
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
@@ -305,6 +303,8 @@
 
 	return 0;
 
+error2:
+	i2c_detach_client(new_client);
 error1:
 	kfree(data);
 error0:
@@ -322,14 +322,15 @@
 
 static int adm1021_detach_client(struct i2c_client *client)
 {
+	struct adm1021_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index e452d0d..526b7ff 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -50,8 +50,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
@@ -60,13 +61,12 @@
  */
 
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_2(adm1025, ne1619);
+I2C_CLIENT_INSMOD_2(adm1025, ne1619);
 
 /*
  * The ADM1025 registers
@@ -132,6 +132,7 @@
 
 struct adm1025_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -312,7 +313,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, adm1025_detect);
+	return i2c_probe(adapter, &addr_data, adm1025_detect);
 }
 
 /*
@@ -416,6 +417,12 @@
 	adm1025_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in1_input);
 	device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -452,6 +459,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -464,7 +473,7 @@
 	struct adm1025_data *data = i2c_get_clientdata(client);
 	int i;
 
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 
 	/*
 	 * Set high limits
@@ -502,15 +511,15 @@
 
 static int adm1025_detach_client(struct i2c_client *client)
 {
+	struct adm1025_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index c8a7f47..6251581 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -28,16 +28,16 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(adm1026);
+I2C_CLIENT_INSMOD_1(adm1026);
 
 static int gpio_input[17]  = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
 				-1, -1, -1, -1, -1, -1, -1, -1 }; 
@@ -259,6 +259,7 @@
 
 struct adm1026_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	enum chips type;
 
@@ -319,13 +320,15 @@
 	if (!(adapter->class & I2C_CLASS_HWMON)) {
 		return 0;
 	}
-	return i2c_detect(adapter, &addr_data, adm1026_detect);
+	return i2c_probe(adapter, &addr_data, adm1026_detect);
 }
 
 int adm1026_detach_client(struct i2c_client *client)
 {
+	struct adm1026_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->class_dev);
 	i2c_detach_client(client);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 	return 0;
 }
 
@@ -1549,12 +1552,18 @@
 		goto exitfree;
 
 	/* Set the VRM version */
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 
 	/* Initialize the ADM1026 chip */
 	adm1026_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exitdetach;
+	}
+
 	device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
 	device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
 	device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
@@ -1690,6 +1699,8 @@
 	return 0;
 
 	/* Error out and cleanup code */
+exitdetach:
+	i2c_detach_client(new_client);
 exitfree:
 	kfree(data);
 exit:
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 9362509..58338ed 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -26,7 +26,8 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Following macros takes channel parameter starting from 0 to 2 */
 #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
@@ -59,16 +60,16 @@
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_2(adm1030, adm1031);
+I2C_CLIENT_INSMOD_2(adm1030, adm1031);
 
 typedef u8 auto_chan_table_t[8][2];
 
 /* Each client has this additional data */
 struct adm1031_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	int chip_type;
 	char valid;		/* !=0 if following fields are valid */
@@ -725,10 +726,10 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, adm1031_detect);
+	return i2c_probe(adapter, &addr_data, adm1031_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
@@ -788,6 +789,12 @@
 	adm1031_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_fan1_input);
 	device_create_file(&new_client->dev, &dev_attr_fan1_div);
 	device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -833,6 +840,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -841,11 +850,14 @@
 
 static int adm1031_detach_client(struct i2c_client *client)
 {
+	struct adm1031_data *data = i2c_get_clientdata(client);
 	int ret;
+
+	hwmon_device_unregister(data->class_dev);
 	if ((ret = i2c_detach_client(client)) != 0) {
 		return ret;
 	}
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index ce2a6eb..bc7faef 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -45,17 +45,16 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
 					I2C_CLIENT_END };
 
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
 /* Insmod parameters */
-SENSORS_INSMOD_3(adm9240, ds1780, lm81);
+I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81);
 
 /* ADM9240 registers */
 #define ADM9240_REG_MAN_ID		0x3e
@@ -150,6 +149,7 @@
 struct adm9240_data {
 	enum chips type;
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid;
 	unsigned long last_updated_measure;
@@ -582,6 +582,12 @@
 	adm9240_init_client(new_client);
 
 	/* populate sysfs filesystem */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in0_min);
 	device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -615,6 +621,9 @@
 	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 
 	return 0;
+
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -625,20 +634,20 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, adm9240_detect);
+	return i2c_probe(adapter, &addr_data, adm9240_detect);
 }
 
 static int adm9240_detach_client(struct i2c_client *client)
 {
+	struct adm9240_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-				"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
@@ -648,7 +657,7 @@
 	u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
 	u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
 
-	data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
+	data->vrm = vid_which_vrm(); /* need this to report vid as mV */
 
 	dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
 			data->vrm % 10);
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 70d996d..8e34855 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -39,8 +39,9 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include "lm75.h"
@@ -54,11 +55,8 @@
 /* I2C addresses to scan */
 static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
 
-/* ISA addresses to scan (none) */
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
 /* Insmod parameters */
-SENSORS_INSMOD_1(asb100);
+I2C_CLIENT_INSMOD_1(asb100);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
 	"{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -183,6 +181,7 @@
    dynamically allocated, at the same time the client itself is allocated. */
 struct asb100_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	enum chips type;
 
@@ -621,7 +620,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, asb100_detect);
+	return i2c_probe(adapter, &addr_data, asb100_detect);
 }
 
 static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
@@ -714,14 +713,6 @@
 	struct i2c_client *new_client;
 	struct asb100_data *data;
 
-	/* asb100 is SMBus only */
-	if (i2c_is_isa_adapter(adapter)) {
-		pr_debug("asb100.o: detect failed, "
-				"cannot attach to legacy adapter!\n");
-		err = -ENODEV;
-		goto ERROR0;
-	}
-
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		pr_debug("asb100.o: detect failed, "
 				"smbus byte data not supported!\n");
@@ -821,6 +812,12 @@
 	data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
+	}
+
 	device_create_file_in(new_client, 0);
 	device_create_file_in(new_client, 1);
 	device_create_file_in(new_client, 2);
@@ -847,6 +844,11 @@
 
 	return 0;
 
+ERROR3:
+	i2c_detach_client(data->lm75[1]);
+	i2c_detach_client(data->lm75[0]);
+	kfree(data->lm75[1]);
+	kfree(data->lm75[0]);
 ERROR2:
 	i2c_detach_client(new_client);
 ERROR1:
@@ -857,21 +859,23 @@
 
 static int asb100_detach_client(struct i2c_client *client)
 {
+	struct asb100_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "client deregistration failed; "
-			"client not detached.\n");
-		return err;
-	}
+	/* main client */
+	if (data)
+		hwmon_device_unregister(data->class_dev);
 
-	if (i2c_get_clientdata(client)==NULL) {
-		/* subclients */
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	/* main client */
+	if (data)
+		kfree(data);
+
+	/* subclient */
+	else
 		kfree(client);
-	} else {
-		/* main client */
-		kfree(i2c_get_clientdata(client));
-	}
 
 	return 0;
 }
@@ -969,7 +973,7 @@
 
 	vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
 	vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 	vid = vid_from_reg(vid, data->vrm);
 
 	/* Start monitoring */
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index fca3fc1..deb4d34 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -23,8 +23,9 @@
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
@@ -40,9 +41,8 @@
 #define ATXP1_GPIO1MASK	0x0f
 
 static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
-SENSORS_INSMOD_1(atxp1);
+I2C_CLIENT_INSMOD_1(atxp1);
 
 static int atxp1_attach_adapter(struct i2c_adapter * adapter);
 static int atxp1_detach_client(struct i2c_client * client);
@@ -59,6 +59,7 @@
 
 struct atxp1_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	unsigned long last_updated;
 	u8 valid;
@@ -252,7 +253,7 @@
 
 static int atxp1_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, &atxp1_detect);
+	return i2c_probe(adapter, &addr_data, &atxp1_detect);
 };
 
 static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -295,7 +296,7 @@
 	}
 
 	/* Get VRM */
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 
 	if ((data->vrm != 90) && (data->vrm != 91)) {
 		dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
@@ -317,6 +318,12 @@
 		goto exit_free;
 	}
 
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_gpio1);
 	device_create_file(&new_client->dev, &dev_attr_gpio2);
 	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
@@ -326,6 +333,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -334,14 +343,17 @@
 
 static int atxp1_detach_client(struct i2c_client * client)
 {
+	struct atxp1_data * data = i2c_get_clientdata(client);
 	int err;
 
+	hwmon_device_unregister(data->class_dev);
+
 	err = i2c_detach_client(client);
 
 	if (err)
 		dev_err(&client->dev, "Failed to detach client.\n");
 	else
-		kfree(i2c_get_clientdata(client));
+		kfree(data);
 
 	return err;
 };
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 5360d58..b0199e0 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -26,16 +26,16 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include "lm75.h"
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
 					0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(ds1621);
+I2C_CLIENT_INSMOD_1(ds1621);
 static int polarity = -1;
 module_param(polarity, int, 0);
 MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
@@ -71,6 +71,7 @@
 /* Each client has this additional data */
 struct ds1621_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -179,10 +180,10 @@
 
 static int ds1621_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, ds1621_detect);
+	return i2c_probe(adapter, &addr_data, ds1621_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int ds1621_detect(struct i2c_adapter *adapter, int address,
                   int kind)
 {
@@ -250,6 +251,12 @@
 	ds1621_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
 	device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -259,6 +266,8 @@
 
 /* OK, this is not exactly good programming practice, usually. But it is
    very code-efficient in this case. */
+      exit_detach:
+	i2c_detach_client(new_client);
       exit_free:
 	kfree(data);
       exit:
@@ -267,15 +276,15 @@
 
 static int ds1621_detach_client(struct i2c_client *client)
 {
+	struct ds1621_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 
 	return 0;
 }
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index da41174..eef6061 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -31,20 +31,20 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 
 static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(fscher);
+I2C_CLIENT_INSMOD_1(fscher);
 
 /*
  * The FSCHER registers
@@ -132,6 +132,7 @@
 
 struct fscher_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -287,7 +288,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, fscher_detect);
+	return i2c_probe(adapter, &addr_data, fscher_detect);
 }
 
 static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -341,6 +342,12 @@
 	fscher_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file_revision(new_client);
 	device_create_file_alarms(new_client);
 	device_create_file_control(new_client);
@@ -360,6 +367,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -368,15 +377,15 @@
 
 static int fscher_detach_client(struct i2c_client *client)
 {
+	struct fscher_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 301ae98..5fc77a5f 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -34,19 +34,19 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/init.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
-SENSORS_INSMOD_1(fscpos);
+I2C_CLIENT_INSMOD_1(fscpos);
 
 /*
  * The FSCPOS registers
@@ -113,6 +113,7 @@
  */
 struct fscpos_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; 		/* 0 until following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -434,7 +435,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, fscpos_detect);
+	return i2c_probe(adapter, &addr_data, fscpos_detect);
 }
 
 int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -496,6 +497,12 @@
 	dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_event);
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in1_input);
@@ -526,6 +533,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -534,14 +543,14 @@
 
 static int fscpos_detach_client(struct i2c_client *client)
 {
+	struct fscpos_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, client"
-							" not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 6bedf72..256b932 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -41,14 +41,14 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80);
+I2C_CLIENT_INSMOD_2(gl518sm_r00, gl518sm_r80);
 
 /* Many GL518 constants specified below */
 
@@ -117,6 +117,7 @@
 /* Each client has this additional data */
 struct gl518_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	enum chips type;
 
 	struct semaphore update_lock;
@@ -346,7 +347,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, gl518_detect);
+	return i2c_probe(adapter, &addr_data, gl518_detect);
 }
 
 static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -419,6 +420,12 @@
 	gl518_init_client((struct i2c_client *) new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in1_input);
 	device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -450,6 +457,8 @@
 /* OK, this is not exactly good programming practice, usually. But it is
    very code-efficient in this case. */
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -477,16 +486,15 @@
 
 static int gl518_detach_client(struct i2c_client *client)
 {
+	struct gl518_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
-	kfree(i2c_get_clientdata(client));
-
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index 80ae8d3..12fd757 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -26,8 +26,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Type of the extra sensor */
 static unsigned short extra_sensor_type;
@@ -36,10 +37,9 @@
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(gl520sm);
+I2C_CLIENT_INSMOD_1(gl520sm);
 
 /* Many GL520 constants specified below 
 One of the inputs can be configured as either temp or voltage.
@@ -120,6 +120,7 @@
 /* Client data */
 struct gl520_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid;		/* zero until the following fields are valid */
 	unsigned long last_updated;	/* in jiffies */
@@ -518,7 +519,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, gl520_detect);
+	return i2c_probe(adapter, &addr_data, gl520_detect);
 }
 
 static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -571,6 +572,12 @@
 	gl520_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file_vid(new_client, 0);
 
 	device_create_file_in(new_client, 0);
@@ -592,6 +599,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -608,7 +617,7 @@
 	conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
 
 	data->alarm_mask = 0xff;
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 
 	if (extra_sensor_type == 1)
 		conf &= ~0x10;
@@ -639,15 +648,15 @@
 
 static int gl520_detach_client(struct i2c_client *client)
 {
+	struct gl520_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
new file mode 100644
index 0000000..312769a
--- /dev/null
+++ b/drivers/hwmon/hwmon-vid.c
@@ -0,0 +1,189 @@
+/*
+    hwmon-vid.c - VID/VRM/VRD voltage conversions
+
+    Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+
+    Partly imported from i2c-vid.h of the lm_sensors project
+    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+    With assistance from Trent Piepho <xyzzy@speakeasy.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hwmon-vid.h>
+
+/*
+    Common code for decoding VID pins.
+
+    References:
+
+    For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
+    available at http://developer.intel.com/.
+
+    For VRD 10.0 and up, "VRD x.y Design Guide",
+    available at http://developer.intel.com/.
+
+    AMD Opteron processors don't follow the Intel specifications.
+    I'm going to "make up" 2.4 as the spec number for the Opterons.
+    No good reason just a mnemonic for the 24x Opteron processor
+    series.
+
+    Opteron VID encoding is:
+       00000  =  1.550 V
+       00001  =  1.525 V
+        . . . .
+       11110  =  0.800 V
+       11111  =  0.000 V (off)
+*/
+
+/* vrm is the VRM/VRD document version multiplied by 10.
+   val is the 4-, 5- or 6-bit VID code.
+   Returned value is in mV to avoid floating point in the kernel. */
+int vid_from_reg(int val, int vrm)
+{
+	int vid;
+
+	switch(vrm) {
+
+	case  0:
+		return 0;
+
+	case 100:               /* VRD 10.0 */
+		if((val & 0x1f) == 0x1f)
+			return 0;
+		if((val & 0x1f) <= 0x09 || val == 0x0a)
+			vid = 10875 - (val & 0x1f) * 250;
+		else
+			vid = 18625 - (val & 0x1f) * 250;
+		if(val & 0x20)
+			vid -= 125;
+		vid /= 10;      /* only return 3 dec. places for now */
+		return vid;
+
+	case 24:                /* Opteron processor */
+		return(val == 0x1f ? 0 : 1550 - val * 25);
+
+	case 91:		/* VRM 9.1 */
+	case 90:		/* VRM 9.0 */
+		return(val == 0x1f ? 0 :
+		                       1850 - val * 25);
+
+	case 85:		/* VRM 8.5 */
+		return((val & 0x10  ? 25 : 0) +
+		       ((val & 0x0f) > 0x04 ? 2050 : 1250) -
+		       ((val & 0x0f) * 50));
+
+	case 84:		/* VRM 8.4 */
+		val &= 0x0f;
+				/* fall through */
+	default:		/* VRM 8.2 */
+		return(val == 0x1f ? 0 :
+		       val & 0x10  ? 5100 - (val) * 100 :
+		                     2050 - (val) * 50);
+	}
+}
+
+
+/*
+    After this point is the code to automatically determine which
+    VRM/VRD specification should be used depending on the CPU.
+*/
+
+struct vrm_model {
+	u8 vendor;
+	u8 eff_family;
+	u8 eff_model;
+	int vrm_type;
+};
+
+#define ANY 0xFF
+
+#ifdef CONFIG_X86
+
+static struct vrm_model vrm_models[] = {
+	{X86_VENDOR_AMD, 0x6, ANY, 90},		/* Athlon Duron etc */
+	{X86_VENDOR_AMD, 0xF, ANY, 24},		/* Athlon 64, Opteron */
+	{X86_VENDOR_INTEL, 0x6, 0x9, 85},	/* 0.13um too */
+	{X86_VENDOR_INTEL, 0x6, 0xB, 85},	/* Tualatin */
+	{X86_VENDOR_INTEL, 0x6, ANY, 82},	/* any P6 */
+	{X86_VENDOR_INTEL, 0x7, ANY, 0},	/* Itanium */
+	{X86_VENDOR_INTEL, 0xF, 0x0, 90},	/* P4 */
+	{X86_VENDOR_INTEL, 0xF, 0x1, 90},	/* P4 Willamette */
+	{X86_VENDOR_INTEL, 0xF, 0x2, 90},	/* P4 Northwood */
+	{X86_VENDOR_INTEL, 0xF, 0x3, 100},	/* P4 Prescott */
+	{X86_VENDOR_INTEL, 0xF, 0x4, 100},	/* P4 Prescott */
+	{X86_VENDOR_INTEL, 0x10,ANY, 0},	/* Itanium 2 */
+	{X86_VENDOR_UNKNOWN, ANY, ANY, 0}	/* stop here */
+};
+
+static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+{
+	int i = 0;
+
+	while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
+		if (vrm_models[i].vendor==vendor)
+			if ((vrm_models[i].eff_family==eff_family)
+			 && ((vrm_models[i].eff_model==eff_model) ||
+			     (vrm_models[i].eff_model==ANY)))
+				return vrm_models[i].vrm_type;
+		i++;
+	}
+
+	return 0;
+}
+
+int vid_which_vrm(void)
+{
+	struct cpuinfo_x86 *c = cpu_data;
+	u32 eax;
+	u8 eff_family, eff_model;
+	int vrm_ret;
+
+	if (c->x86 < 6)		/* Any CPU with family lower than 6 */
+		return 0;	/* doesn't have VID and/or CPUID */
+
+	eax = cpuid_eax(1);
+	eff_family = ((eax & 0x00000F00)>>8);
+	eff_model  = ((eax & 0x000000F0)>>4);
+	if (eff_family == 0xF) {	/* use extended model & family */
+		eff_family += ((eax & 0x00F00000)>>20);
+		eff_model += ((eax & 0x000F0000)>>16)<<4;
+	}
+	vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+	if (vrm_ret == 0)
+		printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
+		       "x86 CPU\n");
+	return vrm_ret;
+}
+
+/* and now something completely different for the non-x86 world */
+#else
+int vid_which_vrm(void)
+{
+	printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
+	return 0;
+}
+#endif
+
+EXPORT_SYMBOL(vid_from_reg);
+EXPORT_SYMBOL(vid_which_vrm);
+
+MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+
+MODULE_DESCRIPTION("hwmon-vid driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
new file mode 100644
index 0000000..9b41c9b
--- /dev/null
+++ b/drivers/hwmon/hwmon.c
@@ -0,0 +1,98 @@
+/*
+    hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
+
+    This file defines the sysfs class "hwmon", for use by sensors drivers.
+
+    Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; version 2 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kdev_t.h>
+#include <linux/idr.h>
+#include <linux/hwmon.h>
+
+#define HWMON_ID_PREFIX "hwmon"
+#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
+
+static struct class *hwmon_class;
+
+static DEFINE_IDR(hwmon_idr);
+
+/**
+ * hwmon_device_register - register w/ hwmon sysfs class
+ * @dev: the device to register
+ *
+ * hwmon_device_unregister() must be called when the class device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new struct class device.
+ */
+struct class_device *hwmon_device_register(struct device *dev)
+{
+	struct class_device *cdev;
+	int id;
+
+	if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)
+		return ERR_PTR(-ENOMEM);
+
+	if (idr_get_new(&hwmon_idr, NULL, &id) < 0)
+		return ERR_PTR(-ENOMEM);
+
+	id = id & MAX_ID_MASK;
+	cdev = class_device_create(hwmon_class, MKDEV(0,0), dev,
+					HWMON_ID_FORMAT, id);
+
+	if (IS_ERR(cdev))
+		idr_remove(&hwmon_idr, id);
+
+	return cdev;
+}
+
+/**
+ * hwmon_device_unregister - removes the previously registered class device
+ *
+ * @cdev: the class device to destroy
+ */
+void hwmon_device_unregister(struct class_device *cdev)
+{
+	int id;
+
+	if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) {
+		class_device_unregister(cdev);
+		idr_remove(&hwmon_idr, id);
+	} else
+		dev_dbg(cdev->dev,
+			"hwmon_device_unregister() failed: bad class ID!\n");
+}
+
+static int __init hwmon_init(void)
+{
+	hwmon_class = class_create(THIS_MODULE, "hwmon");
+	if (IS_ERR(hwmon_class)) {
+		printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
+		return PTR_ERR(hwmon_class);
+	}
+	return 0;
+}
+
+static void __exit hwmon_exit(void)
+{
+	class_destroy(hwmon_class);
+}
+
+module_init(hwmon_init);
+module_exit(hwmon_exit);
+
+EXPORT_SYMBOL_GPL(hwmon_device_register);
+EXPORT_SYMBOL_GPL(hwmon_device_unregister);
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
+MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index db20c9e..53cc2b6 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -36,19 +36,21 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
 					0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-SENSORS_INSMOD_2(it87, it8712);
+I2C_CLIENT_INSMOD_2(it87, it8712);
 
 #define	REG	0x2e	/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
@@ -192,6 +194,7 @@
    allocated. */
 struct it87_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	enum chips type;
 
@@ -218,7 +221,7 @@
 
 
 static int it87_attach_adapter(struct i2c_adapter *adapter);
-static int it87_find(int *address);
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
 static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
 static int it87_detach_client(struct i2c_client *client);
 
@@ -239,6 +242,14 @@
 	.detach_client	= it87_detach_client,
 };
 
+static struct i2c_driver it87_isa_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "it87-isa",
+	.attach_adapter	= it87_isa_attach_adapter,
+	.detach_client	= it87_detach_client,
+};
+
+
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
@@ -686,11 +697,16 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, it87_detect);
+	return i2c_probe(adapter, &addr_data, it87_detect);
 }
 
-/* SuperIO detection - will change normal_isa[0] if a chip is found */
-static int it87_find(int *address)
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+	return it87_detect(adapter, isa_address, -1);
+}
+
+/* SuperIO detection - will change isa_address if a chip is found */
+static int __init it87_find(int *address)
 {
 	int err = -ENODEV;
 
@@ -721,7 +737,7 @@
 	return err;
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i;
@@ -738,7 +754,7 @@
 
 	/* Reserve the ISA region */
 	if (is_isa)
-		if (!request_region(address, IT87_EXTENT, it87_driver.name))
+		if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
 			goto ERROR0;
 
 	/* Probe whether there is anything available on this address. Already
@@ -784,7 +800,7 @@
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
-	new_client->driver = &it87_driver;
+	new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
 	new_client->flags = 0;
 
 	/* Now, we do the remaining detection. */
@@ -840,6 +856,12 @@
 	it87_init_client(new_client, data);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
+	}
+
 	device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
 	device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
 	device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
@@ -897,13 +919,15 @@
 	}
 
 	if (data->type == it8712) {
-		data->vrm = i2c_which_vrm();
+		data->vrm = vid_which_vrm();
 		device_create_file_vrm(new_client);
 		device_create_file_vid(new_client);
 	}
 
 	return 0;
 
+ERROR3:
+	i2c_detach_client(new_client);
 ERROR2:
 	kfree(data);
 ERROR1:
@@ -915,17 +939,17 @@
 
 static int it87_detach_client(struct i2c_client *client)
 {
+	struct it87_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-			"Client deregistration failed, client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	if(i2c_is_isa_client(client))
 		release_region(client->addr, IT87_EXTENT);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
@@ -1158,16 +1182,28 @@
 
 static int __init sm_it87_init(void)
 {
-	int addr;
+	int addr, res;
 
 	if (!it87_find(&addr)) {
-		normal_isa[0] = addr;
+		isa_address = addr;
 	}
-	return i2c_add_driver(&it87_driver);
+
+	res = i2c_add_driver(&it87_driver);
+	if (res)
+		return res;
+
+	res = i2c_isa_add_driver(&it87_isa_driver);
+	if (res) {
+		i2c_del_driver(&it87_driver);
+		return res;
+	}
+
+	return 0;
 }
 
 static void __exit sm_it87_exit(void)
 {
+	i2c_isa_del_driver(&it87_isa_driver);
 	i2c_del_driver(&it87_driver);
 }
 
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 7c6f9ea..be5c709 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -42,8 +42,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
@@ -51,13 +52,12 @@
  */
 
 static unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(lm63);
+I2C_CLIENT_INSMOD_1(lm63);
 
 /*
  * The LM63 registers
@@ -152,6 +152,7 @@
 
 struct lm63_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -358,7 +359,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm63_detect);
+	return i2c_probe(adapter, &addr_data, lm63_detect);
 }
 
 /*
@@ -437,6 +438,12 @@
 	lm63_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	if (data->config & 0x04) { /* tachometer enabled */
 		device_create_file(&new_client->dev,
 				   &sensor_dev_attr_fan1_input.dev_attr);
@@ -462,6 +469,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -505,15 +514,15 @@
 
 static int lm63_detach_client(struct i2c_client *client)
 {
+	struct lm63_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 5be164e..9a3ebdf 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -23,17 +23,17 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include "lm75.h"
 
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
 					0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm75);
+I2C_CLIENT_INSMOD_1(lm75);
 
 /* Many LM75 constants specified below */
 
@@ -46,6 +46,7 @@
 /* Each client has this additional data */
 struct lm75_data {
 	struct i2c_client	client;
+	struct class_device *class_dev;
 	struct semaphore	update_lock;
 	char			valid;		/* !=0 if following fields are valid */
 	unsigned long		last_updated;	/* In jiffies */
@@ -107,10 +108,10 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm75_detect);
+	return i2c_probe(adapter, &addr_data, lm75_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i;
@@ -119,16 +120,6 @@
 	int err = 0;
 	const char *name = "";
 
-	/* Make sure we aren't probing the ISA bus!! This is just a safety check
-	   at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
-	if (i2c_is_isa_adapter(adapter)) {
-		dev_dbg(&adapter->dev,
-			"lm75_detect called for an ISA bus adapter?!?\n");
-		goto exit;
-	}
-#endif
-
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 				     I2C_FUNC_SMBUS_WORD_DATA))
 		goto exit;
@@ -208,12 +199,20 @@
 	lm75_init_client(new_client);
 	
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_temp1_max);
 	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -222,8 +221,10 @@
 
 static int lm75_detach_client(struct i2c_client *client)
 {
+	struct lm75_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->class_dev);
 	i2c_detach_client(client);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 	return 0;
 }
 
@@ -251,8 +252,12 @@
 
 static void lm75_init_client(struct i2c_client *client)
 {
-	/* Initialize the LM75 chip */
-	lm75_write_value(client, LM75_REG_CONF, 0);
+	int reg;
+
+	/* Enable if in shutdown mode */
+	reg = lm75_read_value(client, LM75_REG_CONF);
+	if (reg >= 0 && (reg & 0x01))
+		lm75_write_value(client, LM75_REG_CONF, reg & 0xfe);
 }
 
 static struct lm75_data *lm75_update_device(struct device *dev)
diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h
index 63e3f2f..af7dc65 100644
--- a/drivers/hwmon/lm75.h
+++ b/drivers/hwmon/lm75.h
@@ -25,7 +25,7 @@
     which contains this code, we don't worry about the wasted space.
 */
 
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
 
 /* straight from the datasheet */
 #define LM75_TEMP_MIN (-55000)
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index b98f449..866eab9 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -30,15 +30,14 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm77);
+I2C_CLIENT_INSMOD_1(lm77);
 
 /* The LM77 registers */
 #define LM77_REG_TEMP		0x00
@@ -51,6 +50,7 @@
 /* Each client has this additional data */
 struct lm77_data {
 	struct i2c_client	client;
+	struct class_device *class_dev;
 	struct semaphore	update_lock;
 	char			valid;
 	unsigned long		last_updated;	/* In jiffies */
@@ -208,10 +208,10 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm77_detect);
+	return i2c_probe(adapter, &addr_data, lm77_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
@@ -317,6 +317,12 @@
 	lm77_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
 	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
 	device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -327,6 +333,8 @@
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -335,8 +343,10 @@
 
 static int lm77_detach_client(struct i2c_client *client)
 {
+	struct lm77_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->class_dev);
 	i2c_detach_client(client);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 2924146..f6730dc 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -23,7 +23,10 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 
 /* Addresses to scan */
@@ -31,10 +34,10 @@
 					0x25, 0x26, 0x27, 0x28, 0x29,
 					0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
 					0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-SENSORS_INSMOD_3(lm78, lm78j, lm79);
+I2C_CLIENT_INSMOD_2(lm78, lm79);
 
 /* Many LM78 constants specified below */
 
@@ -104,13 +107,6 @@
 	return val * 1000;
 }
 
-/* VID: mV
-   REG: (see doc/vid) */
-static inline int VID_FROM_REG(u8 val)
-{
-	return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
-}
-
 #define DIV_FROM_REG(val) (1 << (val))
 
 /* There are some complications in a module like this. First off, LM78 chips
@@ -134,6 +130,7 @@
    allocated. */
 struct lm78_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	enum chips type;
 
@@ -156,6 +153,7 @@
 
 
 static int lm78_attach_adapter(struct i2c_adapter *adapter);
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
 static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
 static int lm78_detach_client(struct i2c_client *client);
 
@@ -174,6 +172,14 @@
 	.detach_client	= lm78_detach_client,
 };
 
+static struct i2c_driver lm78_isa_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "lm78-isa",
+	.attach_adapter	= lm78_isa_attach_adapter,
+	.detach_client	= lm78_detach_client,
+};
+
+
 /* 7 Voltages */
 static ssize_t show_in(struct device *dev, char *buf, int nr)
 {
@@ -445,7 +451,7 @@
 static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm78_data *data = lm78_update_device(dev);
-	return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
+	return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
@@ -465,10 +471,15 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm78_detect);
+	return i2c_probe(adapter, &addr_data, lm78_detect);
 }
 
-/* This function is called by i2c_detect */
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+	return lm78_detect(adapter, isa_address, -1);
+}
+
+/* This function is called by i2c_probe */
 int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i, err;
@@ -485,7 +496,8 @@
 
 	/* Reserve the ISA region */
 	if (is_isa)
-		if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
+		if (!request_region(address, LM78_EXTENT,
+				    lm78_isa_driver.name)) {
 			err = -EBUSY;
 			goto ERROR0;
 		}
@@ -540,7 +552,7 @@
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
-	new_client->driver = &lm78_driver;
+	new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver;
 	new_client->flags = 0;
 
 	/* Now, we do the remaining detection. */
@@ -559,10 +571,9 @@
 	/* Determine the chip type. */
 	if (kind <= 0) {
 		i = lm78_read_value(new_client, LM78_REG_CHIPID);
-		if (i == 0x00 || i == 0x20)
+		if (i == 0x00 || i == 0x20	/* LM78 */
+		 || i == 0x40)			/* LM78-J */
 			kind = lm78;
-		else if (i == 0x40)
-			kind = lm78j;
 		else if ((i & 0xfe) == 0xc0)
 			kind = lm79;
 		else {
@@ -578,8 +589,6 @@
 
 	if (kind == lm78) {
 		client_name = "lm78";
-	} else if (kind == lm78j) {
-		client_name = "lm78-j";
 	} else if (kind == lm79) {
 		client_name = "lm79";
 	}
@@ -605,6 +614,12 @@
 	}
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in0_min);
 	device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -643,6 +658,8 @@
 
 	return 0;
 
+ERROR3:
+	i2c_detach_client(new_client);
 ERROR2:
 	kfree(data);
 ERROR1:
@@ -654,18 +671,18 @@
 
 static int lm78_detach_client(struct i2c_client *client)
 {
+	struct lm78_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-		    "Client deregistration failed, client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	if(i2c_is_isa_client(client))
 		release_region(client->addr, LM78_EXTENT);
 
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
@@ -777,18 +794,31 @@
 
 static int __init sm_lm78_init(void)
 {
-	return i2c_add_driver(&lm78_driver);
+	int res;
+
+	res = i2c_add_driver(&lm78_driver);
+	if (res)
+		return res;
+
+	res = i2c_isa_add_driver(&lm78_isa_driver);
+	if (res) {
+		i2c_del_driver(&lm78_driver);
+		return res;
+	}
+
+	return 0;
 }
 
 static void __exit sm_lm78_exit(void)
 {
+	i2c_isa_del_driver(&lm78_isa_driver);
 	i2c_del_driver(&lm78_driver);
 }
 
 
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
+MODULE_DESCRIPTION("LM78/LM79 driver");
 MODULE_LICENSE("GPL");
 
 module_init(sm_lm78_init);
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 8100595..83af8b3 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -26,15 +26,15 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c,
 					0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm80);
+I2C_CLIENT_INSMOD_1(lm80);
 
 /* Many LM80 constants specified below */
 
@@ -107,6 +107,7 @@
 
 struct lm80_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -389,7 +390,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm80_detect);
+	return i2c_probe(adapter, &addr_data, lm80_detect);
 }
 
 int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -451,6 +452,12 @@
 	data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto error_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in0_min);
 	device_create_file(&new_client->dev, &dev_attr_in1_min);
 	device_create_file(&new_client->dev, &dev_attr_in2_min);
@@ -487,6 +494,8 @@
 
 	return 0;
 
+error_detach:
+	i2c_detach_client(new_client);
 error_free:
 	kfree(data);
 exit:
@@ -495,15 +504,15 @@
 
 static int lm80_detach_client(struct i2c_client *client)
 {
+	struct lm80_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index a49008b..d74b2c2 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -32,8 +32,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
@@ -45,13 +46,12 @@
 					0x29, 0x2a, 0x2b,
 					0x4c, 0x4d, 0x4e,
 					I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(lm83);
+I2C_CLIENT_INSMOD_1(lm83);
 
 /*
  * The LM83 registers
@@ -138,6 +138,7 @@
 
 struct lm83_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -212,7 +213,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm83_detect);
+	return i2c_probe(adapter, &addr_data, lm83_detect);
 }
 
 /*
@@ -312,6 +313,12 @@
 	 */
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp1_input.dev_attr);
 	device_create_file(&new_client->dev,
@@ -340,6 +347,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -348,15 +357,15 @@
 
 static int lm83_detach_client(struct i2c_client *client)
 {
+	struct lm83_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-		    "Client deregistration failed, client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index b4d7fd4..ab214df 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -28,15 +28,15 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
+I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
 
 /* The LM85 registers */
 
@@ -281,15 +281,6 @@
 #define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
 #define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
 
-/* i2c-vid.h defines vid_from_reg() */
-#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
-
-/* Unlike some other drivers we DO NOT set initial limits.  Use
- * the config file to set limits.  Some users have reported
- * motherboards shutting down when we set limits in a previous
- * version of the driver.
- */
-
 /* Chip sampling rates
  *
  * Some sensors are not updated more frequently than once per second
@@ -339,6 +330,7 @@
 
 struct lm85_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	enum chips type;
 
@@ -1019,7 +1011,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm85_detect);
+	return i2c_probe(adapter, &addr_data, lm85_detect);
 }
 
 int lm85_detect(struct i2c_adapter *adapter, int address,
@@ -1031,11 +1023,6 @@
 	int err = 0;
 	const char *type_name = "";
 
-	if (i2c_is_isa_adapter(adapter)) {
-		/* This chip has no ISA interface */
-		goto ERROR0 ;
-	};
-
 	if (!i2c_check_functionality(adapter,
 					I2C_FUNC_SMBUS_BYTE_DATA)) {
 		/* We need to be able to do byte I/O */
@@ -1160,12 +1147,18 @@
 		goto ERROR1;
 
 	/* Set the VRM version */
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 
 	/* Initialize the LM85 chip */
 	lm85_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR2;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_fan1_input);
 	device_create_file(&new_client->dev, &dev_attr_fan2_input);
 	device_create_file(&new_client->dev, &dev_attr_fan3_input);
@@ -1235,6 +1228,8 @@
 	return 0;
 
 	/* Error out and cleanup code */
+    ERROR2:
+	i2c_detach_client(new_client);
     ERROR1:
 	kfree(data);
     ERROR0:
@@ -1243,8 +1238,10 @@
 
 int lm85_detach_client(struct i2c_client *client)
 {
+	struct lm85_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->class_dev);
 	i2c_detach_client(client);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index 1921ed1..dca996d 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -57,8 +57,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
@@ -66,13 +67,12 @@
  */
 
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(lm87);
+I2C_CLIENT_INSMOD_1(lm87);
 
 /*
  * The LM87 registers
@@ -175,6 +175,7 @@
 
 struct lm87_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* In jiffies */
@@ -537,7 +538,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm87_detect);
+	return i2c_probe(adapter, &addr_data, lm87_detect);
 }
 
 /*
@@ -608,6 +609,12 @@
 	data->in_scale[7] = 1875;
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in1_input);
 	device_create_file(&new_client->dev, &dev_attr_in1_min);
 	device_create_file(&new_client->dev, &dev_attr_in1_max);
@@ -673,6 +680,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -685,7 +694,7 @@
 	u8 config;
 
 	data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 
 	config = lm87_read_value(client, LM87_REG_CONFIG);
 	if (!(config & 0x01)) {
@@ -719,15 +728,15 @@
 
 static int lm87_detach_client(struct i2c_client *client)
 {
+	struct lm87_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index a67dcad..14de05f 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -75,8 +75,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
@@ -89,13 +90,12 @@
  */
 
 static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
+I2C_CLIENT_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
 
 /*
  * The LM90 registers
@@ -200,6 +200,7 @@
 
 struct lm90_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -352,7 +353,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm90_detect);
+	return i2c_probe(adapter, &addr_data, lm90_detect);
 }
 
 /*
@@ -500,6 +501,12 @@
 	lm90_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp1_input.dev_attr);
 	device_create_file(&new_client->dev,
@@ -524,6 +531,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -547,15 +556,15 @@
 
 static int lm90_detach_client(struct i2c_client *client)
 {
+	struct lm90_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 215c8e4..647b7c7 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -44,17 +44,16 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* The LM92 and MAX6635 have 2 two-state pins for address selection,
    resulting in 4 possible addresses. */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
 				       I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm92);
+I2C_CLIENT_INSMOD_1(lm92);
 
 /* The LM92 registers */
 #define LM92_REG_CONFIG			0x01 /* 8-bit, RW */
@@ -96,6 +95,7 @@
 /* Client data (each client gets its own) */
 struct lm92_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -359,6 +359,12 @@
 	lm92_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
 	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
 	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
@@ -370,6 +376,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -380,20 +388,20 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, lm92_detect);
+	return i2c_probe(adapter, &addr_data, lm92_detect);
 }
 
 static int lm92_detach_client(struct i2c_client *client)
 {
+	struct lm92_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 3c159f1..16bf71f 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -31,20 +31,19 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
 					0x29, 0x2a, 0x2b,
 					0x4c, 0x4d, 0x4e,
 					I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(max1619);
+I2C_CLIENT_INSMOD_1(max1619);
 
 /*
  * The MAX1619 registers
@@ -104,6 +103,7 @@
 
 struct max1619_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -179,7 +179,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, max1619_detect);
+	return i2c_probe(adapter, &addr_data, max1619_detect);
 }
 
 /*
@@ -275,6 +275,12 @@
 	max1619_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
 	device_create_file(&new_client->dev, &dev_attr_temp2_input);
 	device_create_file(&new_client->dev, &dev_attr_temp2_min);
@@ -285,6 +291,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -308,15 +316,15 @@
 
 static int max1619_detach_client(struct i2c_client *client)
 {
+	struct max1619_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index fa4032d..cf2a357 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -38,23 +38,19 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{ NULL }};
 static u8 devid;
-static unsigned int extra_isa[3];
+static unsigned short address;
+static unsigned short extra_isa[3];
 static u8 confreg[4];
 
 enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 };
-static struct i2c_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.normal_isa		= normal_isa,
-	.forces			= forces,
-};
 
 static int init = 1;
 module_param(init, int, 0);
@@ -186,6 +182,7 @@
 
 struct pc87360_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	struct semaphore update_lock;
 	char valid;		/* !=0 if following fields are valid */
@@ -224,8 +221,7 @@
  * Functions declaration
  */
 
-static int pc87360_attach_adapter(struct i2c_adapter *adapter);
-static int pc87360_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pc87360_detect(struct i2c_adapter *adapter);
 static int pc87360_detach_client(struct i2c_client *client);
 
 static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
@@ -242,8 +238,7 @@
 static struct i2c_driver pc87360_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "pc87360",
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter	= pc87360_attach_adapter,
+	.attach_adapter	= pc87360_detect,
 	.detach_client	= pc87360_detach_client,
 };
 
@@ -251,168 +246,178 @@
  * Sysfs stuff
  */
 
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-	size_t count, int nr)
+static ssize_t show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
 {
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index],
+		       FAN_DIV_FROM_REG(data->fan_status[attr->index])));
+}
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index],
+		       FAN_DIV_FROM_REG(data->fan_status[attr->index])));
+}
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n",
+		       FAN_DIV_FROM_REG(data->fan_status[attr->index]));
+}
+static ssize_t show_fan_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n",
+		       FAN_STATUS_FROM_REG(data->fan_status[attr->index]));
+}
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pc87360_data *data = i2c_get_clientdata(client);
 	long fan_min = simple_strtol(buf, NULL, 10);
 
 	down(&data->update_lock);
-	fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[nr]));
+	fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index]));
 
 	/* If it wouldn't fit, change clock divisor */
 	while (fan_min > 255
-	    && (data->fan_status[nr] & 0x60) != 0x60) {
+	    && (data->fan_status[attr->index] & 0x60) != 0x60) {
 		fan_min >>= 1;
-		data->fan[nr] >>= 1;
-		data->fan_status[nr] += 0x20;
+		data->fan[attr->index] >>= 1;
+		data->fan_status[attr->index] += 0x20;
 	}
-	data->fan_min[nr] = fan_min > 255 ? 255 : fan_min;
-	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(nr),
-			    data->fan_min[nr]);
+	data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min;
+	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(attr->index),
+			    data->fan_min[attr->index]);
 
 	/* Write new divider, preserve alarm bits */
-	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(nr),
-			    data->fan_status[nr] & 0xF9);
+	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index),
+			    data->fan_status[attr->index] & 0xF9);
 	up(&data->update_lock);
 
 	return count;
 }
 
 #define show_and_set_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[offset-1], \
-		       FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
-} \
-static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[offset-1], \
-		       FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
-} \
-static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", \
-		       FAN_DIV_FROM_REG(data->fan_status[offset-1])); \
-} \
-static ssize_t show_fan##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", \
-		       FAN_STATUS_FROM_REG(data->fan_status[offset-1])); \
-} \
-static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	return set_fan_min(dev, buf, count, offset-1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
-	show_fan##offset##_input, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
-	show_fan##offset##_min, set_fan##offset##_min); \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
-	show_fan##offset##_div, NULL); \
-static DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
-	show_fan##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+	show_fan_input, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
+	show_fan_min, set_fan_min, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+	show_fan_div, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
+	show_fan_status, NULL, offset-1);
 show_and_set_fan(1)
 show_and_set_fan(2)
 show_and_set_fan(3)
 
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n",
+		       PWM_FROM_REG(data->pwm[attr->index],
+				    FAN_CONFIG_INVERT(data->fan_conf,
+						      attr->index)));
+}
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->pwm[attr->index] = PWM_TO_REG(val,
+			      FAN_CONFIG_INVERT(data->fan_conf, attr->index));
+	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index),
+			    data->pwm[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+
 #define show_and_set_pwm(offset) \
-static ssize_t show_pwm##offset(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", \
-		       PWM_FROM_REG(data->pwm[offset-1], \
-				    FAN_CONFIG_INVERT(data->fan_conf, \
-						      offset-1))); \
-} \
-static ssize_t set_pwm##offset(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->pwm[offset-1] = PWM_TO_REG(val, \
-			      FAN_CONFIG_INVERT(data->fan_conf, offset-1)); \
-	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(offset-1), \
-			    data->pwm[offset-1]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
-	show_pwm##offset, set_pwm##offset);
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
+	show_pwm, set_pwm, offset-1);
 show_and_set_pwm(1)
 show_and_set_pwm(2)
 show_and_set_pwm(3)
 
+static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
+		       data->in_vref));
+}
+static ssize_t show_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
+		       data->in_vref));
+}
+static ssize_t show_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
+		       data->in_vref));
+}
+static ssize_t show_in_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", data->in_status[attr->index]);
+}
+static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
+	pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN,
+			    data->in_min[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_max[attr->index] = IN_TO_REG(val,
+			       data->in_vref);
+	pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX,
+			    data->in_max[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+
 #define show_and_set_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
-		       data->in_vref)); \
-} \
-static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
-		       data->in_vref)); \
-} \
-static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
-		       data->in_vref)); \
-} \
-static ssize_t show_in##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", data->in_status[offset]); \
-} \
-static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->in_min[offset] = IN_TO_REG(val, data->in_vref); \
-	pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MIN, \
-			    data->in_min[offset]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->in_max[offset] = IN_TO_REG(val, \
-			       data->in_vref); \
-	pc87360_write_value(data, LD_IN, offset, PC87365_REG_IN_MAX, \
-			    data->in_max[offset]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
-	show_in##offset##_input, NULL); \
-static DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
-	show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
-	show_in##offset##_max, set_in##offset##_max); \
-static DEVICE_ATTR(in##offset##_status, S_IRUGO, \
-	show_in##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+	show_in_input, NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
+	show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
+	show_in_max, set_in_max, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \
+	show_in_status, NULL, offset);
 show_and_set_in(0)
 show_and_set_in(1)
 show_and_set_in(2)
@@ -425,88 +430,97 @@
 show_and_set_in(9)
 show_and_set_in(10)
 
+static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
+		       data->in_vref));
+}
+static ssize_t show_therm_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
+		       data->in_vref));
+}
+static ssize_t show_therm_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
+		       data->in_vref));
+}
+static ssize_t show_therm_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11],
+		       data->in_vref));
+}
+static ssize_t show_therm_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%u\n", data->in_status[attr->index]);
+}
+static ssize_t set_therm_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
+	pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN,
+			    data->in_min[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_max[attr->index] = IN_TO_REG(val, data->in_vref);
+	pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX,
+			    data->in_max[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref);
+	pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT,
+			    data->in_crit[attr->index-11]);
+	up(&data->update_lock);
+	return count;
+}
+
 #define show_and_set_therm(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset+7], \
-		       data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset+7], \
-		       data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset+7], \
-		       data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[offset-4], \
-		       data->in_vref)); \
-} \
-static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%u\n", data->in_status[offset+7]); \
-} \
-static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->in_min[offset+7] = IN_TO_REG(val, data->in_vref); \
-	pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MIN, \
-			    data->in_min[offset+7]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->in_max[offset+7] = IN_TO_REG(val, data->in_vref); \
-	pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_MAX, \
-			    data->in_max[offset+7]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->in_crit[offset-4] = IN_TO_REG(val, data->in_vref); \
-	pc87360_write_value(data, LD_IN, offset+7, PC87365_REG_TEMP_CRIT, \
-			    data->in_crit[offset-4]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
-	show_temp##offset##_input, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_min, set_temp##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_max, set_temp##offset##_max); \
-static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_crit, set_temp##offset##_crit); \
-static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
-	show_temp##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+	show_therm_input, NULL, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+	show_therm_min, set_therm_min, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+	show_therm_max, set_therm_max, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+	show_therm_crit, set_therm_crit, 11+offset-4); \
+static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+	show_therm_status, NULL, 11+offset-4);
 show_and_set_therm(4)
 show_and_set_therm(5)
 show_and_set_therm(6)
@@ -539,84 +553,93 @@
 }
 static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
 
+static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
+}
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index]));
+}
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index]));
+}
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[attr->index]));
+}
+static ssize_t show_temp_status(struct device *dev, struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct pc87360_data *data = pc87360_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp_status[attr->index]);
+}
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_min[attr->index] = TEMP_TO_REG(val);
+	pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN,
+			    data->temp_min[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_max[attr->index] = TEMP_TO_REG(val);
+	pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX,
+			    data->temp_max[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
+	size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pc87360_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_crit[attr->index] = TEMP_TO_REG(val);
+	pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT,
+			    data->temp_crit[attr->index]);
+	up(&data->update_lock);
+	return count;
+}
+
 #define show_and_set_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
-} \
-static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
-} \
-static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
-}\
-static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[offset-1])); \
-}\
-static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
-	struct pc87360_data *data = pc87360_update_device(dev); \
-	return sprintf(buf, "%d\n", data->temp_status[offset-1]); \
-}\
-static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->temp_min[offset-1] = TEMP_TO_REG(val); \
-	pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MIN, \
-			    data->temp_min[offset-1]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->temp_max[offset-1] = TEMP_TO_REG(val); \
-	pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_MAX, \
-			    data->temp_max[offset-1]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct pc87360_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->temp_crit[offset-1] = TEMP_TO_REG(val); \
-	pc87360_write_value(data, LD_TEMP, offset-1, PC87365_REG_TEMP_CRIT, \
-			    data->temp_crit[offset-1]); \
-	up(&data->update_lock); \
-	return count; \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
-	show_temp##offset##_input, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_min, set_temp##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_max, set_temp##offset##_max); \
-static DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
-	show_temp##offset##_crit, set_temp##offset##_crit); \
-static DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
-	show_temp##offset##_status, NULL);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+	show_temp_input, NULL, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+	show_temp_min, set_temp_min, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+	show_temp_max, set_temp_max, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+	show_temp_crit, set_temp_crit, offset-1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+	show_temp_status, NULL, offset-1);
 show_and_set_temp(1)
 show_and_set_temp(2)
 show_and_set_temp(3)
@@ -632,12 +655,7 @@
  * Device detection, registration and update
  */
 
-static int pc87360_attach_adapter(struct i2c_adapter *adapter)
-{
-	return i2c_detect(adapter, &addr_data, pc87360_detect);
-}
-
-static int pc87360_find(int sioaddr, u8 *devid, int *address)
+static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
 {
 	u16 val;
 	int i;
@@ -683,7 +701,7 @@
 			continue;
 		}
 
-		address[i] = val;
+		addresses[i] = val;
 
 		if (i==0) { /* Fans */
 			confreg[0] = superio_inb(sioaddr, 0xF0);
@@ -727,9 +745,7 @@
 	return 0;
 }
 
-/* We don't really care about the address.
-   Read from extra_isa instead. */
-int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pc87360_detect(struct i2c_adapter *adapter)
 {
 	int i;
 	struct i2c_client *new_client;
@@ -738,9 +754,6 @@
 	const char *name = "pc87360";
 	int use_thermistors = 0;
 
-	if (!i2c_is_isa_adapter(adapter))
-		return -ENODEV;
-
 	if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
 		return -ENOMEM;
 	memset(data, 0x00, sizeof(struct pc87360_data));
@@ -838,51 +851,57 @@
 	}
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
+	}
+
 	if (data->innr) {
-		device_create_file(&new_client->dev, &dev_attr_in0_input);
-		device_create_file(&new_client->dev, &dev_attr_in1_input);
-		device_create_file(&new_client->dev, &dev_attr_in2_input);
-		device_create_file(&new_client->dev, &dev_attr_in3_input);
-		device_create_file(&new_client->dev, &dev_attr_in4_input);
-		device_create_file(&new_client->dev, &dev_attr_in5_input);
-		device_create_file(&new_client->dev, &dev_attr_in6_input);
-		device_create_file(&new_client->dev, &dev_attr_in7_input);
-		device_create_file(&new_client->dev, &dev_attr_in8_input);
-		device_create_file(&new_client->dev, &dev_attr_in9_input);
-		device_create_file(&new_client->dev, &dev_attr_in10_input);
-		device_create_file(&new_client->dev, &dev_attr_in0_min);
-		device_create_file(&new_client->dev, &dev_attr_in1_min);
-		device_create_file(&new_client->dev, &dev_attr_in2_min);
-		device_create_file(&new_client->dev, &dev_attr_in3_min);
-		device_create_file(&new_client->dev, &dev_attr_in4_min);
-		device_create_file(&new_client->dev, &dev_attr_in5_min);
-		device_create_file(&new_client->dev, &dev_attr_in6_min);
-		device_create_file(&new_client->dev, &dev_attr_in7_min);
-		device_create_file(&new_client->dev, &dev_attr_in8_min);
-		device_create_file(&new_client->dev, &dev_attr_in9_min);
-		device_create_file(&new_client->dev, &dev_attr_in10_min);
-		device_create_file(&new_client->dev, &dev_attr_in0_max);
-		device_create_file(&new_client->dev, &dev_attr_in1_max);
-		device_create_file(&new_client->dev, &dev_attr_in2_max);
-		device_create_file(&new_client->dev, &dev_attr_in3_max);
-		device_create_file(&new_client->dev, &dev_attr_in4_max);
-		device_create_file(&new_client->dev, &dev_attr_in5_max);
-		device_create_file(&new_client->dev, &dev_attr_in6_max);
-		device_create_file(&new_client->dev, &dev_attr_in7_max);
-		device_create_file(&new_client->dev, &dev_attr_in8_max);
-		device_create_file(&new_client->dev, &dev_attr_in9_max);
-		device_create_file(&new_client->dev, &dev_attr_in10_max);
-		device_create_file(&new_client->dev, &dev_attr_in0_status);
-		device_create_file(&new_client->dev, &dev_attr_in1_status);
-		device_create_file(&new_client->dev, &dev_attr_in2_status);
-		device_create_file(&new_client->dev, &dev_attr_in3_status);
-		device_create_file(&new_client->dev, &dev_attr_in4_status);
-		device_create_file(&new_client->dev, &dev_attr_in5_status);
-		device_create_file(&new_client->dev, &dev_attr_in6_status);
-		device_create_file(&new_client->dev, &dev_attr_in7_status);
-		device_create_file(&new_client->dev, &dev_attr_in8_status);
-		device_create_file(&new_client->dev, &dev_attr_in9_status);
-		device_create_file(&new_client->dev, &dev_attr_in10_status);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr);
 
 		device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 		device_create_file(&new_client->dev, &dev_attr_vrm);
@@ -890,90 +909,92 @@
 	}
 
 	if (data->tempnr) {
-		device_create_file(&new_client->dev, &dev_attr_temp1_input);
-		device_create_file(&new_client->dev, &dev_attr_temp2_input);
-		device_create_file(&new_client->dev, &dev_attr_temp1_min);
-		device_create_file(&new_client->dev, &dev_attr_temp2_min);
-		device_create_file(&new_client->dev, &dev_attr_temp1_max);
-		device_create_file(&new_client->dev, &dev_attr_temp2_max);
-		device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-		device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-		device_create_file(&new_client->dev, &dev_attr_temp1_status);
-		device_create_file(&new_client->dev, &dev_attr_temp2_status);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr);
 
 		device_create_file(&new_client->dev, &dev_attr_alarms_temp);
 	}
 	if (data->tempnr == 3) {
-		device_create_file(&new_client->dev, &dev_attr_temp3_input);
-		device_create_file(&new_client->dev, &dev_attr_temp3_min);
-		device_create_file(&new_client->dev, &dev_attr_temp3_max);
-		device_create_file(&new_client->dev, &dev_attr_temp3_crit);
-		device_create_file(&new_client->dev, &dev_attr_temp3_status);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr);
 	}
 	if (data->innr == 14) {
-		device_create_file(&new_client->dev, &dev_attr_temp4_input);
-		device_create_file(&new_client->dev, &dev_attr_temp5_input);
-		device_create_file(&new_client->dev, &dev_attr_temp6_input);
-		device_create_file(&new_client->dev, &dev_attr_temp4_min);
-		device_create_file(&new_client->dev, &dev_attr_temp5_min);
-		device_create_file(&new_client->dev, &dev_attr_temp6_min);
-		device_create_file(&new_client->dev, &dev_attr_temp4_max);
-		device_create_file(&new_client->dev, &dev_attr_temp5_max);
-		device_create_file(&new_client->dev, &dev_attr_temp6_max);
-		device_create_file(&new_client->dev, &dev_attr_temp4_crit);
-		device_create_file(&new_client->dev, &dev_attr_temp5_crit);
-		device_create_file(&new_client->dev, &dev_attr_temp6_crit);
-		device_create_file(&new_client->dev, &dev_attr_temp4_status);
-		device_create_file(&new_client->dev, &dev_attr_temp5_status);
-		device_create_file(&new_client->dev, &dev_attr_temp6_status);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr);
 	}
 
 	if (data->fannr) {
 		if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) {
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan1_input);
+					   &sensor_dev_attr_fan1_input.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan1_min);
+					   &sensor_dev_attr_fan1_min.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan1_div);
+					   &sensor_dev_attr_fan1_div.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan1_status);
+					   &sensor_dev_attr_fan1_status.dev_attr);
 		}
 
 		if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) {
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan2_input);
+					   &sensor_dev_attr_fan2_input.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan2_min);
+					   &sensor_dev_attr_fan2_min.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan2_div);
+					   &sensor_dev_attr_fan2_div.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan2_status);
+					   &sensor_dev_attr_fan2_status.dev_attr);
 		}
 
 		if (FAN_CONFIG_CONTROL(data->fan_conf, 0))
-			device_create_file(&new_client->dev, &dev_attr_pwm1);
+			device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
 		if (FAN_CONFIG_CONTROL(data->fan_conf, 1))
-			device_create_file(&new_client->dev, &dev_attr_pwm2);
+			device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
 	}
 	if (data->fannr == 3) {
 		if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) {
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan3_input);
+					   &sensor_dev_attr_fan3_input.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan3_min);
+					   &sensor_dev_attr_fan3_min.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan3_div);
+					   &sensor_dev_attr_fan3_div.dev_attr);
 			device_create_file(&new_client->dev,
-					   &dev_attr_fan3_status);
+					   &sensor_dev_attr_fan3_status.dev_attr);
 		}
 
 		if (FAN_CONFIG_CONTROL(data->fan_conf, 2))
-			device_create_file(&new_client->dev, &dev_attr_pwm3);
+			device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
 	}
 
 	return 0;
 
+ERROR3:
+	i2c_detach_client(new_client);
 ERROR2:
 	for (i = 0; i < 3; i++) {
 		if (data->address[i]) {
@@ -990,11 +1011,10 @@
 	struct pc87360_data *data = i2c_get_clientdata(client);
 	int i;
 
-	if ((i = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((i = i2c_detach_client(client)))
 		return i;
-	}
 
 	for (i = 0; i < 3; i++) {
 		if (data->address[i]) {
@@ -1320,23 +1340,23 @@
 	/* Arbitrarily pick one of the addresses */
 	for (i = 0; i < 3; i++) {
 		if (extra_isa[i] != 0x0000) {
-			normal_isa[0] = extra_isa[i];
+			address = extra_isa[i];
 			break;
 		}
 	}
 
-	if (normal_isa[0] == 0x0000) {
+	if (address == 0x0000) {
 		printk(KERN_WARNING "pc87360: No active logical device, "
 		       "module not inserted.\n");
 		return -ENODEV;
 	}
 
-	return i2c_add_driver(&pc87360_driver);
+	return i2c_isa_add_driver(&pc87360_driver);
 }
 
 static void __exit pc87360_exit(void)
 {
-	i2c_del_driver(&pc87360_driver);
+	i2c_isa_del_driver(&pc87360_driver);
 }
 
 
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 6bbfc8f..8610bce 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -55,7 +55,9 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <asm/io.h>
@@ -68,14 +70,10 @@
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
 
-/* Addresses to scan.
+/* Device address
    Note that we can't determine the ISA address until we have initialized
    our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(sis5595);
+static unsigned short address;
 
 /* Many SIS5595 constants specified below */
 
@@ -168,6 +166,7 @@
    allocated. */
 struct sis5595_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 
 	struct semaphore update_lock;
@@ -190,8 +189,7 @@
 
 static struct pci_dev *s_bridge;	/* pointer to the (only) sis5595 */
 
-static int sis5595_attach_adapter(struct i2c_adapter *adapter);
-static int sis5595_detect(struct i2c_adapter *adapter, int address, int kind);
+static int sis5595_detect(struct i2c_adapter *adapter);
 static int sis5595_detach_client(struct i2c_client *client);
 
 static int sis5595_read_value(struct i2c_client *client, u8 register);
@@ -202,9 +200,7 @@
 static struct i2c_driver sis5595_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "sis5595",
-	.id		= I2C_DRIVERID_SIS5595,
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter	= sis5595_attach_adapter,
+	.attach_adapter	= sis5595_detect,
 	.detach_client	= sis5595_detach_client,
 };
 
@@ -476,14 +472,7 @@
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
  
 /* This is called when the module is loaded */
-static int sis5595_attach_adapter(struct i2c_adapter *adapter)
-{
-	if (!(adapter->class & I2C_CLASS_HWMON))
-		return 0;
-	return i2c_detect(adapter, &addr_data, sis5595_detect);
-}
-
-int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
+static int sis5595_detect(struct i2c_adapter *adapter)
 {
 	int err = 0;
 	int i;
@@ -492,10 +481,6 @@
 	char val;
 	u16 a;
 
-	/* Make sure we are probing the ISA bus!!  */
-	if (!i2c_is_isa_adapter(adapter))
-		goto exit;
-
 	if (force_addr)
 		address = force_addr & ~(SIS5595_EXTENT - 1);
 	/* Reserve the ISA region */
@@ -578,6 +563,12 @@
 	}
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in0_min);
 	device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -608,7 +599,9 @@
 		device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
 	}
 	return 0;
-	
+
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit_release:
@@ -619,18 +612,17 @@
 
 static int sis5595_detach_client(struct i2c_client *client)
 {
+	struct sis5595_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-		    "Client deregistration failed, client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
-	if (i2c_is_isa_client(client))
-		release_region(client->addr, SIS5595_EXTENT);
+	release_region(client->addr, SIS5595_EXTENT);
 
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
@@ -745,7 +737,6 @@
 {
 	u16 val;
 	int *i;
-	int addr = 0;
 
 	for (i = blacklist; *i != 0; i++) {
 		struct pci_dev *dev;
@@ -761,22 +752,19 @@
 	    pci_read_config_word(dev, SIS5595_BASE_REG, &val))
 		return -ENODEV;
 	
-	addr = val & ~(SIS5595_EXTENT - 1);
-	if (addr == 0 && force_addr == 0) {
+	address = val & ~(SIS5595_EXTENT - 1);
+	if (address == 0 && force_addr == 0) {
 		dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
-	if (force_addr)
-		addr = force_addr;	/* so detect will get called */
 
-	if (!addr) {
+	if (!address) {
 		dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
 		return -ENODEV;
 	}
-	normal_isa[0] = addr;
 
 	s_bridge = pci_dev_get(dev);
-	if (i2c_add_driver(&sis5595_driver)) {
+	if (i2c_isa_add_driver(&sis5595_driver)) {
 		pci_dev_put(s_bridge);
 		s_bridge = NULL;
 	}
@@ -803,7 +791,7 @@
 {
 	pci_unregister_driver(&sis5595_pci_driver);
 	if (s_bridge != NULL) {
-		i2c_del_driver(&sis5595_driver);
+		i2c_isa_del_driver(&sis5595_driver);
 		pci_dev_put(s_bridge);
 		s_bridge = NULL;
 	}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index fdeeb3a..7fe7157 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -31,23 +31,14 @@
 #include <linux/ioport.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <asm/io.h>
 
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
 /* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47b397 };
-static struct i2c_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.normal_isa		= normal_isa,
-	.probe			= normal_i2c,		/* cheat */
-	.ignore			= normal_i2c,		/* cheat */
-	.forces			= forces,
-};
+static unsigned short address;
 
 /* Super-I/0 registers and commands */
 
@@ -100,6 +91,7 @@
 
 struct smsc47b397_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 
 	struct semaphore update_lock;
@@ -215,52 +207,40 @@
 #define device_create_file_fan(client, num) \
 	device_create_file(&client->dev, &dev_attr_fan##num##_input)
 
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
-
-static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
-{
-	if (!(adapter->class & I2C_CLASS_HWMON))
-		return 0;
-	return i2c_detect(adapter, &addr_data, smsc47b397_detect);
-}
-
 static int smsc47b397_detach_client(struct i2c_client *client)
 {
+	struct smsc47b397_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	release_region(client->addr, SMSC_EXTENT);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
 
+static int smsc47b397_detect(struct i2c_adapter *adapter);
+
 static struct i2c_driver smsc47b397_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "smsc47b397",
-	.id		= I2C_DRIVERID_SMSC47B397,
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter	= smsc47b397_attach_adapter,
+	.attach_adapter	= smsc47b397_detect,
 	.detach_client	= smsc47b397_detach_client,
 };
 
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int smsc47b397_detect(struct i2c_adapter *adapter)
 {
 	struct i2c_client *new_client;
 	struct smsc47b397_data *data;
 	int err = 0;
 
-	if (!i2c_is_isa_adapter(adapter)) {
-		return 0;
-	}
-
-	if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
-		dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
+	if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
+		dev_err(&adapter->dev, "Region 0x%x already in use!\n",
+			address);
 		return -EBUSY;
 	}
 
@@ -272,7 +252,7 @@
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
-	new_client->addr = addr;
+	new_client->addr = address;
 	init_MUTEX(&data->lock);
 	new_client->adapter = adapter;
 	new_client->driver = &smsc47b397_driver;
@@ -285,6 +265,12 @@
 	if ((err = i2c_attach_client(new_client)))
 		goto error_free;
 
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto error_detach;
+	}
+
 	device_create_file_temp(new_client, 1);
 	device_create_file_temp(new_client, 2);
 	device_create_file_temp(new_client, 3);
@@ -297,14 +283,16 @@
 
 	return 0;
 
+error_detach:
+	i2c_detach_client(new_client);
 error_free:
 	kfree(data);
 error_release:
-	release_region(addr, SMSC_EXTENT);
+	release_region(address, SMSC_EXTENT);
 	return err;
 }
 
-static int __init smsc47b397_find(unsigned int *addr)
+static int __init smsc47b397_find(unsigned short *addr)
 {
 	u8 id, rev;
 
@@ -333,15 +321,15 @@
 {
 	int ret;
 
-	if ((ret = smsc47b397_find(normal_isa)))
+	if ((ret = smsc47b397_find(&address)))
 		return ret;
 
-	return i2c_add_driver(&smsc47b397_driver);
+	return i2c_isa_add_driver(&smsc47b397_driver);
 }
 
 static void __exit smsc47b397_exit(void)
 {
-	i2c_del_driver(&smsc47b397_driver);
+	i2c_isa_del_driver(&smsc47b397_driver);
 }
 
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 7166ad0..7e699a8 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -30,21 +30,14 @@
 #include <linux/ioport.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <asm/io.h>
 
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
 /* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47m1 };
-static struct i2c_address_data addr_data = {
-	.normal_i2c		= normal_i2c,
-	.normal_isa		= normal_isa,
-	.forces			= forces,
-};
+static unsigned short address;
 
 /* Super-I/0 registers and commands */
 
@@ -108,6 +101,7 @@
 
 struct smsc47m1_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 
 	struct semaphore update_lock;
@@ -121,9 +115,7 @@
 };
 
 
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
-static int smsc47m1_find(int *address);
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
+static int smsc47m1_detect(struct i2c_adapter *adapter);
 static int smsc47m1_detach_client(struct i2c_client *client);
 
 static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
@@ -136,9 +128,7 @@
 static struct i2c_driver smsc47m1_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "smsc47m1",
-	.id		= I2C_DRIVERID_SMSC47M1,
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter	= smsc47m1_attach_adapter,
+	.attach_adapter	= smsc47m1_detect,
 	.detach_client	= smsc47m1_detach_client,
 };
 
@@ -354,14 +344,7 @@
 
 static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
 
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
-{
-	if (!(adapter->class & I2C_CLASS_HWMON))
-		return 0;
-	return i2c_detect(adapter, &addr_data, smsc47m1_detect);
-}
-
-static int smsc47m1_find(int *address)
+static int __init smsc47m1_find(unsigned short *addr)
 {
 	u8 val;
 
@@ -388,10 +371,10 @@
 	}
 
 	superio_select();
-	*address = (superio_inb(SUPERIO_REG_BASE) << 8)
-		 |  superio_inb(SUPERIO_REG_BASE + 1);
+	*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
+	      |  superio_inb(SUPERIO_REG_BASE + 1);
 	val = superio_inb(SUPERIO_REG_ACT);
-	if (*address == 0 || (val & 0x01) == 0) {
+	if (*addr == 0 || (val & 0x01) == 0) {
 		printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
 		superio_exit();
 		return -ENODEV;
@@ -401,17 +384,13 @@
 	return 0;
 }
 
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
+static int smsc47m1_detect(struct i2c_adapter *adapter)
 {
 	struct i2c_client *new_client;
 	struct smsc47m1_data *data;
 	int err = 0;
 	int fan1, fan2, pwm1, pwm2;
 
-	if (!i2c_is_isa_adapter(adapter)) {
-		return 0;
-	}
-
 	if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
 		dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
 		return -EBUSY;
@@ -461,6 +440,13 @@
 	   function. */
 	smsc47m1_update_device(&new_client->dev, 1);
 
+	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto error_detach;
+	}
+
 	if (fan1) {
 		device_create_file(&new_client->dev, &dev_attr_fan1_input);
 		device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -494,6 +480,8 @@
 
 	return 0;
 
+error_detach:
+	i2c_detach_client(new_client);
 error_free:
 	kfree(data);
 error_release:
@@ -503,16 +491,16 @@
 
 static int smsc47m1_detach_client(struct i2c_client *client)
 {
+	struct smsc47m1_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	release_region(client->addr, SMSC_EXTENT);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
@@ -573,16 +561,16 @@
 
 static int __init sm_smsc47m1_init(void)
 {
-	if (smsc47m1_find(normal_isa)) {
+	if (smsc47m1_find(&address)) {
 		return -ENODEV;
 	}
 
-	return i2c_add_driver(&smsc47m1_driver);
+	return i2c_isa_add_driver(&smsc47m1_driver);
 }
 
 static void __exit sm_smsc47m1_exit(void)
 {
-	i2c_del_driver(&smsc47m1_driver);
+	i2c_isa_del_driver(&smsc47m1_driver);
 }
 
 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 164d479..eb84997 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -35,7 +35,9 @@
 #include <linux/pci.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <asm/io.h>
 
@@ -47,14 +49,10 @@
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
 
-/* Addresses to scan.
+/* Device address
    Note that we can't determine the ISA address until we have initialized
    our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(via686a);
+static unsigned short address;
 
 /*
    The Via 686a southbridge has a LM78-like chip integrated on the same IC.
@@ -297,6 +295,7 @@
    via686a client is allocated. */
 struct via686a_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -315,8 +314,7 @@
 
 static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */
 
-static int via686a_attach_adapter(struct i2c_adapter *adapter);
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);
+static int via686a_detect(struct i2c_adapter *adapter);
 static int via686a_detach_client(struct i2c_client *client);
 
 static inline int via686a_read_value(struct i2c_client *client, u8 reg)
@@ -576,22 +574,13 @@
 static struct i2c_driver via686a_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "via686a",
-	.id		= I2C_DRIVERID_VIA686A,
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter	= via686a_attach_adapter,
+	.attach_adapter	= via686a_detect,
 	.detach_client	= via686a_detach_client,
 };
 
 
 /* This is called when the module is loaded */
-static int via686a_attach_adapter(struct i2c_adapter *adapter)
-{
-	if (!(adapter->class & I2C_CLASS_HWMON))
-		return 0;
-	return i2c_detect(adapter, &addr_data, via686a_detect);
-}
-
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
+static int via686a_detect(struct i2c_adapter *adapter)
 {
 	struct i2c_client *new_client;
 	struct via686a_data *data;
@@ -599,13 +588,6 @@
 	const char client_name[] = "via686a";
 	u16 val;
 
-	/* Make sure we are probing the ISA bus!!  */
-	if (!i2c_is_isa_adapter(adapter)) {
-		dev_err(&adapter->dev,
-		"via686a_detect called for an I2C bus adapter?!?\n");
-		return 0;
-	}
-
 	/* 8231 requires multiple of 256, we enforce that on 686 as well */
 	if (force_addr)
 		address = force_addr & 0xFF00;
@@ -637,7 +619,7 @@
 
 	if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
 		err = -ENOMEM;
-		goto ERROR0;
+		goto exit_release;
 	}
 	memset(data, 0, sizeof(struct via686a_data));
 
@@ -655,12 +637,18 @@
 	init_MUTEX(&data->update_lock);
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
-		goto ERROR3;
+		goto exit_free;
 
 	/* Initialize the VIA686A chip */
 	via686a_init_client(new_client);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in1_input);
 	device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -695,25 +683,27 @@
 
 	return 0;
 
-ERROR3:
+exit_detach:
+	i2c_detach_client(new_client);
+exit_free:
 	kfree(data);
-ERROR0:
+exit_release:
 	release_region(address, VIA686A_EXTENT);
 	return err;
 }
 
 static int via686a_detach_client(struct i2c_client *client)
 {
+	struct via686a_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-		"Client deregistration failed, client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	release_region(client->addr, VIA686A_EXTENT);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
@@ -810,29 +800,25 @@
 				       const struct pci_device_id *id)
 {
 	u16 val;
-	int addr = 0;
 
 	if (PCIBIOS_SUCCESSFUL !=
 	    pci_read_config_word(dev, VIA686A_BASE_REG, &val))
 		return -ENODEV;
 
-	addr = val & ~(VIA686A_EXTENT - 1);
-	if (addr == 0 && force_addr == 0) {
+	address = val & ~(VIA686A_EXTENT - 1);
+	if (address == 0 && force_addr == 0) {
 		dev_err(&dev->dev, "base address not set - upgrade BIOS "
 			"or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
-	if (force_addr)
-		addr = force_addr;	/* so detect will get called */
 
-	if (!addr) {
+	if (!address) {
 		dev_err(&dev->dev, "No Via 686A sensors found.\n");
 		return -ENODEV;
 	}
-	normal_isa[0] = addr;
 
 	s_bridge = pci_dev_get(dev);
-	if (i2c_add_driver(&via686a_driver)) {
+	if (i2c_isa_add_driver(&via686a_driver)) {
 		pci_dev_put(s_bridge);
 		s_bridge = NULL;
 	}
@@ -859,7 +845,7 @@
 {
 	pci_unregister_driver(&via686a_pci_driver);
 	if (s_bridge != NULL) {
-		i2c_del_driver(&via686a_driver);
+		i2c_isa_del_driver(&via686a_driver);
 		pci_dev_put(s_bridge);
 		s_bridge = NULL;
 	}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 8a40b69..b60efe8 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -9,6 +9,9 @@
     Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
     in testing and debugging this driver.
 
+    This driver also supports the W83627EHG, which is the lead-free
+    version of the W83627EHF.
+
     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
@@ -37,17 +40,14 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <asm/io.h>
 #include "lm75.h"
 
-/* Addresses to scan
-   The actual ISA address is read from Super-I/O configuration space */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(w83627ehf);
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
 
 /*
  * Super-I/O constants and functions
@@ -174,6 +174,7 @@
 
 struct w83627ehf_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 
 	struct semaphore update_lock;
@@ -666,15 +667,12 @@
 	}
 }
 
-static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
+static int w83627ehf_detect(struct i2c_adapter *adapter)
 {
 	struct i2c_client *client;
 	struct w83627ehf_data *data;
 	int i, err = 0;
 
-	if (!i2c_is_isa_adapter(adapter))
-		return 0;
-
 	if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
 		err = -EBUSY;
 		goto exit;
@@ -720,6 +718,12 @@
 		data->has_fan |= (1 << 4);
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&client->dev, &dev_attr_fan1_input);
 	device_create_file(&client->dev, &dev_attr_fan1_min);
 	device_create_file(&client->dev, &dev_attr_fan1_div);
@@ -753,6 +757,8 @@
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(client);
 exit_free:
 	kfree(data);
 exit_release:
@@ -761,24 +767,17 @@
 	return err;
 }
 
-static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
-{
-	if (!(adapter->class & I2C_CLASS_HWMON))
-		return 0;
-	return i2c_detect(adapter, &addr_data, w83627ehf_detect);
-}
-
 static int w83627ehf_detach_client(struct i2c_client *client)
 {
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 	release_region(client->addr, REGION_LENGTH);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
@@ -786,12 +785,11 @@
 static struct i2c_driver w83627ehf_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "w83627ehf",
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter	= w83627ehf_attach_adapter,
+	.attach_adapter	= w83627ehf_detect,
 	.detach_client	= w83627ehf_detach_client,
 };
 
-static int __init w83627ehf_find(int sioaddr, int *address)
+static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
 {
 	u16 val;
 
@@ -809,8 +807,8 @@
 	superio_select(W83627EHF_LD_HWM);
 	val = (superio_inb(SIO_REG_ADDR) << 8)
 	    | superio_inb(SIO_REG_ADDR + 1);
-	*address = val & ~(REGION_LENGTH - 1);
-	if (*address == 0) {
+	*addr = val & ~(REGION_LENGTH - 1);
+	if (*addr == 0) {
 		superio_exit();
 		return -ENODEV;
 	}
@@ -826,16 +824,16 @@
 
 static int __init sensors_w83627ehf_init(void)
 {
-	if (w83627ehf_find(0x2e, &normal_isa[0])
-	 && w83627ehf_find(0x4e, &normal_isa[0]))
+	if (w83627ehf_find(0x2e, &address)
+	 && w83627ehf_find(0x4e, &address))
 		return -ENODEV;
 
-	return i2c_add_driver(&w83627ehf_driver);
+	return i2c_isa_add_driver(&w83627ehf_driver);
 }
 
 static void __exit sensors_w83627ehf_exit(void)
 {
-	i2c_del_driver(&w83627ehf_driver);
+	i2c_isa_del_driver(&w83627ehf_driver);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index bd87a42..02bd5c0 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -42,8 +42,10 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 #include "lm75.h"
 
@@ -56,12 +58,11 @@
 MODULE_PARM_DESC(force_i2c,
 		 "Initialize the i2c address of the sensors");
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
 
 /* Insmod parameters */
-SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
+enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
 
 static int init = 1;
 module_param(init, bool, 0);
@@ -277,6 +278,7 @@
    dynamically allocated, at the same time when a new client is allocated. */
 struct w83627hf_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	enum chips type;
 
@@ -314,9 +316,7 @@
 };
 
 
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
-static int w83627hf_detect(struct i2c_adapter *adapter, int address,
-			  int kind);
+static int w83627hf_detect(struct i2c_adapter *adapter);
 static int w83627hf_detach_client(struct i2c_client *client);
 
 static int w83627hf_read_value(struct i2c_client *client, u16 register);
@@ -328,9 +328,7 @@
 static struct i2c_driver w83627hf_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "w83627hf",
-	.id		= I2C_DRIVERID_W83627HF,
-	.flags		= I2C_DF_NOTIFY,
-	.attach_adapter	= w83627hf_attach_adapter,
+	.attach_adapter	= w83627hf_detect,
 	.detach_client	= w83627hf_detach_client,
 };
 
@@ -959,16 +957,7 @@
 } while (0)
 
 
-/* This function is called when:
-     * w83627hf_driver is inserted (when this module is loaded), for each
-       available adapter
-     * when a new adapter is inserted (and w83627hf_driver is still present) */
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
-{
-	return i2c_detect(adapter, &addr_data, w83627hf_detect);
-}
-
-static int w83627hf_find(int sioaddr, int *address)
+static int __init w83627hf_find(int sioaddr, unsigned short *addr)
 {
 	u16 val;
 
@@ -988,32 +977,24 @@
 	superio_select(W83627HF_LD_HWM);
 	val = (superio_inb(WINB_BASE_REG) << 8) |
 	       superio_inb(WINB_BASE_REG + 1);
-	*address = val & ~(WINB_EXTENT - 1);
-	if (*address == 0 && force_addr == 0) {
+	*addr = val & ~(WINB_EXTENT - 1);
+	if (*addr == 0 && force_addr == 0) {
 		superio_exit();
 		return -ENODEV;
 	}
-	if (force_addr)
-		*address = force_addr;	/* so detect will get called */
 
 	superio_exit();
 	return 0;
 }
 
-int w83627hf_detect(struct i2c_adapter *adapter, int address,
-		   int kind)
+static int w83627hf_detect(struct i2c_adapter *adapter)
 {
-	int val;
+	int val, kind;
 	struct i2c_client *new_client;
 	struct w83627hf_data *data;
 	int err = 0;
 	const char *client_name = "";
 
-	if (!i2c_is_isa_adapter(adapter)) {
-		err = -ENODEV;
-		goto ERROR0;
-	}
-
 	if(force_addr)
 		address = force_addr & ~(WINB_EXTENT - 1);
 
@@ -1102,6 +1083,12 @@
 	data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
+	}
+
 	device_create_file_in(new_client, 0);
 	if (kind != w83697hf)
 		device_create_file_in(new_client, 1);
@@ -1152,6 +1139,8 @@
 
 	return 0;
 
+      ERROR3:
+	i2c_detach_client(new_client);
       ERROR2:
 	kfree(data);
       ERROR1:
@@ -1162,16 +1151,16 @@
 
 static int w83627hf_detach_client(struct i2c_client *client)
 {
+	struct w83627hf_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-		       "Client deregistration failed, client not detached.\n");
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	release_region(client->addr, WINB_EXTENT);
-	kfree(i2c_get_clientdata(client));
+	kfree(data);
 
 	return 0;
 }
@@ -1327,7 +1316,7 @@
 		data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
 	} else {
 		/* Convert VID to voltage based on default VRM */
-		data->vrm = i2c_which_vrm();
+		data->vrm = vid_which_vrm();
 	}
 
 	tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
@@ -1485,20 +1474,17 @@
 
 static int __init sensors_w83627hf_init(void)
 {
-	int addr;
-
-	if (w83627hf_find(0x2e, &addr)
-	 && w83627hf_find(0x4e, &addr)) {
+	if (w83627hf_find(0x2e, &address)
+	 && w83627hf_find(0x4e, &address)) {
 		return -ENODEV;
 	}
-	normal_isa[0] = addr;
 
-	return i2c_add_driver(&w83627hf_driver);
+	return i2c_isa_add_driver(&w83627hf_driver);
 }
 
 static void __exit sensors_w83627hf_exit(void)
 {
-	i2c_del_driver(&w83627hf_driver);
+	i2c_isa_del_driver(&w83627hf_driver);
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 0bb131c..4c43337 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -38,8 +38,10 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 #include "lm75.h"
 
@@ -47,10 +49,10 @@
 static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
 					0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
 					0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
+I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
 		    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -218,6 +220,7 @@
    allocated. */
 struct w83781d_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore lock;
 	enum chips type;
 
@@ -255,6 +258,7 @@
 };
 
 static int w83781d_attach_adapter(struct i2c_adapter *adapter);
+static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter);
 static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
 static int w83781d_detach_client(struct i2c_client *client);
 
@@ -273,6 +277,14 @@
 	.detach_client = w83781d_detach_client,
 };
 
+static struct i2c_driver w83781d_isa_driver = {
+	.owner = THIS_MODULE,
+	.name = "w83781d-isa",
+	.attach_adapter = w83781d_isa_attach_adapter,
+	.detach_client = w83781d_detach_client,
+};
+
+
 /* following are the sysfs callback functions */
 #define show_in_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
@@ -856,7 +868,13 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, w83781d_detect);
+	return i2c_probe(adapter, &addr_data, w83781d_detect);
+}
+
+static int
+w83781d_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+	return w83781d_detect(adapter, isa_address, -1);
 }
 
 /* Assumes that adapter is of I2C, not ISA variety.
@@ -961,10 +979,10 @@
 ERROR_SC_3:
 	i2c_detach_client(data->lm75[0]);
 ERROR_SC_2:
-	if (NULL != data->lm75[1])
+	if (data->lm75[1])
 		kfree(data->lm75[1]);
 ERROR_SC_1:
-	if (NULL != data->lm75[0])
+	if (data->lm75[0])
 		kfree(data->lm75[0]);
 ERROR_SC_0:
 	return err;
@@ -999,7 +1017,7 @@
 	
 	if (is_isa)
 		if (!request_region(address, W83781D_EXTENT,
-				    w83781d_driver.name)) {
+				    w83781d_isa_driver.name)) {
 			dev_dbg(&adapter->dev, "Request of region "
 				"0x%x-0x%x for w83781d failed\n", address,
 				address + W83781D_EXTENT - 1);
@@ -1057,7 +1075,7 @@
 	new_client->addr = address;
 	init_MUTEX(&data->lock);
 	new_client->adapter = adapter;
-	new_client->driver = &w83781d_driver;
+	new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
 	new_client->flags = 0;
 
 	/* Now, we do the remaining detection. */
@@ -1189,6 +1207,12 @@
 			data->pwmenable[i] = 1;
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR4;
+	}
+
 	device_create_file_in(new_client, 0);
 	if (kind != w83783s)
 		device_create_file_in(new_client, 1);
@@ -1241,6 +1265,15 @@
 
 	return 0;
 
+ERROR4:
+	if (data->lm75[1]) {
+		i2c_detach_client(data->lm75[1]);
+		kfree(data->lm75[1]);
+	}
+	if (data->lm75[0]) {
+		i2c_detach_client(data->lm75[0]);
+		kfree(data->lm75[0]);
+	}
 ERROR3:
 	i2c_detach_client(new_client);
 ERROR2:
@@ -1255,24 +1288,26 @@
 static int
 w83781d_detach_client(struct i2c_client *client)
 {
+	struct w83781d_data *data = i2c_get_clientdata(client);
 	int err;
 
+	/* main client */
+	if (data)
+		hwmon_device_unregister(data->class_dev);
+
 	if (i2c_is_isa_client(client))
 		release_region(client->addr, W83781D_EXTENT);
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-		       "Client deregistration failed, client not detached.\n");
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
-	if (i2c_get_clientdata(client)==NULL) {
-		/* subclients */
+	/* main client */
+	if (data)
+		kfree(data);
+
+	/* subclient */
+	else
 		kfree(client);
-	} else {
-		/* main client */
-		kfree(i2c_get_clientdata(client));
-	}
 
 	return 0;
 }
@@ -1443,7 +1478,7 @@
 		w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
 	}
 
-	data->vrm = i2c_which_vrm();
+	data->vrm = vid_which_vrm();
 
 	if ((type != w83781d) && (type != as99127f)) {
 		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
@@ -1613,12 +1648,25 @@
 static int __init
 sensors_w83781d_init(void)
 {
-	return i2c_add_driver(&w83781d_driver);
+	int res;
+
+	res = i2c_add_driver(&w83781d_driver);
+	if (res)
+		return res;
+
+	res = i2c_isa_add_driver(&w83781d_isa_driver);
+	if (res) {
+		i2c_del_driver(&w83781d_driver);
+		return res;
+	}
+
+	return 0;
 }
 
 static void __exit
 sensors_w83781d_exit(void)
 {
+	i2c_isa_del_driver(&w83781d_isa_driver);
 	i2c_del_driver(&w83781d_driver);
 }
 
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
new file mode 100644
index 0000000..ba0c280
--- /dev/null
+++ b/drivers/hwmon/w83792d.c
@@ -0,0 +1,1649 @@
+/*
+    w83792d.c - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+    Copyright (C) 2004, 2005 Winbond Electronics Corp.
+                        Chunhao Huang <DZShen@Winbond.com.tw>,
+                        Rudolf Marek <r.marek@sh.cvut.cz>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    Note:
+    1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver.
+    2. This driver is only for Winbond W83792D C version device, there
+       are also some motherboards with B version W83792D device. The
+       calculation method to in6-in7(measured value, limits) is a little
+       different between C and B version. C or B version can be identified
+       by CR[0x49h].
+*/
+
+/*
+    Supports following chips:
+
+    Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
+    w83792d	9	7	7	3	0x7a	0x5ca3	yes	no
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83792d);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+			"{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int init;
+module_param(init, bool, 0);
+MODULE_PARM_DESC(init, "Set to one to force chip initialization");
+
+/* The W83792D registers */
+static const u8 W83792D_REG_IN[9] = {
+	0x20,	/* Vcore A in DataSheet */
+	0x21,	/* Vcore B in DataSheet */
+	0x22,	/* VIN0 in DataSheet */
+	0x23,	/* VIN1 in DataSheet */
+	0x24,	/* VIN2 in DataSheet */
+	0x25,	/* VIN3 in DataSheet */
+	0x26,	/* 5VCC in DataSheet */
+	0xB0,	/* 5VSB in DataSheet */
+	0xB1	/* VBAT in DataSheet */
+};
+#define W83792D_REG_LOW_BITS1 0x3E  /* Low Bits I in DataSheet */
+#define W83792D_REG_LOW_BITS2 0x3F  /* Low Bits II in DataSheet */
+static const u8 W83792D_REG_IN_MAX[9] = {
+	0x2B,	/* Vcore A High Limit in DataSheet */
+	0x2D,	/* Vcore B High Limit in DataSheet */
+	0x2F,	/* VIN0 High Limit in DataSheet */
+	0x31,	/* VIN1 High Limit in DataSheet */
+	0x33,	/* VIN2 High Limit in DataSheet */
+	0x35,	/* VIN3 High Limit in DataSheet */
+	0x37,	/* 5VCC High Limit in DataSheet */
+	0xB4,	/* 5VSB High Limit in DataSheet */
+	0xB6	/* VBAT High Limit in DataSheet */
+};
+static const u8 W83792D_REG_IN_MIN[9] = {
+	0x2C,	/* Vcore A Low Limit in DataSheet */
+	0x2E,	/* Vcore B Low Limit in DataSheet */
+	0x30,	/* VIN0 Low Limit in DataSheet */
+	0x32,	/* VIN1 Low Limit in DataSheet */
+	0x34,	/* VIN2 Low Limit in DataSheet */
+	0x36,	/* VIN3 Low Limit in DataSheet */
+	0x38,	/* 5VCC Low Limit in DataSheet */
+	0xB5,	/* 5VSB Low Limit in DataSheet */
+	0xB7	/* VBAT Low Limit in DataSheet */
+};
+static const u8 W83792D_REG_FAN[7] = {
+	0x28,	/* FAN 1 Count in DataSheet */
+	0x29,	/* FAN 2 Count in DataSheet */
+	0x2A,	/* FAN 3 Count in DataSheet */
+	0xB8,	/* FAN 4 Count in DataSheet */
+	0xB9,	/* FAN 5 Count in DataSheet */
+	0xBA,	/* FAN 6 Count in DataSheet */
+	0xBE	/* FAN 7 Count in DataSheet */
+};
+static const u8 W83792D_REG_FAN_MIN[7] = {
+	0x3B,	/* FAN 1 Count Low Limit in DataSheet */
+	0x3C,	/* FAN 2 Count Low Limit in DataSheet */
+	0x3D,	/* FAN 3 Count Low Limit in DataSheet */
+	0xBB,	/* FAN 4 Count Low Limit in DataSheet */
+	0xBC,	/* FAN 5 Count Low Limit in DataSheet */
+	0xBD,	/* FAN 6 Count Low Limit in DataSheet */
+	0xBF	/* FAN 7 Count Low Limit in DataSheet */
+};
+#define W83792D_REG_FAN_CFG 0x84	/* FAN Configuration in DataSheet */
+static const u8 W83792D_REG_FAN_DIV[4] = {
+	0x47,	/* contains FAN2 and FAN1 Divisor */
+	0x5B,	/* contains FAN4 and FAN3 Divisor */
+	0x5C,	/* contains FAN6 and FAN5 Divisor */
+	0x9E	/* contains FAN7 Divisor. */
+};
+static const u8 W83792D_REG_PWM[7] = {
+	0x81,	/* FAN 1 Duty Cycle, be used to control */
+	0x83,	/* FAN 2 Duty Cycle, be used to control */
+	0x94,	/* FAN 3 Duty Cycle, be used to control */
+	0xA3,	/* FAN 4 Duty Cycle, be used to control */
+	0xA4,	/* FAN 5 Duty Cycle, be used to control */
+	0xA5,	/* FAN 6 Duty Cycle, be used to control */
+	0xA6	/* FAN 7 Duty Cycle, be used to control */
+};
+#define W83792D_REG_BANK		0x4E
+#define W83792D_REG_TEMP2_CONFIG	0xC2
+#define W83792D_REG_TEMP3_CONFIG	0xCA
+
+static const u8 W83792D_REG_TEMP1[3] = {
+	0x27,	/* TEMP 1 in DataSheet */
+	0x39,	/* TEMP 1 Over in DataSheet */
+	0x3A,	/* TEMP 1 Hyst in DataSheet */
+};
+
+static const u8 W83792D_REG_TEMP_ADD[2][6] = {
+	{ 0xC0,		/* TEMP 2 in DataSheet */
+	  0xC1,		/* TEMP 2(0.5 deg) in DataSheet */
+	  0xC5,		/* TEMP 2 Over High part in DataSheet */
+	  0xC6,		/* TEMP 2 Over Low part in DataSheet */
+	  0xC3,		/* TEMP 2 Thyst High part in DataSheet */
+	  0xC4 },	/* TEMP 2 Thyst Low part in DataSheet */
+	{ 0xC8,		/* TEMP 3 in DataSheet */
+	  0xC9,		/* TEMP 3(0.5 deg) in DataSheet */
+	  0xCD,		/* TEMP 3 Over High part in DataSheet */
+	  0xCE,		/* TEMP 3 Over Low part in DataSheet */
+	  0xCB,		/* TEMP 3 Thyst High part in DataSheet */
+	  0xCC }	/* TEMP 3 Thyst Low part in DataSheet */
+};
+
+static const u8 W83792D_REG_THERMAL[3] = {
+	0x85,	/* SmartFanI: Fan1 target value */
+	0x86,	/* SmartFanI: Fan2 target value */
+	0x96	/* SmartFanI: Fan3 target value */
+};
+
+static const u8 W83792D_REG_TOLERANCE[3] = {
+	0x87,	/* (bit3-0)SmartFan Fan1 tolerance */
+	0x87,	/* (bit7-4)SmartFan Fan2 tolerance */
+	0x97	/* (bit3-0)SmartFan Fan3 tolerance */
+};
+
+static const u8 W83792D_REG_POINTS[3][4] = {
+	{ 0x85,		/* SmartFanII: Fan1 temp point 1 */
+	  0xE3,		/* SmartFanII: Fan1 temp point 2 */
+	  0xE4,		/* SmartFanII: Fan1 temp point 3 */
+	  0xE5 },	/* SmartFanII: Fan1 temp point 4 */
+	{ 0x86,		/* SmartFanII: Fan2 temp point 1 */
+	  0xE6,		/* SmartFanII: Fan2 temp point 2 */
+	  0xE7,		/* SmartFanII: Fan2 temp point 3 */
+	  0xE8 },	/* SmartFanII: Fan2 temp point 4 */
+	{ 0x96,		/* SmartFanII: Fan3 temp point 1 */
+	  0xE9,		/* SmartFanII: Fan3 temp point 2 */
+	  0xEA,		/* SmartFanII: Fan3 temp point 3 */
+	  0xEB }	/* SmartFanII: Fan3 temp point 4 */
+};
+
+static const u8 W83792D_REG_LEVELS[3][4] = {
+	{ 0x88,		/* (bit3-0) SmartFanII: Fan1 Non-Stop */
+	  0x88,		/* (bit7-4) SmartFanII: Fan1 Level 1 */
+	  0xE0,		/* (bit7-4) SmartFanII: Fan1 Level 2 */
+	  0xE0 },	/* (bit3-0) SmartFanII: Fan1 Level 3 */
+	{ 0x89,		/* (bit3-0) SmartFanII: Fan2 Non-Stop */
+	  0x89,		/* (bit7-4) SmartFanII: Fan2 Level 1 */
+	  0xE1,		/* (bit7-4) SmartFanII: Fan2 Level 2 */
+	  0xE1 },	/* (bit3-0) SmartFanII: Fan2 Level 3 */
+	{ 0x98,		/* (bit3-0) SmartFanII: Fan3 Non-Stop */
+	  0x98,		/* (bit7-4) SmartFanII: Fan3 Level 1 */
+	  0xE2,		/* (bit7-4) SmartFanII: Fan3 Level 2 */
+	  0xE2 }	/* (bit3-0) SmartFanII: Fan3 Level 3 */
+};
+
+#define W83792D_REG_CONFIG		0x40
+#define W83792D_REG_VID_FANDIV		0x47
+#define W83792D_REG_CHIPID		0x49
+#define W83792D_REG_WCHIPID		0x58
+#define W83792D_REG_CHIPMAN		0x4F
+#define W83792D_REG_PIN			0x4B
+#define W83792D_REG_I2C_SUBADDR		0x4A
+
+#define W83792D_REG_ALARM1 0xA9		/* realtime status register1 */
+#define W83792D_REG_ALARM2 0xAA		/* realtime status register2 */
+#define W83792D_REG_ALARM3 0xAB		/* realtime status register3 */
+#define W83792D_REG_CHASSIS 0x42	/* Bit 5: Case Open status bit */
+#define W83792D_REG_CHASSIS_CLR 0x44	/* Bit 7: Case Open CLR_CHS/Reset bit */
+
+/* control in0/in1 's limit modifiability */
+#define W83792D_REG_VID_IN_B		0x17
+
+#define W83792D_REG_VBAT		0x5D
+#define W83792D_REG_I2C_ADDR		0x48
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+   variants. Note that you should be a bit careful with which arguments
+   these macros are called: arguments may be evaluated more than once.
+   Fixing this is just not worth it. */
+#define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \
+				((((nr)==6)||((nr)==7))?(val*6):(val*4)))
+#define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \
+				((((nr)==6)||((nr)==7))?(val/6):(val/4)))
+
+static inline u8
+FAN_TO_REG(long rpm, int div)
+{
+	if (rpm == 0)
+		return 255;
+	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div)	((val) == 0   ? -1 : \
+				((val) == 255 ? 0 : \
+						1350000 / ((val) * (div))))
+
+/* for temp1 */
+#define TEMP1_TO_REG(val)	(SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+					: (val)) / 1000, 0, 0xff))
+#define TEMP1_FROM_REG(val)	(((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
+/* for temp2 and temp3, because they need addtional resolution */
+#define TEMP_ADD_FROM_REG(val1, val2) \
+	((((val1) & 0x80 ? (val1)-0x100 \
+		: (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0))
+#define TEMP_ADD_TO_REG_HIGH(val) \
+	(SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+			: (val)) / 1000, 0, 0xff))
+#define TEMP_ADD_TO_REG_LOW(val)	((val%1000) ? 0x80 : 0x00)
+
+#define PWM_FROM_REG(val)		(val)
+#define PWM_TO_REG(val)			(SENSORS_LIMIT((val),0,255))
+#define DIV_FROM_REG(val)		(1 << (val))
+
+static inline u8
+DIV_TO_REG(long val)
+{
+	int i;
+	val = SENSORS_LIMIT(val, 1, 128) >> 1;
+	for (i = 0; i < 6; i++) {
+		if (val == 0)
+			break;
+		val >>= 1;
+	}
+	return ((u8) i);
+}
+
+struct w83792d_data {
+	struct i2c_client client;
+	struct class_device *class_dev;
+	struct semaphore lock;
+	enum chips type;
+
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* array of 2 pointers to subclients */
+	struct i2c_client *lm75[2];
+
+	u8 in[9];		/* Register value */
+	u8 in_max[9];		/* Register value */
+	u8 in_min[9];		/* Register value */
+	u8 low_bits[2];		/* Additional resolution to voltage in0-6 */
+	u8 fan[7];		/* Register value */
+	u8 fan_min[7];		/* Register value */
+	u8 temp1[3];		/* current, over, thyst */
+	u8 temp_add[2][6];	/* Register value */
+	u8 fan_div[7];		/* Register encoding, shifted right */
+	u8 pwm[7];		/* We only consider the first 3 set of pwm,
+				   although 792 chip has 7 set of pwm. */
+	u8 pwmenable[3];
+	u8 pwm_mode[7];		/* indicates PWM or DC mode: 1->PWM; 0->DC */
+	u32 alarms;		/* realtime status register encoding,combined */
+	u8 chassis;		/* Chassis status */
+	u8 chassis_clear;	/* CLR_CHS, clear chassis intrusion detection */
+	u8 thermal_cruise[3];	/* Smart FanI: Fan1,2,3 target value */
+	u8 tolerance[3];	/* Fan1,2,3 tolerance(Smart Fan I/II) */
+	u8 sf2_points[3][4];	/* Smart FanII: Fan1,2,3 temperature points */
+	u8 sf2_levels[3][4];	/* Smart FanII: Fan1,2,3 duty cycle levels */
+};
+
+static int w83792d_attach_adapter(struct i2c_adapter *adapter);
+static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83792d_detach_client(struct i2c_client *client);
+
+static int w83792d_read_value(struct i2c_client *client, u8 register);
+static int w83792d_write_value(struct i2c_client *client, u8 register,
+				u8 value);
+static struct w83792d_data *w83792d_update_device(struct device *dev);
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
+#endif
+
+static void w83792d_init_client(struct i2c_client *client);
+
+static struct i2c_driver w83792d_driver = {
+	.owner = THIS_MODULE,
+	.name = "w83792d",
+	.flags = I2C_DF_NOTIFY,
+	.attach_adapter = w83792d_attach_adapter,
+	.detach_client = w83792d_detach_client,
+};
+
+static long in_count_from_reg(int nr, struct w83792d_data *data)
+{
+	u16 vol_count = data->in[nr];
+	u16 low_bits = 0;
+	vol_count = (vol_count << 2);
+	switch (nr)
+	{
+	case 0:  /* vin0 */
+		low_bits = (data->low_bits[0]) & 0x03;
+		break;
+	case 1:  /* vin1 */
+		low_bits = ((data->low_bits[0]) & 0x0c) >> 2;
+		break;
+	case 2:  /* vin2 */
+		low_bits = ((data->low_bits[0]) & 0x30) >> 4;
+		break;
+	case 3:  /* vin3 */
+		low_bits = ((data->low_bits[0]) & 0xc0) >> 6;
+		break;
+	case 4:  /* vin4 */
+		low_bits = (data->low_bits[1]) & 0x03;
+		break;
+	case 5:  /* vin5 */
+		low_bits = ((data->low_bits[1]) & 0x0c) >> 2;
+		break;
+	case 6:  /* vin6 */
+		low_bits = ((data->low_bits[1]) & 0x30) >> 4;
+	default:
+		break;
+	}
+	vol_count = vol_count | low_bits;
+	return vol_count;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf,"%ld\n", IN_FROM_REG(nr,(in_count_from_reg(nr, data))));
+}
+
+#define show_in_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+			char *buf) \
+{ \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	struct w83792d_data *data = w83792d_update_device(dev); \
+	return sprintf(buf,"%ld\n", (long)(IN_FROM_REG(nr, (data->reg[nr])*4))); \
+}
+
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg (struct device *dev, \
+				struct device_attribute *attr, \
+				const char *buf, size_t count) \
+{ \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83792d_data *data = i2c_get_clientdata(client); \
+	u32 val; \
+	 \
+	val = simple_strtoul(buf, NULL, 10); \
+	data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \
+	w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+	 \
+	return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+#define sysfs_in_reg(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \
+				NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+				show_in_min, store_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+				show_in_max, store_in_max, offset);
+
+sysfs_in_reg(0);
+sysfs_in_reg(1);
+sysfs_in_reg(2);
+sysfs_in_reg(3);
+sysfs_in_reg(4);
+sysfs_in_reg(5);
+sysfs_in_reg(6);
+sysfs_in_reg(7);
+sysfs_in_reg(8);
+
+#define device_create_file_in(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \
+} while (0)
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
+			char *buf) \
+{ \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index - 1; \
+	struct w83792d_data *data = w83792d_update_device(dev); \
+	return sprintf(buf,"%d\n", \
+		FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+}
+
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+	w83792d_write_value(client, W83792D_REG_FAN_MIN[nr],
+				data->fan_min[nr]);
+
+	return count;
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr - 1]));
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least suprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
+static ssize_t
+store_fan_div(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	unsigned long min;
+	/*u8 reg;*/
+	u8 fan_div_reg = 0;
+	u8 tmp_fan_div;
+
+	/* Save fan_min */
+	min = FAN_FROM_REG(data->fan_min[nr],
+			   DIV_FROM_REG(data->fan_div[nr]));
+
+	data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+
+	fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]);
+	fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8;
+	tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70)
+					: ((data->fan_div[nr]) & 0x07);
+	w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1],
+					fan_div_reg | tmp_fan_div);
+
+	/* Restore fan_min */
+	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]);
+
+	return count;
+}
+
+#define sysfs_fan(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \
+				offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+				show_fan_div, store_fan_div, offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+				show_fan_min, store_fan_min, offset);
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+sysfs_fan(4);
+sysfs_fan(5);
+sysfs_fan(6);
+sysfs_fan(7);
+
+#define device_create_file_fan(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature1, includes measured value and limits */
+
+static ssize_t show_temp1(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[nr]));
+}
+
+static ssize_t store_temp1(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	s32 val;
+
+	val = simple_strtol(buf, NULL, 10);
+
+	data->temp1[nr] = TEMP1_TO_REG(val);
+	w83792d_write_value(client, W83792D_REG_TEMP1[nr],
+		data->temp1[nr]);
+
+	return count;
+}
+
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1,
+				store_temp1, 1);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1,
+				store_temp1, 2);
+
+#define device_create_file_temp1(client) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature2-3, includes measured value and limits */
+
+static ssize_t show_temp23(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf,"%ld\n",
+		(long)TEMP_ADD_FROM_REG(data->temp_add[nr][index],
+			data->temp_add[nr][index+1]));
+}
+
+static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	s32 val;
+
+	val = simple_strtol(buf, NULL, 10);
+
+	data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val);
+	data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val);
+	w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index],
+		data->temp_add[nr][index]);
+	w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1],
+		data->temp_add[nr][index+1]);
+
+	return count;
+}
+
+#define sysfs_temp23(name,idx) \
+static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \
+				idx, 0); \
+static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \
+				show_temp23, store_temp23, idx, 2); \
+static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \
+				show_temp23, store_temp23, idx, 4);
+
+sysfs_temp23(temp2,0)
+sysfs_temp23(temp3,1)
+
+#define device_create_file_temp_add(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \
+device_create_file(&client->dev, \
+&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \
+} while (0)
+
+
+/* get reatime status of all sensors items: voltage, temp, fan */
+static ssize_t
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%d\n", data->alarms);
+}
+
+static
+DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+#define device_create_file_alarms(client) \
+device_create_file(&client->dev, &dev_attr_alarms);
+
+
+
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1]));
+}
+
+static ssize_t
+show_pwmenable(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	long pwm_enable_tmp = 1;
+
+	switch (data->pwmenable[nr]) {
+	case 0:
+		pwm_enable_tmp = 1; /* manual mode */
+		break;
+	case 1:
+		pwm_enable_tmp = 3; /*thermal cruise/Smart Fan I */
+		break;
+	case 2:
+		pwm_enable_tmp = 2; /* Smart Fan II */
+		break;
+	}
+
+	return sprintf(buf, "%ld\n", pwm_enable_tmp);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->pwm[nr] = PWM_TO_REG(val);
+	w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]);
+
+	return count;
+}
+
+static ssize_t
+store_pwmenable(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp;
+
+	val = simple_strtoul(buf, NULL, 10);
+	switch (val) {
+	case 1:
+		data->pwmenable[nr] = 0; /* manual mode */
+		break;
+	case 2:
+		data->pwmenable[nr] = 2; /* Smart Fan II */
+		break;
+	case 3:
+		data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */
+		break;
+	default:
+		return -EINVAL;
+	}
+	cfg1_tmp = data->pwmenable[0];
+	cfg2_tmp = (data->pwmenable[1]) << 2;
+	cfg3_tmp = (data->pwmenable[2]) << 4;
+	cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
+	fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp;
+	w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp);
+
+	return count;
+}
+
+#define sysfs_pwm(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+				show_pwm, store_pwm, offset); \
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
+				show_pwmenable, store_pwmenable, offset); \
+
+sysfs_pwm(1);
+sysfs_pwm(2);
+sysfs_pwm(3);
+
+
+#define device_create_file_pwm(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \
+} while (0)
+
+#define device_create_file_pwmenable(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_pwm_mode(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%d\n", data->pwm_mode[nr-1]);
+}
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 pwm_mode_mask = 0;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1);
+	pwm_mode_mask = w83792d_read_value(client,
+		W83792D_REG_PWM[nr]) & 0x7f;
+	w83792d_write_value(client, W83792D_REG_PWM[nr],
+		((data->pwm_mode[nr]) << 7) | pwm_mode_mask);
+
+	return count;
+}
+
+#define sysfs_pwm_mode(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \
+				show_pwm_mode, store_pwm_mode, offset);
+
+sysfs_pwm_mode(1);
+sysfs_pwm_mode(2);
+sysfs_pwm_mode(3);
+
+#define device_create_file_pwm_mode(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_regs_chassis(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%d\n", data->chassis);
+}
+
+static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
+
+#define device_create_file_chassis(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis); \
+} while (0)
+
+
+static ssize_t
+show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%d\n", data->chassis_clear);
+}
+
+static ssize_t
+store_chassis_clear(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 temp1 = 0, temp2 = 0;
+
+	val = simple_strtoul(buf, NULL, 10);
+
+	data->chassis_clear = SENSORS_LIMIT(val, 0 ,1);
+	temp1 = ((data->chassis_clear) << 7) & 0x80;
+	temp2 = w83792d_read_value(client,
+		W83792D_REG_CHASSIS_CLR) & 0x7f;
+	w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2);
+
+	return count;
+}
+
+static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
+		show_chassis_clear, store_chassis_clear);
+
+#define device_create_file_chassis_clear(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis_clear); \
+} while (0)
+
+
+
+/* For Smart Fan I / Thermal Cruise */
+static ssize_t
+show_thermal_cruise(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%ld\n", (long)data->thermal_cruise[nr-1]);
+}
+
+static ssize_t
+store_thermal_cruise(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 target_tmp=0, target_mask=0;
+
+	val = simple_strtoul(buf, NULL, 10);
+	target_tmp = val;
+	target_tmp = target_tmp & 0x7f;
+	target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80;
+	data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255);
+	w83792d_write_value(client, W83792D_REG_THERMAL[nr],
+		(data->thermal_cruise[nr]) | target_mask);
+
+	return count;
+}
+
+#define sysfs_thermal_cruise(offset) \
+static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \
+			show_thermal_cruise, store_thermal_cruise, offset);
+
+sysfs_thermal_cruise(1);
+sysfs_thermal_cruise(2);
+sysfs_thermal_cruise(3);
+
+#define device_create_file_thermal_cruise(client, offset) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_thermal_cruise##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan I/Thermal Cruise and Smart Fan II */
+static ssize_t
+show_tolerance(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%ld\n", (long)data->tolerance[nr-1]);
+}
+
+static ssize_t
+store_tolerance(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 tol_tmp, tol_mask;
+
+	val = simple_strtoul(buf, NULL, 10);
+	tol_mask = w83792d_read_value(client,
+		W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0);
+	tol_tmp = SENSORS_LIMIT(val, 0, 15);
+	tol_tmp &= 0x0f;
+	data->tolerance[nr] = tol_tmp;
+	if (nr == 1) {
+		tol_tmp <<= 4;
+	}
+	w83792d_write_value(client, W83792D_REG_TOLERANCE[nr],
+		tol_mask | tol_tmp);
+
+	return count;
+}
+
+#define sysfs_tolerance(offset) \
+static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \
+				show_tolerance, store_tolerance, offset);
+
+sysfs_tolerance(1);
+sysfs_tolerance(2);
+sysfs_tolerance(3);
+
+#define device_create_file_tolerance(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan II */
+static ssize_t
+show_sf2_point(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%ld\n", (long)data->sf2_points[index-1][nr-1]);
+}
+
+static ssize_t
+store_sf2_point(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr - 1;
+	int index = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 mask_tmp = 0;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127);
+	mask_tmp = w83792d_read_value(client,
+					W83792D_REG_POINTS[index][nr]) & 0x80;
+	w83792d_write_value(client, W83792D_REG_POINTS[index][nr],
+		mask_tmp|data->sf2_points[index][nr]);
+
+	return count;
+}
+
+#define sysfs_sf2_point(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \
+				show_sf2_point, store_sf2_point, offset, index);
+
+sysfs_sf2_point(1, 1);	/* Fan1 */
+sysfs_sf2_point(2, 1);	/* Fan1 */
+sysfs_sf2_point(3, 1);	/* Fan1 */
+sysfs_sf2_point(4, 1);	/* Fan1 */
+sysfs_sf2_point(1, 2);	/* Fan2 */
+sysfs_sf2_point(2, 2);	/* Fan2 */
+sysfs_sf2_point(3, 2);	/* Fan2 */
+sysfs_sf2_point(4, 2);	/* Fan2 */
+sysfs_sf2_point(1, 3);	/* Fan3 */
+sysfs_sf2_point(2, 3);	/* Fan3 */
+sysfs_sf2_point(3, 3);	/* Fan3 */
+sysfs_sf2_point(4, 3);	/* Fan3 */
+
+#define device_create_file_sf2_point(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_sf2_level(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index;
+	struct w83792d_data *data = w83792d_update_device(dev);
+	return sprintf(buf, "%d\n",
+			(((data->sf2_levels[index-1][nr]) * 100) / 15));
+}
+
+static ssize_t
+store_sf2_level(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	int nr = sensor_attr->nr;
+	int index = sensor_attr->index - 1;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	u32 val;
+	u8 mask_tmp=0, level_tmp=0;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15);
+	mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr])
+		& ((nr==3) ? 0xf0 : 0x0f);
+	if (nr==3) {
+		level_tmp = data->sf2_levels[index][nr];
+	} else {
+		level_tmp = data->sf2_levels[index][nr] << 4;
+	}
+	w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp);
+
+	return count;
+}
+
+#define sysfs_sf2_level(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \
+				show_sf2_level, store_sf2_level, offset, index);
+
+sysfs_sf2_level(1, 1);	/* Fan1 */
+sysfs_sf2_level(2, 1);	/* Fan1 */
+sysfs_sf2_level(3, 1);	/* Fan1 */
+sysfs_sf2_level(1, 2);	/* Fan2 */
+sysfs_sf2_level(2, 2);	/* Fan2 */
+sysfs_sf2_level(3, 2);	/* Fan2 */
+sysfs_sf2_level(1, 3);	/* Fan3 */
+sysfs_sf2_level(2, 3);	/* Fan3 */
+sysfs_sf2_level(3, 3);	/* Fan3 */
+
+#define device_create_file_sf2_level(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+/* This function is called when:
+     * w83792d_driver is inserted (when this module is loaded), for each
+       available adapter
+     * when a new adapter is inserted (and w83792d_driver is still present) */
+static int
+w83792d_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, w83792d_detect);
+}
+
+
+static int
+w83792d_create_subclient(struct i2c_adapter *adapter,
+				struct i2c_client *new_client, int addr,
+				struct i2c_client **sub_cli)
+{
+	int err;
+	struct i2c_client *sub_client;
+
+	(*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (!(sub_client)) {
+		return -ENOMEM;
+	}
+	memset(sub_client, 0x00, sizeof(struct i2c_client));
+	sub_client->addr = 0x48 + addr;
+	i2c_set_clientdata(sub_client, NULL);
+	sub_client->adapter = adapter;
+	sub_client->driver = &w83792d_driver;
+	sub_client->flags = 0;
+	strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE);
+	if ((err = i2c_attach_client(sub_client))) {
+		dev_err(&new_client->dev, "subclient registration "
+			"at address 0x%x failed\n", sub_client->addr);
+		kfree(sub_client);
+		return err;
+	}
+	return 0;
+}
+
+
+static int
+w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
+		struct i2c_client *new_client)
+{
+	int i, id, err;
+	u8 val;
+	struct w83792d_data *data = i2c_get_clientdata(new_client);
+
+	id = i2c_adapter_id(adapter);
+	if (force_subclients[0] == id && force_subclients[1] == address) {
+		for (i = 2; i <= 3; i++) {
+			if (force_subclients[i] < 0x48 ||
+			    force_subclients[i] > 0x4f) {
+				dev_err(&new_client->dev, "invalid subclient "
+					"address %d; must be 0x48-0x4f\n",
+					force_subclients[i]);
+				err = -ENODEV;
+				goto ERROR_SC_0;
+			}
+		}
+		w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR,
+					(force_subclients[2] & 0x07) |
+					((force_subclients[3] & 0x07) << 4));
+	}
+
+	val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
+	if (!(val & 0x08)) {
+		err = w83792d_create_subclient(adapter, new_client, val & 0x7,
+						&data->lm75[0]);
+		if (err < 0)
+			goto ERROR_SC_0;
+	}
+	if (!(val & 0x80)) {
+		if ((data->lm75[0] != NULL) &&
+			((val & 0x7) == ((val >> 4) & 0x7))) {
+			dev_err(&new_client->dev, "duplicate addresses 0x%x, "
+				"use force_subclient\n", data->lm75[0]->addr);
+			err = -ENODEV;
+			goto ERROR_SC_1;
+		}
+		err = w83792d_create_subclient(adapter, new_client,
+						(val >> 4) & 0x7, &data->lm75[1]);
+		if (err < 0)
+			goto ERROR_SC_1;
+	}
+
+	return 0;
+
+/* Undo inits in case of errors */
+
+ERROR_SC_1:
+	if (data->lm75[0] != NULL) {
+		i2c_detach_client(data->lm75[0]);
+		kfree(data->lm75[0]);
+	}
+ERROR_SC_0:
+	return err;
+}
+
+
+static int
+w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	int i = 0, val1 = 0, val2;
+	struct i2c_client *new_client;
+	struct w83792d_data *data;
+	int err = 0;
+	const char *client_name = "";
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		goto ERROR0;
+	}
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access w83792d_{read,write}_value. */
+
+	if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto ERROR0;
+	}
+	memset(data, 0, sizeof(struct w83792d_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	init_MUTEX(&data->lock);
+	new_client->adapter = adapter;
+	new_client->driver = &w83792d_driver;
+	new_client->flags = 0;
+
+	/* Now, we do the remaining detection. */
+
+	/* The w83792d may be stuck in some other bank than bank 0. This may
+	   make reading other information impossible. Specify a force=... or
+	   force_*=... parameter, and the Winbond will be reset to the right
+	   bank. */
+	if (kind < 0) {
+		if (w83792d_read_value(new_client, W83792D_REG_CONFIG) & 0x80) {
+			dev_warn(&new_client->dev, "Detection failed at step "
+				"3\n");
+			goto ERROR1;
+		}
+		val1 = w83792d_read_value(new_client, W83792D_REG_BANK);
+		val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
+		/* Check for Winbond ID if in bank 0 */
+		if (!(val1 & 0x07)) {  /* is Bank0 */
+			if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
+			     ((val1 & 0x80) && (val2 != 0x5c))) {
+				goto ERROR1;
+			}
+		}
+		/* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
+		   should match */
+		if (w83792d_read_value(new_client,
+					W83792D_REG_I2C_ADDR) != address) {
+			dev_warn(&new_client->dev, "Detection failed "
+				"at step 5\n");
+			goto ERROR1;
+		}
+	}
+
+	/* We have either had a force parameter, or we have already detected the
+	   Winbond. Put it now into bank 0 and Vendor ID High Byte */
+	w83792d_write_value(new_client,
+			    W83792D_REG_BANK,
+			    (w83792d_read_value(new_client,
+				W83792D_REG_BANK) & 0x78) | 0x80);
+
+	/* Determine the chip type. */
+	if (kind <= 0) {
+		/* get vendor ID */
+		val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
+		if (val2 != 0x5c) {  /* the vendor is NOT Winbond */
+			goto ERROR1;
+		}
+		val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
+		if (val1 == 0x7a && address >= 0x2c) {
+			kind = w83792d;
+		} else {
+			if (kind == 0)
+					dev_warn(&new_client->dev,
+					"w83792d: Ignoring 'force' parameter for"
+					" unknown chip at adapter %d, address"
+					" 0x%02x\n", i2c_adapter_id(adapter),
+					address);
+			goto ERROR1;
+		}
+	}
+
+	if (kind == w83792d) {
+		client_name = "w83792d";
+	} else {
+		dev_err(&new_client->dev, "w83792d: Internal error: unknown"
+					  " kind (%d)?!?", kind);
+		goto ERROR1;
+	}
+
+	/* Fill in the remaining client fields and put into the global list */
+	strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+	data->type = kind;
+
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto ERROR1;
+
+	if ((err = w83792d_detect_subclients(adapter, address,
+			kind, new_client)))
+		goto ERROR2;
+
+	/* Initialize the chip */
+	w83792d_init_client(new_client);
+
+	/* A few vars need to be filled upon startup */
+	for (i = 1; i <= 7; i++) {
+		data->fan_min[i - 1] = w83792d_read_value(new_client,
+					W83792D_REG_FAN_MIN[i]);
+	}
+
+	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto ERROR3;
+	}
+	device_create_file_in(new_client, 0);
+	device_create_file_in(new_client, 1);
+	device_create_file_in(new_client, 2);
+	device_create_file_in(new_client, 3);
+	device_create_file_in(new_client, 4);
+	device_create_file_in(new_client, 5);
+	device_create_file_in(new_client, 6);
+	device_create_file_in(new_client, 7);
+	device_create_file_in(new_client, 8);
+
+	device_create_file_fan(new_client, 1);
+	device_create_file_fan(new_client, 2);
+	device_create_file_fan(new_client, 3);
+	device_create_file_fan(new_client, 4);
+	device_create_file_fan(new_client, 5);
+	device_create_file_fan(new_client, 6);
+	device_create_file_fan(new_client, 7);
+
+	device_create_file_temp1(new_client);		/* Temp1 */
+	device_create_file_temp_add(new_client, 2);	/* Temp2 */
+	device_create_file_temp_add(new_client, 3);	/* Temp3 */
+
+	device_create_file_alarms(new_client);
+
+	device_create_file_pwm(new_client, 1);
+	device_create_file_pwm(new_client, 2);
+	device_create_file_pwm(new_client, 3);
+
+	device_create_file_pwmenable(new_client, 1);
+	device_create_file_pwmenable(new_client, 2);
+	device_create_file_pwmenable(new_client, 3);
+
+	device_create_file_pwm_mode(new_client, 1);
+	device_create_file_pwm_mode(new_client, 2);
+	device_create_file_pwm_mode(new_client, 3);
+
+	device_create_file_chassis(new_client);
+	device_create_file_chassis_clear(new_client);
+
+	device_create_file_thermal_cruise(new_client, 1);
+	device_create_file_thermal_cruise(new_client, 2);
+	device_create_file_thermal_cruise(new_client, 3);
+
+	device_create_file_tolerance(new_client, 1);
+	device_create_file_tolerance(new_client, 2);
+	device_create_file_tolerance(new_client, 3);
+
+	device_create_file_sf2_point(new_client, 1, 1);	/* Fan1 */
+	device_create_file_sf2_point(new_client, 2, 1);	/* Fan1 */
+	device_create_file_sf2_point(new_client, 3, 1);	/* Fan1 */
+	device_create_file_sf2_point(new_client, 4, 1);	/* Fan1 */
+	device_create_file_sf2_point(new_client, 1, 2);	/* Fan2 */
+	device_create_file_sf2_point(new_client, 2, 2);	/* Fan2 */
+	device_create_file_sf2_point(new_client, 3, 2);	/* Fan2 */
+	device_create_file_sf2_point(new_client, 4, 2);	/* Fan2 */
+	device_create_file_sf2_point(new_client, 1, 3);	/* Fan3 */
+	device_create_file_sf2_point(new_client, 2, 3);	/* Fan3 */
+	device_create_file_sf2_point(new_client, 3, 3);	/* Fan3 */
+	device_create_file_sf2_point(new_client, 4, 3);	/* Fan3 */
+
+	device_create_file_sf2_level(new_client, 1, 1);	/* Fan1 */
+	device_create_file_sf2_level(new_client, 2, 1);	/* Fan1 */
+	device_create_file_sf2_level(new_client, 3, 1);	/* Fan1 */
+	device_create_file_sf2_level(new_client, 1, 2);	/* Fan2 */
+	device_create_file_sf2_level(new_client, 2, 2);	/* Fan2 */
+	device_create_file_sf2_level(new_client, 3, 2);	/* Fan2 */
+	device_create_file_sf2_level(new_client, 1, 3);	/* Fan3 */
+	device_create_file_sf2_level(new_client, 2, 3);	/* Fan3 */
+	device_create_file_sf2_level(new_client, 3, 3);	/* Fan3 */
+
+	return 0;
+
+ERROR3:
+	if (data->lm75[0] != NULL) {
+		i2c_detach_client(data->lm75[0]);
+		kfree(data->lm75[0]);
+	}
+	if (data->lm75[1] != NULL) {
+		i2c_detach_client(data->lm75[1]);
+		kfree(data->lm75[1]);
+	}
+ERROR2:
+	i2c_detach_client(new_client);
+ERROR1:
+	kfree(data);
+ERROR0:
+	return err;
+}
+
+static int
+w83792d_detach_client(struct i2c_client *client)
+{
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	int err;
+
+	/* main client */
+	if (data)
+		hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	/* main client */
+	if (data)
+		kfree(data);
+	/* subclient */
+	else
+		kfree(client);
+
+	return 0;
+}
+
+/* The SMBus locks itself, usually, but nothing may access the Winbond between
+   bank switches. ISA access must always be locked explicitly!
+   We ignore the W83792D BUSY flag at this moment - it could lead to deadlocks,
+   would slow down the W83792D access and should not be necessary.
+   There are some ugly typecasts here, but the good news is - they should
+   nowhere else be necessary! */
+static int
+w83792d_read_value(struct i2c_client *client, u8 reg)
+{
+	int res=0;
+	res = i2c_smbus_read_byte_data(client, reg);
+
+	return res;
+}
+
+static int
+w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	i2c_smbus_write_byte_data(client, reg,  value);
+	return 0;
+}
+
+/* Called when we have found a new W83792D. It should set limits, etc. */
+static void
+w83792d_init_client(struct i2c_client *client)
+{
+	u8 temp2_cfg, temp3_cfg, vid_in_b;
+
+	if (init) {
+		w83792d_write_value(client, W83792D_REG_CONFIG, 0x80);
+	}
+	/* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0):
+	   W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of
+	     vin0/vin1 can be modified by user;
+	   W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of
+	     vin0/vin1 auto-updated, can NOT be modified by user. */
+	vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B);
+	w83792d_write_value(client, W83792D_REG_VID_IN_B,
+			    vid_in_b & 0xbf);
+
+	temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP2_CONFIG);
+	temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP3_CONFIG);
+	w83792d_write_value(client, W83792D_REG_TEMP2_CONFIG,
+				temp2_cfg & 0xe6);
+	w83792d_write_value(client, W83792D_REG_TEMP3_CONFIG,
+				temp3_cfg & 0xe6);
+
+	/* Start monitoring */
+	w83792d_write_value(client, W83792D_REG_CONFIG,
+			    (w83792d_read_value(client,
+						W83792D_REG_CONFIG) & 0xf7)
+			    | 0x01);
+}
+
+static struct w83792d_data *w83792d_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83792d_data *data = i2c_get_clientdata(client);
+	int i, j;
+	u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
+
+	down(&data->update_lock);
+
+	if (time_after
+	    (jiffies - data->last_updated, (unsigned long) (HZ * 3))
+	    || time_before(jiffies, data->last_updated) || !data->valid) {
+		dev_dbg(dev, "Starting device update\n");
+
+		/* Update the voltages measured value and limits */
+		for (i = 0; i < 9; i++) {
+			data->in[i] = w83792d_read_value(client,
+						W83792D_REG_IN[i]);
+			data->in_max[i] = w83792d_read_value(client,
+						W83792D_REG_IN_MAX[i]);
+			data->in_min[i] = w83792d_read_value(client,
+						W83792D_REG_IN_MIN[i]);
+		}
+		data->low_bits[0] = w83792d_read_value(client,
+						W83792D_REG_LOW_BITS1);
+		data->low_bits[1] = w83792d_read_value(client,
+						W83792D_REG_LOW_BITS2);
+		for (i = 0; i < 7; i++) {
+			/* Update the Fan measured value and limits */
+			data->fan[i] = w83792d_read_value(client,
+						W83792D_REG_FAN[i]);
+			data->fan_min[i] = w83792d_read_value(client,
+						W83792D_REG_FAN_MIN[i]);
+			/* Update the PWM/DC Value and PWM/DC flag */
+			pwm_array_tmp[i] = w83792d_read_value(client,
+						W83792D_REG_PWM[i]);
+			data->pwm[i] = pwm_array_tmp[i] & 0x0f;
+			data->pwm_mode[i] = (pwm_array_tmp[i] >> 7) & 0x01;
+		}
+
+		reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
+		data->pwmenable[0] = reg_tmp & 0x03;
+		data->pwmenable[1] = (reg_tmp>>2) & 0x03;
+		data->pwmenable[2] = (reg_tmp>>4) & 0x03;
+
+		for (i = 0; i < 3; i++) {
+			data->temp1[i] = w83792d_read_value(client,
+							W83792D_REG_TEMP1[i]);
+		}
+		for (i = 0; i < 2; i++) {
+			for (j = 0; j < 6; j++) {
+				data->temp_add[i][j] = w83792d_read_value(
+					client,W83792D_REG_TEMP_ADD[i][j]);
+			}
+		}
+
+		/* Update the Fan Divisor */
+		for (i = 0; i < 4; i++) {
+			reg_array_tmp[i] = w83792d_read_value(client,
+							W83792D_REG_FAN_DIV[i]);
+		}
+		data->fan_div[0] = reg_array_tmp[0] & 0x07;
+		data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07;
+		data->fan_div[2] = reg_array_tmp[1] & 0x07;
+		data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07;
+		data->fan_div[4] = reg_array_tmp[2] & 0x07;
+		data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07;
+		data->fan_div[6] = reg_array_tmp[3] & 0x07;
+
+		/* Update the realtime status */
+		data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) +
+			(w83792d_read_value(client, W83792D_REG_ALARM2) << 8) +
+			(w83792d_read_value(client, W83792D_REG_ALARM3) << 16);
+
+		/* Update CaseOpen status and it's CLR_CHS. */
+		data->chassis = (w83792d_read_value(client,
+			W83792D_REG_CHASSIS) >> 5) & 0x01;
+		data->chassis_clear = (w83792d_read_value(client,
+			W83792D_REG_CHASSIS_CLR) >> 7) & 0x01;
+
+		/* Update Thermal Cruise/Smart Fan I target value */
+		for (i = 0; i < 3; i++) {
+			data->thermal_cruise[i] =
+				w83792d_read_value(client,
+				W83792D_REG_THERMAL[i]) & 0x7f;
+		}
+
+		/* Update Smart Fan I/II tolerance */
+		reg_tmp = w83792d_read_value(client, W83792D_REG_TOLERANCE[0]);
+		data->tolerance[0] = reg_tmp & 0x0f;
+		data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
+		data->tolerance[2] = w83792d_read_value(client,
+					W83792D_REG_TOLERANCE[2]) & 0x0f;
+
+		/* Update Smart Fan II temperature points */
+		for (i = 0; i < 3; i++) {
+			for (j = 0; j < 4; j++) {
+				data->sf2_points[i][j] = w83792d_read_value(
+					client,W83792D_REG_POINTS[i][j]) & 0x7f;
+			}
+		}
+
+		/* Update Smart Fan II duty cycle levels */
+		for (i = 0; i < 3; i++) {
+			reg_tmp = w83792d_read_value(client,
+						W83792D_REG_LEVELS[i][0]);
+			data->sf2_levels[i][0] = reg_tmp & 0x0f;
+			data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f;
+			reg_tmp = w83792d_read_value(client,
+						W83792D_REG_LEVELS[i][2]);
+			data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f;
+			data->sf2_levels[i][3] = reg_tmp & 0x0f;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+#ifdef DEBUG
+	w83792d_print_debug(data, dev);
+#endif
+
+	return data;
+}
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
+{
+	int i=0, j=0;
+	dev_dbg(dev, "==========The following is the debug message...========\n");
+	dev_dbg(dev, "9 set of Voltages: =====>\n");
+	for (i=0; i<9; i++) {
+		dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]);
+		dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
+		dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
+	}
+	dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits[0]);
+	dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits[1]);
+	dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n");
+	for (i=0; i<7; i++) {
+		dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
+		dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
+		dev_dbg(dev, "pwm[%d]     is: 0x%x\n", i, data->pwm[i]);
+		dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]);
+	}
+	dev_dbg(dev, "3 set of Temperatures: =====>\n");
+	for (i=0; i<3; i++) {
+		dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]);
+	}
+
+	for (i=0; i<2; i++) {
+		for (j=0; j<6; j++) {
+			dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j,
+							data->temp_add[i][j]);
+		}
+	}
+
+	for (i=0; i<7; i++) {
+		dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]);
+	}
+	dev_dbg(dev, "==========End of the debug message...==================\n");
+	dev_dbg(dev, "\n");
+}
+#endif
+
+static int __init
+sensors_w83792d_init(void)
+{
+	return i2c_add_driver(&w83792d_driver);
+}
+
+static void __exit
+sensors_w83792d_exit(void)
+{
+	i2c_del_driver(&w83792d_driver);
+}
+
+MODULE_AUTHOR("Chunhao Huang @ Winbond <DZShen@Winbond.com.tw>");
+MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83792d_init);
+module_exit(sensors_w83792d_exit);
+
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 4469d52..133e34a 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -36,7 +36,8 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* How many retries on register read error */
 #define MAX_RETRIES	5
@@ -47,13 +48,12 @@
  */
 
 static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(w83l785ts);
+I2C_CLIENT_INSMOD_1(w83l785ts);
 
 /*
  * The W83L785TS-S registers
@@ -105,6 +105,7 @@
 
 struct w83l785ts_data {
 	struct i2c_client client;
+	struct class_device *class_dev;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -140,7 +141,7 @@
 {
 	if (!(adapter->class & I2C_CLASS_HWMON))
 		return 0;
-	return i2c_detect(adapter, &addr_data, w83l785ts_detect);
+	return i2c_probe(adapter, &addr_data, w83l785ts_detect);
 }
 
 /*
@@ -239,11 +240,19 @@
 	 */
 
 	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
 	device_create_file(&new_client->dev, &dev_attr_temp1_input);
 	device_create_file(&new_client->dev, &dev_attr_temp1_max);
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_free:
 	kfree(data);
 exit:
@@ -252,15 +261,15 @@
 
 static int w83l785ts_detach_client(struct i2c_client *client)
 {
+	struct w83l785ts_data *data = i2c_get_clientdata(client);
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
-		return err;
-	}
+	hwmon_device_unregister(data->class_dev);
 
-	kfree(i2c_get_clientdata(client));
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index cd17039..71c5a85 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -4,12 +4,8 @@
 
 obj-$(CONFIG_I2C)		+= i2c-core.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
-obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
 obj-y				+= busses/ chips/ algos/
 
-i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
-
-
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index fb5b732..df05df1 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -519,8 +519,6 @@
 /* -----exported algorithm data: -------------------------------------	*/
 
 static struct i2c_algorithm i2c_bit_algo = {
-	.name		= "Bit-shift algorithm",
-	.id		= I2C_ALGO_BIT,
 	.master_xfer	= bit_xfer,
 	.functionality	= bit_func,
 };
@@ -541,8 +539,6 @@
 	DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
 
 	/* register new adapter to i2c module... */
-
-	adap->id |= i2c_bit_algo.id;
 	adap->algo = &i2c_bit_algo;
 
 	adap->timeout = 100;	/* default values, should	*/
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index e6cae39..2db7bfc 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -713,8 +713,6 @@
 /* -----exported algorithm data: -------------------------------------	*/
 
 static struct i2c_algorithm iic_algo = {
-	.name		= "ITE IIC algorithm",
-	.id		= I2C_ALGO_IIC,
 	.master_xfer	= iic_xfer,
 	.algo_control	= algo_control, /* ioctl */
 	.functionality	= iic_func,
@@ -738,8 +736,6 @@
 	            adap->name));
 
 	/* register new adapter to i2c module... */
-
-	adap->id |= iic_algo.id;
 	adap->algo = &iic_algo;
 
 	adap->timeout = 100;	/* default values, should	*/
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index cc3a952..beb10ed 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -187,12 +187,14 @@
 	int numbytes = 0;
 	int state;
 	int ret;
+	int timeout = 100;
 
-	state = pca_status(adap);
-	if ( state != 0xF8 ) {
-		dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state );
-		/* FIXME: what to do. Force stop ? */
-		return -EREMOTEIO;
+	while ((state = pca_status(adap)) != 0xf8 && timeout--) {
+		msleep(10);
+	}
+	if (state != 0xf8) {
+		dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
+		return -EIO;
 	}
 
 	DEB1("{{{ XFER %d messages\n", num);
@@ -354,8 +356,6 @@
 }
 
 static struct i2c_algorithm pca_algo = {
-	.name		= "PCA9564 algorithm",
-	.id		= I2C_ALGO_PCA,
 	.master_xfer	= pca_xfer,
 	.functionality	= pca_func,
 };
@@ -369,8 +369,6 @@
 	int rval;
 
 	/* register new adapter to i2c module... */
-
-	adap->id |= pca_algo.id;
 	adap->algo = &pca_algo;
 
 	adap->timeout = 100;		/* default values, should	*/
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 8d087da..6e498df 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -459,8 +459,6 @@
 /* -----exported algorithm data: -------------------------------------	*/
 
 static struct i2c_algorithm pcf_algo = {
-	.name		= "PCF8584 algorithm",
-	.id		= I2C_ALGO_PCF,
 	.master_xfer	= pcf_xfer,
 	.functionality	= pcf_func,
 };
@@ -476,8 +474,6 @@
 	DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
 
 	/* register new adapter to i2c module... */
-
-	adap->id |= pcf_algo.id;
 	adap->algo = &pcf_algo;
 
 	adap->timeout = 100;		/* default values, should	*/
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
index 422721b..932c4fa 100644
--- a/drivers/i2c/algos/i2c-algo-sgi.c
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -149,7 +149,7 @@
 			err = i2c_write(adap, p->buf, p->len);
 	}
 
-	return err;
+	return (err < 0) ? err : i;
 }
 
 static u32 sgi_func(struct i2c_adapter *adap)
@@ -158,8 +158,6 @@
 }
 
 static struct i2c_algorithm sgi_algo = {
-	.name		= "SGI algorithm",
-	.id		= I2C_ALGO_SGI,
 	.master_xfer	= sgi_xfer,
 	.functionality	= sgi_func,
 };
@@ -169,7 +167,6 @@
  */
 int i2c_sgi_add_bus(struct i2c_adapter *adap)
 {
-	adap->id |= sgi_algo.id;
 	adap->algo = &sgi_algo;
 
 	return i2c_add_adapter(adap);
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index f278549..8ed5ad1 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -135,8 +135,6 @@
 /* -----exported algorithm data: -------------------------------------	*/
 
 static struct i2c_algorithm i2c_sibyte_algo = {
-	.name		= "SiByte algorithm",
-	.id		= I2C_ALGO_SIBYTE,
 	.smbus_xfer	= smbus_xfer,
 	.algo_control	= algo_control, /* ioctl */
 	.functionality	= bit_func,
@@ -151,8 +149,6 @@
 	struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
 
 	/* register new adapter to i2c module... */
-
-	i2c_adap->id |= i2c_sibyte_algo.id;
 	i2c_adap->algo = &i2c_sibyte_algo;
         
         /* Set the frequency to 100 kHz */
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 916ba5e..6e9da13 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -182,14 +182,8 @@
 	  will be called i2c-iop3xx.
 
 config I2C_ISA
-	tristate "ISA Bus support"
+	tristate
 	depends on I2C
-	help
-	  If you say yes to this option, support will be included for i2c
-	  interfaces that are on the ISA bus.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called i2c-isa.
 
 config I2C_ITE
 	tristate "ITE I2C Adapter"
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index f634a07..f021acd 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -472,8 +472,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-i2c SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= ali1535_access,
 	.functionality	= ali1535_func,
 };
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index fdd881a..8694750 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -366,8 +366,6 @@
 }
 
 static struct i2c_algorithm ali1563_algorithm = {
-	.name		= "Non-i2c SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= ali1563_access,
 	.functionality	= ali1563_func,
 };
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 0f781a1..b3f50bf 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -462,8 +462,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= ali15x3_access,
 	.functionality	= ali15x3_func,
 };
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 6347ebc..6ad0603 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -295,8 +295,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= amd756_access,
 	.functionality	= amd756_func,
 };
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index d664448..45ea24b 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -323,8 +323,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name = "Non-I2C SMBus 2.0 adapter",
-	.id = I2C_ALGO_SMBUS,
 	.smbus_xfer = amd8111_access,
 	.functionality = amd8111_func,
 };
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index a7ff112..d06edce 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -283,8 +283,6 @@
 }
 
 static struct i2c_algorithm au1550_algo = {
-	.name		= "Au1550 algorithm",
-	.id		= I2C_ALGO_AU1550,
 	.master_xfer	= au1550_xfer,
 	.functionality	= au1550_func,
 };
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 1ab4131..709beab 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -535,8 +535,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= i801_access,
 	.functionality	= i801_func,
 };
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 93ca36d..a3ed959 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -627,8 +627,6 @@
 }
 
 static struct i2c_algorithm iic_algo = {
-	.name 		= "IBM IIC algorithm",
-	.id   		= I2C_ALGO_OCP,
 	.master_xfer 	= iic_xfer,
 	.functionality	= iic_func
 };
@@ -727,7 +725,7 @@
 	adap = &dev->adap;
 	strcpy(adap->name, "IBM IIC");
 	i2c_set_adapdata(adap, dev);
-	adap->id = I2C_HW_OCP | iic_algo.id;
+	adap->id = I2C_HW_OCP;
 	adap->algo = &iic_algo;
 	adap->client_register = NULL;
 	adap->client_unregister = NULL;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 6b682e9..7bd9102 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -399,8 +399,6 @@
 }
 
 static struct i2c_algorithm iop3xx_i2c_algo = {
-	.name		= "IOP3xx I2C algorithm",
-	.id		= I2C_ALGO_IOP3XX,
 	.master_xfer	= iop3xx_i2c_master_xfer,
 	.algo_control	= iop3xx_i2c_algo_control,
 	.functionality	= iop3xx_i2c_func,
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 00e7f71..bdc6806 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -1,6 +1,8 @@
 /*
-    i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware
-            monitoring
+    i2c-isa.c - an i2c-core-like thing for ISA hardware monitoring chips
+    Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+
+    Based on the i2c-isa pseudo-adapter from the lm_sensors project
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
 
     This program is free software; you can redistribute it and/or modify
@@ -18,30 +20,36 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* This implements an i2c algorithm/adapter for ISA bus. Not that this is
-   on first sight very useful; almost no functionality is preserved.
-   Except that it makes writing drivers for chips which can be on both
-   the SMBus and the ISA bus very much easier. See lm78.c for an example
-   of this. */
+/* This implements an i2c-core-like thing for ISA hardware monitoring
+   chips. Such chips are linked to the i2c subsystem for historical
+   reasons (because the early ISA hardware monitoring chips such as the
+   LM78 had both an I2C and an ISA interface). They used to be
+   registered with the main i2c-core, but as a first step in the
+   direction of a clean separation between I2C and ISA chip drivers,
+   we now have this separate core for ISA ones. It is significantly
+   more simple than the real one, of course, because we don't have to
+   handle multiple busses: there is only one (fake) ISA adapter.
+   It is worth noting that we still rely on i2c-core for some things
+   at the moment - but hopefully this won't last. */
 
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
+#include <linux/i2c-isa.h>
 
 static u32 isa_func(struct i2c_adapter *adapter);
 
 /* This is the actual algorithm we define */
 static struct i2c_algorithm isa_algorithm = {
-	.name		= "ISA bus algorithm",
-	.id		= I2C_ALGO_ISA,
 	.functionality	= isa_func,
 };
 
 /* There can only be one... */
 static struct i2c_adapter isa_adapter = {
 	.owner		= THIS_MODULE,
+	.id		= I2C_HW_ISA,
 	.class          = I2C_CLASS_HWMON,
 	.algo		= &isa_algorithm,
 	.name		= "ISA main adapter",
@@ -53,17 +61,146 @@
 	return 0;
 }
 
+
+/* Copied from i2c-core */
+static ssize_t show_adapter_name(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
+	return sprintf(buf, "%s\n", adap->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
+
+static int i2c_isa_device_probe(struct device *dev)
+{
+	return -ENODEV;
+}
+
+static int i2c_isa_device_remove(struct device *dev)
+{
+	return 0;
+}
+
+
+/* We implement an interface which resembles i2c_{add,del}_driver,
+   but for i2c-isa drivers. We don't have to remember and handle lists
+   of drivers and adapters so this is much more simple, of course. */
+
+int i2c_isa_add_driver(struct i2c_driver *driver)
+{
+	int res;
+
+	/* Add the driver to the list of i2c drivers in the driver core */
+	driver->driver.name = driver->name;
+	driver->driver.bus = &i2c_bus_type;
+	driver->driver.probe = i2c_isa_device_probe;
+	driver->driver.remove = i2c_isa_device_remove;
+	res = driver_register(&driver->driver);
+	if (res)
+		return res;
+	dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->name);
+
+	/* Now look for clients */
+	driver->attach_adapter(&isa_adapter);
+
+	return 0;
+}
+
+int i2c_isa_del_driver(struct i2c_driver *driver)
+{
+	struct list_head *item, *_n;
+	struct i2c_client *client;
+	int res;
+
+	/* Detach all clients belonging to this one driver */
+	list_for_each_safe(item, _n, &isa_adapter.clients) {
+		client = list_entry(item, struct i2c_client, list);
+		if (client->driver != driver)
+			continue;
+		dev_dbg(&isa_adapter.dev, "Detaching client %s at 0x%x\n",
+			client->name, client->addr);
+		if ((res = driver->detach_client(client))) {
+			dev_err(&isa_adapter.dev, "Failed, driver "
+				"%s not unregistered!\n",
+				driver->name);
+			return res;
+		}
+	}
+
+	/* Get the driver off the core list */
+	driver_unregister(&driver->driver);
+	dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->name);
+
+	return 0;
+}
+
+
 static int __init i2c_isa_init(void)
 {
-	return i2c_add_adapter(&isa_adapter);
+	init_MUTEX(&isa_adapter.clist_lock);
+	INIT_LIST_HEAD(&isa_adapter.clients);
+
+	isa_adapter.nr = ANY_I2C_ISA_BUS;
+	isa_adapter.dev.parent = &platform_bus;
+	sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
+	isa_adapter.dev.driver = &i2c_adapter_driver;
+	isa_adapter.dev.release = &i2c_adapter_dev_release;
+	device_register(&isa_adapter.dev);
+	device_create_file(&isa_adapter.dev, &dev_attr_name);
+
+	/* Add this adapter to the i2c_adapter class */
+	memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
+	isa_adapter.class_dev.dev = &isa_adapter.dev;
+	isa_adapter.class_dev.class = &i2c_adapter_class;
+	strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
+		BUS_ID_SIZE);
+	class_device_register(&isa_adapter.class_dev);
+
+	dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
+
+	return 0;
 }
 
 static void __exit i2c_isa_exit(void)
 {
-	i2c_del_adapter(&isa_adapter);
+#ifdef DEBUG
+	struct list_head  *item, *_n;
+	struct i2c_client *client = NULL;
+#endif
+
+	/* There should be no more active client */
+#ifdef DEBUG
+	dev_dbg(&isa_adapter.dev, "Looking for clients\n");
+	list_for_each_safe(item, _n, &isa_adapter.clients) {
+		client = list_entry(item, struct i2c_client, list);
+		dev_err(&isa_adapter.dev, "Driver %s still has an active "
+			"ISA client at 0x%x\n", client->driver->name,
+			client->addr);
+	}
+	if (client != NULL)
+		return;
+#endif
+
+	/* Clean up the sysfs representation */
+	dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
+	init_completion(&isa_adapter.dev_released);
+	init_completion(&isa_adapter.class_dev_released);
+	class_device_unregister(&isa_adapter.class_dev);
+	device_remove_file(&isa_adapter.dev, &dev_attr_name);
+	device_unregister(&isa_adapter.dev);
+
+	/* Wait for sysfs to drop all references */
+	dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
+	wait_for_completion(&isa_adapter.dev_released);
+	wait_for_completion(&isa_adapter.class_dev_released);
+
+	dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
 }
 
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+EXPORT_SYMBOL(i2c_isa_add_driver);
+EXPORT_SYMBOL(i2c_isa_del_driver);
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("ISA bus access through i2c");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 94ae808..37b49c2 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -87,12 +87,9 @@
 };
 #endif /* DEBUG */
 
-static int probe;
-
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
 MODULE_LICENSE("GPL");
-module_param(probe, bool, 0);
 
 #ifdef POLLED_MODE
 /* Don't schedule, the g5 fan controller is too
@@ -498,8 +495,6 @@
 
 /* For now, we only handle combined mode (smbus) */
 static struct i2c_algorithm keywest_algorithm = {
-	.name		= "Keywest i2c",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= keywest_smbus_xfer,
 	.master_xfer	= keywest_xfer,
 	.functionality	= keywest_func,
@@ -621,7 +616,6 @@
 		sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
 		chan->iface = iface;
 		chan->chan_no = i;
-		chan->adapter.id = I2C_ALGO_SMBUS;
 		chan->adapter.algo = &keywest_algorithm;
 		chan->adapter.algo_data = NULL;
 		chan->adapter.client_register = NULL;
@@ -635,15 +629,6 @@
 				chan->adapter.name);
 			i2c_set_adapdata(&chan->adapter, NULL);
 		}
-		if (probe) {
-			printk("Probe: ");
-			for (addr = 0x00; addr <= 0x7f; addr++) {
-				if (i2c_smbus_xfer(&chan->adapter,addr,
-				    0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
-					printk("%02x ", addr);
-			}
-			printk("\n");
-		}
 	}
 
 	printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 9ad3e92..f065583 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -272,8 +272,6 @@
 }
 
 static struct i2c_algorithm mpc_algo = {
-	.name = "MPC algorithm",
-	.id = I2C_ALGO_MPC107,
 	.master_xfer = mpc_xfer,
 	.functionality = mpc_functionality,
 };
@@ -281,7 +279,7 @@
 static struct i2c_adapter mpc_ops = {
 	.owner = THIS_MODULE,
 	.name = "MPC adapter",
-	.id = I2C_ALGO_MPC107 | I2C_HW_MPC107,
+	.id = I2C_HW_MPC107,
 	.algo = &mpc_algo,
 	.class = I2C_CLASS_HWMON,
 	.timeout = 1,
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 5b85278..99abca4 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -423,18 +423,16 @@
 mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 {
 	struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
-	int	i, rc = 0;
+	int	i, rc;
 
 	for (i=0; i<num; i++)
-		if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) != 0)
-			break;
+		if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) < 0)
+			return rc;
 
-	return rc;
+	return num;
 }
 
 static struct i2c_algorithm mv64xxx_i2c_algo = {
-	.name = MV64XXX_I2C_CTLR_NAME " algorithm",
-	.id = I2C_ALGO_MV64XXX,
 	.master_xfer = mv64xxx_i2c_xfer,
 	.functionality = mv64xxx_i2c_functionality,
 };
@@ -523,7 +521,7 @@
 	drv_data->freq_m = pdata->freq_m;
 	drv_data->freq_n = pdata->freq_n;
 	drv_data->irq = platform_get_irq(pd, 0);
-	drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
+	drv_data->adapter.id = I2C_HW_MV64XXX;
 	drv_data->adapter.algo = &mv64xxx_i2c_algo;
 	drv_data->adapter.owner = THIS_MODULE;
 	drv_data->adapter.class = I2C_CLASS_HWMON;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 74eb89a..e0b7a91 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -110,8 +110,6 @@
 
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name = "Non-I2C SMBus adapter",
-	.id = I2C_ALGO_SMBUS,
 	.smbus_xfer = nforce2_access,
 	.functionality = nforce2_func,
 };
@@ -131,7 +129,6 @@
 	struct nforce2_smbus *smbus = adap->algo_data;
 	unsigned char protocol, pec, temp;
 	unsigned char len = 0; /* to keep the compiler quiet */
-	int timeout = 0;
 	int i;
 
 	protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
@@ -191,29 +188,10 @@
 		case I2C_SMBUS_PROC_CALL:
 			dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
 			return -1;
-			/*
-			outb_p(command, NVIDIA_SMB_CMD);
-			outb_p(data->word, NVIDIA_SMB_DATA);
-			outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1);
-			protocol = NVIDIA_SMB_PRTCL_PROC_CALL | pec;
-			read_write = I2C_SMBUS_READ;
-			break;
-			 */
 
 		case I2C_SMBUS_BLOCK_PROC_CALL:
 			dev_err(&adap->dev, "I2C_SMBUS_BLOCK_PROC_CALL not supported!\n");
 			return -1;
-			/*
-			protocol |= pec;
-			len = min_t(u8, data->block[0], 31);
-			outb_p(command, NVIDIA_SMB_CMD);
-			outb_p(len, NVIDIA_SMB_BCNT);
-			for (i = 0; i < len; i++)
-				outb_p(data->block[i + 1], NVIDIA_SMB_DATA + i);
-			protocol = NVIDIA_SMB_PRTCL_BLOCK_PROC_CALL | pec;
-			read_write = I2C_SMBUS_READ;
-			break;
-			*/
 
 		case I2C_SMBUS_WORD_DATA_PEC:
 		case I2C_SMBUS_BLOCK_DATA_PEC:
@@ -232,12 +210,6 @@
 
 	temp = inb_p(NVIDIA_SMB_STS);
 
-#if 0
-	do {
-		i2c_do_pause(1);
-		temp = inb_p(NVIDIA_SMB_STS);
-	} while (((temp & NVIDIA_SMB_STS_DONE) == 0) && (timeout++ < MAX_TIMEOUT));
-#endif
 	if (~temp & NVIDIA_SMB_STS_DONE) {
 		udelay(500);
 		temp = inb_p(NVIDIA_SMB_STS);
@@ -247,9 +219,10 @@
 		temp = inb_p(NVIDIA_SMB_STS);
 	}
 
-	if ((timeout >= MAX_TIMEOUT) || (~temp & NVIDIA_SMB_STS_DONE)
-		|| (temp & NVIDIA_SMB_STS_STATUS))
+	if ((~temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
+		dev_dbg(&adap->dev, "SMBus Timeout! (0x%02x)\n", temp);
 		return -1;
+	}
 
 	if (read_write == I2C_SMBUS_WRITE)
 		return 0;
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 6d34ee3..6d48a4d 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -399,8 +399,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= piix4_access,
 	.functionality	= piix4_func,
 };
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index a3b3825..73a092f 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -568,7 +568,6 @@
 /* i2c bus registration info */
 
 static struct i2c_algorithm s3c24xx_i2c_algorithm = {
-	.name			= "S3C2410-I2C-Algorithm",
 	.master_xfer		= s3c24xx_i2c_xfer,
 	.functionality		= s3c24xx_i2c_func,
 };
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index bbd5e4e..080318d 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -357,8 +357,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= sis5595_access,
 	.functionality	= sis5595_func,
 };
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index f58455e..86f0f44 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -448,8 +448,6 @@
 
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= sis630_access,
 	.functionality	= sis630_func,
 };
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 6484792..ead2ff3 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -249,8 +249,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= sis96x_access,
 	.functionality	= sis96x_func,
 };
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index 00d94e8..73f481e 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -109,8 +109,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.functionality	= stub_func,
 	.smbus_xfer	= stub_xfer,
 };
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 6b50080..99d209e 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -286,8 +286,6 @@
 }
 
 static struct i2c_algorithm smbus_algorithm = {
-	.name		= "Non-I2C SMBus adapter",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= vt596_access,
 	.functionality	= vt596_func,
 };
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index a18bdd9..a1d580e 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -395,8 +395,6 @@
 
 /* For now, we only handle combined mode (smbus) */
 static struct i2c_algorithm scx200_acb_algorithm = {
-	.name		= "NatSemi SCx200 ACCESS.bus",
-	.id		= I2C_ALGO_SMBUS,
 	.smbus_xfer	= scx200_acb_smbus_xfer,
 	.functionality	= scx200_acb_func,
 };
@@ -456,7 +454,7 @@
 	i2c_set_adapdata(adapter, iface);
 	snprintf(adapter->name, I2C_NAME_SIZE, "SCx200 ACB%d", index);
 	adapter->owner = THIS_MODULE;
-	adapter->id = I2C_ALGO_SMBUS;
+	adapter->id = I2C_HW_SMBUS_SCX200;
 	adapter->algo = &scx200_acb_algorithm;
 	adapter->class = I2C_CLASS_HWMON;
 
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 43f70db..6bd44a4 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -2,17 +2,12 @@
 # Miscellaneous I2C chip drivers configuration
 #
 
-config I2C_SENSOR
-	tristate
-	default n
-
 menu "Miscellaneous I2C Chip support"
 	depends on I2C
 
 config SENSORS_DS1337
 	tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
 	depends on I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Dallas Semiconductor
 	  DS1337 and DS1339 real-time clock chips.
@@ -23,7 +18,6 @@
 config SENSORS_DS1374
 	tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
 	depends on I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Dallas Semiconductor
 	  DS1374 real-time clock chips.
@@ -34,7 +28,6 @@
 config SENSORS_EEPROM
 	tristate "EEPROM reader"
 	depends on I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get read-only access to the EEPROM data
 	  available on modern memory DIMMs and Sony Vaio laptops.  Such
@@ -46,7 +39,6 @@
 config SENSORS_PCF8574
 	tristate "Philips PCF8574 and PCF8574A"
 	depends on I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Philips PCF8574 and 
 	  PCF8574A chips.
@@ -67,7 +59,6 @@
 config SENSORS_PCF8591
 	tristate "Philips PCF8591"
 	depends on I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Philips PCF8591 chips.
 
@@ -77,7 +68,6 @@
 config SENSORS_RTC8564
 	tristate "Epson 8564 RTC chip"
 	depends on I2C && EXPERIMENTAL
-	select I2C_SENSOR
 	help
 	  If you say yes here you get support for the Epson 8564 RTC chip.
 
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 82cf959..9d3175c 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/string.h>
 #include <linux/rtc.h>		/* get the user-level API */
 #include <linux/bcd.h>
@@ -39,9 +38,8 @@
  * Functions declaration
  */
 static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
-SENSORS_INSMOD_1(ds1337);
+I2C_CLIENT_INSMOD_1(ds1337);
 
 static int ds1337_attach_adapter(struct i2c_adapter *adapter);
 static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
@@ -227,7 +225,7 @@
 
 static int ds1337_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, ds1337_detect);
+	return i2c_probe(adapter, &addr_data, ds1337_detect);
 }
 
 /*
@@ -354,11 +352,8 @@
 	int err;
 	struct ds1337_data *data = i2c_get_clientdata(client);
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed, "
-			"client not detached.\n");
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	list_del(&data->list);
 	kfree(data);
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index a445736..0936327 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -53,7 +53,6 @@
 	.normal_i2c = normal_addr,
 	.probe = ignore,
 	.ignore = ignore,
-	.force = ignore,
 };
 
 static ulong ds1374_read_rtc(void)
@@ -166,7 +165,7 @@
 			 "can't confirm time set from rtc chip\n");
 }
 
-ulong new_time;
+static ulong new_time;
 
 DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
 
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index a2da31b..d58403a 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -33,15 +33,13 @@
 #include <linux/sched.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
 					0x55, 0x56, 0x57, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(eeprom);
+I2C_CLIENT_INSMOD_1(eeprom);
 
 
 /* Size of EEPROM in bytes */
@@ -153,21 +151,16 @@
 
 static int eeprom_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, eeprom_detect);
+	return i2c_probe(adapter, &addr_data, eeprom_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
 	struct eeprom_data *data;
 	int err = 0;
 
-	/* prevent 24RF08 corruption */
-	if (kind < 0)
-		i2c_smbus_xfer(adapter, address, 0, 0, 0,
-			       I2C_SMBUS_QUICK, NULL);
-
 	/* There are three ways we can read the EEPROM data:
 	   (1) I2C block reads (faster, but unsupported by most adapters)
 	   (2) Consecutive byte reads (100% overhead)
@@ -231,10 +224,8 @@
 	int err;
 
 	err = i2c_detach_client(client);
-	if (err) {
-		dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+	if (err)
 		return err;
-	}
 
 	kfree(i2c_get_clientdata(client));
 
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 778d7e1..3f14528 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -42,7 +42,6 @@
 	.normal_i2c		= normal_addr,
 	.probe			= ignore,
 	.ignore			= ignore,
-	.force			= ignore,
 };
 
 ulong
@@ -145,7 +144,7 @@
 	return;
 }
 
-ulong	new_time;
+static ulong	new_time;
 
 DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
 
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 0230375..9e1aeb6 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -5,97 +5,60 @@
 
     Based on i2c/chips/eeprom.c
 
-    The MAX6875 has two EEPROM sections: config and user.
-    At reset, the config EEPROM is read into the registers.
+    The MAX6875 has a bank of registers and two banks of EEPROM.
+    Address ranges are defined as follows:
+     * 0x0000 - 0x0046 = configuration registers
+     * 0x8000 - 0x8046 = configuration EEPROM
+     * 0x8100 - 0x82FF = user EEPROM
 
-    This driver make 3 binary files available in sysfs:
-      reg_config    - direct access to the registers
-      eeprom_config - acesses configuration eeprom space
-      eeprom_user   - free for application use
+    This driver makes the user EEPROM available for read.
 
-    In our application, we put device serial & model numbers in user eeprom.
+    The registers & config EEPROM should be accessed via i2c-dev.
 
-    Notes:
-      1) The datasheet says that register 0x44 / EEPROM 0x8044 should NOT
-         be overwritten, so the driver explicitly prevents that.
-      2) It's a good idea to keep the config (0x45) locked in config EEPROM.
-         You can temporarily enable config writes by changing register 0x45.
+    The MAX6875 ignores the lowest address bit, so each chip responds to
+    two addresses - 0x50/0x51 and 0x52/0x53.
+
+    Note that the MAX6875 uses i2c_smbus_write_byte_data() to set the read
+    address, so this driver is destructive if loaded for the wrong EEPROM chip.
 
     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; version 2 of the License.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <asm/semaphore.h>
 
-/* Addresses to scan */
-/* No address scanned by default, as this could corrupt standard EEPROMS. */
+/* Do not scan - the MAX6875 access method will write to some EEPROM chips */
 static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(max6875);
-
-/* this param will prevent 'accidental' writes to the eeprom */
-static int allow_write = 0;
-module_param(allow_write, int, 0);
-MODULE_PARM_DESC(allow_write,
-		 "Enable write access:\n"
-		 "*0: Read only\n"
-		 " 1: Read/Write access");
+I2C_CLIENT_INSMOD_1(max6875);
 
 /* The MAX6875 can only read/write 16 bytes at a time */
 #define SLICE_SIZE			16
 #define SLICE_BITS			4
 
-/* CONFIG EEPROM is at addresses 0x8000 - 0x8045, registers are at 0 - 0x45 */
-#define CONFIG_EEPROM_BASE		0x8000
-#define CONFIG_EEPROM_SIZE		0x0046
-#define CONFIG_EEPROM_SLICES		5
-
 /* USER EEPROM is at addresses 0x8100 - 0x82FF */
 #define USER_EEPROM_BASE		0x8100
 #define USER_EEPROM_SIZE		0x0200
 #define USER_EEPROM_SLICES		32
 
 /* MAX6875 commands */
-#define MAX6875_CMD_BLOCK_WRITE		0x83
-#define MAX6875_CMD_BLOCK_READ		0x84
-#define MAX6875_CMD_REBOOT		0x88
-
-enum max6875_area_type {
-	max6875_register_config=0,
-	max6875_eeprom_config,
-	max6875_eeprom_user,
-	max6857_max
-};
-
-struct eeprom_block {
-	enum max6875_area_type	type;
-	u8			slices;
-	u32			size;
-	u32			valid;
-	u32			base;
-	unsigned long		*updated;
-	u8			*data;
-};
+#define MAX6875_CMD_BLK_READ		0x84
 
 /* Each client has this additional data */
 struct max6875_data {
 	struct i2c_client	client;
 	struct semaphore	update_lock;
-	struct eeprom_block	blocks[max6857_max];
-	/* the above structs point into the arrays below */
-	u8 data[USER_EEPROM_SIZE + (CONFIG_EEPROM_SIZE*2)];
-	unsigned long last_updated[USER_EEPROM_SLICES + (CONFIG_EEPROM_SLICES*2)];
+
+	u32			valid;
+	u8			data[USER_EEPROM_SIZE];
+	unsigned long		last_updated[USER_EEPROM_SLICES];
 };
 
 static int max6875_attach_adapter(struct i2c_adapter *adapter);
@@ -111,337 +74,160 @@
 	.detach_client	= max6875_detach_client,
 };
 
-static int max6875_update_slice(struct i2c_client *client,
-				struct eeprom_block *blk,
-				int slice)
+static void max6875_update_slice(struct i2c_client *client, int slice)
 {
 	struct max6875_data *data = i2c_get_clientdata(client);
-	int i, j, addr, count;
-	u8 rdbuf[SLICE_SIZE];
-	int retval = 0;
+	int i, j, addr;
+	u8 *buf;
 
-	if (slice >= blk->slices)
-		return -1;
+	if (slice >= USER_EEPROM_SLICES)
+		return;
 
 	down(&data->update_lock);
 
-	if (!(blk->valid & (1 << slice)) ||
-	    (jiffies - blk->updated[slice] > 300 * HZ) ||
-	    (jiffies < blk->updated[slice])) {
-		dev_dbg(&client->dev, "Starting eeprom update, slice %u, base %u\n",
-			slice, blk->base);
+	buf = &data->data[slice << SLICE_BITS];
 
-		addr = blk->base + (slice << SLICE_BITS);
-		count = blk->size - (slice << SLICE_BITS);
-		if (count > SLICE_SIZE) {
-			count = SLICE_SIZE;
+	if (!(data->valid & (1 << slice)) ||
+	    time_after(jiffies, data->last_updated[slice])) {
+
+		dev_dbg(&client->dev, "Starting update of slice %u\n", slice);
+
+		data->valid &= ~(1 << slice);
+
+		addr = USER_EEPROM_BASE + (slice << SLICE_BITS);
+
+		/* select the eeprom address */
+		if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
+			dev_err(&client->dev, "address set failed\n");
+			goto exit_up;
 		}
 
-		/* Preset the read address */
-		if (addr < 0x100) {
-			/* select the register */
-			if (i2c_smbus_write_byte(client, addr & 0xFF)) {
-				dev_dbg(&client->dev, "max6875 register select has failed!\n");
-				retval = -1;
-				goto exit;
+		if (i2c_check_functionality(client->adapter,
+					    I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+			if (i2c_smbus_read_i2c_block_data(client,
+							  MAX6875_CMD_BLK_READ,
+							  buf) != SLICE_SIZE) {
+				goto exit_up;
 			}
 		} else {
-			/* select the eeprom */
-			if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
-				dev_dbg(&client->dev, "max6875 address set has failed!\n");
-				retval = -1;
-				goto exit;
-			}
-		}
-
-		if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
-			if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLOCK_READ,
-							  rdbuf) != SLICE_SIZE)
-			{
-				retval = -1;
-				goto exit;
-			}
-
-			memcpy(&blk->data[slice << SLICE_BITS], rdbuf, count);
-		} else {
-			for (i = 0; i < count; i++) {
+			for (i = 0; i < SLICE_SIZE; i++) {
 				j = i2c_smbus_read_byte(client);
-				if (j < 0)
-				{
-					retval = -1;
-					goto exit;
+				if (j < 0) {
+					goto exit_up;
 				}
-				blk->data[(slice << SLICE_BITS) + i] = (u8) j;
+				buf[i] = j;
 			}
 		}
-		blk->updated[slice] = jiffies;
-		blk->valid |= (1 << slice);
+		data->last_updated[slice] = jiffies;
+		data->valid |= (1 << slice);
 	}
-	exit:
+exit_up:
 	up(&data->update_lock);
-	return retval;
 }
 
-static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, size_t count,
-			    enum max6875_area_type area_type)
+static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
+			    size_t count)
 {
-	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+	struct i2c_client *client = kobj_to_i2c_client(kobj);
 	struct max6875_data *data = i2c_get_clientdata(client);
-	struct eeprom_block *blk;
-	int slice;
+	int slice, max_slice;
 
-	blk = &data->blocks[area_type];
-
-	if (off > blk->size)
+	if (off > USER_EEPROM_SIZE)
 		return 0;
-	if (off + count > blk->size)
-		count = blk->size - off;
 
-	/* Only refresh slices which contain requested bytes */
-	for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
-		max6875_update_slice(client, blk, slice);
+	if (off + count > USER_EEPROM_SIZE)
+		count = USER_EEPROM_SIZE - off;
 
-	memcpy(buf, &blk->data[off], count);
+	/* refresh slices which contain requested bytes */
+	max_slice = (off + count - 1) >> SLICE_BITS;
+	for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
+		max6875_update_slice(client, slice);
+
+	memcpy(buf, &data->data[off], count);
 
 	return count;
 }
 
-static ssize_t max6875_user_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	return max6875_read(kobj, buf, off, count, max6875_eeprom_user);
-}
-
-static ssize_t max6875_config_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	return max6875_read(kobj, buf, off, count, max6875_eeprom_config);
-}
-
-static ssize_t max6875_cfgreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	return max6875_read(kobj, buf, off, count, max6875_register_config);
-}
-
-
-static ssize_t max6875_write(struct kobject *kobj, char *buf, loff_t off, size_t count,
-			     enum max6875_area_type area_type)
-{
-	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
-	struct max6875_data *data = i2c_get_clientdata(client);
-	struct eeprom_block *blk;
-	int slice, addr, retval;
-	ssize_t sent = 0;
-
-	blk = &data->blocks[area_type];
-
-	if (off > blk->size)
-		return 0;
-	if ((off + count) > blk->size)
-		count = blk->size - off;
-
-	if (down_interruptible(&data->update_lock))
-		return -EAGAIN;
-
-	/* writing to a register is done with i2c_smbus_write_byte_data() */
-	if (blk->type == max6875_register_config) {
-		for (sent = 0; sent < count; sent++) {
-			addr = off + sent;
-			if (addr == 0x44)
-				continue;
-
-			retval = i2c_smbus_write_byte_data(client, addr, buf[sent]);
-		}
-	} else {
-		int cmd, val;
-
-		/* We are writing to EEPROM */
-		for (sent = 0; sent < count; sent++) {
-			addr = blk->base + off + sent;
-			cmd = addr >> 8;
-			val = (addr & 0xff) | (buf[sent] << 8);	// reversed
-
-			if (addr == 0x8044)
-				continue;
-
-			retval = i2c_smbus_write_word_data(client, cmd, val);
-
-			if (retval) {
-				goto error_exit;
-			}
-
-			/* A write takes up to 11 ms */
-			msleep(11);
-		}
-	}
-
-	/* Invalidate the scratch buffer */
-	for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
-		blk->valid &= ~(1 << slice);
-
-	error_exit:
-	up(&data->update_lock);
-
-	return sent;
-}
-
-static ssize_t max6875_user_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	return max6875_write(kobj, buf, off, count, max6875_eeprom_user);
-}
-
-static ssize_t max6875_config_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	return max6875_write(kobj, buf, off, count, max6875_eeprom_config);
-}
-
-static ssize_t max6875_cfgreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
-{
-	return max6875_write(kobj, buf, off, count, max6875_register_config);
-}
-
 static struct bin_attribute user_eeprom_attr = {
 	.attr = {
-		.name = "eeprom_user",
-		.mode = S_IRUGO | S_IWUSR | S_IWGRP,
+		.name = "eeprom",
+		.mode = S_IRUGO,
 		.owner = THIS_MODULE,
 	},
-	.size  = USER_EEPROM_SIZE,
-	.read  = max6875_user_read,
-	.write = max6875_user_write,
-};
-
-static struct bin_attribute config_eeprom_attr = {
-	.attr = {
-		.name = "eeprom_config",
-		.mode = S_IRUGO | S_IWUSR,
-		.owner = THIS_MODULE,
-	},
-	.size  = CONFIG_EEPROM_SIZE,
-	.read  = max6875_config_read,
-	.write = max6875_config_write,
-};
-
-static struct bin_attribute config_register_attr = {
-	.attr = {
-		.name = "reg_config",
-		.mode = S_IRUGO | S_IWUSR,
-		.owner = THIS_MODULE,
-	},
-	.size  = CONFIG_EEPROM_SIZE,
-	.read  = max6875_cfgreg_read,
-	.write = max6875_cfgreg_write,
+	.size = USER_EEPROM_SIZE,
+	.read = max6875_read,
 };
 
 static int max6875_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, max6875_detect);
+	return i2c_probe(adapter, &addr_data, max6875_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-	struct i2c_client *new_client;
+	struct i2c_client *real_client;
+	struct i2c_client *fake_client;
 	struct max6875_data *data;
 	int err = 0;
 
-	/* Prevent 24RF08 corruption (in case of user error) */
-	if (kind < 0)
-		i2c_smbus_xfer(adapter, address, 0, 0, 0,
-			       I2C_SMBUS_QUICK, NULL);
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+				     | I2C_FUNC_SMBUS_READ_BYTE))
+		return 0;
 
-	/* There are three ways we can read the EEPROM data:
-	   (1) I2C block reads (faster, but unsupported by most adapters)
-	   (2) Consecutive byte reads (100% overhead)
-	   (3) Regular byte data reads (200% overhead)
-	   The third method is not implemented by this driver because all
-	   known adapters support at least the second. */
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA |
-				     I2C_FUNC_SMBUS_BYTE |
-				     I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
-		goto exit;
+	/* Only check even addresses */
+	if (address & 1)
+		return 0;
 
-	/* OK. For now, we presume we have a valid client. We now create the
-	   client structure, even though we cannot fill it completely yet.
-	   But it allows us to access eeprom_{read,write}_value. */
-	if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL))) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL)))
+		return -ENOMEM;
 	memset(data, 0, sizeof(struct max6875_data));
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &max6875_driver;
-	new_client->flags = 0;
+	/* A fake client is created on the odd address */
+	if (!(fake_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit_kfree1;
+	}
+	memset(fake_client, 0, sizeof(struct i2c_client));
 
-	/* Setup the user section */
-	data->blocks[max6875_eeprom_user].type    = max6875_eeprom_user;
-	data->blocks[max6875_eeprom_user].slices  = USER_EEPROM_SLICES;
-	data->blocks[max6875_eeprom_user].size    = USER_EEPROM_SIZE;
-	data->blocks[max6875_eeprom_user].base    = USER_EEPROM_BASE;
-	data->blocks[max6875_eeprom_user].data    = data->data;
-	data->blocks[max6875_eeprom_user].updated = data->last_updated;
-
-	/* Setup the config section */
-	data->blocks[max6875_eeprom_config].type    = max6875_eeprom_config;
-	data->blocks[max6875_eeprom_config].slices  = CONFIG_EEPROM_SLICES;
-	data->blocks[max6875_eeprom_config].size    = CONFIG_EEPROM_SIZE;
-	data->blocks[max6875_eeprom_config].base    = CONFIG_EEPROM_BASE;
-	data->blocks[max6875_eeprom_config].data    = &data->data[USER_EEPROM_SIZE];
-	data->blocks[max6875_eeprom_config].updated = &data->last_updated[USER_EEPROM_SLICES];
-
-	/* Setup the register section */
-	data->blocks[max6875_register_config].type    = max6875_register_config;
-	data->blocks[max6875_register_config].slices  = CONFIG_EEPROM_SLICES;
-	data->blocks[max6875_register_config].size    = CONFIG_EEPROM_SIZE;
-	data->blocks[max6875_register_config].base    = 0;
-	data->blocks[max6875_register_config].data    = &data->data[USER_EEPROM_SIZE+CONFIG_EEPROM_SIZE];
-	data->blocks[max6875_register_config].updated = &data->last_updated[USER_EEPROM_SLICES+CONFIG_EEPROM_SLICES];
-
-	/* Init the data */
-	memset(data->data, 0xff, sizeof(data->data));
-
-	/* Fill in the remaining client fields */
-	strlcpy(new_client->name, "max6875", I2C_NAME_SIZE);
+	/* Init real i2c_client */
+	real_client = &data->client;
+	i2c_set_clientdata(real_client, data);
+	real_client->addr = address;
+	real_client->adapter = adapter;
+	real_client->driver = &max6875_driver;
+	real_client->flags = 0;
+	strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
 	init_MUTEX(&data->update_lock);
 
-	/* Verify that the chip is really what we think it is */
-	if ((max6875_update_slice(new_client, &data->blocks[max6875_eeprom_config], 4) < 0) ||
-	    (max6875_update_slice(new_client, &data->blocks[max6875_register_config], 4) < 0))
-		goto exit_kfree;
+	/* Init fake client data */
+	/* set the client data to the i2c_client so that it will get freed */
+	i2c_set_clientdata(fake_client, fake_client);
+	fake_client->addr = address | 1;
+	fake_client->adapter = adapter;
+	fake_client->driver = &max6875_driver;
+	fake_client->flags = 0;
+	strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
 
-	/* 0x41,0x42 must be zero and 0x40 must match in eeprom and registers */
-	if ((data->blocks[max6875_eeprom_config].data[0x41] != 0) ||
-	    (data->blocks[max6875_eeprom_config].data[0x42] != 0) ||
-	    (data->blocks[max6875_register_config].data[0x41] != 0) ||
-	    (data->blocks[max6875_register_config].data[0x42] != 0) ||
-	    (data->blocks[max6875_eeprom_config].data[0x40] !=
-	     data->blocks[max6875_register_config].data[0x40]))
-		goto exit_kfree;
+	/* Prevent 24RF08 corruption (in case of user error) */
+	i2c_smbus_write_quick(real_client, 0);
 
-	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
-		goto exit_kfree;
+	if ((err = i2c_attach_client(real_client)) != 0)
+		goto exit_kfree2;
 
-	/* create the sysfs eeprom files with the correct permissions */
-	if (allow_write == 0) {
-		user_eeprom_attr.attr.mode &= ~S_IWUGO;
-		user_eeprom_attr.write = NULL;
-		config_eeprom_attr.attr.mode &= ~S_IWUGO;
-		config_eeprom_attr.write = NULL;
-		config_register_attr.attr.mode &= ~S_IWUGO;
-		config_register_attr.write = NULL;
-	}
-	sysfs_create_bin_file(&new_client->dev.kobj, &user_eeprom_attr);
-	sysfs_create_bin_file(&new_client->dev.kobj, &config_eeprom_attr);
-	sysfs_create_bin_file(&new_client->dev.kobj, &config_register_attr);
+	if ((err = i2c_attach_client(fake_client)) != 0)
+		goto exit_detach;
+
+	sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
 
 	return 0;
 
-exit_kfree:
+exit_detach:
+	i2c_detach_client(real_client);
+exit_kfree2:
+	kfree(fake_client);
+exit_kfree1:
 	kfree(data);
-exit:
 	return err;
 }
 
@@ -450,13 +236,9 @@
 	int err;
 
 	err = i2c_detach_client(client);
-	if (err) {
-		dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+	if (err)
 		return err;
-	}
-
 	kfree(i2c_get_clientdata(client));
-
 	return 0;
 }
 
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 9f3ad45..225577fd 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -13,14 +13,12 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/hwmon-sysfs.h>
-#include <linux/i2c-sensor.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
-static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(pca9539);
+I2C_CLIENT_INSMOD_1(pca9539);
 
 enum pca9539_cmd
 {
@@ -109,10 +107,10 @@
 
 static int pca9539_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, pca9539_detect);
+	return i2c_probe(adapter, &addr_data, pca9539_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
@@ -164,10 +162,8 @@
 {
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev, "Client deregistration failed.\n");
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	kfree(i2c_get_clientdata(client));
 	return 0;
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index cfcf646..6525743 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -39,16 +39,14 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
 					0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
 					I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_2(pcf8574, pcf8574a);
+I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
 
 /* Initial values */
 #define PCF8574_INIT 255	/* All outputs on (input mode) */
@@ -113,10 +111,10 @@
 
 static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, pcf8574_detect);
+	return i2c_probe(adapter, &addr_data, pcf8574_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
@@ -186,11 +184,8 @@
 {
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-			"Client deregistration failed, client not detached.\n");
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	kfree(i2c_get_clientdata(client));
 	return 0;
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index db812ad..80f1df9 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -24,15 +24,13 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
 					0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(pcf8591);
+I2C_CLIENT_INSMOD_1(pcf8591);
 
 static int input_mode;
 module_param(input_mode, int, 0);
@@ -164,10 +162,10 @@
  */
 static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
 {
-	return i2c_detect(adapter, &addr_data, pcf8591_detect);
+	return i2c_probe(adapter, &addr_data, pcf8591_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	struct i2c_client *new_client;
@@ -241,11 +239,8 @@
 {
 	int err;
 
-	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-			"Client deregistration failed, client not detached.\n");
+	if ((err = i2c_detach_client(client)))
 		return err;
-	}
 
 	kfree(i2c_get_clientdata(client));
 	return 0;
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 588fc22..0b5385c 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -67,7 +67,6 @@
 	.normal_i2c		= normal_addr,
 	.probe			= ignore,
 	.ignore			= ignore,
-	.force			= ignore,
 };
 
 static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 4a9ead2..dda472e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -61,7 +61,7 @@
 	return rc;
 }
 
-static struct bus_type i2c_bus_type = {
+struct bus_type i2c_bus_type = {
 	.name =		"i2c",
 	.match =	i2c_device_match,
 	.suspend =      i2c_bus_suspend,
@@ -78,13 +78,13 @@
 	return 0;
 }
 
-static void i2c_adapter_dev_release(struct device *dev)
+void i2c_adapter_dev_release(struct device *dev)
 {
 	struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
 	complete(&adap->dev_released);
 }
 
-static struct device_driver i2c_adapter_driver = {
+struct device_driver i2c_adapter_driver = {
 	.name =	"i2c_adapter",
 	.bus = &i2c_bus_type,
 	.probe = i2c_device_probe,
@@ -97,7 +97,7 @@
 	complete(&adap->class_dev_released);
 }
 
-static struct class i2c_adapter_class = {
+struct class i2c_adapter_class = {
 	.name =		"i2c-adapter",
 	.release =	&i2c_adapter_class_dev_release,
 };
@@ -188,6 +188,8 @@
 	strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
 	class_device_register(&adap->class_dev);
 
+	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
+
 	/* inform drivers of new adapters */
 	list_for_each(item,&drivers) {
 		driver = list_entry(item, struct i2c_driver, list);
@@ -196,8 +198,6 @@
 			driver->attach_adapter(adap);
 	}
 
-	dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
-
 out_unlock:
 	up(&core_lists);
 	return res;
@@ -220,8 +220,8 @@
 			break;
 	}
 	if (adap_from_list != adap) {
-		pr_debug("I2C: Attempting to delete an unregistered "
-			 "adapter\n");
+		pr_debug("i2c-core: attempting to delete unregistered "
+			 "adapter [%s]\n", adap->name);
 		res = -EINVAL;
 		goto out_unlock;
 	}
@@ -230,9 +230,8 @@
 		driver = list_entry(item, struct i2c_driver, list);
 		if (driver->detach_adapter)
 			if ((res = driver->detach_adapter(adap))) {
-				dev_warn(&adap->dev, "can't detach adapter "
-					 "while detaching driver %s: driver "
-					 "not detached!\n", driver->name);
+				dev_err(&adap->dev, "detach_adapter failed "
+					"for driver [%s]\n", driver->name);
 				goto out_unlock;
 			}
 	}
@@ -247,9 +246,8 @@
 		 * must be deleted, as this would cause invalid states.
 		 */
 		if ((res=client->driver->detach_client(client))) {
-			dev_err(&adap->dev, "adapter not "
-				"unregistered, because client at "
-				"address %02x can't be detached. ",
+			dev_err(&adap->dev, "detach_client failed for client "
+				"[%s] at address 0x%02x\n", client->name,
 				client->addr);
 			goto out_unlock;
 		}
@@ -270,7 +268,7 @@
 	/* free dynamically allocated bus id */
 	idr_remove(&i2c_adapter_idr, adap->nr);
 
-	dev_dbg(&adap->dev, "adapter unregistered\n");
+	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
 
  out_unlock:
 	up(&core_lists);
@@ -303,7 +301,7 @@
 		goto out_unlock;
 	
 	list_add_tail(&driver->list,&drivers);
-	pr_debug("i2c-core: driver %s registered.\n", driver->name);
+	pr_debug("i2c-core: driver [%s] registered\n", driver->name);
 
 	/* now look for instances of driver on our adapters */
 	if (driver->flags & I2C_DF_NOTIFY) {
@@ -331,21 +329,17 @@
 	/* Have a look at each adapter, if clients of this driver are still
 	 * attached. If so, detach them to be able to kill the driver 
 	 * afterwards.
-	 */
-	pr_debug("i2c-core: unregister_driver - looking for clients.\n");
-	/* removing clients does not depend on the notify flag, else 
+	 *
+	 * Removing clients does not depend on the notify flag, else
 	 * invalid operation might (will!) result, when using stale client
 	 * pointers.
 	 */
 	list_for_each(item1,&adapters) {
 		adap = list_entry(item1, struct i2c_adapter, list);
-		dev_dbg(&adap->dev, "examining adapter\n");
 		if (driver->detach_adapter) {
 			if ((res = driver->detach_adapter(adap))) {
-				dev_warn(&adap->dev, "while unregistering "
-				       "dummy driver %s, adapter could "
-				       "not be detached properly; driver "
-				       "not unloaded!",driver->name);
+				dev_err(&adap->dev, "detach_adapter failed "
+					"for driver [%s]\n", driver->name);
 				goto out_unlock;
 			}
 		} else {
@@ -353,16 +347,13 @@
 				client = list_entry(item2, struct i2c_client, list);
 				if (client->driver != driver)
 					continue;
-				pr_debug("i2c-core.o: detaching client %s:\n", client->name);
+				dev_dbg(&adap->dev, "detaching client [%s] "
+					"at 0x%02x\n", client->name,
+					client->addr);
 				if ((res = driver->detach_client(client))) {
-					dev_err(&adap->dev, "while "
-						"unregistering driver "
-						"`%s', the client at "
-						"address %02x of "
-						"adapter could not "
-						"be detached; driver "
-						"not unloaded!",
-						driver->name,
+					dev_err(&adap->dev, "detach_client "
+						"failed for client [%s] at "
+						"0x%02x\n", client->name,
 						client->addr);
 					goto out_unlock;
 				}
@@ -372,7 +363,7 @@
 
 	driver_unregister(&driver->driver);
 	list_del(&driver->list);
-	pr_debug("i2c-core: driver unregistered: %s\n", driver->name);
+	pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
 
  out_unlock:
 	up(&core_lists);
@@ -417,15 +408,12 @@
 	
 	if (adapter->client_register)  {
 		if (adapter->client_register(client))  {
-			dev_warn(&adapter->dev, "warning: client_register "
-				"seems to have failed for client %02x\n",
-				client->addr);
+			dev_dbg(&adapter->dev, "client_register "
+				"failed for client [%s] at 0x%02x\n",
+				client->name, client->addr);
 		}
 	}
 
-	dev_dbg(&adapter->dev, "client [%s] registered to adapter\n",
-		client->name);
-
 	if (client->flags & I2C_CLIENT_ALLOW_USE)
 		client->usage_count = 0;
 
@@ -436,7 +424,8 @@
 	
 	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
 		"%d-%04x", i2c_adapter_id(adapter), client->addr);
-	pr_debug("registering %s\n", client->dev.bus_id);
+	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+		client->name, client->dev.bus_id);
 	device_register(&client->dev);
 	device_create_file(&client->dev, &dev_attr_client_name);
 	
@@ -449,8 +438,12 @@
 	struct i2c_adapter *adapter = client->adapter;
 	int res = 0;
 	
-	if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0))
+	if ((client->flags & I2C_CLIENT_ALLOW_USE)
+	 && (client->usage_count > 0)) {
+		dev_warn(&client->dev, "Client [%s] still busy, "
+			 "can't detach\n", client->name);
 		return -EBUSY;
+	}
 
 	if (adapter->client_unregister)  {
 		res = adapter->client_unregister(client);
@@ -669,98 +662,128 @@
  * Will not work for 10-bit addresses!
  * ----------------------------------------------------
  */
+static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
+			     int (*found_proc) (struct i2c_adapter *, int, int))
+{
+	int err;
+
+	/* Make sure the address is valid */
+	if (addr < 0x03 || addr > 0x77) {
+		dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
+			 addr);
+		return -EINVAL;
+	}
+
+	/* Skip if already in use */
+	if (i2c_check_addr(adapter, addr))
+		return 0;
+
+	/* Make sure there is something at this address, unless forced */
+	if (kind < 0) {
+		if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+				   I2C_SMBUS_QUICK, NULL) < 0)
+			return 0;
+
+		/* prevent 24RF08 corruption */
+		if ((addr & ~0x0f) == 0x50)
+			i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+				       I2C_SMBUS_QUICK, NULL);
+	}
+
+	/* Finally call the custom detection function */
+	err = found_proc(adapter, addr, kind);
+
+	/* -ENODEV can be returned if there is a chip at the given address
+	   but it isn't supported by this chip driver. We catch it here as
+	   this isn't an error. */
+	return (err == -ENODEV) ? 0 : err;
+}
+
 int i2c_probe(struct i2c_adapter *adapter,
 	      struct i2c_client_address_data *address_data,
 	      int (*found_proc) (struct i2c_adapter *, int, int))
 {
-	int addr,i,found,err;
+	int i, err;
 	int adap_id = i2c_adapter_id(adapter);
 
 	/* Forget it if we can't probe using SMBUS_QUICK */
 	if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
 		return -1;
 
-	for (addr = 0x00; addr <= 0x7f; addr++) {
+	/* Force entries are done first, and are not affected by ignore
+	   entries */
+	if (address_data->forces) {
+		unsigned short **forces = address_data->forces;
+		int kind;
 
-		/* Skip if already in use */
-		if (i2c_check_addr(adapter,addr))
-			continue;
-
-		/* If it is in one of the force entries, we don't do any detection
-		   at all */
-		found = 0;
-
-		for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
-			if (((adap_id == address_data->force[i]) || 
-			     (address_data->force[i] == ANY_I2C_BUS)) &&
-			     (addr == address_data->force[i+1])) {
-				dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n",
-					adap_id, addr);
-				if ((err = found_proc(adapter,addr,0)))
-					return err;
-				found = 1;
+		for (kind = 0; forces[kind]; kind++) {
+			for (i = 0; forces[kind][i] != I2C_CLIENT_END;
+			     i += 2) {
+				if (forces[kind][i] == adap_id
+				 || forces[kind][i] == ANY_I2C_BUS) {
+					dev_dbg(&adapter->dev, "found force "
+						"parameter for adapter %d, "
+						"addr 0x%02x, kind %d\n",
+						adap_id, forces[kind][i + 1],
+						kind);
+					err = i2c_probe_address(adapter,
+						forces[kind][i + 1],
+						kind, found_proc);
+					if (err)
+						return err;
+				}
 			}
 		}
-		if (found) 
-			continue;
-
-		/* If this address is in one of the ignores, we can forget about
-		   it right now */
-		for (i = 0;
-		     !found && (address_data->ignore[i] != I2C_CLIENT_END);
-		     i += 2) {
-			if (((adap_id == address_data->ignore[i]) || 
-			    ((address_data->ignore[i] == ANY_I2C_BUS))) &&
-			    (addr == address_data->ignore[i+1])) {
-				dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, "
-					"addr %04x\n", adap_id ,addr);
-				found = 1;
-			}
-		}
-		if (found) 
-			continue;
-
-		/* Now, we will do a detection, but only if it is in the normal or 
-		   probe entries */  
-		for (i = 0;
-		     !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
-		     i += 1) {
-			if (addr == address_data->normal_i2c[i]) {
-				found = 1;
-				dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
-					"addr %02x\n", adap_id, addr);
-			}
-		}
-
-		for (i = 0;
-		     !found && (address_data->probe[i] != I2C_CLIENT_END);
-		     i += 2) {
-			if (((adap_id == address_data->probe[i]) ||
-			    ((address_data->probe[i] == ANY_I2C_BUS))) &&
-			    (addr == address_data->probe[i+1])) {
-				found = 1;
-				dev_dbg(&adapter->dev, "found probe parameter for adapter %d, "
-					"addr %04x\n", adap_id,addr);
-			}
-		}
-		if (!found) 
-			continue;
-
-		/* OK, so we really should examine this address. First check
-		   whether there is some client here at all! */
-		if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
-			if ((err = found_proc(adapter,addr,-1)))
-				return err;
 	}
-	return 0;
-}
 
-/*
- * return id number for a specific adapter
- */
-int i2c_adapter_id(struct i2c_adapter *adap)
-{
-	return adap->nr;
+	/* Probe entries are done second, and are not affected by ignore
+	   entries either */
+	for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
+		if (address_data->probe[i] == adap_id
+		 || address_data->probe[i] == ANY_I2C_BUS) {
+			dev_dbg(&adapter->dev, "found probe parameter for "
+				"adapter %d, addr 0x%02x\n", adap_id,
+				address_data->probe[i + 1]);
+			err = i2c_probe_address(adapter,
+						address_data->probe[i + 1],
+						-1, found_proc);
+			if (err)
+				return err;
+		}
+	}
+
+	/* Normal entries are done last, unless shadowed by an ignore entry */
+	for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
+		int j, ignore;
+
+		ignore = 0;
+		for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
+		     j += 2) {
+			if ((address_data->ignore[j] == adap_id ||
+			     address_data->ignore[j] == ANY_I2C_BUS)
+			 && address_data->ignore[j + 1]
+			    == address_data->normal_i2c[i]) {
+				dev_dbg(&adapter->dev, "found ignore "
+					"parameter for adapter %d, "
+					"addr 0x%02x\n", adap_id,
+					address_data->ignore[j + 1]);
+			}
+			ignore = 1;
+			break;
+		}
+		if (ignore)
+			continue;
+
+		dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
+			"addr 0x%02x\n", adap_id,
+			address_data->normal_i2c[i]);
+		err = i2c_probe_address(adapter, address_data->normal_i2c[i],
+					-1, found_proc);
+		if (err)
+			return err;
+	}
+
+	return 0;
 }
 
 struct i2c_adapter* i2c_get_adapter(int id)
@@ -1171,6 +1194,12 @@
 }
 
 
+/* Next four are needed by i2c-isa */
+EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
+EXPORT_SYMBOL_GPL(i2c_adapter_driver);
+EXPORT_SYMBOL_GPL(i2c_adapter_class);
+EXPORT_SYMBOL_GPL(i2c_bus_type);
+
 EXPORT_SYMBOL(i2c_add_adapter);
 EXPORT_SYMBOL(i2c_del_adapter);
 EXPORT_SYMBOL(i2c_add_driver);
@@ -1186,7 +1215,6 @@
 EXPORT_SYMBOL(i2c_master_recv);
 EXPORT_SYMBOL(i2c_control);
 EXPORT_SYMBOL(i2c_transfer);
-EXPORT_SYMBOL(i2c_adapter_id);
 EXPORT_SYMBOL(i2c_get_adapter);
 EXPORT_SYMBOL(i2c_put_adapter);
 EXPORT_SYMBOL(i2c_probe);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index bc5d557..aa7a4fa 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -434,7 +434,8 @@
 
 	devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor),
 			S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor);
-	dev_dbg(&adap->dev, "Registered as minor %d\n", i2c_dev->minor);
+	pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
+		 adap->name, i2c_dev->minor);
 
 	/* register this i2c device with the driver core */
 	i2c_dev->adap = adap;
@@ -471,7 +472,7 @@
 	wait_for_completion(&i2c_dev->released);
 	kfree(i2c_dev);
 
-	dev_dbg(&adap->dev, "Adapter unregistered\n");
+	pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
 	return 0;
 }
 
diff --git a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c
deleted file mode 100644
index f99a816..0000000
--- a/drivers/i2c/i2c-sensor-detect.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-    i2c-sensor-detect.c - Part of lm_sensors, Linux kernel modules for hardware
-            		  monitoring
-    Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl> and
-    Mark D. Studebaker <mdsxyz123@yahoo.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
-static unsigned short empty[] = {I2C_CLIENT_END};
-static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END};
-
-/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */
-int i2c_detect(struct i2c_adapter *adapter,
-	       struct i2c_address_data *address_data,
-	       int (*found_proc) (struct i2c_adapter *, int, int))
-{
-	int addr, i, found, j, err;
-	struct i2c_force_data *this_force;
-	int is_isa = i2c_is_isa_adapter(adapter);
-	int adapter_id =
-	    is_isa ? ANY_I2C_ISA_BUS : i2c_adapter_id(adapter);
-	unsigned short *normal_i2c;
-	unsigned int *normal_isa;
-	unsigned short *probe;
-	unsigned short *ignore;
-
-	/* Forget it if we can't probe using SMBUS_QUICK */
-	if ((!is_isa) &&
-	    !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK))
-		return -1;
-	
-	/* Use default "empty" list if the adapter doesn't specify any */
-	normal_i2c = probe = ignore = empty;
-	normal_isa = empty_isa;
-	if (address_data->normal_i2c)
-		normal_i2c = address_data->normal_i2c;
-	if (address_data->normal_isa)
-		normal_isa = address_data->normal_isa;
-	if (address_data->probe)
-		probe = address_data->probe;
-	if (address_data->ignore)
-		ignore = address_data->ignore;
-
-	for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
-		if (!is_isa && i2c_check_addr(adapter, addr))
-			continue;
-
-		/* If it is in one of the force entries, we don't do any
-		   detection at all */
-		found = 0;
-		for (i = 0; !found && (this_force = address_data->forces + i, this_force->force); i++) {
-			for (j = 0; !found && (this_force->force[j] != I2C_CLIENT_END); j += 2) {
-				if ( ((adapter_id == this_force->force[j]) ||
-				      ((this_force->force[j] == ANY_I2C_BUS) && !is_isa)) &&
-				      (addr == this_force->force[j + 1]) ) {
-					dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n", adapter_id, addr);
-					if ((err = found_proc(adapter, addr, this_force->kind)))
-						return err;
-					found = 1;
-				}
-			}
-		}
-		if (found)
-			continue;
-
-		/* If this address is in one of the ignores, we can forget about it
-		   right now */
-		for (i = 0; !found && (ignore[i] != I2C_CLIENT_END); i += 2) {
-			if ( ((adapter_id == ignore[i]) ||
-			      ((ignore[i] == ANY_I2C_BUS) &&
-			       !is_isa)) &&
-			      (addr == ignore[i + 1])) {
-				dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, addr %04x\n", adapter_id, addr);
-				found = 1;
-			}
-		}
-		if (found)
-			continue;
-
-		/* Now, we will do a detection, but only if it is in the normal or 
-		   probe entries */
-		if (is_isa) {
-			for (i = 0; !found && (normal_isa[i] != I2C_CLIENT_ISA_END); i += 1) {
-				if (addr == normal_isa[i]) {
-					dev_dbg(&adapter->dev, "found normal isa entry for adapter %d, addr %04x\n", adapter_id, addr);
-					found = 1;
-				}
-			}
-		} else {
-			for (i = 0; !found && (normal_i2c[i] != I2C_CLIENT_END); i += 1) {
-				if (addr == normal_i2c[i]) {
-					found = 1;
-					dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, addr %02x\n", adapter_id, addr);
-				}
-			}
-		}
-
-		for (i = 0;
-		     !found && (probe[i] != I2C_CLIENT_END);
-		     i += 2) {
-			if (((adapter_id == probe[i]) ||
-			     ((probe[i] == ANY_I2C_BUS) && !is_isa))
-			    && (addr == probe[i + 1])) {
-				dev_dbg(&adapter->dev, "found probe parameter for adapter %d, addr %04x\n", adapter_id, addr);
-				found = 1;
-			}
-		}
-		if (!found)
-			continue;
-
-		/* OK, so we really should examine this address. First check
-		   whether there is some client here at all! */
-		if (is_isa ||
-		    (i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0))
-			if ((err = found_proc(adapter, addr, -1)))
-				return err;
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL(i2c_detect);
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
-	      "Rudolf Marek <r.marek@sh.cvut.cz>");
-
-MODULE_DESCRIPTION("i2c-sensor driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c
deleted file mode 100644
index 922e22f..0000000
--- a/drivers/i2c/i2c-sensor-vid.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-    i2c-sensor-vid.c -  Part of lm_sensors, Linux kernel modules for hardware
-        		monitoring
-
-    Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-struct vrm_model {
-	u8 vendor;
-	u8 eff_family;
-	u8 eff_model;
-	int vrm_type;
-};
-
-#define ANY 0xFF
-
-#ifdef CONFIG_X86
-
-static struct vrm_model vrm_models[] = {
-	{X86_VENDOR_AMD, 0x6, ANY, 90},		/* Athlon Duron etc */
-	{X86_VENDOR_AMD, 0xF, ANY, 24},		/* Athlon 64, Opteron */
-	{X86_VENDOR_INTEL, 0x6, 0x9, 85},	/* 0.13um too */
-	{X86_VENDOR_INTEL, 0x6, 0xB, 85},	/* 0xB Tualatin */
-	{X86_VENDOR_INTEL, 0x6, ANY, 82},	/* any P6 */
-	{X86_VENDOR_INTEL, 0x7, ANY, 0},	/* Itanium */
-	{X86_VENDOR_INTEL, 0xF, 0x3, 100},	/* P4 Prescott */
-	{X86_VENDOR_INTEL, 0xF, ANY, 90},	/* P4 before Prescott */
-	{X86_VENDOR_INTEL, 0x10,ANY, 0},	/* Itanium 2 */
-	{X86_VENDOR_UNKNOWN, ANY, ANY, 0}	/* stop here */
-	};
-
-static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
-{
-	int i = 0;
-
-	while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
-		if (vrm_models[i].vendor==vendor)
-			if ((vrm_models[i].eff_family==eff_family)&& \
-			((vrm_models[i].eff_model==eff_model)|| \
-			(vrm_models[i].eff_model==ANY)))
-				return vrm_models[i].vrm_type;
-		i++;
-	}
-
-	return 0;
-}
-
-int i2c_which_vrm(void)
-{
-	struct cpuinfo_x86 *c = cpu_data;
-	u32 eax;
-	u8 eff_family, eff_model;
-	int vrm_ret;
-
-	if (c->x86 < 6) return 0;	/* any CPU with familly lower than 6
-				 	dont have VID and/or CPUID */
-	eax = cpuid_eax(1);
-	eff_family = ((eax & 0x00000F00)>>8);
-	eff_model  = ((eax & 0x000000F0)>>4);
-	if (eff_family == 0xF) {	/* use extended model & family */
-		eff_family += ((eax & 0x00F00000)>>20);
-		eff_model += ((eax & 0x000F0000)>>16)<<4;
-	}
-	vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
-	if (vrm_ret == 0)
-		printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your"
-		" x86 CPU\n");
-	return vrm_ret;
-}
-
-/* and now for something completely different for Non-x86 world*/
-#else
-int i2c_which_vrm(void)
-{
-	printk(KERN_INFO "i2c-sensor.o: Unknown VRM version of your CPU\n");
-	return 0;
-}
-#endif
-
-EXPORT_SYMBOL(i2c_which_vrm);
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 36074e6..6b1ab87 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1464,26 +1464,6 @@
                                                   { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
                                                 };
 
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-                        union i2c_smbus_data data;
-
-                        if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
-                                PRINT(KERN_ERR, lynx->id,"eeprom read start has failed");
-                        else
-                        {
-                                u16 addr;
-                                for (addr=0x00; addr < 0x100; addr++) {
-                                        if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
-                                                PRINT(KERN_ERR, lynx->id, "unable to read i2c %x", addr);
-                                                break;
-                                        }
-                                        else
-                                                PRINT(KERN_DEBUG, lynx->id,"got serial eeprom data at %x: %x",addr, data.byte);
-                                }
-                        }
-#endif
-
                         /* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we
                            do it more efficiently in one transaction rather then using several reads */
                         if (i2c_transfer(i2c_ad, msg, 2) < 0) {
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 781f23f..6284894 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -387,8 +387,6 @@
 
 /* exported algorithm data */
 static struct i2c_algorithm saa7146_algo = {
-	.name		= "saa7146 i2c algorithm",
-	.id		= I2C_ALGO_SAA7146,
 	.master_xfer	= saa7146_i2c_xfer,
 	.functionality	= saa7146_i2c_func,
 };
@@ -412,7 +410,7 @@
 #endif
 		i2c_adapter->algo	   = &saa7146_algo;
 		i2c_adapter->algo_data     = NULL;
-		i2c_adapter->id		   = I2C_ALGO_SAA7146;
+		i2c_adapter->id		   = I2C_HW_SAA7146;
 		i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
 		i2c_adapter->retries = SAA7146_I2C_RETRIES;
 	}
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
index be4266d..56495cb 100644
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -172,8 +172,6 @@
 }
 
 static struct i2c_algorithm flexcop_algo = {
-	.name			= "FlexCop I2C algorithm",
-	.id				= I2C_ALGO_BIT,
 	.master_xfer	= flexcop_master_xfer,
 	.functionality	= flexcop_i2c_func,
 };
@@ -192,7 +190,6 @@
 	fc->i2c_adap.class	    = I2C_CLASS_TV_DIGITAL;
 	fc->i2c_adap.algo       = &flexcop_algo;
 	fc->i2c_adap.algo_data  = NULL;
-	fc->i2c_adap.id         = I2C_ALGO_BIT;
 
 	if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
 		return ret;
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index c3e1b66..9e96a18 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -141,8 +141,6 @@
 }
 
 static struct i2c_algorithm cxusb_i2c_algo = {
-	.name          = "Conexant USB I2C algorithm",
-	.id            = I2C_ALGO_BIT,
 	.master_xfer   = cxusb_i2c_xfer,
 	.functionality = cxusb_i2c_func,
 };
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 9b9d6f8..00b9464 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -156,8 +156,6 @@
 }
 
 struct i2c_algorithm dibusb_i2c_algo = {
-	.name          = "DiBcom USB I2C algorithm",
-	.id            = I2C_ALGO_BIT,
 	.master_xfer   = dibusb_i2c_xfer,
 	.functionality = dibusb_i2c_func,
 };
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 9a676afc..f70e0be 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -77,8 +77,6 @@
 }
 
 static struct i2c_algorithm digitv_i2c_algo = {
-	.name          = "Nebula DigiTV USB I2C algorithm",
-	.id            = I2C_ALGO_BIT,
 	.master_xfer   = digitv_i2c_xfer,
 	.functionality = digitv_i2c_func,
 };
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 9f0a8d9..da97094 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -27,7 +27,6 @@
 #endif
 	d->i2c_adap.algo      = d->props.i2c_algo;
 	d->i2c_adap.algo_data = NULL;
-	d->i2c_adap.id        = I2C_ALGO_BIT;
 
 	i2c_set_adapdata(&d->i2c_adap, d);
 
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 706e0bc..85b437b 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -633,7 +633,6 @@
 	i2c_set_adapdata(&pluto->i2c_adap, pluto);
 	strcpy(pluto->i2c_adap.name, DRIVER_NAME);
 	pluto->i2c_adap.owner = THIS_MODULE;
-	pluto->i2c_adap.id = I2C_ALGO_BIT;
 	pluto->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
 	pluto->i2c_adap.dev.parent = &pdev->dev;
 	pluto->i2c_adap.algo_data = &pluto->i2c_bit;
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index aa43b5f..7daf7b1 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1472,8 +1472,6 @@
 
 
 static struct i2c_algorithm ttusb_dec_algo = {
-	.name		= "ttusb dec i2c algorithm",
-	.id		= I2C_ALGO_BIT,
 	.master_xfer	= master_xfer,
 	.functionality	= functionality,
 };
@@ -1525,7 +1523,6 @@
 #endif
 	ttusb->i2c_adap.algo              = &ttusb_dec_algo;
 	ttusb->i2c_adap.algo_data         = NULL;
-	ttusb->i2c_adap.id                = I2C_ALGO_BIT;
 
 	result = i2c_add_adapter(&ttusb->i2c_adap);
 	if (result) {
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 48989ed..52e32f0 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -391,7 +391,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_adv7170;
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index f898b65..b5ed954 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -441,7 +441,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_adv7175;
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 8733588..c6cfa7c 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -507,7 +507,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_bt819;
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index a070417..76c1b63 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -188,7 +188,7 @@
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, bt832_attach);
 #else
-	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+	if (adap->id == I2C_HW_B_BT848)
 		return i2c_probe(adap, &addr_data, bt832_attach);
 #endif
 	return 0;
@@ -241,7 +241,7 @@
 };
 static struct i2c_client client_template =
 {
-	I2C_DEVNAME("bt832"),
+	.name       = "bt832",
 	.flags      = I2C_CLIENT_ALLOW_USE,
         .driver     = &driver,
 };
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index a5d529c..c13d286 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -295,7 +295,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_bt856;
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index 234a855..706dc48 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -109,7 +109,7 @@
 #ifdef I2C_CLASS_TV_ANALOG
 	.class             = I2C_CLASS_TV_ANALOG,
 #endif
-	I2C_DEVNAME("bt848"),
+	.name              = "bt848",
 	.id                = I2C_HW_B_BT848,
 	.client_register   = attach_inform,
 };
@@ -270,8 +270,6 @@
 }
 
 static struct i2c_algorithm bttv_algo = {
-	.name          = "bt878",
-	.id            = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
 	.master_xfer   = bttv_i2c_xfer,
 	.algo_control  = algo_control,
 	.functionality = functionality,
@@ -282,8 +280,8 @@
 #ifdef I2C_CLASS_TV_ANALOG
 	.class         = I2C_CLASS_TV_ANALOG,
 #endif
-	I2C_DEVNAME("bt878"),
-	.id            = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
+	.name          = "bt878",
+	.id            = I2C_HW_B_BT848 /* FIXME */,
 	.algo          = &bttv_algo,
 	.client_register = attach_inform,
 };
@@ -298,7 +296,7 @@
 	if (bttv_debug)
 		printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n",
 			btv->c.nr,client->driver->name,client->addr,
-			i2c_clientname(client));
+			client->name);
 	if (!client->driver->command)
 		return 0;
 
@@ -326,7 +324,7 @@
 }
 
 static struct i2c_client bttv_i2c_client_template = {
-	I2C_DEVNAME("bttv internal"),
+	.name	= "bttv internal",
 };
 
 
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index a628a55..7f59803 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -95,7 +95,7 @@
 	struct cx88_core *core = i2c_get_adapdata(client->adapter);
 
 	dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->name,client->addr,i2c_clientname(client));
+		client->driver->name, client->addr, client->name);
 	if (!client->driver->command)
 		return 0;
 
@@ -128,7 +128,7 @@
 {
 	struct cx88_core *core = i2c_get_adapdata(client->adapter);
 
-	dprintk(1, "i2c detach [client=%s]\n", i2c_clientname(client));
+	dprintk(1, "i2c detach [client=%s]\n", client->name);
 	return 0;
 }
 
@@ -152,7 +152,7 @@
 /* ----------------------------------------------------------------------- */
 
 static struct i2c_adapter cx8800_i2c_adap_template = {
-	I2C_DEVNAME("cx2388x"),
+	.name              = "cx2388x",
 	.owner             = THIS_MODULE,
 	.id                = I2C_HW_B_CX2388x,
 	.client_register   = attach_inform,
@@ -160,7 +160,7 @@
 };
 
 static struct i2c_client cx8800_i2c_client_template = {
-        I2C_DEVNAME("cx88xx internal"),
+        .name	= "cx88xx internal",
 };
 
 static char *i2c_devs[128] = {
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 9fc5055..1e273ff 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -308,7 +308,7 @@
 
 static struct i2c_client client_template =
 {
-        I2C_DEVNAME("unset"),
+        .name = "unset",
         .driver = &driver
 };
 
@@ -429,10 +429,10 @@
 	struct i2c_client c; char buf; int i,rc;
 
 	switch (adap->id) {
-	case I2C_ALGO_BIT | I2C_HW_B_BT848:
+	case I2C_HW_B_BT848:
 		probe = probe_bttv;
 		break;
-	case I2C_ALGO_SAA7134:
+	case I2C_HW_SAA7134:
 		probe = probe_saa7134;
 		break;
 	}
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index e956234..ca02f6f 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -1437,7 +1437,7 @@
 
 static struct i2c_client client_template =
 {
-	I2C_DEVNAME("(unset)"),
+	.name      = "(unset)",
 	.flags     = I2C_CLIENT_ALLOW_USE,
         .driver    = &driver,
 };
@@ -1509,7 +1509,7 @@
 	}
 
 	/* hello world :-) */
-	printk(KERN_INFO "msp34xx: init: chip=%s",i2c_clientname(c));
+	printk(KERN_INFO "msp34xx: init: chip=%s", c->name);
 	if (HAVE_NICAM(msp))
 		printk(" +nicam");
 	if (HAVE_SIMPLE(msp))
diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c
index 3433619..b3f4d26 100644
--- a/drivers/media/video/ovcamchip/ov6x20.c
+++ b/drivers/media/video/ovcamchip/ov6x20.c
@@ -164,10 +164,10 @@
 	DDEBUG(4, &c->dev, "entered");
 
 	switch (c->adapter->id) {
-	case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511:
+	case I2C_HW_SMBUS_OV511:
 		rc = ov_write_regvals(c, regvals_init_6x20_511);
 		break;
-	case I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518:
+	case I2C_HW_SMBUS_OV518:
 		rc = ov_write_regvals(c, regvals_init_6x20_518);
 		break;
 	default:
@@ -338,7 +338,7 @@
 	/******** Palette-specific regs ********/
 
 	/* OV518 needs 8 bit multiplexed in color mode, and 16 bit in B&W */
-	if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+	if (c->adapter->id == I2C_HW_SMBUS_OV518) {
 		if (win->format == VIDEO_PALETTE_GREY)
 			ov_write_mask(c, 0x13, 0x00, 0x20);
 		else
diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c
index 44a8423..6eab458 100644
--- a/drivers/media/video/ovcamchip/ov6x30.c
+++ b/drivers/media/video/ovcamchip/ov6x30.c
@@ -301,7 +301,7 @@
 	/******** Palette-specific regs ********/
 
 	if (win->format == VIDEO_PALETTE_GREY) {
-		if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+		if (c->adapter->id == I2C_HW_SMBUS_OV518) {
 			/* Do nothing - we're already in 8-bit mode */
 		} else {
 			ov_write_mask(c, 0x13, 0x20, 0x20);
@@ -313,7 +313,7 @@
 		 * Therefore, the OV6630 needs to be in 8-bit multiplexed
 		 * output mode */
 
-		if (c->adapter->id == (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518)) {
+		if (c->adapter->id == I2C_HW_SMBUS_OV518) {
 			/* Do nothing - we want to stay in 8-bit mode */
 			/* Warning: Messing with reg 0x13 breaks OV518 color */
 		} else {
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 54dd561..2de34eb 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -296,10 +296,10 @@
 	 * attach to adapters that are known to contain OV camera chips. */
 
 	switch (adap->id) {
-	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV511):
-	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OV518):
-	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_OVFX2):
-	case (I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF):
+	case I2C_HW_SMBUS_OV511:
+	case I2C_HW_SMBUS_OV518:
+	case I2C_HW_SMBUS_OVFX2:
+	case I2C_HW_SMBUS_W9968CF:
 		PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
 		break;
 	default:
@@ -314,7 +314,7 @@
 	}
 	memcpy(c, &client_template, sizeof *c);
 	c->adapter = adap;
-	strcpy(i2c_clientname(c), "OV????");
+	strcpy(c->name, "OV????");
 
 	ov = kmalloc(sizeof *ov, GFP_KERNEL);
 	if (!ov) {
@@ -328,7 +328,7 @@
 	if (rc < 0)
 		goto error;
 
-	strcpy(i2c_clientname(c), chip_names[ov->subtype]);
+	strcpy(c->name, chip_names[ov->subtype]);
 
 	PDEBUG(1, "Camera chip detection complete");
 
@@ -421,7 +421,7 @@
 };
 
 static struct i2c_client client_template = {
-	I2C_DEVNAME("(unset)"),
+	.name =		"(unset)",
 	.driver =	&driver,
 };
 
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 22d055d..e116bdb 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -470,7 +470,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7110;
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index fcd8973..f18df53 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -489,7 +489,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7111;
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index 2ba997f..e0c70f5 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -827,7 +827,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7114;
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 79d05ea..382911c 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -598,7 +598,7 @@
 
 static struct i2c_client client_template =
 {
-	I2C_DEVNAME("saa6752hs"),
+	.name       = "saa6752hs",
 	.flags      = I2C_CLIENT_ALLOW_USE,
         .driver     = &driver,
 };
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 1203b93..eae6b52 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -334,7 +334,7 @@
 	struct tuner_setup tun_setup;
 
 	d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
-		client->driver->name,client->addr,i2c_clientname(client));
+		 client->driver->name, client->addr, client->name);
 
 	if (!client->driver->command)
 		return 0;
@@ -370,8 +370,6 @@
 }
 
 static struct i2c_algorithm saa7134_algo = {
-	.name          = "saa7134",
-	.id            = I2C_ALGO_SAA7134,
 	.master_xfer   = saa7134_i2c_xfer,
 	.algo_control  = algo_control,
 	.functionality = functionality,
@@ -382,14 +380,14 @@
 #ifdef I2C_CLASS_TV_ANALOG
 	.class         = I2C_CLASS_TV_ANALOG,
 #endif
-	I2C_DEVNAME("saa7134"),
-	.id            = I2C_ALGO_SAA7134,
+	.name          = "saa7134",
+	.id            = I2C_HW_SAA7134,
 	.algo          = &saa7134_algo,
 	.client_register = attach_inform,
 };
 
 static struct i2c_client saa7134_client_template = {
-	I2C_DEVNAME("saa7134 internal"),
+	.name	= "saa7134 internal",
 };
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 108e7a4..e93412f 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -387,7 +387,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7185;
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 7cb1fb3..255b608 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -328,7 +328,7 @@
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, tda7432_attach);
 #else
-	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+	if (adap->id == I2C_HW_B_BT848)
 		return i2c_probe(adap, &addr_data, tda7432_attach);
 #endif
 	return 0;
@@ -513,7 +513,7 @@
 
 static struct i2c_client client_template =
 {
-	I2C_DEVNAME("tda7432"),
+	.name       = "tda7432",
 	.driver     = &driver,
 };
 
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index c29bdfc..1794686 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -205,7 +205,7 @@
 static int attach(struct i2c_adapter *adapter)
 {
 	/* let's see whether this is a know adapter we can attach to */
-	if (adapter->id != I2C_ALGO_SAA7146) {
+	if (adapter->id != I2C_HW_SAA7146) {
 		dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
 		return -ENODEV;
 	}
@@ -231,7 +231,7 @@
 };
 
 static struct i2c_client client_template = {
-	I2C_DEVNAME("tda9840"),
+	.name = "tda9840",
 	.driver = &driver,
 };
 
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 566e1a5..7e3dcdb 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -262,7 +262,7 @@
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, tda9875_attach);
 #else
-	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+	if (adap->id == I2C_HW_B_BT848)
 		return i2c_probe(adap, &addr_data, tda9875_attach);
 #endif
 	return 0;
@@ -384,7 +384,7 @@
 
 static struct i2c_client client_template =
 {
-        I2C_DEVNAME("tda9875"),
+        .name      = "tda9875",
         .driver    = &driver,
 };
 
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index a28a395..d60fc56 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -618,9 +618,9 @@
 		return i2c_probe(adap, &addr_data, tda9887_attach);
 #else
 	switch (adap->id) {
-	case I2C_ALGO_BIT | I2C_HW_B_BT848:
-	case I2C_ALGO_BIT | I2C_HW_B_RIVA:
-	case I2C_ALGO_SAA7134:
+	case I2C_HW_B_BT848:
+	case I2C_HW_B_RIVA:
+	case I2C_HW_SAA7134:
 		return i2c_probe(adap, &addr_data, tda9887_attach);
 		break;
 	}
@@ -793,7 +793,7 @@
 };
 static struct i2c_client client_template =
 {
-	I2C_DEVNAME("tda9887"),
+	.name      = "tda9887",
 	.flags     = I2C_CLIENT_ALLOW_USE,
         .driver    = &driver,
 };
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index b44db8a..ee36883 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -86,7 +86,7 @@
 static int attach(struct i2c_adapter *adapter)
 {
 	/* let's see whether this is a know adapter we can attach to */
-	if (adapter->id != I2C_ALGO_SAA7146) {
+	if (adapter->id != I2C_HW_SAA7146) {
 		dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
 		return -ENODEV;
 	}
@@ -200,7 +200,7 @@
 };
 
 static struct i2c_client client_template = {
-	I2C_DEVNAME("tea6415c"),
+	.name = "tea6415c",
 	.driver = &driver,
 };
 
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 48d4db7..17975c1 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -135,7 +135,7 @@
 static int attach(struct i2c_adapter *adapter)
 {
 	/* let's see whether this is a know adapter we can attach to */
-	if (adapter->id != I2C_ALGO_SAA7146) {
+	if (adapter->id != I2C_HW_SAA7146) {
 		dprintk("refusing to probe on unknown adapter [name='%s',id=0x%x]\n", adapter->name, adapter->id);
 		return -ENODEV;
 	}
@@ -177,7 +177,7 @@
 };
 
 static struct i2c_client client_template = {
-	I2C_DEVNAME("tea6420"),
+	.name = "tea6420",
 	.driver = &driver,
 };
 
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 7d825e5..7920359 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -41,7 +41,6 @@
 	.normal_i2c	= normal_i2c,
 	.probe		= &ignore,
 	.ignore		= &ignore,
-	.force		= &ignore,
 };
 
 /* ---------------------------------------------------------------------- */
@@ -166,7 +165,7 @@
 tuner_probe(struct i2c_adapter *adap)
 {
 	this_adap = 0;
-	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_LP))
+	if (adap->id == I2C_HW_B_LP)
 		return i2c_probe(adap, &addr_data, tuner_attach);
 	return 0;
 }
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index a155e99..3b1893c 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -709,7 +709,7 @@
 		   },
 };
 static struct i2c_client client_template = {
-	I2C_DEVNAME("(tuner unset)"),
+	.name = "(tuner unset)",
 	.flags = I2C_CLIENT_ALLOW_USE,
 	.driver = &driver,
 };
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index f42a1ef..258724b 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -162,24 +162,23 @@
 	unsigned char buffer[2];
 
 	if (-1 == subaddr) {
-		dprintk("%s: chip_write: 0x%x\n",
-			i2c_clientname(&chip->c), val);
+		dprintk("%s: chip_write: 0x%x\n", chip->c.name, val);
 		chip->shadow.bytes[1] = val;
 		buffer[0] = val;
 		if (1 != i2c_master_send(&chip->c,buffer,1)) {
 			printk(KERN_WARNING "%s: I/O error (write 0x%x)\n",
-			       i2c_clientname(&chip->c), val);
+			       chip->c.name, val);
 			return -1;
 		}
 	} else {
 		dprintk("%s: chip_write: reg%d=0x%x\n",
-			i2c_clientname(&chip->c), subaddr, val);
+			chip->c.name, subaddr, val);
 		chip->shadow.bytes[subaddr+1] = val;
 		buffer[0] = subaddr;
 		buffer[1] = val;
 		if (2 != i2c_master_send(&chip->c,buffer,2)) {
 			printk(KERN_WARNING "%s: I/O error (write reg%d=0x%x)\n",
-			       i2c_clientname(&chip->c), subaddr, val);
+			       chip->c.name, subaddr, val);
 			return -1;
 		}
 	}
@@ -203,11 +202,10 @@
 	unsigned char buffer;
 
 	if (1 != i2c_master_recv(&chip->c,&buffer,1)) {
-		printk(KERN_WARNING "%s: I/O error (read)\n",
-		       i2c_clientname(&chip->c));
+		printk(KERN_WARNING "%s: I/O error (read)\n", chip->c.name);
 		return -1;
 	}
-	dprintk("%s: chip_read: 0x%x\n",i2c_clientname(&chip->c),buffer);
+	dprintk("%s: chip_read: 0x%x\n", chip->c.name, buffer);
 	return buffer;
 }
 
@@ -222,12 +220,11 @@
         write[0] = subaddr;
 
 	if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
-		printk(KERN_WARNING "%s: I/O error (read2)\n",
-		       i2c_clientname(&chip->c));
+		printk(KERN_WARNING "%s: I/O error (read2)\n", chip->c.name);
 		return -1;
 	}
 	dprintk("%s: chip_read2: reg%d=0x%x\n",
-		i2c_clientname(&chip->c),subaddr,read[0]);
+		chip->c.name, subaddr, read[0]);
 	return read[0];
 }
 
@@ -240,7 +237,7 @@
 
 	/* update our shadow register set; print bytes if (debug > 0) */
 	dprintk("%s: chip_cmd(%s): reg=%d, data:",
-		i2c_clientname(&chip->c),name,cmd->bytes[0]);
+		chip->c.name, name, cmd->bytes[0]);
 	for (i = 1; i < cmd->count; i++) {
 		dprintk(" 0x%x",cmd->bytes[i]);
 		chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i];
@@ -249,7 +246,7 @@
 
 	/* send data to the chip */
 	if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) {
-		printk(KERN_WARNING "%s: I/O error (%s)\n", i2c_clientname(&chip->c), name);
+		printk(KERN_WARNING "%s: I/O error (%s)\n", chip->c.name, name);
 		return -1;
 	}
 	return 0;
@@ -274,9 +271,9 @@
         struct CHIPSTATE *chip = data;
 	struct CHIPDESC  *desc = chiplist + chip->type;
 
-	daemonize("%s",i2c_clientname(&chip->c));
+	daemonize("%s", chip->c.name);
 	allow_signal(SIGTERM);
-	dprintk("%s: thread started\n", i2c_clientname(&chip->c));
+	dprintk("%s: thread started\n", chip->c.name);
 
 	for (;;) {
 		add_wait_queue(&chip->wq, &wait);
@@ -288,7 +285,7 @@
 		try_to_freeze();
 		if (chip->done || signal_pending(current))
 			break;
-		dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
+		dprintk("%s: thread wakeup\n", chip->c.name);
 
 		/* don't do anything for radio or if mode != auto */
 		if (chip->norm == VIDEO_MODE_RADIO || chip->mode != 0)
@@ -301,7 +298,7 @@
 		mod_timer(&chip->wt, jiffies+2*HZ);
 	}
 
-	dprintk("%s: thread exiting\n", i2c_clientname(&chip->c));
+	dprintk("%s: thread exiting\n", chip->c.name);
         complete_and_exit(&chip->texit, 0);
 	return 0;
 }
@@ -314,7 +311,7 @@
 	if (mode == chip->prevmode)
 	    return;
 
-	dprintk("%s: thread checkmode\n", i2c_clientname(&chip->c));
+	dprintk("%s: thread checkmode\n", chip->c.name);
 	chip->prevmode = mode;
 
 	if (mode & VIDEO_SOUND_STEREO)
@@ -1098,7 +1095,7 @@
 			    /* extern	*/ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF,
 			    /* off	*/ TDA8425_S1_OFF, /* on     */ TDA8425_S1_CH2};
 
-	if (chip->c.adapter->id == (I2C_ALGO_BIT | I2C_HW_B_RIVA)) {
+	if (chip->c.adapter->id == I2C_HW_B_RIVA) {
 		memcpy (desc->inputmap, inputmap, sizeof (inputmap));
 	}
 	return 0;
@@ -1501,7 +1498,7 @@
 		(desc->flags & CHIP_HAS_INPUTSEL)   ? " audiomux"    : "");
 
 	/* fill required data structures */
-	strcpy(i2c_clientname(&chip->c),desc->name);
+	strcpy(chip->c.name, desc->name);
 	chip->type = desc-chiplist;
 	chip->shadow.count = desc->registers+1;
         chip->prevmode = -1;
@@ -1538,7 +1535,7 @@
 		chip->tpid = kernel_thread(chip_thread,(void *)chip,0);
 		if (chip->tpid < 0)
 			printk(KERN_WARNING "%s: kernel_thread() failed\n",
-			       i2c_clientname(&chip->c));
+			       chip->c.name);
 		wake_up_interruptible(&chip->wq);
 	}
 	return 0;
@@ -1548,16 +1545,16 @@
 {
 	/* don't attach on saa7146 based cards,
 	   because dedicated drivers are used */
-	if ((adap->id & I2C_ALGO_SAA7146))
+	if (adap->id == I2C_HW_SAA7146)
 		return 0;
 #ifdef I2C_CLASS_TV_ANALOG
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, chip_attach);
 #else
 	switch (adap->id) {
-	case I2C_ALGO_BIT | I2C_HW_B_BT848:
-	case I2C_ALGO_BIT | I2C_HW_B_RIVA:
-	case I2C_ALGO_SAA7134:
+	case I2C_HW_B_BT848:
+	case I2C_HW_B_RIVA:
+	case I2C_HW_SAA7134:
 		return i2c_probe(adap, &addr_data, chip_attach);
 	}
 #endif
@@ -1591,7 +1588,7 @@
 	struct CHIPSTATE *chip = i2c_get_clientdata(client);
 	struct CHIPDESC  *desc = chiplist + chip->type;
 
-	dprintk("%s: chip_command 0x%x\n",i2c_clientname(&chip->c),cmd);
+	dprintk("%s: chip_command 0x%x\n", chip->c.name, cmd);
 
 	switch (cmd) {
 	case AUDC_SET_INPUT:
@@ -1702,7 +1699,7 @@
 
 static struct i2c_client client_template =
 {
-	I2C_DEVNAME("(unset)"),
+	.name       = "(unset)",
 	.flags      = I2C_CLIENT_ALLOW_USE,
         .driver     = &driver,
 };
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 127ec38..3c3356a 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -534,7 +534,7 @@
 tveeprom_attach_adapter (struct i2c_adapter *adapter)
 {
 	dprintk(1,"%s: id 0x%x\n",__FUNCTION__,adapter->id);
-	if (adapter->id != (I2C_ALGO_BIT | I2C_HW_B_BT848))
+	if (adapter->id != I2C_HW_B_BT848)
 		return 0;
 	return i2c_probe(adapter, &addr_data, tveeprom_detect_client);
 }
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 51b99cd..a43301a 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -91,7 +91,7 @@
         if (cmd == SOUND_MIXER_INFO) {
                 mixer_info info;
                 strlcpy(info.id, "tv card", sizeof(info.id));
-                strlcpy(info.name, i2c_clientname(client), sizeof(info.name));
+                strlcpy(info.name, client->name, sizeof(info.name));
                 info.modify_counter = 42 /* FIXME */;
                 if (copy_to_user(argp, &info, sizeof(info)))
                         return -EFAULT;
@@ -100,7 +100,7 @@
         if (cmd == SOUND_OLD_MIXER_INFO) {
                 _old_mixer_info info;
                 strlcpy(info.id, "tv card", sizeof(info.id));
-                strlcpy(info.name, i2c_clientname(client), sizeof(info.name));
+                strlcpy(info.name, client->name, sizeof(info.name));
                 if (copy_to_user(argp, &info, sizeof(info)))
                         return -EFAULT;
                 return 0;
@@ -276,9 +276,9 @@
 #else
 	/* TV card ??? */
 	switch (client->adapter->id) {
-	case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3:
-	case I2C_ALGO_BIT | I2C_HW_B_BT848:
-	case I2C_ALGO_BIT | I2C_HW_B_RIVA:
+	case I2C_HW_SMBUS_VOODOO3:
+	case I2C_HW_B_BT848:
+	case I2C_HW_B_RIVA:
 		/* ok, have a look ... */
 		break;
 	default:
@@ -295,7 +295,7 @@
 			devices[i].dev = NULL;
 			devices[i].minor = -1;
 			printk("tvmixer: %s unregistered (#1)\n",
-			       i2c_clientname(client));
+			       client->name);
 			return 0;
 		}
 	}
@@ -354,7 +354,7 @@
 		if (devices[i].minor != -1) {
 			unregister_sound_mixer(devices[i].minor);
 			printk("tvmixer: %s unregistered (#2)\n",
-			       i2c_clientname(devices[i].dev));
+			       devices[i].dev->name);
 		}
 	}
 }
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 5dbd9f6..4437bde 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -576,7 +576,6 @@
 	.normal_i2c		= normal_i2c,
 	.probe			= &ignore,
 	.ignore			= &ignore,
-	.force			= &ignore,
 };
 
 static struct i2c_driver vpx3220_i2c_driver;
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 2574308..eed2ace 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -737,7 +737,7 @@
 };
 
 static struct i2c_adapter zoran_i2c_adapter_template = {
-	I2C_DEVNAME("zr36057"),
+	.name = "zr36057",
 	.id = I2C_HW_B_ZR36067,
 	.algo = NULL,
 	.client_register = zoran_i2c_client_register,
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7d8bcb3..ae9e7a5 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -397,7 +397,7 @@
 	  If you're not building a kernel for a Sun 3, say N.
 
 config SUN3_82586
-	tristate "Sun3 on-board Intel 82586 support"
+	bool "Sun3 on-board Intel 82586 support"
 	depends on NET_ETHERNET && SUN3
 	help
 	  This driver enables support for the on-board Intel 82586 based
@@ -1924,12 +1924,15 @@
 	  If in doubt, say Y.
 
 config SIS190
-	tristate "SiS190 gigabit ethernet support"
+	tristate "SiS190/SiS191 gigabit ethernet support"
 	depends on PCI
 	select CRC32
 	select MII
 	---help---
-	  Say Y here if you have a SiS 190 PCI Gigabit Ethernet adapter.
+	  Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or
+	  a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to
+	  appear in lan on motherboard designs which are based on SiS 965
+	  and SiS 966 south bridge.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called sis190.  This is recommended.
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h
index f093488..bf3e7b6 100644
--- a/drivers/net/chelsio/common.h
+++ b/drivers/net/chelsio/common.h
@@ -88,7 +88,7 @@
 
 static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm)
 {
-	u8 *addr = 0;
+	u8 *addr = NULL;
 
 	if (rm->idx++ < rm->dev->mc_count) {
 		addr = rm->list->dmi_addr;
@@ -190,7 +190,7 @@
 struct peespi;
 
 struct adapter {
-	u8 *regs;
+	u8 __iomem *regs;
 	struct pci_dev *pdev;
 	unsigned long registered_device_map;
 	unsigned long open_device_map;
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 28ae478..349ebe7 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -824,7 +824,7 @@
 static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
         struct adapter *adapter = dev->priv;
-        struct mii_ioctl_data *data = (struct mii_ioctl_data *)&req->ifr_data;
+        struct mii_ioctl_data *data = if_mii(req);
 
 	switch (cmd) {
         case SIOCGMIIPHY:
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 93e9f87..51c2b3a 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -1270,7 +1270,7 @@
 
 /* Structure containing variables used by the shared code (e1000_hw.c) */
 struct e1000_hw {
-    uint8_t *hw_addr;
+    uint8_t __iomem *hw_addr;
     uint8_t *flash_address;
     e1000_mac_type mac_type;
     e1000_phy_type phy_type;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index fb6b232..7c9dbc8 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -58,11 +58,10 @@
 
 #define INT_CAUSE_UNMASK_ALL		0x0007ffff
 #define INT_CAUSE_UNMASK_ALL_EXT	0x0011ffff
-#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
 #define INT_CAUSE_MASK_ALL		0x00000000
+#define INT_CAUSE_MASK_ALL_EXT		0x00000000
 #define INT_CAUSE_CHECK_BITS		INT_CAUSE_UNMASK_ALL
 #define INT_CAUSE_CHECK_BITS_EXT	INT_CAUSE_UNMASK_ALL_EXT
-#endif
 
 #ifdef MV643XX_CHECKSUM_OFFLOAD_TX
 #define MAX_DESCS_PER_SKB	(MAX_SKB_FRAGS + 1)
@@ -259,14 +258,13 @@
 static void mv643xx_eth_set_rx_mode(struct net_device *dev)
 {
 	struct mv643xx_private *mp = netdev_priv(dev);
-	u32 config_reg;
 
-	config_reg = ethernet_get_config_reg(mp->port_num);
 	if (dev->flags & IFF_PROMISC)
-		config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+		mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
 	else
-		config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
-	ethernet_set_config_reg(mp->port_num, config_reg);
+		mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+
+	mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
 }
 
 /*
@@ -369,15 +367,6 @@
 
 			dev_kfree_skb_irq(pkt_info.return_info);
 			released = 0;
-
-			/*
-			 * Decrement the number of outstanding skbs counter on
-			 * the TX queue.
-			 */
-			if (mp->tx_ring_skbs == 0)
-				panic("ERROR - TX outstanding SKBs"
-						" counter is corrupted");
-			mp->tx_ring_skbs--;
 		} else
 			dma_unmap_page(NULL, pkt_info.buf_ptr,
 					pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -412,15 +401,13 @@
 	struct pkt_info pkt_info;
 
 #ifdef MV643XX_NAPI
-	while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
+	while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) {
 #else
 	while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
 #endif
 		mp->rx_ring_skbs--;
 		received_packets++;
-#ifdef MV643XX_NAPI
-		budget--;
-#endif
+
 		/* Update statistics. Note byte count includes 4 byte CRC count */
 		stats->rx_packets++;
 		stats->rx_bytes += pkt_info.byte_cnt;
@@ -1044,9 +1031,6 @@
 						DMA_TO_DEVICE);
 
 			dev_kfree_skb_irq(pkt_info.return_info);
-
-			if (mp->tx_ring_skbs)
-				mp->tx_ring_skbs--;
 		} else
 			dma_unmap_page(NULL, pkt_info.buf_ptr,
 					pkt_info.byte_cnt, DMA_TO_DEVICE);
@@ -1189,7 +1173,6 @@
 		pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
 							DMA_TO_DEVICE);
 		pkt_info.return_info = skb;
-		mp->tx_ring_skbs++;
 		status = eth_port_send(mp, &pkt_info);
 		if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
 			printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1274,7 +1257,6 @@
 				pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
 							ETH_TX_LAST_DESC;
 				pkt_info.return_info = skb;
-				mp->tx_ring_skbs++;
 			} else {
 				pkt_info.return_info = 0;
 			}
@@ -1311,7 +1293,6 @@
 	pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
 								DMA_TO_DEVICE);
 	pkt_info.return_info = skb;
-	mp->tx_ring_skbs++;
 	status = eth_port_send(mp, &pkt_info);
 	if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
 		printk(KERN_ERR "%s: Error on transmitting packet\n",
@@ -1356,6 +1337,43 @@
 	return &mp->stats;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static inline void mv643xx_enable_irq(struct mv643xx_private *mp)
+{
+	int port_num = mp->port_num;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mp->lock, flags);
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+					INT_CAUSE_UNMASK_ALL);
+	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+					INT_CAUSE_UNMASK_ALL_EXT);
+	spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static inline void mv643xx_disable_irq(struct mv643xx_private *mp)
+{
+	int port_num = mp->port_num;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mp->lock, flags);
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+					INT_CAUSE_MASK_ALL);
+	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+					INT_CAUSE_MASK_ALL_EXT);
+	spin_unlock_irqrestore(&mp->lock, flags);
+}
+
+static void mv643xx_netpoll(struct net_device *netdev)
+{
+	struct mv643xx_private *mp = netdev_priv(netdev);
+
+	mv643xx_disable_irq(mp);
+	mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
+	mv643xx_enable_irq(mp);
+}
+#endif
+
 /*/
  * mv643xx_eth_probe
  *
@@ -1406,6 +1424,10 @@
 	dev->weight = 64;
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = mv643xx_netpoll;
+#endif
+
 	dev->watchdog_timeo = 2 * HZ;
 	dev->tx_queue_len = mp->tx_ring_size;
 	dev->base_addr = 0;
@@ -1883,6 +1905,9 @@
 	/* Enable port Rx. */
 	mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
 						mp->port_rx_queue_command);
+
+	/* Disable port bandwidth limits by clearing MTU register */
+	mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0);
 }
 
 /*
@@ -2292,34 +2317,6 @@
 	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
 }
 
-/*
- * ethernet_set_config_reg - Set specified bits in configuration register.
- *
- * DESCRIPTION:
- *	This function sets specified bits in the given ethernet
- *	configuration register.
- *
- * INPUT:
- *	unsigned int	eth_port_num	Ethernet Port number.
- *	unsigned int	value		32 bit value.
- *
- * OUTPUT:
- *	The set bits in the value parameter are set in the configuration
- *	register.
- *
- * RETURN:
- *	None.
- *
- */
-static void ethernet_set_config_reg(unsigned int eth_port_num,
-							unsigned int value)
-{
-	unsigned int eth_config_reg;
-
-	eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num));
-	eth_config_reg |= value;
-	mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg);
-}
 
 static int eth_port_autoneg_supported(unsigned int eth_port_num)
 {
@@ -2346,31 +2343,6 @@
 }
 
 /*
- * ethernet_get_config_reg - Get the port configuration register
- *
- * DESCRIPTION:
- *	This function returns the configuration register value of the given
- *	ethernet port.
- *
- * INPUT:
- *	unsigned int	eth_port_num	Ethernet Port number.
- *
- * OUTPUT:
- *	None.
- *
- * RETURN:
- *	Port configuration register value.
- */
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
-{
-	unsigned int eth_config_reg;
-
-	eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG
-								(eth_port_num));
-	return eth_config_reg;
-}
-
-/*
  * eth_port_read_smi_reg - Read PHY registers
  *
  * DESCRIPTION:
@@ -2528,6 +2500,9 @@
 		return ETH_ERROR;
 	}
 
+	mp->tx_ring_skbs++;
+	BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
 	/* Get the Tx Desc ring indexes */
 	tx_desc_curr = mp->tx_curr_desc_q;
 	tx_desc_used = mp->tx_used_desc_q;
@@ -2594,6 +2569,9 @@
 	if (mp->tx_resource_err)
 		return ETH_QUEUE_FULL;
 
+	mp->tx_ring_skbs++;
+	BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
+
 	/* Get the Tx Desc ring indexes */
 	tx_desc_curr = mp->tx_curr_desc_q;
 	tx_desc_used = mp->tx_used_desc_q;
@@ -2694,6 +2672,9 @@
 	/* Any Tx return cancels the Tx resource error status */
 	mp->tx_resource_err = 0;
 
+	BUG_ON(mp->tx_ring_skbs == 0);
+	mp->tx_ring_skbs--;
+
 	return ETH_OK;
 }
 
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
index 7678b59..bcfda51 100644
--- a/drivers/net/mv643xx_eth.h
+++ b/drivers/net/mv643xx_eth.h
@@ -408,10 +408,6 @@
 static void eth_port_reset(unsigned int eth_port_num);
 static void eth_port_start(struct mv643xx_private *mp);
 
-static void ethernet_set_config_reg(unsigned int eth_port_num,
-				    unsigned int value);
-static unsigned int ethernet_get_config_reg(unsigned int eth_port_num);
-
 /* Port MAC address routines */
 static void eth_port_uc_addr_set(unsigned int eth_port_num,
 				 unsigned char *p_addr);
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index 6c92f09..73501d8 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -26,9 +26,6 @@
 	Updated to EISA probing API 5/2003 by Marc Zyngier.
 */
 
-static const char *version =
-	"ne3210.c: Driver revision v0.03, 30/09/98\n";
-
 #include <linux/module.h>
 #include <linux/eisa.h>
 #include <linux/kernel.h>
@@ -197,7 +194,7 @@
 	ei_status.priv = phys_mem;
 
 	if (ei_debug > 0)
-		printk(version);
+		printk("ne3210 loaded.\n");
 
 	ei_status.reset_8390 = &ne3210_reset_8390;
 	ei_status.block_input = &ne3210_block_input;
@@ -360,12 +357,12 @@
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(eisa, ne3210_ids);
 
-int ne3210_init(void)
+static int ne3210_init(void)
 {
 	return eisa_driver_register (&ne3210_eisa_driver);
 }
 
-void ne3210_cleanup(void)
+static void ne3210_cleanup(void)
 {
 	eisa_driver_unregister (&ne3210_eisa_driver);
 }
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 6a2fe35..14f4de1 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -6,7 +6,7 @@
 
 config PHYLIB
 	tristate "PHY Device support and infrastructure"
-	depends on NET_ETHERNET
+	depends on NET_ETHERNET && (BROKEN || !ARCH_S390)
 	help
 	  Ethernet controllers are usually attached to PHY
 	  devices.  This option provides infrastructure for
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 5e81494..9063067 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -170,7 +170,7 @@
 	return bus_register(&mdio_bus_type);
 }
 
-void __exit mdio_bus_exit(void)
+void mdio_bus_exit(void)
 {
 	bus_unregister(&mdio_bus_type);
 }
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 7ca7822..5dda043 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -686,7 +686,7 @@
 
 static int s2io_verify_pci_mode(nic_t *nic)
 {
-	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
 	register u64 val64 = 0;
 	int     mode;
 
@@ -704,7 +704,7 @@
  */
 static int s2io_print_pci_mode(nic_t *nic)
 {
-	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
 	register u64 val64 = 0;
 	int	mode;
 	struct config_param *config = &nic->config;
@@ -1403,7 +1403,7 @@
 	writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7);
 
 	/* Disable RMAC PAD STRIPPING */
-	add = (void *) &bar0->mac_cfg;
+	add = &bar0->mac_cfg;
 	val64 = readq(&bar0->mac_cfg);
 	val64 &= ~(MAC_CFG_RMAC_STRIP_PAD);
 	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key);
@@ -1934,7 +1934,7 @@
 		val64 |= 0x0000800000000000ULL;
 		writeq(val64, &bar0->gpio_control);
 		val64 = 0x0411040400000000ULL;
-		writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
+		writeq(val64, (void __iomem *)bar0 + 0x2700);
 	}
 
 	/*
@@ -2395,7 +2395,7 @@
 	int pkt_cnt = 0, org_pkts_to_process;
 	mac_info_t *mac_control;
 	struct config_param *config;
-	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
 	u64 val64;
 	int i;
 
@@ -2831,7 +2831,7 @@
 		val64 |= 0x0000800000000000ULL;
 		writeq(val64, &bar0->gpio_control);
 		val64 = 0x0411040400000000ULL;
-		writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));
+		writeq(val64, (void __iomem *)bar0 + 0x2700);
 	}
 
 	/*
@@ -3234,7 +3234,7 @@
 
 static void s2io_txpic_intr_handle(nic_t *sp)
 {
-	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0;
+	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	u64 val64;
 
 	val64 = readq(&bar0->pic_int_status);
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index bf3440a..92f7552 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -179,14 +179,6 @@
 	TxInterFrameGapShift	= 24,
 	TxDMAShift		= 8, /* DMA burst value (0-7) is shift this many bits */
 
-	/* StationControl */
-	_1000bpsF		= 0x1c00,
-	_1000bpsH		= 0x0c00,
-	_100bpsF		= 0x1800,
-	_100bpsH		= 0x0800,
-	_10bpsF			= 0x1400,
-	_10bpsH			= 0x0400,
-
 	LinkStatus		= 0x02,		// unused
 	FullDup			= 0x01,		// unused
 
@@ -279,6 +271,12 @@
 	EEPROMMACAddr	= 0x03
 };
 
+enum sis190_feature {
+	F_HAS_RGMII	= 1,
+	F_PHY_88E1111	= 2,
+	F_PHY_BCM5461	= 4
+};
+
 struct sis190_private {
 	void __iomem *mmio_addr;
 	struct pci_dev *pci_dev;
@@ -300,6 +298,7 @@
 	u32 msg_enable;
 	struct mii_if_info mii_if;
 	struct list_head first_phy;
+	u32 features;
 };
 
 struct sis190_phy {
@@ -321,24 +320,25 @@
         const char *name;
         u16 id[2];
         unsigned int type;
+	u32 feature;
 } mii_chip_table[] = {
-	{ "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN },
-	{ "Agere PHY ET1101B",    { 0x0282, 0xf010 }, LAN },
-	{ "Marvell PHY 88E1111",  { 0x0141, 0x0cc0 }, LAN },
-	{ "Realtek PHY RTL8201",  { 0x0000, 0x8200 }, LAN },
+	{ "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
+	{ "Agere PHY ET1101B",    { 0x0282, 0xf010 }, LAN, 0 },
+	{ "Marvell PHY 88E1111",  { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
+	{ "Realtek PHY RTL8201",  { 0x0000, 0x8200 }, LAN, 0 },
 	{ NULL, }
 };
 
 const static struct {
 	const char *name;
-	u8 version;		/* depend on docs */
-	u32 RxConfigMask;	/* clear the bits supported by this chip */
 } sis_chip_info[] = {
-	{ DRV_NAME, 0x00, 0xff7e1880, },
+	{ "SiS 190 PCI Fast Ethernet adapter" },
+	{ "SiS 191 PCI Gigabit Ethernet adapter" },
 };
 
 static struct pci_device_id sis190_pci_tbl[] __devinitdata = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
 	{ 0, },
 };
 
@@ -360,7 +360,7 @@
 MODULE_LICENSE("GPL");
 
 static const u32 sis190_intr_mask =
-	RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt;
+	RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
 
 /*
  * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
@@ -879,11 +879,6 @@
 
 	SIS_W32(IntrStatus, 0xffffffff);
 	SIS_W32(IntrMask, 0x0);
-	/*
-	 * Default is 100Mbps.
-	 * A bit strange: 100Mbps is 0x1801 elsewhere -- FR 2005/06/09
-	 */
-	SIS_W16(StationControl, 0x1901);
 	SIS_W32(GMIIControl, 0x0);
 	SIS_W32(TxMacControl, 0x60);
 	SIS_W16(RxMacControl, 0x02);
@@ -923,35 +918,30 @@
 		     BMSR_ANEGCOMPLETE)) {
 		net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n",
 			 dev->name);
+		netif_carrier_off(dev);
 		mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET);
 		mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
 	} else {
 		/* Rejoice ! */
 		struct {
 			int val;
+			u32 ctl;
 			const char *msg;
-			u16 ctl;
 		} reg31[] = {
-			{ LPA_1000XFULL | LPA_SLCT,
-				"1000 Mbps Full Duplex",
-				0x01 | _1000bpsF },
-			{ LPA_1000XHALF | LPA_SLCT,
-				"1000 Mbps Half Duplex",
-				0x01 | _1000bpsH },
-			{ LPA_100FULL,
-				"100 Mbps Full Duplex",
-				0x01 | _100bpsF },
-			{ LPA_100HALF,
-				"100 Mbps Half Duplex",
-				0x01 | _100bpsH },
-			{ LPA_10FULL,
-				"10 Mbps Full Duplex",
-				0x01 | _10bpsF },
-			{ LPA_10HALF,
-				"10 Mbps Half Duplex",
-				0x01 | _10bpsH },
-			{ 0, "unknown", 0x0000 }
-		}, *p;
+			{ LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000,
+				"1000 Mbps Full Duplex" },
+			{ LPA_1000XHALF | LPA_SLCT, 0x07000c00,
+				"1000 Mbps Half Duplex" },
+			{ LPA_100FULL, 0x04000800 | 0x00001000,
+				"100 Mbps Full Duplex" },
+			{ LPA_100HALF, 0x04000800,
+				"100 Mbps Half Duplex" },
+			{ LPA_10FULL, 0x04000400 | 0x00001000,
+				"10 Mbps Full Duplex" },
+			{ LPA_10HALF, 0x04000400,
+				"10 Mbps Half Duplex" },
+			{ 0, 0x04000400, "unknown" }
+ 		}, *p;
 		u16 adv;
 
 		val = mdio_read(ioaddr, phy_id, 0x1f);
@@ -964,12 +954,29 @@
 
 		val &= adv;
 
-		for (p = reg31; p->ctl; p++) {
+		for (p = reg31; p->val; p++) {
 			if ((val & p->val) == p->val)
 				break;
 		}
-		if (p->ctl)
-			SIS_W16(StationControl, p->ctl);
+
+		p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
+
+		if ((tp->features & F_HAS_RGMII) &&
+		    (tp->features & F_PHY_BCM5461)) {
+			// Set Tx Delay in RGMII mode.
+			mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
+			udelay(200);
+			mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
+			p->ctl |= 0x03000000;
+		}
+
+		SIS_W32(StationControl, p->ctl);
+
+		if (tp->features & F_HAS_RGMII) {
+			SIS_W32(RGDelay, 0x0441);
+			SIS_W32(RGDelay, 0x0440);
+		}
+
 		net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name,
 			 p->msg);
 		netif_carrier_on(dev);
@@ -1308,6 +1315,7 @@
 		phy->type = (p->type == MIX) ?
 			((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
 				LAN : HOME) : p->type;
+		tp->features |= p->feature;
 	} else
 		phy->type = UNKNOWN;
 
@@ -1316,6 +1324,25 @@
 		  (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id);
 }
 
+static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
+{
+	if (tp->features & F_PHY_88E1111) {
+		void __iomem *ioaddr = tp->mmio_addr;
+		int phy_id = tp->mii_if.phy_id;
+		u16 reg[2][2] = {
+			{ 0x808b, 0x0ce1 },
+			{ 0x808f, 0x0c60 }
+		}, *p;
+
+		p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
+
+		mdio_write(ioaddr, phy_id, 0x1b, p[0]);
+		udelay(200);
+		mdio_write(ioaddr, phy_id, 0x14, p[1]);
+		udelay(200);
+	}
+}
+
 /**
  *	sis190_mii_probe - Probe MII PHY for sis190
  *	@dev: the net device to probe for
@@ -1366,6 +1393,8 @@
 	/* Select default PHY for mac */
 	sis190_default_phy(dev);
 
+	sis190_mii_probe_88e1111_fixup(tp);
+
 	mii_if->dev = dev;
 	mii_if->mdio_read = __mdio_read;
 	mii_if->mdio_write = __mdio_write;
@@ -1505,6 +1534,11 @@
 	netif_wake_queue(dev);
 }
 
+static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
+{
+	tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
+}
+
 static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
 						     struct net_device *dev)
 {
@@ -1532,6 +1566,8 @@
 		((u16 *)dev->dev_addr)[0] = le16_to_cpu(w);
 	}
 
+	sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
+
 	return 0;
 }
 
@@ -1577,6 +1613,8 @@
 	outb(0x12, 0x78);
 	reg = inb(0x79);
 
+	sis190_set_rgmii(tp, reg);
+
 	/* Restore the value to ISA Bridge */
 	pci_write_config_byte(isa_bridge, 0x48, tmp8);
 	pci_dev_put(isa_bridge);
@@ -1799,6 +1837,9 @@
 	       dev->dev_addr[2], dev->dev_addr[3],
 	       dev->dev_addr[4], dev->dev_addr[5]);
 
+	net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
+		  (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
+
 	netif_carrier_off(dev);
 
 	sis190_set_speed_auto(dev);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3faf623..dc57352 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -36,6 +36,7 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/workqueue.h>
+#include <linux/prefetch.h>
 
 #include <net/checksum.h>
 
@@ -66,8 +67,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.38"
-#define DRV_MODULE_RELDATE	"September 1, 2005"
+#define DRV_MODULE_VERSION	"3.39"
+#define DRV_MODULE_RELDATE	"September 5, 2005"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -487,7 +488,8 @@
 
 static inline void tg3_cond_int(struct tg3 *tp)
 {
-	if (tp->hw_status->status & SD_STATUS_UPDATED)
+	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+	    (tp->hw_status->status & SD_STATUS_UPDATED))
 		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
 }
 
@@ -3219,18 +3221,17 @@
 		netdev->quota -= work_done;
 	}
 
-	if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+	if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
 		tp->last_tag = sblk->status_tag;
-	rmb();
-	sblk->status &= ~SD_STATUS_UPDATED;
+		rmb();
+	} else
+		sblk->status &= ~SD_STATUS_UPDATED;
 
 	/* if no more work, tell net stack and NIC we're done */
 	done = !tg3_has_work(tp);
 	if (done) {
-		spin_lock(&tp->lock);
 		netif_rx_complete(netdev);
 		tg3_restart_ints(tp);
-		spin_unlock(&tp->lock);
 	}
 
 	return (done ? 0 : 1);
@@ -3278,8 +3279,9 @@
 {
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
-	struct tg3_hw_status *sblk = tp->hw_status;
 
+	prefetch(tp->hw_status);
+	prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
 	/*
 	 * Writing any value to intr-mbox-0 clears PCI INTA# and
 	 * chip-internal interrupt pending events.
@@ -3288,19 +3290,9 @@
 	 * event coalescing.
 	 */
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
-	tp->last_tag = sblk->status_tag;
-	rmb();
-	if (tg3_irq_sync(tp))
-		goto out;
-	sblk->status &= ~SD_STATUS_UPDATED;
-	if (likely(tg3_has_work(tp)))
+	if (likely(!tg3_irq_sync(tp)))
 		netif_rx_schedule(dev);		/* schedule NAPI poll */
-	else {
-		/* No work, re-enable interrupts.  */
-		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-			     tp->last_tag << 24);
-	}
-out:
+
 	return IRQ_RETVAL(1);
 }
 
@@ -3330,9 +3322,10 @@
 		if (tg3_irq_sync(tp))
 			goto out;
 		sblk->status &= ~SD_STATUS_UPDATED;
-		if (likely(tg3_has_work(tp)))
+		if (likely(tg3_has_work(tp))) {
+			prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
 			netif_rx_schedule(dev);		/* schedule NAPI poll */
-		else {
+		} else {
 			/* No work, shared interrupt perhaps?  re-enable
 			 * interrupts, and flush that PCI write
 			 */
@@ -3358,7 +3351,7 @@
 	 * Reading the PCI State register will confirm whether the
 	 * interrupt is ours and will flush the status block.
 	 */
-	if ((sblk->status & SD_STATUS_UPDATED) ||
+	if ((sblk->status_tag != tp->last_tag) ||
 	    !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
 		/*
 		 * writing any value to intr-mbox-0 clears PCI INTA# and
@@ -3369,19 +3362,17 @@
 		 */
 		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 			     0x00000001);
-		tp->last_tag = sblk->status_tag;
-		rmb();
 		if (tg3_irq_sync(tp))
 			goto out;
-		sblk->status &= ~SD_STATUS_UPDATED;
-		if (likely(tg3_has_work(tp)))
-			netif_rx_schedule(dev);		/* schedule NAPI poll */
-		else {
-			/* no work, shared interrupt perhaps?  re-enable
-			 * interrupts, and flush that PCI write
+		if (netif_rx_schedule_prep(dev)) {
+			prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+			/* Update last_tag to mark that this status has been
+			 * seen. Because interrupt may be shared, we may be
+			 * racing with tg3_poll(), so only update last_tag
+			 * if tg3_poll() is not scheduled.
 			 */
-			tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-				       tp->last_tag << 24);
+			tp->last_tag = sblk->status_tag;
+			__netif_rx_schedule(dev);
 		}
 	} else {	/* shared interrupt */
 		handled = 0;
@@ -5962,7 +5953,7 @@
 	tw32(MAC_LED_CTRL, tp->led_ctrl);
 
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
-	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) {
 		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
 		udelay(10);
 	}
@@ -6244,6 +6235,7 @@
 	if (err)
 		return err;
 
+	tp->hw_status->status &= ~SD_STATUS_UPDATED;
 	tg3_enable_ints(tp);
 
 	tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
@@ -7559,6 +7551,38 @@
 	}
 }
 
+static int tg3_phys_id(struct net_device *dev, u32 data)
+{
+	struct tg3 *tp = netdev_priv(dev);
+	int i;
+
+	if (!netif_running(tp->dev))
+		return -EAGAIN;
+
+	if (data == 0)
+		data = 2;
+
+	for (i = 0; i < (data * 2); i++) {
+		if ((i % 2) == 0)
+			tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+					   LED_CTRL_1000MBPS_ON |
+					   LED_CTRL_100MBPS_ON |
+					   LED_CTRL_10MBPS_ON |
+					   LED_CTRL_TRAFFIC_OVERRIDE |
+					   LED_CTRL_TRAFFIC_BLINK |
+					   LED_CTRL_TRAFFIC_LED);
+	
+		else
+			tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+					   LED_CTRL_TRAFFIC_OVERRIDE);
+
+		if (msleep_interruptible(500))
+			break;
+	}
+	tw32(MAC_LED_CTRL, tp->led_ctrl);
+	return 0;
+}
+
 static void tg3_get_ethtool_stats (struct net_device *dev,
 				   struct ethtool_stats *estats, u64 *tmp_stats)
 {
@@ -7618,7 +7642,7 @@
 	if (!netif_running(tp->dev))
 		return -ENODEV;
 
-	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
 		max = TG3_SERDES_TIMEOUT_SEC;
 	else
 		max = TG3_COPPER_TIMEOUT_SEC;
@@ -7903,9 +7927,12 @@
 	return err;
 }
 
-static int tg3_test_loopback(struct tg3 *tp)
+#define TG3_MAC_LOOPBACK	0
+#define TG3_PHY_LOOPBACK	1
+
+static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 {
-	u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key;
+	u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
 	u32 desc_idx;
 	struct sk_buff *skb, *rx_skb;
 	u8 *tx_data;
@@ -7913,18 +7940,26 @@
 	int num_pkts, tx_len, rx_len, i, err;
 	struct tg3_rx_buffer_desc *desc;
 
-	if (!netif_running(tp->dev))
-		return -ENODEV;
+	if (loopback_mode == TG3_MAC_LOOPBACK) {
+		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+			   MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
+			   MAC_MODE_PORT_MODE_GMII;
+		tw32(MAC_MODE, mac_mode);
+	} else if (loopback_mode == TG3_PHY_LOOPBACK) {
+		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+			   MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
+		if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+			mac_mode &= ~MAC_MODE_LINK_POLARITY;
+		tw32(MAC_MODE, mac_mode);
+
+		tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+					   BMCR_SPEED1000);
+	}
+	else
+		return -EINVAL;
 
 	err = -EIO;
 
-	tg3_reset_hw(tp);
-
-	mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-		   MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
-		   MAC_MODE_PORT_MODE_GMII;
-	tw32(MAC_MODE, mac_mode);
-
 	tx_len = 1514;
 	skb = dev_alloc_skb(tx_len);
 	tx_data = skb_put(skb, tx_len);
@@ -7945,15 +7980,15 @@
 
 	rx_start_idx = tp->hw_status->idx[0].rx_producer;
 
-	send_idx = 0;
 	num_pkts = 0;
 
-	tg3_set_txd(tp, send_idx, map, tx_len, 0, 1);
+	tg3_set_txd(tp, tp->tx_prod, map, tx_len, 0, 1);
 
-	send_idx++;
+	tp->tx_prod++;
 	num_pkts++;
 
-	tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx);
+	tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW,
+		     tp->tx_prod);
 	tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
 
 	udelay(10);
@@ -7966,7 +8001,7 @@
 
 		tx_idx = tp->hw_status->idx[0].tx_consumer;
 		rx_idx = tp->hw_status->idx[0].rx_producer;
-		if ((tx_idx == send_idx) &&
+		if ((tx_idx == tp->tx_prod) &&
 		    (rx_idx == (rx_start_idx + num_pkts)))
 			break;
 	}
@@ -7974,7 +8009,7 @@
 	pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
 	dev_kfree_skb(skb);
 
-	if (tx_idx != send_idx)
+	if (tx_idx != tp->tx_prod)
 		goto out;
 
 	if (rx_idx != rx_start_idx + num_pkts)
@@ -8010,6 +8045,30 @@
 	return err;
 }
 
+#define TG3_MAC_LOOPBACK_FAILED		1
+#define TG3_PHY_LOOPBACK_FAILED		2
+#define TG3_LOOPBACK_FAILED		(TG3_MAC_LOOPBACK_FAILED |	\
+					 TG3_PHY_LOOPBACK_FAILED)
+
+static int tg3_test_loopback(struct tg3 *tp)
+{
+	int err = 0;
+
+	if (!netif_running(tp->dev))
+		return TG3_LOOPBACK_FAILED;
+
+	tg3_reset_hw(tp);
+
+	if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
+		err |= TG3_MAC_LOOPBACK_FAILED;
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+		if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
+			err |= TG3_PHY_LOOPBACK_FAILED;
+	}
+
+	return err;
+}
+
 static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 			  u64 *data)
 {
@@ -8050,10 +8109,8 @@
 			etest->flags |= ETH_TEST_FL_FAILED;
 			data[3] = 1;
 		}
-		if (tg3_test_loopback(tp) != 0) {
+		if ((data[4] = tg3_test_loopback(tp)) != 0)
 			etest->flags |= ETH_TEST_FL_FAILED;
-			data[4] = 1;
-		}
 
 		tg3_full_unlock(tp);
 
@@ -8241,6 +8298,7 @@
 	.self_test_count	= tg3_get_test_count,
 	.self_test		= tg3_self_test,
 	.get_strings		= tg3_get_strings,
+	.phys_id		= tg3_phys_id,
 	.get_stats_count	= tg3_get_stats_count,
 	.get_ethtool_stats	= tg3_get_ethtool_stats,
 	.get_coalesce		= tg3_get_coalesce,
@@ -8305,7 +8363,8 @@
 		tw32(NVRAM_CFG1, nvcfg1);
 	}
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)) {
 		switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
 			case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
 				tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -8719,8 +8778,9 @@
 		if (i == (len - 4))
 			nvram_cmd |= NVRAM_CMD_LAST;
 
-		if ((tp->nvram_jedecnum == JEDEC_ST) &&
-			(nvram_cmd & NVRAM_CMD_FIRST)) {
+		if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
+		    (tp->nvram_jedecnum == JEDEC_ST) &&
+		    (nvram_cmd & NVRAM_CMD_FIRST)) {
 
 			if ((ret = tg3_nvram_exec_cmd(tp,
 				NVRAM_CMD_WREN | NVRAM_CMD_GO |
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 5ae22b7..1a431633 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -21,7 +21,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
@@ -34,6 +33,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/processor.h>
 #include <asm/bitops.h>
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index dd7dbf7b..00a07f3 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -289,8 +289,8 @@
 	  a non-standard interface
 
 config PLX_HERMES
-	tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)"
-	depends on PCI && HERMES && EXPERIMENTAL
+	tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
+	depends on PCI && HERMES
 	help
 	  Enable support for PCMCIA cards supported by the "Hermes" (aka
 	  orinoco) driver when used in PLX9052 based PCI adaptors.  These
@@ -299,12 +299,9 @@
 	  802.11b PCMCIA cards can be used in desktop machines.  The Netgear
 	  MA301 is such an adaptor.
 
-	  Support for these adaptors is so far still incomplete and buggy.
-	  You have been warned.
-
 config TMD_HERMES
-	tristate "Hermes in TMD7160 based PCI adaptor support (EXPERIMENTAL)"
-	depends on PCI && HERMES && EXPERIMENTAL
+	tristate "Hermes in TMD7160 based PCI adaptor support"
+	depends on PCI && HERMES
 	help
 	  Enable support for PCMCIA cards supported by the "Hermes" (aka
 	  orinoco) driver when used in TMD7160 based PCI adaptors.  These
@@ -312,12 +309,18 @@
 	  PCI <-> PCMCIA bridge.  Several vendors sell such adaptors so that
 	  802.11b PCMCIA cards can be used in desktop machines.
 
-	  Support for these adaptors is so far still incomplete and buggy.
-	  You have been warned.
+config NORTEL_HERMES
+	tristate "Nortel emobility PCI adaptor support"
+	depends on PCI && HERMES
+	help
+	  Enable support for PCMCIA cards supported by the "Hermes" (aka
+	  orinoco) driver when used in Nortel emobility PCI adaptors.  These
+	  adaptors are not full PCMCIA controllers, but act as a more limited
+	  PCI <-> PCMCIA bridge.
 
 config PCI_HERMES
-	tristate "Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)"
-	depends on PCI && HERMES && EXPERIMENTAL
+	tristate "Prism 2.5 PCI 802.11b adaptor support"
+	depends on PCI && HERMES
 	help
 	  Enable support for PCI and mini-PCI 802.11b wireless NICs based on
 	  the Prism 2.5 chipset.  These are true PCI cards, not the 802.11b
@@ -372,6 +375,19 @@
 	  configure your card and that /etc/pcmcia/wireless.opts works:
 	  <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
 
+config PCMCIA_SPECTRUM
+	tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
+	depends on NET_RADIO && PCMCIA && HERMES
+	---help---
+
+	  This is a driver for 802.11b cards using RAM-loadable Symbol
+	  firmware, such as Symbol Wireless Networker LA4100, CompactFlash
+	  cards by Socket Communications and Intel PRO/Wireless 2011B.
+
+	  This driver requires firmware download on startup.  Utilities
+	  for downloading Symbol firmware are available at
+	  <http://sourceforge.net/projects/orinoco/>
+
 config AIRO_CS
 	tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
 	depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 0953cc0..3a6f7ba 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -22,6 +22,8 @@
 obj-$(CONFIG_PLX_HERMES)	+= orinoco_plx.o
 obj-$(CONFIG_PCI_HERMES)	+= orinoco_pci.o
 obj-$(CONFIG_TMD_HERMES)	+= orinoco_tmd.o
+obj-$(CONFIG_NORTEL_HERMES)	+= orinoco_nortel.o
+obj-$(CONFIG_PCMCIA_SPECTRUM)	+= spectrum_cs.o
 
 obj-$(CONFIG_AIRO)		+= airo.o
 obj-$(CONFIG_AIRO_CS)		+= airo_cs.o airo.o
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index a47fce4..2414e64 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -327,38 +327,38 @@
 
 static inline void read_register(struct net_device *dev, u32 reg, u32 *val)
 {
-	*val = readl((void *)(dev->base_addr + reg));
+	*val = readl((void __iomem *)(dev->base_addr + reg));
 	IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val);
 }
 
 static inline void write_register(struct net_device *dev, u32 reg, u32 val)
 {
-	writel(val, (void *)(dev->base_addr + reg));
+	writel(val, (void __iomem *)(dev->base_addr + reg));
 	IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val);
 }
 
 static inline void read_register_word(struct net_device *dev, u32 reg, u16 *val)
 {
-	*val = readw((void *)(dev->base_addr + reg));
+	*val = readw((void __iomem *)(dev->base_addr + reg));
 	IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val);
 }
 
 static inline void read_register_byte(struct net_device *dev, u32 reg, u8 *val)
 {
-	*val = readb((void *)(dev->base_addr + reg));
+	*val = readb((void __iomem *)(dev->base_addr + reg));
 	IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val);
 }
 
 static inline void write_register_word(struct net_device *dev, u32 reg, u16 val)
 {
-	writew(val, (void *)(dev->base_addr + reg));
+	writew(val, (void __iomem *)(dev->base_addr + reg));
 	IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val);
 }
 
 
 static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val)
 {
-	writeb(val, (void *)(dev->base_addr + reg));
+	writeb(val, (void __iomem *)(dev->base_addr + reg));
 	IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val);
 }
 
@@ -498,7 +498,7 @@
 static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev)
 {
 	return (dev->base_addr &&
-		(readl((void *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START))
+		(readl((void __iomem *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START))
 		 == IPW_DATA_DOA_DEBUG_VALUE));
 }
 
@@ -2125,19 +2125,19 @@
 }
 
 static const struct ipw2100_status_indicator status_handlers[] = {
-	IPW2100_HANDLER(IPW_STATE_INITIALIZED, 0),
-	IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, 0),
+	IPW2100_HANDLER(IPW_STATE_INITIALIZED, NULL),
+	IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, NULL),
 	IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated),
 	IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost),
-	IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, 0),
+	IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, NULL),
 	IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete),
-	IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, 0),
-	IPW2100_HANDLER(IPW_STATE_LEFT_PSP, 0),
+	IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, NULL),
+	IPW2100_HANDLER(IPW_STATE_LEFT_PSP, NULL),
 	IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill),
-	IPW2100_HANDLER(IPW_STATE_DISABLED, 0),
-	IPW2100_HANDLER(IPW_STATE_POWER_DOWN, 0),
+	IPW2100_HANDLER(IPW_STATE_DISABLED, NULL),
+	IPW2100_HANDLER(IPW_STATE_POWER_DOWN, NULL),
 	IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning),
-	IPW2100_HANDLER(-1, 0)
+	IPW2100_HANDLER(-1, NULL)
 };
 
 
@@ -6327,7 +6327,7 @@
 
 static struct net_device *ipw2100_alloc_device(
 	struct pci_dev *pci_dev,
-	char *base_addr,
+	void __iomem *base_addr,
 	unsigned long mem_start,
 	unsigned long mem_len)
 {
@@ -6474,7 +6474,7 @@
 				const struct pci_device_id *ent)
 {
 	unsigned long mem_start, mem_len, mem_flags;
-	char *base_addr = NULL;
+	void __iomem *base_addr = NULL;
 	struct net_device *dev = NULL;
 	struct ipw2100_priv *priv = NULL;
 	int err = 0;
@@ -6664,7 +6664,7 @@
 	}
 
 	if (base_addr)
-		iounmap((char*)base_addr);
+		iounmap(base_addr);
 
 	pci_release_regions(pci_dev);
 	pci_disable_device(pci_dev);
@@ -6714,7 +6714,7 @@
 			free_irq(dev->irq, priv);
 
 		if (dev->base_addr)
-			iounmap((unsigned char *)dev->base_addr);
+			iounmap((void __iomem *)dev->base_addr);
 
 		free_ieee80211(dev);
 	}
@@ -8574,6 +8574,7 @@
 	struct net_device *dev = priv->net_dev;
 	const unsigned char *microcode_data = fw->uc.data;
 	unsigned int microcode_data_left = fw->uc.size;
+	void __iomem *reg = (void __iomem *)dev->base_addr;
 
 	struct symbol_alive_response response;
 	int i, j;
@@ -8581,23 +8582,23 @@
 
 	/* Symbol control */
 	write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 
 	/* HW config */
 	write_nic_byte(dev, 0x210014, 0x72);	/* fifo width =16 */
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_byte(dev, 0x210014, 0x72);	/* fifo width =16 */
-	readl((void *)(dev->base_addr));
+	readl(reg);
 
 	/* EN_CS_ACCESS bit to reset control store pointer */
 	write_nic_byte(dev, 0x210000, 0x40);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_byte(dev, 0x210000, 0x0);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_byte(dev, 0x210000, 0x40);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 
 	/* copy microcode from buffer into Symbol */
 
@@ -8609,31 +8610,31 @@
 
 	/* EN_CS_ACCESS bit to reset the control store pointer */
 	write_nic_byte(dev, 0x210000, 0x0);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 
 	/* Enable System (Reg 0)
 	 * first enable causes garbage in RX FIFO */
 	write_nic_byte(dev, 0x210000, 0x0);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_byte(dev, 0x210000, 0x80);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 
 	/* Reset External Baseband Reg */
 	write_nic_word(dev, IPW2100_CONTROL_REG, 0x703);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_word(dev, IPW2100_CONTROL_REG, 0x707);
-	readl((void *)(dev->base_addr));
+	readl(reg);
 
 	/* HW Config (Reg 5) */
 	write_nic_byte(dev, 0x210014, 0x72);	// fifo width =16
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_byte(dev, 0x210014, 0x72);	// fifo width =16
-	readl((void *)(dev->base_addr));
+	readl(reg);
 
 	/* Enable System (Reg 0)
 	 * second enable should be OK */
 	write_nic_byte(dev, 0x210000, 0x00);	// clear enable system
-	readl((void *)(dev->base_addr));
+	readl(reg);
 	write_nic_byte(dev, 0x210000, 0x80);	// set enable system
 
 	/* check Symbol is enabled - upped this from 5 as it wasn't always
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 3bff09d..66bb590 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -42,9 +42,11 @@
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/random.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/firmware.h>
 #include <linux/wireless.h>
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 
 #include <net/ieee80211.h>
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index d794735..8de49fe 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -1053,8 +1053,9 @@
 		u16 channel;
 	} __attribute__ ((packed)) req;
 	const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
-	struct prism2_scan_apinfo *atom;
+	struct prism2_scan_apinfo *atom = NULL;
 	int offset = 4;
+	int found = 0;
 	u8 *buf;
 	u16 len;
 
@@ -1089,15 +1090,18 @@
 	 * we were requested to join */
 	for (; offset + atom_len <= len; offset += atom_len) {
 		atom = (struct prism2_scan_apinfo *) (buf + offset);
-		if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0)
-			goto found;
+		if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
+			found = 1;
+			break;
+		}
 	}
 
-	DEBUG(1, "%s: Requested AP not found in scan results\n",
-	      dev->name);
-	goto out;
+	if (! found) {
+		DEBUG(1, "%s: Requested AP not found in scan results\n",
+		      dev->name);
+		goto out;
+	}
 
- found:
 	memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
 	req.channel = atom->channel;	/* both are little-endian */
 	err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
@@ -1284,8 +1288,10 @@
 		/* Read scan data */
 		err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
 				       infofid, sizeof(info));
-		if (err)
+		if (err) {
+			kfree(buf);
 			break;
+		}
 
 #ifdef ORINOCO_DEBUG
 		{
@@ -4021,7 +4027,8 @@
 }
 
 /* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II */
+ * format that the Wireless Tools will understand - Jean II
+ * Return message length or -errno for fatal errors */
 static inline int orinoco_translate_scan(struct net_device *dev,
 					 char *buffer,
 					 char *scan,
@@ -4061,13 +4068,19 @@
 		break;
 	case FIRMWARE_TYPE_INTERSIL:
 		offset = 4;
-		if (priv->has_hostscan)
-			atom_len = scan[0] + (scan[1] << 8);
-		else
+		if (priv->has_hostscan) {
+			atom_len = le16_to_cpup((u16 *)scan);
+			/* Sanity check for atom_len */
+			if (atom_len < sizeof(struct prism2_scan_apinfo)) {
+				printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
+				dev->name, atom_len);
+				return -EIO;
+			}
+		} else
 			atom_len = offsetof(struct prism2_scan_apinfo, atim);
 		break;
 	default:
-		return 0;
+		return -EOPNOTSUPP;
 	}
 
 	/* Check that we got an whole number of atoms */
@@ -4075,7 +4088,7 @@
 		printk(KERN_ERR "%s: Unexpected scan data length %d, "
 		       "atom_len %d, offset %d\n", dev->name, scan_len,
 		       atom_len, offset);
-		return 0;
+		return -EIO;
 	}
 
 	/* Read the entries one by one */
@@ -4210,33 +4223,41 @@
 		/* We have some results to push back to user space */
 
 		/* Translate to WE format */
-		srq->length = orinoco_translate_scan(dev, extra,
-						     priv->scan_result,
-						     priv->scan_len);
+		int ret = orinoco_translate_scan(dev, extra,
+						 priv->scan_result,
+						 priv->scan_len);
 
-		/* Return flags */
-		srq->flags = (__u16) priv->scan_mode;
+		if (ret < 0) {
+			err = ret;
+			kfree(priv->scan_result);
+			priv->scan_result = NULL;
+		} else {
+			srq->length = ret;
 
-		/* Results are here, so scan no longer in progress */
-		priv->scan_inprogress = 0;
+			/* Return flags */
+			srq->flags = (__u16) priv->scan_mode;
 
-		/* In any case, Scan results will be cleaned up in the
-		 * reset function and when exiting the driver.
-		 * The person triggering the scanning may never come to
-		 * pick the results, so we need to do it in those places.
-		 * Jean II */
+			/* In any case, Scan results will be cleaned up in the
+			 * reset function and when exiting the driver.
+			 * The person triggering the scanning may never come to
+			 * pick the results, so we need to do it in those places.
+			 * Jean II */
 
 #ifdef SCAN_SINGLE_READ
-		/* If you enable this option, only one client (the first
-		 * one) will be able to read the result (and only one
-		 * time). If there is multiple concurent clients that
-		 * want to read scan results, this behavior is not
-		 * advisable - Jean II */
-		kfree(priv->scan_result);
-		priv->scan_result = NULL;
+			/* If you enable this option, only one client (the first
+			 * one) will be able to read the result (and only one
+			 * time). If there is multiple concurent clients that
+			 * want to read scan results, this behavior is not
+			 * advisable - Jean II */
+			kfree(priv->scan_result);
+			priv->scan_result = NULL;
 #endif /* SCAN_SINGLE_READ */
-		/* Here, if too much time has elapsed since last scan,
-		 * we may want to clean up scan results... - Jean II */
+			/* Here, if too much time has elapsed since last scan,
+			 * we may want to clean up scan results... - Jean II */
+		}
+
+		/* Scan is no longer in progress */
+		priv->scan_inprogress = 0;
 	}
 	  
 	orinoco_unlock(priv, &flags);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 1cc1492..d1fb1ba 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -604,7 +604,6 @@
 
 static struct pcmcia_device_id orinoco_cs_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
-	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001),
 	PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002),
 	PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
 	PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a),
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
new file mode 100644
index 0000000..86fa58e
--- /dev/null
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -0,0 +1,324 @@
+/* orinoco_nortel.c
+ * 
+ * Driver for Prism II devices which would usually be driven by orinoco_cs,
+ * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter. 
+ *
+ * Copyright (C) 2002 Tobias Hoffmann
+ *           (C) 2003 Christoph Jungegger <disdos@traum404.de>
+ *
+ * Some of this code is borrowed from orinoco_plx.c
+ *	Copyright (C) 2001 Daniel Barlow
+ * Some of this code is borrowed from orinoco_pci.c 
+ *  Copyright (C) 2001 Jean Tourrilhes
+ * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
+ * has been copied from it. linux-wlan-ng-0.1.10 is originally :
+ *	Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
+ * 
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above.  If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#define DRIVER_NAME "orinoco_nortel"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/fcntl.h>
+
+#include <pcmcia/cisreg.h>
+
+#include "hermes.h"
+#include "orinoco.h"
+
+#define COR_OFFSET    (0xe0)	/* COR attribute offset of Prism2 PC card */
+#define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA)	/* Enable PC card with interrupt in level trigger */
+
+
+/* Nortel specific data */
+struct nortel_pci_card {
+	unsigned long iobase1;
+	unsigned long iobase2;
+};
+
+/*
+ * Do a soft reset of the PCI card using the Configuration Option Register
+ * We need this to get going...
+ * This is the part of the code that is strongly inspired from wlan-ng
+ *
+ * Note bis : Don't try to access HERMES_CMD during the reset phase.
+ * It just won't work !
+ */
+static int nortel_pci_cor_reset(struct orinoco_private *priv)
+{
+	struct nortel_pci_card *card = priv->card;
+
+	/* Assert the reset until the card notice */
+	outw_p(8, card->iobase1 + 2);
+	inw(card->iobase2 + COR_OFFSET);
+	outw_p(0x80, card->iobase2 + COR_OFFSET);
+	mdelay(1);
+
+	/* Give time for the card to recover from this hard effort */
+	outw_p(0, card->iobase2 + COR_OFFSET);
+	outw_p(0, card->iobase2 + COR_OFFSET);
+	mdelay(1);
+
+	/* set COR as usual */
+	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+	mdelay(1);
+
+	outw_p(0x228, card->iobase1 + 2);
+
+	return 0;
+}
+
+int nortel_pci_hw_init(struct nortel_pci_card *card)
+{
+	int i;
+	u32 reg;
+
+	/* setup bridge */
+	if (inw(card->iobase1) & 1) {
+		printk(KERN_ERR PFX "brg1 answer1 wrong\n");
+		return -EBUSY;
+	}
+	outw_p(0x118, card->iobase1 + 2);
+	outw_p(0x108, card->iobase1 + 2);
+	mdelay(30);
+	outw_p(0x8, card->iobase1 + 2);
+	for (i = 0; i < 30; i++) {
+		mdelay(30);
+		if (inw(card->iobase1) & 0x10) {
+			break;
+		}
+	}
+	if (i == 30) {
+		printk(KERN_ERR PFX "brg1 timed out\n");
+		return -EBUSY;
+	}
+	if (inw(card->iobase2 + 0xe0) & 1) {
+		printk(KERN_ERR PFX "brg2 answer1 wrong\n");
+		return -EBUSY;
+	}
+	if (inw(card->iobase2 + 0xe2) & 1) {
+		printk(KERN_ERR PFX "brg2 answer2 wrong\n");
+		return -EBUSY;
+	}
+	if (inw(card->iobase2 + 0xe4) & 1) {
+		printk(KERN_ERR PFX "brg2 answer3 wrong\n");
+		return -EBUSY;
+	}
+
+	/* set the PCMCIA COR-Register */
+	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+	mdelay(1);
+	reg = inw(card->iobase2 + COR_OFFSET);
+	if (reg != COR_VALUE) {
+		printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
+		       reg);
+		return -EBUSY;
+	}
+
+	/* set leds */
+	outw_p(1, card->iobase1 + 10);
+	return 0;
+}
+
+static int nortel_pci_init_one(struct pci_dev *pdev,
+			       const struct pci_device_id *ent)
+{
+	int err;
+	struct orinoco_private *priv;
+	struct nortel_pci_card *card;
+	struct net_device *dev;
+	void __iomem *iomem;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot enable PCI device\n");
+		return err;
+	}
+
+	err = pci_request_regions(pdev, DRIVER_NAME);
+	if (err != 0) {
+		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+		goto fail_resources;
+	}
+
+	iomem = pci_iomap(pdev, 3, 0);
+	if (!iomem) {
+		err = -ENOMEM;
+		goto fail_map_io;
+	}
+
+	/* Allocate network device */
+	dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset);
+	if (!dev) {
+		printk(KERN_ERR PFX "Cannot allocate network device\n");
+		err = -ENOMEM;
+		goto fail_alloc;
+	}
+
+	priv = netdev_priv(dev);
+	card = priv->card;
+	card->iobase1 = pci_resource_start(pdev, 0);
+	card->iobase2 = pci_resource_start(pdev, 1);
+	dev->base_addr = pci_resource_start(pdev, 2);
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING);
+
+	printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
+	       "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
+
+	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+			  dev->name, dev);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
+		err = -EBUSY;
+		goto fail_irq;
+	}
+	dev->irq = pdev->irq;
+
+	err = nortel_pci_hw_init(card);
+	if (err) {
+		printk(KERN_ERR PFX "Hardware initialization failed\n");
+		goto fail;
+	}
+
+	err = nortel_pci_cor_reset(priv);
+	if (err) {
+		printk(KERN_ERR PFX "Initial reset failed\n");
+		goto fail;
+	}
+
+
+	err = register_netdev(dev);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot register network device\n");
+		goto fail;
+	}
+
+	pci_set_drvdata(pdev, dev);
+
+	return 0;
+
+ fail:
+	free_irq(pdev->irq, dev);
+
+ fail_irq:
+	pci_set_drvdata(pdev, NULL);
+	free_orinocodev(dev);
+
+ fail_alloc:
+	pci_iounmap(pdev, iomem);
+
+ fail_map_io:
+	pci_release_regions(pdev);
+
+ fail_resources:
+	pci_disable_device(pdev);
+
+	return err;
+}
+
+static void __devexit nortel_pci_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct nortel_pci_card *card = priv->card;
+
+	/* clear leds */
+	outw_p(0, card->iobase1 + 10);
+
+	unregister_netdev(dev);
+	free_irq(dev->irq, dev);
+	pci_set_drvdata(pdev, NULL);
+	free_orinocodev(dev);
+	pci_iounmap(pdev, priv->hw.iobase);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+
+static struct pci_device_id nortel_pci_id_table[] = {
+	/* Nortel emobility PCI */
+	{0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
+	{0,},
+};
+
+MODULE_DEVICE_TABLE(pci, nortel_pci_id_table);
+
+static struct pci_driver nortel_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = nortel_pci_id_table,
+	.probe = nortel_pci_init_one,
+	.remove = __devexit_p(nortel_pci_remove_one),
+};
+
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
+MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
+MODULE_DESCRIPTION
+    ("Driver for wireless LAN cards using the Nortel PCI bridge");
+MODULE_LICENSE("Dual MPL/GPL");
+
+static int __init nortel_pci_init(void)
+{
+	printk(KERN_DEBUG "%s\n", version);
+	return pci_module_init(&nortel_pci_driver);
+}
+
+static void __exit nortel_pci_exit(void)
+{
+	pci_unregister_driver(&nortel_pci_driver);
+	ssleep(1);
+}
+
+module_init(nortel_pci_init);
+module_exit(nortel_pci_exit);
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
new file mode 100644
index 0000000..39c6cdf
--- /dev/null
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -0,0 +1,1120 @@
+/*
+ * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
+ * Symbol Wireless Networker LA4100, CompactFlash cards by Socket
+ * Communications and Intel PRO/Wireless 2011B.
+ *
+ * The driver implements Symbol firmware download.  The rest is handled
+ * in hermes.c and orinoco.c.
+ *
+ * Utilities for downloading the Symbol firmware are available at
+ * http://sourceforge.net/projects/orinoco/
+ *
+ * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
+ * Portions based on orinoco_cs.c:
+ * 	Copyright (C) David Gibson, Linuxcare Australia
+ * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
+ * 	Copyright (C) Symbol Technologies.
+ *
+ * See copyright notice in file orinoco.c.
+ */
+
+#define DRIVER_NAME "spectrum_cs"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/config.h>
+#ifdef  __IN_PCMCIA_PACKAGE__
+#include <pcmcia/k_compat.h>
+#endif /* __IN_PCMCIA_PACKAGE__ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "orinoco.h"
+
+/*
+ * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into
+ * the driver.  Use get_symbol_fw script to generate spectrum_fw.h and
+ * copy it to the same directory as spectrum_cs.c.
+ *
+ * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the
+ * runtime using hotplug.  Use the same get_symbol_fw script to generate
+ * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the
+ * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and
+ * make sure that you have hotplug installed and enabled in the kernel.
+ */
+/* #define SPECTRUM_FW_INCLUDED 1 */
+
+#ifdef SPECTRUM_FW_INCLUDED
+/* Header with the firmware */
+#include "spectrum_fw.h"
+#else	/* !SPECTRUM_FW_INCLUDED */
+#include <linux/firmware.h>
+static unsigned char *primsym;
+static unsigned char *secsym;
+static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
+static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
+#endif	/* !SPECTRUM_FW_INCLUDED */
+
+/********************************************************************/
+/* Module stuff							    */
+/********************************************************************/
+
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
+MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader");
+MODULE_LICENSE("Dual MPL/GPL");
+
+/* Module parameters */
+
+/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
+ * don't have any CIS entry for it. This workaround it... */
+static int ignore_cis_vcc; /* = 0 */
+module_param(ignore_cis_vcc, int, 0);
+MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
+
+/********************************************************************/
+/* Magic constants						    */
+/********************************************************************/
+
+/*
+ * The dev_info variable is the "key" that is used to match up this
+ * device driver with appropriate cards, through the card
+ * configuration database.
+ */
+static dev_info_t dev_info = DRIVER_NAME;
+
+/********************************************************************/
+/* Data structures						    */
+/********************************************************************/
+
+/* PCMCIA specific device information (goes in the card field of
+ * struct orinoco_private */
+struct orinoco_pccard {
+	dev_link_t link;
+	dev_node_t node;
+};
+
+/*
+ * A linked list of "instances" of the device.  Each actual PCMCIA
+ * card corresponds to one device instance, and is described by one
+ * dev_link_t structure (defined in ds.h).
+ */
+static dev_link_t *dev_list; /* = NULL */
+
+/********************************************************************/
+/* Function prototypes						    */
+/********************************************************************/
+
+/* device methods */
+static int spectrum_cs_hard_reset(struct orinoco_private *priv);
+
+/* PCMCIA gumpf */
+static void spectrum_cs_config(dev_link_t * link);
+static void spectrum_cs_release(dev_link_t * link);
+static int spectrum_cs_event(event_t event, int priority,
+			    event_callback_args_t * args);
+
+static dev_link_t *spectrum_cs_attach(void);
+static void spectrum_cs_detach(dev_link_t *);
+
+/********************************************************************/
+/* Firmware downloader						    */
+/********************************************************************/
+
+/* Position of PDA in the adapter memory */
+#define EEPROM_ADDR	0x3000
+#define EEPROM_LEN	0x200
+#define PDA_OFFSET	0x100
+
+#define PDA_ADDR	(EEPROM_ADDR + PDA_OFFSET)
+#define PDA_WORDS	((EEPROM_LEN - PDA_OFFSET) / 2)
+
+/* Constants for the CISREG_CCSR register */
+#define HCR_RUN		0x07	/* run firmware after reset */
+#define HCR_IDLE	0x0E	/* don't run firmware after reset */
+#define HCR_MEM16	0x10	/* memory width bit, should be preserved */
+
+/*
+ * AUX port access.  To unlock the AUX port write the access keys to the
+ * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
+ * register.  Then read it and make sure it's HERMES_AUX_ENABLED.
+ */
+#define HERMES_AUX_ENABLE	0x8000	/* Enable auxiliary port access */
+#define HERMES_AUX_DISABLE	0x4000	/* Disable to auxiliary port access */
+#define HERMES_AUX_ENABLED	0xC000	/* Auxiliary port is open */
+
+#define HERMES_AUX_PW0	0xFE01
+#define HERMES_AUX_PW1	0xDC23
+#define HERMES_AUX_PW2	0xBA45
+
+/* End markers */
+#define PDI_END		0x00000000	/* End of PDA */
+#define BLOCK_END	0xFFFFFFFF	/* Last image block */
+#define TEXT_END	0x1A		/* End of text header */
+
+/*
+ * The following structures have little-endian fields denoted by
+ * the leading underscore.  Don't access them directly - use inline
+ * functions defined below.
+ */
+
+/*
+ * The binary image to be downloaded consists of series of data blocks.
+ * Each block has the following structure.
+ */
+struct dblock {
+	u32 _addr;		/* adapter address where to write the block */
+	u16 _len;		/* length of the data only, in bytes */
+	char data[0];		/* data to be written */
+} __attribute__ ((packed));
+
+/*
+ * Plug Data References are located in in the image after the last data
+ * block.  They refer to areas in the adapter memory where the plug data
+ * items with matching ID should be written.
+ */
+struct pdr {
+	u32 _id;		/* record ID */
+	u32 _addr;		/* adapter address where to write the data */
+	u32 _len;		/* expected length of the data, in bytes */
+	char next[0];		/* next PDR starts here */
+} __attribute__ ((packed));
+
+
+/*
+ * Plug Data Items are located in the EEPROM read from the adapter by
+ * primary firmware.  They refer to the device-specific data that should
+ * be plugged into the secondary firmware.
+ */
+struct pdi {
+	u16 _len;		/* length of ID and data, in words */
+	u16 _id;		/* record ID */
+	char data[0];		/* plug data */
+} __attribute__ ((packed));;
+
+
+/* Functions for access to little-endian data */
+static inline u32
+dblock_addr(const struct dblock *blk)
+{
+	return le32_to_cpu(blk->_addr);
+}
+
+static inline u32
+dblock_len(const struct dblock *blk)
+{
+	return le16_to_cpu(blk->_len);
+}
+
+static inline u32
+pdr_id(const struct pdr *pdr)
+{
+	return le32_to_cpu(pdr->_id);
+}
+
+static inline u32
+pdr_addr(const struct pdr *pdr)
+{
+	return le32_to_cpu(pdr->_addr);
+}
+
+static inline u32
+pdr_len(const struct pdr *pdr)
+{
+	return le32_to_cpu(pdr->_len);
+}
+
+static inline u32
+pdi_id(const struct pdi *pdi)
+{
+	return le16_to_cpu(pdi->_id);
+}
+
+/* Return length of the data only, in bytes */
+static inline u32
+pdi_len(const struct pdi *pdi)
+{
+	return 2 * (le16_to_cpu(pdi->_len) - 1);
+}
+
+
+/* Set address of the auxiliary port */
+static inline void
+spectrum_aux_setaddr(hermes_t *hw, u32 addr)
+{
+	hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
+	hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
+}
+
+
+/* Open access to the auxiliary port */
+static int
+spectrum_aux_open(hermes_t *hw)
+{
+	int i;
+
+	/* Already open? */
+	if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED)
+		return 0;
+
+	hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
+	hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
+	hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
+	hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE);
+
+	for (i = 0; i < 20; i++) {
+		udelay(10);
+		if (hermes_read_reg(hw, HERMES_CONTROL) ==
+		    HERMES_AUX_ENABLED)
+			return 0;
+	}
+
+	return -EBUSY;
+}
+
+
+#define CS_CHECK(fn, ret) \
+  do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+
+/*
+ * Reset the card using configuration registers COR and CCSR.
+ * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
+ */
+static int
+spectrum_reset(dev_link_t *link, int idle)
+{
+	int last_ret, last_fn;
+	conf_reg_t reg;
+	u_int save_cor;
+
+	/* Doing it if hardware is gone is guaranteed crash */
+	if (!(link->state & DEV_CONFIG))
+		return -ENODEV;
+
+	/* Save original COR value */
+	reg.Function = 0;
+	reg.Action = CS_READ;
+	reg.Offset = CISREG_COR;
+	CS_CHECK(AccessConfigurationRegister,
+		 pcmcia_access_configuration_register(link->handle, &reg));
+	save_cor = reg.Value;
+
+	/* Soft-Reset card */
+	reg.Action = CS_WRITE;
+	reg.Offset = CISREG_COR;
+	reg.Value = (save_cor | COR_SOFT_RESET);
+	CS_CHECK(AccessConfigurationRegister,
+		 pcmcia_access_configuration_register(link->handle, &reg));
+	udelay(1000);
+
+	/* Read CCSR */
+	reg.Action = CS_READ;
+	reg.Offset = CISREG_CCSR;
+	CS_CHECK(AccessConfigurationRegister,
+		 pcmcia_access_configuration_register(link->handle, &reg));
+
+	/*
+	 * Start or stop the firmware.  Memory width bit should be
+	 * preserved from the value we've just read.
+	 */
+	reg.Action = CS_WRITE;
+	reg.Offset = CISREG_CCSR;
+	reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
+	CS_CHECK(AccessConfigurationRegister,
+		 pcmcia_access_configuration_register(link->handle, &reg));
+	udelay(1000);
+
+	/* Restore original COR configuration index */
+	reg.Action = CS_WRITE;
+	reg.Offset = CISREG_COR;
+	reg.Value = (save_cor & ~COR_SOFT_RESET);
+	CS_CHECK(AccessConfigurationRegister,
+		 pcmcia_access_configuration_register(link->handle, &reg));
+	udelay(1000);
+	return 0;
+
+      cs_failed:
+	cs_error(link->handle, last_fn, last_ret);
+	return -ENODEV;
+}
+
+
+/*
+ * Scan PDR for the record with the specified RECORD_ID.
+ * If it's not found, return NULL.
+ */
+static struct pdr *
+spectrum_find_pdr(struct pdr *first_pdr, u32 record_id)
+{
+	struct pdr *pdr = first_pdr;
+
+	while (pdr_id(pdr) != PDI_END) {
+		/*
+		 * PDR area is currently not terminated by PDI_END.
+		 * It's followed by CRC records, which have the type
+		 * field where PDR has length.  The type can be 0 or 1.
+		 */
+		if (pdr_len(pdr) < 2)
+			return NULL;
+
+		/* If the record ID matches, we are done */
+		if (pdr_id(pdr) == record_id)
+			return pdr;
+
+		pdr = (struct pdr *) pdr->next;
+	}
+	return NULL;
+}
+
+
+/* Process one Plug Data Item - find corresponding PDR and plug it */
+static int
+spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
+{
+	struct pdr *pdr;
+
+	/* Find the PDI corresponding to this PDR */
+	pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi));
+
+	/* No match is found, safe to ignore */
+	if (!pdr)
+		return 0;
+
+	/* Lengths of the data in PDI and PDR must match */
+	if (pdi_len(pdi) != pdr_len(pdr))
+		return -EINVAL;
+
+	/* do the actual plugging */
+	spectrum_aux_setaddr(hw, pdr_addr(pdr));
+	hermes_write_words(hw, HERMES_AUXDATA, pdi->data,
+			   pdi_len(pdi) / 2);
+
+	return 0;
+}
+
+
+/* Read PDA from the adapter */
+static int
+spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len)
+{
+	int ret;
+	int pda_size;
+
+	/* Issue command to read EEPROM */
+	ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
+	if (ret)
+		return ret;
+
+	/* Open auxiliary port */
+	ret = spectrum_aux_open(hw);
+	if (ret)
+		return ret;
+
+	/* read PDA from EEPROM */
+	spectrum_aux_setaddr(hw, PDA_ADDR);
+	hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2);
+
+	/* Check PDA length */
+	pda_size = le16_to_cpu(pda[0]);
+	if (pda_size > pda_len)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+/* Parse PDA and write the records into the adapter */
+static int
+spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
+		   u16 *pda)
+{
+	int ret;
+	struct pdi *pdi;
+	struct pdr *first_pdr;
+	const struct dblock *blk = first_block;
+
+	/* Skip all blocks to locate Plug Data References */
+	while (dblock_addr(blk) != BLOCK_END)
+		blk = (struct dblock *) &blk->data[dblock_len(blk)];
+
+	first_pdr = (struct pdr *) blk;
+
+	/* Go through every PDI and plug them into the adapter */
+	pdi = (struct pdi *) (pda + 2);
+	while (pdi_id(pdi) != PDI_END) {
+		ret = spectrum_plug_pdi(hw, first_pdr, pdi);
+		if (ret)
+			return ret;
+
+		/* Increment to the next PDI */
+		pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
+	}
+	return 0;
+}
+
+
+/* Load firmware blocks into the adapter */
+static int
+spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
+{
+	const struct dblock *blk;
+	u32 blkaddr;
+	u32 blklen;
+
+	blk = first_block;
+	blkaddr = dblock_addr(blk);
+	blklen = dblock_len(blk);
+
+	while (dblock_addr(blk) != BLOCK_END) {
+		spectrum_aux_setaddr(hw, blkaddr);
+		hermes_write_words(hw, HERMES_AUXDATA, blk->data,
+				   blklen / 2);
+
+		blk = (struct dblock *) &blk->data[blklen];
+		blkaddr = dblock_addr(blk);
+		blklen = dblock_len(blk);
+	}
+	return 0;
+}
+
+
+/*
+ * Process a firmware image - stop the card, load the firmware, reset
+ * the card and make sure it responds.  For the secondary firmware take
+ * care of the PDA - read it and then write it on top of the firmware.
+ */
+static int
+spectrum_dl_image(hermes_t *hw, dev_link_t *link,
+		  const unsigned char *image)
+{
+	int ret;
+	const unsigned char *ptr;
+	const struct dblock *first_block;
+
+	/* Plug Data Area (PDA) */
+	u16 pda[PDA_WORDS];
+
+	/* Binary block begins after the 0x1A marker */
+	ptr = image;
+	while (*ptr++ != TEXT_END);
+	first_block = (const struct dblock *) ptr;
+
+	/* Read the PDA */
+	if (image != primsym) {
+		ret = spectrum_read_pda(hw, pda, sizeof(pda));
+		if (ret)
+			return ret;
+	}
+
+	/* Stop the firmware, so that it can be safely rewritten */
+	ret = spectrum_reset(link, 1);
+	if (ret)
+		return ret;
+
+	/* Program the adapter with new firmware */
+	ret = spectrum_load_blocks(hw, first_block);
+	if (ret)
+		return ret;
+
+	/* Write the PDA to the adapter */
+	if (image != primsym) {
+		ret = spectrum_apply_pda(hw, first_block, pda);
+		if (ret)
+			return ret;
+	}
+
+	/* Run the firmware */
+	ret = spectrum_reset(link, 0);
+	if (ret)
+		return ret;
+
+	/* Reset hermes chip and make sure it responds */
+	ret = hermes_init(hw);
+
+	/* hermes_reset() should return 0 with the secondary firmware */
+	if (image != primsym && ret != 0)
+		return -ENODEV;
+
+	/* And this should work with any firmware */
+	if (!hermes_present(hw))
+		return -ENODEV;
+
+	return 0;
+}
+
+
+/*
+ * Download the firmware into the card, this also does a PCMCIA soft
+ * reset on the card, to make sure it's in a sane state.
+ */
+static int
+spectrum_dl_firmware(hermes_t *hw, dev_link_t *link)
+{
+	int ret;
+	client_handle_t handle = link->handle;
+
+#ifndef SPECTRUM_FW_INCLUDED
+	const struct firmware *fw_entry;
+
+	if (request_firmware(&fw_entry, primary_fw_name,
+			     &handle_to_dev(handle)) == 0) {
+		primsym = fw_entry->data;
+	} else {
+		printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+		       primary_fw_name);
+		return -ENOENT;
+	}
+
+	if (request_firmware(&fw_entry, secondary_fw_name,
+			     &handle_to_dev(handle)) == 0) {
+		secsym = fw_entry->data;
+	} else {
+		printk(KERN_ERR PFX "Cannot find firmware: %s\n",
+		       secondary_fw_name);
+		return -ENOENT;
+	}
+#endif
+
+	/* Load primary firmware */
+	ret = spectrum_dl_image(hw, link, primsym);
+	if (ret) {
+		printk(KERN_ERR PFX "Primary firmware download failed\n");
+		return ret;
+	}
+
+	/* Load secondary firmware */
+	ret = spectrum_dl_image(hw, link, secsym);
+
+	if (ret) {
+		printk(KERN_ERR PFX "Secondary firmware download failed\n");
+	}
+
+	return ret;
+}
+
+/********************************************************************/
+/* Device methods     						    */
+/********************************************************************/
+
+static int
+spectrum_cs_hard_reset(struct orinoco_private *priv)
+{
+	struct orinoco_pccard *card = priv->card;
+	dev_link_t *link = &card->link;
+	int err;
+
+	if (!hermes_present(&priv->hw)) {
+		/* The firmware needs to be reloaded */
+		if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {
+			printk(KERN_ERR PFX "Firmware download failed\n");
+			err = -ENODEV;
+		}
+	} else {
+		/* Soft reset using COR and HCR */
+		spectrum_reset(link, 0);
+	}
+
+	return 0;
+}
+
+/********************************************************************/
+/* PCMCIA stuff     						    */
+/********************************************************************/
+
+/*
+ * This creates an "instance" of the driver, allocating local data
+ * structures for one device.  The device is registered with Card
+ * Services.
+ * 
+ * The dev_link structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a card
+ * insertion event.  */
+static dev_link_t *
+spectrum_cs_attach(void)
+{
+	struct net_device *dev;
+	struct orinoco_private *priv;
+	struct orinoco_pccard *card;
+	dev_link_t *link;
+	client_reg_t client_reg;
+	int ret;
+
+	dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
+	if (! dev)
+		return NULL;
+	priv = netdev_priv(dev);
+	card = priv->card;
+
+	/* Link both structures together */
+	link = &card->link;
+	link->priv = dev;
+
+	/* Interrupt setup */
+	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
+	link->irq.Handler = orinoco_interrupt;
+	link->irq.Instance = dev; 
+
+	/* General socket configuration defaults can go here.  In this
+	 * client, we assume very little, and rely on the CIS for
+	 * almost everything.  In most clients, many details (i.e.,
+	 * number, sizes, and attributes of IO windows) are fixed by
+	 * the nature of the device, and can be hard-wired here. */
+	link->conf.Attributes = 0;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+
+	/* Register with Card Services */
+	/* FIXME: need a lock? */
+	link->next = dev_list;
+	dev_list = link;
+
+	client_reg.dev_info = &dev_info;
+	client_reg.Version = 0x0210; /* FIXME: what does this mean? */
+	client_reg.event_callback_args.client_data = link;
+
+	ret = pcmcia_register_client(&link->handle, &client_reg);
+	if (ret != CS_SUCCESS) {
+		cs_error(link->handle, RegisterClient, ret);
+		spectrum_cs_detach(link);
+		return NULL;
+	}
+
+	return link;
+}				/* spectrum_cs_attach */
+
+/*
+ * This deletes a driver "instance".  The device is de-registered with
+ * Card Services.  If it has been released, all local data structures
+ * are freed.  Otherwise, the structures will be freed when the device
+ * is released.
+ */
+static void spectrum_cs_detach(dev_link_t *link)
+{
+	dev_link_t **linkp;
+	struct net_device *dev = link->priv;
+
+	/* Locate device structure */
+	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+		if (*linkp == link)
+			break;
+
+	BUG_ON(*linkp == NULL);
+
+	if (link->state & DEV_CONFIG)
+		spectrum_cs_release(link);
+
+	/* Break the link with Card Services */
+	if (link->handle)
+		pcmcia_deregister_client(link->handle);
+
+	/* Unlink device structure, and free it */
+	*linkp = link->next;
+	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
+	if (link->dev) {
+		DEBUG(0, PFX "About to unregister net device %p\n",
+		      dev);
+		unregister_netdev(dev);
+	}
+	free_orinocodev(dev);
+}				/* spectrum_cs_detach */
+
+/*
+ * spectrum_cs_config() is scheduled to run after a CARD_INSERTION
+ * event is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+
+static void
+spectrum_cs_config(dev_link_t *link)
+{
+	struct net_device *dev = link->priv;
+	client_handle_t handle = link->handle;
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct orinoco_pccard *card = priv->card;
+	hermes_t *hw = &priv->hw;
+	int last_fn, last_ret;
+	u_char buf[64];
+	config_info_t conf;
+	cisinfo_t info;
+	tuple_t tuple;
+	cisparse_t parse;
+	void __iomem *mem;
+
+	CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
+
+	/*
+	 * This reads the card's CONFIG tuple to find its
+	 * configuration registers.
+	 */
+	tuple.DesiredTuple = CISTPL_CONFIG;
+	tuple.Attributes = 0;
+	tuple.TupleData = buf;
+	tuple.TupleDataMax = sizeof(buf);
+	tuple.TupleOffset = 0;
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+	CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+
+	/* Configure card */
+	link->state |= DEV_CONFIG;
+
+	/* Look up the current Vcc */
+	CS_CHECK(GetConfigurationInfo,
+		 pcmcia_get_configuration_info(handle, &conf));
+	link->conf.Vcc = conf.Vcc;
+
+	/*
+	 * In this loop, we scan the CIS for configuration table
+	 * entries, each of which describes a valid card
+	 * configuration, including voltage, IO window, memory window,
+	 * and interrupt settings.
+	 *
+	 * We make no assumptions about the card to be configured: we
+	 * use just the information available in the CIS.  In an ideal
+	 * world, this would work for any PCMCIA card, but it requires
+	 * a complete and accurate CIS.  In practice, a driver usually
+	 * "knows" most of these things without consulting the CIS,
+	 * and most client drivers will only use the CIS to fill in
+	 * implementation-defined details.
+	 */
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+	while (1) {
+		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+		cistpl_cftable_entry_t dflt = { .index = 0 };
+
+		if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
+		    || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
+			goto next_entry;
+
+		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+			dflt = *cfg;
+		if (cfg->index == 0)
+			goto next_entry;
+		link->conf.ConfigIndex = cfg->index;
+
+		/* Does this card need audio output? */
+		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+			link->conf.Attributes |= CONF_ENABLE_SPKR;
+			link->conf.Status = CCSR_AUDIO_ENA;
+		}
+
+		/* Use power settings for Vcc and Vpp if present */
+		/* Note that the CIS values need to be rescaled */
+		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+				DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+				if (!ignore_cis_vcc)
+					goto next_entry;
+			}
+		} else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
+				DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
+				if(!ignore_cis_vcc)
+					goto next_entry;
+			}
+		}
+
+		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 =
+			    cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
+			link->conf.Vpp1 = link->conf.Vpp2 =
+			    dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		
+		/* Do we need to allocate an interrupt? */
+		link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+		/* IO window settings */
+		link->io.NumPorts1 = link->io.NumPorts2 = 0;
+		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+			cistpl_io_t *io =
+			    (cfg->io.nwin) ? &cfg->io : &dflt.io;
+			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+			if (!(io->flags & CISTPL_IO_8BIT))
+				link->io.Attributes1 =
+				    IO_DATA_PATH_WIDTH_16;
+			if (!(io->flags & CISTPL_IO_16BIT))
+				link->io.Attributes1 =
+				    IO_DATA_PATH_WIDTH_8;
+			link->io.IOAddrLines =
+			    io->flags & CISTPL_IO_LINES_MASK;
+			link->io.BasePort1 = io->win[0].base;
+			link->io.NumPorts1 = io->win[0].len;
+			if (io->nwin > 1) {
+				link->io.Attributes2 =
+				    link->io.Attributes1;
+				link->io.BasePort2 = io->win[1].base;
+				link->io.NumPorts2 = io->win[1].len;
+			}
+
+			/* This reserves IO space but doesn't actually enable it */
+			if (pcmcia_request_io(link->handle, &link->io) != 0)
+				goto next_entry;
+		}
+
+
+		/* If we got this far, we're cool! */
+
+		break;
+		
+	next_entry:
+		if (link->io.NumPorts1)
+			pcmcia_release_io(link->handle, &link->io);
+		last_ret = pcmcia_get_next_tuple(handle, &tuple);
+		if (last_ret  == CS_NO_MORE_ITEMS) {
+			printk(KERN_ERR PFX "GetNextTuple(): No matching "
+			       "CIS configuration.  Maybe you need the "
+			       "ignore_cis_vcc=1 parameter.\n");
+			goto cs_failed;
+		}
+	}
+
+	/*
+	 * Allocate an interrupt line.  Note that this does not assign
+	 * a handler to the interrupt, unless the 'Handler' member of
+	 * the irq structure is initialized.
+	 */
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+
+	/* We initialize the hermes structure before completing PCMCIA
+	 * configuration just in case the interrupt handler gets
+	 * called. */
+	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+	if (!mem)
+		goto cs_failed;
+
+	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
+
+	/*
+	 * This actually configures the PCMCIA socket -- setting up
+	 * the I/O windows and the interrupt mapping, and putting the
+	 * card and host interface into "Memory and IO" mode.
+	 */
+	CS_CHECK(RequestConfiguration,
+		 pcmcia_request_configuration(link->handle, &link->conf));
+
+	/* Ok, we have the configuration, prepare to register the netdev */
+	dev->base_addr = link->io.BasePort1;
+	dev->irq = link->irq.AssignedIRQ;
+	SET_MODULE_OWNER(dev);
+	card->node.major = card->node.minor = 0;
+
+	/* Reset card and download firmware */
+	if (spectrum_cs_hard_reset(priv) != 0) {
+		goto failed;
+	}
+
+	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
+	/* Tell the stack we exist */
+	if (register_netdev(dev) != 0) {
+		printk(KERN_ERR PFX "register_netdev() failed\n");
+		goto failed;
+	}
+
+	/* At this point, the dev_node_t structure(s) needs to be
+	 * initialized and arranged in a linked list at link->dev. */
+	strcpy(card->node.dev_name, dev->name);
+	link->dev = &card->node; /* link->dev being non-NULL is also
+                                    used to indicate that the
+                                    net_device has been registered */
+	link->state &= ~DEV_CONFIG_PENDING;
+
+	/* Finally, report what we've done */
+	printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
+	       dev->name, link->conf.ConfigIndex,
+	       link->conf.Vcc / 10, link->conf.Vcc % 10);
+	if (link->conf.Vpp1)
+		printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
+		       link->conf.Vpp1 % 10);
+	printk(", irq %d", link->irq.AssignedIRQ);
+	if (link->io.NumPorts1)
+		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+		       link->io.BasePort1 + link->io.NumPorts1 - 1);
+	if (link->io.NumPorts2)
+		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
+		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	printk("\n");
+
+	return;
+
+ cs_failed:
+	cs_error(link->handle, last_fn, last_ret);
+
+ failed:
+	spectrum_cs_release(link);
+}				/* spectrum_cs_config */
+
+/*
+ * After a card is removed, spectrum_cs_release() will unregister the
+ * device, and release the PCMCIA configuration.  If the device is
+ * still open, this will be postponed until it is closed.
+ */
+static void
+spectrum_cs_release(dev_link_t *link)
+{
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+	unsigned long flags;
+
+	/* We're committed to taking the device away now, so mark the
+	 * hardware as unavailable */
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->hw_unavailable++;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Don't bother checking to see if these succeed or not */
+	pcmcia_release_configuration(link->handle);
+	if (link->io.NumPorts1)
+		pcmcia_release_io(link->handle, &link->io);
+	if (link->irq.AssignedIRQ)
+		pcmcia_release_irq(link->handle, &link->irq);
+	link->state &= ~DEV_CONFIG;
+	if (priv->hw.iobase)
+		ioport_unmap(priv->hw.iobase);
+}				/* spectrum_cs_release */
+
+/*
+ * The card status event handler.  Mostly, this schedules other stuff
+ * to run after an event is received.
+ */
+static int
+spectrum_cs_event(event_t event, int priority,
+		       event_callback_args_t * args)
+{
+	dev_link_t *link = args->client_data;
+	struct net_device *dev = link->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
+	int err = 0;
+	unsigned long flags;
+
+	switch (event) {
+	case CS_EVENT_CARD_REMOVAL:
+		link->state &= ~DEV_PRESENT;
+		if (link->state & DEV_CONFIG) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&priv->lock, flags);
+			netif_device_detach(dev);
+			priv->hw_unavailable++;
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
+		break;
+
+	case CS_EVENT_CARD_INSERTION:
+		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+		spectrum_cs_config(link);
+		break;
+
+	case CS_EVENT_PM_SUSPEND:
+		link->state |= DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_RESET_PHYSICAL:
+		/* Mark the device as stopped, to block IO until later */
+		if (link->state & DEV_CONFIG) {
+			/* This is probably racy, but I can't think of
+                           a better way, short of rewriting the PCMCIA
+                           layer to not suck :-( */
+			spin_lock_irqsave(&priv->lock, flags);
+
+			err = __orinoco_down(dev);
+			if (err)
+				printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
+				       dev->name,
+				       event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
+				       err);
+
+			netif_device_detach(dev);
+			priv->hw_unavailable++;
+
+			spin_unlock_irqrestore(&priv->lock, flags);
+
+			pcmcia_release_configuration(link->handle);
+		}
+		break;
+
+	case CS_EVENT_PM_RESUME:
+		link->state &= ~DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_CARD_RESET:
+		if (link->state & DEV_CONFIG) {
+			/* FIXME: should we double check that this is
+			 * the same card as we had before */
+			pcmcia_request_configuration(link->handle, &link->conf);
+			netif_device_attach(dev);
+			priv->hw_unavailable--;
+			schedule_work(&priv->reset_work);
+		}
+		break;
+	}
+
+	return err;
+}				/* spectrum_cs_event */
+
+/********************************************************************/
+/* Module initialization					    */
+/********************************************************************/
+
+/* Can't be declared "const" or the whole __initdata section will
+ * become const */
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Pavel Roskin <proski@gnu.org>,"
+	" David Gibson <hermes@gibson.dropbear.id.au>, et al)";
+
+static struct pcmcia_device_id spectrum_cs_ids[] = {
+	PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
+	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
+	PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */
+	PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
+
+static struct pcmcia_driver orinoco_driver = {
+	.owner		= THIS_MODULE,
+	.drv		= {
+		.name	= DRIVER_NAME,
+	},
+	.attach		= spectrum_cs_attach,
+	.event		= spectrum_cs_event,
+	.detach		= spectrum_cs_detach,
+	.id_table       = spectrum_cs_ids,
+};
+
+static int __init
+init_spectrum_cs(void)
+{
+	printk(KERN_DEBUG "%s\n", version);
+
+	return pcmcia_register_driver(&orinoco_driver);
+}
+
+static void __exit
+exit_spectrum_cs(void)
+{
+	pcmcia_unregister_driver(&orinoco_driver);
+	BUG_ON(dev_list != NULL);
+}
+
+module_init(init_spectrum_cs);
+module_exit(exit_spectrum_cs);
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 7bac2f7..a1178a6 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -20,27 +20,18 @@
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
-
 #include <asm/hardware/scoop.h>
-#include <asm/arch/corgi.h>
 #include <asm/arch/pxa-regs.h>
 
 #include "soc_common.h"
 
 #define	NO_KEEP_VS 0x0001
 
-static unsigned char keep_vs;
-static unsigned char keep_rd;
-
-static struct pcmcia_irqs irqs[] = {
-	{ 0, CORGI_IRQ_GPIO_CF_CD, "PCMCIA0 CD"},
-};
-
-static void sharpsl_pcmcia_init_reset(void)
+static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev)
 {
-	reset_scoop(&corgiscoop_device.dev);
-	keep_vs = NO_KEEP_VS;
-	keep_rd = 0;
+	reset_scoop(scoopdev->dev);
+	scoopdev->keep_vs = NO_KEEP_VS;
+	scoopdev->keep_rd = 0;
 }
 
 static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
@@ -71,29 +62,35 @@
 	pxa_gpio_mode(GPIO57_nIOIS16_MD);
 
 	/* Register interrupts */
-	ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	if (scoop_devs[skt->nr].cd_irq >= 0) {
+		struct pcmcia_irqs cd_irq;
 
-	if (ret) {
-		printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
-		return ret;
+		cd_irq.sock = skt->nr;
+		cd_irq.irq  = scoop_devs[skt->nr].cd_irq;
+		cd_irq.str  = scoop_devs[skt->nr].cd_irq_str;
+		ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1);
+
+		if (ret) {
+			printk(KERN_ERR "Request for Compact Flash IRQ failed\n");
+			return ret;
+		}
 	}
 
-	/* Enable interrupt */
-	write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, 0x00C0);
-	write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, 0x0101);
-	keep_vs = NO_KEEP_VS;
-
-	skt->irq = CORGI_IRQ_GPIO_CF_IRQ;
+	skt->irq = scoop_devs[skt->nr].irq;
 
 	return 0;
 }
 
 static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	if (scoop_devs[skt->nr].cd_irq >= 0) {
+		struct pcmcia_irqs cd_irq;
 
-	/* CF_BUS_OFF */
-	sharpsl_pcmcia_init_reset();
+		cd_irq.sock = skt->nr;
+		cd_irq.irq  = scoop_devs[skt->nr].cd_irq;
+		cd_irq.str  = scoop_devs[skt->nr].cd_irq_str;
+		soc_pcmcia_free_irqs(skt, &cd_irq, 1);
+	}
 }
 
 
@@ -101,31 +98,32 @@
 				    struct pcmcia_state *state)
 {
 	unsigned short cpr, csr;
+	struct device *scoop = scoop_devs[skt->nr].dev;
 
-	cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR);
+	cpr = read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR);
 
-	write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x00FF);
-	write_scoop_reg(&corgiscoop_device.dev, SCOOP_ISR, 0x0000);
-	write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x0000);
-	csr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CSR);
+	write_scoop_reg(scoop, SCOOP_IRM, 0x00FF);
+	write_scoop_reg(scoop, SCOOP_ISR, 0x0000);
+	write_scoop_reg(scoop, SCOOP_IRM, 0x0000);
+	csr = read_scoop_reg(scoop, SCOOP_CSR);
 	if (csr & 0x0004) {
 		/* card eject */
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
-		keep_vs = NO_KEEP_VS;
+		write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+		scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
 	}
-	else if (!(keep_vs & NO_KEEP_VS)) {
+	else if (!(scoop_devs[skt->nr].keep_vs & NO_KEEP_VS)) {
 		/* keep vs1,vs2 */
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
-		csr |= keep_vs;
+		write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+		csr |= scoop_devs[skt->nr].keep_vs;
 	}
 	else if (cpr & 0x0003) {
 		/* power on */
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
-		keep_vs = (csr & 0x00C0);
+		write_scoop_reg(scoop, SCOOP_CDR, 0x0000);
+		scoop_devs[skt->nr].keep_vs = (csr & 0x00C0);
 	}
 	else {
 		/* card detect */
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0002);
+		write_scoop_reg(scoop, SCOOP_CDR, 0x0002);
 	}
 
 	state->detect = (csr & 0x0004) ? 0 : 1;
@@ -147,6 +145,7 @@
 				       const socket_state_t *state)
 {
 	unsigned long flags;
+	struct device *scoop = scoop_devs[skt->nr].dev;
 
 	unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr;
 
@@ -166,10 +165,10 @@
 
 	local_irq_save(flags);
 
-	nmcr = (mcr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR)) & ~0x0010;
-	ncpr = (cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR)) & ~0x0083;
-	nccr = (ccr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR)) & ~0x0080;
-	nimr = (imr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR)) & ~0x003E;
+	nmcr = (mcr = read_scoop_reg(scoop, SCOOP_MCR)) & ~0x0010;
+	ncpr = (cpr = read_scoop_reg(scoop, SCOOP_CPR)) & ~0x0083;
+	nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080;
+	nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E;
 
 	ncpr |= (state->Vcc == 33) ? 0x0001 :
 				(state->Vcc == 50) ? 0x0002 : 0;
@@ -184,22 +183,22 @@
 			((skt->status&SS_WRPROT) ? 0x0008 : 0);
 
 	if (!(ncpr & 0x0003)) {
-		keep_rd = 0;
-	} else if (!keep_rd) {
+		scoop_devs[skt->nr].keep_rd = 0;
+	} else if (!scoop_devs[skt->nr].keep_rd) {
 		if (nccr & 0x0080)
-			keep_rd = 1;
+			scoop_devs[skt->nr].keep_rd = 1;
 		else
 			nccr |= 0x0080;
 	}
 
 	if (mcr != nmcr)
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, nmcr);
+		write_scoop_reg(scoop, SCOOP_MCR, nmcr);
 	if (cpr != ncpr)
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR, ncpr);
+		write_scoop_reg(scoop, SCOOP_CPR, ncpr);
 	if (ccr != nccr)
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR, nccr);
+		write_scoop_reg(scoop, SCOOP_CCR, nccr);
 	if (imr != nimr)
-		write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, nimr);
+		write_scoop_reg(scoop, SCOOP_IMR, nimr);
 
 	local_irq_restore(flags);
 
@@ -208,10 +207,18 @@
 
 static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
+	sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
+
+	/* Enable interrupt */
+	write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0);
+	write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101);
+	scoop_devs[skt->nr].keep_vs = NO_KEEP_VS;
 }
 
 static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
+	/* CF_BUS_OFF */
+	sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]);
 }
 
 static struct pcmcia_low_level sharpsl_pcmcia_ops = {
@@ -223,7 +230,7 @@
 	.socket_init		= sharpsl_pcmcia_socket_init,
 	.socket_suspend		= sharpsl_pcmcia_socket_suspend,
 	.first				= 0,
-	.nr					= 1,
+	.nr					= 0,
 };
 
 static struct platform_device *sharpsl_pcmcia_device;
@@ -232,12 +239,15 @@
 {
 	int ret;
 
+	sharpsl_pcmcia_ops.nr=scoop_num;
 	sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
 	if (!sharpsl_pcmcia_device)
 		return -ENOMEM;
+
 	memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device));
 	sharpsl_pcmcia_device->name = "pxa2xx-pcmcia";
 	sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
+	sharpsl_pcmcia_device->dev.parent=scoop_devs[0].dev;
 
 	ret = platform_device_register(sharpsl_pcmcia_device);
 	if (ret)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 0cc879e..5959e67 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -269,7 +269,10 @@
 
 	__stop_tx(up);
 
-	if (up->port.type == PORT_16C950 && tty_stop /*FIXME*/) {
+	/*
+	 * We really want to stop the transmitter from sending.
+	 */
+	if (up->port.type == PORT_16C950) {
 		up->acr |= UART_ACR_TXDIS;
 		serial_icr_write(up, UART_ACR, up->acr);
 	}
@@ -283,10 +286,11 @@
 		up->ier |= UART_IER_THRI;
 		serial_out(up, UART_IER, up->ier);
 	}
+
 	/*
-	 * We only do this from uart_start
+	 * Re-enable the transmitter if we disabled it.
 	 */
-	if (tty_start && up->port.type == PORT_16C950 /*FIXME*/) {
+	if (up->port.type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
 		up->acr &= ~UART_ACR_TXDIS;
 		serial_icr_write(up, UART_ACR, up->acr);
 	}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 79422a3..9f44e83 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -782,7 +782,7 @@
 		return -E2BIG;
 	}
 
-	bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb%d", busnum);
+	bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb_host%d", busnum);
 	if (IS_ERR(bus->class_dev)) {
 		clear_bit(busnum, busmap.busmap);
 		up(&usb_bus_list_lock);
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index ca9f3a3..f36c0b6 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -1523,7 +1523,6 @@
 static int w9968cf_i2c_attach_inform(struct i2c_client* client)
 {
 	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
-	const char* clientname = i2c_clientname(client);
 	int id = client->driver->id, err = 0;
 
 	if (id == I2C_DRIVERID_OVCAMCHIP) {
@@ -1535,12 +1534,12 @@
 		}
 	} else {
 		DBG(4, "Rejected client [%s] with driver [%s]", 
-		    clientname, client->driver->name)
+		    client->name, client->driver->name)
 		return -EINVAL;
 	}
 
 	DBG(5, "I2C attach client [%s] with driver [%s]",
-	    clientname, client->driver->name)
+	    client->name, client->driver->name)
 
 	return 0;
 }
@@ -1549,12 +1548,11 @@
 static int w9968cf_i2c_detach_inform(struct i2c_client* client)
 {
 	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
-	const char* clientname = i2c_clientname(client);
 
 	if (cam->sensor_client == client)
 		cam->sensor_client = NULL;
 
-	DBG(5, "I2C detach client [%s]", clientname)
+	DBG(5, "I2C detach client [%s]", client->name)
 
 	return 0;
 }
@@ -1573,15 +1571,13 @@
 	int err = 0;
 
 	static struct i2c_algorithm algo = {
-		.name =          "W996[87]CF algorithm",
-		.id =            I2C_ALGO_SMBUS,
 		.smbus_xfer =    w9968cf_i2c_smbus_xfer,
 		.algo_control =  w9968cf_i2c_control,
 		.functionality = w9968cf_i2c_func,
 	};
 
 	static struct i2c_adapter adap = {
-		.id =                I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF,
+		.id =                I2C_HW_SMBUS_W9968CF,
 		.class =             I2C_CLASS_CAM_DIGITAL,
 		.owner =             THIS_MODULE,
 		.client_register =   w9968cf_i2c_attach_inform,
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index 7622441..a9d0414 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -75,7 +75,7 @@
 
 	strcpy(chan->adapter.name, name);
 	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.id		= I2C_ALGO_ATI;
+	chan->adapter.id		= I2C_HW_B_RADEON;
 	chan->adapter.algo_data		= &chan->algo;
 	chan->adapter.dev.parent	= &chan->rinfo->pdev->dev;
 	chan->algo.setsda		= radeon_gpio_setsda;
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index 67f8534..ad60bbb 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1271,7 +1271,7 @@
 }
 
 static int maven_attach_adapter(struct i2c_adapter* adapter) {
-	if (adapter->id == (I2C_ALGO_BIT | I2C_HW_B_G400))
+	if (adapter->id == I2C_HW_B_G400)
 		return i2c_probe(adapter, &addr_data, &maven_detect_client);
 	return 0;
 }
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 3757c14..1a91bff 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -90,14 +90,13 @@
 	return val;
 }
 
-#define I2C_ALGO_NVIDIA   0x0e0000
 static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
 {
 	int rc;
 
 	strcpy(chan->adapter.name, name);
 	chan->adapter.owner = THIS_MODULE;
-	chan->adapter.id = I2C_ALGO_NVIDIA;
+	chan->adapter.id = I2C_HW_B_NVIDIA;
 	chan->adapter.algo_data = &chan->algo;
 	chan->adapter.dev.parent = &chan->par->pci_dev->dev;
 	chan->algo.setsda = nvidia_gpio_setsda;
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index da1334d..77151d8 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -92,14 +92,13 @@
 	return val;
 }
 
-#define I2C_ALGO_RIVA   0x0e0000
 static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
 {
 	int rc;
 
 	strcpy(chan->adapter.name, name);
 	chan->adapter.owner		= THIS_MODULE;
-	chan->adapter.id		= I2C_ALGO_RIVA;
+	chan->adapter.id		= I2C_HW_B_RIVA;
 	chan->adapter.algo_data		= &chan->algo;
 	chan->adapter.dev.parent	= &chan->par->pdev->dev;
 	chan->algo.setsda		= riva_gpio_setsda;
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 024a0ce..847698b 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -137,7 +137,6 @@
 	return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
 }
 
-#define I2C_ALGO_SAVAGE   0x0f0000
 static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
 				const char *name)
 {
@@ -147,7 +146,7 @@
 	if (add_bus && chan->par) {
 		strcpy(chan->adapter.name, name);
 		chan->adapter.owner		= THIS_MODULE;
-		chan->adapter.id		= I2C_ALGO_SAVAGE;
+		chan->adapter.id		= I2C_HW_B_SAVAGE;
 		chan->adapter.algo_data		= &chan->algo;
 		chan->adapter.dev.parent	= &chan->par->pcidev->dev;
 		chan->algo.udelay		= 40;
diff --git a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h
index 7ea771f..527404b 100644
--- a/include/asm-arm/hardware/scoop.h
+++ b/include/asm-arm/hardware/scoop.h
@@ -40,6 +40,19 @@
 	unsigned short io_dir;
 };
 
+/* Structure for linking scoop devices to PCMCIA sockets */
+struct scoop_pcmcia_dev {
+	struct device *dev;     /* Pointer to this socket's scoop device */
+	int	irq;                /* irq for socket */
+	int cd_irq;
+	const char *cd_irq_str;
+	unsigned char keep_vs;
+	unsigned char keep_rd;
+};
+
+extern int scoop_num;
+extern struct scoop_pcmcia_dev *scoop_devs;
+
 void reset_scoop(struct device *dev);
 unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
 unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index 2cf279a..96c6db7 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -47,9 +47,7 @@
 
 #ifdef CONFIG_NO_IDLE_HZ
 
-#define DYN_TICK_SKIPPING	(1 << 2)
 #define DYN_TICK_ENABLED	(1 << 1)
-#define DYN_TICK_SUITABLE	(1 << 0)
 
 struct dyn_tick_timer {
 	unsigned int	state;			/* Current state */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index b3bb326..3fa9428 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -6,6 +6,9 @@
 #define VMLINUX_SYMBOL(_sym_) _sym_
 #endif
 
+/* Align . to a 8 byte boundary equals to maximum function alignment. */
+#define ALIGN_FUNCTION()  . = ALIGN(8)
+
 #define RODATA								\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		*(.rodata) *(.rodata.*)					\
@@ -79,12 +82,18 @@
 		VMLINUX_SYMBOL(__security_initcall_end) = .;		\
 	}
 
+/* sched.text is aling to function alignment to secure we have same
+ * address even at second ld pass when generating System.map */
 #define SCHED_TEXT							\
+		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__sched_text_start) = .;			\
 		*(.sched.text)						\
 		VMLINUX_SYMBOL(__sched_text_end) = .;
 
+/* spinlock.text is aling to function alignment to secure we have same
+ * address even at second ld pass when generating System.map */
 #define LOCK_TEXT							\
+		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__lock_text_start) = .;			\
 		*(.spinlock.text)					\
 		VMLINUX_SYMBOL(__lock_text_end) = .;
diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h
index 1b5018a..7eb4004 100644
--- a/include/linux/hwmon-sysfs.h
+++ b/include/linux/hwmon-sysfs.h
@@ -33,4 +33,19 @@
 	.index =	_index,					\
 }
 
+struct sensor_device_attribute_2 {
+	struct device_attribute dev_attr;
+	u8 index;
+	u8 nr;
+};
+#define to_sensor_dev_attr_2(_dev_attr) \
+	container_of(_dev_attr, struct sensor_device_attribute_2, dev_attr)
+
+#define SENSOR_DEVICE_ATTR_2(_name,_mode,_show,_store,_nr,_index)	\
+struct sensor_device_attribute_2 sensor_dev_attr_##_name = {	\
+	.dev_attr =	__ATTR(_name,_mode,_show,_store),	\
+	.index =	_index,					\
+	.nr =		_nr,					\
+}
+
 #endif /* _LINUX_HWMON_SYSFS_H */
diff --git a/include/linux/hwmon-vid.h b/include/linux/hwmon-vid.h
new file mode 100644
index 0000000..cd4b7a0
--- /dev/null
+++ b/include/linux/hwmon-vid.h
@@ -0,0 +1,45 @@
+/*
+    hwmon-vid.h - VID/VRM/VRD voltage conversions
+
+    Originally part of lm_sensors
+    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+    With assistance from Trent Piepho <xyzzy@speakeasy.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _LINUX_HWMON_VID_H
+#define _LINUX_HWMON_VID_H
+
+int vid_from_reg(int val, int vrm);
+int vid_which_vrm(void);
+
+/* vrm is the VRM/VRD document version multiplied by 10.
+   val is in mV to avoid floating point in the kernel.
+   Returned value is the 4-, 5- or 6-bit VID code.
+   Note that only VRM 9.x is supported for now. */
+static inline int vid_to_reg(int val, int vrm)
+{
+	switch (vrm) {
+	case 91:		/* VRM 9.1 */
+	case 90:		/* VRM 9.0 */
+		return ((val >= 1100) && (val <= 1850) ?
+			((18499 - val * 10) / 25 + 5) / 10 : -1);
+	default:
+		return -1;
+	}
+}
+
+#endif /* _LINUX_HWMON_VID_H */
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
new file mode 100644
index 0000000..0efd994
--- /dev/null
+++ b/include/linux/hwmon.h
@@ -0,0 +1,35 @@
+/*
+    hwmon.h - part of lm_sensors, Linux kernel modules for hardware monitoring
+
+    This file declares helper functions for the sysfs class "hwmon",
+    for use by sensors drivers.
+
+    Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; version 2 of the License.
+*/
+
+#ifndef _HWMON_H_
+#define _HWMON_H_
+
+#include <linux/device.h>
+
+struct class_device *hwmon_device_register(struct device *dev);
+
+void hwmon_device_unregister(struct class_device *cdev);
+
+/* Scale user input to sensible values */
+static inline int SENSORS_LIMIT(long value, long low, long high)
+{
+	if (value < low)
+		return low;
+	else if (value > high)
+		return high;
+	else
+		return value;
+}
+
+#endif
+
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 33f0825..44f3087 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -1,6 +1,6 @@
 /* ------------------------------------------------------------------------- */
 /* 									     */
-/* i2c.h - definitions for the i2c-bus interface			     */
+/* i2c-id.h - identifier values for i2c drivers and adapters		     */
 /* 									     */
 /* ------------------------------------------------------------------------- */
 /*   Copyright (C) 1995-1999 Simon G. Vogl
@@ -24,16 +24,6 @@
 #define LINUX_I2C_ID_H
 
 /*
- * This file is part of the i2c-bus package and contains the identifier
- * values for drivers, adapters and other folk populating these serial
- * worlds. 
- *
- * These will change often (i.e. additions) , therefore this has been 
- * separated from the functional interface definitions of the i2c api.
- *
- */
-
-/*
  * ---- Driver types -----------------------------------------------------
  *       device id name + number        function description, i2c address(es)
  *
@@ -170,151 +160,113 @@
 
 /*
  * ---- Adapter types ----------------------------------------------------
- *
- * First, we distinguish between several algorithms to access the hardware
- * interface types, as a PCF 8584 needs other care than a bit adapter.
- */
-
-#define I2C_ALGO_NONE	0x000000
-#define I2C_ALGO_BIT	0x010000	/* bit style adapters		*/
-#define I2C_ALGO_PCF	0x020000	/* PCF 8584 style adapters	*/
-#define I2C_ALGO_ATI	0x030000	/* ATI video card		*/
-#define I2C_ALGO_SMBUS	0x040000
-#define I2C_ALGO_ISA 	0x050000	/* lm_sensors ISA pseudo-adapter */
-#define I2C_ALGO_SAA7146 0x060000	/* SAA 7146 video decoder bus	*/
-#define I2C_ALGO_ACB 	0x070000	/* ACCESS.bus algorithm         */
-#define I2C_ALGO_IIC    0x080000 	/* ITE IIC bus */
-#define I2C_ALGO_SAA7134 0x090000
-#define I2C_ALGO_MPC824X 0x0a0000	/* Motorola 8240 / 8245         */
-#define I2C_ALGO_IPMI 	0x0b0000	/* IPMI dummy adapter */
-#define I2C_ALGO_IPMB 	0x0c0000	/* IPMB adapter */
-#define I2C_ALGO_MPC107 0x0d0000
-#define I2C_ALGO_EC     0x100000        /* ACPI embedded controller     */
-
-#define I2C_ALGO_MPC8XX 0x110000	/* MPC8xx PowerPC I2C algorithm */
-#define I2C_ALGO_OCP    0x120000	/* IBM or otherwise On-chip I2C algorithm */
-#define I2C_ALGO_BITHS	0x130000	/* enhanced bit style adapters	*/
-#define I2C_ALGO_IOP3XX	0x140000	/* XSCALE IOP3XX On-chip I2C alg */
-#define I2C_ALGO_SIBYTE 0x150000	/* Broadcom SiByte SOCs		*/
-#define I2C_ALGO_SGI	0x160000	/* SGI algorithm		*/
-
-#define I2C_ALGO_USB	0x170000	/* USB algorithm		*/
-#define I2C_ALGO_VIRT	0x180000	/* Virtual bus adapter		*/
-
-#define I2C_ALGO_MV64XXX 0x190000	/* Marvell mv64xxx i2c ctlr	*/
-#define I2C_ALGO_PCA	0x1a0000	/* PCA 9564 style adapters	*/
-#define I2C_ALGO_AU1550	0x1b0000        /* Au1550 PSC algorithm		*/
-
-#define I2C_ALGO_EXP	0x800000	/* experimental			*/
-
-#define I2C_ALGO_MASK	0xff0000	/* Mask for algorithms		*/
-#define I2C_ALGO_SHIFT	0x10	/* right shift to get index values 	*/
-
-#define I2C_HW_ADAPS	0x10000		/* # adapter types		*/
-#define I2C_HW_MASK	0xffff		
-
-
-/* hw specific modules that are defined per algorithm layer
  */
 
 /* --- Bit algorithm adapters 						*/
-#define I2C_HW_B_LP	0x00	/* Parallel port Philips style adapter	*/
-#define I2C_HW_B_LPC	0x01	/* Parallel port, over control reg.	*/
-#define I2C_HW_B_SER	0x02	/* Serial line interface		*/
-#define I2C_HW_B_ELV	0x03	/* ELV Card				*/
-#define I2C_HW_B_VELLE	0x04	/* Vellemann K8000			*/
-#define I2C_HW_B_BT848	0x05	/* BT848 video boards			*/
-#define I2C_HW_B_WNV	0x06	/* Winnov Videums			*/
-#define I2C_HW_B_VIA	0x07	/* Via vt82c586b			*/
-#define I2C_HW_B_HYDRA	0x08	/* Apple Hydra Mac I/O			*/
-#define I2C_HW_B_G400	0x09	/* Matrox G400				*/
-#define I2C_HW_B_I810	0x0a	/* Intel I810 				*/
-#define I2C_HW_B_VOO	0x0b	/* 3dfx Voodoo 3 / Banshee      	*/
-#define I2C_HW_B_PPORT  0x0c	/* Primitive parallel port adapter	*/
-#define I2C_HW_B_SAVG	0x0d	/* Savage 4                     	*/
-#define I2C_HW_B_SCX200	0x0e	/* Nat'l Semi SCx200 I2C        	*/
-#define I2C_HW_B_RIVA	0x10	/* Riva based graphics cards		*/
-#define I2C_HW_B_IOC	0x11	/* IOC bit-wiggling			*/
-#define I2C_HW_B_TSUNA  0x12	/* DEC Tsunami chipset			*/
-#define I2C_HW_B_FRODO  0x13    /* 2d3D, Inc. SA-1110 Development Board */
-#define I2C_HW_B_OMAHA  0x14    /* Omaha I2C interface (ARM)		*/
-#define I2C_HW_B_GUIDE  0x15    /* Guide bit-basher			*/
-#define I2C_HW_B_IXP2000 0x16	/* GPIO on IXP2000 systems              */
-#define I2C_HW_B_IXP4XX 0x17	/* GPIO on IXP4XX systems		*/
-#define I2C_HW_B_S3VIA	0x18	/* S3Via ProSavage adapter		*/
-#define I2C_HW_B_ZR36067 0x19	/* Zoran-36057/36067 based boards	*/
-#define I2C_HW_B_PCILYNX 0x1a	/* TI PCILynx I2C adapter		*/
-#define I2C_HW_B_CX2388x 0x1b	/* connexant 2388x based tv cards	*/
+#define I2C_HW_B_LP		0x010000 /* Parallel port Philips style */
+#define I2C_HW_B_LPC		0x010001 /* Parallel port control reg. */
+#define I2C_HW_B_SER		0x010002 /* Serial line interface */
+#define I2C_HW_B_ELV		0x010003 /* ELV Card */
+#define I2C_HW_B_VELLE		0x010004 /* Vellemann K8000 */
+#define I2C_HW_B_BT848		0x010005 /* BT848 video boards */
+#define I2C_HW_B_WNV		0x010006 /* Winnov Videums */
+#define I2C_HW_B_VIA		0x010007 /* Via vt82c586b */
+#define I2C_HW_B_HYDRA		0x010008 /* Apple Hydra Mac I/O */
+#define I2C_HW_B_G400		0x010009 /* Matrox G400 */
+#define I2C_HW_B_I810		0x01000a /* Intel I810 */
+#define I2C_HW_B_VOO		0x01000b /* 3dfx Voodoo 3 / Banshee */
+#define I2C_HW_B_PPORT		0x01000c /* Primitive parallel port adapter */
+#define I2C_HW_B_SAVG		0x01000d /* Savage 4 */
+#define I2C_HW_B_SCX200		0x01000e /* Nat'l Semi SCx200 I2C */
+#define I2C_HW_B_RIVA		0x010010 /* Riva based graphics cards */
+#define I2C_HW_B_IOC		0x010011 /* IOC bit-wiggling */
+#define I2C_HW_B_TSUNA		0x010012 /* DEC Tsunami chipset */
+#define I2C_HW_B_FRODO		0x010013 /* 2d3D SA-1110 Development Board */
+#define I2C_HW_B_OMAHA		0x010014 /* Omaha I2C interface (ARM) */
+#define I2C_HW_B_GUIDE		0x010015 /* Guide bit-basher */
+#define I2C_HW_B_IXP2000	0x010016 /* GPIO on IXP2000 systems */
+#define I2C_HW_B_IXP4XX		0x010017 /* GPIO on IXP4XX systems */
+#define I2C_HW_B_S3VIA		0x010018 /* S3Via ProSavage adapter */
+#define I2C_HW_B_ZR36067	0x010019 /* Zoran-36057/36067 based boards */
+#define I2C_HW_B_PCILYNX	0x01001a /* TI PCILynx I2C adapter */
+#define I2C_HW_B_CX2388x	0x01001b /* connexant 2388x based tv cards */
+#define I2C_HW_B_NVIDIA		0x01001c /* nvidia framebuffer driver */
+#define I2C_HW_B_SAVAGE		0x01001d /* savage framebuffer driver */
+#define I2C_HW_B_RADEON		0x01001e /* radeon framebuffer driver */
 
 /* --- PCF 8584 based algorithms					*/
-#define I2C_HW_P_LP	0x00	/* Parallel port interface		*/
-#define I2C_HW_P_ISA	0x01	/* generic ISA Bus inteface card	*/
-#define I2C_HW_P_ELEK	0x02	/* Elektor ISA Bus inteface card	*/
+#define I2C_HW_P_LP		0x020000 /* Parallel port interface */
+#define I2C_HW_P_ISA		0x020001 /* generic ISA Bus inteface card */
+#define I2C_HW_P_ELEK		0x020002 /* Elektor ISA Bus inteface card */
 
 /* --- PCA 9564 based algorithms */
-#define I2C_HW_A_ISA	0x00	/* generic ISA Bus interface card	*/
+#define I2C_HW_A_ISA		0x1a0000 /* generic ISA Bus interface card */
 
 /* --- ACPI Embedded controller algorithms                              */
-#define I2C_HW_ACPI_EC          0x00
+#define I2C_HW_ACPI_EC          0x1f0000
 
 /* --- MPC824x PowerPC adapters						*/
-#define I2C_HW_MPC824X 0x00	/* Motorola 8240 / 8245                 */
+#define I2C_HW_MPC824X		0x100001 /* Motorola 8240 / 8245 */
 
 /* --- MPC8xx PowerPC adapters						*/
-#define I2C_HW_MPC8XX_EPON 0x00	/* Eponymous MPC8xx I2C adapter 	*/
+#define I2C_HW_MPC8XX_EPON	0x110000 /* Eponymous MPC8xx I2C adapter */
 
 /* --- ITE based algorithms						*/
-#define I2C_HW_I_IIC	0x00	/* controller on the ITE */
+#define I2C_HW_I_IIC		0x080000 /* controller on the ITE */
 
 /* --- PowerPC on-chip adapters						*/
-#define I2C_HW_OCP 0x00	/* IBM on-chip I2C adapter 	*/
+#define I2C_HW_OCP		0x120000 /* IBM on-chip I2C adapter */
 
 /* --- Broadcom SiByte adapters						*/
-#define I2C_HW_SIBYTE	0x00
+#define I2C_HW_SIBYTE		0x150000
 
 /* --- SGI adapters							*/
-#define I2C_HW_SGI_VINO	0x00
-#define I2C_HW_SGI_MACE	0x01
+#define I2C_HW_SGI_VINO		0x160000
+#define I2C_HW_SGI_MACE		0x160001
 
 /* --- XSCALE on-chip adapters                          */
-#define I2C_HW_IOP3XX 0x00
+#define I2C_HW_IOP3XX		0x140000
 
 /* --- Au1550 PSC adapters adapters					*/
-#define I2C_HW_AU1550_PSC	0x00
+#define I2C_HW_AU1550_PSC	0x1b0000
 
 /* --- SMBus only adapters						*/
-#define I2C_HW_SMBUS_PIIX4	0x00
-#define I2C_HW_SMBUS_ALI15X3	0x01
-#define I2C_HW_SMBUS_VIA2	0x02
-#define I2C_HW_SMBUS_VOODOO3	0x03
-#define I2C_HW_SMBUS_I801	0x04
-#define I2C_HW_SMBUS_AMD756	0x05
-#define I2C_HW_SMBUS_SIS5595	0x06
-#define I2C_HW_SMBUS_ALI1535	0x07
-#define I2C_HW_SMBUS_SIS630	0x08
-#define I2C_HW_SMBUS_SIS96X	0x09
-#define I2C_HW_SMBUS_AMD8111	0x0a
-#define I2C_HW_SMBUS_SCX200	0x0b
-#define I2C_HW_SMBUS_NFORCE2	0x0c
-#define I2C_HW_SMBUS_W9968CF	0x0d
-#define I2C_HW_SMBUS_OV511	0x0e	/* OV511(+) USB 1.1 webcam ICs	*/
-#define I2C_HW_SMBUS_OV518	0x0f	/* OV518(+) USB 1.1 webcam ICs	*/
-#define I2C_HW_SMBUS_OV519	0x10	/* OV519 USB 1.1 webcam IC	*/
-#define I2C_HW_SMBUS_OVFX2	0x11	/* Cypress/OmniVision FX2 webcam */
+#define I2C_HW_SMBUS_PIIX4	0x040000
+#define I2C_HW_SMBUS_ALI15X3	0x040001
+#define I2C_HW_SMBUS_VIA2	0x040002
+#define I2C_HW_SMBUS_VOODOO3	0x040003
+#define I2C_HW_SMBUS_I801	0x040004
+#define I2C_HW_SMBUS_AMD756	0x040005
+#define I2C_HW_SMBUS_SIS5595	0x040006
+#define I2C_HW_SMBUS_ALI1535	0x040007
+#define I2C_HW_SMBUS_SIS630	0x040008
+#define I2C_HW_SMBUS_SIS96X	0x040009
+#define I2C_HW_SMBUS_AMD8111	0x04000a
+#define I2C_HW_SMBUS_SCX200	0x04000b
+#define I2C_HW_SMBUS_NFORCE2	0x04000c
+#define I2C_HW_SMBUS_W9968CF	0x04000d
+#define I2C_HW_SMBUS_OV511	0x04000e /* OV511(+) USB 1.1 webcam ICs */
+#define I2C_HW_SMBUS_OV518	0x04000f /* OV518(+) USB 1.1 webcam ICs */
+#define I2C_HW_SMBUS_OV519	0x040010 /* OV519 USB 1.1 webcam IC */
+#define I2C_HW_SMBUS_OVFX2	0x040011 /* Cypress/OmniVision FX2 webcam */
 
 /* --- ISA pseudo-adapter						*/
-#define I2C_HW_ISA 0x00
+#define I2C_HW_ISA		0x050000
 
 /* --- IPMI pseudo-adapter						*/
-#define I2C_HW_IPMI 0x00
+#define I2C_HW_IPMI		0x0b0000
 
 /* --- IPMB adapter						*/
-#define I2C_HW_IPMB 0x00
+#define I2C_HW_IPMB		0x0c0000
 
 /* --- MCP107 adapter */
-#define I2C_HW_MPC107 0x00
+#define I2C_HW_MPC107		0x0d0000
 
 /* --- Marvell mv64xxx i2c adapter */
-#define I2C_HW_MV64XXX 0x00
+#define I2C_HW_MV64XXX		0x190000
+
+/* --- Miscellaneous adapters */
+#define I2C_HW_SAA7146		0x060000 /* SAA7146 video decoder bus */
+#define I2C_HW_SAA7134		0x090000 /* SAA7134 video decoder bus */
 
 #endif /* LINUX_I2C_ID_H */
diff --git a/include/linux/i2c-isa.h b/include/linux/i2c-isa.h
new file mode 100644
index 0000000..67e3598
--- /dev/null
+++ b/include/linux/i2c-isa.h
@@ -0,0 +1,36 @@
+/*
+ * i2c-isa.h - definitions for the i2c-isa pseudo-i2c-adapter interface
+ *
+ * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LINUX_I2C_ISA_H
+#define _LINUX_I2C_ISA_H
+
+#include <linux/i2c.h>
+
+extern int i2c_isa_add_driver(struct i2c_driver *driver);
+extern int i2c_isa_del_driver(struct i2c_driver *driver);
+
+/* Detect whether we are on the isa bus. This is only useful to hybrid
+   (i2c+isa) drivers. */
+#define i2c_is_isa_adapter(adapptr) \
+        ((adapptr)->id == I2C_HW_ISA)
+#define i2c_is_isa_client(clientptr) \
+        i2c_is_isa_adapter((clientptr)->adapter)
+
+#endif /* _LINUX_I2C_ISA_H */
diff --git a/include/linux/i2c-sensor.h b/include/linux/i2c-sensor.h
deleted file mode 100644
index 21b6252..0000000
--- a/include/linux/i2c-sensor.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-    i2c-sensor.h - Part of the i2c package
-    was originally sensors.h - Part of lm_sensors, Linux kernel modules
-                               for hardware monitoring
-    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _LINUX_I2C_SENSOR_H
-#define _LINUX_I2C_SENSOR_H
-
-/* A structure containing detect information.
-   Force variables overrule all other variables; they force a detection on
-   that place. If a specific chip is given, the module blindly assumes this
-   chip type is present; if a general force (kind == 0) is given, the module
-   will still try to figure out what type of chip is present. This is useful
-   if for some reasons the detect for SMBus or ISA address space filled
-   fails.
-   probe: insmod parameter. Initialize this list with I2C_CLIENT_ISA_END values.
-     A list of pairs. The first value is a bus number (ANY_I2C_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the address. 
-   kind: The kind of chip. 0 equals any chip.
-*/
-struct i2c_force_data {
-	unsigned short *force;
-	unsigned short kind;
-};
-
-/* A structure containing the detect information.
-   normal_i2c: filled in by the module writer. Terminated by I2C_CLIENT_ISA_END.
-     A list of I2C addresses which should normally be examined.
-   normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
-     A list of ISA addresses which should normally be examined.
-   probe: insmod parameter. Initialize this list with I2C_CLIENT_ISA_END values.
-     A list of pairs. The first value is a bus number (ANY_I2C_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the address. These
-     addresses are also probed, as if they were in the 'normal' list.
-   ignore: insmod parameter. Initialize this list with I2C_CLIENT_ISA_END values.
-     A list of pairs. The first value is a bus number (ANY_I2C_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the I2C address. These
-     addresses are never probed. This parameter overrules 'normal' and 
-     'probe', but not the 'force' lists.
-   force_data: insmod parameters. A list, ending with an element of which
-     the force field is NULL.
-*/
-struct i2c_address_data {
-	unsigned short *normal_i2c;
-	unsigned int *normal_isa;
-	unsigned short *probe;
-	unsigned short *ignore;
-	struct i2c_force_data *forces;
-};
-
-#define SENSORS_MODULE_PARM_FORCE(name) \
-  I2C_CLIENT_MODULE_PARM(force_ ## name, \
-                      "List of adapter,address pairs which are unquestionably" \
-                      " assumed to contain a `" # name "' chip")
-
-
-/* This defines several insmod variables, and the addr_data structure */
-#define SENSORS_INSMOD \
-  I2C_CLIENT_MODULE_PARM(probe, \
-                      "List of adapter,address pairs to scan additionally"); \
-  I2C_CLIENT_MODULE_PARM(ignore, \
-                      "List of adapter,address pairs not to scan"); \
-	static struct i2c_address_data addr_data = {			\
-			.normal_i2c =		normal_i2c,		\
-			.normal_isa =		normal_isa,		\
-			.probe =		probe,			\
-			.ignore =		ignore,			\
-			.forces =		forces,			\
-		}
-
-/* The following functions create an enum with the chip names as elements. 
-   The first element of the enum is any_chip. These are the only macros
-   a module will want to use. */
-
-#define SENSORS_INSMOD_0 \
-  enum chips { any_chip }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  static struct i2c_force_data forces[] = {{force,any_chip},{NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_1(chip1) \
-  enum chips { any_chip, chip1 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  static struct i2c_force_data forces[] = {{force,any_chip},\
-                                                 {force_ ## chip1,chip1}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_2(chip1,chip2) \
-  enum chips { any_chip, chip1, chip2 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_3(chip1,chip2,chip3) \
-  enum chips { any_chip, chip1, chip2, chip3 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_4(chip1,chip2,chip3,chip4) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_5(chip1,chip2,chip3,chip4,chip5) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_6(chip1,chip2,chip3,chip4,chip5,chip6) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  SENSORS_MODULE_PARM_FORCE(chip6); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {force_ ## chip6,chip6}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_7(chip1,chip2,chip3,chip4,chip5,chip6,chip7) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  SENSORS_MODULE_PARM_FORCE(chip6); \
-  SENSORS_MODULE_PARM_FORCE(chip7); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {force_ ## chip6,chip6}, \
-                                                 {force_ ## chip7,chip7}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \
-  enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \
-  I2C_CLIENT_MODULE_PARM(force, \
-                      "List of adapter,address pairs to boldly assume " \
-                      "to be present"); \
-  SENSORS_MODULE_PARM_FORCE(chip1); \
-  SENSORS_MODULE_PARM_FORCE(chip2); \
-  SENSORS_MODULE_PARM_FORCE(chip3); \
-  SENSORS_MODULE_PARM_FORCE(chip4); \
-  SENSORS_MODULE_PARM_FORCE(chip5); \
-  SENSORS_MODULE_PARM_FORCE(chip6); \
-  SENSORS_MODULE_PARM_FORCE(chip7); \
-  SENSORS_MODULE_PARM_FORCE(chip8); \
-  static struct i2c_force_data forces[] = {{force,any_chip}, \
-                                                 {force_ ## chip1,chip1}, \
-                                                 {force_ ## chip2,chip2}, \
-                                                 {force_ ## chip3,chip3}, \
-                                                 {force_ ## chip4,chip4}, \
-                                                 {force_ ## chip5,chip5}, \
-                                                 {force_ ## chip6,chip6}, \
-                                                 {force_ ## chip7,chip7}, \
-                                                 {force_ ## chip8,chip8}, \
-                                                 {NULL}}; \
-  SENSORS_INSMOD
-
-/* Detect function. It iterates over all possible addresses itself. For
-   SMBus addresses, it will only call found_proc if some client is connected
-   to the SMBus (unless a 'force' matched); for ISA detections, this is not
-   done. */
-extern int i2c_detect(struct i2c_adapter *adapter,
-		      struct i2c_address_data *address_data,
-		      int (*found_proc) (struct i2c_adapter *, int, int));
-
-
-/* This macro is used to scale user-input to sensible values in almost all
-   chip drivers. */
-static inline int SENSORS_LIMIT(long value, long low, long high)
-{
-	if (value < low)
-		return low;
-	else if (value > high)
-		return high;
-	else
-		return value;
-}
-#endif				/* def _LINUX_I2C_SENSOR_H */
diff --git a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
deleted file mode 100644
index 41d0635..0000000
--- a/include/linux/i2c-vid.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-    i2c-vid.h - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
-    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
-    With assistance from Trent Piepho <xyzzy@speakeasy.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/*
-    This file contains common code for decoding VID pins.
-    This file is #included in various chip drivers in this directory.
-    As the user is unlikely to load more than one driver which
-    includes this code we don't worry about the wasted space.
-    Reference: VRM x.y DC-DC Converter Design Guidelines,
-    available at http://developer.intel.com
-*/
-
-/*
-    AMD Opteron processors don't follow the Intel VRM spec.
-    I'm going to "make up" 2.4 as the VRM spec for the Opterons.
-    No good reason just a mnemonic for the 24x Opteron processor
-    series
-
-    Opteron VID encoding is:
-
-       00000  =  1.550 V
-       00001  =  1.525 V
-        . . . .
-       11110  =  0.800 V
-       11111  =  0.000 V (off)
- */
-
-/*
-    Legal val values 0x00 - 0x1f; except for VRD 10.0, 0x00 - 0x3f.
-    vrm is the Intel VRM document version.
-    Note: vrm version is scaled by 10 and the return value is scaled by 1000
-    to avoid floating point in the kernel.
-*/
-
-int i2c_which_vrm(void);
-
-#define DEFAULT_VRM	82
-
-static inline int vid_from_reg(int val, int vrm)
-{
-	int vid;
-
-	switch(vrm) {
-
-	case  0:
-		return 0;
-
-	case 100:               /* VRD 10.0 */
-		if((val & 0x1f) == 0x1f)
-			return 0;
-		if((val & 0x1f) <= 0x09 || val == 0x0a)
-			vid = 10875 - (val & 0x1f) * 250;
-		else
-			vid = 18625 - (val & 0x1f) * 250;
-		if(val & 0x20)
-			vid -= 125;
-		vid /= 10;      /* only return 3 dec. places for now */
-		return vid;
-
-	case 24:                /* Opteron processor */
-		return(val == 0x1f ? 0 : 1550 - val * 25);
-
-	case 91:		/* VRM 9.1 */
-	case 90:		/* VRM 9.0 */
-		return(val == 0x1f ? 0 :
-		                       1850 - val * 25);
-
-	case 85:		/* VRM 8.5 */
-		return((val & 0x10  ? 25 : 0) +
-		       ((val & 0x0f) > 0x04 ? 2050 : 1250) -
-		       ((val & 0x0f) * 50));
-
-	case 84:		/* VRM 8.4 */
-		val &= 0x0f;
-				/* fall through */
-	default:		/* VRM 8.2 */
-		return(val == 0x1f ? 0 :
-		       val & 0x10  ? 5100 - (val) * 100 :
-		                     2050 - (val) * 50);
-	}
-}
-
-static inline int vid_to_reg(int val, int vrm)
-{
-	switch (vrm) {
-	case 91:		/* VRM 9.1 */
-	case 90:		/* VRM 9.0 */
-		return ((val >= 1100) && (val <= 1850) ?
-			((18499 - val * 10) / 25 + 5) / 10 : -1);
-	default:
-		return -1;
-	}
-}
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index be837b1..be35332 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -34,6 +34,13 @@
 #include <linux/device.h>	/* for struct device */
 #include <asm/semaphore.h>
 
+/* --- For i2c-isa ---------------------------------------------------- */
+
+extern void i2c_adapter_dev_release(struct device *dev);
+extern struct device_driver i2c_adapter_driver;
+extern struct class i2c_adapter_class;
+extern struct bus_type i2c_bus_type;
+
 /* --- General options ------------------------------------------------	*/
 
 struct i2c_msg;
@@ -41,7 +48,6 @@
 struct i2c_adapter;
 struct i2c_client;
 struct i2c_driver;
-struct i2c_client_address_data;
 union i2c_smbus_data;
 
 /*
@@ -143,12 +149,9 @@
  */
 struct i2c_client {
 	unsigned int flags;		/* div., see below		*/
-	unsigned int addr;		/* chip address - NOTE: 7bit 	*/
+	unsigned short addr;		/* chip address - NOTE: 7bit 	*/
 					/* addresses are stored in the	*/
-					/* _LOWER_ 7 bits of this char	*/
-	/* addr: unsigned int to make lm_sensors i2c-isa adapter work
-	  more cleanly. It does not take any more memory space, due to
-	  alignment considerations */
+					/* _LOWER_ 7 bits		*/
 	struct i2c_adapter *adapter;	/* the adapter we sit on	*/
 	struct i2c_driver *driver;	/* and our access routines	*/
 	int usage_count;		/* How many accesses currently  */
@@ -160,6 +163,11 @@
 };
 #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
 
+static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
+{
+	return to_i2c_client(container_of(kobj, struct device, kobj));
+}
+
 static inline void *i2c_get_clientdata (struct i2c_client *dev)
 {
 	return dev_get_drvdata (&dev->dev);
@@ -170,13 +178,6 @@
 	dev_set_drvdata (&dev->dev, data);
 }
 
-#define I2C_DEVNAME(str)	.name = str
-
-static inline char *i2c_clientname(struct i2c_client *c)
-{
-	return &c->name[0];
-}
-
 /*
  * The following structs are for those who like to implement new bus drivers:
  * i2c_algorithm is the interface to a class of hardware solutions which can
@@ -184,9 +185,6 @@
  * to name two of the most common.
  */
 struct i2c_algorithm {
-	char name[32];				/* textual description 	*/
-	unsigned int id;
-
 	/* If an adapter algorithm can't do I2C-level access, set master_xfer
 	   to NULL. If an adapter algorithm can do SMBus access, set 
 	   smbus_xfer. If set to NULL, the SMBus protocol is simulated
@@ -214,8 +212,7 @@
  */
 struct i2c_adapter {
 	struct module *owner;
-	unsigned int id;/* == is algo->id | hwdep.struct->id, 		*/
-			/* for registered values see below		*/
+	unsigned int id;
 	unsigned int class;
 	struct i2c_algorithm *algo;/* the algorithm to access the bus	*/
 	void *algo_data;
@@ -292,12 +289,11 @@
 	unsigned short *normal_i2c;
 	unsigned short *probe;
 	unsigned short *ignore;
-	unsigned short *force;
+	unsigned short **forces;
 };
 
 /* Internal numbers to terminate lists */
 #define I2C_CLIENT_END		0xfffeU
-#define I2C_CLIENT_ISA_END	0xfffefffeU
 
 /* The numbers to use to set I2C bus address */
 #define ANY_I2C_BUS		0xffff
@@ -356,10 +352,6 @@
  */
 extern int i2c_control(struct i2c_client *,unsigned int, unsigned long);
 
-/* This call returns a unique low identifier for each registered adapter,
- * or -1 if the adapter was not registered. 
- */
-extern int i2c_adapter_id(struct i2c_adapter *adap);
 extern struct i2c_adapter* i2c_get_adapter(int id);
 extern void i2c_put_adapter(struct i2c_adapter *adap);
 
@@ -376,6 +368,12 @@
 	return (func & i2c_get_functionality(adap)) == func;
 }
 
+/* Return id number for a specific adapter */
+static inline int i2c_adapter_id(struct i2c_adapter *adap)
+{
+	return adap->nr;
+}
+
 /*
  * I2C Message - used for pure i2c transaction, also from /dev interface
  */
@@ -510,9 +508,6 @@
 #define I2C_FUNCS	0x0705	/* Get the adapter functionality */
 #define I2C_RDWR	0x0707	/* Combined R/W transfer (one stop only)*/
 #define I2C_PEC		0x0708	/* != 0 for SMBus PEC                   */
-#if 0
-#define I2C_ACK_TEST	0x0710	/* See if a slave is at a specific address */
-#endif
 
 #define I2C_SMBUS	0x0720	/* SMBus-level access */
 
@@ -556,27 +551,148 @@
   module_param_array(var, short, &var##_num, 0); \
   MODULE_PARM_DESC(var,desc)
 
-/* This is the one you want to use in your own modules */
+#define I2C_CLIENT_MODULE_PARM_FORCE(name)				\
+I2C_CLIENT_MODULE_PARM(force_##name,					\
+		       "List of adapter,address pairs which are "	\
+		       "unquestionably assumed to contain a `"		\
+		       # name "' chip")
+
+
+#define I2C_CLIENT_INSMOD_COMMON					\
+I2C_CLIENT_MODULE_PARM(probe, "List of adapter,address pairs to scan "	\
+		       "additionally");					\
+I2C_CLIENT_MODULE_PARM(ignore, "List of adapter,address pairs not to "	\
+		       "scan");						\
+static struct i2c_client_address_data addr_data = {			\
+	.normal_i2c	= normal_i2c,					\
+	.probe		= probe,					\
+	.ignore		= ignore,					\
+	.forces		= forces,					\
+}
+
+/* These are the ones you want to use in your own drivers. Pick the one
+   which matches the number of devices the driver differenciates between. */
 #define I2C_CLIENT_INSMOD \
-  I2C_CLIENT_MODULE_PARM(probe, \
-                      "List of adapter,address pairs to scan additionally"); \
-  I2C_CLIENT_MODULE_PARM(ignore, \
-                      "List of adapter,address pairs not to scan"); \
   I2C_CLIENT_MODULE_PARM(force, \
                       "List of adapter,address pairs to boldly assume " \
                       "to be present"); \
-	static struct i2c_client_address_data addr_data = {		\
-			.normal_i2c = 		normal_i2c,		\
-			.probe =		probe,			\
-			.ignore =		ignore,			\
-			.force =		force,			\
-		}
+	static unsigned short *forces[] = {				\
+			force,						\
+			NULL						\
+		};							\
+I2C_CLIENT_INSMOD_COMMON
 
-/* Detect whether we are on the isa bus. If this returns true, all i2c
-   access will fail! */
-#define i2c_is_isa_client(clientptr) \
-        ((clientptr)->adapter->algo->id == I2C_ALGO_ISA)
-#define i2c_is_isa_adapter(adapptr) \
-        ((adapptr)->algo->id == I2C_ALGO_ISA)
+#define I2C_CLIENT_INSMOD_1(chip1)					\
+enum chips { any_chip, chip1 };						\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+static unsigned short *forces[] = { force, force_##chip1, NULL };	\
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_2(chip1, chip2)				\
+enum chips { any_chip, chip1, chip2 };					\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip2);					\
+static unsigned short *forces[] = { force, force_##chip1,		\
+				    force_##chip2, NULL };		\
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_3(chip1, chip2, chip3)			\
+enum chips { any_chip, chip1, chip2, chip3 };				\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip2);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip3);					\
+static unsigned short *forces[] = { force, force_##chip1,		\
+				    force_##chip2, force_##chip3,	\
+				    NULL };				\
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_4(chip1, chip2, chip3, chip4)			\
+enum chips { any_chip, chip1, chip2, chip3, chip4 };			\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip2);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip3);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip4);					\
+static unsigned short *forces[] = { force, force_##chip1,		\
+				    force_##chip2, force_##chip3,	\
+				    force_##chip4, NULL};		\
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_5(chip1, chip2, chip3, chip4, chip5)		\
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 };		\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip2);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip3);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip4);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip5);					\
+static unsigned short *forces[] = { force, force_##chip1,		\
+				    force_##chip2, force_##chip3,	\
+				    force_##chip4, force_##chip5,	\
+				    NULL };				\
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_6(chip1, chip2, chip3, chip4, chip5, chip6)	\
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 };	\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip2);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip3);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip4);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip5);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip6);					\
+static unsigned short *forces[] = { force, force_##chip1,		\
+				    force_##chip2, force_##chip3,	\
+				    force_##chip4, force_##chip5,	\
+				    force_##chip6, NULL };		\
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_7(chip1, chip2, chip3, chip4, chip5, chip6, chip7) \
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6,	\
+	     chip7 };							\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip2);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip3);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip4);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip5);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip6);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip7);					\
+static unsigned short *forces[] = { force, force_##chip1,		\
+				    force_##chip2, force_##chip3,	\
+				    force_##chip4, force_##chip5,	\
+				    force_##chip6, force_##chip7,	\
+				    NULL };				\
+I2C_CLIENT_INSMOD_COMMON
+
+#define I2C_CLIENT_INSMOD_8(chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8) \
+enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6,	\
+	     chip7, chip8 };						\
+I2C_CLIENT_MODULE_PARM(force, "List of adapter,address pairs to "	\
+		       "boldly assume to be present");			\
+I2C_CLIENT_MODULE_PARM_FORCE(chip1);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip2);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip3);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip4);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip5);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip6);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip7);					\
+I2C_CLIENT_MODULE_PARM_FORCE(chip8);					\
+static unsigned short *forces[] = { force, force_##chip1,		\
+				    force_##chip2, force_##chip3,	\
+				    force_##chip4, force_##chip5,	\
+				    force_##chip6, force_##chip7,	\
+				    force_##chip8, NULL };		\
+I2C_CLIENT_INSMOD_COMMON
 
 #endif /* _LINUX_I2C_H */
diff --git a/include/linux/klist.h b/include/linux/klist.h
index eebf5e5..c4d1fae 100644
--- a/include/linux/klist.h
+++ b/include/linux/klist.h
@@ -9,6 +9,9 @@
  *	This file is rleased under the GPL v2.
  */
 
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/kref.h>
@@ -31,8 +34,8 @@
 	struct completion	n_removed;
 };
 
-extern void klist_add_tail(struct klist * k, struct klist_node * n);
-extern void klist_add_head(struct klist * k, struct klist_node * n);
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
 
 extern void klist_del(struct klist_node * n);
 extern void klist_remove(struct klist_node * n);
@@ -53,3 +56,4 @@
 extern void klist_iter_exit(struct klist_iter * i);
 extern struct klist_node * klist_next(struct klist_iter * i);
 
+#endif
diff --git a/include/media/id.h b/include/media/id.h
index a39a642..801ddef 100644
--- a/include/media/id.h
+++ b/include/media/id.h
@@ -34,8 +34,3 @@
 #ifndef  I2C_DRIVERID_SAA6752HS
 # define I2C_DRIVERID_SAA6752HS I2C_DRIVERID_EXP0+8
 #endif
-
-/* algorithms */
-#ifndef I2C_ALGO_SAA7134
-# define I2C_ALGO_SAA7134 0x090000
-#endif
diff --git a/include/net/irda/irlan_filter.h b/include/net/irda/irlan_filter.h
index 3afeb6c..492deda 100644
--- a/include/net/irda/irlan_filter.h
+++ b/include/net/irda/irlan_filter.h
@@ -28,6 +28,6 @@
 void irlan_check_command_param(struct irlan_cb *self, char *param, 
 			       char *value);
 void irlan_filter_request(struct irlan_cb *self, struct sk_buff *skb);
-int irlan_print_filter(struct seq_file *seq, int filter_type);
+void irlan_print_filter(struct seq_file *seq, int filter_type);
 
 #endif /* IRLAN_FILTER_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index cf62826..8c48fbe 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1377,9 +1377,10 @@
 
 #ifdef CONFIG_SYSCTL
 extern struct ctl_table core_table[];
-extern int sysctl_optmem_max;
 #endif
 
+extern int sysctl_optmem_max;
+
 extern __u32 sysctl_wmem_default;
 extern __u32 sysctl_rmem_default;
 
diff --git a/init/Kconfig b/init/Kconfig
index 05a75c4..d5a1a12 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -77,6 +77,22 @@
 	  object and source tree, in that order.  Your total string can
 	  be a maximum of 64 characters.
 
+config LOCALVERSION_AUTO
+	bool "Automatically append version information to the version string"
+	default y
+	help
+	  This will try to automatically determine if the current tree is a
+	  release tree by looking for git tags that
+	  belong to the current top of tree revision.
+
+	  A string of the format -gxxxxxxxx will be added to the localversion
+	  if a git based tree is found.  The string generated by this will be
+	  appended after any matching localversion* files, and after the value
+	  set in CONFIG_LOCALVERSION
+
+	  Note: This requires Perl, and a git repository, but not necessarily
+	  the git or cogito tools to be installed.
+
 config SWAP
 	bool "Support for paging of anonymous memory (swap)"
 	depends on MMU
@@ -238,6 +254,8 @@
 
 	  Say N if unsure.
 
+source "usr/Kconfig"
+
 menuconfig EMBEDDED
 	bool "Configure standard kernel features (for small systems)"
 	help
@@ -260,8 +278,8 @@
 	help
 	   Normally kallsyms only contains the symbols of functions, for nicer
 	   OOPS messages.  Some debuggers can use kallsyms for other
-	   symbols too: say Y here to include all symbols, and you
-	   don't care about adding 300k to the size of your kernel.
+	   symbols too: say Y here to include all symbols, if you need them 
+	   and you don't care about adding 300k to the size of your kernel.
 
 	   Say N.
 
diff --git a/init/Makefile b/init/Makefile
index 93a53fb..a230007 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -25,4 +25,5 @@
 
 include/linux/compile.h: FORCE
 	@echo '  CHK     $@'
-	@$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CC) $(CFLAGS)"
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
+	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(CFLAGS)"
diff --git a/lib/klist.c b/lib/klist.c
index 738ab81..a70c836 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -79,11 +79,11 @@
 
 /**
  *	klist_add_head - Initialize a klist_node and add it to front.
- *	@k:	klist it's going on.
  *	@n:	node we're adding.
+ *	@k:	klist it's going on.
  */
 
-void klist_add_head(struct klist * k, struct klist_node * n)
+void klist_add_head(struct klist_node * n, struct klist * k)
 {
 	klist_node_init(k, n);
 	add_head(k, n);
@@ -94,11 +94,11 @@
 
 /**
  *	klist_add_tail - Initialize a klist_node and add it to back.
- *	@k:	klist it's going on.
  *	@n:	node we're adding.
+ *	@k:	klist it's going on.
  */
 
-void klist_add_tail(struct klist * k, struct klist_node * n)
+void klist_add_tail(struct klist_node * n, struct klist * k)
 {
 	klist_node_init(k, n);
 	add_tail(k, n);
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index 4dbb5af..d89056e 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -21,6 +21,7 @@
 
 #include "resources.h"
 #include "signaling.h"		/* for WAITING and sigd_attach */
+#include "common.h"
 
 
 static DECLARE_MUTEX(ioctl_mutex);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 289c1b5..404b761 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -695,7 +695,7 @@
 	return ret;
 }
 
-static int ethtool_get_perm_addr(struct net_device *dev, void *useraddr)
+static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_perm_addr epaddr;
 	u8 *data;
diff --git a/net/core/filter.c b/net/core/filter.c
index cd91a24..079c2ed 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -182,7 +182,7 @@
 				A = ntohl(*(u32 *)ptr);
 				continue;
 			}
-			return 0;
+			break;
 		case BPF_LD|BPF_H|BPF_ABS:
 			k = fentry->k;
  load_h:
@@ -191,7 +191,7 @@
 				A = ntohs(*(u16 *)ptr);
 				continue;
 			}
-			return 0;
+			break;
 		case BPF_LD|BPF_B|BPF_ABS:
 			k = fentry->k;
 load_b:
@@ -200,7 +200,7 @@
 				A = *(u8 *)ptr;
 				continue;
 			}
-			return 0;
+			break;
 		case BPF_LD|BPF_W|BPF_LEN:
 			A = skb->len;
 			continue;
diff --git a/net/core/sock.c b/net/core/sock.c
index ccd10fd..c135945 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1719,8 +1719,8 @@
 EXPORT_SYMBOL(sock_wmalloc);
 EXPORT_SYMBOL(sock_i_uid);
 EXPORT_SYMBOL(sock_i_ino);
-#ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_optmem_max);
+#ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_rmem_max);
 EXPORT_SYMBOL(sysctl_wmem_max);
 #endif
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index d582faa..a5905f5 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -831,7 +831,7 @@
 	left = stats->len - ((void *)info_element - (void *)beacon);
 	while (left >= sizeof(struct ieee80211_info_element_hdr)) {
 		if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
-			IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
+			IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n",
 					     info_element->len + sizeof(struct ieee80211_info_element),
 					     left);
 			return 1;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 63e1066..953129d 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -54,6 +54,7 @@
 #include <linux/major.h>
 #include <linux/root_dev.h>
 #include <linux/delay.h>
+#include <linux/nfs_fs.h>
 #include <net/arp.h>
 #include <net/ip.h>
 #include <net/ipconfig.h>
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index cbcc9fc..f3f0013 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -769,10 +769,10 @@
 					if (off == PAGE_SIZE) {
 						put_page(page);
 						TCP_PAGE(sk) = page = NULL;
-						TCP_OFF(sk) = off = 0;
+						off = 0;
 					}
 				} else
-					BUG_ON(off);
+					off = 0;
 
 				if (copy > PAGE_SIZE - off)
 					copy = PAGE_SIZE - off;
diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
index 343c5d4..ca7d358 100644
--- a/net/irda/irlan/irlan_filter.c
+++ b/net/irda/irlan/irlan_filter.c
@@ -27,6 +27,7 @@
 #include <linux/seq_file.h>
 
 #include <net/irda/irlan_common.h>
+#include <net/irda/irlan_filter.h>
 
 /*
  * Function irlan_filter_request (self, skb)
diff --git a/net/irda/qos.c b/net/irda/qos.c
index df732d5..ddfb5c5 100644
--- a/net/irda/qos.c
+++ b/net/irda/qos.c
@@ -37,6 +37,7 @@
 #include <net/irda/parameters.h>
 #include <net/irda/qos.h>
 #include <net/irda/irlap.h>
+#include <net/irda/irlap_frame.h>
 
 /*
  * Maximum values of the baud rate we negociate with the other end.
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index e089f17..49a3900 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -344,14 +344,14 @@
 	} while(nfnl && nfnl->sk_receive_queue.qlen);
 }
 
-void __exit nfnetlink_exit(void)
+static void __exit nfnetlink_exit(void)
 {
 	printk("Removing netfilter NETLINK layer.\n");
 	sock_release(nfnl->sk_socket);
 	return;
 }
 
-int __init nfnetlink_init(void)
+static int __init nfnetlink_init(void)
 {
 	printk("Netfilter messages via NETLINK v%s.\n", nfversion);
 
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index e3a5285..249bddb 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -76,17 +76,6 @@
 
 static DEFINE_RWLOCK(instances_lock);
 
-u_int64_t htonll(u_int64_t in)
-{
-	u_int64_t out;
-	int i;
-
-	for (i = 0; i < sizeof(u_int64_t); i++)
-		((u_int8_t *)&out)[sizeof(u_int64_t)-1] = ((u_int8_t *)&in)[i];
-
-	return out;
-}
-
 #define INSTANCE_BUCKETS	16
 static struct hlist_head instance_table[INSTANCE_BUCKETS];
 
@@ -497,8 +486,8 @@
 	if (entry->skb->tstamp.off_sec) {
 		struct nfqnl_msg_packet_timestamp ts;
 
-		ts.sec = htonll(skb_tv_base.tv_sec + entry->skb->tstamp.off_sec);
-		ts.usec = htonll(skb_tv_base.tv_usec + entry->skb->tstamp.off_usec);
+		ts.sec = cpu_to_be64(skb_tv_base.tv_sec + entry->skb->tstamp.off_sec);
+		ts.usec = cpu_to_be64(skb_tv_base.tv_usec + entry->skb->tstamp.off_usec);
 
 		NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
 	}
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index dc48934..75b28dd 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -42,6 +42,7 @@
  */
 
 #include <net/sctp/structs.h>
+#include <net/sctp/sctp.h>
 #include <linux/sysctl.h>
 
 static ctl_handler sctp_sysctl_jiffies_ms;
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
new file mode 100644
index 0000000..9087273
--- /dev/null
+++ b/scripts/Kbuild.include
@@ -0,0 +1,96 @@
+####
+# kbuild: Generic definitions
+
+# Convinient variables
+comma   := ,
+empty   :=
+space   := $(empty) $(empty)
+
+###
+# The temporary file to save gcc -MD generated dependencies must not
+# contain a comma
+depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
+
+###
+# filechk is used to check if the content of a generated file is updated.
+# Sample usage:
+# define filechk_sample
+#	echo $KERNELRELEASE
+# endef
+# version.h : Makefile
+#	$(call filechk,sample)
+# The rule defined shall write to stdout the content of the new file.
+# The existing file will be compared with the new one.
+# - If no file exist it is created
+# - If the content differ the new file is used
+# - If they are equal no change, and no timestamp update
+# - stdin is piped in from the first prerequisite ($<) so one has
+#   to specify a valid file as first prerequisite (often the kbuild file)
+define filechk
+	$(Q)set -e;				\
+	echo '  CHK     $@';			\
+	mkdir -p $(dir $@);			\
+	$(filechk_$(1)) < $< > $@.tmp;		\
+	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
+		rm -f $@.tmp;			\
+	else					\
+		echo '  UPD     $@';		\
+		mv -f $@.tmp $@;		\
+	fi
+endef
+
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
+# Usage:
+# $(Q)$(MAKE) $(build)=dir
+build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
+
+# If quiet is set, only print short version of command
+cmd = @$(if $($(quiet)cmd_$(1)),\
+      echo '  $(subst ','\'',$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
+
+###
+# if_changed      - execute command if any prerequisite is newer than 
+#                   target, or command line has changed
+# if_changed_dep  - as if_changed, but uses fixdep to reveal dependencies
+#                   including used config symbols
+# if_changed_rule - as if_changed but execute rule instead
+# See Documentation/kbuild/makefiles.txt for more info
+
+ifneq ($(KBUILD_NOCMDDEP),1)
+# Check if both arguments has same arguments. Result in empty string if equal
+# User may override this check using make KBUILD_NOCMDDEP=1
+arg-check = $(strip $(filter-out $(1), $(2)) $(filter-out $(2), $(1)) )
+endif
+
+# echo command. Short version is $(quiet) equals quiet, otherwise full command
+echo-cmd = $(if $($(quiet)cmd_$(1)), \
+	echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';)
+
+# function to only execute the passed command if necessary
+# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
+# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
+# 
+if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
+	@set -e; \
+	$(echo-cmd) \
+	$(cmd_$(1)); \
+	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
+
+# execute the command and also postprocess generated .d dependencies
+# file
+if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
+	$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),                  \
+	@set -e; \
+	$(echo-cmd) \
+	$(cmd_$(1)); \
+	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
+	rm -f $(depfile); \
+	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
+
+# Usage: $(call if_changed_rule,foo)
+# will check if $(cmd_foo) changed, or any of the prequisites changed,
+# and if so will execute $(rule_foo)
+if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
+			@set -e; \
+			$(rule_$(1)))
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 76ba6be..506e3f3 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -10,8 +10,11 @@
 # Read .config if it exist, otherwise ignore
 -include .config
 
-include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
 
+include scripts/Kbuild.include
 include scripts/Makefile.lib
 
 ifdef host-progs
@@ -169,7 +172,7 @@
 			-T $(@D)/.tmp_$(@F:.o=.ver);			\
 		rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);	\
 	else								\
-		mv $(@D)/.tmp_$(@F) $@;					\
+		mv -f $(@D)/.tmp_$(@F) $@;				\
 	fi;
 endif
 
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index ff3e87d..8974ea5 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -7,7 +7,14 @@
 .PHONY: __clean
 __clean:
 
-include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)
+# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
+# Usage:
+# $(Q)$(MAKE) $(clean)=dir
+clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
+
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
 
 # Figure out what we need to build from the various variables
 # ==========================================================================
@@ -87,8 +94,3 @@
 # If quiet is set, only print short version of command
 
 cmd = @$(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
-
-# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir
-# Usage:
-# $(Q)$(MAKE) $(clean)=dir
-clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 2821a2b..2d51970 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -98,7 +98,8 @@
 # Create executable from a single .c file
 # host-csingle -> Executable
 quiet_cmd_host-csingle 	= HOSTCC  $@
-      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $<
+      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) -o $@ $< \
+	  	$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
 $(host-csingle): %: %.c FORCE
 	$(call if_changed_dep,host-csingle)
 
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 7cf75cc..0f81dcf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -1,13 +1,3 @@
-# ===========================================================================
-# kbuild: Generic definitions
-# ===========================================================================
-
-# Standard vars
-
-comma   := ,
-empty   :=
-space   := $(empty) $(empty)
-
 # Backward compatibility - to be removed...
 extra-y	+= $(EXTRA_TARGETS)
 # Figure out what we need to build from the various variables
@@ -84,10 +74,6 @@
 subdir-ym	:= $(addprefix $(obj)/,$(subdir-ym))
 obj-dirs	:= $(addprefix $(obj)/,$(obj-dirs))
 
-# The temporary file to save gcc -MD generated dependencies must not
-# contain a comma
-depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
-
 # These flags are needed for modversions and compiling, so we define them here
 # already
 # $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will 
@@ -179,89 +165,4 @@
 quiet_cmd_gzip = GZIP    $@
 cmd_gzip = gzip -f -9 < $< > $@
 
-# ===========================================================================
-# Generic stuff
-# ===========================================================================
-
-ifneq ($(KBUILD_NOCMDDEP),1)
-# Check if both arguments has same arguments. Result in empty string if equal
-# User may override this check using make KBUILD_NOCMDDEP=1
-arg-check = $(strip $(filter-out $(1), $(2)) $(filter-out $(2), $(1)) )
-
-endif
-
-# echo command. Short version is $(quiet) equals quiet, otherwise full command
-echo-cmd = $(if $($(quiet)cmd_$(1)), \
-	echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';)
-
-# function to only execute the passed command if necessary
-# >'< substitution is for echo to work, >$< substitution to preserve $ when reloading .cmd file
-# note: when using inline perl scripts [perl -e '...$$t=1;...'] in $(cmd_xxx) double $$ your perl vars
-# 
-if_changed = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ), \
-	@set -e; \
-	$(echo-cmd) \
-	$(cmd_$(1)); \
-	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
-
-
-# execute the command and also postprocess generated .d dependencies
-# file
-
-if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
-	$(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),                  \
-	@set -e; \
-	$(echo-cmd) \
-	$(cmd_$(1)); \
-	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
-	rm -f $(depfile); \
-	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
-
-# Usage: $(call if_changed_rule,foo)
-# will check if $(cmd_foo) changed, or any of the prequisites changed,
-# and if so will execute $(rule_foo)
-
-if_changed_rule = $(if $(strip $? $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
-			@set -e; \
-			$(rule_$(1)))
-
-# If quiet is set, only print short version of command
-
-cmd = @$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
-
-#	$(call descend,<dir>,<target>)
-#	Recursively call a sub-make in <dir> with target <target> 
-# Usage is deprecated, because make do not see this as an invocation of make.
-descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
-
-# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
-# Usage:
-# $(Q)$(MAKE) $(build)=dir
-build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
-
-# filechk is used to check if the content of a generated file is updated.
-# Sample usage:
-# define filechk_sample
-#	echo $KERNELRELEASE
-# endef
-# version.h : Makefile
-#	$(call filechk,sample)
-# The rule defined shall write to stdout the content of the new file.
-# The existing file will be compared with the new one.
-# - If no file exist it is created
-# - If the content differ the new file is used
-# - If they are equal no change, and no timestamp update
-
-define filechk
-	$(Q)set -e;				\
-	echo '  CHK     $@';			\
-	mkdir -p $(dir $@);			\
-	$(filechk_$(1)) $(2) > $@.tmp;		\
-	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
-		rm -f $@.tmp;			\
-	else					\
-		echo '  UPD     $@';		\
-		mv -f $@.tmp $@;		\
-	fi
-endef
 
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 85d6494..23fd1bd 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -5,7 +5,7 @@
 .PHONY: __modinst
 __modinst:
 
-include scripts/Makefile.lib
+include scripts/Kbuild.include
 
 #
 
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 94b550e..0c4f3a9 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -36,6 +36,7 @@
 _modpost: __modpost
 
 include .config
+include scripts/Kbuild.include
 include scripts/Makefile.lib
 
 symverfile := $(objtree)/Module.symvers
diff --git a/scripts/conmakehash.c b/scripts/conmakehash.c
index 93dd23f2..e0c6891 100644
--- a/scripts/conmakehash.c
+++ b/scripts/conmakehash.c
@@ -33,7 +33,7 @@
 
 int getunicode(char **p0)
 {
-  unsigned char *p = *p0;
+  char *p = *p0;
 
   while (*p == ' ' || *p == '\t')
     p++;
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index d3d2e53..9be41a9f 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -207,9 +207,9 @@
 		 * move then they may get dropped in pass 2, which breaks the
 		 * kallsyms rules.
 		 */
-		if ((s->addr == _etext && strcmp(s->sym + offset, "_etext")) ||
-		    (s->addr == _einittext && strcmp(s->sym + offset, "_einittext")) ||
-		    (s->addr == _eextratext && strcmp(s->sym + offset, "_eextratext")))
+		if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) ||
+		    (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) ||
+		    (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext")))
 			return 0;
 	}
 
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 8b84c42..c3d2578 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -59,7 +59,7 @@
 void menu_end_entry(void);
 void menu_add_dep(struct expr *dep);
 struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep);
-void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
 void menu_finalize(struct menu *parent);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 8c59b21..5cfa6c4 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -136,9 +136,9 @@
 	return prop;
 }
 
-void menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
+struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep)
 {
-	menu_add_prop(type, prompt, NULL, dep);
+	return menu_add_prop(type, prompt, NULL, dep);
 }
 
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index f163d8d..ff4fcc0 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1531,7 +1531,7 @@
 
     {
 	menu_add_entry(NULL);
-	menu_add_prop(P_MENU, yyvsp[-1].string, NULL, NULL);
+	menu_add_prompt(P_MENU, yyvsp[-1].string, NULL);
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 ;}
     break;
@@ -1586,7 +1586,7 @@
 
     {
 	menu_add_entry(NULL);
-	menu_add_prop(P_COMMENT, yyvsp[-1].string, NULL, NULL);
+	menu_add_prompt(P_COMMENT, yyvsp[-1].string, NULL);
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 ;}
     break;
@@ -1640,7 +1640,7 @@
   case 86:
 
     {
-	menu_add_prop(P_PROMPT, yyvsp[-1].string, NULL, yyvsp[0].expr);
+	menu_add_prompt(P_PROMPT, yyvsp[-1].string, yyvsp[0].expr);
 ;}
     break;
 
@@ -1925,7 +1925,7 @@
 	sym_init();
 	menu_init();
 	modules_sym = sym_lookup("MODULES", 0);
-	rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
+	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
 	//zconfdebug = 1;
 	zconfparse();
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 54460f8..e1a0f45 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -342,7 +342,7 @@
 menu: T_MENU prompt T_EOL
 {
 	menu_add_entry(NULL);
-	menu_add_prop(P_MENU, $2, NULL, NULL);
+	menu_add_prompt(P_MENU, $2, NULL);
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 };
 
@@ -392,7 +392,7 @@
 comment: T_COMMENT prompt T_EOL
 {
 	menu_add_entry(NULL);
-	menu_add_prop(P_COMMENT, $2, NULL, NULL);
+	menu_add_prompt(P_COMMENT, $2, NULL);
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 };
 
@@ -443,7 +443,7 @@
 	  /* empty */
 	| prompt if_expr
 {
-	menu_add_prop(P_PROMPT, $1, NULL, $2);
+	menu_add_prompt(P_PROMPT, $1, $2);
 };
 
 prompt:	  T_WORD
@@ -487,7 +487,7 @@
 	sym_init();
 	menu_init();
 	modules_sym = sym_lookup("MODULES", 0);
-	rootmenu.prompt = menu_add_prop(P_MENU, "Linux Kernel Configuration", NULL, NULL);
+	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
 	//zconfdebug = 1;
 	zconfparse();
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 0835dc2..8aaf74e6 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1665,11 +1665,17 @@
 }
 
 sub process_file($) {
-    my ($file) = "$ENV{'SRCTREE'}@_";
+    my $file;
     my $identifier;
     my $func;
     my $initial_section_counter = $section_counter;
 
+    if (defined($ENV{'SRCTREE'})) {
+	$file = "$ENV{'SRCTREE'}" . "/" . "@_";
+    }
+    else {
+	$file = "@_";
+    }
     if (defined($source_map{$file})) {
 	$file = $source_map{$file};
     }
diff --git a/scripts/lxdialog/dialog.h b/scripts/lxdialog/dialog.h
index c571548..eb63e1b 100644
--- a/scripts/lxdialog/dialog.h
+++ b/scripts/lxdialog/dialog.h
@@ -163,7 +163,7 @@
 int dialog_checklist (const char *title, const char *prompt, int height,
 		int width, int list_height, int item_no,
 		const char * const * items, int flag);
-extern unsigned char dialog_input_result[];
+extern char dialog_input_result[];
 int dialog_inputbox (const char *title, const char *prompt, int height,
 		int width, const char *init);
 
diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c
index fa7bebc..074d2d6 100644
--- a/scripts/lxdialog/inputbox.c
+++ b/scripts/lxdialog/inputbox.c
@@ -21,7 +21,7 @@
 
 #include "dialog.h"
 
-unsigned char dialog_input_result[MAX_LEN + 1];
+char dialog_input_result[MAX_LEN + 1];
 
 /*
  *  Print the termination buttons
@@ -48,7 +48,7 @@
 {
     int i, x, y, box_y, box_x, box_width;
     int input_x = 0, scroll = 0, key = 0, button = -1;
-    unsigned char *instr = dialog_input_result;
+    char *instr = dialog_input_result;
     WINDOW *dialog;
 
     /* center dialog box on screen */
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index 8d118d1..d7b8a38 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -1,7 +1,8 @@
 TARGET=$1
 ARCH=$2
 SMP=$3
-CC=$4
+PREEMPT=$4
+CC=$5
 
 # If compile.h exists already and we don't own autoconf.h
 # (i.e. we're not the same user who did make *config), don't
@@ -26,8 +27,10 @@
 
 
 UTS_VERSION="#$VERSION"
-if [ -n "$SMP" ] ; then UTS_VERSION="$UTS_VERSION SMP"; fi
-UTS_VERSION="$UTS_VERSION `LC_ALL=C LANG=C date`"
+CONFIG_FLAGS=""
+if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
+if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
+UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS `LC_ALL=C LANG=C date`"
 
 # Truncate to maximum length
 
@@ -37,7 +40,8 @@
 # Generate a temporary compile.h
 
 ( echo /\* This file is auto generated, version $VERSION \*/
-
+  if [ -n "$CONFIG_FLAGS" ] ; then echo "/* $CONFIG_FLAGS */"; fi
+  
   echo \#define UTS_MACHINE \"$ARCH\"
 
   echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index 1112347..43271a1 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -252,9 +252,9 @@
 }
 
 /* FIXME: Handle .s files differently (eg. # starts comments) --RR */
-static int parse_file(const signed char *fname, struct md4_ctx *md)
+static int parse_file(const char *fname, struct md4_ctx *md)
 {
-	signed char *file;
+	char *file;
 	unsigned long i, len;
 
 	file = grab_file(fname, &len);
@@ -332,7 +332,7 @@
 	   Sum all files in the same dir or subdirs.
 	*/
 	while ((line = get_next_line(&pos, file, flen)) != NULL) {
-		signed char* p = line;
+		char* p = line;
 		if (strncmp(line, "deps_", sizeof("deps_")-1) == 0) {
 			check_files = 1;
 			continue;
@@ -458,7 +458,7 @@
 	close(fd);
 }
 
-static int strip_rcs_crap(signed char *version)
+static int strip_rcs_crap(char *version)
 {
 	unsigned int len, full_len;
 
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 3b1f2ef..f3e7e8e 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -59,7 +59,7 @@
 	$(CONFIG_SHELL) $(MKSPEC) prebuilt > $@
 	
 binrpm-pkg: $(objtree)/binkernel.spec
-	$(MAKE)
+	$(MAKE) KBUILD_SRC=
 	set -e; \
 	$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
 	set -e; \
@@ -74,16 +74,30 @@
 #
 .PHONY: deb-pkg
 deb-pkg:
-	$(MAKE)
+	$(MAKE) KBUILD_SRC=
 	$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
 
 clean-dirs += $(objtree)/debian/
 
 
+# tarball targets
+# ---------------------------------------------------------------------------
+.PHONY: tar%pkg
+tar%pkg:
+	$(MAKE)
+	$(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@
+
+clean-dirs += $(objtree)/tar-install/
+
+
 # Help text displayed when executing 'make help'
 # ---------------------------------------------------------------------------
 help:
-	@echo  '  rpm-pkg         - Build the kernel as an RPM package'
-	@echo  '  binrpm-pkg      - Build an rpm package containing the compiled kernel & modules'
-	@echo  '  deb-pkg         - Build the kernel as an deb package'
+	@echo '  rpm-pkg         - Build the kernel as an RPM package'
+	@echo '  binrpm-pkg      - Build an rpm package containing the compiled kernel'
+	@echo '                    and modules'
+	@echo '  deb-pkg         - Build the kernel as an deb package'
+	@echo '  tar-pkg         - Build the kernel as an uncompressed tarball'
+	@echo '  targz-pkg       - Build the kernel as a gzip compressed tarball'
+	@echo '  tarbz2-pkg      - Build the kernel as a bzip2 compressed tarball'
 
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index c279b63..6edb29f 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -14,18 +14,38 @@
 # Some variables and settings used throughout the script
 version=$KERNELRELEASE
 tmpdir="$objtree/debian/tmp"
+packagename=linux-$version
+
+if [ "$ARCH" == "um" ] ; then
+	packagename=user-mode-linux-$version
+fi
 
 # Setup the directory structure
 rm -rf "$tmpdir"
 mkdir -p "$tmpdir/DEBIAN" "$tmpdir/lib" "$tmpdir/boot"
+if [ "$ARCH" == "um" ] ; then
+	mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/share/doc/$packagename" "$tmpdir/usr/bin"
+fi
 
 # Build and install the kernel
-cp System.map "$tmpdir/boot/System.map-$version"
-cp .config "$tmpdir/boot/config-$version"
-cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+if [ "$ARCH" == "um" ] ; then
+	$MAKE linux
+	cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
+	cp .config "$tmpdir/usr/share/doc/$packagename/config"
+	gzip "$tmpdir/usr/share/doc/$packagename/config"
+	cp $KBUILD_IMAGE "$tmpdir/usr/bin/linux-$version"
+else 
+	cp System.map "$tmpdir/boot/System.map-$version"
+	cp .config "$tmpdir/boot/config-$version"
+	cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
+fi
 
 if grep -q '^CONFIG_MODULES=y' .config ; then
-	INSTALL_MOD_PATH="$tmpdir" make modules_install
+	INSTALL_MOD_PATH="$tmpdir" make KBUILD_SRC= modules_install
+	if [ "$ARCH" == "um" ] ; then
+		mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/"
+		rmdir "$tmpdir/lib/modules/$version"
+	fi
 fi
 
 # Install the maintainer scripts
@@ -53,6 +73,8 @@
 EOF
 
 # Generate a control file
+if [ "$ARCH" == "um" ]; then
+
 cat <<EOF > debian/control
 Source: linux
 Section: base
@@ -60,12 +82,34 @@
 Maintainer: $name
 Standards-Version: 3.6.1
 
-Package: linux-$version
+Package: $packagename
+Architecture: any
+Description: User Mode Linux kernel, version $version
+ User-mode Linux is a port of the Linux kernel to its own system call
+ interface.  It provides a kind of virtual machine, which runs Linux
+ as a user process under another Linux kernel.  This is useful for
+ kernel development, sandboxes, jails, experimentation, and
+ many other things.
+ .
+ This package contains the Linux kernel, modules and corresponding other
+ files version $version
+EOF
+
+else
+cat <<EOF > debian/control
+Source: linux
+Section: base
+Priority: optional
+Maintainer: $name
+Standards-Version: 3.6.1
+
+Package: $packagename
 Architecture: any
 Description: Linux kernel, version $version
  This package contains the Linux kernel, modules and corresponding other
- files version $version.
+ files version $version
 EOF
+fi
 
 # Fix some ownership and permissions
 chown -R root:root "$tmpdir"
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
new file mode 100644
index 0000000..d8fffe6
--- /dev/null
+++ b/scripts/package/buildtar
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+#
+# buildtar 0.0.3
+#
+# (C) 2004-2005 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
+#
+# This script is used to compile a tarball from the currently
+# prepared kernel. Based upon the builddeb script from
+# Wichert Akkerman <wichert@wiggy.net>.
+#
+
+set -e
+
+#
+# Some variables and settings used throughout the script
+#
+version="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}${EXTRANAME}"
+tmpdir="${objtree}/tar-install"
+tarball="${objtree}/linux-${version}.tar"
+
+
+#
+# Figure out how to compress, if requested at all
+#
+case "${1}" in
+	tar-pkg)
+		compress="cat"
+		file_ext=""
+		;;
+	targz-pkg)
+		compress="gzip -c9"
+		file_ext=".gz"
+		;;
+	tarbz2-pkg)
+		compress="bzip2 -c9"
+		file_ext=".bz2"
+		;;
+	*)
+		echo "Unknown tarball target \"${1}\" requested, please add it to ${0}." >&2
+		exit 1
+		;;
+esac
+
+
+#
+# Clean-up and re-create the temporary directory
+#
+rm -rf -- "${tmpdir}"
+mkdir -p -- "${tmpdir}/boot"
+
+
+#
+# Try to install modules
+#
+if ! make INSTALL_MOD_PATH="${tmpdir}" modules_install; then
+	echo "" >&2
+	echo "Ignoring error at module_install time, since that could be" >&2
+	echo "a result of missing local modutils/module-init-tools," >&2
+	echo "or you just didn't compile in module support at all..." >&2
+	echo "" >&2
+fi
+
+
+#
+# Install basic kernel files
+#
+cp -v -- System.map "${tmpdir}/boot/System.map-${version}"
+cp -v -- .config "${tmpdir}/boot/config-${version}"
+cp -v -- vmlinux "${tmpdir}/boot/vmlinux-${version}"
+
+
+#
+# Install arch-specific kernel image(s)
+#
+case "${ARCH}" in
+	i386)
+		[ -f arch/i386/boot/bzImage ] && cp -v -- arch/i386/boot/bzImage "${tmpdir}/boot/vmlinuz-${version}"
+		;;
+	alpha)
+		[ -f arch/alpha/boot/vmlinux.gz ] && cp -v -- arch/alpha/boot/vmlinux.gz "${tmpdir}/boot/vmlinuz-${version}"
+		;;
+	vax)
+		[ -f vmlinux.SYS ] && cp -v -- vmlinux.SYS "${tmpdir}/boot/vmlinux-${version}.SYS"
+		[ -f vmlinux.dsk ] && cp -v -- vmlinux.dsk "${tmpdir}/boot/vmlinux-${version}.dsk"
+		;;
+	*)
+		[ -f "${KBUILD_IMAGE}" ] && cp -v -- "${KBUILD_IMAGE}" "${tmpdir}/boot/vmlinux-kbuild-${version}"
+		echo "" >&2
+		echo '** ** **  WARNING  ** ** **' >&2
+		echo "" >&2
+		echo "Your architecture did not define any architecture-dependant files" >&2
+		echo "to be placed into the tarball. Please add those to ${0} ..." >&2
+		echo "" >&2
+		sleep 5
+		;;
+esac
+
+
+#
+# Create the tarball
+#
+(
+	cd "${tmpdir}"
+	tar cf - . | ${compress} > "${tarball}${file_ext}"
+)
+
+echo "Tarball successfully created in ${tarball}${file_ext}"
+
+exit 0
+
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index 6e7a58f..0b10387 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -62,10 +62,19 @@
 fi
 
 echo "%install"
+echo "%ifarch ia64"
+echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
+echo "%else"
 echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
+echo "%endif"
 
 echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install'
+echo "%ifarch ia64"
+echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
+echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
+echo "%else"
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
+echo "%endif"
 
 echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
 
diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl
index d5cabb8..f04f627 100644
--- a/scripts/reference_discarded.pl
+++ b/scripts/reference_discarded.pl
@@ -96,6 +96,7 @@
 		     $from !~ /\.debug_ranges$/ &&
 		     $from !~ /\.debug_line$/ &&
 		     $from !~ /\.debug_frame$/ &&
+		     $from !~ /\.debug_loc$/ &&
 		     $from !~ /\.exitcall\.exit$/ &&
 		     $from !~ /\.eh_frame$/ &&
 		     $from !~ /\.stab$/)) {
diff --git a/scripts/reference_init.pl b/scripts/reference_init.pl
index 9a24084..7f6960b 100644
--- a/scripts/reference_init.pl
+++ b/scripts/reference_init.pl
@@ -98,6 +98,7 @@
 		     $from !~ /\.pdr$/ &&
 		     $from !~ /\__param$/ &&
 		     $from !~ /\.altinstructions/ &&
+		     $from !~ /\.eh_frame/ &&
 		     $from !~ /\.debug_/)) {
 			printf("Error: %s %s refers to %s\n", $object, $from, $line);
 		}
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
new file mode 100644
index 0000000..7c805c8
--- /dev/null
+++ b/scripts/setlocalversion
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+# Copyright 2004 - Ryan Anderson <ryan@michonline.com>  GPL v2
+
+use strict;
+use warnings;
+use Digest::MD5;
+require 5.006;
+
+if (@ARGV != 1) {
+	print <<EOT;
+Usage: setlocalversion <srctree>
+EOT
+	exit(1);
+}
+
+my ($srctree) = @ARGV;
+chdir($srctree);
+
+my @LOCALVERSIONS = ();
+
+# We are going to use the following commands to try and determine if this
+# repository is at a Version boundary (i.e, 2.6.10 vs 2.6.10 + some patches) We
+# currently assume that all meaningful version boundaries are marked by a tag.
+# We don't care what the tag is, just that something exists.
+
+# Git/Cogito store the top-of-tree "commit" in .git/HEAD
+# A list of known tags sits in .git/refs/tags/
+#
+# The simple trick here is to just compare the two of these, and if we get a
+# match, return nothing, otherwise, return a subset of the SHA-1 hash in
+# .git/HEAD
+
+sub do_git_checks {
+	open(H,"<.git/HEAD") or return;
+	my $head = <H>;
+	chomp $head;
+	close(H);
+
+	opendir(D,".git/refs/tags") or return;
+	foreach my $tagfile (grep !/^\.{1,2}$/, readdir(D)) {
+		open(F,"<.git/refs/tags/" . $tagfile) or return;
+		my $tag = <F>;
+		chomp $tag;
+		close(F);
+		return if ($tag eq $head);
+	}
+	closedir(D);
+
+	push @LOCALVERSIONS, "g" . substr($head,0,8);
+}
+
+if ( -d ".git") {
+	do_git_checks();
+}
+
+printf "-%s\n", join("-",@LOCALVERSIONS) if (scalar @LOCALVERSIONS > 0);
diff --git a/usr/Kconfig b/usr/Kconfig
new file mode 100644
index 0000000..07727f3
--- /dev/null
+++ b/usr/Kconfig
@@ -0,0 +1,46 @@
+#
+# Configuration for initramfs
+#
+
+config INITRAMFS_SOURCE
+	string "Initramfs source file(s)"
+	default ""
+	help
+	  This can be either a single cpio archive with a .cpio suffix or a
+	  space-separated list of directories and files for building the
+	  initramfs image.  A cpio archive should contain a filesystem archive
+	  to be used as an initramfs image.  Directories should contain a
+	  filesystem layout to be included in the initramfs image.  Files
+	  should contain entries according to the format described by the
+	  "usr/gen_init_cpio" program in the kernel tree.
+
+	  When multiple directories and files are specified then the
+	  initramfs image will be the aggregate of all of them.
+
+	  See <file:Documentation/early-userspace/README for more details.
+
+	  If you are not sure, leave it blank.
+
+config INITRAMFS_ROOT_UID
+	int "User ID to map to 0 (user root)"
+	depends on INITRAMFS_SOURCE!=""
+	default "0"
+	help
+	  This setting is only meaningful if the INITRAMFS_SOURCE is
+	  contains a directory.  Setting this user ID (UID) to something
+	  other than "0" will cause all files owned by that UID to be
+	  owned by user root in the initial ramdisk image.
+
+	  If you are not sure, leave it set to "0".
+
+config INITRAMFS_ROOT_GID
+	int "Group ID to map to 0 (group root)"
+	depends on INITRAMFS_SOURCE!=""
+	default "0"
+	help
+	  This setting is only meaningful if the INITRAMFS_SOURCE is
+	  contains a directory.  Setting this group ID (GID) to something
+	  other than "0" will cause all files owned by that GID to be
+	  owned by group root in the initial ramdisk image.
+
+	  If you are not sure, leave it set to "0".
diff --git a/usr/Makefile b/usr/Makefile
index 248d555..e2129cb 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -27,7 +27,7 @@
 filechk_initramfs_list = $(CONFIG_SHELL) \
  $(srctree)/scripts/gen_initramfs_list.sh $(gen_initramfs_args) $(quotefixed_initramfs_source)
 
-$(obj)/initramfs_list: FORCE
+$(obj)/initramfs_list: $(obj)/Makefile FORCE
 	$(call filechk,initramfs_list)
 
 quiet_cmd_cpio = CPIO    $@