瀏覽代碼

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/hwmon-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/hwmon-2.6:
  hwmon: Fix debug messages in w83781d
  hwmon: Let w83781d and lm78 load again
  w83627ehf: Fix the detection of fan5
  k8temp: Documentation update
  smsc47m1: List the SMSC LPC47M112 as supported
  hwmon: Fix documentation typos
  adm9240: Update Grant Coady's email address
  w83791d: Fix unchecked return status
Linus Torvalds 18 年之前
父節點
當前提交
64d9a39ec9

+ 1 - 1
Documentation/hwmon/adm9240

@@ -24,7 +24,7 @@ Authors:
     Frodo Looijaard <frodol@dds.nl>,
     Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>,
     Philip Edelbrock <phil@netroedge.com>,
     Michiel Rook <michiel@grendelproject.nl>,
     Michiel Rook <michiel@grendelproject.nl>,
-    Grant Coady <gcoady@gmail.com> with guidance
+    Grant Coady <gcoady.lk@gmail.com> with guidance
         from Jean Delvare <khali@linux-fr.org>
         from Jean Delvare <khali@linux-fr.org>
 
 
 Interface
 Interface

+ 1 - 1
Documentation/hwmon/f71805f

@@ -17,7 +17,7 @@ Thanks to Kris Chen from Fintek for answering technical questions and
 providing additional documentation.
 providing additional documentation.
 
 
 Thanks to Chris Lin from Jetway for providing wiring schematics and
 Thanks to Chris Lin from Jetway for providing wiring schematics and
-anwsering technical questions.
+answering technical questions.
 
 
 
 
 Description
 Description

+ 8 - 5
Documentation/hwmon/k8temp

@@ -2,7 +2,7 @@ Kernel driver k8temp
 ====================
 ====================
 
 
 Supported chips:
 Supported chips:
-  * AMD K8 CPU
+  * AMD Athlon64/FX or Opteron CPUs
     Prefix: 'k8temp'
     Prefix: 'k8temp'
     Addresses scanned: PCI space
     Addresses scanned: PCI space
     Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
     Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf
@@ -13,10 +13,13 @@ Contact: Rudolf Marek <r.marek@sh.cvut.cz>
 Description
 Description
 -----------
 -----------
 
 
-This driver permits reading temperature sensor(s) embedded inside AMD K8 CPUs.
-Official documentation says that it works from revision F of K8 core, but
-in fact it seems to be implemented for all revisions of K8 except the first
-two revisions (SH-B0 and SH-B3).
+This driver permits reading temperature sensor(s) embedded inside AMD K8
+family CPUs (Athlon64/FX, Opteron). Official documentation says that it works
+from revision F of K8 core, but in fact it seems to be implemented for all
+revisions of K8 except the first two revisions (SH-B0 and SH-B3).
+
+Please note that you will need at least lm-sensors 2.10.1 for proper userspace
+support.
 
 
 There can be up to four temperature sensors inside single CPU. The driver
 There can be up to four temperature sensors inside single CPU. The driver
 will auto-detect the sensors and will display only temperatures from
 will auto-detect the sensors and will display only temperatures from

+ 3 - 1
Documentation/hwmon/smsc47m1

@@ -2,12 +2,14 @@ Kernel driver smsc47m1
 ======================
 ======================
 
 
 Supported chips:
 Supported chips:
-  * SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192
+  * SMSC LPC47B27x, LPC47M112, LPC47M10x, LPC47M13x, LPC47M14x,
+    LPC47M15x and LPC47M192
     Addresses scanned: none, address read from Super I/O config space
     Addresses scanned: none, address read from Super I/O config space
     Prefix: 'smsc47m1'
     Prefix: 'smsc47m1'
     Datasheets:
     Datasheets:
         http://www.smsc.com/main/datasheets/47b27x.pdf
         http://www.smsc.com/main/datasheets/47b27x.pdf
         http://www.smsc.com/main/datasheets/47m10x.pdf
         http://www.smsc.com/main/datasheets/47m10x.pdf
