[PATCH 04/16] hwmon: Fix w83627ehf/hf vs PNPACPI conflict (bug #4014)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Petr Vandrovec <vandrove at vc.cvut.cz>

This patch changes w83627hf and w83627ehf drivers to reserve only ports
0x295-0x296, instead of full 0x290-0x297 range.  While some other sensors
chips respond to all addresses in 0x290-0x297 range, Winbond chips respond
to 0x295-0x296 only (this behavior is implied by documentation, and matches
behavior observed on real systems).  This is not problem alone, as no
BIOS was found to put something at these unused addresses, and sensors
chip itself provides nothing there as well.

But in addition to only respond to these two addresses, also BIOS vendors 
report in their ACPI-PnP structures that there is some resource at I/O 
address 0x295 of length 2.  And when later this hwmon driver attempts to
request region with base 0x290/length 8, it fails as one request_region
cannot span more than one device.

Due to this we have to ask only for region this hardware really occupies,
otherwise driver cannot be loaded on systems with ACPI-PnP enabled.

Signed-off-by: Petr Vandrovec <vandrove at vc.cvut.cz>
Signed-off-by: Jean Delvare <khali at linux-fr.org>

 drivers/hwmon/w83627ehf.c |   13 ++++++++-----
 drivers/hwmon/w83627hf.c  |   21 +++++++++++++--------
 2 files changed, 21 insertions(+), 13 deletions(-)

--- linux-2.6.14-rc3.orig/drivers/hwmon/w83627ehf.c	2005-10-07 20:08:16.000000000 +0200
+++ linux-2.6.14-rc3/drivers/hwmon/w83627ehf.c	2005-10-07 20:42:22.000000000 +0200
@@ -105,7 +105,9 @@
  * ISA constants
  */
 
-#define REGION_LENGTH		8
+#define REGION_ALIGNMENT	~7
+#define REGION_OFFSET		5
+#define REGION_LENGTH		2
 #define ADDR_REG_OFFSET		5
 #define DATA_REG_OFFSET		6
 
@@ -673,7 +675,8 @@
 	struct w83627ehf_data *data;
 	int i, err = 0;
 
-	if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
+	if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
+	                    w83627ehf_driver.name)) {
 		err = -EBUSY;
 		goto exit;
 	}
@@ -762,7 +765,7 @@
 exit_free:
 	kfree(data);
 exit_release:
-	release_region(address, REGION_LENGTH);
+	release_region(address + REGION_OFFSET, REGION_LENGTH);
 exit:
 	return err;
 }
@@ -776,7 +779,7 @@
 
 	if ((err = i2c_detach_client(client)))
 		return err;
-	release_region(client->addr, REGION_LENGTH);
+	release_region(client->addr + REGION_OFFSET, REGION_LENGTH);
 	kfree(data);
 
 	return 0;
@@ -807,7 +810,7 @@
 	superio_select(W83627EHF_LD_HWM);
 	val = (superio_inb(SIO_REG_ADDR) << 8)
 	    | superio_inb(SIO_REG_ADDR + 1);
-	*addr = val & ~(REGION_LENGTH - 1);
+	*addr = val & REGION_ALIGNMENT;
 	if (*addr == 0) {
 		superio_exit();
 		return -ENODEV;
--- linux-2.6.14-rc3.orig/drivers/hwmon/w83627hf.c	2005-10-07 20:08:16.000000000 +0200
+++ linux-2.6.14-rc3/drivers/hwmon/w83627hf.c	2005-10-07 20:42:22.000000000 +0200
@@ -142,10 +142,14 @@
 #define WINB_BASE_REG 0x60
 /* Constants specified below */
 
-/* Length of ISA address segment */
-#define WINB_EXTENT 8
+/* Alignment of the base address */
+#define WINB_ALIGNMENT		~7
 
-/* Where are the ISA address/data registers relative to the base address */
+/* Offset & size of I/O region we are interested in */
+#define WINB_REGION_OFFSET	5
+#define WINB_REGION_SIZE	2
+
+/* Where are the sensors address/data registers relative to the base address */
 #define W83781D_ADDR_REG_OFFSET 5
 #define W83781D_DATA_REG_OFFSET 6
 
@@ -981,7 +985,7 @@
 	superio_select(W83627HF_LD_HWM);
 	val = (superio_inb(WINB_BASE_REG) << 8) |
 	       superio_inb(WINB_BASE_REG + 1);
-	*addr = val & ~(WINB_EXTENT - 1);
+	*addr = val & WINB_ALIGNMENT;
 	if (*addr == 0 && force_addr == 0) {
 		superio_exit();
 		return -ENODEV;
@@ -1000,9 +1004,10 @@
 	const char *client_name = "";
 
 	if(force_addr)
-		address = force_addr & ~(WINB_EXTENT - 1);
+		address = force_addr & WINB_ALIGNMENT;
 
-	if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
+	if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
+	                    w83627hf_driver.name)) {
 		err = -EBUSY;
 		goto ERROR0;
 	}
@@ -1148,7 +1153,7 @@
       ERROR2:
 	kfree(data);
       ERROR1:
-	release_region(address, WINB_EXTENT);
+	release_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE);
       ERROR0:
 	return err;
 }
@@ -1163,7 +1168,7 @@
 	if ((err = i2c_detach_client(client)))
 		return err;
 
-	release_region(client->addr, WINB_EXTENT);
+	release_region(client->addr + WINB_REGION_OFFSET, WINB_REGION_SIZE);
 	kfree(data);
 
 	return 0;

-- 
Jean Delvare




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux