diff -uprN linux-2.6.18-rc2/drivers/hwmon/Kconfig linux-2.6.18-rc2-patched/drivers/hwmon/Kconfig
--- linux-2.6.18-rc2/drivers/hwmon/Kconfig	2006-08-24 17:45:20.593382000 +0200
+++ linux-2.6.18-rc2-patched/drivers/hwmon/Kconfig	2006-08-24 17:46:07.996344500 +0200
@@ -461,6 +461,15 @@ config SENSORS_W83792D
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83792d.
 
+config SENSORS_W83793
+	tristate "Winbond W83793"
+	depends on HWMON && I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Winbond W83793 chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called w83793.
+
 config SENSORS_W83L785TS
 	tristate "Winbond W83L785TS-S"
 	depends on HWMON && I2C && EXPERIMENTAL
diff -uprN linux-2.6.18-rc2/drivers/hwmon/Makefile linux-2.6.18-rc2-patched/drivers/hwmon/Makefile
--- linux-2.6.18-rc2/drivers/hwmon/Makefile	2006-08-24 17:45:20.601382500 +0200
+++ linux-2.6.18-rc2-patched/drivers/hwmon/Makefile	2006-08-24 17:46:55.527315000 +0200
@@ -9,6 +9,7 @@ obj-$(CONFIG_HWMON_VID)		+= hwmon-vid.o
 obj-$(CONFIG_SENSORS_ASB100)	+= asb100.o
 obj-$(CONFIG_SENSORS_W83627HF)	+= w83627hf.o
 obj-$(CONFIG_SENSORS_W83792D)	+= w83792d.o
+obj-$(CONFIG_SENSORS_W83793)	+= w83793.o
 obj-$(CONFIG_SENSORS_W83781D)	+= w83781d.o
 obj-$(CONFIG_SENSORS_W83791D)	+= w83791d.o
 
diff -uprN linux-2.6.18-rc2/drivers/hwmon/w83793.c linux-2.6.18-rc2-patched/drivers/hwmon/w83793.c
--- linux-2.6.18-rc2/drivers/hwmon/w83793.c	2006-08-23 18:49:30.000000000 +0200
+++ linux-2.6.18-rc2-patched/drivers/hwmon/w83793.c	2006-08-24 17:03:43.000000000 +0200
@@ -1,7 +1,6 @@
 /*
-    w83793.c - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
-    Copyright (c) 2006 Winbond Electronics Corp.
+    w83793.c - Linux kernel modules for hardware monitoring
+    Copyright (C) 2006 Winbond Electronics Corp.
                   Yuan Mu <ymu@winbond.com>
 
     This program is free software; you can redistribute it and/or modify
@@ -16,7 +15,8 @@
 
     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.
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301 USA.
 */
 
 /*
@@ -144,7 +144,7 @@ static u8 scale_in[] = { 2, 2, 2, 16, 16
 
 #define WRITE_TO_REG(REG, val, stored_val)				\
 	do {								\
-			if (0 != w83793_write_value(client, REG, val))	\
+			if (w83793_write_value(client, REG, val) >= 0)	\
 				stored_val = val;			\
 	} while(0)
 
@@ -171,7 +171,7 @@ struct w83793_data {
 	enum chips type;
 	struct mutex lock;
 	struct mutex update_lock;
-	char valid;		/* !=0 if following fields are valid */
+	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 	unsigned long last_nonvolatile;	/* In jiffies, last time we update the
 					   nonvolatile registers */