+        http://www.smsc.com/main/datasheets/47m112.pdf
         http://www.smsc.com/main/tools/discontinued/47m13x.pdf
         http://www.smsc.com/main/tools/discontinued/47m13x.pdf
         http://www.smsc.com/main/datasheets/47m14x.pdf
         http://www.smsc.com/main/datasheets/47m14x.pdf
         http://www.smsc.com/main/tools/discontinued/47m15x.pdf
         http://www.smsc.com/main/tools/discontinued/47m15x.pdf

+ 3 - 3
Documentation/hwmon/w83627ehf

@@ -26,7 +26,7 @@ fan control mode).
 Temperatures are measured in degrees Celsius and measurement resolution is 1
 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
 degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
 the temperature gets higher than high limit; it stays on until the temperature
 the temperature gets higher than high limit; it stays on until the temperature
-falls below the Hysteresis value.
+falls below the hysteresis value.
 
 
 Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
 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
 triggered if the rotation speed has dropped below a programmable limit. Fan
@@ -67,9 +67,9 @@ Thermal Cruise mode
 
 
 If the temperature is in the range defined by:
 If the temperature is in the range defined by:
 
 
-pwm[1-4]_target    - set target temperature, unit millidegree Celcius
+pwm[1-4]_target    - set target temperature, unit millidegree Celsius
 		     (range 0 - 127000)
 		     (range 0 - 127000)
-pwm[1-4]_tolerance - tolerance, unit millidegree Celcius (range 0 - 15000)
+pwm[1-4]_tolerance - tolerance, unit millidegree Celsius (range 0 - 15000)
 
 
 there are no changes to fan speed. Once the temperature leaves the interval,
 there are no changes to fan speed. Once the temperature leaves the interval,
 fan speed increases (temp is higher) or decreases if lower than desired.
 fan speed increases (temp is higher) or decreases if lower than desired.

+ 6 - 0
MAINTAINERS

@@ -1668,6 +1668,12 @@ M:	sct@redhat.com, akpm@osdl.org
 L:	ext2-devel@lists.sourceforge.net
 L:	ext2-devel@lists.sourceforge.net
 S:	Maintained
 S:	Maintained
 
 
+K8TEMP HARDWARE MONITORING DRIVER
+P:	Rudolf Marek
+M:	r.marek@assembler.cz
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 KCONFIG
 KCONFIG
 P:	Roman Zippel
 P:	Roman Zippel
 M:	zippel@linux-m68k.org
 M:	zippel@linux-m68k.org

+ 6 - 4
drivers/hwmon/Kconfig

@@ -95,11 +95,13 @@ config SENSORS_ADM9240
 	  will be called adm9240.
 	  will be called adm9240.
 
 
 config SENSORS_K8TEMP
 config SENSORS_K8TEMP
-	tristate "AMD K8 processor sensor"
+	tristate "AMD Athlon64/FX or Opteron temperature sensor"
 	depends on HWMON && X86 && PCI && EXPERIMENTAL
 	depends on HWMON && X86 && PCI && EXPERIMENTAL
 	help
 	help
 	  If you say yes here you get support for the temperature
 	  If you say yes here you get support for the temperature
-	  sensor(s) inside your AMD K8 CPU.
+	  sensor(s) inside your CPU. Supported is whole AMD K8
+	  microarchitecture. Please note that you will need at least
+	  lm-sensors 2.10.1 for proper userspace support.
 
 
 	  This driver can also be built as a module.  If so, the module
 	  This driver can also be built as a module.  If so, the module
 	  will be called k8temp.
 	  will be called k8temp.
@@ -369,8 +371,8 @@ config SENSORS_SMSC47M1
 	help
 	help
 	  If you say yes here you get support for the integrated fan
 	  If you say yes here you get support for the integrated fan
 	  monitoring and control capabilities of the SMSC LPC47B27x,
 	  monitoring and control capabilities of the SMSC LPC47B27x,
-	  LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and
-	  LPC47M997 chips.
+	  LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x,
+	  LPC47M192 and LPC47M997 chips.
 
 
 	  The temperature and voltage sensor features of the LPC47M192
 	  The temperature and voltage sensor features of the LPC47M192
 	  and LPC47M997 are supported by another driver, select also
 	  and LPC47M997 are supported by another driver, select also

+ 2 - 2
drivers/hwmon/adm9240.c

@@ -5,7 +5,7 @@
  * Copyright (C) 1999	Frodo Looijaard <frodol@dds.nl>
  * Copyright (C) 1999	Frodo Looijaard <frodol@dds.nl>
  *			Philip Edelbrock <phil@netroedge.com>
  *			Philip Edelbrock <phil@netroedge.com>
  * Copyright (C) 2003	Michiel Rook <michiel@grendelproject.nl>
  * Copyright (C) 2003	Michiel Rook <michiel@grendelproject.nl>
- * Copyright (C) 2005	Grant Coady <gcoady@gmail.com> with valuable
+ * Copyright (C) 2005	Grant Coady <gcoady.lk@gmail.com> with valuable
  * 				guidance from Jean Delvare
  * 				guidance from Jean Delvare
  *
  *
  * Driver supports	Analog Devices		ADM9240
  * Driver supports	Analog Devices		ADM9240
@@ -774,7 +774,7 @@ static void __exit sensors_adm9240_exit(void)
 }
 }
 
 
 MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
 MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
-		"Grant Coady <gcoady@gmail.com> and others");
+		"Grant Coady <gcoady.lk@gmail.com> and others");
 MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
 MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 

+ 6 - 6
drivers/hwmon/lm78.c

@@ -815,18 +815,18 @@ static int __init sm_lm78_init(void)
 	if (res)
 	if (res)
 		return res;
 		return res;
 
 
-	res = i2c_isa_add_driver(&lm78_isa_driver);
-	if (res) {
-		i2c_del_driver(&lm78_driver);
-		return res;
-	}
+	/* Don't exit if this one fails, we still want the I2C variants
+	   to work! */
+	if (i2c_isa_add_driver(&lm78_isa_driver))
+		isa_address = 0;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
 static void __exit sm_lm78_exit(void)
 static void __exit sm_lm78_exit(void)
 {
 {
-	i2c_isa_del_driver(&lm78_isa_driver);
+	if (isa_address)
+		i2c_isa_del_driver(&lm78_isa_driver);
 	i2c_del_driver(&lm78_driver);
 	i2c_del_driver(&lm78_driver);
 }
 }
 
 

+ 6 - 5
drivers/hwmon/smsc47m1.c

@@ -2,8 +2,8 @@
     smsc47m1.c - Part of lm_sensors, Linux kernel modules
     smsc47m1.c - Part of lm_sensors, Linux kernel modules
                  for hardware monitoring
                  for hardware monitoring
 
 
-    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x,
-    LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
+    Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x,
+    LPC47M14x, LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips.
 
 
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
     Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
@@ -380,8 +380,8 @@ static int __init smsc47m1_find(unsigned short *addr)
 	val = superio_inb(SUPERIO_REG_DEVID);
 	val = superio_inb(SUPERIO_REG_DEVID);
 
 
 	/*
 	/*
-	 * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
-	 * 0x5F) and LPC47B27x (device id 0x51) have fan control.
+	 * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
+	 * (device id 0x5F) and LPC47B27x (device id 0x51) have fan control.
 	 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
 	 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
 	 * can do much more besides (device id 0x60).
 	 * can do much more besides (device id 0x60).
 	 * The LPC47M997 is undocumented, but seems to be compatible with
 	 * The LPC47M997 is undocumented, but seems to be compatible with
@@ -390,7 +390,8 @@ static int __init smsc47m1_find(unsigned short *addr)
 	if (val == 0x51)
 	if (val == 0x51)
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
 	else if (val == 0x59)
 	else if (val == 0x59)
-		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M10x/LPC47M13x\n");
+		printk(KERN_INFO "smsc47m1: Found SMSC "
+		       "LPC47M10x/LPC47M112/LPC47M13x\n");
 	else if (val == 0x5F)
 	else if (val == 0x5F)
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
 		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
 	else if (val == 0x60)
 	else if (val == 0x60)

+ 9 - 2
drivers/hwmon/w83627ehf.c

@@ -354,6 +354,8 @@ static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
 	case 0:
 	case 0:
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
 		    | ((data->fan_div[0] & 0x03) << 4);
 		    | ((data->fan_div[0] & 0x03) << 4);
+		/* fan5 input control bit is write only, compute the value */
+		reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
 		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
 		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
 		    | ((data->fan_div[0] & 0x04) << 3);
 		    | ((data->fan_div[0] & 0x04) << 3);