@@ -254,7 +254,7 @@ store_vrm(struct device *dev, struct dev
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
 
-	data->vrm = simple_strtol(buf, NULL, 10);
+	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
 
@@ -293,7 +293,7 @@ store_beep(struct device *dev, struct de
 	u8 beep_bit = 1 << shift;
 	u8 val;
 
-	val = simple_strtol(buf, NULL, 10);
+	val = simple_strtoul(buf, NULL, 10);
 	if (val != 0 && val != 1)
 		return -EINVAL;
 
@@ -320,7 +320,7 @@ store_beep_enable(struct device *dev, st
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
-	u8 val = simple_strtol(buf, NULL, 10);
+	u8 val = simple_strtoul(buf, NULL, 10);
 
 	if (val != 0 && val != 1)
 		return -EINVAL;
@@ -404,7 +404,7 @@ show_pwm(struct device *dev, struct devi
 	struct sensor_device_attribute_2 *sensor_attr =
 	    to_sensor_dev_attr_2(attr);
 	struct w83793_data *data = w83793_update_device(dev);
-	u8 val;
+	u16 val;
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
 
@@ -549,7 +549,7 @@ show_sf_setup(struct device *dev, struct
 	    to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	struct w83793_data *data = w83793_update_device(dev);
-	u8 val = 0;
+	u16 val = 0;
 
 	if (SETUP_PWM_DEFAULT == nr) {
 		val = (data->pwm_default & 0x3f) << 2;
@@ -1014,12 +1014,21 @@ static int w83793_attach_adapter(struct 
 static int w83793_detach_client(struct i2c_client *client)
 {
 	struct w83793_data *data = i2c_get_clientdata(client);
-	int err;
+	int err, i;
 
 	/* main client */
 	if (data)
 		hwmon_device_unregister(data->class_dev);
 
+	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+		device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+		device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+		device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
 	if ((err = i2c_detach_client(client)))
 		return err;
 
@@ -1113,12 +1122,12 @@ w83793_detect_subclients(struct i2c_adap
 
 	/* Undo inits in case of errors */
 
-      ERROR_SC_1:
+ERROR_SC_1:
 	if (data->lm75[0] != NULL) {
 		i2c_detach_client(data->lm75[0]);
 		kfree(data->lm75[0]);
 	}
-      ERROR_SC_0:
+ERROR_SC_0:
 	return err;
 }
 
@@ -1134,7 +1143,7 @@ static int w83793_detect(struct i2c_adap
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		err = -EINVAL;
-		goto ERROR0;
+		goto exit;
 	}
 
 	/* OK. For now, we presume we have a valid client. We now create the
@@ -1143,7 +1152,7 @@ static int w83793_detect(struct i2c_adap
 
 	if (!(data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL))) {
 		err = -ENOMEM;
-		goto ERROR0;
+		goto exit;
 	}
 
 	client = &data->client;
@@ -1162,7 +1171,7 @@ static int w83793_detect(struct i2c_adap
 		if (w83793_read_value(client, W83793_REG_CONFIG) & 0x80) {
 			dev_dbg(dev, "Detection failed at step 1\n");
 			err = -ENODEV;
-			goto ERROR1;
+			goto free_mem;
 		}
 
 		data->bank = w83793_read_value(client, W83793_REG_BANKSEL);
@@ -1171,7 +1180,7 @@ static int w83793_detect(struct i2c_adap
 		if (tmp != w83793_read_value(client, W83793_REG_VENDORID)) {
 			dev_dbg(dev, "Detection failed at check vendor id\n");
 			err = -ENODEV;
-			goto ERROR1;
+			goto free_mem;
 		}
 
 		/* If Winbond chip, address of chip and W83793_REG_I2C_ADDR
@@ -1180,7 +1189,7 @@ static int w83793_detect(struct i2c_adap
 		    (address << 1)) {
 			dev_dbg(dev, "Detection failed at check i2c addr\n");
 			err = -ENODEV;
-			goto ERROR1;
+			goto free_mem;
 		}
 
 	}
@@ -1201,14 +1210,14 @@ static int w83793_detect(struct i2c_adap
 					 " 0x%02x\n",
 					 i2c_adapter_id(adapter), address);
 			err = -ENODEV;
-			goto ERROR1;
+			goto free_mem;
 		}
 	}
 
 	if (kind != w83793) {
 		dev_err(dev, "w83793: Internal error: unknown kind %d\n", kind);
 		err = -ENODEV;
-		goto ERROR1;
+		goto free_mem;
 	}
 
 	/* Fill in the remaining client fields and put into the global list */
@@ -1220,10 +1229,10 @@ static int w83793_detect(struct i2c_adap
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(client)))
-		goto ERROR1;
+		goto free_mem;
 
 	if ((err = w83793_detect_subclients(adapter, address, kind, client)))
-		goto ERROR2;
+		goto detach_client;
 
 	/* Initialize the chip */
 	w83793_init_client(client);
@@ -1274,17 +1283,18 @@ static int w83793_detect(struct i2c_adap
 	}
 
 	/* Register sysfs hooks */
-	data->class_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->class_dev)) {
-		err = PTR_ERR(data->class_dev);
-		goto ERROR3;
+	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
+		err = device_create_file(dev, &w83793_sensor_attr_2[i].dev_attr);
+		if (err)
+			goto exit_remove;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
-		device_create_file(dev, &w83793_sensor_attr_2[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
+		err = device_create_file(dev, &sda_single_files[i].dev_attr);
+		if (err)
+			goto exit_remove;
 
-	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
-		device_create_file(dev, &sda_single_files[i].dev_attr);
+	}
 
 	for (i = 5; i < 12; i++) {
 		int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
@@ -1292,26 +1302,45 @@ static int w83793_detect(struct i2c_adap
 		int j;
 		if (!(data->has_fan & (1 << i)))
 			continue;
-		for (j = 0; j < files_fan; j++)
-			device_create_file(dev,
-					   &w83793_left_fan[(i -
-							     5) *
-							    files_fan +
-							    j].dev_attr);
+		for (j = 0; j < files_fan; j++) {
+			err = device_create_file(dev,
+					   &w83793_left_fan[(i - 5) * files_fan
+								+ j].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
 
 		if (i >= 8 || !(data->has_pwm & (1 << i)))
 			continue;
 
-		for (j = 0; j < files_pwm; j++)
-			device_create_file(dev,
-					   &w83793_left_fan[(i -
-							     3) *
-							    files_pwm +
-							    j].dev_attr);
+		for (j = 0; j < files_pwm; j++) {
+			err = device_create_file(dev,
+					   &w83793_left_fan[(i - 3) * files_pwm
+								+ j].dev_attr);
+			if (err)
+				goto exit_remove;
+	}
+
+	data->class_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove;
 	}
+
 	return 0;
 
-      ERROR3:
+	/* Unregister sysfs hooks */
+
+exit_remove:
+	for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
+		device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
+		device_remove_file(dev, &sda_single_files[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
+		device_remove_file(dev, &w83793_left_fan[i].dev_attr);
+
 	if (data->lm75[0] != NULL) {
 		i2c_detach_client(data->lm75[0]);
 		kfree(data->lm75[0]);
@@ -1320,11 +1349,11 @@ static int w83793_detect(struct i2c_adap
 		i2c_detach_client(data->lm75[1]);
 		kfree(data->lm75[1]);
 	}
-      ERROR2:
+detach_client:
 	i2c_detach_client(client);
-      ERROR1:
+free_mem:
 	kfree(data);
-      ERROR0:
+exit:
 	return err;
 }
 
@@ -1468,7 +1497,7 @@ static struct w83793_data *w83793_update
 	data->last_updated = jiffies;
 	data->valid = 1;
 
-      END:
+END:
 	mutex_unlock(&data->update_lock);
 	return data;
 }
@@ -1487,14 +1516,16 @@ static u8 w83793_read_value(struct i2c_c
 		    (client, W83793_REG_BANKSEL, new_bank) >= 0)
 			data->bank = new_bank;
 		else {
-			dev_err(&client->dev, "set bank to %d failed, fall back"
-				" to bank %d, read reg 0x%x error\n", new_bank,
-				data->bank, reg);
+			dev_err(&client->dev,
+				"set bank to %d failed, fall back"
+				" to bank %d, read reg 0x%x error\n",
+				new_bank, data->bank, reg);
 			goto END;
 		}
 	}
 	res = i2c_smbus_read_byte_data(client, reg & 0xff);
-      END:
+END:
+	res = 0x0;	/* read 0x0 from the chip */
 	mutex_unlock(&data->lock);
 	return res;
 }
@@ -1508,15 +1539,20 @@ static int w83793_write_value(struct i2c
 	mutex_lock(&data->lock);
 	new_bank |= data->bank & 0xfc;
 	if (data->bank != new_bank) {
-		res =
-		    i2c_smbus_write_byte_data(client, W83793_REG_BANKSEL,
-					      new_bank);
-		if (res < 0)
+		if ((res = i2c_smbus_write_byte_data
+		    (client, W83793_REG_BANKSEL, new_bank)) >= 0)
+			data->bank = new_bank;
+		else {
+			dev_err(&client->dev,
+				"set bank to %d failed, fall back"
+				" to bank %d, write reg 0x%x error\n",
+				new_bank, data->bank, reg);
 			goto END;
-		data->bank = new_bank;
+		}
 	}
+
 	res = i2c_smbus_write_byte_data(client, reg & 0xff, value);
-      END:
+END:
 	mutex_unlock(&data->lock);
 	return res;
 }