@@ -362,6 +364,8 @@ static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
 	case 1:
 	case 1:
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
 		    | ((data->fan_div[1] & 0x03) << 6);
 		    | ((data->fan_div[1] & 0x03) << 6);
+		/* fan5 input control bit is write only, compute the value */
+		reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
 		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
 		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
 		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
 		    | ((data->fan_div[1] & 0x04) << 4);
 		    | ((data->fan_div[1] & 0x04) << 4);
@@ -1216,13 +1220,16 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
 	superio_exit();
 	superio_exit();
 
 
 	/* It looks like fan4 and fan5 pins can be alternatively used
 	/* It looks like fan4 and fan5 pins can be alternatively used
-	   as fan on/off switches */
+	   as fan on/off switches, but fan5 control is write only :/
+	   We assume that if the serial interface is disabled, designers
+	   connected fan5 as input unless they are emitting log 1, which
+	   is not the default. */
 
 
 	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
 	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
 	i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
 	i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
 	if ((i & (1 << 2)) && (!fan4pin))
 	if ((i & (1 << 2)) && (!fan4pin))
 		data->has_fan |= (1 << 3);
 		data->has_fan |= (1 << 3);
-	if ((i & (1 << 0)) && (!fan5pin))
+	if (!(i & (1 << 1)) && (!fan5pin))
 		data->has_fan |= (1 << 4);
 		data->has_fan |= (1 << 4);
 
 
 	/* Register sysfs hooks */
 	/* Register sysfs hooks */

+ 16 - 14
drivers/hwmon/w83781d.c

@@ -1099,7 +1099,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 	   bank. */
 	   bank. */
 	if (kind < 0) {
 	if (kind < 0) {
 		if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) {
 		if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) {
-			dev_dbg(dev, "Detection failed at step 3\n");
+			dev_dbg(&adapter->dev, "Detection of w83781d chip "
+				"failed at step 3\n");
 			err = -ENODEV;
 			err = -ENODEV;
 			goto ERROR2;
 			goto ERROR2;
 		}
 		}
@@ -1109,7 +1110,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 		if ((!(val1 & 0x07)) &&
 		if ((!(val1 & 0x07)) &&
 		    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
 		    (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
 		     || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
 		     || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
-			dev_dbg(dev, "Detection failed at step 4\n");
+			dev_dbg(&adapter->dev, "Detection of w83781d chip "
+				"failed at step 4\n");
 			err = -ENODEV;
 			err = -ENODEV;
 			goto ERROR2;
 			goto ERROR2;
 		}
 		}
@@ -1119,7 +1121,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 				  ((val1 & 0x80) && (val2 == 0x5c)))) {
 				  ((val1 & 0x80) && (val2 == 0x5c)))) {
 			if (w83781d_read_value
 			if (w83781d_read_value
 			    (client, W83781D_REG_I2C_ADDR) != address) {
 			    (client, W83781D_REG_I2C_ADDR) != address) {
-				dev_dbg(dev, "Detection failed at step 5\n");
+				dev_dbg(&adapter->dev, "Detection of w83781d "
+					"chip failed at step 5\n");
 				err = -ENODEV;
 				err = -ENODEV;
 				goto ERROR2;
 				goto ERROR2;
 			}
 			}
@@ -1141,8 +1144,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 		else if (val2 == 0x12)
 		else if (val2 == 0x12)
 			vendid = asus;
 			vendid = asus;
 		else {
 		else {
-			dev_dbg(dev, "Chip was made by neither "
-				"Winbond nor Asus?\n");
+			dev_dbg(&adapter->dev, "w83781d chip vendor is "
+				"neither Winbond nor Asus\n");
 			err = -ENODEV;
 			err = -ENODEV;
 			goto ERROR2;
 			goto ERROR2;
 		}
 		}
@@ -1161,10 +1164,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 			kind = as99127f;
 			kind = as99127f;
 		else {
 		else {
 			if (kind == 0)
 			if (kind == 0)
-				dev_warn(dev, "Ignoring 'force' "
+				dev_warn(&adapter->dev, "Ignoring 'force' "
 					 "parameter for unknown chip at "
 					 "parameter for unknown chip at "
-					 "adapter %d, address 0x%02x\n",
-					 i2c_adapter_id(adapter), address);
+					 "address 0x%02x\n", address);
 			err = -EINVAL;
 			err = -EINVAL;
 			goto ERROR2;
 			goto ERROR2;
 		}
 		}
@@ -1685,11 +1687,10 @@ sensors_w83781d_init(void)
 	if (res)
 	if (res)
 		return res;
 		return res;
 
 
-	res = i2c_isa_add_driver(&w83781d_isa_driver);
-	if (res) {
-		i2c_del_driver(&w83781d_driver);
-		return res;
-	}
+	/* Don't exit if this one fails, we still want the I2C variants
+	   to work! */
+	if (i2c_isa_add_driver(&w83781d_isa_driver))
+		isa_address = 0;
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1697,7 +1698,8 @@ sensors_w83781d_init(void)
 static void __exit
 static void __exit
 sensors_w83781d_exit(void)
 sensors_w83781d_exit(void)
 {
 {
-	i2c_isa_del_driver(&w83781d_isa_driver);
+	if (isa_address)
+		i2c_isa_del_driver(&w83781d_isa_driver);
 	i2c_del_driver(&w83781d_driver);
 	i2c_del_driver(&w83781d_driver);
 }
 }
 
 

+ 56 - 29
drivers/hwmon/w83791d.c

@@ -746,6 +746,52 @@ static ssize_t store_vrm_reg(struct device *dev,
 
 
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
 
+#define IN_UNIT_ATTRS(X) \
+	&sda_in_input[X].dev_attr.attr, \
+	&sda_in_min[X].dev_attr.attr,   \
+	&sda_in_max[X].dev_attr.attr
+
+#define FAN_UNIT_ATTRS(X) \
+	&sda_fan_input[X].dev_attr.attr,        \
+	&sda_fan_min[X].dev_attr.attr,          \
+	&sda_fan_div[X].dev_attr.attr
+
+#define TEMP_UNIT_ATTRS(X) \
+	&sda_temp_input[X].dev_attr.attr,       \
+	&sda_temp_max[X].dev_attr.attr,         \
+	&sda_temp_max_hyst[X].dev_attr.attr
+
+static struct attribute *w83791d_attributes[] = {
+	IN_UNIT_ATTRS(0),
+	IN_UNIT_ATTRS(1),
+	IN_UNIT_ATTRS(2),
+	IN_UNIT_ATTRS(3),
+	IN_UNIT_ATTRS(4),
+	IN_UNIT_ATTRS(5),
+	IN_UNIT_ATTRS(6),
+	IN_UNIT_ATTRS(7),
+	IN_UNIT_ATTRS(8),
+	IN_UNIT_ATTRS(9),
+	FAN_UNIT_ATTRS(0),
+	FAN_UNIT_ATTRS(1),
+	FAN_UNIT_ATTRS(2),
+	FAN_UNIT_ATTRS(3),
+	FAN_UNIT_ATTRS(4),
+	TEMP_UNIT_ATTRS(0),
+	TEMP_UNIT_ATTRS(1),
+	TEMP_UNIT_ATTRS(2),
+	&dev_attr_alarms.attr,
+	&sda_beep_ctrl[0].dev_attr.attr,
+	&sda_beep_ctrl[1].dev_attr.attr,
+	&dev_attr_cpu0_vid.attr,
+	&dev_attr_vrm.attr,
+	NULL
+};
+
+static const struct attribute_group w83791d_group = {
+	.attrs = w83791d_attributes,
+};
+
 /* This function is called when:
 /* This function is called when:
      * w83791d_driver is inserted (when this module is loaded), for each
      * w83791d_driver is inserted (when this module is loaded), for each
        available adapter
        available adapter
@@ -967,41 +1013,20 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
 	}
 	}
 
 
 	/* Register sysfs hooks */
 	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&client->dev.kobj, &w83791d_group)))
+		goto error3;
+
+	/* Everything is ready, now register the working device */
 	data->class_dev = hwmon_device_register(dev);
 	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		err = PTR_ERR(data->class_dev);
-		goto error3;
+		goto error4;
 	}
 	}
 
 
-	for (i = 0; i < NUMBER_OF_VIN; i++) {
-		device_create_file(dev, &sda_in_input[i].dev_attr);
-		device_create_file(dev, &sda_in_min[i].dev_attr);
-		device_create_file(dev, &sda_in_max[i].dev_attr);
-	}
-
-	for (i = 0; i < NUMBER_OF_FANIN; i++) {
-		device_create_file(dev, &sda_fan_input[i].dev_attr);
-		device_create_file(dev, &sda_fan_div[i].dev_attr);
-		device_create_file(dev, &sda_fan_min[i].dev_attr);
-	}
-
-	for (i = 0; i < NUMBER_OF_TEMPIN; i++) {
-		device_create_file(dev, &sda_temp_input[i].dev_attr);
-		device_create_file(dev, &sda_temp_max[i].dev_attr);
-		device_create_file(dev, &sda_temp_max_hyst[i].dev_attr);
-	}
-
-	device_create_file(dev, &dev_attr_alarms);
-
-	for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) {
-		device_create_file(dev, &sda_beep_ctrl[i].dev_attr);
-	}
-
-	device_create_file(dev, &dev_attr_cpu0_vid);
-	device_create_file(dev, &dev_attr_vrm);
-
 	return 0;
 	return 0;
 
 
+error4:
+	sysfs_remove_group(&client->dev.kobj, &w83791d_group);
 error3:
 error3:
 	if (data->lm75[0] != NULL) {
 	if (data->lm75[0] != NULL) {
 		i2c_detach_client(data->lm75[0]);
 		i2c_detach_client(data->lm75[0]);
@@ -1025,8 +1050,10 @@ static int w83791d_detach_client(struct i2c_client *client)
 	int err;
 	int err;
 
 
 	/* main client */
 	/* main client */
-	if (data)
+	if (data) {
 		hwmon_device_unregister(data->class_dev);
 		hwmon_device_unregister(data->class_dev);
+		sysfs_remove_group(&client->dev.kobj, &w83791d_group);
+	}
 
 
 	if ((err = i2c_detach_client(client)))
 	if ((err = i2c_detach_client(client)))
 		return err;
 		return err;

+ 1 - 1
drivers/i2c/busses/i2c-isa.c

@@ -91,7 +91,7 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
 	/* Now look for clients */
 	/* Now look for clients */
 	res = driver->attach_adapter(&isa_adapter);
 	res = driver->attach_adapter(&isa_adapter);
 	if (res) {
 	if (res) {
-		dev_err(&isa_adapter.dev,
+		dev_dbg(&isa_adapter.dev,
 			"Driver %s failed to attach adapter, unregistering\n",
 			"Driver %s failed to attach adapter, unregistering\n",
 			driver->driver.name);
 			driver->driver.name);
 		driver_unregister(&driver->driver);
 		driver_unregister(&driver->driver);