* [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing @ 2010-03-23 14:12 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 14:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Acquire the I/O region for the Super I/O chip while we're working on it. Further alter the way multiple Super I/O addresses are probed for chips such that errors in the probing process are passed on from the module initialisation function. Some code cleanup: properly using, previously defined, functions rather than duplicating their code. --- drivers/hwmon/f71882fg.c | 38 +++++++++++++++++++++++--------------- 1 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 4230729..25e1cad 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) static int superio_inw(int base, int reg) { int val; - outb(reg++, base); - val = inb(base + 1) << 8; - outb(reg, base); - val |= inb(base + 1); + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); return val; } @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) { u16 val; - outb(reg++, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET) << 8; - outb(reg, data->addr + ADDR_REG_OFFSET); - val |= inb(data->addr + DATA_REG_OFFSET); + val = f71882fg_read8(data, reg) << 8; + val |= f71882fg_read8(data, reg + 1); return val; } @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) { - outb(reg++, data->addr + ADDR_REG_OFFSET); - outb(val >> 8, data->addr + DATA_REG_OFFSET); - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val & 255, data->addr + DATA_REG_OFFSET); + f71882fg_write8(data, reg, val >> 8); + f71882fg_write8(data, reg + 1, val & 0xff); } static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, int err = -ENODEV; u16 devid; + /* Don't step on other driver's I/O space by accident */ + if (!request_region(sioaddr, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)sioaddr); + return -EIO; + } + superio_enter(sioaddr); devid = superio_inw(sioaddr, SIO_REG_MANID); @@ -2238,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); + release_region(sioaddr, 2); return err; } @@ -2289,14 +2291,20 @@ exit_device_put: static int __init f71882fg_init(void) { + static const unsigned short addrs[] = { 0x2e, 0x4e }; int err = -ENODEV; - unsigned short address; + unsigned short address = /* shut up compiler */ 0; struct f71882fg_sio_data sio_data; + int i; memset(&sio_data, 0, sizeof(sio_data)); - if (f71882fg_find(0x2e, &address, &sio_data) && - f71882fg_find(0x4e, &address, &sio_data)) + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71882fg_find(addrs[i], &address, &sio_data); + if (err == 0) + break; + } + if (i == ARRAY_SIZE(addrs)) goto exit; err = platform_driver_register(&f71882fg_driver); -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O regions @ 2010-03-23 14:12 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 14:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Acquire the I/O region for the Super I/O chip while we're working on it. Further alter the way multiple Super I/O addresses are probed for chips such that errors in the probing process are passed on from the module initialisation function. Some code cleanup: properly using, previously defined, functions rather than duplicating their code. --- drivers/hwmon/f71882fg.c | 38 +++++++++++++++++++++++--------------- 1 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 4230729..25e1cad 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) static int superio_inw(int base, int reg) { int val; - outb(reg++, base); - val = inb(base + 1) << 8; - outb(reg, base); - val |= inb(base + 1); + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); return val; } @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) { u16 val; - outb(reg++, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET) << 8; - outb(reg, data->addr + ADDR_REG_OFFSET); - val |= inb(data->addr + DATA_REG_OFFSET); + val = f71882fg_read8(data, reg) << 8; + val |= f71882fg_read8(data, reg + 1); return val; } @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) { - outb(reg++, data->addr + ADDR_REG_OFFSET); - outb(val >> 8, data->addr + DATA_REG_OFFSET); - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val & 255, data->addr + DATA_REG_OFFSET); + f71882fg_write8(data, reg, val >> 8); + f71882fg_write8(data, reg + 1, val & 0xff); } static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, int err = -ENODEV; u16 devid; + /* Don't step on other driver's I/O space by accident */ + if (!request_region(sioaddr, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)sioaddr); + return -EIO; + } + superio_enter(sioaddr); devid = superio_inw(sioaddr, SIO_REG_MANID); @@ -2238,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); + release_region(sioaddr, 2); return err; } @@ -2289,14 +2291,20 @@ exit_device_put: static int __init f71882fg_init(void) { + static const unsigned short addrs[] = { 0x2e, 0x4e }; int err = -ENODEV; - unsigned short address; + unsigned short address = /* shut up compiler */ 0; struct f71882fg_sio_data sio_data; + int i; memset(&sio_data, 0, sizeof(sio_data)); - if (f71882fg_find(0x2e, &address, &sio_data) && - f71882fg_find(0x4e, &address, &sio_data)) + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71882fg_find(addrs[i], &address, &sio_data); + if (err = 0) + break; + } + if (i = ARRAY_SIZE(addrs)) goto exit; err = platform_driver_register(&f71882fg_driver); -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-23 14:12 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O regions Giel van Schijndel @ 2010-03-23 14:17 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 14:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 874 bytes --] On Tue, Mar 23, 2010 at 03:12:15PM +0100, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. Oh yes, this in preparation for adding watchdog support for the Fintek F71808E (very similar to the F71889) to this driver. I'll be sending in a patch for adding sensor hardware monitor support for the F71808E first (i.e. before the addition of watchdog support). PS I'm using the watchdog API as described in Documentation/watchdog/watchdog-api.txt. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-23 14:17 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 14:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 874 bytes --] On Tue, Mar 23, 2010 at 03:12:15PM +0100, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. Oh yes, this in preparation for adding watchdog support for the Fintek F71808E (very similar to the F71889) to this driver. I'll be sending in a patch for adding sensor hardware monitor support for the F71808E first (i.e. before the addition of watchdog support). PS I'm using the watchdog API as described in Documentation/watchdog/watchdog-api.txt. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the Fintek F71808E 2010-03-23 14:17 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel @ 2010-03-23 23:12 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Allow device probing to recognise the Fintek F71808E. Sysfs interface: * Fan/pwm control is the same as for F71889FG * Temperature and voltage sensor handling is largely the same as for the F71889FG - Has one temperature sensor less (doesn't have temp3) - Misses one voltage sensor (doesn't have V6, thus in6_input refers to what in7_input refers for F71889FG) For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up such that it can largely be reused. --- Documentation/hwmon/f71882fg | 4 ++ drivers/hwmon/Kconfig | 6 ++-- drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index a7952c2..1a07fd6 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -2,6 +2,10 @@ Kernel driver f71882fg ====================== Supported chips: + * Fintek F71808E + Prefix: 'f71808fg' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71858FG Prefix: 'f71858fg' Addresses scanned: none, address read from Super I/O config space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e4595e6..7053608 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -332,11 +332,11 @@ config SENSORS_F71805F will be called f71805f. config SENSORS_F71882FG - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" depends on EXPERIMENTAL help - If you say yes here you get support for hardware monitoring - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, + If you say yes here you get support for hardware monitoring features + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, F71889FG and F8000 Super-I/O chips. This driver can also be built as a module. If so, the module diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 25e1cad..b290b87 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -45,6 +45,7 @@ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ @@ -96,9 +97,10 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { + "f71808fg", "f71858fg", "f71862fg", "f71882fg", @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { +/* In attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* In attr for the f71808fg */ +static struct sensor_device_attribute_2 f71808_in_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 1), @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { store_temp_beep, 0, 6), SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), +}; + +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 f71862_temp_attr[] = { SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 3), @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->temp_type[1] = 6; break; } + } else if (data->type == f71808fg) { + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + data->temp_type[1] = (reg & 0x02) ? 2 : 4; + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + } else { reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) == 0x01) @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, val /= 1000; - if (data->type == f71889fg) + if (data->type == f71889fg + || data->type == f71808fg) val = SENSORS_LIMIT(val, -128, 127); else val = SENSORS_LIMIT(val, 0, 127); @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) /* fall through! */ case f71862fg: err = f71882fg_create_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + if (err) + goto exit_unregister_sysfs; + /* fall through! */ + case f71808fg: + if (data->type == f71808fg) { + err = f71882fg_create_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + if (err) + goto exit_unregister_sysfs; + } + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: err = f71882fg_create_sysfs_files(pdev, @@ -2002,6 +2049,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71862fg: err = (data->pwm_enable & 0x15) != 0x15; break; + case f71808fg: case f71882fg: case f71889fg: err = 0; @@ -2047,6 +2095,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) f8000_auto_pwm_attr, ARRAY_SIZE(f8000_auto_pwm_attr)); break; + case f71808fg: case f71889fg: for (i = 0; i < nr_fans; i++) { data->pwm_auto_point_mapping[i] = @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) /* fall through! */ case f71862fg: f71882fg_remove_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + /* fall through! */ + case f71808fg: + if (data->type == f71808fg) + f71882fg_remove_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: f71882fg_remove_sysfs_files(pdev, @@ -2195,6 +2256,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); switch (devid) { + case SIO_F71808_ID: + sio_data->type = f71808fg; + break; case SIO_F71858_ID: sio_data->type = f71858fg; break; -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the @ 2010-03-23 23:12 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Allow device probing to recognise the Fintek F71808E. Sysfs interface: * Fan/pwm control is the same as for F71889FG * Temperature and voltage sensor handling is largely the same as for the F71889FG - Has one temperature sensor less (doesn't have temp3) - Misses one voltage sensor (doesn't have V6, thus in6_input refers to what in7_input refers for F71889FG) For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up such that it can largely be reused. --- Documentation/hwmon/f71882fg | 4 ++ drivers/hwmon/Kconfig | 6 ++-- drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index a7952c2..1a07fd6 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -2,6 +2,10 @@ Kernel driver f71882fg =========== Supported chips: + * Fintek F71808E + Prefix: 'f71808fg' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71858FG Prefix: 'f71858fg' Addresses scanned: none, address read from Super I/O config space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e4595e6..7053608 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -332,11 +332,11 @@ config SENSORS_F71805F will be called f71805f. config SENSORS_F71882FG - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" depends on EXPERIMENTAL help - If you say yes here you get support for hardware monitoring - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, + If you say yes here you get support for hardware monitoring features + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, F71889FG and F8000 Super-I/O chips. This driver can also be built as a module. If so, the module diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 25e1cad..b290b87 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -45,6 +45,7 @@ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ @@ -96,9 +97,10 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { + "f71808fg", "f71858fg", "f71862fg", "f71882fg", @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { +/* In attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* In attr for the f71808fg */ +static struct sensor_device_attribute_2 f71808_in_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 1), @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { store_temp_beep, 0, 6), SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), +}; + +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 f71862_temp_attr[] = { SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 3), @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->temp_type[1] = 6; break; } + } else if (data->type = f71808fg) { + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + data->temp_type[1] = (reg & 0x02) ? 2 : 4; + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + } else { reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) = 0x01) @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, val /= 1000; - if (data->type = f71889fg) + if (data->type = f71889fg + || data->type = f71808fg) val = SENSORS_LIMIT(val, -128, 127); else val = SENSORS_LIMIT(val, 0, 127); @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) /* fall through! */ case f71862fg: err = f71882fg_create_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + if (err) + goto exit_unregister_sysfs; + /* fall through! */ + case f71808fg: + if (data->type = f71808fg) { + err = f71882fg_create_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + if (err) + goto exit_unregister_sysfs; + } + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: err = f71882fg_create_sysfs_files(pdev, @@ -2002,6 +2049,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71862fg: err = (data->pwm_enable & 0x15) != 0x15; break; + case f71808fg: case f71882fg: case f71889fg: err = 0; @@ -2047,6 +2095,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) f8000_auto_pwm_attr, ARRAY_SIZE(f8000_auto_pwm_attr)); break; + case f71808fg: case f71889fg: for (i = 0; i < nr_fans; i++) { data->pwm_auto_point_mapping[i] @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) /* fall through! */ case f71862fg: f71882fg_remove_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + /* fall through! */ + case f71808fg: + if (data->type = f71808fg) + f71882fg_remove_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: f71882fg_remove_sysfs_files(pdev, @@ -2195,6 +2256,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); switch (devid) { + case SIO_F71808_ID: + sio_data->type = f71808fg; + break; case SIO_F71858_ID: sio_data->type = f71858fg; break; -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH 2/4] hwmon: f71882fg: prepare for addition of watchdog support 2010-03-23 23:12 ` [lm-sensors] [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the Giel van Schijndel @ 2010-03-23 23:12 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Rename the `address' variable that's used in some places to hwmon_addr to indicate it refers to the hardware monitor (HWMON in datasheet) "logical device" of the chip. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index b290b87..7b31e14 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2233,7 +2233,7 @@ static int f71882fg_remove(struct platform_device *pdev) return 0; } -static int __init f71882fg_find(int sioaddr, unsigned short *address, +static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, struct f71882fg_sio_data *sio_data) { int err = -ENODEV; @@ -2290,16 +2290,16 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, goto exit; } - *address = superio_inw(sioaddr, SIO_REG_ADDR); - if (*address == 0) { + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); + if (*hwmon_addr == 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); goto exit; } - *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ + *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ err = 0; printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", - f71882fg_names[sio_data->type], (unsigned int)*address, + f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); @@ -2307,17 +2307,17 @@ exit: return err; } -static int __init f71882fg_device_add(unsigned short address, +static int __init f71882fg_device_add(unsigned short hwmon_addr, const struct f71882fg_sio_data *sio_data) { struct resource res = { - .start = address, - .end = address + REGION_LENGTH - 1, + .start = hwmon_addr, + .end = hwmon_addr + REGION_LENGTH - 1, .flags = IORESOURCE_IO, }; int err; - f71882fg_pdev = platform_device_alloc(DRVNAME, address); + f71882fg_pdev = platform_device_alloc(DRVNAME, hwmon_addr); if (!f71882fg_pdev) return -ENOMEM; @@ -2357,14 +2357,14 @@ static int __init f71882fg_init(void) { static const unsigned short addrs[] = { 0x2e, 0x4e }; int err = -ENODEV; - unsigned short address = /* shut up compiler */ 0; + unsigned short hwmon_addr = /* shut up compiler */ 0; struct f71882fg_sio_data sio_data; int i; memset(&sio_data, 0, sizeof(sio_data)); for (i = 0; i < ARRAY_SIZE(addrs); i++) { - err = f71882fg_find(addrs[i], &address, &sio_data); + err = f71882fg_find(addrs[i], &hwmon_addr, &sio_data); if (err == 0) break; } @@ -2375,7 +2375,7 @@ static int __init f71882fg_init(void) if (err) goto exit; - err = f71882fg_device_add(address, &sio_data); + err = f71882fg_device_add(hwmon_addr, &sio_data); if (err) goto exit_driver; -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition of @ 2010-03-23 23:12 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Rename the `address' variable that's used in some places to hwmon_addr to indicate it refers to the hardware monitor (HWMON in datasheet) "logical device" of the chip. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index b290b87..7b31e14 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2233,7 +2233,7 @@ static int f71882fg_remove(struct platform_device *pdev) return 0; } -static int __init f71882fg_find(int sioaddr, unsigned short *address, +static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, struct f71882fg_sio_data *sio_data) { int err = -ENODEV; @@ -2290,16 +2290,16 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, goto exit; } - *address = superio_inw(sioaddr, SIO_REG_ADDR); - if (*address = 0) { + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); + if (*hwmon_addr = 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); goto exit; } - *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ + *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ err = 0; printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", - f71882fg_names[sio_data->type], (unsigned int)*address, + f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); @@ -2307,17 +2307,17 @@ exit: return err; } -static int __init f71882fg_device_add(unsigned short address, +static int __init f71882fg_device_add(unsigned short hwmon_addr, const struct f71882fg_sio_data *sio_data) { struct resource res = { - .start = address, - .end = address + REGION_LENGTH - 1, + .start = hwmon_addr, + .end = hwmon_addr + REGION_LENGTH - 1, .flags = IORESOURCE_IO, }; int err; - f71882fg_pdev = platform_device_alloc(DRVNAME, address); + f71882fg_pdev = platform_device_alloc(DRVNAME, hwmon_addr); if (!f71882fg_pdev) return -ENOMEM; @@ -2357,14 +2357,14 @@ static int __init f71882fg_init(void) { static const unsigned short addrs[] = { 0x2e, 0x4e }; int err = -ENODEV; - unsigned short address = /* shut up compiler */ 0; + unsigned short hwmon_addr = /* shut up compiler */ 0; struct f71882fg_sio_data sio_data; int i; memset(&sio_data, 0, sizeof(sio_data)); for (i = 0; i < ARRAY_SIZE(addrs); i++) { - err = f71882fg_find(addrs[i], &address, &sio_data); + err = f71882fg_find(addrs[i], &hwmon_addr, &sio_data); if (err = 0) break; } @@ -2375,7 +2375,7 @@ static int __init f71882fg_init(void) if (err) goto exit; - err = f71882fg_device_add(address, &sio_data); + err = f71882fg_device_add(hwmon_addr, &sio_data); if (err) goto exit_driver; -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH 3/4] hwmon: f71882fg: add watchdog detection code 2010-03-23 23:12 ` [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition of Giel van Schijndel @ 2010-03-23 23:12 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Factor out code for detecting the hardware monitor into a separate function. Then add a function for detecting the watchdog. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 74 ++++++++++++++++++++++++++++++++++++---------- 1 files changed, 58 insertions(+), 16 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7b31e14..8006271 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2233,6 +2233,54 @@ static int f71882fg_remove(struct platform_device *pdev) return 0; } +static int __init f71882fg_find_watchdog(int sioaddr, + const struct f71882fg_sio_data *sio_data) +{ + switch (sio_data->type) { + case f71808fg: + break; + + case f71862fg: + case f71882fg: + case f71889fg: + /* These have a watchdog, though it isn't implemented (yet). */ + return -ENOSYS; + + case f71858fg: + default: + /* + * Confirmed (by datasheet) not to have a watchdog. That is, + * except for chips matched by the 'default' label of course. + */ + return -ENODEV; + } + + return 0; +} + +static int __init f71882fg_find_hwmon(int sioaddr, unsigned short *hwmon_addr, + struct f71882fg_sio_data *sio_data) +{ + if (sio_data->type == f71858fg) + superio_select(sioaddr, SIO_F71858FG_LD_HWM); + else + superio_select(sioaddr, SIO_F71882FG_LD_HWM); + + if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { + printk(KERN_WARNING DRVNAME ": Device not activated\n"); + return -ENODEV; + } + + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); + if (*hwmon_addr == 0) { + printk(KERN_WARNING DRVNAME ": Base address not set\n"); + return -ENODEV; + } + *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ + + return 0; +} + static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, struct f71882fg_sio_data *sio_data) { @@ -2280,27 +2328,21 @@ static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, goto exit; } - if (sio_data->type == f71858fg) - superio_select(sioaddr, SIO_F71858FG_LD_HWM); - else - superio_select(sioaddr, SIO_F71882FG_LD_HWM); - - if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { - printk(KERN_WARNING DRVNAME ": Device not activated\n"); - goto exit; - } - - *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); - if (*hwmon_addr == 0) { - printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = f71882fg_find_hwmon(sioaddr, hwmon_addr, sio_data); + if (err) goto exit; - } - *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ - err = 0; printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); + + err = f71882fg_find_watchdog(sioaddr, sio_data); + if (err == 0) + printk(KERN_INFO DRVNAME ": has supported watchdog\n"); + else if (err != -ENODEV && err != -ENOSYS) + goto exit; + + err = 0; exit: superio_exit(sioaddr); release_region(sioaddr, 2); -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 3/4] hwmon: f71882fg: add watchdog detection @ 2010-03-23 23:12 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Factor out code for detecting the hardware monitor into a separate function. Then add a function for detecting the watchdog. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 74 ++++++++++++++++++++++++++++++++++++---------- 1 files changed, 58 insertions(+), 16 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7b31e14..8006271 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2233,6 +2233,54 @@ static int f71882fg_remove(struct platform_device *pdev) return 0; } +static int __init f71882fg_find_watchdog(int sioaddr, + const struct f71882fg_sio_data *sio_data) +{ + switch (sio_data->type) { + case f71808fg: + break; + + case f71862fg: + case f71882fg: + case f71889fg: + /* These have a watchdog, though it isn't implemented (yet). */ + return -ENOSYS; + + case f71858fg: + default: + /* + * Confirmed (by datasheet) not to have a watchdog. That is, + * except for chips matched by the 'default' label of course. + */ + return -ENODEV; + } + + return 0; +} + +static int __init f71882fg_find_hwmon(int sioaddr, unsigned short *hwmon_addr, + struct f71882fg_sio_data *sio_data) +{ + if (sio_data->type = f71858fg) + superio_select(sioaddr, SIO_F71858FG_LD_HWM); + else + superio_select(sioaddr, SIO_F71882FG_LD_HWM); + + if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { + printk(KERN_WARNING DRVNAME ": Device not activated\n"); + return -ENODEV; + } + + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); + if (*hwmon_addr = 0) { + printk(KERN_WARNING DRVNAME ": Base address not set\n"); + return -ENODEV; + } + *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ + + return 0; +} + static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, struct f71882fg_sio_data *sio_data) { @@ -2280,27 +2328,21 @@ static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, goto exit; } - if (sio_data->type = f71858fg) - superio_select(sioaddr, SIO_F71858FG_LD_HWM); - else - superio_select(sioaddr, SIO_F71882FG_LD_HWM); - - if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { - printk(KERN_WARNING DRVNAME ": Device not activated\n"); - goto exit; - } - - *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); - if (*hwmon_addr = 0) { - printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = f71882fg_find_hwmon(sioaddr, hwmon_addr, sio_data); + if (err) goto exit; - } - *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ - err = 0; printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); + + err = f71882fg_find_watchdog(sioaddr, sio_data); + if (err = 0) + printk(KERN_INFO DRVNAME ": has supported watchdog\n"); + else if (err != -ENODEV && err != -ENOSYS) + goto exit; + + err = 0; exit: superio_exit(sioaddr); release_region(sioaddr, 2); -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-23 23:12 ` [lm-sensors] [PATCH 3/4] hwmon: f71882fg: add watchdog detection Giel van Schijndel @ 2010-03-23 23:12 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Implement the watchdog API for the Fintek F71808E. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 553 insertions(+), 0 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 8006271..3604613 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -26,14 +26,19 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> +#include <linux/miscdevice.h> #include <linux/mutex.h> +#include <linux/notifier.h> #include <linux/io.h> #include <linux/acpi.h> +#include <linux/reboot.h> +#include <linux/watchdog.h> #define DRVNAME "f71882fg" #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ @@ -91,12 +96,52 @@ #define F71882FG_REG_START 0x01 +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static int start_withtimeout = 0; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { @@ -113,6 +158,9 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); static inline void superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -162,6 +210,24 @@ struct f71882fg_data { s8 pwm_auto_point_temp[4][4]; }; +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data *watchdog; + /* Sysfs in */ static ssize_t show_in(struct device *dev, struct device_attribute *devattr, char *buf); @@ -883,6 +949,26 @@ static int superio_inw(int base, int reg) return val; } +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + static inline void superio_enter(int base) { /* according to the datasheet the key must be send twice! */ @@ -1941,6 +2027,430 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev, device_remove_file(&pdev->dev, &attr[i].dev_attr); } +static int watchdog_set_timeout(int timeout) +{ + if (!watchdog) + return -ENODEV; + + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog->lock); + + watchdog->timeout = timeout; + if (timeout > 0xff) { + watchdog->timer_val = DIV_ROUND_UP(timeout, 60); + watchdog->minutes_mode = true; + } else { + watchdog->timer_val = timeout; + watchdog->minutes_mode = false; + } + + mutex_unlock(&watchdog->lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + + if (pw <= 1) { + watchdog->pulse_val = 0; + } else if (pw <= 25) { + watchdog->pulse_val = 1; + } else if (pw <= 125) { + watchdog->pulse_val = 2; + } else if (pw <= 5000) { + watchdog->pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": watchdog pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog->pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog->lock); + return err; +} + +static int watchdog_keepalive(void) +{ + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + if (watchdog->minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, + watchdog->timeout); + + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + return 0; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + /* Watchdog pin configuration */ + switch (watchdog->type) { + case f71808fg: + /* Set ping 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog->sioaddr, 0x2a, 3); + superio_clear_bit(watchdog->sioaddr, 0x2b, 3); + break; + + default: + /* 'default' label to shut up the compiler and catch programmer errors */ + err = -ENODEV; + goto exit_unlock; + } + + superio_select(watchdog->sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog->sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog->pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog->sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog->pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_unlock: + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + + return err; +} + +static int watchdog_stop(void) +{ + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + + return 0; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + status = (watchdog->caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog->lock); + + return status; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog->opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog->opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog->expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog->opened); + + if (!watchdog->expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c == 'V'); + } + + /* Lock to properly order writes across fork()ed processes */ + mutex_lock(&watchdog->lock); + watchdog->expect_close = expect_close; + mutex_unlock(&watchdog->lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog->ident, + sizeof(watchdog->ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + watchdog_stop(); + } + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog->timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(void) +{ + int err = 0; + + if (!request_region(watchdog->sioaddr, 2, + watchdog->ident.identity)) { + printk(KERN_ERR DRVNAME + ": I/O address 0x%04x already in use\n", + (int)watchdog->sioaddr); + return -EIO; + } + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + goto exit_region; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog starting timeout out of range\n"); + err = -EINVAL; + goto exit_reboot; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_reboot; + } + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %d seconds!\n", + start_withtimeout); + } + + return 0; + +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); +exit_region: + release_region(watchdog->sioaddr, 2); + + return err; +} + static int __devinit f71882fg_probe(struct platform_device *pdev) { struct f71882fg_data *data; @@ -2236,8 +2746,32 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find_watchdog(int sioaddr, const struct f71882fg_sio_data *sio_data) { + int err = 0; + switch (sio_data->type) { case f71808fg: + watchdog = kzalloc(sizeof(*watchdog), GFP_KERNEL); + if (!watchdog) + return -ENOMEM; + + mutex_init(&watchdog->lock); + watchdog->sioaddr = sioaddr; + watchdog->type = sio_data->type; + + watchdog->ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + snprintf(watchdog->ident.identity, + sizeof(watchdog->ident.identity), "%s watchdog", + f71882fg_names[watchdog->type]); + + err = watchdog_set_timeout(timeout); + if (err) + goto exit_alloc; + err = watchdog_set_pulse_width(pulse_width); + if (err) + goto exit_alloc; + break; case f71862fg: @@ -2256,6 +2790,12 @@ static int __init f71882fg_find_watchdog(int sioaddr, } return 0; + +exit_alloc: + kfree(watchdog); + watchdog = NULL; + + return err; } static int __init f71882fg_find_hwmon(int sioaddr, unsigned short *hwmon_addr, @@ -2421,6 +2961,12 @@ static int __init f71882fg_init(void) if (err) goto exit_driver; + if (watchdog) { + err = watchdog_init(); + if (err) + goto exit_driver; + } + return 0; exit_driver: @@ -2433,6 +2979,13 @@ static void __exit f71882fg_exit(void) { platform_device_unregister(f71882fg_pdev); platform_driver_unregister(&f71882fg_driver); + + if (watchdog) { + watchdog_stop(); + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); + release_region(watchdog->sioaddr, 2); + } } MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API @ 2010-03-23 23:12 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:12 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Implement the watchdog API for the Fintek F71808E. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 553 insertions(+), 0 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 8006271..3604613 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -26,14 +26,19 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> +#include <linux/miscdevice.h> #include <linux/mutex.h> +#include <linux/notifier.h> #include <linux/io.h> #include <linux/acpi.h> +#include <linux/reboot.h> +#include <linux/watchdog.h> #define DRVNAME "f71882fg" #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ @@ -91,12 +96,52 @@ #define F71882FG_REG_START 0x01 +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static int start_withtimeout = 0; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { @@ -113,6 +158,9 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); static inline void superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -162,6 +210,24 @@ struct f71882fg_data { s8 pwm_auto_point_temp[4][4]; }; +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data *watchdog; + /* Sysfs in */ static ssize_t show_in(struct device *dev, struct device_attribute *devattr, char *buf); @@ -883,6 +949,26 @@ static int superio_inw(int base, int reg) return val; } +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + static inline void superio_enter(int base) { /* according to the datasheet the key must be send twice! */ @@ -1941,6 +2027,430 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev, device_remove_file(&pdev->dev, &attr[i].dev_attr); } +static int watchdog_set_timeout(int timeout) +{ + if (!watchdog) + return -ENODEV; + + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog->lock); + + watchdog->timeout = timeout; + if (timeout > 0xff) { + watchdog->timer_val = DIV_ROUND_UP(timeout, 60); + watchdog->minutes_mode = true; + } else { + watchdog->timer_val = timeout; + watchdog->minutes_mode = false; + } + + mutex_unlock(&watchdog->lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + + if (pw <= 1) { + watchdog->pulse_val = 0; + } else if (pw <= 25) { + watchdog->pulse_val = 1; + } else if (pw <= 125) { + watchdog->pulse_val = 2; + } else if (pw <= 5000) { + watchdog->pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": watchdog pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog->pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog->lock); + return err; +} + +static int watchdog_keepalive(void) +{ + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + if (watchdog->minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, + watchdog->timeout); + + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + return 0; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + /* Watchdog pin configuration */ + switch (watchdog->type) { + case f71808fg: + /* Set ping 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog->sioaddr, 0x2a, 3); + superio_clear_bit(watchdog->sioaddr, 0x2b, 3); + break; + + default: + /* 'default' label to shut up the compiler and catch programmer errors */ + err = -ENODEV; + goto exit_unlock; + } + + superio_select(watchdog->sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog->sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog->pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog->sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog->pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_unlock: + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + + return err; +} + +static int watchdog_stop(void) +{ + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + + return 0; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + if (!watchdog) + return -ENODEV; + + mutex_lock(&watchdog->lock); + status = (watchdog->caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog->lock); + + return status; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog->opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog->opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog->expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog->opened); + + if (!watchdog->expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c = 'V'); + } + + /* Lock to properly order writes across fork()ed processes */ + mutex_lock(&watchdog->lock); + watchdog->expect_close = expect_close; + mutex_unlock(&watchdog->lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog->ident, + sizeof(watchdog->ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + watchdog_stop(); + } + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog->timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code = SYS_DOWN || code = SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(void) +{ + int err = 0; + + if (!request_region(watchdog->sioaddr, 2, + watchdog->ident.identity)) { + printk(KERN_ERR DRVNAME + ": I/O address 0x%04x already in use\n", + (int)watchdog->sioaddr); + return -EIO; + } + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + goto exit_region; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog starting timeout out of range\n"); + err = -EINVAL; + goto exit_reboot; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_reboot; + } + + mutex_lock(&watchdog->lock); + superio_enter(watchdog->sioaddr); + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(watchdog->sioaddr); + mutex_unlock(&watchdog->lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %d seconds!\n", + start_withtimeout); + } + + return 0; + +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); +exit_region: + release_region(watchdog->sioaddr, 2); + + return err; +} + static int __devinit f71882fg_probe(struct platform_device *pdev) { struct f71882fg_data *data; @@ -2236,8 +2746,32 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find_watchdog(int sioaddr, const struct f71882fg_sio_data *sio_data) { + int err = 0; + switch (sio_data->type) { case f71808fg: + watchdog = kzalloc(sizeof(*watchdog), GFP_KERNEL); + if (!watchdog) + return -ENOMEM; + + mutex_init(&watchdog->lock); + watchdog->sioaddr = sioaddr; + watchdog->type = sio_data->type; + + watchdog->ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + snprintf(watchdog->ident.identity, + sizeof(watchdog->ident.identity), "%s watchdog", + f71882fg_names[watchdog->type]); + + err = watchdog_set_timeout(timeout); + if (err) + goto exit_alloc; + err = watchdog_set_pulse_width(pulse_width); + if (err) + goto exit_alloc; + break; case f71862fg: @@ -2256,6 +2790,12 @@ static int __init f71882fg_find_watchdog(int sioaddr, } return 0; + +exit_alloc: + kfree(watchdog); + watchdog = NULL; + + return err; } static int __init f71882fg_find_hwmon(int sioaddr, unsigned short *hwmon_addr, @@ -2421,6 +2961,12 @@ static int __init f71882fg_init(void) if (err) goto exit_driver; + if (watchdog) { + err = watchdog_init(); + if (err) + goto exit_driver; + } + return 0; exit_driver: @@ -2433,6 +2979,13 @@ static void __exit f71882fg_exit(void) { platform_device_unregister(f71882fg_pdev); platform_driver_unregister(&f71882fg_driver); + + if (watchdog) { + watchdog_stop(); + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); + release_region(watchdog->sioaddr, 2); + } } MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-23 23:12 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API Giel van Schijndel @ 2010-03-23 23:26 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:26 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 652 bytes --] On Wed, Mar 24, 2010 at 12:12:16AM +0100, Giel van Schijndel wrote: > Implement the watchdog API for the Fintek F71808E. Looking at the F71889FG datasheet I think implementing watchdog support for that chip can be accomplished rather easily. I think it's as simple as adding the pin initialisation (multi function select registers 0x2a and 0x2b) sequence to the switch statement in watchdog_start(). That being said; I don't have physical access to that chip myself, thus I couldn't actually test it (unlike the F71808E, for which I've already tested these patches). -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-23 23:26 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:26 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 652 bytes --] On Wed, Mar 24, 2010 at 12:12:16AM +0100, Giel van Schijndel wrote: > Implement the watchdog API for the Fintek F71808E. Looking at the F71889FG datasheet I think implementing watchdog support for that chip can be accomplished rather easily. I think it's as simple as adding the pin initialisation (multi function select registers 0x2a and 0x2b) sequence to the switch statement in watchdog_start(). That being said; I don't have physical access to that chip myself, thus I couldn't actually test it (unlike the F71808E, for which I've already tested these patches). -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-23 23:12 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API Giel van Schijndel @ 2010-03-24 8:37 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:37 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, Nack: As the watchdog has its own SIO logical device number, it should have a separate driver, not have support glued to the hwmon driver. Regards, Hans On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Implement the watchdog API for the Fintek F71808E. > > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 553 insertions(+), 0 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 8006271..3604613 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -26,14 +26,19 @@ > #include<linux/hwmon.h> > #include<linux/hwmon-sysfs.h> > #include<linux/err.h> > +#include<linux/miscdevice.h> > #include<linux/mutex.h> > +#include<linux/notifier.h> > #include<linux/io.h> > #include<linux/acpi.h> > +#include<linux/reboot.h> > +#include<linux/watchdog.h> > > #define DRVNAME "f71882fg" > > #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ > #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ > +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ > #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ > #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ > > @@ -91,12 +96,52 @@ > > #define F71882FG_REG_START 0x01 > > +#define F71808FG_REG_WDO_CONF 0xf0 > +#define F71808FG_REG_WDT_CONF 0xf5 > +#define F71808FG_REG_WD_TIME 0xf6 > + > +#define F71808FG_FLAG_WDOUT_EN 7 > + > +#define F71808FG_FLAG_WDTMOUT_STS 5 > +#define F71808FG_FLAG_WD_EN 5 > +#define F71808FG_FLAG_WD_PULSE 4 > +#define F71808FG_FLAG_WD_UNIT 3 > + > #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ > > +/* Default values */ > +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ > +#define WATCHDOG_MAX_TIMEOUT (60 * 255) > +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for > + watchdog signal */ > + > static unsigned short force_id; > module_param(force_id, ushort, 0); > MODULE_PARM_DESC(force_id, "Override the detected device ID"); > > +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; > +static int timeout = 60; /* default timeout in seconds */ > +module_param(timeout, int, 0); > +MODULE_PARM_DESC(timeout, > + "Watchdog timeout in seconds. 1<= timeout<=" > + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" > + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); > + > +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; > +module_param(pulse_width, uint, 0); > +MODULE_PARM_DESC(pulse_width, > + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" > + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); > + > +static int nowayout = WATCHDOG_NOWAYOUT; > +module_param(nowayout, bool, 0444); > +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); > + > +static int start_withtimeout = 0; > +module_param(start_withtimeout, uint, 0); > +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" > + " given initial timeout. Zero (default) disables this feature."); > + > enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; > > static const char *f71882fg_names[] = { > @@ -113,6 +158,9 @@ static struct platform_device *f71882fg_pdev; > /* Super-I/O Function prototypes */ > static inline int superio_inb(int base, int reg); > static inline int superio_inw(int base, int reg); > +static inline void superio_outb(int base, int reg, u8 val); > +static inline void superio_set_bit(int base, int reg, int bit); > +static inline void superio_clear_bit(int base, int reg, int bit); > static inline void superio_enter(int base); > static inline void superio_select(int base, int ld); > static inline void superio_exit(int base); > @@ -162,6 +210,24 @@ struct f71882fg_data { > s8 pwm_auto_point_temp[4][4]; > }; > > +struct watchdog_data { > + unsigned short sioaddr; > + enum chips type; > + unsigned long opened; > + struct mutex lock; > + char expect_close; > + struct watchdog_info ident; > + > + unsigned short timeout; > + u8 timer_val; /* content for the wd_time register */ > + char minutes_mode; > + u8 pulse_val; /* pulse width flag */ > + char pulse_mode; /* enable pulse output mode? */ > + char caused_reboot; /* last reboot was by the watchdog */ > +}; > + > +static struct watchdog_data *watchdog; > + > /* Sysfs in */ > static ssize_t show_in(struct device *dev, struct device_attribute *devattr, > char *buf); > @@ -883,6 +949,26 @@ static int superio_inw(int base, int reg) > return val; > } > > +static inline void superio_outb(int base, int reg, u8 val) > +{ > + outb(reg, base); > + outb(val, base + 1); > +} > + > +static inline void superio_set_bit(int base, int reg, int bit) > +{ > + unsigned long val = superio_inb(base, reg); > + __set_bit(bit,&val); > + superio_outb(base, reg, val); > +} > + > +static inline void superio_clear_bit(int base, int reg, int bit) > +{ > + unsigned long val = superio_inb(base, reg); > + __clear_bit(bit,&val); > + superio_outb(base, reg, val); > +} > + > static inline void superio_enter(int base) > { > /* according to the datasheet the key must be send twice! */ > @@ -1941,6 +2027,430 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev, > device_remove_file(&pdev->dev,&attr[i].dev_attr); > } > > +static int watchdog_set_timeout(int timeout) > +{ > + if (!watchdog) > + return -ENODEV; > + > + if (timeout<= 0 > + || timeout> max_timeout) { > + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); > + return -EINVAL; > + } > + > + mutex_lock(&watchdog->lock); > + > + watchdog->timeout = timeout; > + if (timeout> 0xff) { > + watchdog->timer_val = DIV_ROUND_UP(timeout, 60); > + watchdog->minutes_mode = true; > + } else { > + watchdog->timer_val = timeout; > + watchdog->minutes_mode = false; > + } > + > + mutex_unlock(&watchdog->lock); > + > + return 0; > +} > + > +static int watchdog_set_pulse_width(unsigned int pw) > +{ > + int err = 0; > + > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + > + if (pw<= 1) { > + watchdog->pulse_val = 0; > + } else if (pw<= 25) { > + watchdog->pulse_val = 1; > + } else if (pw<= 125) { > + watchdog->pulse_val = 2; > + } else if (pw<= 5000) { > + watchdog->pulse_val = 3; > + } else { > + printk(KERN_ERR DRVNAME ": watchdog pulse width out of range\n"); > + err = -EINVAL; > + goto exit_unlock; > + } > + > + watchdog->pulse_mode = pw; > + > +exit_unlock: > + mutex_unlock(&watchdog->lock); > + return err; > +} > + > +static int watchdog_keepalive(void) > +{ > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + if (watchdog->minutes_mode) > + /* select minutes for timer units */ > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + else > + /* select seconds for timer units */ > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + > + /* Set timer value */ > + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, > + watchdog->timeout); > + > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + return 0; > +} > + > +static int watchdog_start(void) > +{ > + /* Make sure we don't die as soon as the watchdog is enabled below */ > + int err = watchdog_keepalive(); > + if (err) > + return err; > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + /* Watchdog pin configuration */ > + switch (watchdog->type) { > + case f71808fg: > + /* Set ping 21 to GPIO23/WDTRST#, then to WDTRST# */ > + superio_clear_bit(watchdog->sioaddr, 0x2a, 3); > + superio_clear_bit(watchdog->sioaddr, 0x2b, 3); > + break; > + > + default: > + /* 'default' label to shut up the compiler and catch programmer errors */ > + err = -ENODEV; > + goto exit_unlock; > + } > + > + superio_select(watchdog->sioaddr, SIO_F71808FG_LD_WDT); > + superio_set_bit(watchdog->sioaddr, SIO_REG_ENABLE, 0); > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDO_CONF, > + F71808FG_FLAG_WDOUT_EN); > + > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_EN); > + > + if (watchdog->pulse_mode) { > + /* Select "pulse" output mode with given duration */ > + u8 wdt_conf = superio_inb(watchdog->sioaddr, > + F71808FG_REG_WDT_CONF); > + > + /* Set WD_PSWIDTH bits (1:0) */ > + wdt_conf = (wdt_conf& 0xfc) | (watchdog->pulse_val& 0x03); > + /* Set WD_PULSE to "pulse" mode */ > + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); > + > + superio_outb(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + wdt_conf); > + } else { > + /* Select "level" output mode */ > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_PULSE); > + } > + > +exit_unlock: > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + > + return err; > +} > + > +static int watchdog_stop(void) > +{ > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_EN); > + > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + > + return 0; > +} > + > +static int watchdog_get_status(void) > +{ > + int status = 0; > + > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + status = (watchdog->caused_reboot) ? WDIOF_CARDRESET : 0; > + mutex_unlock(&watchdog->lock); > + > + return status; > +} > + > +/* /dev/watchdog api */ > + > +static int watchdog_open(struct inode *inode, struct file *file) > +{ > + int err; > + > + /* If the watchdog is alive we don't need to start it again */ > + if (test_and_set_bit(0,&watchdog->opened)) > + return -EBUSY; > + > + err = watchdog_start(); > + if (err) { > + clear_bit(0,&watchdog->opened); > + return err; > + } > + > + if (nowayout) > + __module_get(THIS_MODULE); > + > + watchdog->expect_close = 0; > + return nonseekable_open(inode, file); > +} > + > +static int watchdog_release(struct inode *inode, struct file *file) > +{ > + clear_bit(0,&watchdog->opened); > + > + if (!watchdog->expect_close) { > + watchdog_keepalive(); > + printk(KERN_CRIT DRVNAME > + ": Unexpected close, not stopping watchdog!\n"); > + } else if (!nowayout) { > + watchdog_stop(); > + } > + return 0; > +} > + > +/* > + * watchdog_write: > + * @file: file handle to the watchdog > + * @buf: buffer to write > + * @count: count of bytes > + * @ppos: pointer to the position to write. No seeks allowed > + * > + * A write to a watchdog device is defined as a keepalive signal. Any > + * write of data will do, as we we don't define content meaning. > + */ > + > +static ssize_t watchdog_write(struct file *file, const char __user *buf, > + size_t count, loff_t *ppos) > +{ > + if (count) { > + if (!nowayout) { > + size_t i; > + > + /* In case it was set long ago */ > + bool expect_close = false; > + > + for (i = 0; i != count; i++) { > + char c; > + if (get_user(c, buf + i)) > + return -EFAULT; > + expect_close = (c == 'V'); > + } > + > + /* Lock to properly order writes across fork()ed processes */ > + mutex_lock(&watchdog->lock); > + watchdog->expect_close = expect_close; > + mutex_unlock(&watchdog->lock); > + } > + > + /* someone wrote to us, we should restart timer */ > + watchdog_keepalive(); > + } > + return count; > +} > + > +/* > + * watchdog_ioctl: > + * @inode: inode of the device > + * @file: file handle to the device > + * @cmd: watchdog command > + * @arg: argument pointer > + * > + * The watchdog API defines a common set of functions for all watchdogs > + * according to their available features. > + */ > +static long watchdog_ioctl(struct file *file, unsigned int cmd, > + unsigned long arg) > +{ > + int status; > + int new_options; > + int new_timeout; > + union { > + struct watchdog_info __user *ident; > + int __user *i; > + } uarg; > + > + uarg.i = (int __user *)arg; > + > + switch (cmd) { > + case WDIOC_GETSUPPORT: > + return copy_to_user(uarg.ident,&watchdog->ident, > + sizeof(watchdog->ident)) ? -EFAULT : 0; > + > + case WDIOC_GETSTATUS: > + status = watchdog_get_status(); > + if (status< 0) > + return status; > + return put_user(status, uarg.i); > + > + case WDIOC_GETBOOTSTATUS: > + return put_user(0, uarg.i); > + > + case WDIOC_SETOPTIONS: > + if (get_user(new_options, uarg.i)) > + return -EFAULT; > + > + if (new_options& WDIOS_DISABLECARD) { > + watchdog_stop(); > + } > + > + if (new_options& WDIOS_ENABLECARD) > + return watchdog_start(); > + > + > + case WDIOC_KEEPALIVE: > + watchdog_keepalive(); > + return 0; > + > + case WDIOC_SETTIMEOUT: > + if (get_user(new_timeout, uarg.i)) > + return -EFAULT; > + > + if (watchdog_set_timeout(new_timeout)) > + return -EINVAL; > + > + watchdog_keepalive(); > + /* Fall */ > + > + case WDIOC_GETTIMEOUT: > + return put_user(watchdog->timeout, uarg.i); > + > + default: > + return -ENOTTY; > + > + } > +} > + > +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, > + void *unused) > +{ > + if (code == SYS_DOWN || code == SYS_HALT) > + watchdog_stop(); > + return NOTIFY_DONE; > +} > + > +static const struct file_operations watchdog_fops = { > + .owner = THIS_MODULE, > + .llseek = no_llseek, > + .open = watchdog_open, > + .release = watchdog_release, > + .write = watchdog_write, > + .unlocked_ioctl = watchdog_ioctl, > +}; > + > +static struct miscdevice watchdog_miscdev = { > + .minor = WATCHDOG_MINOR, > + .name = "watchdog", > + .fops =&watchdog_fops, > +}; > + > +static struct notifier_block watchdog_notifier = { > + .notifier_call = watchdog_notify_sys, > +}; > + > +static int __init watchdog_init(void) > +{ > + int err = 0; > + > + if (!request_region(watchdog->sioaddr, 2, > + watchdog->ident.identity)) { > + printk(KERN_ERR DRVNAME > + ": I/O address 0x%04x already in use\n", > + (int)watchdog->sioaddr); > + return -EIO; > + } > + > + err = register_reboot_notifier(&watchdog_notifier); > + if (err) > + goto exit_region; > + > + err = misc_register(&watchdog_miscdev); > + if (err) { > + printk(KERN_ERR DRVNAME > + ": cannot register miscdev on minor=%d\n", > + watchdog_miscdev.minor); > + goto exit_reboot; > + } > + > + if (start_withtimeout) { > + if (start_withtimeout<= 0 > + || start_withtimeout> max_timeout) { > + printk(KERN_ERR DRVNAME ": watchdog starting timeout out of range\n"); > + err = -EINVAL; > + goto exit_reboot; > + } > + > + err = watchdog_start(); > + if (err) { > + printk(KERN_ERR DRVNAME > + ": cannot start watchdog timer\n"); > + goto exit_reboot; > + } > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + if (start_withtimeout> 0xff) { > + /* select minutes for timer units */ > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, > + DIV_ROUND_UP(start_withtimeout, 60)); > + } else { > + /* select seconds for timer units */ > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, > + start_withtimeout); > + } > + > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + > + if (nowayout) > + __module_get(THIS_MODULE); > + > + printk(KERN_INFO DRVNAME > + ": watchdog started with initial timeout of %d seconds!\n", > + start_withtimeout); > + } > + > + return 0; > + > +exit_reboot: > + unregister_reboot_notifier(&watchdog_notifier); > +exit_region: > + release_region(watchdog->sioaddr, 2); > + > + return err; > +} > + > static int __devinit f71882fg_probe(struct platform_device *pdev) > { > struct f71882fg_data *data; > @@ -2236,8 +2746,32 @@ static int f71882fg_remove(struct platform_device *pdev) > static int __init f71882fg_find_watchdog(int sioaddr, > const struct f71882fg_sio_data *sio_data) > { > + int err = 0; > + > switch (sio_data->type) { > case f71808fg: > + watchdog = kzalloc(sizeof(*watchdog), GFP_KERNEL); > + if (!watchdog) > + return -ENOMEM; > + > + mutex_init(&watchdog->lock); > + watchdog->sioaddr = sioaddr; > + watchdog->type = sio_data->type; > + > + watchdog->ident.options = WDIOC_SETTIMEOUT > + | WDIOF_MAGICCLOSE > + | WDIOF_KEEPALIVEPING; > + snprintf(watchdog->ident.identity, > + sizeof(watchdog->ident.identity), "%s watchdog", > + f71882fg_names[watchdog->type]); > + > + err = watchdog_set_timeout(timeout); > + if (err) > + goto exit_alloc; > + err = watchdog_set_pulse_width(pulse_width); > + if (err) > + goto exit_alloc; > + > break; > > case f71862fg: > @@ -2256,6 +2790,12 @@ static int __init f71882fg_find_watchdog(int sioaddr, > } > > return 0; > + > +exit_alloc: > + kfree(watchdog); > + watchdog = NULL; > + > + return err; > } > > static int __init f71882fg_find_hwmon(int sioaddr, unsigned short *hwmon_addr, > @@ -2421,6 +2961,12 @@ static int __init f71882fg_init(void) > if (err) > goto exit_driver; > > + if (watchdog) { > + err = watchdog_init(); > + if (err) > + goto exit_driver; > + } > + > return 0; > > exit_driver: > @@ -2433,6 +2979,13 @@ static void __exit f71882fg_exit(void) > { > platform_device_unregister(f71882fg_pdev); > platform_driver_unregister(&f71882fg_driver); > + > + if (watchdog) { > + watchdog_stop(); > + misc_deregister(&watchdog_miscdev); > + unregister_reboot_notifier(&watchdog_notifier); > + release_region(watchdog->sioaddr, 2); > + } > } > > MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-24 8:37 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:37 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, Nack: As the watchdog has its own SIO logical device number, it should have a separate driver, not have support glued to the hwmon driver. Regards, Hans On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Implement the watchdog API for the Fintek F71808E. > > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 553 insertions(+), 0 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 8006271..3604613 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -26,14 +26,19 @@ > #include<linux/hwmon.h> > #include<linux/hwmon-sysfs.h> > #include<linux/err.h> > +#include<linux/miscdevice.h> > #include<linux/mutex.h> > +#include<linux/notifier.h> > #include<linux/io.h> > #include<linux/acpi.h> > +#include<linux/reboot.h> > +#include<linux/watchdog.h> > > #define DRVNAME "f71882fg" > > #define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ > #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ > +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ > #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ > #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ > > @@ -91,12 +96,52 @@ > > #define F71882FG_REG_START 0x01 > > +#define F71808FG_REG_WDO_CONF 0xf0 > +#define F71808FG_REG_WDT_CONF 0xf5 > +#define F71808FG_REG_WD_TIME 0xf6 > + > +#define F71808FG_FLAG_WDOUT_EN 7 > + > +#define F71808FG_FLAG_WDTMOUT_STS 5 > +#define F71808FG_FLAG_WD_EN 5 > +#define F71808FG_FLAG_WD_PULSE 4 > +#define F71808FG_FLAG_WD_UNIT 3 > + > #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ > > +/* Default values */ > +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ > +#define WATCHDOG_MAX_TIMEOUT (60 * 255) > +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for > + watchdog signal */ > + > static unsigned short force_id; > module_param(force_id, ushort, 0); > MODULE_PARM_DESC(force_id, "Override the detected device ID"); > > +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; > +static int timeout = 60; /* default timeout in seconds */ > +module_param(timeout, int, 0); > +MODULE_PARM_DESC(timeout, > + "Watchdog timeout in seconds. 1<= timeout<=" > + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" > + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); > + > +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; > +module_param(pulse_width, uint, 0); > +MODULE_PARM_DESC(pulse_width, > + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" > + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); > + > +static int nowayout = WATCHDOG_NOWAYOUT; > +module_param(nowayout, bool, 0444); > +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); > + > +static int start_withtimeout = 0; > +module_param(start_withtimeout, uint, 0); > +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" > + " given initial timeout. Zero (default) disables this feature."); > + > enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; > > static const char *f71882fg_names[] = { > @@ -113,6 +158,9 @@ static struct platform_device *f71882fg_pdev; > /* Super-I/O Function prototypes */ > static inline int superio_inb(int base, int reg); > static inline int superio_inw(int base, int reg); > +static inline void superio_outb(int base, int reg, u8 val); > +static inline void superio_set_bit(int base, int reg, int bit); > +static inline void superio_clear_bit(int base, int reg, int bit); > static inline void superio_enter(int base); > static inline void superio_select(int base, int ld); > static inline void superio_exit(int base); > @@ -162,6 +210,24 @@ struct f71882fg_data { > s8 pwm_auto_point_temp[4][4]; > }; > > +struct watchdog_data { > + unsigned short sioaddr; > + enum chips type; > + unsigned long opened; > + struct mutex lock; > + char expect_close; > + struct watchdog_info ident; > + > + unsigned short timeout; > + u8 timer_val; /* content for the wd_time register */ > + char minutes_mode; > + u8 pulse_val; /* pulse width flag */ > + char pulse_mode; /* enable pulse output mode? */ > + char caused_reboot; /* last reboot was by the watchdog */ > +}; > + > +static struct watchdog_data *watchdog; > + > /* Sysfs in */ > static ssize_t show_in(struct device *dev, struct device_attribute *devattr, > char *buf); > @@ -883,6 +949,26 @@ static int superio_inw(int base, int reg) > return val; > } > > +static inline void superio_outb(int base, int reg, u8 val) > +{ > + outb(reg, base); > + outb(val, base + 1); > +} > + > +static inline void superio_set_bit(int base, int reg, int bit) > +{ > + unsigned long val = superio_inb(base, reg); > + __set_bit(bit,&val); > + superio_outb(base, reg, val); > +} > + > +static inline void superio_clear_bit(int base, int reg, int bit) > +{ > + unsigned long val = superio_inb(base, reg); > + __clear_bit(bit,&val); > + superio_outb(base, reg, val); > +} > + > static inline void superio_enter(int base) > { > /* according to the datasheet the key must be send twice! */ > @@ -1941,6 +2027,430 @@ static void f71882fg_remove_sysfs_files(struct platform_device *pdev, > device_remove_file(&pdev->dev,&attr[i].dev_attr); > } > > +static int watchdog_set_timeout(int timeout) > +{ > + if (!watchdog) > + return -ENODEV; > + > + if (timeout<= 0 > + || timeout> max_timeout) { > + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); > + return -EINVAL; > + } > + > + mutex_lock(&watchdog->lock); > + > + watchdog->timeout = timeout; > + if (timeout> 0xff) { > + watchdog->timer_val = DIV_ROUND_UP(timeout, 60); > + watchdog->minutes_mode = true; > + } else { > + watchdog->timer_val = timeout; > + watchdog->minutes_mode = false; > + } > + > + mutex_unlock(&watchdog->lock); > + > + return 0; > +} > + > +static int watchdog_set_pulse_width(unsigned int pw) > +{ > + int err = 0; > + > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + > + if (pw<= 1) { > + watchdog->pulse_val = 0; > + } else if (pw<= 25) { > + watchdog->pulse_val = 1; > + } else if (pw<= 125) { > + watchdog->pulse_val = 2; > + } else if (pw<= 5000) { > + watchdog->pulse_val = 3; > + } else { > + printk(KERN_ERR DRVNAME ": watchdog pulse width out of range\n"); > + err = -EINVAL; > + goto exit_unlock; > + } > + > + watchdog->pulse_mode = pw; > + > +exit_unlock: > + mutex_unlock(&watchdog->lock); > + return err; > +} > + > +static int watchdog_keepalive(void) > +{ > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + if (watchdog->minutes_mode) > + /* select minutes for timer units */ > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + else > + /* select seconds for timer units */ > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + > + /* Set timer value */ > + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, > + watchdog->timeout); > + > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + return 0; > +} > + > +static int watchdog_start(void) > +{ > + /* Make sure we don't die as soon as the watchdog is enabled below */ > + int err = watchdog_keepalive(); > + if (err) > + return err; > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + /* Watchdog pin configuration */ > + switch (watchdog->type) { > + case f71808fg: > + /* Set ping 21 to GPIO23/WDTRST#, then to WDTRST# */ > + superio_clear_bit(watchdog->sioaddr, 0x2a, 3); > + superio_clear_bit(watchdog->sioaddr, 0x2b, 3); > + break; > + > + default: > + /* 'default' label to shut up the compiler and catch programmer errors */ > + err = -ENODEV; > + goto exit_unlock; > + } > + > + superio_select(watchdog->sioaddr, SIO_F71808FG_LD_WDT); > + superio_set_bit(watchdog->sioaddr, SIO_REG_ENABLE, 0); > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDO_CONF, > + F71808FG_FLAG_WDOUT_EN); > + > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_EN); > + > + if (watchdog->pulse_mode) { > + /* Select "pulse" output mode with given duration */ > + u8 wdt_conf = superio_inb(watchdog->sioaddr, > + F71808FG_REG_WDT_CONF); > + > + /* Set WD_PSWIDTH bits (1:0) */ > + wdt_conf = (wdt_conf& 0xfc) | (watchdog->pulse_val& 0x03); > + /* Set WD_PULSE to "pulse" mode */ > + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); > + > + superio_outb(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + wdt_conf); > + } else { > + /* Select "level" output mode */ > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_PULSE); > + } > + > +exit_unlock: > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + > + return err; > +} > + > +static int watchdog_stop(void) > +{ > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_EN); > + > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + > + return 0; > +} > + > +static int watchdog_get_status(void) > +{ > + int status = 0; > + > + if (!watchdog) > + return -ENODEV; > + > + mutex_lock(&watchdog->lock); > + status = (watchdog->caused_reboot) ? WDIOF_CARDRESET : 0; > + mutex_unlock(&watchdog->lock); > + > + return status; > +} > + > +/* /dev/watchdog api */ > + > +static int watchdog_open(struct inode *inode, struct file *file) > +{ > + int err; > + > + /* If the watchdog is alive we don't need to start it again */ > + if (test_and_set_bit(0,&watchdog->opened)) > + return -EBUSY; > + > + err = watchdog_start(); > + if (err) { > + clear_bit(0,&watchdog->opened); > + return err; > + } > + > + if (nowayout) > + __module_get(THIS_MODULE); > + > + watchdog->expect_close = 0; > + return nonseekable_open(inode, file); > +} > + > +static int watchdog_release(struct inode *inode, struct file *file) > +{ > + clear_bit(0,&watchdog->opened); > + > + if (!watchdog->expect_close) { > + watchdog_keepalive(); > + printk(KERN_CRIT DRVNAME > + ": Unexpected close, not stopping watchdog!\n"); > + } else if (!nowayout) { > + watchdog_stop(); > + } > + return 0; > +} > + > +/* > + * watchdog_write: > + * @file: file handle to the watchdog > + * @buf: buffer to write > + * @count: count of bytes > + * @ppos: pointer to the position to write. No seeks allowed > + * > + * A write to a watchdog device is defined as a keepalive signal. Any > + * write of data will do, as we we don't define content meaning. > + */ > + > +static ssize_t watchdog_write(struct file *file, const char __user *buf, > + size_t count, loff_t *ppos) > +{ > + if (count) { > + if (!nowayout) { > + size_t i; > + > + /* In case it was set long ago */ > + bool expect_close = false; > + > + for (i = 0; i != count; i++) { > + char c; > + if (get_user(c, buf + i)) > + return -EFAULT; > + expect_close = (c = 'V'); > + } > + > + /* Lock to properly order writes across fork()ed processes */ > + mutex_lock(&watchdog->lock); > + watchdog->expect_close = expect_close; > + mutex_unlock(&watchdog->lock); > + } > + > + /* someone wrote to us, we should restart timer */ > + watchdog_keepalive(); > + } > + return count; > +} > + > +/* > + * watchdog_ioctl: > + * @inode: inode of the device > + * @file: file handle to the device > + * @cmd: watchdog command > + * @arg: argument pointer > + * > + * The watchdog API defines a common set of functions for all watchdogs > + * according to their available features. > + */ > +static long watchdog_ioctl(struct file *file, unsigned int cmd, > + unsigned long arg) > +{ > + int status; > + int new_options; > + int new_timeout; > + union { > + struct watchdog_info __user *ident; > + int __user *i; > + } uarg; > + > + uarg.i = (int __user *)arg; > + > + switch (cmd) { > + case WDIOC_GETSUPPORT: > + return copy_to_user(uarg.ident,&watchdog->ident, > + sizeof(watchdog->ident)) ? -EFAULT : 0; > + > + case WDIOC_GETSTATUS: > + status = watchdog_get_status(); > + if (status< 0) > + return status; > + return put_user(status, uarg.i); > + > + case WDIOC_GETBOOTSTATUS: > + return put_user(0, uarg.i); > + > + case WDIOC_SETOPTIONS: > + if (get_user(new_options, uarg.i)) > + return -EFAULT; > + > + if (new_options& WDIOS_DISABLECARD) { > + watchdog_stop(); > + } > + > + if (new_options& WDIOS_ENABLECARD) > + return watchdog_start(); > + > + > + case WDIOC_KEEPALIVE: > + watchdog_keepalive(); > + return 0; > + > + case WDIOC_SETTIMEOUT: > + if (get_user(new_timeout, uarg.i)) > + return -EFAULT; > + > + if (watchdog_set_timeout(new_timeout)) > + return -EINVAL; > + > + watchdog_keepalive(); > + /* Fall */ > + > + case WDIOC_GETTIMEOUT: > + return put_user(watchdog->timeout, uarg.i); > + > + default: > + return -ENOTTY; > + > + } > +} > + > +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, > + void *unused) > +{ > + if (code = SYS_DOWN || code = SYS_HALT) > + watchdog_stop(); > + return NOTIFY_DONE; > +} > + > +static const struct file_operations watchdog_fops = { > + .owner = THIS_MODULE, > + .llseek = no_llseek, > + .open = watchdog_open, > + .release = watchdog_release, > + .write = watchdog_write, > + .unlocked_ioctl = watchdog_ioctl, > +}; > + > +static struct miscdevice watchdog_miscdev = { > + .minor = WATCHDOG_MINOR, > + .name = "watchdog", > + .fops =&watchdog_fops, > +}; > + > +static struct notifier_block watchdog_notifier = { > + .notifier_call = watchdog_notify_sys, > +}; > + > +static int __init watchdog_init(void) > +{ > + int err = 0; > + > + if (!request_region(watchdog->sioaddr, 2, > + watchdog->ident.identity)) { > + printk(KERN_ERR DRVNAME > + ": I/O address 0x%04x already in use\n", > + (int)watchdog->sioaddr); > + return -EIO; > + } > + > + err = register_reboot_notifier(&watchdog_notifier); > + if (err) > + goto exit_region; > + > + err = misc_register(&watchdog_miscdev); > + if (err) { > + printk(KERN_ERR DRVNAME > + ": cannot register miscdev on minor=%d\n", > + watchdog_miscdev.minor); > + goto exit_reboot; > + } > + > + if (start_withtimeout) { > + if (start_withtimeout<= 0 > + || start_withtimeout> max_timeout) { > + printk(KERN_ERR DRVNAME ": watchdog starting timeout out of range\n"); > + err = -EINVAL; > + goto exit_reboot; > + } > + > + err = watchdog_start(); > + if (err) { > + printk(KERN_ERR DRVNAME > + ": cannot start watchdog timer\n"); > + goto exit_reboot; > + } > + > + mutex_lock(&watchdog->lock); > + superio_enter(watchdog->sioaddr); > + > + if (start_withtimeout> 0xff) { > + /* select minutes for timer units */ > + superio_set_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, > + DIV_ROUND_UP(start_withtimeout, 60)); > + } else { > + /* select seconds for timer units */ > + superio_clear_bit(watchdog->sioaddr, F71808FG_REG_WDT_CONF, > + F71808FG_FLAG_WD_UNIT); > + superio_outb(watchdog->sioaddr, F71808FG_REG_WD_TIME, > + start_withtimeout); > + } > + > + superio_exit(watchdog->sioaddr); > + mutex_unlock(&watchdog->lock); > + > + if (nowayout) > + __module_get(THIS_MODULE); > + > + printk(KERN_INFO DRVNAME > + ": watchdog started with initial timeout of %d seconds!\n", > + start_withtimeout); > + } > + > + return 0; > + > +exit_reboot: > + unregister_reboot_notifier(&watchdog_notifier); > +exit_region: > + release_region(watchdog->sioaddr, 2); > + > + return err; > +} > + > static int __devinit f71882fg_probe(struct platform_device *pdev) > { > struct f71882fg_data *data; > @@ -2236,8 +2746,32 @@ static int f71882fg_remove(struct platform_device *pdev) > static int __init f71882fg_find_watchdog(int sioaddr, > const struct f71882fg_sio_data *sio_data) > { > + int err = 0; > + > switch (sio_data->type) { > case f71808fg: > + watchdog = kzalloc(sizeof(*watchdog), GFP_KERNEL); > + if (!watchdog) > + return -ENOMEM; > + > + mutex_init(&watchdog->lock); > + watchdog->sioaddr = sioaddr; > + watchdog->type = sio_data->type; > + > + watchdog->ident.options = WDIOC_SETTIMEOUT > + | WDIOF_MAGICCLOSE > + | WDIOF_KEEPALIVEPING; > + snprintf(watchdog->ident.identity, > + sizeof(watchdog->ident.identity), "%s watchdog", > + f71882fg_names[watchdog->type]); > + > + err = watchdog_set_timeout(timeout); > + if (err) > + goto exit_alloc; > + err = watchdog_set_pulse_width(pulse_width); > + if (err) > + goto exit_alloc; > + > break; > > case f71862fg: > @@ -2256,6 +2790,12 @@ static int __init f71882fg_find_watchdog(int sioaddr, > } > > return 0; > + > +exit_alloc: > + kfree(watchdog); > + watchdog = NULL; > + > + return err; > } > > static int __init f71882fg_find_hwmon(int sioaddr, unsigned short *hwmon_addr, > @@ -2421,6 +2961,12 @@ static int __init f71882fg_init(void) > if (err) > goto exit_driver; > > + if (watchdog) { > + err = watchdog_init(); > + if (err) > + goto exit_driver; > + } > + > return 0; > > exit_driver: > @@ -2433,6 +2979,13 @@ static void __exit f71882fg_exit(void) > { > platform_device_unregister(f71882fg_pdev); > platform_driver_unregister(&f71882fg_driver); > + > + if (watchdog) { > + watchdog_stop(); > + misc_deregister(&watchdog_miscdev); > + unregister_reboot_notifier(&watchdog_notifier); > + release_region(watchdog->sioaddr, 2); > + } > } > > MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 8:37 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Hans de Goede @ 2010-03-24 9:36 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:36 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 419 bytes --] On Wed, Mar 24, 2010 at 09:37:43AM +0100, Hans de Goede wrote: > Nack: > As the watchdog has its own SIO logical device number, it should > have a separate driver, not have support glued to the hwmon driver. Thus, if I understand correctly, you would suggest for me to implement a new driver in drivers/watchdog/ to implement this driver? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-24 9:36 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:36 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 419 bytes --] On Wed, Mar 24, 2010 at 09:37:43AM +0100, Hans de Goede wrote: > Nack: > As the watchdog has its own SIO logical device number, it should > have a separate driver, not have support glued to the hwmon driver. Thus, if I understand correctly, you would suggest for me to implement a new driver in drivers/watchdog/ to implement this driver? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 9:36 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel @ 2010-03-24 10:33 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 10:33 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/24/2010 10:36 AM, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 09:37:43AM +0100, Hans de Goede wrote: >> Nack: >> As the watchdog has its own SIO logical device number, it should >> have a separate driver, not have support glued to the hwmon driver. > > Thus, if I understand correctly, you would suggest for me to implement a > new driver in drivers/watchdog/ to implement this driver? > Yes, correct. Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-24 10:33 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 10:33 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/24/2010 10:36 AM, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 09:37:43AM +0100, Hans de Goede wrote: >> Nack: >> As the watchdog has its own SIO logical device number, it should >> have a separate driver, not have support glued to the hwmon driver. > > Thus, if I understand correctly, you would suggest for me to implement a > new driver in drivers/watchdog/ to implement this driver? > Yes, correct. Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 10:33 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Hans de Goede @ 2010-03-24 15:35 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 15:35 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 2542 bytes --] On Wed, Mar 24, 2010 at 11:33:00AM +0100, Hans de Goede wrote: > On 03/24/2010 10:36 AM, Giel van Schijndel wrote: >>On Wed, Mar 24, 2010 at 09:37:43AM +0100, Hans de Goede wrote: >>> Nack: >>> As the watchdog has its own SIO logical device number, it should >>> have a separate driver, not have support glued to the hwmon driver. >> >> Thus, if I understand correctly, you would suggest for me to >> implement a new driver in drivers/watchdog/ to implement this >> feature? > > Yes, correct. So I've now started out working on moving the watchdog code to a separate driver. I/O port conflict However, this driver would have to lock the SIO port range as well. Unlike the hardware monitor, however, the watchdog (VID controller on some datasheets) doesn't appear to provide for an alternative I/O port mapping. Meaning the wathdog driver would have to maintain a permanent hold on the SIO port range. This would thus interfere with the operation of the f71882fg driver. I.e. it would prevent the device probing stage from working, thus preventing it from loading *after* my in-development watchdog driver. Alternative logical device port mapping Regarding address mapping: the 16 bit SIO_REG_ADDR(0x60) register does exist for this logical device, though according to the datasheet it is set to 0x0000 by default. Reading the value from hardware it claims to be mapped on 0x0AE0, trying to read from that port range (using f71882fg_read8) yields nothing more than 0xFF for any register mentioned in the datasheet. Hardware monitor alternate port range Further, when looking at the way that SIO_REG_ADDR is currently used by the f71882fg driver I get more confused: > *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); > /* error checking: *hwmon_addr != 0 */ > *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ For the F71808E and F71889, which both have 0x295, for hardware monitor base address that code ^^ combined with the addition of ADDR_REG_OFFSET and DATA_REG_OFFSET (see f71882fg_(read|write)8) all of this basically amounts to mangling 0x295 -> 0x290 -> (0x295,0x296). So my question: is there any particular reason for performing this address mangling? Mostly: is there anything there that I should try replicating in order to get mapping of the watchdog device on an alternate port range working? PS Perhaps this would be easier to converse about if you had the datasheet? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-24 15:35 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 15:35 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 2542 bytes --] On Wed, Mar 24, 2010 at 11:33:00AM +0100, Hans de Goede wrote: > On 03/24/2010 10:36 AM, Giel van Schijndel wrote: >>On Wed, Mar 24, 2010 at 09:37:43AM +0100, Hans de Goede wrote: >>> Nack: >>> As the watchdog has its own SIO logical device number, it should >>> have a separate driver, not have support glued to the hwmon driver. >> >> Thus, if I understand correctly, you would suggest for me to >> implement a new driver in drivers/watchdog/ to implement this >> feature? > > Yes, correct. So I've now started out working on moving the watchdog code to a separate driver. I/O port conflict However, this driver would have to lock the SIO port range as well. Unlike the hardware monitor, however, the watchdog (VID controller on some datasheets) doesn't appear to provide for an alternative I/O port mapping. Meaning the wathdog driver would have to maintain a permanent hold on the SIO port range. This would thus interfere with the operation of the f71882fg driver. I.e. it would prevent the device probing stage from working, thus preventing it from loading *after* my in-development watchdog driver. Alternative logical device port mapping Regarding address mapping: the 16 bit SIO_REG_ADDR(0x60) register does exist for this logical device, though according to the datasheet it is set to 0x0000 by default. Reading the value from hardware it claims to be mapped on 0x0AE0, trying to read from that port range (using f71882fg_read8) yields nothing more than 0xFF for any register mentioned in the datasheet. Hardware monitor alternate port range Further, when looking at the way that SIO_REG_ADDR is currently used by the f71882fg driver I get more confused: > *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); > /* error checking: *hwmon_addr != 0 */ > *hwmon_addr &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ For the F71808E and F71889, which both have 0x295, for hardware monitor base address that code ^^ combined with the addition of ADDR_REG_OFFSET and DATA_REG_OFFSET (see f71882fg_(read|write)8) all of this basically amounts to mangling 0x295 -> 0x290 -> (0x295,0x296). So my question: is there any particular reason for performing this address mangling? Mostly: is there anything there that I should try replicating in order to get mapping of the watchdog device on an alternate port range working? PS Perhaps this would be easier to converse about if you had the datasheet? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 15:35 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel @ 2010-03-24 15:51 ` Alan Cox -1 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-24 15:51 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel > hold on the SIO port range. This would thus interfere with the operation > of the f71882fg driver. I.e. it would prevent the device probing stage > from working, thus preventing it from loading *after* my in-development > watchdog driver. There are two ways to deal with that really 1. Add a multi-function driver - it finds the chip and claims the port regions and then provides methods for locked access to them as well as creating other device instances that the drivers map to (probably platform devices ?) which in turn trigger the loading/binding of the relevant low level devices. 2. Fix the kernel request_resource stuff to support a sleeping non exclusive resource so request/free of regions can be used as a resource semaphore by co-operative devices. #2 is actually not hard but when I did the patch originally it then wasn't needed by the driver I had in mind for other reasons. See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea Maybe its worth resurrecting ? Alan ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-24 15:51 ` Alan Cox 0 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-24 15:51 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel > hold on the SIO port range. This would thus interfere with the operation > of the f71882fg driver. I.e. it would prevent the device probing stage > from working, thus preventing it from loading *after* my in-development > watchdog driver. There are two ways to deal with that really 1. Add a multi-function driver - it finds the chip and claims the port regions and then provides methods for locked access to them as well as creating other device instances that the drivers map to (probably platform devices ?) which in turn trigger the loading/binding of the relevant low level devices. 2. Fix the kernel request_resource stuff to support a sleeping non exclusive resource so request/free of regions can be used as a resource semaphore by co-operative devices. #2 is actually not hard but when I did the patch originally it then wasn't needed by the driver I had in mind for other reasons. See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea Maybe its worth resurrecting ? Alan _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 15:51 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Alan Cox @ 2010-03-24 16:20 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 16:20 UTC (permalink / raw) To: Alan Cox Cc: Giel van Schijndel, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/24/2010 04:51 PM, Alan Cox wrote: >> hold on the SIO port range. This would thus interfere with the operation >> of the f71882fg driver. I.e. it would prevent the device probing stage >> from working, thus preventing it from loading *after* my in-development >> watchdog driver. > > There are two ways to deal with that really > > 1. Add a multi-function driver - it finds the chip and claims the port > regions and then provides methods for locked access to them as well as > creating other device instances that the drivers map to (probably platform > devices ?) which in turn trigger the loading/binding of the relevant low > level devices. > > 2. Fix the kernel request_resource stuff to support a sleeping non > exclusive resource so request/free of regions can be used as a resource > semaphore by co-operative devices. > > #2 is actually not hard but when I did the patch originally it then > wasn't needed by the driver I had in mind for other reasons. > > See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea > > Maybe its worth resurrecting ? > Or, a bit more specific solution would be to resurrect the superio lock coordinator patches, which were written (but never merged) 2 years ago to solve exactly this problem: http://lists.lm-sensors.org/pipermail/lm-sensors/2008-July/023743.html Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-24 16:20 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 16:20 UTC (permalink / raw) To: Alan Cox Cc: Giel van Schijndel, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/24/2010 04:51 PM, Alan Cox wrote: >> hold on the SIO port range. This would thus interfere with the operation >> of the f71882fg driver. I.e. it would prevent the device probing stage >> from working, thus preventing it from loading *after* my in-development >> watchdog driver. > > There are two ways to deal with that really > > 1. Add a multi-function driver - it finds the chip and claims the port > regions and then provides methods for locked access to them as well as > creating other device instances that the drivers map to (probably platform > devices ?) which in turn trigger the loading/binding of the relevant low > level devices. > > 2. Fix the kernel request_resource stuff to support a sleeping non > exclusive resource so request/free of regions can be used as a resource > semaphore by co-operative devices. > > #2 is actually not hard but when I did the patch originally it then > wasn't needed by the driver I had in mind for other reasons. > > See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea > > Maybe its worth resurrecting ? > Or, a bit more specific solution would be to resurrect the superio lock coordinator patches, which were written (but never merged) 2 years ago to solve exactly this problem: http://lists.lm-sensors.org/pipermail/lm-sensors/2008-July/023743.html Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 16:20 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Hans de Goede @ 2010-03-24 20:35 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 20:35 UTC (permalink / raw) To: Hans de Goede Cc: Alan Cox, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 2483 bytes --] On Wed, Mar 24, 2010 at 05:20:59PM +0100, Hans de Goede wrote: > On 03/24/2010 04:51 PM, Alan Cox wrote: >>> hold on the SIO port range. This would thus interfere with the >>> operation of the f71882fg driver. I.e. it would prevent the device >>> probing stage from working, thus preventing it from loading *after* >>> my in-development watchdog driver. >> >> There are two ways to deal with that really >> >> 1. Add a multi-function driver - it finds the chip and claims the >> port regions and then provides methods for locked access to them as >> well as creating other device instances that the drivers map to >> (probably platform devices ?) which in turn trigger the >> loading/binding of the relevant low level devices. >> >> 2. Fix the kernel request_resource stuff to support a sleeping non >> exclusive resource so request/free of regions can be used as a >> resource semaphore by co-operative devices. >> >> #2 is actually not hard but when I did the patch originally it then >> wasn't needed by the driver I had in mind for other reasons. >> >> See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea >> >> Maybe its worth resurrecting ? > > Or, a bit more specific solution would be to resurrect the superio > lock coordinator patches, which were written (but never merged) 2 > years ago to solve exactly this problem: > http://lists.lm-sensors.org/pipermail/lm-sensors/2008-July/023743.html When performing some searches I find messages going back to at least september 2006 [1] [2]. With multiple occurences of these patches being "dusted off". They never got applied though, and for that (*not* applying them) I cannot find any reason. Is there any? Or did people just become uninterested and let the patches "collect dust"? Then regarding Alan's patch. The fact that it is a *lot* simpler than Jim Cromie's SuperIO locks coordinator is IMHO a significant advantage over the latter. Furthermore, "lock coordinator" seems like a bad name to me, since those patches seem especially concerned with centralising the way that SuperIO devices are probed for. Thus if the only thing required is to serialize resource access I think plain-ol' locking (with the ability to block on the lock, rather than polling for it). [1] http://lists.lm-sensors.org/pipermail/lm-sensors/2006-June/016476.html [2] http://lkml.org/lkml/2006/9/14/20 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-24 20:35 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 20:35 UTC (permalink / raw) To: Hans de Goede Cc: Alan Cox, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 2483 bytes --] On Wed, Mar 24, 2010 at 05:20:59PM +0100, Hans de Goede wrote: > On 03/24/2010 04:51 PM, Alan Cox wrote: >>> hold on the SIO port range. This would thus interfere with the >>> operation of the f71882fg driver. I.e. it would prevent the device >>> probing stage from working, thus preventing it from loading *after* >>> my in-development watchdog driver. >> >> There are two ways to deal with that really >> >> 1. Add a multi-function driver - it finds the chip and claims the >> port regions and then provides methods for locked access to them as >> well as creating other device instances that the drivers map to >> (probably platform devices ?) which in turn trigger the >> loading/binding of the relevant low level devices. >> >> 2. Fix the kernel request_resource stuff to support a sleeping non >> exclusive resource so request/free of regions can be used as a >> resource semaphore by co-operative devices. >> >> #2 is actually not hard but when I did the patch originally it then >> wasn't needed by the driver I had in mind for other reasons. >> >> See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea >> >> Maybe its worth resurrecting ? > > Or, a bit more specific solution would be to resurrect the superio > lock coordinator patches, which were written (but never merged) 2 > years ago to solve exactly this problem: > http://lists.lm-sensors.org/pipermail/lm-sensors/2008-July/023743.html When performing some searches I find messages going back to at least september 2006 [1] [2]. With multiple occurences of these patches being "dusted off". They never got applied though, and for that (*not* applying them) I cannot find any reason. Is there any? Or did people just become uninterested and let the patches "collect dust"? Then regarding Alan's patch. The fact that it is a *lot* simpler than Jim Cromie's SuperIO locks coordinator is IMHO a significant advantage over the latter. Furthermore, "lock coordinator" seems like a bad name to me, since those patches seem especially concerned with centralising the way that SuperIO devices are probed for. Thus if the only thing required is to serialize resource access I think plain-ol' locking (with the ability to block on the lock, rather than polling for it). [1] http://lists.lm-sensors.org/pipermail/lm-sensors/2006-June/016476.html [2] http://lkml.org/lkml/2006/9/14/20 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 20:35 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel @ 2010-04-25 21:20 ` Jim Cromie -1 siblings, 0 replies; 159+ messages in thread From: Jim Cromie @ 2010-04-25 21:20 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, linux-kernel, lm-sensors, Laurens Leemans, Alan Cox On Wed, Mar 24, 2010 at 4:35 PM, Giel van Schijndel <me@mortis.eu> wrote: > On Wed, Mar 24, 2010 at 05:20:59PM +0100, Hans de Goede wrote: >> On 03/24/2010 04:51 PM, Alan Cox wrote: >>>> hold on the SIO port range. This would thus interfere with the >>>> operation of the f71882fg driver. I.e. it would prevent the device >>>> probing stage from working, thus preventing it from loading *after* >>>> my in-development watchdog driver. >>> >>> There are two ways to deal with that really >>> >>> 1. Add a multi-function driver - it finds the chip and claims the >>> port regions and then provides methods for locked access to them as >>> well as creating other device instances that the drivers map to >>> (probably platform devices ?) which in turn trigger the >>> loading/binding of the relevant low level devices. >>> >>> 2. Fix the kernel request_resource stuff to support a sleeping non >>> exclusive resource so request/free of regions can be used as a >>> resource semaphore by co-operative devices. >>> >>> #2 is actually not hard but when I did the patch originally it then >>> wasn't needed by the driver I had in mind for other reasons. >>> >>> See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea >>> >>> Maybe its worth resurrecting ? >> >> Or, a bit more specific solution would be to resurrect the superio >> lock coordinator patches, which were written (but never merged) 2 >> years ago to solve exactly this problem: >> http://lists.lm-sensors.org/pipermail/lm-sensors/2008-July/023743.html > > When performing some searches I find messages going back to at least > september 2006 [1] [2]. With multiple occurences of these patches being > "dusted off". They never got applied though, and for that (*not* > applying them) I cannot find any reason. Is there any? Or did people > just become uninterested and let the patches "collect dust"? > For my part, I started seeing difficulties in the centralized probing, esp around the unlocking sequences; stuff thats device specific, but wanted to be hidden in the centralized probe. When it was just byte-sequences, it was ok, but then too many variations presented. > Then regarding Alan's patch. The fact that it is a *lot* simpler than > Jim Cromie's SuperIO locks coordinator is IMHO a significant advantage > over the latter. Furthermore, "lock coordinator" seems like a bad name > to me, since those patches seem especially concerned with centralising > the way that SuperIO devices are probed for. Thus if the only thing > required is to serialize resource access I think plain-ol' locking > (with the ability to block on the lock, rather than polling for it). > "coordinator" was meant to imply cooperative drivers, though thats *always* the case, in that drivers would at least have to check a mutex. > [1] http://lists.lm-sensors.org/pipermail/lm-sensors/2006-June/016476.html > [2] http://lkml.org/lkml/2006/9/14/20 > > -- > Met vriendelijke groet, > With kind regards, > Giel van Schijndel > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.10 (GNU/Linux) > > iEYEARECAAYFAkuqd6sACgkQZBYm/87l50K6KwCdEMTmQ2Y4k0yi8GcWOSHIeel8 > g90An3Yso3XhFqwniMyIwEa/gOSQ9uPw > =NFuC > -----END PGP SIGNATURE----- > > _______________________________________________ > lm-sensors mailing list > lm-sensors@lm-sensors.org > http://lists.lm-sensors.org/mailman/listinfo/lm-sensors > ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-04-25 21:20 ` Jim Cromie 0 siblings, 0 replies; 159+ messages in thread From: Jim Cromie @ 2010-04-25 21:20 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, linux-kernel, lm-sensors, Laurens Leemans, Alan Cox On Wed, Mar 24, 2010 at 4:35 PM, Giel van Schijndel <me@mortis.eu> wrote: > On Wed, Mar 24, 2010 at 05:20:59PM +0100, Hans de Goede wrote: >> On 03/24/2010 04:51 PM, Alan Cox wrote: >>>> hold on the SIO port range. This would thus interfere with the >>>> operation of the f71882fg driver. I.e. it would prevent the device >>>> probing stage from working, thus preventing it from loading *after* >>>> my in-development watchdog driver. >>> >>> There are two ways to deal with that really >>> >>> 1. Add a multi-function driver - it finds the chip and claims the >>> port regions and then provides methods for locked access to them as >>> well as creating other device instances that the drivers map to >>> (probably platform devices ?) which in turn trigger the >>> loading/binding of the relevant low level devices. >>> >>> 2. Fix the kernel request_resource stuff to support a sleeping non >>> exclusive resource so request/free of regions can be used as a >>> resource semaphore by co-operative devices. >>> >>> #2 is actually not hard but when I did the patch originally it then >>> wasn't needed by the driver I had in mind for other reasons. >>> >>> See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea >>> >>> Maybe its worth resurrecting ? >> >> Or, a bit more specific solution would be to resurrect the superio >> lock coordinator patches, which were written (but never merged) 2 >> years ago to solve exactly this problem: >> http://lists.lm-sensors.org/pipermail/lm-sensors/2008-July/023743.html > > When performing some searches I find messages going back to at least > september 2006 [1] [2]. With multiple occurences of these patches being > "dusted off". They never got applied though, and for that (*not* > applying them) I cannot find any reason. Is there any? Or did people > just become uninterested and let the patches "collect dust"? > For my part, I started seeing difficulties in the centralized probing, esp around the unlocking sequences; stuff thats device specific, but wanted to be hidden in the centralized probe. When it was just byte-sequences, it was ok, but then too many variations presented. > Then regarding Alan's patch. The fact that it is a *lot* simpler than > Jim Cromie's SuperIO locks coordinator is IMHO a significant advantage > over the latter. Furthermore, "lock coordinator" seems like a bad name > to me, since those patches seem especially concerned with centralising > the way that SuperIO devices are probed for. Thus if the only thing > required is to serialize resource access I think plain-ol' locking > (with the ability to block on the lock, rather than polling for it). > "coordinator" was meant to imply cooperative drivers, though thats *always* the case, in that drivers would at least have to check a mutex. > [1] http://lists.lm-sensors.org/pipermail/lm-sensors/2006-June/016476.html > [2] http://lkml.org/lkml/2006/9/14/20 > > -- > Met vriendelijke groet, > With kind regards, > Giel van Schijndel > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.10 (GNU/Linux) > > iEYEARECAAYFAkuqd6sACgkQZBYm/87l50K6KwCdEMTmQ2Y4k0yi8GcWOSHIeel8 > g90An3Yso3XhFqwniMyIwEa/gOSQ9uPw > =NFuC > -----END PGP SIGNATURE----- > > _______________________________________________ > lm-sensors mailing list > lm-sensors@lm-sensors.org > http://lists.lm-sensors.org/mailman/listinfo/lm-sensors > _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-24 15:51 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Alan Cox @ 2010-03-25 8:54 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 8:54 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1589 bytes --] On Wed, Mar 24, 2010 at 03:51:51PM +0000, Alan Cox wrote: >> hold on the SIO port range. This would thus interfere with the >> operation of the f71882fg driver. I.e. it would prevent the device >> probing stage from working, thus preventing it from loading *after* >> my in-development watchdog driver. > > There are two ways to deal with that really > > ... snip ... > > 2. Fix the kernel request_resource stuff to support a sleeping non > exclusive resource so request/free of regions can be used as a resource > semaphore by co-operative devices. > > #2 is actually not hard but when I did the patch originally it then > wasn't needed by the driver I had in mind for other reasons. > > See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea > > Maybe its worth resurrecting ? In this particular case I most definitely think it's worth resurrecting. Using your patch (I had to change the IORESOURCE_MUXED constant's value though) I can completely solve the I/O sharing issue for the f71882fg + watchdog case with only a single line modification to the f71882fg driver. One question regarding your patch though: how will it function when driver (A) locks an I/O region using request_region() then driver (B) comes along and tries to lock it using request_muxed_region()? One problem I imagine might occur is that driver (A)'s 'struct resource' doesn't have the IORESOURCE_MUXED flags set, thus simply won't wake up driver (B) on the 'muxed_resource_wait' queue. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-25 8:54 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 8:54 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 1589 bytes --] On Wed, Mar 24, 2010 at 03:51:51PM +0000, Alan Cox wrote: >> hold on the SIO port range. This would thus interfere with the >> operation of the f71882fg driver. I.e. it would prevent the device >> probing stage from working, thus preventing it from loading *after* >> my in-development watchdog driver. > > There are two ways to deal with that really > > ... snip ... > > 2. Fix the kernel request_resource stuff to support a sleeping non > exclusive resource so request/free of regions can be used as a resource > semaphore by co-operative devices. > > #2 is actually not hard but when I did the patch originally it then > wasn't needed by the driver I had in mind for other reasons. > > See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea > > Maybe its worth resurrecting ? In this particular case I most definitely think it's worth resurrecting. Using your patch (I had to change the IORESOURCE_MUXED constant's value though) I can completely solve the I/O sharing issue for the f71882fg + watchdog case with only a single line modification to the f71882fg driver. One question regarding your patch though: how will it function when driver (A) locks an I/O region using request_region() then driver (B) comes along and tries to lock it using request_muxed_region()? One problem I imagine might occur is that driver (A)'s 'struct resource' doesn't have the IORESOURCE_MUXED flags set, thus simply won't wake up driver (B) on the 'muxed_resource_wait' queue. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-25 8:54 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel @ 2010-03-25 10:40 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 10:40 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 4336 bytes --] On Thu, Mar 25, 2010 at 09:54:50AM +0100, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 03:51:51PM +0000, Alan Cox wrote: >>> hold on the SIO port range. This would thus interfere with the >>> operation of the f71882fg driver. I.e. it would prevent the device >>> probing stage from working, thus preventing it from loading *after* >>> my in-development watchdog driver. >> >> There are two ways to deal with that really >> >> ... snip ... >> >> 2. Fix the kernel request_resource stuff to support a sleeping non >> exclusive resource so request/free of regions can be used as a resource >> semaphore by co-operative devices. >> >> #2 is actually not hard but when I did the patch originally it then >> wasn't needed by the driver I had in mind for other reasons. >> >> See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea >> >> Maybe its worth resurrecting ? > > In this particular case I most definitely think it's worth resurrecting. > Using your patch (I had to change the IORESOURCE_MUXED constant's value > though) I can completely solve the I/O sharing issue for the f71882fg + > watchdog case with only a single line modification to the f71882fg > driver. > > ... snip ... Using Alan's patch and the one following the dashed line I can implement (and have already done so) a separate watchdog driver for the Fintek F71808E. Should I just ask for this patch to be applied together with Alan's? Then submit the new driver? (I'm a bit new to the non-technical aspects of Linux kernel development). ======================================================================== hwmon: f71882fg: use a muxed resource lock for the Super I/O port Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. --- drivers/hwmon/f71882fg.c | 28 +++++++++++++++------------- 1 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..e09416d 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,17 +2249,10 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { @@ -2306,7 +2309,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-25 10:40 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 10:40 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 4336 bytes --] On Thu, Mar 25, 2010 at 09:54:50AM +0100, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 03:51:51PM +0000, Alan Cox wrote: >>> hold on the SIO port range. This would thus interfere with the >>> operation of the f71882fg driver. I.e. it would prevent the device >>> probing stage from working, thus preventing it from loading *after* >>> my in-development watchdog driver. >> >> There are two ways to deal with that really >> >> ... snip ... >> >> 2. Fix the kernel request_resource stuff to support a sleeping non >> exclusive resource so request/free of regions can be used as a resource >> semaphore by co-operative devices. >> >> #2 is actually not hard but when I did the patch originally it then >> wasn't needed by the driver I had in mind for other reasons. >> >> See http://groups.google.com/group/linux.kernel/msg/1425fc2aad32e6ea >> >> Maybe its worth resurrecting ? > > In this particular case I most definitely think it's worth resurrecting. > Using your patch (I had to change the IORESOURCE_MUXED constant's value > though) I can completely solve the I/O sharing issue for the f71882fg + > watchdog case with only a single line modification to the f71882fg > driver. > > ... snip ... Using Alan's patch and the one following the dashed line I can implement (and have already done so) a separate watchdog driver for the Fintek F71808E. Should I just ask for this patch to be applied together with Alan's? Then submit the new driver? (I'm a bit new to the non-technical aspects of Linux kernel development). ======================================================================== hwmon: f71882fg: use a muxed resource lock for the Super I/O port Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. --- drivers/hwmon/f71882fg.c | 28 +++++++++++++++------------- 1 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..e09416d 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,17 +2249,10 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { @@ -2306,7 +2309,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-25 10:40 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel @ 2010-03-25 12:50 ` Alan Cox -1 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-25 12:50 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel O> Using Alan's patch and the one following the dashed line I can implement > (and have already done so) a separate watchdog driver for the Fintek > F71808E. > > Should I just ask for this patch to be applied together with Alan's? > Then submit the new driver? (I'm a bit new to the non-technical aspects > of Linux kernel development). I'd expect to see a submission of three patches I think 1. Patch adding the muxed resource support 2. Patch making the hwmon driver use it 3. Patch adding the new driver which needs it and then we have a few other bits of code that probably should adopt it, but that is a separate matter and other maintainers can do that bit. Alan ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-25 12:50 ` Alan Cox 0 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-25 12:50 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel O> Using Alan's patch and the one following the dashed line I can implement > (and have already done so) a separate watchdog driver for the Fintek > F71808E. > > Should I just ask for this patch to be applied together with Alan's? > Then submit the new driver? (I'm a bit new to the non-technical aspects > of Linux kernel development). I'd expect to see a submission of three patches I think 1. Patch adding the muxed resource support 2. Patch making the hwmon driver use it 3. Patch adding the new driver which needs it and then we have a few other bits of code that probably should adopt it, but that is a separate matter and other maintainers can do that bit. Alan _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 2010-03-25 12:50 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Alan Cox @ 2010-03-25 13:06 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-25 13:06 UTC (permalink / raw) To: Alan Cox Cc: Giel van Schijndel, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, On 03/25/2010 01:50 PM, Alan Cox wrote: > O> Using Alan's patch and the one following the dashed line I can implement >> (and have already done so) a separate watchdog driver for the Fintek >> F71808E. >> >> Should I just ask for this patch to be applied together with Alan's? >> Then submit the new driver? (I'm a bit new to the non-technical aspects >> of Linux kernel development). > > I'd expect to see a submission of three patches I think > > 1. Patch adding the muxed resource support > 2. Patch making the hwmon driver use it > 3. Patch adding the new driver which needs it > > and then we have a few other bits of code that probably should adopt it, > but that is a separate matter and other maintainers can do that bit. > What Alan said :) Although I'm not sure what the proper place is to post this entire set, I guess linux-kernel itself, with lm_sensors in the CC. Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog @ 2010-03-25 13:06 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-25 13:06 UTC (permalink / raw) To: Alan Cox Cc: Giel van Schijndel, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, On 03/25/2010 01:50 PM, Alan Cox wrote: > O> Using Alan's patch and the one following the dashed line I can implement >> (and have already done so) a separate watchdog driver for the Fintek >> F71808E. >> >> Should I just ask for this patch to be applied together with Alan's? >> Then submit the new driver? (I'm a bit new to the non-technical aspects >> of Linux kernel development). > > I'd expect to see a submission of three patches I think > > 1. Patch adding the muxed resource support > 2. Patch making the hwmon driver use it > 3. Patch adding the new driver which needs it > > and then we have a few other bits of code that probably should adopt it, > but that is a separate matter and other maintainers can do that bit. > What Alan said :) Although I'm not sure what the proper place is to post this entire set, I guess linux-kernel itself, with lm_sensors in the CC. Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* [PATCH 1/3] resource: shared I/O region support 2010-03-25 12:50 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Alan Cox @ 2010-03-25 13:17 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 13:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel, Alan Cox From: Alan Cox <alan@lxorguk.ukuu.org.uk> This patch was originally written by Alan Cox [1]. I only updated it to apply correctly to Linus' current tree and changed IORESOURCE_MUXED's value from 0x00200000 to 0x00400000 because the former has already been taken in use since. [1] https://patchwork.kernel.org/patch/32397/ Patch after this line: ======================================================================== SuperIO devices share regions and use lock/unlock operations to chip select. We therefore need to be able to request a resource and wait for it to be freed by whichever other SuperIO device currently hogs it. Right now you have to poll which is horrible. Add a MUXED field to IO port resources. If the MUXED field is set on the resource and on the request (via request_muxed_region) then we block until the previous owner of the muxed resource releases their region. This allows us to implement proper resource sharing and locking for superio chips using code of the form enable_my_superio_dev() { request_muxed_region(0x44, 0x02, "superio:watchdog"); outb() ..sequence to enable chip } disable_my_superio_dev() { outb() .. sequence of disable chip release_region(0x44, 0x02); } Signed-off-by: Giel van Schijndel <me@mortis.eu> --- include/linux/ioport.h | 4 +++- kernel/resource.c | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 71ab79d..604fd29 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -52,6 +52,7 @@ struct resource_list { #define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_DISABLED 0x10000000 @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) } /* Convenience shorthand with allocation */ -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) #define request_mem_region_exclusive(start,n,name) \ diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..1484180 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -651,6 +651,8 @@ resource_size_t resource_alignment(struct resource *res) * release_region releases a matching busy region. */ +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); + /** * __request_region - create a new busy resource region * @parent: parent resource descriptor @@ -663,6 +665,7 @@ struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags) { + DECLARE_WAITQUEUE(wait, current); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) @@ -687,7 +690,14 @@ struct resource * __request_region(struct resource *parent, if (!(conflict->flags & IORESOURCE_BUSY)) continue; } - + if (conflict->flags & flags & IORESOURCE_MUXED) { + add_wait_queue(&muxed_resource_wait, &wait); + write_unlock(&resource_lock); + schedule(); + remove_wait_queue(&muxed_resource_wait, &wait); + write_lock(&resource_lock); + continue; + } /* Uhhuh, that didn't work out.. */ kfree(res); res = NULL; @@ -761,6 +771,8 @@ void __release_region(struct resource *parent, resource_size_t start, break; *p = res->sibling; write_unlock(&resource_lock); + if (res->flags & IORESOURCE_MUXED) + wake_up(&muxed_resource_wait); kfree(res); return; } -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-25 13:17 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 13:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel, Alan Cox From: Alan Cox <alan@lxorguk.ukuu.org.uk> This patch was originally written by Alan Cox [1]. I only updated it to apply correctly to Linus' current tree and changed IORESOURCE_MUXED's value from 0x00200000 to 0x00400000 because the former has already been taken in use since. [1] https://patchwork.kernel.org/patch/32397/ Patch after this line: ==================================== SuperIO devices share regions and use lock/unlock operations to chip select. We therefore need to be able to request a resource and wait for it to be freed by whichever other SuperIO device currently hogs it. Right now you have to poll which is horrible. Add a MUXED field to IO port resources. If the MUXED field is set on the resource and on the request (via request_muxed_region) then we block until the previous owner of the muxed resource releases their region. This allows us to implement proper resource sharing and locking for superio chips using code of the form enable_my_superio_dev() { request_muxed_region(0x44, 0x02, "superio:watchdog"); outb() ..sequence to enable chip } disable_my_superio_dev() { outb() .. sequence of disable chip release_region(0x44, 0x02); } Signed-off-by: Giel van Schijndel <me@mortis.eu> --- include/linux/ioport.h | 4 +++- kernel/resource.c | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 71ab79d..604fd29 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -52,6 +52,7 @@ struct resource_list { #define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_DISABLED 0x10000000 @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) } /* Convenience shorthand with allocation */ -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) #define request_mem_region_exclusive(start,n,name) \ diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..1484180 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -651,6 +651,8 @@ resource_size_t resource_alignment(struct resource *res) * release_region releases a matching busy region. */ +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); + /** * __request_region - create a new busy resource region * @parent: parent resource descriptor @@ -663,6 +665,7 @@ struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags) { + DECLARE_WAITQUEUE(wait, current); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) @@ -687,7 +690,14 @@ struct resource * __request_region(struct resource *parent, if (!(conflict->flags & IORESOURCE_BUSY)) continue; } - + if (conflict->flags & flags & IORESOURCE_MUXED) { + add_wait_queue(&muxed_resource_wait, &wait); + write_unlock(&resource_lock); + schedule(); + remove_wait_queue(&muxed_resource_wait, &wait); + write_lock(&resource_lock); + continue; + } /* Uhhuh, that didn't work out.. */ kfree(res); res = NULL; @@ -761,6 +771,8 @@ void __release_region(struct resource *parent, resource_size_t start, break; *p = res->sibling; write_unlock(&resource_lock); + if (res->flags & IORESOURCE_MUXED) + wake_up(&muxed_resource_wait); kfree(res); return; } -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-03-25 13:17 ` [lm-sensors] " Giel van Schijndel @ 2010-03-25 13:17 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 13:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 28 +++++++++++++++------------- 1 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..e09416d 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,17 +2249,10 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { @@ -2306,7 +2309,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock @ 2010-03-25 13:17 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 13:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 28 +++++++++++++++------------- 1 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..e09416d 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,17 +2249,10 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { @@ -2306,7 +2309,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E 2010-03-25 13:17 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock Giel van Schijndel @ 2010-03-25 13:17 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 13:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Add a new watchdog driver for the Fintek F71808E Super I/O chip. --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/f71808e_wdt.c | 726 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 738 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/f71808e_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index bdcdbd5..653896f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -382,6 +382,17 @@ config ALIM7101_WDT Most people will say N. +config F71808E_WDT + tristate "Fintek F71808E Watchdog" + depends on X86 && EXPERIMENTAL + help + This is the driver for the hardware watchdog on the Fintek + F71808E Super I/O chip. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called f71808e_wdt. + + config GEODE_WDT tristate "AMD Geode CS5535/CS5536 Watchdog" depends on CS5535_MFGPT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 5e3cb95..e2f308d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c new file mode 100644 index 0000000..7d547a9 --- /dev/null +++ b/drivers/watchdog/f71808e_wdt.c @@ -0,0 +1,726 @@ +/*************************************************************************** + * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * + * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * + * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/uaccess.h> +#include <linux/watchdog.h> + +#define DRVNAME "f71808e_wdt" + +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ +#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ +#define SIO_F71858_ID 0x0507 /* Chipset ID */ +#define SIO_F71862_ID 0x0601 /* Chipset ID */ +#define SIO_F71882_ID 0x0541 /* Chipset ID */ +#define SIO_F71889_ID 0x0723 /* Chipset ID */ + +#define F71882FG_REG_START 0x01 + +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static unsigned int start_withtimeout; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; + +static const char *f71808e_names[] = { + "f71808fg", + "f71858fg", + "f71862fg", + "f71882fg", + "f71889fg", +}; + +/* Super-I/O Function prototypes */ +static inline int superio_inb(int base, int reg); +static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); +static inline int superio_enter(int base); +static inline void superio_select(int base, int ld); +static inline void superio_exit(int base); + +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data watchdog = { + .lock = __MUTEX_INITIALIZER(watchdog.lock), +}; + +/* Super I/O functions */ +static inline int superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int superio_inw(int base, int reg) +{ + int val; + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); + return val; +} + +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline int superio_enter(int base) +{ + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + + /* according to the datasheet the key must be send twice! */ + outb(SIO_UNLOCK_KEY, base); + outb(SIO_UNLOCK_KEY, base); + + return 0; +} + +static inline void superio_select(int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void superio_exit(int base) +{ + outb(SIO_LOCK_KEY, base); + release_region(base, 2); +} + +static int watchdog_set_timeout(int timeout) +{ + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog.lock); + + watchdog.timeout = timeout; + if (timeout > 0xff) { + watchdog.timer_val = DIV_ROUND_UP(timeout, 60); + watchdog.minutes_mode = true; + } else { + watchdog.timer_val = timeout; + watchdog.minutes_mode = false; + } + + mutex_unlock(&watchdog.lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + + if (pw <= 1) { + watchdog.pulse_val = 0; + } else if (pw <= 25) { + watchdog.pulse_val = 1; + } else if (pw <= 125) { + watchdog.pulse_val = 2; + } else if (pw <= 5000) { + watchdog.pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog.pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_keepalive(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + + if (watchdog.minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME, + watchdog.timeout); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + + /* Watchdog pin configuration */ + switch (watchdog.type) { + case f71808fg: + /* Set ping 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog.sioaddr, 0x2a, 3); + superio_clear_bit(watchdog.sioaddr, 0x2b, 3); + break; + + default: + /* + * 'default' label to shut up the compiler and catch + * programmer errors + */ + err = -ENODEV; + goto exit_superio; + } + + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog.pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog.sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_superio: + superio_exit(watchdog.sioaddr); +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_stop(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + mutex_lock(&watchdog.lock); + status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog.lock); + + return status; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog.opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog.opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog.expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog.opened); + + if (!watchdog.expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c == 'V'); + } + + /* Properly order writes across fork()ed processes */ + mutex_lock(&watchdog.lock); + watchdog.expect_close = expect_close; + mutex_unlock(&watchdog.lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog.ident, + sizeof(watchdog.ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) + watchdog_stop(); + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog.timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(int sioaddr) +{ + int wdt_conf, err = 0; + + /* No need to lock watchdog.lock here because no entry points + * into the module have been registered yet. + */ + watchdog.sioaddr = sioaddr; + watchdog.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + + snprintf(watchdog.ident.identity, + sizeof(watchdog.ident.identity), "%s watchdog", + f71808e_names[watchdog.type]); + + err = superio_enter(sioaddr); + if (err) + return err; + + wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); + watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS; + + superio_exit(sioaddr); + + err = watchdog_set_timeout(timeout); + if (err) + return err; + err = watchdog_set_pulse_width(pulse_width); + if (err) + return err; + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + return err; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME + ": starting timeout out of range\n"); + err = -EINVAL; + goto exit_miscdev; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_miscdev; + } + + mutex_lock(&watchdog.lock); + err = superio_enter(sioaddr); + if (err) + goto exit_unlock; + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(sioaddr); + mutex_unlock(&watchdog.lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %u sec\n", + start_withtimeout); + } + + return 0; + +exit_unlock: + mutex_unlock(&watchdog.lock); +exit_miscdev: + misc_deregister(&watchdog_miscdev); +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); + + return err; +} + +static int __init f71808e_find(int sioaddr) +{ + u16 devid; + int err = superio_enter(sioaddr); + if (err) + return err; + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) { + pr_debug(DRVNAME ": Not a Fintek device\n"); + goto exit; + } + + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); + switch (devid) { + case SIO_F71808_ID: + watchdog.type = f71808fg; + break; + case SIO_F71862_ID: + case SIO_F71882_ID: + case SIO_F71889_ID: + /* These have a watchdog, though it isn't implemented (yet). */ + err = -ENOSYS; + goto exit; + case SIO_F71858_ID: + /* Confirmed (by datasheet) not to have a watchdog. */ + err = -ENODEV; + goto exit; + default: + printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n", + (unsigned int)devid); + err = -ENODEV; + goto exit; + } + + printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n", + f71808e_names[watchdog.type], + (int)superio_inb(sioaddr, SIO_REG_DEVREV)); +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71808e_init(void) +{ + static const unsigned short addrs[] = { 0x2e, 0x4e }; + int err = -ENODEV; + int i; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71808e_find(addrs[i]); + if (err == 0) + break; + } + if (i == ARRAY_SIZE(addrs)) + return err; + + return watchdog_init(addrs[i]); +} + +static void __exit f71808e_exit(void) +{ + watchdog_stop(); + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); +} + +MODULE_DESCRIPTION("F71808E Watchdog Driver"); +MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>"); +MODULE_LICENSE("GPL"); + +module_init(f71808e_init); +module_exit(f71808e_exit); -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog @ 2010-03-25 13:17 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 13:17 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Add a new watchdog driver for the Fintek F71808E Super I/O chip. --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/f71808e_wdt.c | 726 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 738 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/f71808e_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index bdcdbd5..653896f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -382,6 +382,17 @@ config ALIM7101_WDT Most people will say N. +config F71808E_WDT + tristate "Fintek F71808E Watchdog" + depends on X86 && EXPERIMENTAL + help + This is the driver for the hardware watchdog on the Fintek + F71808E Super I/O chip. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called f71808e_wdt. + + config GEODE_WDT tristate "AMD Geode CS5535/CS5536 Watchdog" depends on CS5535_MFGPT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 5e3cb95..e2f308d 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c new file mode 100644 index 0000000..7d547a9 --- /dev/null +++ b/drivers/watchdog/f71808e_wdt.c @@ -0,0 +1,726 @@ +/*************************************************************************** + * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * + * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * + * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/uaccess.h> +#include <linux/watchdog.h> + +#define DRVNAME "f71808e_wdt" + +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ +#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ +#define SIO_F71858_ID 0x0507 /* Chipset ID */ +#define SIO_F71862_ID 0x0601 /* Chipset ID */ +#define SIO_F71882_ID 0x0541 /* Chipset ID */ +#define SIO_F71889_ID 0x0723 /* Chipset ID */ + +#define F71882FG_REG_START 0x01 + +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static unsigned int start_withtimeout; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; + +static const char *f71808e_names[] = { + "f71808fg", + "f71858fg", + "f71862fg", + "f71882fg", + "f71889fg", +}; + +/* Super-I/O Function prototypes */ +static inline int superio_inb(int base, int reg); +static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); +static inline int superio_enter(int base); +static inline void superio_select(int base, int ld); +static inline void superio_exit(int base); + +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data watchdog = { + .lock = __MUTEX_INITIALIZER(watchdog.lock), +}; + +/* Super I/O functions */ +static inline int superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int superio_inw(int base, int reg) +{ + int val; + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); + return val; +} + +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline int superio_enter(int base) +{ + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + + /* according to the datasheet the key must be send twice! */ + outb(SIO_UNLOCK_KEY, base); + outb(SIO_UNLOCK_KEY, base); + + return 0; +} + +static inline void superio_select(int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void superio_exit(int base) +{ + outb(SIO_LOCK_KEY, base); + release_region(base, 2); +} + +static int watchdog_set_timeout(int timeout) +{ + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog.lock); + + watchdog.timeout = timeout; + if (timeout > 0xff) { + watchdog.timer_val = DIV_ROUND_UP(timeout, 60); + watchdog.minutes_mode = true; + } else { + watchdog.timer_val = timeout; + watchdog.minutes_mode = false; + } + + mutex_unlock(&watchdog.lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + + if (pw <= 1) { + watchdog.pulse_val = 0; + } else if (pw <= 25) { + watchdog.pulse_val = 1; + } else if (pw <= 125) { + watchdog.pulse_val = 2; + } else if (pw <= 5000) { + watchdog.pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog.pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_keepalive(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + + if (watchdog.minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME, + watchdog.timeout); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + + /* Watchdog pin configuration */ + switch (watchdog.type) { + case f71808fg: + /* Set ping 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog.sioaddr, 0x2a, 3); + superio_clear_bit(watchdog.sioaddr, 0x2b, 3); + break; + + default: + /* + * 'default' label to shut up the compiler and catch + * programmer errors + */ + err = -ENODEV; + goto exit_superio; + } + + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog.pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog.sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_superio: + superio_exit(watchdog.sioaddr); +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_stop(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + mutex_lock(&watchdog.lock); + status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog.lock); + + return status; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog.opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog.opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog.expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog.opened); + + if (!watchdog.expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c = 'V'); + } + + /* Properly order writes across fork()ed processes */ + mutex_lock(&watchdog.lock); + watchdog.expect_close = expect_close; + mutex_unlock(&watchdog.lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog.ident, + sizeof(watchdog.ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) + watchdog_stop(); + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog.timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code = SYS_DOWN || code = SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(int sioaddr) +{ + int wdt_conf, err = 0; + + /* No need to lock watchdog.lock here because no entry points + * into the module have been registered yet. + */ + watchdog.sioaddr = sioaddr; + watchdog.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + + snprintf(watchdog.ident.identity, + sizeof(watchdog.ident.identity), "%s watchdog", + f71808e_names[watchdog.type]); + + err = superio_enter(sioaddr); + if (err) + return err; + + wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); + watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS; + + superio_exit(sioaddr); + + err = watchdog_set_timeout(timeout); + if (err) + return err; + err = watchdog_set_pulse_width(pulse_width); + if (err) + return err; + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + return err; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME + ": starting timeout out of range\n"); + err = -EINVAL; + goto exit_miscdev; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_miscdev; + } + + mutex_lock(&watchdog.lock); + err = superio_enter(sioaddr); + if (err) + goto exit_unlock; + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(sioaddr); + mutex_unlock(&watchdog.lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %u sec\n", + start_withtimeout); + } + + return 0; + +exit_unlock: + mutex_unlock(&watchdog.lock); +exit_miscdev: + misc_deregister(&watchdog_miscdev); +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); + + return err; +} + +static int __init f71808e_find(int sioaddr) +{ + u16 devid; + int err = superio_enter(sioaddr); + if (err) + return err; + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) { + pr_debug(DRVNAME ": Not a Fintek device\n"); + goto exit; + } + + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); + switch (devid) { + case SIO_F71808_ID: + watchdog.type = f71808fg; + break; + case SIO_F71862_ID: + case SIO_F71882_ID: + case SIO_F71889_ID: + /* These have a watchdog, though it isn't implemented (yet). */ + err = -ENOSYS; + goto exit; + case SIO_F71858_ID: + /* Confirmed (by datasheet) not to have a watchdog. */ + err = -ENODEV; + goto exit; + default: + printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n", + (unsigned int)devid); + err = -ENODEV; + goto exit; + } + + printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n", + f71808e_names[watchdog.type], + (int)superio_inb(sioaddr, SIO_REG_DEVREV)); +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71808e_init(void) +{ + static const unsigned short addrs[] = { 0x2e, 0x4e }; + int err = -ENODEV; + int i; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71808e_find(addrs[i]); + if (err = 0) + break; + } + if (i = ARRAY_SIZE(addrs)) + return err; + + return watchdog_init(addrs[i]); +} + +static void __exit f71808e_exit(void) +{ + watchdog_stop(); + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); +} + +MODULE_DESCRIPTION("F71808E Watchdog Driver"); +MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>"); +MODULE_LICENSE("GPL"); + +module_init(f71808e_init); +module_exit(f71808e_exit); -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E 2010-03-25 13:17 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog Giel van Schijndel @ 2010-03-30 9:06 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-30 9:06 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Wim Van Sebroeck, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 23428 bytes --] On Thu, Mar 25, 2010 at 02:17:43PM +0100, Giel van Schijndel wrote: > Add a new watchdog driver for the Fintek F71808E Super I/O chip. Updated patch: * fixes a bug where detection wouldn't function properly if a non-Fintek device was found (or a wrong Super I/O port chosen). * Add support for the F71882FG NOTE: This patch depends on patch [1] (applied in [2]) and patch [3]. [1] https://patchwork.kernel.org/patch/89023/ [2] http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commit;h=316607809324cc796c0809630b6ae8a768404296 [3] https://patchwork.kernel.org/patch/88235/ Patch after this line: ======================================================================== [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Add a new watchdog driver for the Fintek F71808E Super I/O chip. --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/f71808e_wdt.c | 767 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 779 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/f71808e_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 050ee14..d973105 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -366,6 +366,17 @@ config ALIM7101_WDT Most people will say N. +config F71808E_WDT + tristate "Fintek F71808E Watchdog" + depends on X86 && EXPERIMENTAL + help + This is the driver for the hardware watchdog on the Fintek + F71808E Super I/O chip. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called f71808e_wdt. + + config GEODE_WDT tristate "AMD Geode CS5535/CS5536 Watchdog" depends on CS5535_MFGPT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 475c611..6f0f3d9 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c new file mode 100644 index 0000000..b0314ea --- /dev/null +++ b/drivers/watchdog/f71808e_wdt.c @@ -0,0 +1,767 @@ +/*************************************************************************** + * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * + * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * + * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/uaccess.h> +#include <linux/watchdog.h> + +#define DRVNAME "f71808e_wdt" + +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ +#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ +#define SIO_F71858_ID 0x0507 /* Chipset ID */ +#define SIO_F71862_ID 0x0601 /* Chipset ID */ +#define SIO_F71882_ID 0x0541 /* Chipset ID */ +#define SIO_F71889_ID 0x0723 /* Chipset ID */ + +#define F71882FG_REG_START 0x01 + +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static unsigned int start_withtimeout; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; + +static const char *f71808e_names[] = { + "f71808fg", + "f71858fg", + "f71862fg", + "f71882fg", + "f71889fg", +}; + +/* Super-I/O Function prototypes */ +static inline int superio_inb(int base, int reg); +static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); +static inline int superio_enter(int base); +static inline void superio_select(int base, int ld); +static inline void superio_exit(int base); + +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data watchdog = { + .lock = __MUTEX_INITIALIZER(watchdog.lock), +}; + +/* Super I/O functions */ +static inline int superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int superio_inw(int base, int reg) +{ + int val; + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); + return val; +} + +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline int superio_enter(int base) +{ + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + + /* according to the datasheet the key must be send twice! */ + outb(SIO_UNLOCK_KEY, base); + outb(SIO_UNLOCK_KEY, base); + + return 0; +} + +static inline void superio_select(int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void superio_exit(int base) +{ + outb(SIO_LOCK_KEY, base); + release_region(base, 2); +} + +static int watchdog_set_timeout(int timeout) +{ + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog.lock); + + watchdog.timeout = timeout; + if (timeout > 0xff) { + watchdog.timer_val = DIV_ROUND_UP(timeout, 60); + watchdog.minutes_mode = true; + } else { + watchdog.timer_val = timeout; + watchdog.minutes_mode = false; + } + + mutex_unlock(&watchdog.lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + + if (pw <= 1) { + watchdog.pulse_val = 0; + } else if (pw <= 25) { + watchdog.pulse_val = 1; + } else if (pw <= 125) { + watchdog.pulse_val = 2; + } else if (pw <= 5000) { + watchdog.pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog.pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_keepalive(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (watchdog.minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME, + watchdog.timeout); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + /* Watchdog pin configuration */ + switch (watchdog.type) { + case f71808fg: + /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog.sioaddr, 0x2a, 3); + superio_clear_bit(watchdog.sioaddr, 0x2b, 3); + break; + + case f71882fg: + /* Set pin 56 to WDTRST# */ + superio_set_bit(watchdog.sioaddr, 0x29, 1); + break; + + default: + /* + * 'default' label to shut up the compiler and catch + * programmer errors + */ + err = -ENODEV; + goto exit_superio; + } + + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog.pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog.sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_superio: + superio_exit(watchdog.sioaddr); +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_stop(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + mutex_lock(&watchdog.lock); + status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog.lock); + + return status; +} + +static bool watchdog_is_running(void) +{ + /* + * if we fail to determine the watchdog's status assume it to be + * running to be on the safe side + */ + bool is_running = true; + + mutex_lock(&watchdog.lock); + if (superio_enter(watchdog.sioaddr)) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0)) + && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF) & F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return is_running; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog.opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog.opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog.expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog.opened); + + if (!watchdog.expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c == 'V'); + } + + /* Properly order writes across fork()ed processes */ + mutex_lock(&watchdog.lock); + watchdog.expect_close = expect_close; + mutex_unlock(&watchdog.lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog.ident, + sizeof(watchdog.ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) + watchdog_stop(); + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog.timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(int sioaddr) +{ + int wdt_conf, err = 0; + + /* No need to lock watchdog.lock here because no entry points + * into the module have been registered yet. + */ + watchdog.sioaddr = sioaddr; + watchdog.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + + snprintf(watchdog.ident.identity, + sizeof(watchdog.ident.identity), "%s watchdog", + f71808e_names[watchdog.type]); + + err = superio_enter(sioaddr); + if (err) + return err; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); + watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS; + + superio_exit(sioaddr); + + err = watchdog_set_timeout(timeout); + if (err) + return err; + err = watchdog_set_pulse_width(pulse_width); + if (err) + return err; + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + return err; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME + ": starting timeout out of range\n"); + err = -EINVAL; + goto exit_miscdev; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_miscdev; + } + + mutex_lock(&watchdog.lock); + err = superio_enter(sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(sioaddr); + mutex_unlock(&watchdog.lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %u sec\n", + start_withtimeout); + } + + return 0; + +exit_unlock: + mutex_unlock(&watchdog.lock); +exit_miscdev: + misc_deregister(&watchdog_miscdev); +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); + + return err; +} + +static int __init f71808e_find(int sioaddr) +{ + u16 devid; + int err = superio_enter(sioaddr); + if (err) + return err; + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) { + pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; + goto exit; + } + + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); + switch (devid) { + case SIO_F71808_ID: + watchdog.type = f71808fg; + break; + case SIO_F71882_ID: + watchdog.type = f71882fg; + break; + case SIO_F71862_ID: + case SIO_F71889_ID: + /* These have a watchdog, though it isn't implemented (yet). */ + err = -ENOSYS; + goto exit; + case SIO_F71858_ID: + /* Confirmed (by datasheet) not to have a watchdog. */ + err = -ENODEV; + goto exit; + default: + printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n", + (unsigned int)devid); + err = -ENODEV; + goto exit; + } + + printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n", + f71808e_names[watchdog.type], + (int)superio_inb(sioaddr, SIO_REG_DEVREV)); +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71808e_init(void) +{ + static const unsigned short addrs[] = { 0x2e, 0x4e }; + int err = -ENODEV; + int i; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71808e_find(addrs[i]); + if (err == 0) + break; + } + if (i == ARRAY_SIZE(addrs)) + return err; + + return watchdog_init(addrs[i]); +} + +static void __exit f71808e_exit(void) +{ + if (watchdog_is_running()) + { + printk(KERN_WARNING DRVNAME ": Watchdog timer still running, stopping it\n"); + watchdog_stop(); + } + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); +} + +MODULE_DESCRIPTION("F71808E Watchdog Driver"); +MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>"); +MODULE_LICENSE("GPL"); + +module_init(f71808e_init); +module_exit(f71808e_exit); -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new @ 2010-03-30 9:06 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-30 9:06 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Wim Van Sebroeck, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 23428 bytes --] On Thu, Mar 25, 2010 at 02:17:43PM +0100, Giel van Schijndel wrote: > Add a new watchdog driver for the Fintek F71808E Super I/O chip. Updated patch: * fixes a bug where detection wouldn't function properly if a non-Fintek device was found (or a wrong Super I/O port chosen). * Add support for the F71882FG NOTE: This patch depends on patch [1] (applied in [2]) and patch [3]. [1] https://patchwork.kernel.org/patch/89023/ [2] http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commit;h=316607809324cc796c0809630b6ae8a768404296 [3] https://patchwork.kernel.org/patch/88235/ Patch after this line: ======================================================================== [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Add a new watchdog driver for the Fintek F71808E Super I/O chip. --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/f71808e_wdt.c | 767 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 779 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/f71808e_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 050ee14..d973105 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -366,6 +366,17 @@ config ALIM7101_WDT Most people will say N. +config F71808E_WDT + tristate "Fintek F71808E Watchdog" + depends on X86 && EXPERIMENTAL + help + This is the driver for the hardware watchdog on the Fintek + F71808E Super I/O chip. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called f71808e_wdt. + + config GEODE_WDT tristate "AMD Geode CS5535/CS5536 Watchdog" depends on CS5535_MFGPT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 475c611..6f0f3d9 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c new file mode 100644 index 0000000..b0314ea --- /dev/null +++ b/drivers/watchdog/f71808e_wdt.c @@ -0,0 +1,767 @@ +/*************************************************************************** + * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * + * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * + * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/uaccess.h> +#include <linux/watchdog.h> + +#define DRVNAME "f71808e_wdt" + +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ +#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ +#define SIO_F71858_ID 0x0507 /* Chipset ID */ +#define SIO_F71862_ID 0x0601 /* Chipset ID */ +#define SIO_F71882_ID 0x0541 /* Chipset ID */ +#define SIO_F71889_ID 0x0723 /* Chipset ID */ + +#define F71882FG_REG_START 0x01 + +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static unsigned int start_withtimeout; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; + +static const char *f71808e_names[] = { + "f71808fg", + "f71858fg", + "f71862fg", + "f71882fg", + "f71889fg", +}; + +/* Super-I/O Function prototypes */ +static inline int superio_inb(int base, int reg); +static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); +static inline int superio_enter(int base); +static inline void superio_select(int base, int ld); +static inline void superio_exit(int base); + +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data watchdog = { + .lock = __MUTEX_INITIALIZER(watchdog.lock), +}; + +/* Super I/O functions */ +static inline int superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int superio_inw(int base, int reg) +{ + int val; + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); + return val; +} + +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline int superio_enter(int base) +{ + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + + /* according to the datasheet the key must be send twice! */ + outb(SIO_UNLOCK_KEY, base); + outb(SIO_UNLOCK_KEY, base); + + return 0; +} + +static inline void superio_select(int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void superio_exit(int base) +{ + outb(SIO_LOCK_KEY, base); + release_region(base, 2); +} + +static int watchdog_set_timeout(int timeout) +{ + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog.lock); + + watchdog.timeout = timeout; + if (timeout > 0xff) { + watchdog.timer_val = DIV_ROUND_UP(timeout, 60); + watchdog.minutes_mode = true; + } else { + watchdog.timer_val = timeout; + watchdog.minutes_mode = false; + } + + mutex_unlock(&watchdog.lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + + if (pw <= 1) { + watchdog.pulse_val = 0; + } else if (pw <= 25) { + watchdog.pulse_val = 1; + } else if (pw <= 125) { + watchdog.pulse_val = 2; + } else if (pw <= 5000) { + watchdog.pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog.pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_keepalive(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (watchdog.minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME, + watchdog.timeout); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + /* Watchdog pin configuration */ + switch (watchdog.type) { + case f71808fg: + /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog.sioaddr, 0x2a, 3); + superio_clear_bit(watchdog.sioaddr, 0x2b, 3); + break; + + case f71882fg: + /* Set pin 56 to WDTRST# */ + superio_set_bit(watchdog.sioaddr, 0x29, 1); + break; + + default: + /* + * 'default' label to shut up the compiler and catch + * programmer errors + */ + err = -ENODEV; + goto exit_superio; + } + + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog.pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog.sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_superio: + superio_exit(watchdog.sioaddr); +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_stop(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + mutex_lock(&watchdog.lock); + status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog.lock); + + return status; +} + +static bool watchdog_is_running(void) +{ + /* + * if we fail to determine the watchdog's status assume it to be + * running to be on the safe side + */ + bool is_running = true; + + mutex_lock(&watchdog.lock); + if (superio_enter(watchdog.sioaddr)) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0)) + && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF) & F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return is_running; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog.opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog.opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog.expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog.opened); + + if (!watchdog.expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c == 'V'); + } + + /* Properly order writes across fork()ed processes */ + mutex_lock(&watchdog.lock); + watchdog.expect_close = expect_close; + mutex_unlock(&watchdog.lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog.ident, + sizeof(watchdog.ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) + watchdog_stop(); + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog.timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(int sioaddr) +{ + int wdt_conf, err = 0; + + /* No need to lock watchdog.lock here because no entry points + * into the module have been registered yet. + */ + watchdog.sioaddr = sioaddr; + watchdog.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + + snprintf(watchdog.ident.identity, + sizeof(watchdog.ident.identity), "%s watchdog", + f71808e_names[watchdog.type]); + + err = superio_enter(sioaddr); + if (err) + return err; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); + watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS; + + superio_exit(sioaddr); + + err = watchdog_set_timeout(timeout); + if (err) + return err; + err = watchdog_set_pulse_width(pulse_width); + if (err) + return err; + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + return err; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME + ": starting timeout out of range\n"); + err = -EINVAL; + goto exit_miscdev; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_miscdev; + } + + mutex_lock(&watchdog.lock); + err = superio_enter(sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(sioaddr); + mutex_unlock(&watchdog.lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %u sec\n", + start_withtimeout); + } + + return 0; + +exit_unlock: + mutex_unlock(&watchdog.lock); +exit_miscdev: + misc_deregister(&watchdog_miscdev); +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); + + return err; +} + +static int __init f71808e_find(int sioaddr) +{ + u16 devid; + int err = superio_enter(sioaddr); + if (err) + return err; + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) { + pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; + goto exit; + } + + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); + switch (devid) { + case SIO_F71808_ID: + watchdog.type = f71808fg; + break; + case SIO_F71882_ID: + watchdog.type = f71882fg; + break; + case SIO_F71862_ID: + case SIO_F71889_ID: + /* These have a watchdog, though it isn't implemented (yet). */ + err = -ENOSYS; + goto exit; + case SIO_F71858_ID: + /* Confirmed (by datasheet) not to have a watchdog. */ + err = -ENODEV; + goto exit; + default: + printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n", + (unsigned int)devid); + err = -ENODEV; + goto exit; + } + + printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n", + f71808e_names[watchdog.type], + (int)superio_inb(sioaddr, SIO_REG_DEVREV)); +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71808e_init(void) +{ + static const unsigned short addrs[] = { 0x2e, 0x4e }; + int err = -ENODEV; + int i; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71808e_find(addrs[i]); + if (err == 0) + break; + } + if (i == ARRAY_SIZE(addrs)) + return err; + + return watchdog_init(addrs[i]); +} + +static void __exit f71808e_exit(void) +{ + if (watchdog_is_running()) + { + printk(KERN_WARNING DRVNAME ": Watchdog timer still running, stopping it\n"); + watchdog_stop(); + } + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); +} + +MODULE_DESCRIPTION("F71808E Watchdog Driver"); +MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>"); +MODULE_LICENSE("GPL"); + +module_init(f71808e_init); +module_exit(f71808e_exit); -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E 2010-03-30 9:06 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Giel van Schijndel @ 2010-05-20 7:52 ` Wim Van Sebroeck -1 siblings, 0 replies; 159+ messages in thread From: Wim Van Sebroeck @ 2010-05-20 7:52 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Wim Van Sebroeck, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, > On Thu, Mar 25, 2010 at 02:17:43PM +0100, Giel van Schijndel wrote: > > Add a new watchdog driver for the Fintek F71808E Super I/O chip. > > Updated patch: > * fixes a bug where detection wouldn't function properly if a > non-Fintek device was found (or a wrong Super I/O port chosen). > * Add support for the F71882FG > > NOTE: This patch depends on patch [1] (applied in [2]) and patch [3]. > > [1] https://patchwork.kernel.org/patch/89023/ > [2] http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commit;h=316607809324cc796c0809630b6ae8a768404296 > [3] https://patchwork.kernel.org/patch/88235/ Driver looks OK to me. Can't apply it before the I/O resource sharing is in place. How do you want to proceed? Kind regards, Wim. ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new @ 2010-05-20 7:52 ` Wim Van Sebroeck 0 siblings, 0 replies; 159+ messages in thread From: Wim Van Sebroeck @ 2010-05-20 7:52 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Wim Van Sebroeck, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, > On Thu, Mar 25, 2010 at 02:17:43PM +0100, Giel van Schijndel wrote: > > Add a new watchdog driver for the Fintek F71808E Super I/O chip. > > Updated patch: > * fixes a bug where detection wouldn't function properly if a > non-Fintek device was found (or a wrong Super I/O port chosen). > * Add support for the F71882FG > > NOTE: This patch depends on patch [1] (applied in [2]) and patch [3]. > > [1] https://patchwork.kernel.org/patch/89023/ > [2] http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commit;h16607809324cc796c0809630b6ae8a768404296 > [3] https://patchwork.kernel.org/patch/88235/ Driver looks OK to me. Can't apply it before the I/O resource sharing is in place. How do you want to proceed? Kind regards, Wim. _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E 2010-05-20 7:52 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Wim Van Sebroeck @ 2010-05-25 21:08 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-05-25 21:08 UTC (permalink / raw) To: Wim Van Sebroeck Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1035 bytes --] On Thu, May 20, 2010 at 09:52:29AM +0200, Wim Van Sebroeck wrote: >> On Thu, Mar 25, 2010 at 02:17:43PM +0100, Giel van Schijndel wrote: >> > Add a new watchdog driver for the Fintek F71808E Super I/O chip. >> >> Updated patch: >> * fixes a bug where detection wouldn't function properly if a >> non-Fintek device was found (or a wrong Super I/O port chosen). >> * Add support for the F71882FG >> >> NOTE: This patch depends on patch [1] (applied in [2]) and patch [3]. >> >> [1] https://patchwork.kernel.org/patch/89023/ >> [2] http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commit;h=316607809324cc796c0809630b6ae8a768404296 >> [3] https://patchwork.kernel.org/patch/88235/ > > Driver looks OK to me. Can't apply it before the I/O resource sharing > is in place. How do you want to proceed? I would think applying it to watchdog-next to apply it for the next kernel release (similar to Jean Delvare's linux-next). -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new @ 2010-05-25 21:08 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-05-25 21:08 UTC (permalink / raw) To: Wim Van Sebroeck Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 1035 bytes --] On Thu, May 20, 2010 at 09:52:29AM +0200, Wim Van Sebroeck wrote: >> On Thu, Mar 25, 2010 at 02:17:43PM +0100, Giel van Schijndel wrote: >> > Add a new watchdog driver for the Fintek F71808E Super I/O chip. >> >> Updated patch: >> * fixes a bug where detection wouldn't function properly if a >> non-Fintek device was found (or a wrong Super I/O port chosen). >> * Add support for the F71882FG >> >> NOTE: This patch depends on patch [1] (applied in [2]) and patch [3]. >> >> [1] https://patchwork.kernel.org/patch/89023/ >> [2] http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=commit;h=316607809324cc796c0809630b6ae8a768404296 >> [3] https://patchwork.kernel.org/patch/88235/ > > Driver looks OK to me. Can't apply it before the I/O resource sharing > is in place. How do you want to proceed? I would think applying it to watchdog-next to apply it for the next kernel release (similar to Jean Delvare's linux-next). -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E 2010-05-25 21:08 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Giel van Schijndel @ 2010-05-26 7:38 ` Wim Van Sebroeck -1 siblings, 0 replies; 159+ messages in thread From: Wim Van Sebroeck @ 2010-05-26 7:38 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, > > Driver looks OK to me. Can't apply it before the I/O resource sharing > > is in place. How do you want to proceed? > > I would think applying it to watchdog-next to apply it for the next > kernel release (similar to Jean Delvare's linux-next). Will add it after 2.6.35-rc1 is out then. Kind regards, Wim. ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new @ 2010-05-26 7:38 ` Wim Van Sebroeck 0 siblings, 0 replies; 159+ messages in thread From: Wim Van Sebroeck @ 2010-05-26 7:38 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, > > Driver looks OK to me. Can't apply it before the I/O resource sharing > > is in place. How do you want to proceed? > > I would think applying it to watchdog-next to apply it for the next > kernel release (similar to Jean Delvare's linux-next). Will add it after 2.6.35-rc1 is out then. Kind regards, Wim. _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E 2010-05-26 7:38 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Wim Van Sebroeck @ 2010-07-31 21:36 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-07-31 21:36 UTC (permalink / raw) To: Wim Van Sebroeck Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 514 bytes --] On Wed, May 26, 2010 at 09:38:43 +0200, Wim Van Sebroeck wrote: >>> Driver looks OK to me. Can't apply it before the I/O resource >>> sharing is in place. How do you want to proceed? >> >> I would think applying it to watchdog-next to apply it for the next >> kernel release (similar to Jean Delvare's linux-next). > > Will add it after 2.6.35-rc1 is out then. Sending a reminder, as 2.6.35-rc1 has been tagged for a while now. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new @ 2010-07-31 21:36 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-07-31 21:36 UTC (permalink / raw) To: Wim Van Sebroeck Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 514 bytes --] On Wed, May 26, 2010 at 09:38:43 +0200, Wim Van Sebroeck wrote: >>> Driver looks OK to me. Can't apply it before the I/O resource >>> sharing is in place. How do you want to proceed? >> >> I would think applying it to watchdog-next to apply it for the next >> kernel release (similar to Jean Delvare's linux-next). > > Will add it after 2.6.35-rc1 is out then. Sending a reminder, as 2.6.35-rc1 has been tagged for a while now. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-03-25 13:17 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock Giel van Schijndel @ 2010-03-25 21:10 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-25 21:10 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/25/2010 02:17 PM, Giel van Schijndel wrote: > Sleep while acquiring a resource lock on the Super I/O port. This should > prevent collisions from causing the hardware probe to fail with -EBUSY. > Looks good to me (assuming the previous patch in the series gets applied). Acked-by: Hans de Goede <hdegoede@redhat.com> Regards, hans > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 28 +++++++++++++++------------- > 1 files changed, 15 insertions(+), 13 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 7857ed3..e09416d 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; > /* Super-I/O Function prototypes */ > static inline int superio_inb(int base, int reg); > static inline int superio_inw(int base, int reg); > -static inline void superio_enter(int base); > +static inline int superio_enter(int base); > static inline void superio_select(int base, int ld); > static inline void superio_exit(int base); > > @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) > return val; > } > > -static inline void superio_enter(int base) > +static inline int superio_enter(int base) > { > + /* Don't step on other drivers' I/O space by accident */ > + if (!request_muxed_region(base, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)base); > + return -EBUSY; > + } > + > /* according to the datasheet the key must be send twice! */ > outb(SIO_UNLOCK_KEY, base); > outb(SIO_UNLOCK_KEY, base); > + > + return 0; > } > > static inline void superio_select(int base, int ld) > @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) > static inline void superio_exit(int base) > { > outb(SIO_LOCK_KEY, base); > + release_region(base, 2); > } > > static inline int fan_from_reg(u16 reg) > @@ -2239,17 +2249,10 @@ static int f71882fg_remove(struct platform_device *pdev) > static int __init f71882fg_find(int sioaddr, unsigned short *address, > struct f71882fg_sio_data *sio_data) > { > - int err = -ENODEV; > u16 devid; > - > - /* Don't step on other drivers' I/O space by accident */ > - if (!request_region(sioaddr, 2, DRVNAME)) { > - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > - (int)sioaddr); > - return -EBUSY; > - } > - > - superio_enter(sioaddr); > + int err = superio_enter(sioaddr); > + if (err) > + return err; > > devid = superio_inw(sioaddr, SIO_REG_MANID); > if (devid != SIO_FINTEK_ID) { > @@ -2306,7 +2309,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > - release_region(sioaddr, 2); > return err; > } > ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource @ 2010-03-25 21:10 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-25 21:10 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/25/2010 02:17 PM, Giel van Schijndel wrote: > Sleep while acquiring a resource lock on the Super I/O port. This should > prevent collisions from causing the hardware probe to fail with -EBUSY. > Looks good to me (assuming the previous patch in the series gets applied). Acked-by: Hans de Goede <hdegoede@redhat.com> Regards, hans > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 28 +++++++++++++++------------- > 1 files changed, 15 insertions(+), 13 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 7857ed3..e09416d 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; > /* Super-I/O Function prototypes */ > static inline int superio_inb(int base, int reg); > static inline int superio_inw(int base, int reg); > -static inline void superio_enter(int base); > +static inline int superio_enter(int base); > static inline void superio_select(int base, int ld); > static inline void superio_exit(int base); > > @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) > return val; > } > > -static inline void superio_enter(int base) > +static inline int superio_enter(int base) > { > + /* Don't step on other drivers' I/O space by accident */ > + if (!request_muxed_region(base, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)base); > + return -EBUSY; > + } > + > /* according to the datasheet the key must be send twice! */ > outb(SIO_UNLOCK_KEY, base); > outb(SIO_UNLOCK_KEY, base); > + > + return 0; > } > > static inline void superio_select(int base, int ld) > @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) > static inline void superio_exit(int base) > { > outb(SIO_LOCK_KEY, base); > + release_region(base, 2); > } > > static inline int fan_from_reg(u16 reg) > @@ -2239,17 +2249,10 @@ static int f71882fg_remove(struct platform_device *pdev) > static int __init f71882fg_find(int sioaddr, unsigned short *address, > struct f71882fg_sio_data *sio_data) > { > - int err = -ENODEV; > u16 devid; > - > - /* Don't step on other drivers' I/O space by accident */ > - if (!request_region(sioaddr, 2, DRVNAME)) { > - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > - (int)sioaddr); > - return -EBUSY; > - } > - > - superio_enter(sioaddr); > + int err = superio_enter(sioaddr); > + if (err) > + return err; > > devid = superio_inw(sioaddr, SIO_REG_MANID); > if (devid != SIO_FINTEK_ID) { > @@ -2306,7 +2309,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > - release_region(sioaddr, 2); > return err; > } > _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-03-25 13:17 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock Giel van Schijndel @ 2010-04-25 10:35 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-04-25 10:35 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 4102 bytes --] On Thu, Mar 25, 2010 at 02:17:42PM +0100, Giel van Schijndel wrote: > Sleep while acquiring a resource lock on the Super I/O port. This should > prevent collisions from causing the hardware probe to fail with -EBUSY. Fix a bug which caused f71882fg_find() to pretend to be succesfull on Super I/O ports which didn't have a Fintek chip attached. This was caused by returning 0 instead of -ENODEV, adding several 'err = -ENODEV' statements preceding the 'goto exit' statements fixed this. Patch follows this line: ======================================================================== Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++------------- 1 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..85512a7 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,21 +2249,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2280,6 +2284,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2290,12 +2295,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2306,7 +2313,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource @ 2010-04-25 10:35 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-04-25 10:35 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 4102 bytes --] On Thu, Mar 25, 2010 at 02:17:42PM +0100, Giel van Schijndel wrote: > Sleep while acquiring a resource lock on the Super I/O port. This should > prevent collisions from causing the hardware probe to fail with -EBUSY. Fix a bug which caused f71882fg_find() to pretend to be succesfull on Super I/O ports which didn't have a Fintek chip attached. This was caused by returning 0 instead of -ENODEV, adding several 'err = -ENODEV' statements preceding the 'goto exit' statements fixed this. Patch follows this line: ======================================================================== Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++------------- 1 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..85512a7 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,21 +2249,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2280,6 +2284,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2290,12 +2295,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2306,7 +2313,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-04-25 10:35 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource Giel van Schijndel @ 2010-07-31 21:21 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-07-31 21:21 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1083 bytes --] On Sun, Apr 25, 2010 at 12:35:40 +0200, Giel van Schijndel wrote: > On Thu, Mar 25, 2010 at 14:17:42 +0100, Giel van Schijndel wrote: >> Sleep while acquiring a resource lock on the Super I/O port. This >> should prevent collisions from causing the hardware probe to fail >> with -EBUSY. > > Fix a bug which caused f71882fg_find() to pretend to be succesfull on > Super I/O ports which didn't have a Fintek chip attached. This was > caused by returning 0 instead of -ENODEV, adding several 'err = > -ENODEV' statements preceding the 'goto exit' statements fixed this. > > Patch follows this line: > ======================================================================== > Sleep while acquiring a resource lock on the Super I/O port. This > should prevent collisions from causing the hardware probe to fail with > -EBUSY. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> All of this patch's dependencies now reside in mainline, so I'd like to "renew" the request for applying it. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource @ 2010-07-31 21:21 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-07-31 21:21 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 1083 bytes --] On Sun, Apr 25, 2010 at 12:35:40 +0200, Giel van Schijndel wrote: > On Thu, Mar 25, 2010 at 14:17:42 +0100, Giel van Schijndel wrote: >> Sleep while acquiring a resource lock on the Super I/O port. This >> should prevent collisions from causing the hardware probe to fail >> with -EBUSY. > > Fix a bug which caused f71882fg_find() to pretend to be succesfull on > Super I/O ports which didn't have a Fintek chip attached. This was > caused by returning 0 instead of -ENODEV, adding several 'err = > -ENODEV' statements preceding the 'goto exit' statements fixed this. > > Patch follows this line: > ======================================================================== > Sleep while acquiring a resource lock on the Super I/O port. This > should prevent collisions from causing the hardware probe to fail with > -EBUSY. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> All of this patch's dependencies now reside in mainline, so I'd like to "renew" the request for applying it. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-25 13:17 ` [lm-sensors] " Giel van Schijndel @ 2010-03-25 15:57 ` Alan Cox -1 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-25 15:57 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Thu, 25 Mar 2010 14:17:41 +0100 Giel van Schijndel <me@mortis.eu> wrote: > From: Alan Cox <alan@lxorguk.ukuu.org.uk> > > This patch was originally written by Alan Cox [1]. I only updated it to > apply correctly to Linus' current tree and changed IORESOURCE_MUXED's > value from 0x00200000 to 0x00400000 because the former has already been > taken in use since. > > [1] https://patchwork.kernel.org/patch/32397/ > > Patch after this line: > ======================================================================== > SuperIO devices share regions and use lock/unlock operations to chip > select. We therefore need to be able to request a resource and wait for > it to be freed by whichever other SuperIO device currently hogs it. > Right now you have to poll which is horrible. > > Add a MUXED field to IO port resources. If the MUXED field is set on the > resource and on the request (via request_muxed_region) then we block > until the previous owner of the muxed resource releases their region. > > This allows us to implement proper resource sharing and locking for > superio chips using code of the form > > enable_my_superio_dev() { > request_muxed_region(0x44, 0x02, "superio:watchdog"); > outb() ..sequence to enable chip > } > > disable_my_superio_dev() { > outb() .. sequence of disable chip > release_region(0x44, 0x02); > } > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > --- > include/linux/ioport.h | 4 +++- > kernel/resource.c | 14 +++++++++++++- > 2 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/include/linux/ioport.h b/include/linux/ioport.h > index 71ab79d..604fd29 100644 > --- a/include/linux/ioport.h > +++ b/include/linux/ioport.h > @@ -52,6 +52,7 @@ struct resource_list { > > #define IORESOURCE_MEM_64 0x00100000 > #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ > +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ > > #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ > #define IORESOURCE_DISABLED 0x10000000 > @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) > } > > /* Convenience shorthand with allocation */ > -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) > +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) > +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) > #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) > #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) > #define request_mem_region_exclusive(start,n,name) \ > diff --git a/kernel/resource.c b/kernel/resource.c > index 2d5be5d..1484180 100644 > --- a/kernel/resource.c > +++ b/kernel/resource.c > @@ -651,6 +651,8 @@ resource_size_t resource_alignment(struct resource *res) > * release_region releases a matching busy region. > */ > > +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); > + > /** > * __request_region - create a new busy resource region > * @parent: parent resource descriptor > @@ -663,6 +665,7 @@ struct resource * __request_region(struct resource *parent, > resource_size_t start, resource_size_t n, > const char *name, int flags) > { > + DECLARE_WAITQUEUE(wait, current); > struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); > > if (!res) > @@ -687,7 +690,14 @@ struct resource * __request_region(struct resource *parent, > if (!(conflict->flags & IORESOURCE_BUSY)) > continue; > } > - > + if (conflict->flags & flags & IORESOURCE_MUXED) { > + add_wait_queue(&muxed_resource_wait, &wait); > + write_unlock(&resource_lock); needs a set_current_state(TASK_UNINTERRUPTIBLE); here (error from my original test patch that I noticed re-reviewing it) ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-25 15:57 ` Alan Cox 0 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-25 15:57 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Thu, 25 Mar 2010 14:17:41 +0100 Giel van Schijndel <me@mortis.eu> wrote: > From: Alan Cox <alan@lxorguk.ukuu.org.uk> > > This patch was originally written by Alan Cox [1]. I only updated it to > apply correctly to Linus' current tree and changed IORESOURCE_MUXED's > value from 0x00200000 to 0x00400000 because the former has already been > taken in use since. > > [1] https://patchwork.kernel.org/patch/32397/ > > Patch after this line: > ==================================== > SuperIO devices share regions and use lock/unlock operations to chip > select. We therefore need to be able to request a resource and wait for > it to be freed by whichever other SuperIO device currently hogs it. > Right now you have to poll which is horrible. > > Add a MUXED field to IO port resources. If the MUXED field is set on the > resource and on the request (via request_muxed_region) then we block > until the previous owner of the muxed resource releases their region. > > This allows us to implement proper resource sharing and locking for > superio chips using code of the form > > enable_my_superio_dev() { > request_muxed_region(0x44, 0x02, "superio:watchdog"); > outb() ..sequence to enable chip > } > > disable_my_superio_dev() { > outb() .. sequence of disable chip > release_region(0x44, 0x02); > } > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > --- > include/linux/ioport.h | 4 +++- > kernel/resource.c | 14 +++++++++++++- > 2 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/include/linux/ioport.h b/include/linux/ioport.h > index 71ab79d..604fd29 100644 > --- a/include/linux/ioport.h > +++ b/include/linux/ioport.h > @@ -52,6 +52,7 @@ struct resource_list { > > #define IORESOURCE_MEM_64 0x00100000 > #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ > +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ > > #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ > #define IORESOURCE_DISABLED 0x10000000 > @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) > } > > /* Convenience shorthand with allocation */ > -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) > +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) > +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) > #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) > #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) > #define request_mem_region_exclusive(start,n,name) \ > diff --git a/kernel/resource.c b/kernel/resource.c > index 2d5be5d..1484180 100644 > --- a/kernel/resource.c > +++ b/kernel/resource.c > @@ -651,6 +651,8 @@ resource_size_t resource_alignment(struct resource *res) > * release_region releases a matching busy region. > */ > > +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); > + > /** > * __request_region - create a new busy resource region > * @parent: parent resource descriptor > @@ -663,6 +665,7 @@ struct resource * __request_region(struct resource *parent, > resource_size_t start, resource_size_t n, > const char *name, int flags) > { > + DECLARE_WAITQUEUE(wait, current); > struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); > > if (!res) > @@ -687,7 +690,14 @@ struct resource * __request_region(struct resource *parent, > if (!(conflict->flags & IORESOURCE_BUSY)) > continue; > } > - > + if (conflict->flags & flags & IORESOURCE_MUXED) { > + add_wait_queue(&muxed_resource_wait, &wait); > + write_unlock(&resource_lock); needs a set_current_state(TASK_UNINTERRUPTIBLE); here (error from my original test patch that I noticed re-reviewing it) _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-25 15:57 ` [lm-sensors] " Alan Cox @ 2010-03-25 18:03 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 18:03 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 5477 bytes --] On Thu, Mar 25, 2010 at 03:57:05PM +0000, Alan Cox wrote: > On Thu, 25 Mar 2010 14:17:41 +0100 Giel van Schijndel wrote: >> From: Alan Cox <alan@lxorguk.ukuu.org.uk> >> >> This patch was originally written by Alan Cox [1]. I only updated it to >> apply correctly to Linus' current tree and changed IORESOURCE_MUXED's >> value from 0x00200000 to 0x00400000 because the former has already been >> taken in use since. >> >> [1] https://patchwork.kernel.org/patch/32397/ >> >> Patch after this line: >> ======================================================================== >> ... snip ... >> @@ -687,7 +690,14 @@ struct resource * __request_region(struct resource *parent, >> if (!(conflict->flags & IORESOURCE_BUSY)) >> continue; >> } >> - >> + if (conflict->flags & flags & IORESOURCE_MUXED) { >> + add_wait_queue(&muxed_resource_wait, &wait); >> + write_unlock(&resource_lock); > > needs a set_current_state(TASK_UNINTERRUPTIBLE); here > > (error from my original test patch that I noticed re-reviewing it) Always fun reviewing your own code ;-) New patch attached. One question though. I did some reading in Documentation/memory-barriers.txt and think it is correct *not* to call set_current_state(TASK_INTERRUPTIBLE) after schedule() finishes. Could you confirm or deny that? Patch after this line: resource: shared I/O region support SuperIO devices share regions and use lock/unlock operations to chip select. We therefore need to be able to request a resource and wait for it to be freed by whichever other SuperIO device currently hogs it. Right now you have to poll which is horrible. Add a MUXED field to IO port resources. If the MUXED field is set on the resource and on the request (via request_muxed_region) then we block until the previous owner of the muxed resource releases their region. This allows us to implement proper resource sharing and locking for superio chips using code of the form enable_my_superio_dev() { request_muxed_region(0x44, 0x02, "superio:watchdog"); outb() ..sequence to enable chip } disable_my_superio_dev() { outb() .. sequence of disable chip release_region(0x44, 0x02); } Signed-off-by: Giel van Schijndel <me@mortis.eu> --- include/linux/ioport.h | 4 +++- kernel/resource.c | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 71ab79d..604fd29 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -52,6 +52,7 @@ struct resource_list { #define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_DISABLED 0x10000000 @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) } /* Convenience shorthand with allocation */ -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) #define request_mem_region_exclusive(start,n,name) \ diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..ab44c7f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -15,6 +15,7 @@ #include <linux/spinlock.h> #include <linux/fs.h> #include <linux/proc_fs.h> +#include <linux/sched.h> #include <linux/seq_file.h> #include <linux/device.h> #include <linux/pfn.h> @@ -651,6 +652,8 @@ resource_size_t resource_alignment(struct resource *res) * release_region releases a matching busy region. */ +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); + /** * __request_region - create a new busy resource region * @parent: parent resource descriptor @@ -663,6 +666,7 @@ struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags) { + DECLARE_WAITQUEUE(wait, current); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) @@ -687,7 +691,15 @@ struct resource * __request_region(struct resource *parent, if (!(conflict->flags & IORESOURCE_BUSY)) continue; } - + if (conflict->flags & flags & IORESOURCE_MUXED) { + add_wait_queue(&muxed_resource_wait, &wait); + write_unlock(&resource_lock); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + remove_wait_queue(&muxed_resource_wait, &wait); + write_lock(&resource_lock); + continue; + } /* Uhhuh, that didn't work out.. */ kfree(res); res = NULL; @@ -761,6 +773,8 @@ void __release_region(struct resource *parent, resource_size_t start, break; *p = res->sibling; write_unlock(&resource_lock); + if (res->flags & IORESOURCE_MUXED) + wake_up(&muxed_resource_wait); kfree(res); return; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-25 18:03 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-25 18:03 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 5477 bytes --] On Thu, Mar 25, 2010 at 03:57:05PM +0000, Alan Cox wrote: > On Thu, 25 Mar 2010 14:17:41 +0100 Giel van Schijndel wrote: >> From: Alan Cox <alan@lxorguk.ukuu.org.uk> >> >> This patch was originally written by Alan Cox [1]. I only updated it to >> apply correctly to Linus' current tree and changed IORESOURCE_MUXED's >> value from 0x00200000 to 0x00400000 because the former has already been >> taken in use since. >> >> [1] https://patchwork.kernel.org/patch/32397/ >> >> Patch after this line: >> ======================================================================== >> ... snip ... >> @@ -687,7 +690,14 @@ struct resource * __request_region(struct resource *parent, >> if (!(conflict->flags & IORESOURCE_BUSY)) >> continue; >> } >> - >> + if (conflict->flags & flags & IORESOURCE_MUXED) { >> + add_wait_queue(&muxed_resource_wait, &wait); >> + write_unlock(&resource_lock); > > needs a set_current_state(TASK_UNINTERRUPTIBLE); here > > (error from my original test patch that I noticed re-reviewing it) Always fun reviewing your own code ;-) New patch attached. One question though. I did some reading in Documentation/memory-barriers.txt and think it is correct *not* to call set_current_state(TASK_INTERRUPTIBLE) after schedule() finishes. Could you confirm or deny that? Patch after this line: resource: shared I/O region support SuperIO devices share regions and use lock/unlock operations to chip select. We therefore need to be able to request a resource and wait for it to be freed by whichever other SuperIO device currently hogs it. Right now you have to poll which is horrible. Add a MUXED field to IO port resources. If the MUXED field is set on the resource and on the request (via request_muxed_region) then we block until the previous owner of the muxed resource releases their region. This allows us to implement proper resource sharing and locking for superio chips using code of the form enable_my_superio_dev() { request_muxed_region(0x44, 0x02, "superio:watchdog"); outb() ..sequence to enable chip } disable_my_superio_dev() { outb() .. sequence of disable chip release_region(0x44, 0x02); } Signed-off-by: Giel van Schijndel <me@mortis.eu> --- include/linux/ioport.h | 4 +++- kernel/resource.c | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 71ab79d..604fd29 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -52,6 +52,7 @@ struct resource_list { #define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_DISABLED 0x10000000 @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) } /* Convenience shorthand with allocation */ -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) #define request_mem_region_exclusive(start,n,name) \ diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..ab44c7f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -15,6 +15,7 @@ #include <linux/spinlock.h> #include <linux/fs.h> #include <linux/proc_fs.h> +#include <linux/sched.h> #include <linux/seq_file.h> #include <linux/device.h> #include <linux/pfn.h> @@ -651,6 +652,8 @@ resource_size_t resource_alignment(struct resource *res) * release_region releases a matching busy region. */ +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); + /** * __request_region - create a new busy resource region * @parent: parent resource descriptor @@ -663,6 +666,7 @@ struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags) { + DECLARE_WAITQUEUE(wait, current); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) @@ -687,7 +691,15 @@ struct resource * __request_region(struct resource *parent, if (!(conflict->flags & IORESOURCE_BUSY)) continue; } - + if (conflict->flags & flags & IORESOURCE_MUXED) { + add_wait_queue(&muxed_resource_wait, &wait); + write_unlock(&resource_lock); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + remove_wait_queue(&muxed_resource_wait, &wait); + write_lock(&resource_lock); + continue; + } /* Uhhuh, that didn't work out.. */ kfree(res); res = NULL; @@ -761,6 +773,8 @@ void __release_region(struct resource *parent, resource_size_t start, break; *p = res->sibling; write_unlock(&resource_lock); + if (res->flags & IORESOURCE_MUXED) + wake_up(&muxed_resource_wait); kfree(res); return; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-25 18:03 ` [lm-sensors] " Giel van Schijndel @ 2010-03-25 18:16 ` Alan Cox -1 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-25 18:16 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel > Always fun reviewing your own code ;-) > > New patch attached. > > One question though. I did some reading in > Documentation/memory-barriers.txt and think it is correct *not* to call > set_current_state(TASK_INTERRUPTIBLE) after schedule() finishes. Could > you confirm or deny that? After the schedule() returns we will be in TASK_RUNNING which is where we want to be ... > + if (res->flags & IORESOURCE_MUXED) > + wake_up(&muxed_resource_wait); > kfree(res); > return; And you'll want a Signed-off-by: Alan Cox <alan@linux.intel.com> > } -- -- "Alan, I'm getting a bit worried about you." -- Linus Torvalds ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-25 18:16 ` Alan Cox 0 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-25 18:16 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel > Always fun reviewing your own code ;-) > > New patch attached. > > One question though. I did some reading in > Documentation/memory-barriers.txt and think it is correct *not* to call > set_current_state(TASK_INTERRUPTIBLE) after schedule() finishes. Could > you confirm or deny that? After the schedule() returns we will be in TASK_RUNNING which is where we want to be ... > + if (res->flags & IORESOURCE_MUXED) > + wake_up(&muxed_resource_wait); > kfree(res); > return; And you'll want a Signed-off-by: Alan Cox <alan@linux.intel.com> > } -- -- "Alan, I'm getting a bit worried about you." -- Linus Torvalds _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-25 18:16 ` [lm-sensors] " Alan Cox @ 2010-03-29 8:18 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-29 8:18 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Jesse Barnes, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 494 bytes --] On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: >> + if (res->flags & IORESOURCE_MUXED) >> + wake_up(&muxed_resource_wait); >> kfree(res); >> return; > > And you'll want a > > Signed-off-by: Alan Cox <alan@linux.intel.com> Yes, thanks. Anyone specific I should mail to get this patch applied? I don't see any entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 8:18 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-29 8:18 UTC (permalink / raw) To: Alan Cox Cc: Hans de Goede, Jean Delvare, Jonathan Cameron, Jesse Barnes, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 494 bytes --] On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: >> + if (res->flags & IORESOURCE_MUXED) >> + wake_up(&muxed_resource_wait); >> kfree(res); >> return; > > And you'll want a > > Signed-off-by: Alan Cox <alan@linux.intel.com> Yes, thanks. Anyone specific I should mail to get this patch applied? I don't see any entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 8:18 ` [lm-sensors] " Giel van Schijndel @ 2010-03-29 16:07 ` Jesse Barnes -1 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 16:07 UTC (permalink / raw) To: Giel van Schijndel Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 10:18:34 +0200 Giel van Schijndel <me@mortis.eu> wrote: > On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: > >> + if (res->flags & IORESOURCE_MUXED) > >> + wake_up(&muxed_resource_wait); > >> kfree(res); > >> return; > > > > And you'll want a > > > > Signed-off-by: Alan Cox <alan@linux.intel.com> > > Yes, thanks. > > Anyone specific I should mail to get this patch applied? I don't see any > entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. I can take it; sometimes Linus applies resource stuff directly though. Can you resend with the appropriate s-o-bs etc? Thanks, -- Jesse Barnes, Intel Open Source Technology Center ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 16:07 ` Jesse Barnes 0 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 16:07 UTC (permalink / raw) To: Giel van Schijndel Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 10:18:34 +0200 Giel van Schijndel <me@mortis.eu> wrote: > On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: > >> + if (res->flags & IORESOURCE_MUXED) > >> + wake_up(&muxed_resource_wait); > >> kfree(res); > >> return; > > > > And you'll want a > > > > Signed-off-by: Alan Cox <alan@linux.intel.com> > > Yes, thanks. > > Anyone specific I should mail to get this patch applied? I don't see any > entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. I can take it; sometimes Linus applies resource stuff directly though. Can you resend with the appropriate s-o-bs etc? Thanks, -- Jesse Barnes, Intel Open Source Technology Center _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 16:07 ` [lm-sensors] " Jesse Barnes @ 2010-03-29 17:38 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-29 17:38 UTC (permalink / raw) To: Jesse Barnes Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 5048 bytes --] On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: > On Mon, 29 Mar 2010 10:18:34 +0200> Giel van Schijndel wrote: >> On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: >>>> + if (res->flags & IORESOURCE_MUXED) >>>> + wake_up(&muxed_resource_wait); >>>> kfree(res); >>>> return; >>> >>> And you'll want a >>> >>> Signed-off-by: Alan Cox <alan@linux.intel.com> >> >> Yes, thanks. >> >> Anyone specific I should mail to get this patch applied? I don't see any >> entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. > > I can take it; sometimes Linus applies resource stuff directly though. > > Can you resend with the appropriate s-o-bs etc? Sure. (I copied Alan's signed-off-by from his reply to the patch) Patch after this line: ======================================================================== resource: shared I/O region support SuperIO devices share regions and use lock/unlock operations to chip select. We therefore need to be able to request a resource and wait for it to be freed by whichever other SuperIO device currently hogs it. Right now you have to poll which is horrible. Add a MUXED field to IO port resources. If the MUXED field is set on the resource and on the request (via request_muxed_region) then we block until the previous owner of the muxed resource releases their region. This allows us to implement proper resource sharing and locking for superio chips using code of the form enable_my_superio_dev() { request_muxed_region(0x44, 0x02, "superio:watchdog"); outb() ..sequence to enable chip } disable_my_superio_dev() { outb() .. sequence of disable chip release_region(0x44, 0x02); } Signed-off-by: Giel van Schijndel <me@mortis.eu> Signed-off-by: Alan Cox <alan@linux.intel.com> --- include/linux/ioport.h | 4 +++- kernel/resource.c | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 71ab79d..604fd29 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -52,6 +52,7 @@ struct resource_list { #define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_DISABLED 0x10000000 @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) } /* Convenience shorthand with allocation */ -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) #define request_mem_region_exclusive(start,n,name) \ diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..ab44c7f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -15,6 +15,7 @@ #include <linux/spinlock.h> #include <linux/fs.h> #include <linux/proc_fs.h> +#include <linux/sched.h> #include <linux/seq_file.h> #include <linux/device.h> #include <linux/pfn.h> @@ -651,6 +652,8 @@ resource_size_t resource_alignment(struct resource *res) * release_region releases a matching busy region. */ +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); + /** * __request_region - create a new busy resource region * @parent: parent resource descriptor @@ -663,6 +666,7 @@ struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags) { + DECLARE_WAITQUEUE(wait, current); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) @@ -687,7 +691,15 @@ struct resource * __request_region(struct resource *parent, if (!(conflict->flags & IORESOURCE_BUSY)) continue; } - + if (conflict->flags & flags & IORESOURCE_MUXED) { + add_wait_queue(&muxed_resource_wait, &wait); + write_unlock(&resource_lock); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + remove_wait_queue(&muxed_resource_wait, &wait); + write_lock(&resource_lock); + continue; + } /* Uhhuh, that didn't work out.. */ kfree(res); res = NULL; @@ -761,6 +773,8 @@ void __release_region(struct resource *parent, resource_size_t start, break; *p = res->sibling; write_unlock(&resource_lock); + if (res->flags & IORESOURCE_MUXED) + wake_up(&muxed_resource_wait); kfree(res); return; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 17:38 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-29 17:38 UTC (permalink / raw) To: Jesse Barnes Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 5048 bytes --] On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: > On Mon, 29 Mar 2010 10:18:34 +0200> Giel van Schijndel wrote: >> On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: >>>> + if (res->flags & IORESOURCE_MUXED) >>>> + wake_up(&muxed_resource_wait); >>>> kfree(res); >>>> return; >>> >>> And you'll want a >>> >>> Signed-off-by: Alan Cox <alan@linux.intel.com> >> >> Yes, thanks. >> >> Anyone specific I should mail to get this patch applied? I don't see any >> entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. > > I can take it; sometimes Linus applies resource stuff directly though. > > Can you resend with the appropriate s-o-bs etc? Sure. (I copied Alan's signed-off-by from his reply to the patch) Patch after this line: ======================================================================== resource: shared I/O region support SuperIO devices share regions and use lock/unlock operations to chip select. We therefore need to be able to request a resource and wait for it to be freed by whichever other SuperIO device currently hogs it. Right now you have to poll which is horrible. Add a MUXED field to IO port resources. If the MUXED field is set on the resource and on the request (via request_muxed_region) then we block until the previous owner of the muxed resource releases their region. This allows us to implement proper resource sharing and locking for superio chips using code of the form enable_my_superio_dev() { request_muxed_region(0x44, 0x02, "superio:watchdog"); outb() ..sequence to enable chip } disable_my_superio_dev() { outb() .. sequence of disable chip release_region(0x44, 0x02); } Signed-off-by: Giel van Schijndel <me@mortis.eu> Signed-off-by: Alan Cox <alan@linux.intel.com> --- include/linux/ioport.h | 4 +++- kernel/resource.c | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 71ab79d..604fd29 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -52,6 +52,7 @@ struct resource_list { #define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ +#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_DISABLED 0x10000000 @@ -141,7 +142,8 @@ static inline unsigned long resource_type(const struct resource *res) } /* Convenience shorthand with allocation */ -#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) +#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED) #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) #define request_mem_region_exclusive(start,n,name) \ diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..ab44c7f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -15,6 +15,7 @@ #include <linux/spinlock.h> #include <linux/fs.h> #include <linux/proc_fs.h> +#include <linux/sched.h> #include <linux/seq_file.h> #include <linux/device.h> #include <linux/pfn.h> @@ -651,6 +652,8 @@ resource_size_t resource_alignment(struct resource *res) * release_region releases a matching busy region. */ +static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait); + /** * __request_region - create a new busy resource region * @parent: parent resource descriptor @@ -663,6 +666,7 @@ struct resource * __request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags) { + DECLARE_WAITQUEUE(wait, current); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); if (!res) @@ -687,7 +691,15 @@ struct resource * __request_region(struct resource *parent, if (!(conflict->flags & IORESOURCE_BUSY)) continue; } - + if (conflict->flags & flags & IORESOURCE_MUXED) { + add_wait_queue(&muxed_resource_wait, &wait); + write_unlock(&resource_lock); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + remove_wait_queue(&muxed_resource_wait, &wait); + write_lock(&resource_lock); + continue; + } /* Uhhuh, that didn't work out.. */ kfree(res); res = NULL; @@ -761,6 +773,8 @@ void __release_region(struct resource *parent, resource_size_t start, break; *p = res->sibling; write_unlock(&resource_lock); + if (res->flags & IORESOURCE_MUXED) + wake_up(&muxed_resource_wait); kfree(res); return; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 17:38 ` [lm-sensors] " Giel van Schijndel @ 2010-03-29 17:44 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-29 17:44 UTC (permalink / raw) To: Jesse Barnes Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 809 bytes --] On Mon, Mar 29, 2010 at 07:38:00PM +0200, Giel van Schijndel wrote: > On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: >> I can take it; sometimes Linus applies resource stuff directly though. >> >> Can you resend with the appropriate s-o-bs etc? > > Sure. > > (I copied Alan's signed-off-by from his reply to the patch) > > Patch after this line: > ... snip ... PS (to be sure authorship is maintained): > This patch was originally written by Alan Cox [1]. I only updated it to > apply correctly to Linus' current tree and changed IORESOURCE_MUXED's > value from 0x00200000 to 0x00400000 because the former has already been > taken in use since. > > [1] https://patchwork.kernel.org/patch/32397/ -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 17:44 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-29 17:44 UTC (permalink / raw) To: Jesse Barnes Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 809 bytes --] On Mon, Mar 29, 2010 at 07:38:00PM +0200, Giel van Schijndel wrote: > On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: >> I can take it; sometimes Linus applies resource stuff directly though. >> >> Can you resend with the appropriate s-o-bs etc? > > Sure. > > (I copied Alan's signed-off-by from his reply to the patch) > > Patch after this line: > ... snip ... PS (to be sure authorship is maintained): > This patch was originally written by Alan Cox [1]. I only updated it to > apply correctly to Linus' current tree and changed IORESOURCE_MUXED's > value from 0x00200000 to 0x00400000 because the former has already been > taken in use since. > > [1] https://patchwork.kernel.org/patch/32397/ -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 17:38 ` [lm-sensors] " Giel van Schijndel @ 2010-03-29 17:45 ` H. Peter Anvin -1 siblings, 0 replies; 159+ messages in thread From: H. Peter Anvin @ 2010-03-29 17:45 UTC (permalink / raw) To: Giel van Schijndel Cc: Jesse Barnes, Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On 03/29/2010 10:38 AM, Giel van Schijndel wrote: > > Patch after this line: > ======================================================================== > resource: shared I/O region support > > SuperIO devices share regions and use lock/unlock operations to chip > select. We therefore need to be able to request a resource and wait for > it to be freed by whichever other SuperIO device currently hogs it. > Right now you have to poll which is horrible. > > Add a MUXED field to IO port resources. If the MUXED field is set on the > resource and on the request (via request_muxed_region) then we block > until the previous owner of the muxed resource releases their region. > > This allows us to implement proper resource sharing and locking for > superio chips using code of the form > > enable_my_superio_dev() { > request_muxed_region(0x44, 0x02, "superio:watchdog"); > outb() ..sequence to enable chip > } > > disable_my_superio_dev() { > outb() .. sequence of disable chip > release_region(0x44, 0x02); > } > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > Signed-off-by: Alan Cox <alan@linux.intel.com> I have to question this approach a bit. I would much rather see this as a two-step process, where multiple devices request the same region with a "sharable" flag, and then have a mutex associated with the struct resource (perhaps we need an outer container called "struct muxed_resource" or some such.) What I *really* object to with this patch is that it inherently assumes that there is only one multiplexed resource in the entire system... but of course nowhere enforces that. -hpa ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 17:45 ` H. Peter Anvin 0 siblings, 0 replies; 159+ messages in thread From: H. Peter Anvin @ 2010-03-29 17:45 UTC (permalink / raw) To: Giel van Schijndel Cc: Jesse Barnes, Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On 03/29/2010 10:38 AM, Giel van Schijndel wrote: > > Patch after this line: > ==================================== > resource: shared I/O region support > > SuperIO devices share regions and use lock/unlock operations to chip > select. We therefore need to be able to request a resource and wait for > it to be freed by whichever other SuperIO device currently hogs it. > Right now you have to poll which is horrible. > > Add a MUXED field to IO port resources. If the MUXED field is set on the > resource and on the request (via request_muxed_region) then we block > until the previous owner of the muxed resource releases their region. > > This allows us to implement proper resource sharing and locking for > superio chips using code of the form > > enable_my_superio_dev() { > request_muxed_region(0x44, 0x02, "superio:watchdog"); > outb() ..sequence to enable chip > } > > disable_my_superio_dev() { > outb() .. sequence of disable chip > release_region(0x44, 0x02); > } > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > Signed-off-by: Alan Cox <alan@linux.intel.com> I have to question this approach a bit. I would much rather see this as a two-step process, where multiple devices request the same region with a "sharable" flag, and then have a mutex associated with the struct resource (perhaps we need an outer container called "struct muxed_resource" or some such.) What I *really* object to with this patch is that it inherently assumes that there is only one multiplexed resource in the entire system... but of course nowhere enforces that. -hpa _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 17:45 ` [lm-sensors] " H. Peter Anvin @ 2010-03-29 18:06 ` Jesse Barnes -1 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 18:06 UTC (permalink / raw) To: H. Peter Anvin Cc: Giel van Schijndel, Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 10:45:35 -0700 "H. Peter Anvin" <hpa@zytor.com> wrote: > On 03/29/2010 10:38 AM, Giel van Schijndel wrote: > > > > Patch after this line: > > ======================================================================== > > resource: shared I/O region support > > > > SuperIO devices share regions and use lock/unlock operations to chip > > select. We therefore need to be able to request a resource and wait for > > it to be freed by whichever other SuperIO device currently hogs it. > > Right now you have to poll which is horrible. > > > > Add a MUXED field to IO port resources. If the MUXED field is set on the > > resource and on the request (via request_muxed_region) then we block > > until the previous owner of the muxed resource releases their region. > > > > This allows us to implement proper resource sharing and locking for > > superio chips using code of the form > > > > enable_my_superio_dev() { > > request_muxed_region(0x44, 0x02, "superio:watchdog"); > > outb() ..sequence to enable chip > > } > > > > disable_my_superio_dev() { > > outb() .. sequence of disable chip > > release_region(0x44, 0x02); > > } > > > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > > Signed-off-by: Alan Cox <alan@linux.intel.com> > > I have to question this approach a bit. > > I would much rather see this as a two-step process, where multiple > devices request the same region with a "sharable" flag, and then have a > mutex associated with the struct resource (perhaps we need an outer > container called "struct muxed_resource" or some such.) > > What I *really* object to with this patch is that it inherently assumes > that there is only one multiplexed resource in the entire system... but > of course nowhere enforces that. Well that does keep it simple, and with just one user that's probably best. But why not use the common bus driver method? Muxing at the resource level only seems to solve part of the problem... It doesn't guarantee for example that driver A does something to a shared region that breaks driver B; it just makes sure they don't access the same region at the same time. -- Jesse Barnes, Intel Open Source Technology Center ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 18:06 ` Jesse Barnes 0 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 18:06 UTC (permalink / raw) To: H. Peter Anvin Cc: Giel van Schijndel, Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 10:45:35 -0700 "H. Peter Anvin" <hpa@zytor.com> wrote: > On 03/29/2010 10:38 AM, Giel van Schijndel wrote: > > > > Patch after this line: > > ==================================== > > resource: shared I/O region support > > > > SuperIO devices share regions and use lock/unlock operations to chip > > select. We therefore need to be able to request a resource and wait for > > it to be freed by whichever other SuperIO device currently hogs it. > > Right now you have to poll which is horrible. > > > > Add a MUXED field to IO port resources. If the MUXED field is set on the > > resource and on the request (via request_muxed_region) then we block > > until the previous owner of the muxed resource releases their region. > > > > This allows us to implement proper resource sharing and locking for > > superio chips using code of the form > > > > enable_my_superio_dev() { > > request_muxed_region(0x44, 0x02, "superio:watchdog"); > > outb() ..sequence to enable chip > > } > > > > disable_my_superio_dev() { > > outb() .. sequence of disable chip > > release_region(0x44, 0x02); > > } > > > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > > Signed-off-by: Alan Cox <alan@linux.intel.com> > > I have to question this approach a bit. > > I would much rather see this as a two-step process, where multiple > devices request the same region with a "sharable" flag, and then have a > mutex associated with the struct resource (perhaps we need an outer > container called "struct muxed_resource" or some such.) > > What I *really* object to with this patch is that it inherently assumes > that there is only one multiplexed resource in the entire system... but > of course nowhere enforces that. Well that does keep it simple, and with just one user that's probably best. But why not use the common bus driver method? Muxing at the resource level only seems to solve part of the problem... It doesn't guarantee for example that driver A does something to a shared region that breaks driver B; it just makes sure they don't access the same region at the same time. -- Jesse Barnes, Intel Open Source Technology Center _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 18:06 ` [lm-sensors] " Jesse Barnes @ 2010-03-29 18:17 ` H. Peter Anvin -1 siblings, 0 replies; 159+ messages in thread From: H. Peter Anvin @ 2010-03-29 18:17 UTC (permalink / raw) To: Jesse Barnes Cc: Giel van Schijndel, Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On 03/29/2010 11:06 AM, Jesse Barnes wrote: >> >> I have to question this approach a bit. >> >> I would much rather see this as a two-step process, where multiple >> devices request the same region with a "sharable" flag, and then have a >> mutex associated with the struct resource (perhaps we need an outer >> container called "struct muxed_resource" or some such.) >> >> What I *really* object to with this patch is that it inherently assumes >> that there is only one multiplexed resource in the entire system... but >> of course nowhere enforces that. > > Well that does keep it simple, and with just one user that's probably > best. > > But why not use the common bus driver method? Muxing at the resource > level only seems to solve part of the problem... It doesn't guarantee > for example that driver A does something to a shared region that breaks > driver B; it just makes sure they don't access the same region at the > same time. > The common bus driver method is the obvious thing to do, but it would presumably be greatly helped by librarization. -hpa ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 18:17 ` H. Peter Anvin 0 siblings, 0 replies; 159+ messages in thread From: H. Peter Anvin @ 2010-03-29 18:17 UTC (permalink / raw) To: Jesse Barnes Cc: Giel van Schijndel, Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On 03/29/2010 11:06 AM, Jesse Barnes wrote: >> >> I have to question this approach a bit. >> >> I would much rather see this as a two-step process, where multiple >> devices request the same region with a "sharable" flag, and then have a >> mutex associated with the struct resource (perhaps we need an outer >> container called "struct muxed_resource" or some such.) >> >> What I *really* object to with this patch is that it inherently assumes >> that there is only one multiplexed resource in the entire system... but >> of course nowhere enforces that. > > Well that does keep it simple, and with just one user that's probably > best. > > But why not use the common bus driver method? Muxing at the resource > level only seems to solve part of the problem... It doesn't guarantee > for example that driver A does something to a shared region that breaks > driver B; it just makes sure they don't access the same region at the > same time. > The common bus driver method is the obvious thing to do, but it would presumably be greatly helped by librarization. -hpa _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 18:06 ` [lm-sensors] " Jesse Barnes @ 2010-03-29 18:29 ` Alan Cox -1 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-29 18:29 UTC (permalink / raw) To: Jesse Barnes Cc: H. Peter Anvin, Giel van Schijndel, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel > Well that does keep it simple, and with just one user that's probably > best. > > But why not use the common bus driver method? Muxing at the resource > level only seems to solve part of the problem... It doesn't guarantee > for example that driver A does something to a shared region that breaks > driver B; it just makes sure they don't access the same region at the > same time. The obvious reason for not doing that kind of grand over-engineering is that you are assuming the devices involved are remotely related. On quite a few systems we have a collection of superio config interfaces on random low ports all with their own lock/unlock rituals. They range from parallel devices to watchdogs and god knows what else. Right now we have various bits of driver code (parport is a good one) that exist on a cross fingers, pray and poke model. It would be nice to fix that. For most super I/O devices the muxing is basically a glorified chip select line. There isn't any structure to impose over it. Where you have structure there are better ways to do it, but one does not exclude the other. Alan ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 18:29 ` Alan Cox 0 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-29 18:29 UTC (permalink / raw) To: Jesse Barnes Cc: H. Peter Anvin, Giel van Schijndel, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel > Well that does keep it simple, and with just one user that's probably > best. > > But why not use the common bus driver method? Muxing at the resource > level only seems to solve part of the problem... It doesn't guarantee > for example that driver A does something to a shared region that breaks > driver B; it just makes sure they don't access the same region at the > same time. The obvious reason for not doing that kind of grand over-engineering is that you are assuming the devices involved are remotely related. On quite a few systems we have a collection of superio config interfaces on random low ports all with their own lock/unlock rituals. They range from parallel devices to watchdogs and god knows what else. Right now we have various bits of driver code (parport is a good one) that exist on a cross fingers, pray and poke model. It would be nice to fix that. For most super I/O devices the muxing is basically a glorified chip select line. There isn't any structure to impose over it. Where you have structure there are better ways to do it, but one does not exclude the other. Alan _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 18:29 ` [lm-sensors] " Alan Cox @ 2010-04-02 20:29 ` Jesse Barnes -1 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-04-02 20:29 UTC (permalink / raw) To: Alan Cox Cc: H. Peter Anvin, Giel van Schijndel, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 19:29:57 +0100 Alan Cox <alan@lxorguk.ukuu.org.uk> wrote: > > Well that does keep it simple, and with just one user that's probably > > best. > > > > But why not use the common bus driver method? Muxing at the resource > > level only seems to solve part of the problem... It doesn't guarantee > > for example that driver A does something to a shared region that breaks > > driver B; it just makes sure they don't access the same region at the > > same time. > > The obvious reason for not doing that kind of grand over-engineering is > that you are assuming the devices involved are remotely related. On quite > a few systems we have a collection of superio config interfaces on random > low ports all with their own lock/unlock rituals. They range from > parallel devices to watchdogs and god knows what else. Right now we have > various bits of driver code (parport is a good one) that exist on a cross > fingers, pray and poke model. It would be nice to fix that. > > For most super I/O devices the muxing is basically a glorified chip select > line. There isn't any structure to impose over it. Where you have > structure there are better ways to do it, but one does not exclude the > other. Well I'm not sure such over-engineering would be "grand", but it does seem like overkill for the devices you're covering here. At any rate, the patch is in my linux-next tree, so it'll head to Linus next merge cycle unless some big new objections arise. -- Jesse Barnes, Intel Open Source Technology Center ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-04-02 20:29 ` Jesse Barnes 0 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-04-02 20:29 UTC (permalink / raw) To: Alan Cox Cc: H. Peter Anvin, Giel van Schijndel, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 19:29:57 +0100 Alan Cox <alan@lxorguk.ukuu.org.uk> wrote: > > Well that does keep it simple, and with just one user that's probably > > best. > > > > But why not use the common bus driver method? Muxing at the resource > > level only seems to solve part of the problem... It doesn't guarantee > > for example that driver A does something to a shared region that breaks > > driver B; it just makes sure they don't access the same region at the > > same time. > > The obvious reason for not doing that kind of grand over-engineering is > that you are assuming the devices involved are remotely related. On quite > a few systems we have a collection of superio config interfaces on random > low ports all with their own lock/unlock rituals. They range from > parallel devices to watchdogs and god knows what else. Right now we have > various bits of driver code (parport is a good one) that exist on a cross > fingers, pray and poke model. It would be nice to fix that. > > For most super I/O devices the muxing is basically a glorified chip select > line. There isn't any structure to impose over it. Where you have > structure there are better ways to do it, but one does not exclude the > other. Well I'm not sure such over-engineering would be "grand", but it does seem like overkill for the devices you're covering here. At any rate, the patch is in my linux-next tree, so it'll head to Linus next merge cycle unless some big new objections arise. -- Jesse Barnes, Intel Open Source Technology Center _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 17:45 ` [lm-sensors] " H. Peter Anvin @ 2010-03-29 18:39 ` Alan Cox -1 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-29 18:39 UTC (permalink / raw) To: H. Peter Anvin Cc: Giel van Schijndel, Jesse Barnes, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel > What I *really* object to with this patch is that it inherently assumes > that there is only one multiplexed resource in the entire system... but > of course nowhere enforces that. The patch does nothing of the sort. Not unless there is a bug I am not seeing anyway. It does assume nobody tries to grab pairs of such resources as it doesn't do deadlock avoidance. It's now a shared resource patch however, its a multiplexor patch and that is precisely why it is called MUX not SHARED or OVERLAY Alan ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 18:39 ` Alan Cox 0 siblings, 0 replies; 159+ messages in thread From: Alan Cox @ 2010-03-29 18:39 UTC (permalink / raw) To: H. Peter Anvin Cc: Giel van Schijndel, Jesse Barnes, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel > What I *really* object to with this patch is that it inherently assumes > that there is only one multiplexed resource in the entire system... but > of course nowhere enforces that. The patch does nothing of the sort. Not unless there is a bug I am not seeing anyway. It does assume nobody tries to grab pairs of such resources as it doesn't do deadlock avoidance. It's now a shared resource patch however, its a multiplexor patch and that is precisely why it is called MUX not SHARED or OVERLAY Alan _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 18:39 ` [lm-sensors] " Alan Cox @ 2010-03-29 18:56 ` H. Peter Anvin -1 siblings, 0 replies; 159+ messages in thread From: H. Peter Anvin @ 2010-03-29 18:56 UTC (permalink / raw) To: Alan Cox Cc: Giel van Schijndel, Jesse Barnes, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On 03/29/2010 11:39 AM, Alan Cox wrote: >> What I *really* object to with this patch is that it inherently assumes >> that there is only one multiplexed resource in the entire system... but >> of course nowhere enforces that. > > The patch does nothing of the sort. Not unless there is a bug I am not > seeing anyway. It does assume nobody tries to grab pairs of such > resources as it doesn't do deadlock avoidance. > > It's now a shared resource patch however, its a multiplexor patch and > that is precisely why it is called MUX not SHARED or OVERLAY > Alan Sorry, I missed the "continue", which of course handles the situation I was worried about. The shared wait queue is a bit inelegant, but if it turns out to be a bottleneck in real life then we either have bigger problems or it can be addressed at that time. -hpa ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 18:56 ` H. Peter Anvin 0 siblings, 0 replies; 159+ messages in thread From: H. Peter Anvin @ 2010-03-29 18:56 UTC (permalink / raw) To: Alan Cox Cc: Giel van Schijndel, Jesse Barnes, Hans de Goede, Jean Delvare, Jonathan Cameron, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On 03/29/2010 11:39 AM, Alan Cox wrote: >> What I *really* object to with this patch is that it inherently assumes >> that there is only one multiplexed resource in the entire system... but >> of course nowhere enforces that. > > The patch does nothing of the sort. Not unless there is a bug I am not > seeing anyway. It does assume nobody tries to grab pairs of such > resources as it doesn't do deadlock avoidance. > > It's now a shared resource patch however, its a multiplexor patch and > that is precisely why it is called MUX not SHARED or OVERLAY > Alan Sorry, I missed the "continue", which of course handles the situation I was worried about. The shared wait queue is a bit inelegant, but if it turns out to be a bottleneck in real life then we either have bigger problems or it can be addressed at that time. -hpa _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 17:38 ` [lm-sensors] " Giel van Schijndel @ 2010-03-29 17:59 ` Jesse Barnes -1 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 17:59 UTC (permalink / raw) To: Giel van Schijndel Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 19:38:00 +0200 Giel van Schijndel <me@mortis.eu> wrote: > On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: > > On Mon, 29 Mar 2010 10:18:34 +0200> Giel van Schijndel wrote: > >> On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: > >>>> + if (res->flags & IORESOURCE_MUXED) > >>>> + wake_up(&muxed_resource_wait); > >>>> kfree(res); > >>>> return; > >>> > >>> And you'll want a > >>> > >>> Signed-off-by: Alan Cox <alan@linux.intel.com> > >> > >> Yes, thanks. > >> > >> Anyone specific I should mail to get this patch applied? I don't see any > >> entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. > > > > I can take it; sometimes Linus applies resource stuff directly though. > > > > Can you resend with the appropriate s-o-bs etc? > > Sure. > > (I copied Alan's signed-off-by from his reply to the patch) Applied to my for-linus branch with Alan as author. Thanks, -- Jesse Barnes, Intel Open Source Technology Center ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 17:59 ` Jesse Barnes 0 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 17:59 UTC (permalink / raw) To: Giel van Schijndel Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 19:38:00 +0200 Giel van Schijndel <me@mortis.eu> wrote: > On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: > > On Mon, 29 Mar 2010 10:18:34 +0200> Giel van Schijndel wrote: > >> On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: > >>>> + if (res->flags & IORESOURCE_MUXED) > >>>> + wake_up(&muxed_resource_wait); > >>>> kfree(res); > >>>> return; > >>> > >>> And you'll want a > >>> > >>> Signed-off-by: Alan Cox <alan@linux.intel.com> > >> > >> Yes, thanks. > >> > >> Anyone specific I should mail to get this patch applied? I don't see any > >> entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. > > > > I can take it; sometimes Linus applies resource stuff directly though. > > > > Can you resend with the appropriate s-o-bs etc? > > Sure. > > (I copied Alan's signed-off-by from his reply to the patch) Applied to my for-linus branch with Alan as author. Thanks, -- Jesse Barnes, Intel Open Source Technology Center _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/3] resource: shared I/O region support 2010-03-29 17:38 ` [lm-sensors] " Giel van Schijndel @ 2010-03-29 17:59 ` Jesse Barnes -1 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 17:59 UTC (permalink / raw) To: Giel van Schijndel Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 19:38:00 +0200 Giel van Schijndel <me@mortis.eu> wrote: > On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: > > On Mon, 29 Mar 2010 10:18:34 +0200> Giel van Schijndel wrote: > >> On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: > >>>> + if (res->flags & IORESOURCE_MUXED) > >>>> + wake_up(&muxed_resource_wait); > >>>> kfree(res); > >>>> return; > >>> > >>> And you'll want a > >>> > >>> Signed-off-by: Alan Cox <alan@linux.intel.com> > >> > >> Yes, thanks. > >> > >> Anyone specific I should mail to get this patch applied? I don't see any > >> entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. > > > > I can take it; sometimes Linus applies resource stuff directly though. > > > > Can you resend with the appropriate s-o-bs etc? > > Sure. > > (I copied Alan's signed-off-by from his reply to the patch) ...looking again I see it should be in my linux-next branch instead, I'll move it over. Thanks, -- Jesse Barnes, Intel Open Source Technology Center ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/3] resource: shared I/O region support @ 2010-03-29 17:59 ` Jesse Barnes 0 siblings, 0 replies; 159+ messages in thread From: Jesse Barnes @ 2010-03-29 17:59 UTC (permalink / raw) To: Giel van Schijndel Cc: Alan Cox, Hans de Goede, Jean Delvare, Jonathan Cameron, H. Peter Anvin, Andrew Morton, Bjorn Helgaas, Dominik Brodowski, Laurens Leemans, lm-sensors, linux-kernel On Mon, 29 Mar 2010 19:38:00 +0200 Giel van Schijndel <me@mortis.eu> wrote: > On Mon, Mar 29, 2010 at 09:07:13AM -0700, Jesse Barnes wrote: > > On Mon, 29 Mar 2010 10:18:34 +0200> Giel van Schijndel wrote: > >> On Thu, Mar 25, 2010 at 06:16:33PM +0000, Alan Cox wrote: > >>>> + if (res->flags & IORESOURCE_MUXED) > >>>> + wake_up(&muxed_resource_wait); > >>>> kfree(res); > >>>> return; > >>> > >>> And you'll want a > >>> > >>> Signed-off-by: Alan Cox <alan@linux.intel.com> > >> > >> Yes, thanks. > >> > >> Anyone specific I should mail to get this patch applied? I don't see any > >> entry in MAINTAINERS for kernel/resource.c or include/linux/resource.h. > > > > I can take it; sometimes Linus applies resource stuff directly though. > > > > Can you resend with the appropriate s-o-bs etc? > > Sure. > > (I copied Alan's signed-off-by from his reply to the patch) ...looking again I see it should be in my linux-next branch instead, I'll move it over. Thanks, -- Jesse Barnes, Intel Open Source Technology Center _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 2/4] hwmon: f71882fg: prepare for addition of watchdog support 2010-03-23 23:12 ` [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition of Giel van Schijndel @ 2010-03-24 8:26 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:26 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Ack. Acked-by: Hans de Goede <hdegoede@redhat.com> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Rename the `address' variable that's used in some places to hwmon_addr > to indicate it refers to the hardware monitor (HWMON in datasheet) > "logical device" of the chip. > > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 24 ++++++++++++------------ > 1 files changed, 12 insertions(+), 12 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index b290b87..7b31e14 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2233,7 +2233,7 @@ static int f71882fg_remove(struct platform_device *pdev) > return 0; > } > > -static int __init f71882fg_find(int sioaddr, unsigned short *address, > +static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, > struct f71882fg_sio_data *sio_data) > { > int err = -ENODEV; > @@ -2290,16 +2290,16 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > goto exit; > } > > - *address = superio_inw(sioaddr, SIO_REG_ADDR); > - if (*address == 0) { > + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); > + if (*hwmon_addr == 0) { > printk(KERN_WARNING DRVNAME ": Base address not set\n"); > goto exit; > } > - *address&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > + *hwmon_addr&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > > err = 0; > printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", > - f71882fg_names[sio_data->type], (unsigned int)*address, > + f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > @@ -2307,17 +2307,17 @@ exit: > return err; > } > > -static int __init f71882fg_device_add(unsigned short address, > +static int __init f71882fg_device_add(unsigned short hwmon_addr, > const struct f71882fg_sio_data *sio_data) > { > struct resource res = { > - .start = address, > - .end = address + REGION_LENGTH - 1, > + .start = hwmon_addr, > + .end = hwmon_addr + REGION_LENGTH - 1, > .flags = IORESOURCE_IO, > }; > int err; > > - f71882fg_pdev = platform_device_alloc(DRVNAME, address); > + f71882fg_pdev = platform_device_alloc(DRVNAME, hwmon_addr); > if (!f71882fg_pdev) > return -ENOMEM; > > @@ -2357,14 +2357,14 @@ static int __init f71882fg_init(void) > { > static const unsigned short addrs[] = { 0x2e, 0x4e }; > int err = -ENODEV; > - unsigned short address = /* shut up compiler */ 0; > + unsigned short hwmon_addr = /* shut up compiler */ 0; > struct f71882fg_sio_data sio_data; > int i; > > memset(&sio_data, 0, sizeof(sio_data)); > > for (i = 0; i< ARRAY_SIZE(addrs); i++) { > - err = f71882fg_find(addrs[i],&address,&sio_data); > + err = f71882fg_find(addrs[i],&hwmon_addr,&sio_data); > if (err == 0) > break; > } > @@ -2375,7 +2375,7 @@ static int __init f71882fg_init(void) > if (err) > goto exit; > > - err = f71882fg_device_add(address,&sio_data); > + err = f71882fg_device_add(hwmon_addr,&sio_data); > if (err) > goto exit_driver; > ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition @ 2010-03-24 8:26 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:26 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Ack. Acked-by: Hans de Goede <hdegoede@redhat.com> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Rename the `address' variable that's used in some places to hwmon_addr > to indicate it refers to the hardware monitor (HWMON in datasheet) > "logical device" of the chip. > > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 24 ++++++++++++------------ > 1 files changed, 12 insertions(+), 12 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index b290b87..7b31e14 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2233,7 +2233,7 @@ static int f71882fg_remove(struct platform_device *pdev) > return 0; > } > > -static int __init f71882fg_find(int sioaddr, unsigned short *address, > +static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, > struct f71882fg_sio_data *sio_data) > { > int err = -ENODEV; > @@ -2290,16 +2290,16 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > goto exit; > } > > - *address = superio_inw(sioaddr, SIO_REG_ADDR); > - if (*address = 0) { > + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); > + if (*hwmon_addr = 0) { > printk(KERN_WARNING DRVNAME ": Base address not set\n"); > goto exit; > } > - *address&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > + *hwmon_addr&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > > err = 0; > printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", > - f71882fg_names[sio_data->type], (unsigned int)*address, > + f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > @@ -2307,17 +2307,17 @@ exit: > return err; > } > > -static int __init f71882fg_device_add(unsigned short address, > +static int __init f71882fg_device_add(unsigned short hwmon_addr, > const struct f71882fg_sio_data *sio_data) > { > struct resource res = { > - .start = address, > - .end = address + REGION_LENGTH - 1, > + .start = hwmon_addr, > + .end = hwmon_addr + REGION_LENGTH - 1, > .flags = IORESOURCE_IO, > }; > int err; > > - f71882fg_pdev = platform_device_alloc(DRVNAME, address); > + f71882fg_pdev = platform_device_alloc(DRVNAME, hwmon_addr); > if (!f71882fg_pdev) > return -ENOMEM; > > @@ -2357,14 +2357,14 @@ static int __init f71882fg_init(void) > { > static const unsigned short addrs[] = { 0x2e, 0x4e }; > int err = -ENODEV; > - unsigned short address = /* shut up compiler */ 0; > + unsigned short hwmon_addr = /* shut up compiler */ 0; > struct f71882fg_sio_data sio_data; > int i; > > memset(&sio_data, 0, sizeof(sio_data)); > > for (i = 0; i< ARRAY_SIZE(addrs); i++) { > - err = f71882fg_find(addrs[i],&address,&sio_data); > + err = f71882fg_find(addrs[i],&hwmon_addr,&sio_data); > if (err = 0) > break; > } > @@ -2375,7 +2375,7 @@ static int __init f71882fg_init(void) > if (err) > goto exit; > > - err = f71882fg_device_add(address,&sio_data); > + err = f71882fg_device_add(hwmon_addr,&sio_data); > if (err) > goto exit_driver; > _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 2/4] hwmon: f71882fg: prepare for addition of watchdog support 2010-03-23 23:12 ` [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition of Giel van Schijndel @ 2010-03-24 8:36 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:36 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Correction, nack on this one see me reply to patch 4/4 Regards, Hans On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Rename the `address' variable that's used in some places to hwmon_addr > to indicate it refers to the hardware monitor (HWMON in datasheet) > "logical device" of the chip. > > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 24 ++++++++++++------------ > 1 files changed, 12 insertions(+), 12 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index b290b87..7b31e14 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2233,7 +2233,7 @@ static int f71882fg_remove(struct platform_device *pdev) > return 0; > } > > -static int __init f71882fg_find(int sioaddr, unsigned short *address, > +static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, > struct f71882fg_sio_data *sio_data) > { > int err = -ENODEV; > @@ -2290,16 +2290,16 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > goto exit; > } > > - *address = superio_inw(sioaddr, SIO_REG_ADDR); > - if (*address == 0) { > + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); > + if (*hwmon_addr == 0) { > printk(KERN_WARNING DRVNAME ": Base address not set\n"); > goto exit; > } > - *address&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > + *hwmon_addr&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > > err = 0; > printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", > - f71882fg_names[sio_data->type], (unsigned int)*address, > + f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > @@ -2307,17 +2307,17 @@ exit: > return err; > } > > -static int __init f71882fg_device_add(unsigned short address, > +static int __init f71882fg_device_add(unsigned short hwmon_addr, > const struct f71882fg_sio_data *sio_data) > { > struct resource res = { > - .start = address, > - .end = address + REGION_LENGTH - 1, > + .start = hwmon_addr, > + .end = hwmon_addr + REGION_LENGTH - 1, > .flags = IORESOURCE_IO, > }; > int err; > > - f71882fg_pdev = platform_device_alloc(DRVNAME, address); > + f71882fg_pdev = platform_device_alloc(DRVNAME, hwmon_addr); > if (!f71882fg_pdev) > return -ENOMEM; > > @@ -2357,14 +2357,14 @@ static int __init f71882fg_init(void) > { > static const unsigned short addrs[] = { 0x2e, 0x4e }; > int err = -ENODEV; > - unsigned short address = /* shut up compiler */ 0; > + unsigned short hwmon_addr = /* shut up compiler */ 0; > struct f71882fg_sio_data sio_data; > int i; > > memset(&sio_data, 0, sizeof(sio_data)); > > for (i = 0; i< ARRAY_SIZE(addrs); i++) { > - err = f71882fg_find(addrs[i],&address,&sio_data); > + err = f71882fg_find(addrs[i],&hwmon_addr,&sio_data); > if (err == 0) > break; > } > @@ -2375,7 +2375,7 @@ static int __init f71882fg_init(void) > if (err) > goto exit; > > - err = f71882fg_device_add(address,&sio_data); > + err = f71882fg_device_add(hwmon_addr,&sio_data); > if (err) > goto exit_driver; > ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition @ 2010-03-24 8:36 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:36 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Correction, nack on this one see me reply to patch 4/4 Regards, Hans On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Rename the `address' variable that's used in some places to hwmon_addr > to indicate it refers to the hardware monitor (HWMON in datasheet) > "logical device" of the chip. > > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 24 ++++++++++++------------ > 1 files changed, 12 insertions(+), 12 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index b290b87..7b31e14 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2233,7 +2233,7 @@ static int f71882fg_remove(struct platform_device *pdev) > return 0; > } > > -static int __init f71882fg_find(int sioaddr, unsigned short *address, > +static int __init f71882fg_find(int sioaddr, unsigned short *hwmon_addr, > struct f71882fg_sio_data *sio_data) > { > int err = -ENODEV; > @@ -2290,16 +2290,16 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > goto exit; > } > > - *address = superio_inw(sioaddr, SIO_REG_ADDR); > - if (*address = 0) { > + *hwmon_addr = superio_inw(sioaddr, SIO_REG_ADDR); > + if (*hwmon_addr = 0) { > printk(KERN_WARNING DRVNAME ": Base address not set\n"); > goto exit; > } > - *address&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > + *hwmon_addr&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > > err = 0; > printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", > - f71882fg_names[sio_data->type], (unsigned int)*address, > + f71882fg_names[sio_data->type], (unsigned int)*hwmon_addr, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > @@ -2307,17 +2307,17 @@ exit: > return err; > } > > -static int __init f71882fg_device_add(unsigned short address, > +static int __init f71882fg_device_add(unsigned short hwmon_addr, > const struct f71882fg_sio_data *sio_data) > { > struct resource res = { > - .start = address, > - .end = address + REGION_LENGTH - 1, > + .start = hwmon_addr, > + .end = hwmon_addr + REGION_LENGTH - 1, > .flags = IORESOURCE_IO, > }; > int err; > > - f71882fg_pdev = platform_device_alloc(DRVNAME, address); > + f71882fg_pdev = platform_device_alloc(DRVNAME, hwmon_addr); > if (!f71882fg_pdev) > return -ENOMEM; > > @@ -2357,14 +2357,14 @@ static int __init f71882fg_init(void) > { > static const unsigned short addrs[] = { 0x2e, 0x4e }; > int err = -ENODEV; > - unsigned short address = /* shut up compiler */ 0; > + unsigned short hwmon_addr = /* shut up compiler */ 0; > struct f71882fg_sio_data sio_data; > int i; > > memset(&sio_data, 0, sizeof(sio_data)); > > for (i = 0; i< ARRAY_SIZE(addrs); i++) { > - err = f71882fg_find(addrs[i],&address,&sio_data); > + err = f71882fg_find(addrs[i],&hwmon_addr,&sio_data); > if (err = 0) > break; > } > @@ -2375,7 +2375,7 @@ static int __init f71882fg_init(void) > if (err) > goto exit; > > - err = f71882fg_device_add(address,&sio_data); > + err = f71882fg_device_add(hwmon_addr,&sio_data); > if (err) > goto exit_driver; > _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the Fintek F71808E 2010-03-23 23:12 ` [lm-sensors] [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the Giel van Schijndel @ 2010-03-24 8:25 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:25 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, See comments inline. On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Allow device probing to recognise the Fintek F71808E. > > Sysfs interface: > * Fan/pwm control is the same as for F71889FG > * Temperature and voltage sensor handling is largely the same as for > the F71889FG > - Has one temperature sensor less (doesn't have temp3) > - Misses one voltage sensor (doesn't have V6, thus in6_input refers to > what in7_input refers for F71889FG) > > For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up > such that it can largely be reused. > --- > Documentation/hwmon/f71882fg | 4 ++ > drivers/hwmon/Kconfig | 6 ++-- > drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- > 3 files changed, 79 insertions(+), 11 deletions(-) > > diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg > index a7952c2..1a07fd6 100644 > --- a/Documentation/hwmon/f71882fg > +++ b/Documentation/hwmon/f71882fg > @@ -2,6 +2,10 @@ Kernel driver f71882fg > ====================== > > Supported chips: > + * Fintek F71808E > + Prefix: 'f71808fg' > + Addresses scanned: none, address read from Super I/O config space > + Datasheet: Not public > * Fintek F71858FG > Prefix: 'f71858fg' > Addresses scanned: none, address read from Super I/O config space > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig > index e4595e6..7053608 100644 > --- a/drivers/hwmon/Kconfig > +++ b/drivers/hwmon/Kconfig > @@ -332,11 +332,11 @@ config SENSORS_F71805F > will be called f71805f. > > config SENSORS_F71882FG > - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" > + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" > depends on EXPERIMENTAL > help > - If you say yes here you get support for hardware monitoring > - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, > + If you say yes here you get support for hardware monitoring features > + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, > F71889FG and F8000 Super-I/O chips. > > This driver can also be built as a module. If so, the module > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 25e1cad..b290b87 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -45,6 +45,7 @@ > #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ > > #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ > +#define SIO_F71808_ID 0x0901 /* Chipset ID */ > #define SIO_F71858_ID 0x0507 /* Chipset ID */ > #define SIO_F71862_ID 0x0601 /* Chipset ID */ > #define SIO_F71882_ID 0x0541 /* Chipset ID */ > @@ -96,9 +97,10 @@ static unsigned short force_id; > module_param(force_id, ushort, 0); > MODULE_PARM_DESC(force_id, "Override the detected device ID"); > > -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; > +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; > > static const char *f71882fg_names[] = { > + "f71808fg", > "f71858fg", > "f71862fg", > "f71882fg", > @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { > SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), > }; > > -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ > -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { > +/* In attr common to the f71862fg, f71882fg and f71889fg */ > +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { > SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), > SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), > SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), > @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { > SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), > SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), > SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), > +}; > + > +/* In attr for the f71808fg */ > +static struct sensor_device_attribute_2 f71808_in_attr[] = { > + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), > + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), > + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), > + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), > + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), > + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), > + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), > + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), > +}; > + > +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ > +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { > SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), > SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, > store_temp_max, 0, 1), > @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { > store_temp_beep, 0, 6), > SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), > SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), > +}; > + > +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ > +static struct sensor_device_attribute_2 f71862_temp_attr[] = { > SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), > SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, > store_temp_max, 0, 3), > @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) > data->temp_type[1] = 6; > break; > } > + } else if (data->type == f71808fg) { > + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); > + data->temp_type[1] = (reg& 0x02) ? 2 : 4; > + data->temp_type[2] = (reg& 0x04) ? 2 : 4; > + > } else { > reg2 = f71882fg_read8(data, F71882FG_REG_PECI); > if ((reg2& 0x03) == 0x01) > @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, > > val /= 1000; > > - if (data->type == f71889fg) > + if (data->type == f71889fg > + || data->type == f71808fg) > val = SENSORS_LIMIT(val, -128, 127); > else > val = SENSORS_LIMIT(val, 0, 127); > @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) > /* fall through! */ > case f71862fg: > err = f71882fg_create_sysfs_files(pdev, > - fxxxx_in_temp_attr, > - ARRAY_SIZE(fxxxx_in_temp_attr)); > + f71862_temp_attr, > + ARRAY_SIZE(f71862_temp_attr)); > + if (err) > + goto exit_unregister_sysfs; > + err = f71882fg_create_sysfs_files(pdev, > + fxxxx_in_attr, > + ARRAY_SIZE(fxxxx_in_attr)); > + if (err) > + goto exit_unregister_sysfs; > + /* fall through! */ Ugh, please don't fall through, and then have an if below to only do some parts of the case falling through. This is quite confusing at first I thought your code was buggy I had to read it twice to notice the if. Instead just duplicate the following lines: > + err = f71882fg_create_sysfs_files(pdev, > + fxxxx_temp_attr, > + ARRAY_SIZE(fxxxx_temp_attr)); In the f71862fg case, end the f71862fg case with a break and remove the if test from the f71808fg case. > + case f71808fg: > + if (data->type == f71808fg) { > + err = f71882fg_create_sysfs_files(pdev, > + f71808_in_attr, > + ARRAY_SIZE(f71808_in_attr)); > + if (err) > + goto exit_unregister_sysfs; > + } > + err = f71882fg_create_sysfs_files(pdev, > + fxxxx_temp_attr, > + ARRAY_SIZE(fxxxx_temp_attr)); > break; > case f8000: > err = f71882fg_create_sysfs_files(pdev, > @@ -2002,6 +2049,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) > case f71862fg: > err = (data->pwm_enable& 0x15) != 0x15; > break; > + case f71808fg: > case f71882fg: > case f71889fg: > err = 0; > @@ -2047,6 +2095,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) > f8000_auto_pwm_attr, > ARRAY_SIZE(f8000_auto_pwm_attr)); > break; > + case f71808fg: > case f71889fg: > for (i = 0; i< nr_fans; i++) { > data->pwm_auto_point_mapping[i] = > @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) > /* fall through! */ > case f71862fg: > f71882fg_remove_sysfs_files(pdev, > - fxxxx_in_temp_attr, > - ARRAY_SIZE(fxxxx_in_temp_attr)); > + f71862_temp_attr, > + ARRAY_SIZE(f71862_temp_attr)); > + f71882fg_remove_sysfs_files(pdev, > + fxxxx_in_attr, > + ARRAY_SIZE(fxxxx_in_attr)); > + /* fall through! */ Idem. > + case f71808fg: > + if (data->type == f71808fg) > + f71882fg_remove_sysfs_files(pdev, > + f71808_in_attr, > + ARRAY_SIZE(f71808_in_attr)); > + f71882fg_remove_sysfs_files(pdev, > + fxxxx_temp_attr, > + ARRAY_SIZE(fxxxx_temp_attr)); > break; > case f8000: > f71882fg_remove_sysfs_files(pdev, > @@ -2195,6 +2256,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > > devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); > switch (devid) { > + case SIO_F71808_ID: > + sio_data->type = f71808fg; > + break; > case SIO_F71858_ID: > sio_data->type = f71858fg; > break; Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for @ 2010-03-24 8:25 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:25 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, See comments inline. On 03/24/2010 12:12 AM, Giel van Schijndel wrote: > Allow device probing to recognise the Fintek F71808E. > > Sysfs interface: > * Fan/pwm control is the same as for F71889FG > * Temperature and voltage sensor handling is largely the same as for > the F71889FG > - Has one temperature sensor less (doesn't have temp3) > - Misses one voltage sensor (doesn't have V6, thus in6_input refers to > what in7_input refers for F71889FG) > > For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up > such that it can largely be reused. > --- > Documentation/hwmon/f71882fg | 4 ++ > drivers/hwmon/Kconfig | 6 ++-- > drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- > 3 files changed, 79 insertions(+), 11 deletions(-) > > diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg > index a7952c2..1a07fd6 100644 > --- a/Documentation/hwmon/f71882fg > +++ b/Documentation/hwmon/f71882fg > @@ -2,6 +2,10 @@ Kernel driver f71882fg > =========== > > Supported chips: > + * Fintek F71808E > + Prefix: 'f71808fg' > + Addresses scanned: none, address read from Super I/O config space > + Datasheet: Not public > * Fintek F71858FG > Prefix: 'f71858fg' > Addresses scanned: none, address read from Super I/O config space > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig > index e4595e6..7053608 100644 > --- a/drivers/hwmon/Kconfig > +++ b/drivers/hwmon/Kconfig > @@ -332,11 +332,11 @@ config SENSORS_F71805F > will be called f71805f. > > config SENSORS_F71882FG > - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" > + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" > depends on EXPERIMENTAL > help > - If you say yes here you get support for hardware monitoring > - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, > + If you say yes here you get support for hardware monitoring features > + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, > F71889FG and F8000 Super-I/O chips. > > This driver can also be built as a module. If so, the module > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 25e1cad..b290b87 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -45,6 +45,7 @@ > #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ > > #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ > +#define SIO_F71808_ID 0x0901 /* Chipset ID */ > #define SIO_F71858_ID 0x0507 /* Chipset ID */ > #define SIO_F71862_ID 0x0601 /* Chipset ID */ > #define SIO_F71882_ID 0x0541 /* Chipset ID */ > @@ -96,9 +97,10 @@ static unsigned short force_id; > module_param(force_id, ushort, 0); > MODULE_PARM_DESC(force_id, "Override the detected device ID"); > > -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; > +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; > > static const char *f71882fg_names[] = { > + "f71808fg", > "f71858fg", > "f71862fg", > "f71882fg", > @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { > SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), > }; > > -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ > -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { > +/* In attr common to the f71862fg, f71882fg and f71889fg */ > +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { > SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), > SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), > SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), > @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { > SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), > SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), > SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), > +}; > + > +/* In attr for the f71808fg */ > +static struct sensor_device_attribute_2 f71808_in_attr[] = { > + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), > + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), > + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), > + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), > + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), > + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), > + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), > + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), > +}; > + > +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ > +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { > SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), > SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, > store_temp_max, 0, 1), > @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { > store_temp_beep, 0, 6), > SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), > SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), > +}; > + > +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ > +static struct sensor_device_attribute_2 f71862_temp_attr[] = { > SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), > SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, > store_temp_max, 0, 3), > @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) > data->temp_type[1] = 6; > break; > } > + } else if (data->type = f71808fg) { > + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); > + data->temp_type[1] = (reg& 0x02) ? 2 : 4; > + data->temp_type[2] = (reg& 0x04) ? 2 : 4; > + > } else { > reg2 = f71882fg_read8(data, F71882FG_REG_PECI); > if ((reg2& 0x03) = 0x01) > @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, > > val /= 1000; > > - if (data->type = f71889fg) > + if (data->type = f71889fg > + || data->type = f71808fg) > val = SENSORS_LIMIT(val, -128, 127); > else > val = SENSORS_LIMIT(val, 0, 127); > @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) > /* fall through! */ > case f71862fg: > err = f71882fg_create_sysfs_files(pdev, > - fxxxx_in_temp_attr, > - ARRAY_SIZE(fxxxx_in_temp_attr)); > + f71862_temp_attr, > + ARRAY_SIZE(f71862_temp_attr)); > + if (err) > + goto exit_unregister_sysfs; > + err = f71882fg_create_sysfs_files(pdev, > + fxxxx_in_attr, > + ARRAY_SIZE(fxxxx_in_attr)); > + if (err) > + goto exit_unregister_sysfs; > + /* fall through! */ Ugh, please don't fall through, and then have an if below to only do some parts of the case falling through. This is quite confusing at first I thought your code was buggy I had to read it twice to notice the if. Instead just duplicate the following lines: > + err = f71882fg_create_sysfs_files(pdev, > + fxxxx_temp_attr, > + ARRAY_SIZE(fxxxx_temp_attr)); In the f71862fg case, end the f71862fg case with a break and remove the if test from the f71808fg case. > + case f71808fg: > + if (data->type = f71808fg) { > + err = f71882fg_create_sysfs_files(pdev, > + f71808_in_attr, > + ARRAY_SIZE(f71808_in_attr)); > + if (err) > + goto exit_unregister_sysfs; > + } > + err = f71882fg_create_sysfs_files(pdev, > + fxxxx_temp_attr, > + ARRAY_SIZE(fxxxx_temp_attr)); > break; > case f8000: > err = f71882fg_create_sysfs_files(pdev, > @@ -2002,6 +2049,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) > case f71862fg: > err = (data->pwm_enable& 0x15) != 0x15; > break; > + case f71808fg: > case f71882fg: > case f71889fg: > err = 0; > @@ -2047,6 +2095,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) > f8000_auto_pwm_attr, > ARRAY_SIZE(f8000_auto_pwm_attr)); > break; > + case f71808fg: > case f71889fg: > for (i = 0; i< nr_fans; i++) { > data->pwm_auto_point_mapping[i] > @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) > /* fall through! */ > case f71862fg: > f71882fg_remove_sysfs_files(pdev, > - fxxxx_in_temp_attr, > - ARRAY_SIZE(fxxxx_in_temp_attr)); > + f71862_temp_attr, > + ARRAY_SIZE(f71862_temp_attr)); > + f71882fg_remove_sysfs_files(pdev, > + fxxxx_in_attr, > + ARRAY_SIZE(fxxxx_in_attr)); > + /* fall through! */ Idem. > + case f71808fg: > + if (data->type = f71808fg) > + f71882fg_remove_sysfs_files(pdev, > + f71808_in_attr, > + ARRAY_SIZE(f71808_in_attr)); > + f71882fg_remove_sysfs_files(pdev, > + fxxxx_temp_attr, > + ARRAY_SIZE(fxxxx_temp_attr)); > break; > case f8000: > f71882fg_remove_sysfs_files(pdev, > @@ -2195,6 +2256,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > > devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); > switch (devid) { > + case SIO_F71808_ID: > + sio_data->type = f71808fg; > + break; > case SIO_F71858_ID: > sio_data->type = f71858fg; > break; Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E 2010-03-24 8:25 ` [lm-sensors] [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for Hans de Goede @ 2010-03-24 9:23 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:23 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 12018 bytes --] On Wed, Mar 24, 2010 at 09:25:08AM +0100, Hans de Goede wrote: > See comments inline. > > On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >> Allow device probing to recognise the Fintek F71808E. >> >> Sysfs interface: >> * Fan/pwm control is the same as for F71889FG >> * Temperature and voltage sensor handling is largely the same as for >> the F71889FG >> - Has one temperature sensor less (doesn't have temp3) >> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >> what in7_input refers for F71889FG) >> >> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >> such that it can largely be reused. >> --- >> Documentation/hwmon/f71882fg | 4 ++ >> drivers/hwmon/Kconfig | 6 ++-- >> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >> 3 files changed, 79 insertions(+), 11 deletions(-) >> >> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >> index 25e1cad..b290b87 100644 >> --- a/drivers/hwmon/f71882fg.c >> +++ b/drivers/hwmon/f71882fg.c >> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >> /* fall through! */ >> case f71862fg: >> err = f71882fg_create_sysfs_files(pdev, >> - fxxxx_in_temp_attr, >> - ARRAY_SIZE(fxxxx_in_temp_attr)); >> + f71862_temp_attr, >> + ARRAY_SIZE(f71862_temp_attr)); >> + if (err) >> + goto exit_unregister_sysfs; >> + err = f71882fg_create_sysfs_files(pdev, >> + fxxxx_in_attr, >> + ARRAY_SIZE(fxxxx_in_attr)); >> + if (err) >> + goto exit_unregister_sysfs; >> + /* fall through! */ > > Ugh, please don't fall through, and then have an if below to only do > some parts of the case falling through. This is quite confusing > at first I thought your code was buggy I had to read it twice to notice > the if. Instead just duplicate the following lines: >> + err = f71882fg_create_sysfs_files(pdev, >> + fxxxx_temp_attr, >> + ARRAY_SIZE(fxxxx_temp_attr)); > In the f71862fg case, end the f71862fg case with a break and remove > the if test from the f71808fg case. > >> + case f71808fg: >> + if (data->type == f71808fg) { >> + err = f71882fg_create_sysfs_files(pdev, >> + f71808_in_attr, >> + ARRAY_SIZE(f71808_in_attr)); >> + if (err) >> + goto exit_unregister_sysfs; >> + } >> + err = f71882fg_create_sysfs_files(pdev, >> + fxxxx_temp_attr, >> + ARRAY_SIZE(fxxxx_temp_attr)); >> break; >> case f8000: >> err = f71882fg_create_sysfs_files(pdev, >> @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) >> /* fall through! */ >> case f71862fg: >> f71882fg_remove_sysfs_files(pdev, >> - fxxxx_in_temp_attr, >> - ARRAY_SIZE(fxxxx_in_temp_attr)); >> + f71862_temp_attr, >> + ARRAY_SIZE(f71862_temp_attr)); >> + f71882fg_remove_sysfs_files(pdev, >> + fxxxx_in_attr, >> + ARRAY_SIZE(fxxxx_in_attr)); >> + /* fall through! */ > > Idem. Ack. New and improved patch follows this line. ======================================================================== hwmon: f71882fg: Add support for the Fintek F71808E Allow device probing to recognise the Fintek F71808E. Sysfs interface: * Fan/pwm control is the same as for F71889FG * Temperature and voltage sensor handling is largely the same as for the F71889FG - Has one temperature sensor less (doesn't have temp3) - Misses one voltage sensor (doesn't have V6, thus in6_input refers to what in7_input refers for F71889FG) For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up such that it can largely be reused. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- Documentation/hwmon/f71882fg | 4 ++ drivers/hwmon/Kconfig | 6 ++-- drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index a7952c2..1a07fd6 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -2,6 +2,10 @@ Kernel driver f71882fg ====================== Supported chips: + * Fintek F71808E + Prefix: 'f71808fg' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71858FG Prefix: 'f71858fg' Addresses scanned: none, address read from Super I/O config space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e4595e6..7053608 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -332,11 +332,11 @@ config SENSORS_F71805F will be called f71805f. config SENSORS_F71882FG - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" depends on EXPERIMENTAL help - If you say yes here you get support for hardware monitoring - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, + If you say yes here you get support for hardware monitoring features + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, F71889FG and F8000 Super-I/O chips. This driver can also be built as a module. If so, the module diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 28bcbac..0b89bb6 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -45,6 +45,7 @@ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ @@ -96,9 +97,10 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { + "f71808fg", "f71858fg", "f71862fg", "f71882fg", @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { +/* In attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* In attr for the f71808fg */ +static struct sensor_device_attribute_2 f71808_in_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 1), @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { store_temp_beep, 0, 6), SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), +}; + +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 f71862_temp_attr[] = { SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 3), @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->temp_type[1] = 6; break; } + } else if (data->type == f71808fg) { + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + data->temp_type[1] = (reg & 0x02) ? 2 : 4; + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + } else { reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) == 0x01) @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, val /= 1000; - if (data->type == f71889fg) + if (data->type == f71889fg + || data->type == f71808fg) val = SENSORS_LIMIT(val, -128, 127); else val = SENSORS_LIMIT(val, 0, 127); @@ -1974,8 +2002,28 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) /* fall through! */ case f71862fg: err = f71882fg_create_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + err = f71882fg_create_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: err = f71882fg_create_sysfs_files(pdev, @@ -2002,6 +2050,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71862fg: err = (data->pwm_enable & 0x15) != 0x15; break; + case f71808fg: case f71882fg: case f71889fg: err = 0; @@ -2047,6 +2096,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) f8000_auto_pwm_attr, ARRAY_SIZE(f8000_auto_pwm_attr)); break; + case f71808fg: case f71889fg: for (i = 0; i < nr_fans; i++) { data->pwm_auto_point_mapping[i] = @@ -2126,8 +2176,22 @@ static int f71882fg_remove(struct platform_device *pdev) /* fall through! */ case f71862fg: f71882fg_remove_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + f71882fg_remove_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: f71882fg_remove_sysfs_files(pdev, @@ -2195,6 +2259,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); switch (devid) { + case SIO_F71808_ID: + sio_data->type = f71808fg; + break; case SIO_F71858_ID: sio_data->type = f71858fg; break; -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the @ 2010-03-24 9:23 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:23 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 12018 bytes --] On Wed, Mar 24, 2010 at 09:25:08AM +0100, Hans de Goede wrote: > See comments inline. > > On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >> Allow device probing to recognise the Fintek F71808E. >> >> Sysfs interface: >> * Fan/pwm control is the same as for F71889FG >> * Temperature and voltage sensor handling is largely the same as for >> the F71889FG >> - Has one temperature sensor less (doesn't have temp3) >> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >> what in7_input refers for F71889FG) >> >> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >> such that it can largely be reused. >> --- >> Documentation/hwmon/f71882fg | 4 ++ >> drivers/hwmon/Kconfig | 6 ++-- >> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >> 3 files changed, 79 insertions(+), 11 deletions(-) >> >> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >> index 25e1cad..b290b87 100644 >> --- a/drivers/hwmon/f71882fg.c >> +++ b/drivers/hwmon/f71882fg.c >> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >> /* fall through! */ >> case f71862fg: >> err = f71882fg_create_sysfs_files(pdev, >> - fxxxx_in_temp_attr, >> - ARRAY_SIZE(fxxxx_in_temp_attr)); >> + f71862_temp_attr, >> + ARRAY_SIZE(f71862_temp_attr)); >> + if (err) >> + goto exit_unregister_sysfs; >> + err = f71882fg_create_sysfs_files(pdev, >> + fxxxx_in_attr, >> + ARRAY_SIZE(fxxxx_in_attr)); >> + if (err) >> + goto exit_unregister_sysfs; >> + /* fall through! */ > > Ugh, please don't fall through, and then have an if below to only do > some parts of the case falling through. This is quite confusing > at first I thought your code was buggy I had to read it twice to notice > the if. Instead just duplicate the following lines: >> + err = f71882fg_create_sysfs_files(pdev, >> + fxxxx_temp_attr, >> + ARRAY_SIZE(fxxxx_temp_attr)); > In the f71862fg case, end the f71862fg case with a break and remove > the if test from the f71808fg case. > >> + case f71808fg: >> + if (data->type == f71808fg) { >> + err = f71882fg_create_sysfs_files(pdev, >> + f71808_in_attr, >> + ARRAY_SIZE(f71808_in_attr)); >> + if (err) >> + goto exit_unregister_sysfs; >> + } >> + err = f71882fg_create_sysfs_files(pdev, >> + fxxxx_temp_attr, >> + ARRAY_SIZE(fxxxx_temp_attr)); >> break; >> case f8000: >> err = f71882fg_create_sysfs_files(pdev, >> @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) >> /* fall through! */ >> case f71862fg: >> f71882fg_remove_sysfs_files(pdev, >> - fxxxx_in_temp_attr, >> - ARRAY_SIZE(fxxxx_in_temp_attr)); >> + f71862_temp_attr, >> + ARRAY_SIZE(f71862_temp_attr)); >> + f71882fg_remove_sysfs_files(pdev, >> + fxxxx_in_attr, >> + ARRAY_SIZE(fxxxx_in_attr)); >> + /* fall through! */ > > Idem. Ack. New and improved patch follows this line. ======================================================================== hwmon: f71882fg: Add support for the Fintek F71808E Allow device probing to recognise the Fintek F71808E. Sysfs interface: * Fan/pwm control is the same as for F71889FG * Temperature and voltage sensor handling is largely the same as for the F71889FG - Has one temperature sensor less (doesn't have temp3) - Misses one voltage sensor (doesn't have V6, thus in6_input refers to what in7_input refers for F71889FG) For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up such that it can largely be reused. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- Documentation/hwmon/f71882fg | 4 ++ drivers/hwmon/Kconfig | 6 ++-- drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index a7952c2..1a07fd6 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -2,6 +2,10 @@ Kernel driver f71882fg ====================== Supported chips: + * Fintek F71808E + Prefix: 'f71808fg' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71858FG Prefix: 'f71858fg' Addresses scanned: none, address read from Super I/O config space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e4595e6..7053608 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -332,11 +332,11 @@ config SENSORS_F71805F will be called f71805f. config SENSORS_F71882FG - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" depends on EXPERIMENTAL help - If you say yes here you get support for hardware monitoring - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, + If you say yes here you get support for hardware monitoring features + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, F71889FG and F8000 Super-I/O chips. This driver can also be built as a module. If so, the module diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 28bcbac..0b89bb6 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -45,6 +45,7 @@ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ @@ -96,9 +97,10 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { + "f71808fg", "f71858fg", "f71862fg", "f71882fg", @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { +/* In attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* In attr for the f71808fg */ +static struct sensor_device_attribute_2 f71808_in_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 1), @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { store_temp_beep, 0, 6), SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), +}; + +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 f71862_temp_attr[] = { SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 3), @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->temp_type[1] = 6; break; } + } else if (data->type == f71808fg) { + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + data->temp_type[1] = (reg & 0x02) ? 2 : 4; + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + } else { reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) == 0x01) @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, val /= 1000; - if (data->type == f71889fg) + if (data->type == f71889fg + || data->type == f71808fg) val = SENSORS_LIMIT(val, -128, 127); else val = SENSORS_LIMIT(val, 0, 127); @@ -1974,8 +2002,28 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) /* fall through! */ case f71862fg: err = f71882fg_create_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + err = f71882fg_create_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: err = f71882fg_create_sysfs_files(pdev, @@ -2002,6 +2050,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71862fg: err = (data->pwm_enable & 0x15) != 0x15; break; + case f71808fg: case f71882fg: case f71889fg: err = 0; @@ -2047,6 +2096,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) f8000_auto_pwm_attr, ARRAY_SIZE(f8000_auto_pwm_attr)); break; + case f71808fg: case f71889fg: for (i = 0; i < nr_fans; i++) { data->pwm_auto_point_mapping[i] = @@ -2126,8 +2176,22 @@ static int f71882fg_remove(struct platform_device *pdev) /* fall through! */ case f71862fg: f71882fg_remove_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + f71882fg_remove_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: f71882fg_remove_sysfs_files(pdev, @@ -2195,6 +2259,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); switch (devid) { + case SIO_F71808_ID: + sio_data->type = f71808fg; + break; case SIO_F71858_ID: sio_data->type = f71858fg; break; -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E 2010-03-24 9:23 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Giel van Schijndel @ 2010-03-24 10:31 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 10:31 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/24/2010 10:23 AM, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 09:25:08AM +0100, Hans de Goede wrote: >> See comments inline. >> >> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >>> Allow device probing to recognise the Fintek F71808E. >>> >>> Sysfs interface: >>> * Fan/pwm control is the same as for F71889FG >>> * Temperature and voltage sensor handling is largely the same as for >>> the F71889FG >>> - Has one temperature sensor less (doesn't have temp3) >>> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >>> what in7_input refers for F71889FG) >>> >>> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >>> such that it can largely be reused. >>> --- >>> Documentation/hwmon/f71882fg | 4 ++ >>> drivers/hwmon/Kconfig | 6 ++-- >>> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >>> 3 files changed, 79 insertions(+), 11 deletions(-) >>> >>> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >>> index 25e1cad..b290b87 100644 >>> --- a/drivers/hwmon/f71882fg.c >>> +++ b/drivers/hwmon/f71882fg.c >>> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >>> /* fall through! */ >>> case f71862fg: >>> err = f71882fg_create_sysfs_files(pdev, >>> - fxxxx_in_temp_attr, >>> - ARRAY_SIZE(fxxxx_in_temp_attr)); >>> + f71862_temp_attr, >>> + ARRAY_SIZE(f71862_temp_attr)); >>> + if (err) >>> + goto exit_unregister_sysfs; >>> + err = f71882fg_create_sysfs_files(pdev, >>> + fxxxx_in_attr, >>> + ARRAY_SIZE(fxxxx_in_attr)); >>> + if (err) >>> + goto exit_unregister_sysfs; >>> + /* fall through! */ >> >> Ugh, please don't fall through, and then have an if below to only do >> some parts of the case falling through. This is quite confusing >> at first I thought your code was buggy I had to read it twice to notice >> the if. Instead just duplicate the following lines: >>> + err = f71882fg_create_sysfs_files(pdev, >>> + fxxxx_temp_attr, >>> + ARRAY_SIZE(fxxxx_temp_attr)); >> In the f71862fg case, end the f71862fg case with a break and remove >> the if test from the f71808fg case. >> >>> + case f71808fg: >>> + if (data->type == f71808fg) { >>> + err = f71882fg_create_sysfs_files(pdev, >>> + f71808_in_attr, >>> + ARRAY_SIZE(f71808_in_attr)); >>> + if (err) >>> + goto exit_unregister_sysfs; >>> + } >>> + err = f71882fg_create_sysfs_files(pdev, >>> + fxxxx_temp_attr, >>> + ARRAY_SIZE(fxxxx_temp_attr)); >>> break; >>> case f8000: >>> err = f71882fg_create_sysfs_files(pdev, >>> @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) >>> /* fall through! */ >>> case f71862fg: >>> f71882fg_remove_sysfs_files(pdev, >>> - fxxxx_in_temp_attr, >>> - ARRAY_SIZE(fxxxx_in_temp_attr)); >>> + f71862_temp_attr, >>> + ARRAY_SIZE(f71862_temp_attr)); >>> + f71882fg_remove_sysfs_files(pdev, >>> + fxxxx_in_attr, >>> + ARRAY_SIZE(fxxxx_in_attr)); >>> + /* fall through! */ >> >> Idem. > > Ack. New and improved patch follows this line. > ======================================================================== > hwmon: f71882fg: Add support for the Fintek F71808E > This new version looks good to me: Acked-by: Hans de Goede <hdegoede@redhat.com> Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the @ 2010-03-24 10:31 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 10:31 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 03/24/2010 10:23 AM, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 09:25:08AM +0100, Hans de Goede wrote: >> See comments inline. >> >> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >>> Allow device probing to recognise the Fintek F71808E. >>> >>> Sysfs interface: >>> * Fan/pwm control is the same as for F71889FG >>> * Temperature and voltage sensor handling is largely the same as for >>> the F71889FG >>> - Has one temperature sensor less (doesn't have temp3) >>> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >>> what in7_input refers for F71889FG) >>> >>> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >>> such that it can largely be reused. >>> --- >>> Documentation/hwmon/f71882fg | 4 ++ >>> drivers/hwmon/Kconfig | 6 ++-- >>> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >>> 3 files changed, 79 insertions(+), 11 deletions(-) >>> >>> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >>> index 25e1cad..b290b87 100644 >>> --- a/drivers/hwmon/f71882fg.c >>> +++ b/drivers/hwmon/f71882fg.c >>> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >>> /* fall through! */ >>> case f71862fg: >>> err = f71882fg_create_sysfs_files(pdev, >>> - fxxxx_in_temp_attr, >>> - ARRAY_SIZE(fxxxx_in_temp_attr)); >>> + f71862_temp_attr, >>> + ARRAY_SIZE(f71862_temp_attr)); >>> + if (err) >>> + goto exit_unregister_sysfs; >>> + err = f71882fg_create_sysfs_files(pdev, >>> + fxxxx_in_attr, >>> + ARRAY_SIZE(fxxxx_in_attr)); >>> + if (err) >>> + goto exit_unregister_sysfs; >>> + /* fall through! */ >> >> Ugh, please don't fall through, and then have an if below to only do >> some parts of the case falling through. This is quite confusing >> at first I thought your code was buggy I had to read it twice to notice >> the if. Instead just duplicate the following lines: >>> + err = f71882fg_create_sysfs_files(pdev, >>> + fxxxx_temp_attr, >>> + ARRAY_SIZE(fxxxx_temp_attr)); >> In the f71862fg case, end the f71862fg case with a break and remove >> the if test from the f71808fg case. >> >>> + case f71808fg: >>> + if (data->type = f71808fg) { >>> + err = f71882fg_create_sysfs_files(pdev, >>> + f71808_in_attr, >>> + ARRAY_SIZE(f71808_in_attr)); >>> + if (err) >>> + goto exit_unregister_sysfs; >>> + } >>> + err = f71882fg_create_sysfs_files(pdev, >>> + fxxxx_temp_attr, >>> + ARRAY_SIZE(fxxxx_temp_attr)); >>> break; >>> case f8000: >>> err = f71882fg_create_sysfs_files(pdev, >>> @@ -2126,8 +2175,20 @@ static int f71882fg_remove(struct platform_device *pdev) >>> /* fall through! */ >>> case f71862fg: >>> f71882fg_remove_sysfs_files(pdev, >>> - fxxxx_in_temp_attr, >>> - ARRAY_SIZE(fxxxx_in_temp_attr)); >>> + f71862_temp_attr, >>> + ARRAY_SIZE(f71862_temp_attr)); >>> + f71882fg_remove_sysfs_files(pdev, >>> + fxxxx_in_attr, >>> + ARRAY_SIZE(fxxxx_in_attr)); >>> + /* fall through! */ >> >> Idem. > > Ack. New and improved patch follows this line. > ==================================== > hwmon: f71882fg: Add support for the Fintek F71808E > This new version looks good to me: Acked-by: Hans de Goede <hdegoede@redhat.com> Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E 2010-03-24 10:31 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Hans de Goede @ 2010-07-31 23:31 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-07-31 23:31 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 2752 bytes --] On Wed, Mar 24, 2010 at 11:31:40 +0100, Hans de Goede wrote: > On 03/24/2010 10:23, Giel van Schijndel wrote: >> On Wed, Mar 24, 2010 at 09:25:08 +0100, Hans de Goede wrote: >>> See comments inline. >>> >>> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >>>> Allow device probing to recognise the Fintek F71808E. >>>> >>>> Sysfs interface: >>>> * Fan/pwm control is the same as for F71889FG >>>> * Temperature and voltage sensor handling is largely the same as for >>>> the F71889FG >>>> - Has one temperature sensor less (doesn't have temp3) >>>> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >>>> what in7_input refers for F71889FG) >>>> >>>> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >>>> such that it can largely be reused. >>>>--- >>>> Documentation/hwmon/f71882fg | 4 ++ >>>> drivers/hwmon/Kconfig | 6 ++-- >>>> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >>>> 3 files changed, 79 insertions(+), 11 deletions(-) >>>> >>>> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >>>> index 25e1cad..b290b87 100644 >>>> --- a/drivers/hwmon/f71882fg.c >>>> +++ b/drivers/hwmon/f71882fg.c >>>> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >>>> ... snip ... >>>> + /* fall through! */ >>> >>> Ugh, please don't fall through, and then have an if below to only do >>> some parts of the case falling through. This is quite confusing at >>> first I thought your code was buggy I had to read it twice to notice >>> the if. Instead just duplicate the following lines: >>>> + err = f71882fg_create_sysfs_files(pdev, >>>> + fxxxx_temp_attr, >>>> + ARRAY_SIZE(fxxxx_temp_attr)); >>> In the f71862fg case, end the f71862fg case with a break and remove >>> the if test from the f71808fg case. >>> >>>>+ case f71808fg: >>>>+ if (data->type == f71808fg) { >>>>+ err = f71882fg_create_sysfs_files(pdev, >>>>+ f71808_in_attr, >>>>+ ARRAY_SIZE(f71808_in_attr)); >>>>+ if (err) >>>>+ goto exit_unregister_sysfs; >>>>+ } >>>>+ err = f71882fg_create_sysfs_files(pdev, >>>>+ fxxxx_temp_attr, >>>>+ ARRAY_SIZE(fxxxx_temp_attr)); >>>> ... snip ... >> >> Ack. New and improved patch follows this line. >> ===================================================================== >> hwmon: f71882fg: Add support for the Fintek F71808E > > This new version looks good to me: > Acked-by: Hans de Goede <hdegoede@redhat.com> Thanks. Anyone else I need to poke in order to set this on track to mainline? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the @ 2010-07-31 23:31 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-07-31 23:31 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 2752 bytes --] On Wed, Mar 24, 2010 at 11:31:40 +0100, Hans de Goede wrote: > On 03/24/2010 10:23, Giel van Schijndel wrote: >> On Wed, Mar 24, 2010 at 09:25:08 +0100, Hans de Goede wrote: >>> See comments inline. >>> >>> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >>>> Allow device probing to recognise the Fintek F71808E. >>>> >>>> Sysfs interface: >>>> * Fan/pwm control is the same as for F71889FG >>>> * Temperature and voltage sensor handling is largely the same as for >>>> the F71889FG >>>> - Has one temperature sensor less (doesn't have temp3) >>>> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >>>> what in7_input refers for F71889FG) >>>> >>>> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >>>> such that it can largely be reused. >>>>--- >>>> Documentation/hwmon/f71882fg | 4 ++ >>>> drivers/hwmon/Kconfig | 6 ++-- >>>> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >>>> 3 files changed, 79 insertions(+), 11 deletions(-) >>>> >>>> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >>>> index 25e1cad..b290b87 100644 >>>> --- a/drivers/hwmon/f71882fg.c >>>> +++ b/drivers/hwmon/f71882fg.c >>>> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >>>> ... snip ... >>>> + /* fall through! */ >>> >>> Ugh, please don't fall through, and then have an if below to only do >>> some parts of the case falling through. This is quite confusing at >>> first I thought your code was buggy I had to read it twice to notice >>> the if. Instead just duplicate the following lines: >>>> + err = f71882fg_create_sysfs_files(pdev, >>>> + fxxxx_temp_attr, >>>> + ARRAY_SIZE(fxxxx_temp_attr)); >>> In the f71862fg case, end the f71862fg case with a break and remove >>> the if test from the f71808fg case. >>> >>>>+ case f71808fg: >>>>+ if (data->type == f71808fg) { >>>>+ err = f71882fg_create_sysfs_files(pdev, >>>>+ f71808_in_attr, >>>>+ ARRAY_SIZE(f71808_in_attr)); >>>>+ if (err) >>>>+ goto exit_unregister_sysfs; >>>>+ } >>>>+ err = f71882fg_create_sysfs_files(pdev, >>>>+ fxxxx_temp_attr, >>>>+ ARRAY_SIZE(fxxxx_temp_attr)); >>>> ... snip ... >> >> Ack. New and improved patch follows this line. >> ===================================================================== >> hwmon: f71882fg: Add support for the Fintek F71808E > > This new version looks good to me: > Acked-by: Hans de Goede <hdegoede@redhat.com> Thanks. Anyone else I need to poke in order to set this on track to mainline? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E 2010-07-31 23:31 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Giel van Schijndel @ 2010-08-01 6:12 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-01 6:12 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 08/01/2010 01:31 AM, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 11:31:40 +0100, Hans de Goede wrote: >> On 03/24/2010 10:23, Giel van Schijndel wrote: >>> On Wed, Mar 24, 2010 at 09:25:08 +0100, Hans de Goede wrote: >>>> See comments inline. >>>> >>>> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >>>>> Allow device probing to recognise the Fintek F71808E. >>>>> >>>>> Sysfs interface: >>>>> * Fan/pwm control is the same as for F71889FG >>>>> * Temperature and voltage sensor handling is largely the same as for >>>>> the F71889FG >>>>> - Has one temperature sensor less (doesn't have temp3) >>>>> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >>>>> what in7_input refers for F71889FG) >>>>> >>>>> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >>>>> such that it can largely be reused. >>>>> --- >>>>> Documentation/hwmon/f71882fg | 4 ++ >>>>> drivers/hwmon/Kconfig | 6 ++-- >>>>> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >>>>> 3 files changed, 79 insertions(+), 11 deletions(-) >>>>> >>>>> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >>>>> index 25e1cad..b290b87 100644 >>>>> --- a/drivers/hwmon/f71882fg.c >>>>> +++ b/drivers/hwmon/f71882fg.c >>>>> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >>>>> ... snip ... >>>>> + /* fall through! */ >>>> >>>> Ugh, please don't fall through, and then have an if below to only do >>>> some parts of the case falling through. This is quite confusing at >>>> first I thought your code was buggy I had to read it twice to notice >>>> the if. Instead just duplicate the following lines: >>>>> + err = f71882fg_create_sysfs_files(pdev, >>>>> + fxxxx_temp_attr, >>>>> + ARRAY_SIZE(fxxxx_temp_attr)); >>>> In the f71862fg case, end the f71862fg case with a break and remove >>>> the if test from the f71808fg case. >>>> >>>>> + case f71808fg: >>>>> + if (data->type == f71808fg) { >>>>> + err = f71882fg_create_sysfs_files(pdev, >>>>> + f71808_in_attr, >>>>> + ARRAY_SIZE(f71808_in_attr)); >>>>> + if (err) >>>>> + goto exit_unregister_sysfs; >>>>> + } >>>>> + err = f71882fg_create_sysfs_files(pdev, >>>>> + fxxxx_temp_attr, >>>>> + ARRAY_SIZE(fxxxx_temp_attr)); >>>>> ... snip ... >>> >>> Ack. New and improved patch follows this line. >>> ===================================================================== >>> hwmon: f71882fg: Add support for the Fintek F71808E >> >> This new version looks good to me: >> Acked-by: Hans de Goede<hdegoede@redhat.com> > > Thanks. Anyone else I need to poke in order to set this on track to > mainline? > No, Jean should have picked this up, I guess it has fallen through the cracks. I think it is probably best if you resend this patch and the watchdog patches re-based against the latest upstream rc, then I'll re-review them and ack them and Jean can then put them into his tree. Thanks & Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the @ 2010-08-01 6:12 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-01 6:12 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, On 08/01/2010 01:31 AM, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 11:31:40 +0100, Hans de Goede wrote: >> On 03/24/2010 10:23, Giel van Schijndel wrote: >>> On Wed, Mar 24, 2010 at 09:25:08 +0100, Hans de Goede wrote: >>>> See comments inline. >>>> >>>> On 03/24/2010 12:12 AM, Giel van Schijndel wrote: >>>>> Allow device probing to recognise the Fintek F71808E. >>>>> >>>>> Sysfs interface: >>>>> * Fan/pwm control is the same as for F71889FG >>>>> * Temperature and voltage sensor handling is largely the same as for >>>>> the F71889FG >>>>> - Has one temperature sensor less (doesn't have temp3) >>>>> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >>>>> what in7_input refers for F71889FG) >>>>> >>>>> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >>>>> such that it can largely be reused. >>>>> --- >>>>> Documentation/hwmon/f71882fg | 4 ++ >>>>> drivers/hwmon/Kconfig | 6 ++-- >>>>> drivers/hwmon/f71882fg.c | 80 +++++++++++++++++++++++++++++++++++++---- >>>>> 3 files changed, 79 insertions(+), 11 deletions(-) >>>>> >>>>> diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c >>>>> index 25e1cad..b290b87 100644 >>>>> --- a/drivers/hwmon/f71882fg.c >>>>> +++ b/drivers/hwmon/f71882fg.c >>>>> @@ -1974,8 +2002,27 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) >>>>> ... snip ... >>>>> + /* fall through! */ >>>> >>>> Ugh, please don't fall through, and then have an if below to only do >>>> some parts of the case falling through. This is quite confusing at >>>> first I thought your code was buggy I had to read it twice to notice >>>> the if. Instead just duplicate the following lines: >>>>> + err = f71882fg_create_sysfs_files(pdev, >>>>> + fxxxx_temp_attr, >>>>> + ARRAY_SIZE(fxxxx_temp_attr)); >>>> In the f71862fg case, end the f71862fg case with a break and remove >>>> the if test from the f71808fg case. >>>> >>>>> + case f71808fg: >>>>> + if (data->type = f71808fg) { >>>>> + err = f71882fg_create_sysfs_files(pdev, >>>>> + f71808_in_attr, >>>>> + ARRAY_SIZE(f71808_in_attr)); >>>>> + if (err) >>>>> + goto exit_unregister_sysfs; >>>>> + } >>>>> + err = f71882fg_create_sysfs_files(pdev, >>>>> + fxxxx_temp_attr, >>>>> + ARRAY_SIZE(fxxxx_temp_attr)); >>>>> ... snip ... >>> >>> Ack. New and improved patch follows this line. >>> ==================================>>> hwmon: f71882fg: Add support for the Fintek F71808E >> >> This new version looks good to me: >> Acked-by: Hans de Goede<hdegoede@redhat.com> > > Thanks. Anyone else I need to poke in order to set this on track to > mainline? > No, Jean should have picked this up, I guess it has fallen through the cracks. I think it is probably best if you resend this patch and the watchdog patches re-based against the latest upstream rc, then I'll re-review them and ack them and Jean can then put them into his tree. Thanks & Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-01 6:12 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Hans de Goede @ 2010-08-01 13:22 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:22 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Wim Van Sebroeck, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1031 bytes --] On Sun, Aug 01, 2010 at 08:12:40 +0200, Hans de Goede wrote: > On 08/01/2010 01:31 AM, Giel van Schijndel wrote: >> On Wed, Mar 24, 2010 at 11:31:40 +0100, Hans de Goede wrote: >>> On 03/24/2010 10:23, Giel van Schijndel wrote: >>>> Ack. New and improved patch follows this line. >>>> =================================================================== >>>> hwmon: f71882fg: Add support for the Fintek F71808E >>> >>> This new version looks good to me: >>> Acked-by: Hans de Goede<hdegoede@redhat.com> >> >> Thanks. Anyone else I need to poke in order to set this on track to >> mainline? > > No, > > Jean should have picked this up, I guess it has fallen through the cracks. > > I think it is probably best if you resend this patch and the watchdog > patches re-based against the latest upstream rc, then I'll re-review > them and ack them and Jean can then put them into his tree. Ack. I'll resend them as replies to this mail. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the @ 2010-08-01 13:22 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:22 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Wim Van Sebroeck, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 1031 bytes --] On Sun, Aug 01, 2010 at 08:12:40 +0200, Hans de Goede wrote: > On 08/01/2010 01:31 AM, Giel van Schijndel wrote: >> On Wed, Mar 24, 2010 at 11:31:40 +0100, Hans de Goede wrote: >>> On 03/24/2010 10:23, Giel van Schijndel wrote: >>>> Ack. New and improved patch follows this line. >>>> =================================================================== >>>> hwmon: f71882fg: Add support for the Fintek F71808E >>> >>> This new version looks good to me: >>> Acked-by: Hans de Goede<hdegoede@redhat.com> >> >> Thanks. Anyone else I need to poke in order to set this on track to >> mainline? > > No, > > Jean should have picked this up, I guess it has fallen through the cracks. > > I think it is probably best if you resend this patch and the watchdog > patches re-based against the latest upstream rc, then I'll re-review > them and ack them and Jean can then put them into his tree. Ack. I'll resend them as replies to this mail. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-01 13:22 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Giel van Schijndel @ 2010-08-01 13:30 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:30 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Giel van Schijndel, Randy Dunlap, Hans de Goede, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Allow device probing to recognise the Fintek F71808E. Sysfs interface: * Fan/pwm control is the same as for F71889FG * Temperature and voltage sensor handling is largely the same as for the F71889FG - Has one temperature sensor less (doesn't have temp3) - Misses one voltage sensor (doesn't have V6, thus in6_input refers to what in7_input refers for F71889FG) For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up such that it can largely be reused. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- Documentation/hwmon/f71882fg | 4 ++ drivers/hwmon/Kconfig | 6 ++-- drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index a7952c2..1a07fd6 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -2,6 +2,10 @@ Kernel driver f71882fg ====================== Supported chips: + * Fintek F71808E + Prefix: 'f71808fg' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71858FG Prefix: 'f71858fg' Addresses scanned: none, address read from Super I/O config space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e19cf8e..7d0beac 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -332,11 +332,11 @@ config SENSORS_F71805F will be called f71805f. config SENSORS_F71882FG - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" depends on EXPERIMENTAL help - If you say yes here you get support for hardware monitoring - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, + If you say yes here you get support for hardware monitoring features + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, F71889FG and F8000 Super-I/O chips. This driver can also be built as a module. If so, the module diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index f4d2279..7857ed3 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -45,6 +45,7 @@ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ @@ -96,9 +97,10 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { + "f71808fg", "f71858fg", "f71862fg", "f71882fg", @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { +/* In attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* In attr for the f71808fg */ +static struct sensor_device_attribute_2 f71808_in_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 1), @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { store_temp_beep, 0, 6), SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), +}; + +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 f71862_temp_attr[] = { SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 3), @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->temp_type[1] = 6; break; } + } else if (data->type == f71808fg) { + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + data->temp_type[1] = (reg & 0x02) ? 2 : 4; + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + } else { reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) == 0x01) @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, val /= 1000; - if (data->type == f71889fg) + if (data->type == f71889fg + || data->type == f71808fg) val = SENSORS_LIMIT(val, -128, 127); else val = SENSORS_LIMIT(val, 0, 127); @@ -1974,8 +2002,28 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) /* fall through! */ case f71862fg: err = f71882fg_create_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + err = f71882fg_create_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: err = f71882fg_create_sysfs_files(pdev, @@ -2002,6 +2050,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71862fg: err = (data->pwm_enable & 0x15) != 0x15; break; + case f71808fg: case f71882fg: case f71889fg: err = 0; @@ -2047,6 +2096,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) f8000_auto_pwm_attr, ARRAY_SIZE(f8000_auto_pwm_attr)); break; + case f71808fg: case f71889fg: for (i = 0; i < nr_fans; i++) { data->pwm_auto_point_mapping[i] = @@ -2126,8 +2176,22 @@ static int f71882fg_remove(struct platform_device *pdev) /* fall through! */ case f71862fg: f71882fg_remove_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + f71882fg_remove_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: f71882fg_remove_sysfs_files(pdev, @@ -2195,6 +2259,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); switch (devid) { + case SIO_F71808_ID: + sio_data->type = f71808fg; + break; case SIO_F71858_ID: sio_data->type = f71858fg; break; -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Fintek @ 2010-08-01 13:30 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:30 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Giel van Schijndel, Randy Dunlap, Hans de Goede, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Allow device probing to recognise the Fintek F71808E. Sysfs interface: * Fan/pwm control is the same as for F71889FG * Temperature and voltage sensor handling is largely the same as for the F71889FG - Has one temperature sensor less (doesn't have temp3) - Misses one voltage sensor (doesn't have V6, thus in6_input refers to what in7_input refers for F71889FG) For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up such that it can largely be reused. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- Documentation/hwmon/f71882fg | 4 ++ drivers/hwmon/Kconfig | 6 ++-- drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg index a7952c2..1a07fd6 100644 --- a/Documentation/hwmon/f71882fg +++ b/Documentation/hwmon/f71882fg @@ -2,6 +2,10 @@ Kernel driver f71882fg =========== Supported chips: + * Fintek F71808E + Prefix: 'f71808fg' + Addresses scanned: none, address read from Super I/O config space + Datasheet: Not public * Fintek F71858FG Prefix: 'f71858fg' Addresses scanned: none, address read from Super I/O config space diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e19cf8e..7d0beac 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -332,11 +332,11 @@ config SENSORS_F71805F will be called f71805f. config SENSORS_F71882FG - tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000" + tristate "Fintek F71808E, F71858FG, F71862FG, F71882FG, F71889FG and F8000" depends on EXPERIMENTAL help - If you say yes here you get support for hardware monitoring - features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG, + If you say yes here you get support for hardware monitoring features + of the Fintek F71808E, F71858FG, F71862FG/71863FG, F71882FG/F71883FG, F71889FG and F8000 Super-I/O chips. This driver can also be built as a module. If so, the module diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index f4d2279..7857ed3 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -45,6 +45,7 @@ #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ #define SIO_F71858_ID 0x0507 /* Chipset ID */ #define SIO_F71862_ID 0x0601 /* Chipset ID */ #define SIO_F71882_ID 0x0541 /* Chipset ID */ @@ -96,9 +97,10 @@ static unsigned short force_id; module_param(force_id, ushort, 0); MODULE_PARM_DESC(force_id, "Override the detected device ID"); -enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg, f8000 }; static const char *f71882fg_names[] = { + "f71808fg", "f71858fg", "f71862fg", "f71882fg", @@ -306,8 +308,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = { SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), }; -/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ -static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { +/* In attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_in_attr[] = { SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), @@ -317,6 +319,22 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* In attr for the f71808fg */ +static struct sensor_device_attribute_2 f71808_in_attr[] = { + SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), + SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), + SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), + SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), + SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), + SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), + SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 7), + SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 8), +}; + +/* Temp attr common to the f71808fg, f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 fxxxx_temp_attr[] = { SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 1), @@ -355,6 +373,10 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = { store_temp_beep, 0, 6), SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), +}; + +/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */ +static struct sensor_device_attribute_2 f71862_temp_attr[] = { SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, store_temp_max, 0, 3), @@ -989,6 +1011,11 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->temp_type[1] = 6; break; } + } else if (data->type = f71808fg) { + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + data->temp_type[1] = (reg & 0x02) ? 2 : 4; + data->temp_type[2] = (reg & 0x04) ? 2 : 4; + } else { reg2 = f71882fg_read8(data, F71882FG_REG_PECI); if ((reg2 & 0x03) = 0x01) @@ -1871,7 +1898,8 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, val /= 1000; - if (data->type = f71889fg) + if (data->type = f71889fg + || data->type = f71808fg) val = SENSORS_LIMIT(val, -128, 127); else val = SENSORS_LIMIT(val, 0, 127); @@ -1974,8 +2002,28 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) /* fall through! */ case f71862fg: err = f71882fg_create_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + err = f71882fg_create_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + if (err) + goto exit_unregister_sysfs; + err = f71882fg_create_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: err = f71882fg_create_sysfs_files(pdev, @@ -2002,6 +2050,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) case f71862fg: err = (data->pwm_enable & 0x15) != 0x15; break; + case f71808fg: case f71882fg: case f71889fg: err = 0; @@ -2047,6 +2096,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) f8000_auto_pwm_attr, ARRAY_SIZE(f8000_auto_pwm_attr)); break; + case f71808fg: case f71889fg: for (i = 0; i < nr_fans; i++) { data->pwm_auto_point_mapping[i] @@ -2126,8 +2176,22 @@ static int f71882fg_remove(struct platform_device *pdev) /* fall through! */ case f71862fg: f71882fg_remove_sysfs_files(pdev, - fxxxx_in_temp_attr, - ARRAY_SIZE(fxxxx_in_temp_attr)); + f71862_temp_attr, + ARRAY_SIZE(f71862_temp_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_in_attr, + ARRAY_SIZE(fxxxx_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); + break; + case f71808fg: + f71882fg_remove_sysfs_files(pdev, + f71808_in_attr, + ARRAY_SIZE(f71808_in_attr)); + f71882fg_remove_sysfs_files(pdev, + fxxxx_temp_attr, + ARRAY_SIZE(fxxxx_temp_attr)); break; case f8000: f71882fg_remove_sysfs_files(pdev, @@ -2195,6 +2259,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); switch (devid) { + case SIO_F71808_ID: + sio_data->type = f71808fg; + break; case SIO_F71858_ID: sio_data->type = f71858fg; break; -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-01 13:30 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Fintek Giel van Schijndel (?) @ 2010-08-04 11:36 ` Hans de Goede 2010-08-04 15:44 ` Giel van Schijndel 2010-08-10 19:11 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Giel van Schijndel -1 siblings, 2 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-04 11:36 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Hi, I know I've reviewed this patch before, but now I have a datasheet so this time I've been a bit more thorough and I've found 2 small issues and 1 bigger one. Andrew can you please drop this patch from -mm until this is resolved? On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > Allow device probing to recognise the Fintek F71808E. > > Sysfs interface: > * Fan/pwm control is the same as for F71889FG My datasheet strongly disagrees with this the F71889FG has 5 pwm zones each with their own speed divided by 4 boundary temps, where as the F71808E has 3 pwm zones divided by 2 boundary temps. So it is much more like the F71862FG, which also has 2 boundary temps, and 3 pwm zones, *but* the F71862FG has one pwm zone hardwired to 100%. So it looks like you need to create a new f71808e_auto_pwm_attr array esp. for this model, as well as a special case for reading the auto pwm attr in f71882fg_update_device. Also the auto pwm of the F71808E allows following of digital temps read to peci / amdsi / ibex rather then following a directly connected temp diode like the F71889FG, which the driver does not support, so you should check if this is enabled and if so disable the auto pwm attr entirely. Code for this is already in place for the F71889FG, you simply need to make it trigger when the chip is a F71808E too. > * Temperature and voltage sensor handling is largely the same as for > the F71889FG > - Has one temperature sensor less (doesn't have temp3) > - Misses one voltage sensor (doesn't have V6, thus in6_input refers to > what in7_input refers for F71889FG) > > For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up > such that it can largely be reused. There is a problem here though, the new fxxxx_temp_attr contains attributes for temp#_max_beep and temp#_crit_beep, but the F71808E lacks that function. So I think that the new fxxxx_temp_attr need to be split into fxxxx_temp_attr and fxxxx_temp_beep_attr, like is already done with fxxxx_fan_attr. Also while making changes, I must say I don't like the splitting of fxxxx_temp_attr into fxxxx_temp_attr and f71862_temp_attr just because the number of sensors differs. I think it would be better to instead make fxxxx_temp_attr a 2 dimensional array like fxxxx_fan_attr and like with fxxxx_fan_attr register as many sensor attr blocks as the specific model has. > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > Documentation/hwmon/f71882fg | 4 ++ > drivers/hwmon/Kconfig | 6 ++-- > drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- > 3 files changed, 82 insertions(+), 11 deletions(-) > > diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg > index a7952c2..1a07fd6 100644 > --- a/Documentation/hwmon/f71882fg > +++ b/Documentation/hwmon/f71882fg > @@ -2,6 +2,10 @@ Kernel driver f71882fg > ====================== > > Supported chips: > + * Fintek F71808E > + Prefix: 'f71808fg' This is wrong, as you already indicate and the datasheet as well this chip in question is an f71808e not an f71808fg, also note that there is an f71808a model as well which is different (and has a different super io chip id). One last request in the second switch case in f71882fg_remove() there is a default label which contains a comment which models it applies to, please add the f71808e to that comment. Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-04 11:36 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede @ 2010-08-04 15:44 ` Giel van Schijndel 2010-08-13 10:56 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Hans de Goede 2010-08-10 19:11 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Giel van Schijndel 1 sibling, 1 reply; 159+ messages in thread From: Giel van Schijndel @ 2010-08-04 15:44 UTC (permalink / raw) To: Hans de Goede Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc [-- Attachment #1: Type: text/plain, Size: 7931 bytes --] On Wed, Aug 04, 2010 at 13:36:22 +0200, Hans de Goede wrote: > On 08/01/2010 03:30, Giel van Schijndel wrote: >> Allow device probing to recognise the Fintek F71808E. >> >> Sysfs interface: >> * Fan/pwm control is the same as for F71889FG > > My datasheet strongly disagrees with this the F71889FG has 5 pwm zones > each with their own speed divided by 4 boundary temps, where as > the F71808E has 3 pwm zones divided by 2 boundary temps. So it is much > more like the F71862FG, which also has 2 boundary temps, and 3 pwm zones, > *but* the F71862FG has one pwm zone hardwired to 100%. I'm assuming that by "pwm zone" you mean a separate PWM output channel? I.e. each "pwm zone" controls a single fan? Because in the datasheet I have for the F71889 only 3 fan controls are mentioned, not 5, it does however have 4 boundary temps: > 7.5. Hardware Monitor > ... snip ... > ... page 46-47: > Device registers, the following is a register map order which shows a > summary of all registers. Please refer each one register if you want > more detail information. > Register CR01 ~ CR03 -> Configuration Registers > Register CR0A ~ CR0F -> PECI/SST/TSI Control Register > Register CR10 ~ CR4F -> Voltage Setting Register > Register CR60 ~ CR8E -> Temperature Setting Register > Register CR90 ~ CRDF -> Fan Control Setting Register > -> Fan1 Detail Setting CRA0 ~ CRAF > -> Fan2 Detail Setting CRB0 ~ CRBF > -> Fan3 Detail Setting CRC0 ~ CRCF > Register CR5A ~ CR5D -> HW Chip ID and Vender ID Register > So it looks like you need to create a new f71808e_auto_pwm_attr array > esp. for this model, as well as a special case for reading the > auto pwm attr in f71882fg_update_device. Ack. > Also the auto pwm of the F71808E allows following of digital temps > read to peci / amdsi / ibex rather then following a directly connected > temp diode like the F71889FG, which the driver does not support, so > you should check if this is enabled and if so disable the auto pwm > attr entirely. Code for this is already in place for the F71889FG, > you simply need to make it trigger when the chip is a F71808E too. Do you mean the checking of the FANx_TEMP_SEL_DIG flag in the fan's "Temperature Mapping Select" registers currently done for the F71889 in the second switch-statement inside f71882fg_probe? As that code is already used for the F71808E as well. >> * Temperature and voltage sensor handling is largely the same as for >> the F71889FG >> - Has one temperature sensor less (doesn't have temp3) >> - Misses one voltage sensor (doesn't have V6, thus in6_input refers to >> what in7_input refers for F71889FG) >> >> For the purpose of the sysfs interface fxxxx_in_temp_attr[] is split up >> such that it can largely be reused. > > There is a problem here though, the new fxxxx_temp_attr contains > attributes for temp#_max_beep and temp#_crit_beep, but the F71808E > lacks that function. So I think that the new fxxxx_temp_attr > need to be split into fxxxx_temp_attr and fxxxx_temp_beep_attr, > like is already done with fxxxx_fan_attr. Ack. > Also while making changes, I must say I don't like the splitting > of fxxxx_temp_attr into fxxxx_temp_attr and f71862_temp_attr just because > the number of sensors differs. I think it would be better to instead > make fxxxx_temp_attr a 2 dimensional array like fxxxx_fan_attr and like > with fxxxx_fan_attr register as many sensor attr blocks as the specific > model has. Right, that's probably a nicer way of going about it, I think that might be easier done in a separate patch (most likely preceding the addition of F71808E support), though I'll look at that. >> Signed-off-by: Giel van Schijndel<me@mortis.eu> >> --- >> Documentation/hwmon/f71882fg | 4 ++ >> drivers/hwmon/Kconfig | 6 ++-- >> drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- >> 3 files changed, 82 insertions(+), 11 deletions(-) >> >> diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg >> index a7952c2..1a07fd6 100644 >> --- a/Documentation/hwmon/f71882fg >> +++ b/Documentation/hwmon/f71882fg >> @@ -2,6 +2,10 @@ Kernel driver f71882fg >> ====================== >> >> Supported chips: >> + * Fintek F71808E >> + Prefix: 'f71808fg' > > This is wrong, as you already indicate and the datasheet as well this > chip in question is an f71808e not an f71808fg, also note that there is > an f71808a model as well which is different (and has a different super io > chip id). Ah yes, I think I, wrongly, assumed that 'fg' was just some suffix used in this driver. For example, I cannot find F71889FG in the datasheet I have, only 'F71889' along with 'F71889F' in the section "Ordering Information" (for the F71889 I've got datasheet version V0.17P released December 2008). At the same time the F71808E datasheet I have clearly marks the chip as F71808E all over the entire datasheet (version V0.17P released October 2009). Either way I changed that ^^ portion of documentation while changing the enumeration value 'f71808fg' -> 'f71808e' in the code itself as well. > One last request in the second switch case in f71882fg_remove() > there is a default label which contains a comment which models it applies > to, please add the f71808e to that comment. Wouldn't it be better, to instead replace that 'default' label with a serie of case labels that code applies to? Along with providing the same documentation effect (expressed in C instead of English) it would cause GCC to warn whenever one of the chips was forgotten in a switch statement. E.g. something similar to this patch: ======================================================================== diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index b891b65..bfb2b4c 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2113,7 +2113,8 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) break; } /* fall through */ - default: /* f71858fg / f71882fg */ + case f71858fg: + case f71882fg: err = f71882fg_create_sysfs_files(pdev, &fxxxx_auto_pwm_attr[0][0], ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans); @@ -2224,7 +2225,10 @@ static int f71882fg_remove(struct platform_device *pdev) f8000_auto_pwm_attr, ARRAY_SIZE(f8000_auto_pwm_attr)); break; - default: /* f71808e / f71858fg / f71882fg / f71889fg */ + case f71808e: + case f71858fg: + case f71882fg: + case f71889fg: f71882fg_remove_sysfs_files(pdev, &fxxxx_auto_pwm_attr[0][0], ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans); ======================================================================== PS For comparison, which datasheet versions do you have? All Fintek datasheets I have access to: * F71808E - V0.17P, October 2009 * F71858 - V0.26P, July 2007 * F71862 - V0.28P, July 2008 * F71882 - V0.24P, November 2006 * F71889 - V0.17P, December 2008 Those most interesting are of course the F71808E, F71862 and F71889---as you refer to those in your text. This because I have already had experience with a hardware vendor giving me the wrong datasheets and would like to prevent any such mistakes from causing similar communication problems here. -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-04 15:44 ` Giel van Schijndel @ 2010-08-13 10:56 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-13 10:56 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Hi, On 08/04/2010 05:44 PM, Giel van Schijndel wrote: > On Wed, Aug 04, 2010 at 13:36:22 +0200, Hans de Goede wrote: >> On 08/01/2010 03:30, Giel van Schijndel wrote: >>> Allow device probing to recognise the Fintek F71808E. >>> >>> Sysfs interface: >>> * Fan/pwm control is the same as for F71889FG >> >> My datasheet strongly disagrees with this the F71889FG has 5 pwm zones >> each with their own speed divided by 4 boundary temps, where as >> the F71808E has 3 pwm zones divided by 2 boundary temps. So it is much >> more like the F71862FG, which also has 2 boundary temps, and 3 pwm zones, >> *but* the F71862FG has one pwm zone hardwired to 100%. > > I'm assuming that by "pwm zone" you mean a separate PWM output channel? > I.e. each "pwm zone" controls a single fan? > With pwm zone I mean the number of different speeds which can be programmed for one output channel, the temps divide the entire temp range into zones (number of zones == number of temps + 1) and for each zone one can then tell at what speed / pwm setting the fan should operate when the temperature is in that zone. <snip> >> Also while making changes, I must say I don't like the splitting >> of fxxxx_temp_attr into fxxxx_temp_attr and f71862_temp_attr just because >> the number of sensors differs. I think it would be better to instead >> make fxxxx_temp_attr a 2 dimensional array like fxxxx_fan_attr and like >> with fxxxx_fan_attr register as many sensor attr blocks as the specific >> model has. > > Right, that's probably a nicer way of going about it, I think that might > be easier done in a separate patch (most likely preceding the addition > of F71808E support), though I'll look at that. > Yes first splitting the attr in a separate patch would be very good. >>> Signed-off-by: Giel van Schijndel<me@mortis.eu> >>> --- >>> Documentation/hwmon/f71882fg | 4 ++ >>> drivers/hwmon/Kconfig | 6 ++-- >>> drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- >>> 3 files changed, 82 insertions(+), 11 deletions(-) >>> >>> diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg >>> index a7952c2..1a07fd6 100644 >>> --- a/Documentation/hwmon/f71882fg >>> +++ b/Documentation/hwmon/f71882fg >>> @@ -2,6 +2,10 @@ Kernel driver f71882fg >>> ====================== >>> >>> Supported chips: >>> + * Fintek F71808E >>> + Prefix: 'f71808fg' >> >> This is wrong, as you already indicate and the datasheet as well this >> chip in question is an f71808e not an f71808fg, also note that there is >> an f71808a model as well which is different (and has a different super io >> chip id). > > Ah yes, I think I, wrongly, assumed that 'fg' was just some suffix used > in this driver. For example, I cannot find F71889FG in the datasheet I > have, only 'F71889' along with 'F71889F' in the section "Ordering > Information" (for the F71889 I've got datasheet version V0.17P released > December 2008). > I have a V0.27P datasheet for the 71889, but yes the fg suffix does not seem to be mentioned anywhere in the datasheet not sure where it comes from. I do know however that there are now new chips coming out with different a and e suffixes so I suggest that we stay with fg for the old chips and use a and e to distuingish the new ones. > At the same time the F71808E datasheet I have clearly marks the chip as > F71808E all over the entire datasheet (version V0.17P released October > 2009). > Right. > Either way I changed that ^^ portion of documentation while changing the > enumeration value 'f71808fg' -> 'f71808e' in the code itself as well. > Good. >> One last request in the second switch case in f71882fg_remove() >> there is a default label which contains a comment which models it applies >> to, please add the f71808e to that comment. > > Wouldn't it be better, to instead replace that 'default' label with a > serie of case labels that code applies to? Along with providing the > same documentation effect (expressed in C instead of English) it would > cause GCC to warn whenever one of the chips was forgotten in a switch > statement. Ack, if you could do that that would be great! Please do that in a preparation patch though and not in the main patch. <snip> > PS For comparison, which datasheet versions do you have? > All Fintek datasheets I have access to: > * F71808E - V0.17P, October 2009 > * F71858 - V0.26P, July 2007 > * F71862 - V0.28P, July 2008 > * F71882 - V0.24P, November 2006 > * F71889 - V0.17P, December 2008 > > Those most interesting are of course the F71808E, F71862 and F71889---as > you refer to those in your text. This because I have already had > experience with a hardware vendor giving me the wrong datasheets and > would like to prevent any such mistakes from causing similar > communication problems here. Here is my list: F71612A_V020P.pdf F71808A_V0.15P.pdf F71808E_V0.20P.pdf F71858_V026P.pdf F71862_V028P.pdf F71869E_V0.19P.pdf F71869_V1.1.pdf F71882_V0.24P.pdf F71889E_V0.19P.pdf F71889_V0.27P.pdf F8000_REG.pdf Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the @ 2010-08-13 10:56 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-13 10:56 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Hi, On 08/04/2010 05:44 PM, Giel van Schijndel wrote: > On Wed, Aug 04, 2010 at 13:36:22 +0200, Hans de Goede wrote: >> On 08/01/2010 03:30, Giel van Schijndel wrote: >>> Allow device probing to recognise the Fintek F71808E. >>> >>> Sysfs interface: >>> * Fan/pwm control is the same as for F71889FG >> >> My datasheet strongly disagrees with this the F71889FG has 5 pwm zones >> each with their own speed divided by 4 boundary temps, where as >> the F71808E has 3 pwm zones divided by 2 boundary temps. So it is much >> more like the F71862FG, which also has 2 boundary temps, and 3 pwm zones, >> *but* the F71862FG has one pwm zone hardwired to 100%. > > I'm assuming that by "pwm zone" you mean a separate PWM output channel? > I.e. each "pwm zone" controls a single fan? > With pwm zone I mean the number of different speeds which can be programmed for one output channel, the temps divide the entire temp range into zones (number of zones = number of temps + 1) and for each zone one can then tell at what speed / pwm setting the fan should operate when the temperature is in that zone. <snip> >> Also while making changes, I must say I don't like the splitting >> of fxxxx_temp_attr into fxxxx_temp_attr and f71862_temp_attr just because >> the number of sensors differs. I think it would be better to instead >> make fxxxx_temp_attr a 2 dimensional array like fxxxx_fan_attr and like >> with fxxxx_fan_attr register as many sensor attr blocks as the specific >> model has. > > Right, that's probably a nicer way of going about it, I think that might > be easier done in a separate patch (most likely preceding the addition > of F71808E support), though I'll look at that. > Yes first splitting the attr in a separate patch would be very good. >>> Signed-off-by: Giel van Schijndel<me@mortis.eu> >>> --- >>> Documentation/hwmon/f71882fg | 4 ++ >>> drivers/hwmon/Kconfig | 6 ++-- >>> drivers/hwmon/f71882fg.c | 83 ++++++++++++++++++++++++++++++++++++++---- >>> 3 files changed, 82 insertions(+), 11 deletions(-) >>> >>> diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg >>> index a7952c2..1a07fd6 100644 >>> --- a/Documentation/hwmon/f71882fg >>> +++ b/Documentation/hwmon/f71882fg >>> @@ -2,6 +2,10 @@ Kernel driver f71882fg >>> =========== >>> >>> Supported chips: >>> + * Fintek F71808E >>> + Prefix: 'f71808fg' >> >> This is wrong, as you already indicate and the datasheet as well this >> chip in question is an f71808e not an f71808fg, also note that there is >> an f71808a model as well which is different (and has a different super io >> chip id). > > Ah yes, I think I, wrongly, assumed that 'fg' was just some suffix used > in this driver. For example, I cannot find F71889FG in the datasheet I > have, only 'F71889' along with 'F71889F' in the section "Ordering > Information" (for the F71889 I've got datasheet version V0.17P released > December 2008). > I have a V0.27P datasheet for the 71889, but yes the fg suffix does not seem to be mentioned anywhere in the datasheet not sure where it comes from. I do know however that there are now new chips coming out with different a and e suffixes so I suggest that we stay with fg for the old chips and use a and e to distuingish the new ones. > At the same time the F71808E datasheet I have clearly marks the chip as > F71808E all over the entire datasheet (version V0.17P released October > 2009). > Right. > Either way I changed that ^^ portion of documentation while changing the > enumeration value 'f71808fg' -> 'f71808e' in the code itself as well. > Good. >> One last request in the second switch case in f71882fg_remove() >> there is a default label which contains a comment which models it applies >> to, please add the f71808e to that comment. > > Wouldn't it be better, to instead replace that 'default' label with a > serie of case labels that code applies to? Along with providing the > same documentation effect (expressed in C instead of English) it would > cause GCC to warn whenever one of the chips was forgotten in a switch > statement. Ack, if you could do that that would be great! Please do that in a preparation patch though and not in the main patch. <snip> > PS For comparison, which datasheet versions do you have? > All Fintek datasheets I have access to: > * F71808E - V0.17P, October 2009 > * F71858 - V0.26P, July 2007 > * F71862 - V0.28P, July 2008 > * F71882 - V0.24P, November 2006 > * F71889 - V0.17P, December 2008 > > Those most interesting are of course the F71808E, F71862 and F71889---as > you refer to those in your text. This because I have already had > experience with a hardware vendor giving me the wrong datasheets and > would like to prevent any such mistakes from causing similar > communication problems here. Here is my list: F71612A_V020P.pdf F71808A_V0.15P.pdf F71808E_V0.20P.pdf F71858_V026P.pdf F71862_V028P.pdf F71869E_V0.19P.pdf F71869_V1.1.pdf F71882_V0.24P.pdf F71889E_V0.19P.pdf F71889_V0.27P.pdf F8000_REG.pdf Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-04 11:36 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede @ 2010-08-10 19:11 ` Giel van Schijndel 2010-08-10 19:11 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Giel van Schijndel 1 sibling, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-10 19:11 UTC (permalink / raw) To: Hans de Goede Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc [-- Attachment #1: Type: text/plain, Size: 1393 bytes --] On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >> Allow device probing to recognise the Fintek F71808E. >> >> Sysfs interface: >> * Fan/pwm control is the same as for F71889FG > > My datasheet strongly disagrees with this ... I just noticed this patch was applied to mainline anyway. Regardless, I will (try to) address these issues you raised. Right now however, I am prioritising personal stuff above this driver---bachelor's thesis and graduation presentation. When finished with that (september) I'll allocate time to these issues again. PS Those datasheets are written very poorly, although I have seen worse. And as a reader I tend to become more "lazy" when I discover the writer was "lazy" (not exactly by choice, more out of habit). Unfortunately that doesn't work very well as reading style with technical documentation, so this probably explains some of the errors in this current patch. PPS I do have a patch ready that addresses some of the issues you raised. Those are only the cosmetic changes though (e.g. change naming of chip, comment updates, etc.). Would you suggest me to send it right now already or wait until I have time to address the other issues as well? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the @ 2010-08-10 19:11 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-10 19:11 UTC (permalink / raw) To: Hans de Goede Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc [-- Attachment #1.1: Type: text/plain, Size: 1393 bytes --] On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >> Allow device probing to recognise the Fintek F71808E. >> >> Sysfs interface: >> * Fan/pwm control is the same as for F71889FG > > My datasheet strongly disagrees with this ... I just noticed this patch was applied to mainline anyway. Regardless, I will (try to) address these issues you raised. Right now however, I am prioritising personal stuff above this driver---bachelor's thesis and graduation presentation. When finished with that (september) I'll allocate time to these issues again. PS Those datasheets are written very poorly, although I have seen worse. And as a reader I tend to become more "lazy" when I discover the writer was "lazy" (not exactly by choice, more out of habit). Unfortunately that doesn't work very well as reading style with technical documentation, so this probably explains some of the errors in this current patch. PPS I do have a patch ready that addresses some of the issues you raised. Those are only the cosmetic changes though (e.g. change naming of chip, comment updates, etc.). Would you suggest me to send it right now already or wait until I have time to address the other issues as well? -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-10 19:11 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Giel van Schijndel @ 2010-08-13 10:01 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-13 10:01 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Hi, On 08/10/2010 09:11 PM, Giel van Schijndel wrote: > On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: >> On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >>> Allow device probing to recognise the Fintek F71808E. >>> >>> Sysfs interface: >>> * Fan/pwm control is the same as for F71889FG >> >> My datasheet strongly disagrees with this ... > > I just noticed this patch was applied to mainline anyway. Regardless, I > will (try to) address these issues you raised. > > Right now however, I am prioritising personal stuff above this > driver---bachelor's thesis and graduation presentation. When finished > with that (september) I'll allocate time to these issues again. > I've send a mail directly to akpm asking for this to be removed, hopefully this will help. > PPS I do have a patch ready that addresses some of the issues you > raised. Those are only the cosmetic changes though (e.g. change > naming of chip, comment updates, etc.). Would you suggest me to > send it right now already or wait until I have time to address the > other issues as well? My goal for 2.6.36 is to pull the patch, and then we can wait til all issues are fixed properly before re-introducing it. Regards, Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the @ 2010-08-13 10:01 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-13 10:01 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Andrew Morton, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Hi, On 08/10/2010 09:11 PM, Giel van Schijndel wrote: > On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: >> On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >>> Allow device probing to recognise the Fintek F71808E. >>> >>> Sysfs interface: >>> * Fan/pwm control is the same as for F71889FG >> >> My datasheet strongly disagrees with this ... > > I just noticed this patch was applied to mainline anyway. Regardless, I > will (try to) address these issues you raised. > > Right now however, I am prioritising personal stuff above this > driver---bachelor's thesis and graduation presentation. When finished > with that (september) I'll allocate time to these issues again. > I've send a mail directly to akpm asking for this to be removed, hopefully this will help. > PPS I do have a patch ready that addresses some of the issues you > raised. Those are only the cosmetic changes though (e.g. change > naming of chip, comment updates, etc.). Would you suggest me to > send it right now already or wait until I have time to address the > other issues as well? My goal for 2.6.36 is to pull the patch, and then we can wait til all issues are fixed properly before re-introducing it. Regards, Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-13 10:01 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Hans de Goede @ 2010-08-18 18:24 ` Andrew Morton -1 siblings, 0 replies; 159+ messages in thread From: Andrew Morton @ 2010-08-18 18:24 UTC (permalink / raw) To: Hans de Goede Cc: Giel van Schijndel, Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc On Fri, 13 Aug 2010 12:01:36 +0200 Hans de Goede <hdegoede@redhat.com> wrote: > Hi, > > On 08/10/2010 09:11 PM, Giel van Schijndel wrote: > > On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: > >> On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > >>> Allow device probing to recognise the Fintek F71808E. > >>> > >>> Sysfs interface: > >>> * Fan/pwm control is the same as for F71889FG > >> > >> My datasheet strongly disagrees with this ... > > > > I just noticed this patch was applied to mainline anyway. Regardless, I > > will (try to) address these issues you raised. > > > > Right now however, I am prioritising personal stuff above this > > driver---bachelor's thesis and graduation presentation. When finished > > with that (september) I'll allocate time to these issues again. > > > > I've send a mail directly to akpm asking for this to be removed, hopefully > this will help. It seems that I managed to muck up my paperwork and the patch was merged into mainline. We can revert it, or we can fix it up in place in time for 2.6.36. What do you guys suggest? ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the @ 2010-08-18 18:24 ` Andrew Morton 0 siblings, 0 replies; 159+ messages in thread From: Andrew Morton @ 2010-08-18 18:24 UTC (permalink / raw) To: Hans de Goede Cc: Giel van Schijndel, Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc On Fri, 13 Aug 2010 12:01:36 +0200 Hans de Goede <hdegoede@redhat.com> wrote: > Hi, > > On 08/10/2010 09:11 PM, Giel van Schijndel wrote: > > On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: > >> On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > >>> Allow device probing to recognise the Fintek F71808E. > >>> > >>> Sysfs interface: > >>> * Fan/pwm control is the same as for F71889FG > >> > >> My datasheet strongly disagrees with this ... > > > > I just noticed this patch was applied to mainline anyway. Regardless, I > > will (try to) address these issues you raised. > > > > Right now however, I am prioritising personal stuff above this > > driver---bachelor's thesis and graduation presentation. When finished > > with that (september) I'll allocate time to these issues again. > > > > I've send a mail directly to akpm asking for this to be removed, hopefully > this will help. It seems that I managed to muck up my paperwork and the patch was merged into mainline. We can revert it, or we can fix it up in place in time for 2.6.36. What do you guys suggest? _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-18 18:24 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Andrew Morton @ 2010-08-22 18:04 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-22 18:04 UTC (permalink / raw) To: Andrew Morton Cc: Giel van Schijndel, Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Hi, On 08/18/2010 08:24 PM, Andrew Morton wrote: > On Fri, 13 Aug 2010 12:01:36 +0200 > Hans de Goede<hdegoede@redhat.com> wrote: > >> Hi, >> >> On 08/10/2010 09:11 PM, Giel van Schijndel wrote: >>> On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: >>>> On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >>>>> Allow device probing to recognise the Fintek F71808E. >>>>> >>>>> Sysfs interface: >>>>> * Fan/pwm control is the same as for F71889FG >>>> >>>> My datasheet strongly disagrees with this ... >>> >>> I just noticed this patch was applied to mainline anyway. Regardless, I >>> will (try to) address these issues you raised. >>> >>> Right now however, I am prioritising personal stuff above this >>> driver---bachelor's thesis and graduation presentation. When finished >>> with that (september) I'll allocate time to these issues again. >>> >> >> I've send a mail directly to akpm asking for this to be removed, hopefully >> this will help. > > It seems that I managed to muck up my paperwork and the patch was > merged into mainline. > > We can revert it, or we can fix it up in place in time for 2.6.36. > What do you guys suggest? Since both Giel and I are low on time to work on this, and since missing hwmon support on a system is not really a big deal (for most users) I suggest that this patch is reverted until we find the time to do it properly. Regards, Hans p.s. I've already seen mails that you've dropped this patch from -mm, does that mean it thas been removed from mainly too ? If not please remove it from mainline / ask Linus to remove it. Thanks. Hans ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the @ 2010-08-22 18:04 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-08-22 18:04 UTC (permalink / raw) To: Andrew Morton Cc: Giel van Schijndel, Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc Hi, On 08/18/2010 08:24 PM, Andrew Morton wrote: > On Fri, 13 Aug 2010 12:01:36 +0200 > Hans de Goede<hdegoede@redhat.com> wrote: > >> Hi, >> >> On 08/10/2010 09:11 PM, Giel van Schijndel wrote: >>> On Wed, Aug 04, 2010 at 01:36:22PM +0200, Hans de Goede wrote: >>>> On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >>>>> Allow device probing to recognise the Fintek F71808E. >>>>> >>>>> Sysfs interface: >>>>> * Fan/pwm control is the same as for F71889FG >>>> >>>> My datasheet strongly disagrees with this ... >>> >>> I just noticed this patch was applied to mainline anyway. Regardless, I >>> will (try to) address these issues you raised. >>> >>> Right now however, I am prioritising personal stuff above this >>> driver---bachelor's thesis and graduation presentation. When finished >>> with that (september) I'll allocate time to these issues again. >>> >> >> I've send a mail directly to akpm asking for this to be removed, hopefully >> this will help. > > It seems that I managed to muck up my paperwork and the patch was > merged into mainline. > > We can revert it, or we can fix it up in place in time for 2.6.36. > What do you guys suggest? Since both Giel and I are low on time to work on this, and since missing hwmon support on a system is not really a big deal (for most users) I suggest that this patch is reverted until we find the time to do it properly. Regards, Hans p.s. I've already seen mails that you've dropped this patch from -mm, does that mean it thas been removed from mainly too ? If not please remove it from mainline / ask Linus to remove it. Thanks. Hans _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E 2010-08-22 18:04 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Hans de Goede @ 2010-08-22 18:28 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-22 18:28 UTC (permalink / raw) To: Hans de Goede Cc: Andrew Morton, Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc [-- Attachment #1: Type: text/plain, Size: 445 bytes --] On Sun, Aug 22, 2010 at 08:04:38PM +0200, Hans de Goede wrote: > p.s. > > I've already seen mails that you've dropped this patch from -mm, does that > mean it thas been removed from mainly too ? If not please remove it from > mainline / ask Linus to remove it. Checking .../torvalds/linux-2.6.git you can see it's been reverted in mainline (see commit f2e41e9). -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the @ 2010-08-22 18:28 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-22 18:28 UTC (permalink / raw) To: Hans de Goede Cc: Andrew Morton, Laurens Leemans, Jonathan Cameron, Randy Dunlap, Jean Delvare, Mark Brown, Samuel Ortiz, lm-sensors, linux-kernel, linux-doc [-- Attachment #1.1: Type: text/plain, Size: 445 bytes --] On Sun, Aug 22, 2010 at 08:04:38PM +0200, Hans de Goede wrote: > p.s. > > I've already seen mails that you've dropped this patch from -mm, does that > mean it thas been removed from mainly too ? If not please remove it from > mainline / ask Linus to remove it. Checking .../torvalds/linux-2.6.git you can see it's been reverted in mainline (see commit f2e41e9). -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-08-01 13:22 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Giel van Schijndel @ 2010-08-01 13:30 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:30 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Giel van Schijndel, Jean Delvare, Hans de Goede, lm-sensors, linux-kernel Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++------------- 1 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..267cb92 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,21 +2249,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2280,6 +2284,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2290,12 +2295,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2306,7 +2313,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock @ 2010-08-01 13:30 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:30 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Giel van Schijndel, Jean Delvare, Hans de Goede, lm-sensors, linux-kernel Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++------------- 1 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 7857ed3..267cb92 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2239,21 +2249,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2280,6 +2284,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2290,12 +2295,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address = 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2306,7 +2313,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH 2/2] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E and F71882FG 2010-08-01 13:30 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock Giel van Schijndel @ 2010-08-01 13:30 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:30 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Giel van Schijndel, Wim Van Sebroeck, Andrew Morton, Russell King, Tony Lindgren, Marc Zyngier, Thierry Reding, linux-watchdog, linux-kernel Add a new watchdog driver for the Fintek F71808E and F71882FG Super I/O controllers. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/f71808e_wdt.c | 768 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 780 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/f71808e_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index afcfacc..edfd57d 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -401,6 +401,17 @@ config ALIM7101_WDT Most people will say N. +config F71808E_WDT + tristate "Fintek F71808E and F71882FG Watchdog" + depends on X86 && EXPERIMENTAL + help + This is the driver for the hardware watchdog on the Fintek + F71808E and F71882FG Super I/O controllers. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called f71808e_wdt. + + config GEODE_WDT tristate "AMD Geode CS5535/CS5536 Watchdog" depends on CS5535_MFGPT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 72f3e20..9e3d616 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c new file mode 100644 index 0000000..7e5c266 --- /dev/null +++ b/drivers/watchdog/f71808e_wdt.c @@ -0,0 +1,768 @@ +/*************************************************************************** + * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * + * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * + * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/uaccess.h> +#include <linux/watchdog.h> + +#define DRVNAME "f71808e_wdt" + +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ +#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ +#define SIO_F71858_ID 0x0507 /* Chipset ID */ +#define SIO_F71862_ID 0x0601 /* Chipset ID */ +#define SIO_F71882_ID 0x0541 /* Chipset ID */ +#define SIO_F71889_ID 0x0723 /* Chipset ID */ + +#define F71882FG_REG_START 0x01 + +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static unsigned int start_withtimeout; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; + +static const char *f71808e_names[] = { + "f71808fg", + "f71858fg", + "f71862fg", + "f71882fg", + "f71889fg", +}; + +/* Super-I/O Function prototypes */ +static inline int superio_inb(int base, int reg); +static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); +static inline int superio_enter(int base); +static inline void superio_select(int base, int ld); +static inline void superio_exit(int base); + +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data watchdog = { + .lock = __MUTEX_INITIALIZER(watchdog.lock), +}; + +/* Super I/O functions */ +static inline int superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int superio_inw(int base, int reg) +{ + int val; + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); + return val; +} + +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline int superio_enter(int base) +{ + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + + /* according to the datasheet the key must be send twice! */ + outb(SIO_UNLOCK_KEY, base); + outb(SIO_UNLOCK_KEY, base); + + return 0; +} + +static inline void superio_select(int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void superio_exit(int base) +{ + outb(SIO_LOCK_KEY, base); + release_region(base, 2); +} + +static int watchdog_set_timeout(int timeout) +{ + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog.lock); + + watchdog.timeout = timeout; + if (timeout > 0xff) { + watchdog.timer_val = DIV_ROUND_UP(timeout, 60); + watchdog.minutes_mode = true; + } else { + watchdog.timer_val = timeout; + watchdog.minutes_mode = false; + } + + mutex_unlock(&watchdog.lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + + if (pw <= 1) { + watchdog.pulse_val = 0; + } else if (pw <= 25) { + watchdog.pulse_val = 1; + } else if (pw <= 125) { + watchdog.pulse_val = 2; + } else if (pw <= 5000) { + watchdog.pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog.pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_keepalive(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (watchdog.minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME, + watchdog.timer_val); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + /* Watchdog pin configuration */ + switch (watchdog.type) { + case f71808fg: + /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog.sioaddr, 0x2a, 3); + superio_clear_bit(watchdog.sioaddr, 0x2b, 3); + break; + + case f71882fg: + /* Set pin 56 to WDTRST# */ + superio_set_bit(watchdog.sioaddr, 0x29, 1); + break; + + default: + /* + * 'default' label to shut up the compiler and catch + * programmer errors + */ + err = -ENODEV; + goto exit_superio; + } + + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog.pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog.sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_superio: + superio_exit(watchdog.sioaddr); +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_stop(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + mutex_lock(&watchdog.lock); + status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog.lock); + + return status; +} + +static bool watchdog_is_running(void) +{ + /* + * if we fail to determine the watchdog's status assume it to be + * running to be on the safe side + */ + bool is_running = true; + + mutex_lock(&watchdog.lock); + if (superio_enter(watchdog.sioaddr)) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0)) + && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF) + & F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return is_running; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog.opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog.opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog.expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog.opened); + + if (!watchdog.expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c == 'V'); + } + + /* Properly order writes across fork()ed processes */ + mutex_lock(&watchdog.lock); + watchdog.expect_close = expect_close; + mutex_unlock(&watchdog.lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog.ident, + sizeof(watchdog.ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) + watchdog_stop(); + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog.timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(int sioaddr) +{ + int wdt_conf, err = 0; + + /* No need to lock watchdog.lock here because no entry points + * into the module have been registered yet. + */ + watchdog.sioaddr = sioaddr; + watchdog.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + + snprintf(watchdog.ident.identity, + sizeof(watchdog.ident.identity), "%s watchdog", + f71808e_names[watchdog.type]); + + err = superio_enter(sioaddr); + if (err) + return err; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); + watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS; + + superio_exit(sioaddr); + + err = watchdog_set_timeout(timeout); + if (err) + return err; + err = watchdog_set_pulse_width(pulse_width); + if (err) + return err; + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + return err; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME + ": starting timeout out of range\n"); + err = -EINVAL; + goto exit_miscdev; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_miscdev; + } + + mutex_lock(&watchdog.lock); + err = superio_enter(sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(sioaddr); + mutex_unlock(&watchdog.lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %u sec\n", + start_withtimeout); + } + + return 0; + +exit_unlock: + mutex_unlock(&watchdog.lock); +exit_miscdev: + misc_deregister(&watchdog_miscdev); +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); + + return err; +} + +static int __init f71808e_find(int sioaddr) +{ + u16 devid; + int err = superio_enter(sioaddr); + if (err) + return err; + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) { + pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; + goto exit; + } + + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); + switch (devid) { + case SIO_F71808_ID: + watchdog.type = f71808fg; + break; + case SIO_F71882_ID: + watchdog.type = f71882fg; + break; + case SIO_F71862_ID: + case SIO_F71889_ID: + /* These have a watchdog, though it isn't implemented (yet). */ + err = -ENOSYS; + goto exit; + case SIO_F71858_ID: + /* Confirmed (by datasheet) not to have a watchdog. */ + err = -ENODEV; + goto exit; + default: + printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n", + (unsigned int)devid); + err = -ENODEV; + goto exit; + } + + printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n", + f71808e_names[watchdog.type], + (int)superio_inb(sioaddr, SIO_REG_DEVREV)); +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71808e_init(void) +{ + static const unsigned short addrs[] = { 0x2e, 0x4e }; + int err = -ENODEV; + int i; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71808e_find(addrs[i]); + if (err == 0) + break; + } + if (i == ARRAY_SIZE(addrs)) + return err; + + return watchdog_init(addrs[i]); +} + +static void __exit f71808e_exit(void) +{ + if (watchdog_is_running()) { + printk(KERN_WARNING DRVNAME + ": Watchdog timer still running, stopping it\n"); + watchdog_stop(); + } + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); +} + +MODULE_DESCRIPTION("F71808E Watchdog Driver"); +MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>"); +MODULE_LICENSE("GPL"); + +module_init(f71808e_init); +module_exit(f71808e_exit); -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH 2/2] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E and F71882FG @ 2010-08-01 13:30 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-08-01 13:30 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Giel van Schijndel, Wim Van Sebroeck, Andrew Morton, Russell King, Tony Lindgren, Marc Zyngier, Thierry Reding, linux-watchdog, linux-kernel Add a new watchdog driver for the Fintek F71808E and F71882FG Super I/O controllers. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/watchdog/Kconfig | 11 + drivers/watchdog/Makefile | 1 + drivers/watchdog/f71808e_wdt.c | 768 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 780 insertions(+), 0 deletions(-) create mode 100644 drivers/watchdog/f71808e_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index afcfacc..edfd57d 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -401,6 +401,17 @@ config ALIM7101_WDT Most people will say N. +config F71808E_WDT + tristate "Fintek F71808E and F71882FG Watchdog" + depends on X86 && EXPERIMENTAL + help + This is the driver for the hardware watchdog on the Fintek + F71808E and F71882FG Super I/O controllers. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called f71808e_wdt. + + config GEODE_WDT tristate "AMD Geode CS5535/CS5536 Watchdog" depends on CS5535_MFGPT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 72f3e20..9e3d616 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c new file mode 100644 index 0000000..7e5c266 --- /dev/null +++ b/drivers/watchdog/f71808e_wdt.c @@ -0,0 +1,768 @@ +/*************************************************************************** + * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * + * Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com> * + * Copyright (C) 2010 Giel van Schijndel <me@mortis.eu> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/miscdevice.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/notifier.h> +#include <linux/reboot.h> +#include <linux/uaccess.h> +#include <linux/watchdog.h> + +#define DRVNAME "f71808e_wdt" + +#define SIO_F71808FG_LD_WDT 0x07 /* Watchdog timer logical device */ +#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71808_ID 0x0901 /* Chipset ID */ +#define SIO_F71858_ID 0x0507 /* Chipset ID */ +#define SIO_F71862_ID 0x0601 /* Chipset ID */ +#define SIO_F71882_ID 0x0541 /* Chipset ID */ +#define SIO_F71889_ID 0x0723 /* Chipset ID */ + +#define F71882FG_REG_START 0x01 + +#define F71808FG_REG_WDO_CONF 0xf0 +#define F71808FG_REG_WDT_CONF 0xf5 +#define F71808FG_REG_WD_TIME 0xf6 + +#define F71808FG_FLAG_WDOUT_EN 7 + +#define F71808FG_FLAG_WDTMOUT_STS 5 +#define F71808FG_FLAG_WD_EN 5 +#define F71808FG_FLAG_WD_PULSE 4 +#define F71808FG_FLAG_WD_UNIT 3 + +/* Default values */ +#define WATCHDOG_TIMEOUT 60 /* 1 minute default timeout */ +#define WATCHDOG_MAX_TIMEOUT (60 * 255) +#define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for + watchdog signal */ + +static unsigned short force_id; +module_param(force_id, ushort, 0); +MODULE_PARM_DESC(force_id, "Override the detected device ID"); + +static const int max_timeout = WATCHDOG_MAX_TIMEOUT; +static int timeout = 60; /* default timeout in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in seconds. 1<= timeout <=" + __MODULE_STRING(WATCHDOG_MAX_TIMEOUT) " (default=" + __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); + +static unsigned int pulse_width = WATCHDOG_PULSE_WIDTH; +module_param(pulse_width, uint, 0); +MODULE_PARM_DESC(pulse_width, + "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" + " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); + +static unsigned int start_withtimeout; +module_param(start_withtimeout, uint, 0); +MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" + " given initial timeout. Zero (default) disables this feature."); + +enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; + +static const char *f71808e_names[] = { + "f71808fg", + "f71858fg", + "f71862fg", + "f71882fg", + "f71889fg", +}; + +/* Super-I/O Function prototypes */ +static inline int superio_inb(int base, int reg); +static inline int superio_inw(int base, int reg); +static inline void superio_outb(int base, int reg, u8 val); +static inline void superio_set_bit(int base, int reg, int bit); +static inline void superio_clear_bit(int base, int reg, int bit); +static inline int superio_enter(int base); +static inline void superio_select(int base, int ld); +static inline void superio_exit(int base); + +struct watchdog_data { + unsigned short sioaddr; + enum chips type; + unsigned long opened; + struct mutex lock; + char expect_close; + struct watchdog_info ident; + + unsigned short timeout; + u8 timer_val; /* content for the wd_time register */ + char minutes_mode; + u8 pulse_val; /* pulse width flag */ + char pulse_mode; /* enable pulse output mode? */ + char caused_reboot; /* last reboot was by the watchdog */ +}; + +static struct watchdog_data watchdog = { + .lock = __MUTEX_INITIALIZER(watchdog.lock), +}; + +/* Super I/O functions */ +static inline int superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int superio_inw(int base, int reg) +{ + int val; + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); + return val; +} + +static inline void superio_outb(int base, int reg, u8 val) +{ + outb(reg, base); + outb(val, base + 1); +} + +static inline void superio_set_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __set_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline void superio_clear_bit(int base, int reg, int bit) +{ + unsigned long val = superio_inb(base, reg); + __clear_bit(bit, &val); + superio_outb(base, reg, val); +} + +static inline int superio_enter(int base) +{ + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)base); + return -EBUSY; + } + + /* according to the datasheet the key must be send twice! */ + outb(SIO_UNLOCK_KEY, base); + outb(SIO_UNLOCK_KEY, base); + + return 0; +} + +static inline void superio_select(int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void superio_exit(int base) +{ + outb(SIO_LOCK_KEY, base); + release_region(base, 2); +} + +static int watchdog_set_timeout(int timeout) +{ + if (timeout <= 0 + || timeout > max_timeout) { + printk(KERN_ERR DRVNAME ": watchdog timeout out of range\n"); + return -EINVAL; + } + + mutex_lock(&watchdog.lock); + + watchdog.timeout = timeout; + if (timeout > 0xff) { + watchdog.timer_val = DIV_ROUND_UP(timeout, 60); + watchdog.minutes_mode = true; + } else { + watchdog.timer_val = timeout; + watchdog.minutes_mode = false; + } + + mutex_unlock(&watchdog.lock); + + return 0; +} + +static int watchdog_set_pulse_width(unsigned int pw) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + + if (pw <= 1) { + watchdog.pulse_val = 0; + } else if (pw <= 25) { + watchdog.pulse_val = 1; + } else if (pw <= 125) { + watchdog.pulse_val = 2; + } else if (pw <= 5000) { + watchdog.pulse_val = 3; + } else { + printk(KERN_ERR DRVNAME ": pulse width out of range\n"); + err = -EINVAL; + goto exit_unlock; + } + + watchdog.pulse_mode = pw; + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_keepalive(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (watchdog.minutes_mode) + /* select minutes for timer units */ + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + else + /* select seconds for timer units */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + + /* Set timer value */ + superio_outb(watchdog.sioaddr, F71808FG_REG_WD_TIME, + watchdog.timer_val); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return err; +} + +static int watchdog_start(void) +{ + /* Make sure we don't die as soon as the watchdog is enabled below */ + int err = watchdog_keepalive(); + if (err) + return err; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + /* Watchdog pin configuration */ + switch (watchdog.type) { + case f71808fg: + /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ + superio_clear_bit(watchdog.sioaddr, 0x2a, 3); + superio_clear_bit(watchdog.sioaddr, 0x2b, 3); + break; + + case f71882fg: + /* Set pin 56 to WDTRST# */ + superio_set_bit(watchdog.sioaddr, 0x29, 1); + break; + + default: + /* + * 'default' label to shut up the compiler and catch + * programmer errors + */ + err = -ENODEV; + goto exit_superio; + } + + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + superio_set_bit(watchdog.sioaddr, SIO_REG_ENABLE, 0); + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDO_CONF, + F71808FG_FLAG_WDOUT_EN); + + superio_set_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + if (watchdog.pulse_mode) { + /* Select "pulse" output mode with given duration */ + u8 wdt_conf = superio_inb(watchdog.sioaddr, + F71808FG_REG_WDT_CONF); + + /* Set WD_PSWIDTH bits (1:0) */ + wdt_conf = (wdt_conf & 0xfc) | (watchdog.pulse_val & 0x03); + /* Set WD_PULSE to "pulse" mode */ + wdt_conf |= BIT(F71808FG_FLAG_WD_PULSE); + + superio_outb(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf); + } else { + /* Select "level" output mode */ + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_PULSE); + } + +exit_superio: + superio_exit(watchdog.sioaddr); +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_stop(void) +{ + int err = 0; + + mutex_lock(&watchdog.lock); + err = superio_enter(watchdog.sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + superio_clear_bit(watchdog.sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + + return err; +} + +static int watchdog_get_status(void) +{ + int status = 0; + + mutex_lock(&watchdog.lock); + status = (watchdog.caused_reboot) ? WDIOF_CARDRESET : 0; + mutex_unlock(&watchdog.lock); + + return status; +} + +static bool watchdog_is_running(void) +{ + /* + * if we fail to determine the watchdog's status assume it to be + * running to be on the safe side + */ + bool is_running = true; + + mutex_lock(&watchdog.lock); + if (superio_enter(watchdog.sioaddr)) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0)) + && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF) + & F71808FG_FLAG_WD_EN); + + superio_exit(watchdog.sioaddr); + +exit_unlock: + mutex_unlock(&watchdog.lock); + return is_running; +} + +/* /dev/watchdog api */ + +static int watchdog_open(struct inode *inode, struct file *file) +{ + int err; + + /* If the watchdog is alive we don't need to start it again */ + if (test_and_set_bit(0, &watchdog.opened)) + return -EBUSY; + + err = watchdog_start(); + if (err) { + clear_bit(0, &watchdog.opened); + return err; + } + + if (nowayout) + __module_get(THIS_MODULE); + + watchdog.expect_close = 0; + return nonseekable_open(inode, file); +} + +static int watchdog_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &watchdog.opened); + + if (!watchdog.expect_close) { + watchdog_keepalive(); + printk(KERN_CRIT DRVNAME + ": Unexpected close, not stopping watchdog!\n"); + } else if (!nowayout) { + watchdog_stop(); + } + return 0; +} + +/* + * watchdog_write: + * @file: file handle to the watchdog + * @buf: buffer to write + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t watchdog_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + bool expect_close = false; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + expect_close = (c == 'V'); + } + + /* Properly order writes across fork()ed processes */ + mutex_lock(&watchdog.lock); + watchdog.expect_close = expect_close; + mutex_unlock(&watchdog.lock); + } + + /* someone wrote to us, we should restart timer */ + watchdog_keepalive(); + } + return count; +} + +/* + * watchdog_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. + */ +static long watchdog_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + int status; + int new_options; + int new_timeout; + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + uarg.i = (int __user *)arg; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &watchdog.ident, + sizeof(watchdog.ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + status = watchdog_get_status(); + if (status < 0) + return status; + return put_user(status, uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_SETOPTIONS: + if (get_user(new_options, uarg.i)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) + watchdog_stop(); + + if (new_options & WDIOS_ENABLECARD) + return watchdog_start(); + + + case WDIOC_KEEPALIVE: + watchdog_keepalive(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + if (watchdog_set_timeout(new_timeout)) + return -EINVAL; + + watchdog_keepalive(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(watchdog.timeout, uarg.i); + + default: + return -ENOTTY; + + } +} + +static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + watchdog_stop(); + return NOTIFY_DONE; +} + +static const struct file_operations watchdog_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .open = watchdog_open, + .release = watchdog_release, + .write = watchdog_write, + .unlocked_ioctl = watchdog_ioctl, +}; + +static struct miscdevice watchdog_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &watchdog_fops, +}; + +static struct notifier_block watchdog_notifier = { + .notifier_call = watchdog_notify_sys, +}; + +static int __init watchdog_init(int sioaddr) +{ + int wdt_conf, err = 0; + + /* No need to lock watchdog.lock here because no entry points + * into the module have been registered yet. + */ + watchdog.sioaddr = sioaddr; + watchdog.ident.options = WDIOC_SETTIMEOUT + | WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING; + + snprintf(watchdog.ident.identity, + sizeof(watchdog.ident.identity), "%s watchdog", + f71808e_names[watchdog.type]); + + err = superio_enter(sioaddr); + if (err) + return err; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); + watchdog.caused_reboot = wdt_conf & F71808FG_FLAG_WDTMOUT_STS; + + superio_exit(sioaddr); + + err = watchdog_set_timeout(timeout); + if (err) + return err; + err = watchdog_set_pulse_width(pulse_width); + if (err) + return err; + + err = register_reboot_notifier(&watchdog_notifier); + if (err) + return err; + + err = misc_register(&watchdog_miscdev); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot register miscdev on minor=%d\n", + watchdog_miscdev.minor); + goto exit_reboot; + } + + if (start_withtimeout) { + if (start_withtimeout <= 0 + || start_withtimeout > max_timeout) { + printk(KERN_ERR DRVNAME + ": starting timeout out of range\n"); + err = -EINVAL; + goto exit_miscdev; + } + + err = watchdog_start(); + if (err) { + printk(KERN_ERR DRVNAME + ": cannot start watchdog timer\n"); + goto exit_miscdev; + } + + mutex_lock(&watchdog.lock); + err = superio_enter(sioaddr); + if (err) + goto exit_unlock; + superio_select(watchdog.sioaddr, SIO_F71808FG_LD_WDT); + + if (start_withtimeout > 0xff) { + /* select minutes for timer units */ + superio_set_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + DIV_ROUND_UP(start_withtimeout, 60)); + } else { + /* select seconds for timer units */ + superio_clear_bit(sioaddr, F71808FG_REG_WDT_CONF, + F71808FG_FLAG_WD_UNIT); + superio_outb(sioaddr, F71808FG_REG_WD_TIME, + start_withtimeout); + } + + superio_exit(sioaddr); + mutex_unlock(&watchdog.lock); + + if (nowayout) + __module_get(THIS_MODULE); + + printk(KERN_INFO DRVNAME + ": watchdog started with initial timeout of %u sec\n", + start_withtimeout); + } + + return 0; + +exit_unlock: + mutex_unlock(&watchdog.lock); +exit_miscdev: + misc_deregister(&watchdog_miscdev); +exit_reboot: + unregister_reboot_notifier(&watchdog_notifier); + + return err; +} + +static int __init f71808e_find(int sioaddr) +{ + u16 devid; + int err = superio_enter(sioaddr); + if (err) + return err; + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) { + pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; + goto exit; + } + + devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); + switch (devid) { + case SIO_F71808_ID: + watchdog.type = f71808fg; + break; + case SIO_F71882_ID: + watchdog.type = f71882fg; + break; + case SIO_F71862_ID: + case SIO_F71889_ID: + /* These have a watchdog, though it isn't implemented (yet). */ + err = -ENOSYS; + goto exit; + case SIO_F71858_ID: + /* Confirmed (by datasheet) not to have a watchdog. */ + err = -ENODEV; + goto exit; + default: + printk(KERN_INFO DRVNAME ": Unrecognized Fintek device: %04x\n", + (unsigned int)devid); + err = -ENODEV; + goto exit; + } + + printk(KERN_INFO DRVNAME ": Found %s watchdog chip, revision %d\n", + f71808e_names[watchdog.type], + (int)superio_inb(sioaddr, SIO_REG_DEVREV)); +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71808e_init(void) +{ + static const unsigned short addrs[] = { 0x2e, 0x4e }; + int err = -ENODEV; + int i; + + for (i = 0; i < ARRAY_SIZE(addrs); i++) { + err = f71808e_find(addrs[i]); + if (err == 0) + break; + } + if (i == ARRAY_SIZE(addrs)) + return err; + + return watchdog_init(addrs[i]); +} + +static void __exit f71808e_exit(void) +{ + if (watchdog_is_running()) { + printk(KERN_WARNING DRVNAME + ": Watchdog timer still running, stopping it\n"); + watchdog_stop(); + } + misc_deregister(&watchdog_miscdev); + unregister_reboot_notifier(&watchdog_notifier); +} + +MODULE_DESCRIPTION("F71808E Watchdog Driver"); +MODULE_AUTHOR("Giel van Schijndel <me@mortis.eu>"); +MODULE_LICENSE("GPL"); + +module_init(f71808e_init); +module_exit(f71808e_exit); -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-08-01 13:30 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock Giel van Schijndel (?) (?) @ 2010-08-04 11:38 ` Hans de Goede 2010-10-02 22:59 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource Giel van Schijndel -1 siblings, 1 reply; 159+ messages in thread From: Hans de Goede @ 2010-08-04 11:38 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Jean Delvare, lm-sensors, linux-kernel Ack! Acked-by: Hans de Goede <hdegoede@redhat.com> On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > Sleep while acquiring a resource lock on the Super I/O port. This should > prevent collisions from causing the hardware probe to fail with -EBUSY. > > Signed-off-by: Giel van Schijndel<me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++------------- > 1 files changed, 19 insertions(+), 13 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 7857ed3..267cb92 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -113,7 +113,7 @@ static struct platform_device *f71882fg_pdev; > /* Super-I/O Function prototypes */ > static inline int superio_inb(int base, int reg); > static inline int superio_inw(int base, int reg); > -static inline void superio_enter(int base); > +static inline int superio_enter(int base); > static inline void superio_select(int base, int ld); > static inline void superio_exit(int base); > > @@ -883,11 +883,20 @@ static int superio_inw(int base, int reg) > return val; > } > > -static inline void superio_enter(int base) > +static inline int superio_enter(int base) > { > + /* Don't step on other drivers' I/O space by accident */ > + if (!request_muxed_region(base, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + base); > + return -EBUSY; > + } > + > /* according to the datasheet the key must be send twice! */ > outb(SIO_UNLOCK_KEY, base); > outb(SIO_UNLOCK_KEY, base); > + > + return 0; > } > > static inline void superio_select(int base, int ld) > @@ -899,6 +908,7 @@ static inline void superio_select(int base, int ld) > static inline void superio_exit(int base) > { > outb(SIO_LOCK_KEY, base); > + release_region(base, 2); > } > > static inline int fan_from_reg(u16 reg) > @@ -2239,21 +2249,15 @@ static int f71882fg_remove(struct platform_device *pdev) > static int __init f71882fg_find(int sioaddr, unsigned short *address, > struct f71882fg_sio_data *sio_data) > { > - int err = -ENODEV; > u16 devid; > - > - /* Don't step on other drivers' I/O space by accident */ > - if (!request_region(sioaddr, 2, DRVNAME)) { > - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > - (int)sioaddr); > - return -EBUSY; > - } > - > - superio_enter(sioaddr); > + int err = superio_enter(sioaddr); > + if (err) > + return err; > > devid = superio_inw(sioaddr, SIO_REG_MANID); > if (devid != SIO_FINTEK_ID) { > pr_debug(DRVNAME ": Not a Fintek device\n"); > + err = -ENODEV; > goto exit; > } > > @@ -2280,6 +2284,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > default: > printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", > (unsigned int)devid); > + err = -ENODEV; > goto exit; > } > > @@ -2290,12 +2295,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > > if (!(superio_inb(sioaddr, SIO_REG_ENABLE)& 0x01)) { > printk(KERN_WARNING DRVNAME ": Device not activated\n"); > + err = -ENODEV; > goto exit; > } > > *address = superio_inw(sioaddr, SIO_REG_ADDR); > if (*address == 0) { > printk(KERN_WARNING DRVNAME ": Base address not set\n"); > + err = -ENODEV; > goto exit; > } > *address&= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ > @@ -2306,7 +2313,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > - release_region(sioaddr, 2); > return err; > } > ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-08-04 11:38 ` [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Hans de Goede @ 2010-10-02 22:59 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-10-02 22:59 UTC (permalink / raw) To: Hans de Goede Cc: Laurens Leemans, Jonathan Cameron, Jean Delvare, Guenter Roeck, Andrew Morton, lm-sensors, linux-kernel, 597820 [-- Attachment #1: Type: text/plain, Size: 1171 bytes --] On Wed, Aug 04, 2010 at 01:38:50PM +0200, Hans de Goede wrote: > Ack! > > Acked-by: Hans de Goede <hdegoede@redhat.com> > > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >> Sleep while acquiring a resource lock on the Super I/O port. This should >> prevent collisions from causing the hardware probe to fail with -EBUSY. >> >> Signed-off-by: Giel van Schijndel<me@mortis.eu> Would anyone please apply this patch? It's been sitting for quite some time now collecting dust (none of that fictional bit-rot thus far however). If this patch needs to be resubmitted or requires me to poke a specific individual please let me know (and what individual to poke). FYI the Message-ID of that patch is: <1280669455-31283-1-git-send-email-me@mortis.eu> PS I've added Guenter Roeck and Andrew Morton to the CC list because between now and the original submission date they got appended to scripts/get_maintainer.pl's output. -- Met vriendelijke groet, With kind regards, Giel van Schijndel -- "It would seem that perfection is attained not when no more can be added, but when no more can be removed." -- Antoine de Saint Exupéry [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource @ 2010-10-02 22:59 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-10-02 22:59 UTC (permalink / raw) To: Hans de Goede Cc: Laurens Leemans, Jonathan Cameron, Jean Delvare, Guenter Roeck, Andrew Morton, lm-sensors, linux-kernel, 597820 [-- Attachment #1.1: Type: text/plain, Size: 1171 bytes --] On Wed, Aug 04, 2010 at 01:38:50PM +0200, Hans de Goede wrote: > Ack! > > Acked-by: Hans de Goede <hdegoede@redhat.com> > > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: >> Sleep while acquiring a resource lock on the Super I/O port. This should >> prevent collisions from causing the hardware probe to fail with -EBUSY. >> >> Signed-off-by: Giel van Schijndel<me@mortis.eu> Would anyone please apply this patch? It's been sitting for quite some time now collecting dust (none of that fictional bit-rot thus far however). If this patch needs to be resubmitted or requires me to poke a specific individual please let me know (and what individual to poke). FYI the Message-ID of that patch is: <1280669455-31283-1-git-send-email-me@mortis.eu> PS I've added Guenter Roeck and Andrew Morton to the CC list because between now and the original submission date they got appended to scripts/get_maintainer.pl's output. -- Met vriendelijke groet, With kind regards, Giel van Schijndel -- "It would seem that perfection is attained not when no more can be added, but when no more can be removed." -- Antoine de Saint Exupéry [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-10-02 22:59 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource Giel van Schijndel @ 2010-10-03 1:06 ` Guenter Roeck -1 siblings, 0 replies; 159+ messages in thread From: Guenter Roeck @ 2010-10-03 1:06 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Laurens Leemans, Jonathan Cameron, Jean Delvare, Andrew Morton, lm-sensors, linux-kernel, 597820 On Sat, Oct 02, 2010 at 06:59:58PM -0400, Giel van Schijndel wrote: > On Wed, Aug 04, 2010 at 01:38:50PM +0200, Hans de Goede wrote: > > Ack! > > > > Acked-by: Hans de Goede <hdegoede@redhat.com> > > > > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > >> Sleep while acquiring a resource lock on the Super I/O port. This should > >> prevent collisions from causing the hardware probe to fail with -EBUSY. > >> > >> Signed-off-by: Giel van Schijndel<me@mortis.eu> > Acked-by: Guenter Roeck <guenter.roeck@ericsson.com> Jean, if it is ok with you, I can apply it to my tree. I tried to find the patch on the web in downloadable form, but didn't find the correct version of it. So it would be great if you could re-send it. Thanks, Guenter ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource @ 2010-10-03 1:06 ` Guenter Roeck 0 siblings, 0 replies; 159+ messages in thread From: Guenter Roeck @ 2010-10-03 1:06 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Laurens Leemans, Jonathan Cameron, Jean Delvare, Andrew Morton, lm-sensors, linux-kernel, 597820 On Sat, Oct 02, 2010 at 06:59:58PM -0400, Giel van Schijndel wrote: > On Wed, Aug 04, 2010 at 01:38:50PM +0200, Hans de Goede wrote: > > Ack! > > > > Acked-by: Hans de Goede <hdegoede@redhat.com> > > > > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > >> Sleep while acquiring a resource lock on the Super I/O port. This should > >> prevent collisions from causing the hardware probe to fail with -EBUSY. > >> > >> Signed-off-by: Giel van Schijndel<me@mortis.eu> > Acked-by: Guenter Roeck <guenter.roeck@ericsson.com> Jean, if it is ok with you, I can apply it to my tree. I tried to find the patch on the web in downloadable form, but didn't find the correct version of it. So it would be great if you could re-send it. Thanks, Guenter _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-10-03 1:06 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource Guenter Roeck @ 2010-10-03 9:01 ` Jean Delvare -1 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-10-03 9:01 UTC (permalink / raw) To: Guenter Roeck Cc: Giel van Schijndel, Hans de Goede, Laurens Leemans, Jonathan Cameron, Andrew Morton, lm-sensors, linux-kernel, 597820 On Sat, 2 Oct 2010 18:06:35 -0700, Guenter Roeck wrote: > On Sat, Oct 02, 2010 at 06:59:58PM -0400, Giel van Schijndel wrote: > > On Wed, Aug 04, 2010 at 01:38:50PM +0200, Hans de Goede wrote: > > > Ack! > > > > > > Acked-by: Hans de Goede <hdegoede@redhat.com> > > > > > > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > > >> Sleep while acquiring a resource lock on the Super I/O port. This should > > >> prevent collisions from causing the hardware probe to fail with -EBUSY. > > >> > > >> Signed-off-by: Giel van Schijndel<me@mortis.eu> > > > Acked-by: Guenter Roeck <guenter.roeck@ericsson.com> > > Jean, if it is ok with you, I can apply it to my tree. I have no objection. I never had the time to look at these patches, and won't have it any time soon. So I'm very happy if you can handle them. > I tried to find the patch on the web in downloadable form, but didn't find > the correct version of it. So it would be great if you could re-send it. -- Jean Delvare ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource @ 2010-10-03 9:01 ` Jean Delvare 0 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-10-03 9:01 UTC (permalink / raw) To: Guenter Roeck Cc: Giel van Schijndel, Hans de Goede, Laurens Leemans, Jonathan Cameron, Andrew Morton, lm-sensors, linux-kernel, 597820 On Sat, 2 Oct 2010 18:06:35 -0700, Guenter Roeck wrote: > On Sat, Oct 02, 2010 at 06:59:58PM -0400, Giel van Schijndel wrote: > > On Wed, Aug 04, 2010 at 01:38:50PM +0200, Hans de Goede wrote: > > > Ack! > > > > > > Acked-by: Hans de Goede <hdegoede@redhat.com> > > > > > > On 08/01/2010 03:30 PM, Giel van Schijndel wrote: > > >> Sleep while acquiring a resource lock on the Super I/O port. This should > > >> prevent collisions from causing the hardware probe to fail with -EBUSY. > > >> > > >> Signed-off-by: Giel van Schijndel<me@mortis.eu> > > > Acked-by: Guenter Roeck <guenter.roeck@ericsson.com> > > Jean, if it is ok with you, I can apply it to my tree. I have no objection. I never had the time to look at these patches, and won't have it any time soon. So I'm very happy if you can handle them. > I tried to find the patch on the web in downloadable form, but didn't find > the correct version of it. So it would be great if you could re-send it. -- Jean Delvare _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* [PATCH] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-10-03 1:06 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource Guenter Roeck @ 2010-10-03 12:09 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-10-03 12:09 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Debian Bug #597820, Giel van Schijndel, Jean Delvare, Guenter Roeck, Hans de Goede, Andrew Morton, lm-sensors, linux-kernel Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++------------- 1 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 537841e..75afb3b 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -111,7 +111,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -861,11 +861,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -877,6 +886,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2175,21 +2185,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2213,6 +2217,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2223,12 +2228,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2239,7 +2246,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH] hwmon: f71882fg: use a muxed resource lock for @ 2010-10-03 12:09 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-10-03 12:09 UTC (permalink / raw) Cc: Laurens Leemans, Jonathan Cameron, Debian Bug #597820, Giel van Schijndel, Jean Delvare, Guenter Roeck, Hans de Goede, Andrew Morton, lm-sensors, linux-kernel Sleep while acquiring a resource lock on the Super I/O port. This should prevent collisions from causing the hardware probe to fail with -EBUSY. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 32 +++++++++++++++++++------------- 1 files changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 537841e..75afb3b 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -111,7 +111,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -861,11 +861,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -877,6 +886,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2175,21 +2185,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2213,6 +2217,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2223,12 +2228,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address = 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2239,7 +2246,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: use a muxed resource lock for the Super I/O port 2010-10-03 12:09 ` [lm-sensors] [PATCH] hwmon: f71882fg: use a muxed resource lock for Giel van Schijndel @ 2010-10-03 13:31 ` Guenter Roeck -1 siblings, 0 replies; 159+ messages in thread From: Guenter Roeck @ 2010-10-03 13:31 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Debian Bug #597820, Jean Delvare, Hans de Goede, Andrew Morton, lm-sensors, linux-kernel On Sun, Oct 03, 2010 at 08:09:49AM -0400, Giel van Schijndel wrote: > Sleep while acquiring a resource lock on the Super I/O port. This should > prevent collisions from causing the hardware probe to fail with -EBUSY. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> Applied. Guenter ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: use a muxed resource lock @ 2010-10-03 13:31 ` Guenter Roeck 0 siblings, 0 replies; 159+ messages in thread From: Guenter Roeck @ 2010-10-03 13:31 UTC (permalink / raw) To: Giel van Schijndel Cc: Laurens Leemans, Jonathan Cameron, Debian Bug #597820, Jean Delvare, Hans de Goede, Andrew Morton, lm-sensors, linux-kernel On Sun, Oct 03, 2010 at 08:09:49AM -0400, Giel van Schijndel wrote: > Sleep while acquiring a resource lock on the Super I/O port. This should > prevent collisions from causing the hardware probe to fail with -EBUSY. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> Applied. Guenter _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-23 14:12 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O regions Giel van Schijndel @ 2010-03-23 23:01 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:01 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 820 bytes --] On Tue, Mar 23, 2010 at 03:12:15PM +0100, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. > --- > drivers/hwmon/f71882fg.c | 38 +++++++++++++++++++++++--------------- > 1 files changed, 23 insertions(+), 15 deletions(-) Sorry, forgot to sign off the commit message itself. So just to be sure it's understood to be signed off on by myself: Signed-off-by: Giel van Schijndel <me@mortis.eu> -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-23 23:01 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-23 23:01 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 820 bytes --] On Tue, Mar 23, 2010 at 03:12:15PM +0100, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. > --- > drivers/hwmon/f71882fg.c | 38 +++++++++++++++++++++++--------------- > 1 files changed, 23 insertions(+), 15 deletions(-) Sorry, forgot to sign off the commit message itself. So just to be sure it's understood to be signed off on by myself: Signed-off-by: Giel van Schijndel <me@mortis.eu> -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-23 14:12 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O regions Giel van Schijndel @ 2010-03-24 8:14 ` Hans de Goede -1 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:14 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, I don't have any objections against the proposed changes, but there are 3 unrelated changes in this patch, please break them up in separate patches: 1) code cleanup: properly using, previously defined, functions rather than duplicating their code. 2) properly acquire I/O regions while probing 3) Make the addresses to probe an array And IMHO you might just as well drop number 3, it does not really make the code any better readable, and the old way is how all superio hwmon drivers do things. Regards, Hans On 03/23/2010 03:12 PM, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. > --- > drivers/hwmon/f71882fg.c | 38 +++++++++++++++++++++++--------------- > 1 files changed, 23 insertions(+), 15 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 4230729..25e1cad 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) > static int superio_inw(int base, int reg) > { > int val; > - outb(reg++, base); > - val = inb(base + 1)<< 8; > - outb(reg, base); > - val |= inb(base + 1); > + val = superio_inb(base, reg)<< 8; > + val |= superio_inb(base, reg + 1); > return val; > } > > @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) > { > u16 val; > > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - val = inb(data->addr + DATA_REG_OFFSET)<< 8; > - outb(reg, data->addr + ADDR_REG_OFFSET); > - val |= inb(data->addr + DATA_REG_OFFSET); > + val = f71882fg_read8(data, reg)<< 8; > + val |= f71882fg_read8(data, reg + 1); > > return val; > } > @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) > > static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) > { > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - outb(val>> 8, data->addr + DATA_REG_OFFSET); > - outb(reg, data->addr + ADDR_REG_OFFSET); > - outb(val& 255, data->addr + DATA_REG_OFFSET); > + f71882fg_write8(data, reg, val>> 8); > + f71882fg_write8(data, reg + 1, val& 0xff); > } > > static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) > @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > int err = -ENODEV; > u16 devid; > > + /* Don't step on other driver's I/O space by accident */ > + if (!request_region(sioaddr, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)sioaddr); > + return -EIO; > + } > + > superio_enter(sioaddr); > > devid = superio_inw(sioaddr, SIO_REG_MANID); > @@ -2238,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > + release_region(sioaddr, 2); > return err; > } > > @@ -2289,14 +2291,20 @@ exit_device_put: > > static int __init f71882fg_init(void) > { > + static const unsigned short addrs[] = { 0x2e, 0x4e }; > int err = -ENODEV; > - unsigned short address; > + unsigned short address = /* shut up compiler */ 0; > struct f71882fg_sio_data sio_data; > + int i; > > memset(&sio_data, 0, sizeof(sio_data)); > > - if (f71882fg_find(0x2e,&address,&sio_data)&& > - f71882fg_find(0x4e,&address,&sio_data)) > + for (i = 0; i< ARRAY_SIZE(addrs); i++) { > + err = f71882fg_find(addrs[i],&address,&sio_data); > + if (err == 0) > + break; > + } > + if (i == ARRAY_SIZE(addrs)) > goto exit; > > err = platform_driver_register(&f71882fg_driver); ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-24 8:14 ` Hans de Goede 0 siblings, 0 replies; 159+ messages in thread From: Hans de Goede @ 2010-03-24 8:14 UTC (permalink / raw) To: Giel van Schijndel Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi, I don't have any objections against the proposed changes, but there are 3 unrelated changes in this patch, please break them up in separate patches: 1) code cleanup: properly using, previously defined, functions rather than duplicating their code. 2) properly acquire I/O regions while probing 3) Make the addresses to probe an array And IMHO you might just as well drop number 3, it does not really make the code any better readable, and the old way is how all superio hwmon drivers do things. Regards, Hans On 03/23/2010 03:12 PM, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. > --- > drivers/hwmon/f71882fg.c | 38 +++++++++++++++++++++++--------------- > 1 files changed, 23 insertions(+), 15 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 4230729..25e1cad 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) > static int superio_inw(int base, int reg) > { > int val; > - outb(reg++, base); > - val = inb(base + 1)<< 8; > - outb(reg, base); > - val |= inb(base + 1); > + val = superio_inb(base, reg)<< 8; > + val |= superio_inb(base, reg + 1); > return val; > } > > @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) > { > u16 val; > > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - val = inb(data->addr + DATA_REG_OFFSET)<< 8; > - outb(reg, data->addr + ADDR_REG_OFFSET); > - val |= inb(data->addr + DATA_REG_OFFSET); > + val = f71882fg_read8(data, reg)<< 8; > + val |= f71882fg_read8(data, reg + 1); > > return val; > } > @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) > > static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) > { > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - outb(val>> 8, data->addr + DATA_REG_OFFSET); > - outb(reg, data->addr + ADDR_REG_OFFSET); > - outb(val& 255, data->addr + DATA_REG_OFFSET); > + f71882fg_write8(data, reg, val>> 8); > + f71882fg_write8(data, reg + 1, val& 0xff); > } > > static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) > @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > int err = -ENODEV; > u16 devid; > > + /* Don't step on other driver's I/O space by accident */ > + if (!request_region(sioaddr, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)sioaddr); > + return -EIO; > + } > + > superio_enter(sioaddr); > > devid = superio_inw(sioaddr, SIO_REG_MANID); > @@ -2238,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > + release_region(sioaddr, 2); > return err; > } > > @@ -2289,14 +2291,20 @@ exit_device_put: > > static int __init f71882fg_init(void) > { > + static const unsigned short addrs[] = { 0x2e, 0x4e }; > int err = -ENODEV; > - unsigned short address; > + unsigned short address = /* shut up compiler */ 0; > struct f71882fg_sio_data sio_data; > + int i; > > memset(&sio_data, 0, sizeof(sio_data)); > > - if (f71882fg_find(0x2e,&address,&sio_data)&& > - f71882fg_find(0x4e,&address,&sio_data)) > + for (i = 0; i< ARRAY_SIZE(addrs); i++) { > + err = f71882fg_find(addrs[i],&address,&sio_data); > + if (err = 0) > + break; > + } > + if (i = ARRAY_SIZE(addrs)) > goto exit; > > err = platform_driver_register(&f71882fg_driver); _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-24 8:14 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Hans de Goede @ 2010-03-24 8:46 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 8:46 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 2336 bytes --] On Wed, Mar 24, 2010 at 09:14:14AM +0100, Hans de Goede wrote: > I don't have any objections against the proposed changes, but there > are 3 unrelated changes in this patch, please break them up in > separate patches: > > 1) code cleanup: properly using, previously defined, functions rather > than duplicating their code. > 2) properly acquire I/O regions while probing > 3) Make the addresses to probe an array > > And IMHO you might just as well drop number 3, it does not really make > the code any better readable, and the old way is how all superio hwmon > drivers do things. Okay, broken up patches will follow as replies to this message. Regarding number (3), my goal wasn't to put the probe addresses in an array. My goal (as I think should have been made clear by the commit message I had added) was to make sure that upon failure f71882fg_find's return value gets passed back from the module's init function. This to make sure the *proper* error code gets passed back to the user of insmod/modprobe (as opposed to it being replaced by -ENODEV). Further I think non -ENODEV errors should probably immediately result in module initialisation failing (rather than retrying a probe), that's a design choice though (which my patch doesn't bother addressing right now). However, regarding the for-loop/array thing, the same behaviour can be aqcuired with a patch like the one following this line. (Please tell me if you like this approach or something similar better. Though, personally, I think it's "hackisher"/dirtier). diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 4230729..42d6304 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2295,9 +2295,11 @@ static int __init f71882fg_init(void) memset(&sio_data, 0, sizeof(sio_data)); - if (f71882fg_find(0x2e, &address, &sio_data) && - f71882fg_find(0x4e, &address, &sio_data)) - goto exit; + if (f71882fg_find(0x2e, &address, &sio_data)) { + err = f71882fg_find(0x4e, &address, &sio_data); + if (err) + goto exit; + } err = platform_driver_register(&f71882fg_driver); if (err) -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-24 8:46 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 8:46 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 2336 bytes --] On Wed, Mar 24, 2010 at 09:14:14AM +0100, Hans de Goede wrote: > I don't have any objections against the proposed changes, but there > are 3 unrelated changes in this patch, please break them up in > separate patches: > > 1) code cleanup: properly using, previously defined, functions rather > than duplicating their code. > 2) properly acquire I/O regions while probing > 3) Make the addresses to probe an array > > And IMHO you might just as well drop number 3, it does not really make > the code any better readable, and the old way is how all superio hwmon > drivers do things. Okay, broken up patches will follow as replies to this message. Regarding number (3), my goal wasn't to put the probe addresses in an array. My goal (as I think should have been made clear by the commit message I had added) was to make sure that upon failure f71882fg_find's return value gets passed back from the module's init function. This to make sure the *proper* error code gets passed back to the user of insmod/modprobe (as opposed to it being replaced by -ENODEV). Further I think non -ENODEV errors should probably immediately result in module initialisation failing (rather than retrying a probe), that's a design choice though (which my patch doesn't bother addressing right now). However, regarding the for-loop/array thing, the same behaviour can be aqcuired with a patch like the one following this line. (Please tell me if you like this approach or something similar better. Though, personally, I think it's "hackisher"/dirtier). diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 4230729..42d6304 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2295,9 +2295,11 @@ static int __init f71882fg_init(void) memset(&sio_data, 0, sizeof(sio_data)); - if (f71882fg_find(0x2e, &address, &sio_data) && - f71882fg_find(0x4e, &address, &sio_data)) - goto exit; + if (f71882fg_find(0x2e, &address, &sio_data)) { + err = f71882fg_find(0x4e, &address, &sio_data); + if (err) + goto exit; + } err = platform_driver_register(&f71882fg_driver); if (err) -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [PATCH] hwmon: f71882fg: code cleanup 2010-03-24 8:46 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel @ 2010-03-24 9:09 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:09 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Some code cleanup: properly using previously defined functions, rather than duplicating their code. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 18 ++++++------------ 1 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 4230729..ca34e5c 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) static int superio_inw(int base, int reg) { int val; - outb(reg++, base); - val = inb(base + 1) << 8; - outb(reg, base); - val |= inb(base + 1); + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); return val; } @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) { u16 val; - outb(reg++, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET) << 8; - outb(reg, data->addr + ADDR_REG_OFFSET); - val |= inb(data->addr + DATA_REG_OFFSET); + val = f71882fg_read8(data, reg) << 8; + val |= f71882fg_read8(data, reg + 1); return val; } @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) { - outb(reg++, data->addr + ADDR_REG_OFFSET); - outb(val >> 8, data->addr + DATA_REG_OFFSET); - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val & 255, data->addr + DATA_REG_OFFSET); + f71882fg_write8(data, reg, val >> 8); + f71882fg_write8(data, reg + 1, val & 0xff); } static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH] hwmon: f71882fg: code cleanup @ 2010-03-24 9:09 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:09 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Some code cleanup: properly using previously defined functions, rather than duplicating their code. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 18 ++++++------------ 1 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 4230729..ca34e5c 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) static int superio_inw(int base, int reg) { int val; - outb(reg++, base); - val = inb(base + 1) << 8; - outb(reg, base); - val |= inb(base + 1); + val = superio_inb(base, reg) << 8; + val |= superio_inb(base, reg + 1); return val; } @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) { u16 val; - outb(reg++, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET) << 8; - outb(reg, data->addr + ADDR_REG_OFFSET); - val |= inb(data->addr + DATA_REG_OFFSET); + val = f71882fg_read8(data, reg) << 8; + val |= f71882fg_read8(data, reg + 1); return val; } @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) { - outb(reg++, data->addr + ADDR_REG_OFFSET); - outb(val >> 8, data->addr + DATA_REG_OFFSET); - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val & 255, data->addr + DATA_REG_OFFSET); + f71882fg_write8(data, reg, val >> 8); + f71882fg_write8(data, reg + 1, val & 0xff); } static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: code cleanup 2010-03-24 9:09 ` [lm-sensors] " Giel van Schijndel @ 2010-03-24 12:54 ` Jean Delvare -1 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 12:54 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Wed, 24 Mar 2010 10:09:01 +0100, Giel van Schijndel wrote: > Some code cleanup: properly using previously defined functions, rather > than duplicating their code. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 18 ++++++------------ > 1 files changed, 6 insertions(+), 12 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 4230729..ca34e5c 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) > static int superio_inw(int base, int reg) > { > int val; > - outb(reg++, base); > - val = inb(base + 1) << 8; > - outb(reg, base); > - val |= inb(base + 1); > + val = superio_inb(base, reg) << 8; > + val |= superio_inb(base, reg + 1); > return val; > } > > @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) > { > u16 val; > > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - val = inb(data->addr + DATA_REG_OFFSET) << 8; > - outb(reg, data->addr + ADDR_REG_OFFSET); > - val |= inb(data->addr + DATA_REG_OFFSET); > + val = f71882fg_read8(data, reg) << 8; > + val |= f71882fg_read8(data, reg + 1); > > return val; > } > @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) > > static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) > { > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - outb(val >> 8, data->addr + DATA_REG_OFFSET); > - outb(reg, data->addr + ADDR_REG_OFFSET); > - outb(val & 255, data->addr + DATA_REG_OFFSET); > + f71882fg_write8(data, reg, val >> 8); > + f71882fg_write8(data, reg + 1, val & 0xff); > } > > static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) Applied, thanks. -- Jean Delvare ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: code cleanup @ 2010-03-24 12:54 ` Jean Delvare 0 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 12:54 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Wed, 24 Mar 2010 10:09:01 +0100, Giel van Schijndel wrote: > Some code cleanup: properly using previously defined functions, rather > than duplicating their code. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 18 ++++++------------ > 1 files changed, 6 insertions(+), 12 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 4230729..ca34e5c 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -856,10 +856,8 @@ static inline int superio_inb(int base, int reg) > static int superio_inw(int base, int reg) > { > int val; > - outb(reg++, base); > - val = inb(base + 1) << 8; > - outb(reg, base); > - val |= inb(base + 1); > + val = superio_inb(base, reg) << 8; > + val |= superio_inb(base, reg + 1); > return val; > } > > @@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) > { > u16 val; > > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - val = inb(data->addr + DATA_REG_OFFSET) << 8; > - outb(reg, data->addr + ADDR_REG_OFFSET); > - val |= inb(data->addr + DATA_REG_OFFSET); > + val = f71882fg_read8(data, reg) << 8; > + val |= f71882fg_read8(data, reg + 1); > > return val; > } > @@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) > > static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) > { > - outb(reg++, data->addr + ADDR_REG_OFFSET); > - outb(val >> 8, data->addr + DATA_REG_OFFSET); > - outb(reg, data->addr + ADDR_REG_OFFSET); > - outb(val & 255, data->addr + DATA_REG_OFFSET); > + f71882fg_write8(data, reg, val >> 8); > + f71882fg_write8(data, reg + 1, val & 0xff); > } > > static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) Applied, thanks. -- Jean Delvare _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* [PATCH] hwmon: f71882fg: acquire I/O regions while we're working with them 2010-03-24 8:46 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel @ 2010-03-24 9:09 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:09 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Acquire the I/O region for the Super I/O chip while we're working on it. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index ca34e5c..fe7b671 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2178,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, int err = -ENODEV; u16 devid; + /* Don't step on other drivers' I/O space by accident */ + if (!request_region(sioaddr, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)sioaddr); + return -EIO; + } + superio_enter(sioaddr); devid = superio_inw(sioaddr, SIO_REG_MANID); @@ -2232,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); + release_region(sioaddr, 2); return err; } -- 1.6.4.4 ^ permalink raw reply related [flat|nested] 159+ messages in thread
* [lm-sensors] [PATCH] hwmon: f71882fg: acquire I/O regions while @ 2010-03-24 9:09 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:09 UTC (permalink / raw) To: Hans de Goede Cc: Jean Delvare, Giel van Schijndel, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Acquire the I/O region for the Super I/O chip while we're working on it. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index ca34e5c..fe7b671 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2178,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, int err = -ENODEV; u16 devid; + /* Don't step on other drivers' I/O space by accident */ + if (!request_region(sioaddr, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)sioaddr); + return -EIO; + } + superio_enter(sioaddr); devid = superio_inw(sioaddr, SIO_REG_MANID); @@ -2232,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); + release_region(sioaddr, 2); return err; } -- 1.6.4.4 _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-24 8:46 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel @ 2010-03-24 9:28 ` Jean Delvare -1 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 9:28 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, On Wed, 24 Mar 2010 09:46:43 +0100, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 09:14:14AM +0100, Hans de Goede wrote: > > I don't have any objections against the proposed changes, but there > > are 3 unrelated changes in this patch, please break them up in > > separate patches: > > > > 1) code cleanup: properly using, previously defined, functions rather > > than duplicating their code. > > 2) properly acquire I/O regions while probing > > 3) Make the addresses to probe an array > > > > And IMHO you might just as well drop number 3, it does not really make > > the code any better readable, and the old way is how all superio hwmon > > drivers do things. > > Okay, broken up patches will follow as replies to this message. > > Regarding number (3), my goal wasn't to put the probe addresses in an > array. My goal (as I think should have been made clear by the commit > message I had added) was to make sure that upon failure f71882fg_find's > return value gets passed back from the module's init function. This to > make sure the *proper* error code gets passed back to the user of > insmod/modprobe (as opposed to it being replaced by -ENODEV). This doesn't make much sense. We call f71882fg_find up to twice, so we can get up to 2 error codes, but the module init function can only return one. There is no rationale for favoring the value returned by the second call over the value returned by the first call. So it seems reasonable to return an arbitrary error code. Of course we could spend code comparing the error values and returning the right one if the two functions returned the same error value, and only use the arbitrary default if they returned different values. But honestly I don't see any point in doing this in practice. Let's just log errors other than -ENODEV so that the user can see the exact cause of failure in the kernel log. > Further I think non -ENODEV errors should probably immediately result in > module initialisation failing (rather than retrying a probe), that's a > design choice though (which my patch doesn't bother addressing right > now). I disagree. If the probe of 0x2e/0x2f fails because that region was busy, this should not prevent us from giving a try to region 0x4e/0x4f. I can't think of any error that would warrant avoiding the probe at 0x4e/0x4f. Worse thing that can happen is that the second probe fails too. No big deal. > However, regarding the for-loop/array thing, the same behaviour can be > aqcuired with a patch like the one following this line. (Please tell me > if you like this approach or something similar better. Though, > personally, I think it's "hackisher"/dirtier). > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 4230729..42d6304 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2295,9 +2295,11 @@ static int __init f71882fg_init(void) > > memset(&sio_data, 0, sizeof(sio_data)); > > - if (f71882fg_find(0x2e, &address, &sio_data) && > - f71882fg_find(0x4e, &address, &sio_data)) > - goto exit; > + if (f71882fg_find(0x2e, &address, &sio_data)) { > + err = f71882fg_find(0x4e, &address, &sio_data); > + if (err) > + goto exit; > + } > > err = platform_driver_register(&f71882fg_driver); > if (err) > I don't like either implementation, I would leave the code as it is today. -- Jean Delvare ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-24 9:28 ` Jean Delvare 0 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 9:28 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel Hi Giel, On Wed, 24 Mar 2010 09:46:43 +0100, Giel van Schijndel wrote: > On Wed, Mar 24, 2010 at 09:14:14AM +0100, Hans de Goede wrote: > > I don't have any objections against the proposed changes, but there > > are 3 unrelated changes in this patch, please break them up in > > separate patches: > > > > 1) code cleanup: properly using, previously defined, functions rather > > than duplicating their code. > > 2) properly acquire I/O regions while probing > > 3) Make the addresses to probe an array > > > > And IMHO you might just as well drop number 3, it does not really make > > the code any better readable, and the old way is how all superio hwmon > > drivers do things. > > Okay, broken up patches will follow as replies to this message. > > Regarding number (3), my goal wasn't to put the probe addresses in an > array. My goal (as I think should have been made clear by the commit > message I had added) was to make sure that upon failure f71882fg_find's > return value gets passed back from the module's init function. This to > make sure the *proper* error code gets passed back to the user of > insmod/modprobe (as opposed to it being replaced by -ENODEV). This doesn't make much sense. We call f71882fg_find up to twice, so we can get up to 2 error codes, but the module init function can only return one. There is no rationale for favoring the value returned by the second call over the value returned by the first call. So it seems reasonable to return an arbitrary error code. Of course we could spend code comparing the error values and returning the right one if the two functions returned the same error value, and only use the arbitrary default if they returned different values. But honestly I don't see any point in doing this in practice. Let's just log errors other than -ENODEV so that the user can see the exact cause of failure in the kernel log. > Further I think non -ENODEV errors should probably immediately result in > module initialisation failing (rather than retrying a probe), that's a > design choice though (which my patch doesn't bother addressing right > now). I disagree. If the probe of 0x2e/0x2f fails because that region was busy, this should not prevent us from giving a try to region 0x4e/0x4f. I can't think of any error that would warrant avoiding the probe at 0x4e/0x4f. Worse thing that can happen is that the second probe fails too. No big deal. > However, regarding the for-loop/array thing, the same behaviour can be > aqcuired with a patch like the one following this line. (Please tell me > if you like this approach or something similar better. Though, > personally, I think it's "hackisher"/dirtier). > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index 4230729..42d6304 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2295,9 +2295,11 @@ static int __init f71882fg_init(void) > > memset(&sio_data, 0, sizeof(sio_data)); > > - if (f71882fg_find(0x2e, &address, &sio_data) && > - f71882fg_find(0x4e, &address, &sio_data)) > - goto exit; > + if (f71882fg_find(0x2e, &address, &sio_data)) { > + err = f71882fg_find(0x4e, &address, &sio_data); > + if (err) > + goto exit; > + } > > err = platform_driver_register(&f71882fg_driver); > if (err) > I don't like either implementation, I would leave the code as it is today. -- Jean Delvare _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-23 14:12 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O regions Giel van Schijndel @ 2010-03-24 9:29 ` Jean Delvare -1 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 9:29 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Tue, 23 Mar 2010 15:12:15 +0100, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. > (...) On top of Hans' comments, to which I agree: > static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) > @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > int err = -ENODEV; > u16 devid; > > + /* Don't step on other driver's I/O space by accident */ > + if (!request_region(sioaddr, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)sioaddr); > + return -EIO; This is the wrong error code. This isn't an I/O error. You want -EBUSY. > + } > + > superio_enter(sioaddr); > > devid = superio_inw(sioaddr, SIO_REG_MANID); -- Jean Delvare ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-24 9:29 ` Jean Delvare 0 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 9:29 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Tue, 23 Mar 2010 15:12:15 +0100, Giel van Schijndel wrote: > Acquire the I/O region for the Super I/O chip while we're working on it. > > Further alter the way multiple Super I/O addresses are probed for chips > such that errors in the probing process are passed on from the module > initialisation function. > > Some code cleanup: properly using, previously defined, functions rather > than duplicating their code. > (...) On top of Hans' comments, to which I agree: > static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) > @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > int err = -ENODEV; > u16 devid; > > + /* Don't step on other driver's I/O space by accident */ > + if (!request_region(sioaddr, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)sioaddr); > + return -EIO; This is the wrong error code. This isn't an I/O error. You want -EBUSY. > + } > + > superio_enter(sioaddr); > > devid = superio_inw(sioaddr, SIO_REG_MANID); -- Jean Delvare _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-24 9:29 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Jean Delvare @ 2010-03-24 9:34 ` Giel van Schijndel -1 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:34 UTC (permalink / raw) To: Jean Delvare Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1970 bytes --] On Wed, Mar 24, 2010 at 10:29:42AM +0100, Jean Delvare wrote: > On Tue, 23 Mar 2010 15:12:15 +0100, Giel van Schijndel wrote: >> static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) >> @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, >> int err = -ENODEV; >> u16 devid; >> >> + /* Don't step on other driver's I/O space by accident */ >> + if (!request_region(sioaddr, 2, DRVNAME)) { >> + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", >> + (int)sioaddr); >> + return -EIO; > > This is the wrong error code. This isn't an I/O error. You want -EBUSY. Ack. New patch follows this line. ======================================================================== hwmon: f71882fg: acquire I/O regions while we're working with them Acquire the I/O region for the Super I/O chip while we're working on it. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index ca34e5c..537841e 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2178,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, int err = -ENODEV; u16 devid; + /* Don't step on other drivers' I/O space by accident */ + if (!request_region(sioaddr, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)sioaddr); + return -EBUSY; + } + superio_enter(sioaddr); devid = superio_inw(sioaddr, SIO_REG_MANID); @@ -2232,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); + release_region(sioaddr, 2); return err; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-24 9:34 ` Giel van Schijndel 0 siblings, 0 replies; 159+ messages in thread From: Giel van Schijndel @ 2010-03-24 9:34 UTC (permalink / raw) To: Jean Delvare Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel [-- Attachment #1.1: Type: text/plain, Size: 1970 bytes --] On Wed, Mar 24, 2010 at 10:29:42AM +0100, Jean Delvare wrote: > On Tue, 23 Mar 2010 15:12:15 +0100, Giel van Schijndel wrote: >> static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) >> @@ -2184,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, >> int err = -ENODEV; >> u16 devid; >> >> + /* Don't step on other driver's I/O space by accident */ >> + if (!request_region(sioaddr, 2, DRVNAME)) { >> + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", >> + (int)sioaddr); >> + return -EIO; > > This is the wrong error code. This isn't an I/O error. You want -EBUSY. Ack. New patch follows this line. ======================================================================== hwmon: f71882fg: acquire I/O regions while we're working with them Acquire the I/O region for the Super I/O chip while we're working on it. Signed-off-by: Giel van Schijndel <me@mortis.eu> --- drivers/hwmon/f71882fg.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index ca34e5c..537841e 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2178,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, int err = -ENODEV; u16 devid; + /* Don't step on other drivers' I/O space by accident */ + if (!request_region(sioaddr, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + (int)sioaddr); + return -EBUSY; + } + superio_enter(sioaddr); devid = superio_inw(sioaddr, SIO_REG_MANID); @@ -2232,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); + release_region(sioaddr, 2); return err; } -- 1.6.4.4 -- Met vriendelijke groet, With kind regards, Giel van Schijndel [-- Attachment #1.2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 153 bytes --] _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply related [flat|nested] 159+ messages in thread
* Re: [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing 2010-03-24 9:34 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel @ 2010-03-24 12:54 ` Jean Delvare -1 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 12:54 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Wed, 24 Mar 2010 10:34:37 +0100, Giel van Schijndel wrote: > hwmon: f71882fg: acquire I/O regions while we're working with them > > Acquire the I/O region for the Super I/O chip while we're working on it. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 8 ++++++++ > 1 files changed, 8 insertions(+), 0 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index ca34e5c..537841e 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2178,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > int err = -ENODEV; > u16 devid; > > + /* Don't step on other drivers' I/O space by accident */ > + if (!request_region(sioaddr, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)sioaddr); > + return -EBUSY; > + } > + > superio_enter(sioaddr); > > devid = superio_inw(sioaddr, SIO_REG_MANID); > @@ -2232,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > + release_region(sioaddr, 2); > return err; > } > Applied, thanks. -- Jean Delvare ^ permalink raw reply [flat|nested] 159+ messages in thread
* Re: [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O @ 2010-03-24 12:54 ` Jean Delvare 0 siblings, 0 replies; 159+ messages in thread From: Jean Delvare @ 2010-03-24 12:54 UTC (permalink / raw) To: Giel van Schijndel Cc: Hans de Goede, Jonathan Cameron, Laurens Leemans, lm-sensors, linux-kernel On Wed, 24 Mar 2010 10:34:37 +0100, Giel van Schijndel wrote: > hwmon: f71882fg: acquire I/O regions while we're working with them > > Acquire the I/O region for the Super I/O chip while we're working on it. > > Signed-off-by: Giel van Schijndel <me@mortis.eu> > --- > drivers/hwmon/f71882fg.c | 8 ++++++++ > 1 files changed, 8 insertions(+), 0 deletions(-) > > diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c > index ca34e5c..537841e 100644 > --- a/drivers/hwmon/f71882fg.c > +++ b/drivers/hwmon/f71882fg.c > @@ -2178,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > int err = -ENODEV; > u16 devid; > > + /* Don't step on other drivers' I/O space by accident */ > + if (!request_region(sioaddr, 2, DRVNAME)) { > + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", > + (int)sioaddr); > + return -EBUSY; > + } > + > superio_enter(sioaddr); > > devid = superio_inw(sioaddr, SIO_REG_MANID); > @@ -2232,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, > (int)superio_inb(sioaddr, SIO_REG_DEVREV)); > exit: > superio_exit(sioaddr); > + release_region(sioaddr, 2); > return err; > } > Applied, thanks. -- Jean Delvare _______________________________________________ lm-sensors mailing list lm-sensors@lm-sensors.org http://lists.lm-sensors.org/mailman/listinfo/lm-sensors ^ permalink raw reply [flat|nested] 159+ messages in thread
end of thread, other threads:[~2010-10-03 13:33 UTC | newest] Thread overview: 159+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-03-23 14:12 [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Giel van Schijndel 2010-03-23 14:12 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O regions Giel van Schijndel 2010-03-23 14:17 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Giel van Schijndel 2010-03-23 14:17 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel 2010-03-23 23:12 ` [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the Fintek F71808E Giel van Schijndel 2010-03-23 23:12 ` [lm-sensors] [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the Giel van Schijndel 2010-03-23 23:12 ` [PATCH 2/4] hwmon: f71882fg: prepare for addition of watchdog support Giel van Schijndel 2010-03-23 23:12 ` [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition of Giel van Schijndel 2010-03-23 23:12 ` [PATCH 3/4] hwmon: f71882fg: add watchdog detection code Giel van Schijndel 2010-03-23 23:12 ` [lm-sensors] [PATCH 3/4] hwmon: f71882fg: add watchdog detection Giel van Schijndel 2010-03-23 23:12 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Giel van Schijndel 2010-03-23 23:12 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API Giel van Schijndel 2010-03-23 23:26 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Giel van Schijndel 2010-03-23 23:26 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel 2010-03-24 8:37 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Hans de Goede 2010-03-24 8:37 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Hans de Goede 2010-03-24 9:36 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Giel van Schijndel 2010-03-24 9:36 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel 2010-03-24 10:33 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Hans de Goede 2010-03-24 10:33 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Hans de Goede 2010-03-24 15:35 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Giel van Schijndel 2010-03-24 15:35 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel 2010-03-24 15:51 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Alan Cox 2010-03-24 15:51 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Alan Cox 2010-03-24 16:20 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Hans de Goede 2010-03-24 16:20 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Hans de Goede 2010-03-24 20:35 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Giel van Schijndel 2010-03-24 20:35 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel 2010-04-25 21:20 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Jim Cromie 2010-04-25 21:20 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Jim Cromie 2010-03-25 8:54 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Giel van Schijndel 2010-03-25 8:54 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel 2010-03-25 10:40 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Giel van Schijndel 2010-03-25 10:40 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Giel van Schijndel 2010-03-25 12:50 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Alan Cox 2010-03-25 12:50 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Alan Cox 2010-03-25 13:06 ` [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog API for F71808E and F71889 Hans de Goede 2010-03-25 13:06 ` [lm-sensors] [PATCH 4/4] [RFC] hwmon: f71882fg: Add watchdog Hans de Goede 2010-03-25 13:17 ` [PATCH 1/3] resource: shared I/O region support Giel van Schijndel 2010-03-25 13:17 ` [lm-sensors] " Giel van Schijndel 2010-03-25 13:17 ` [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Giel van Schijndel 2010-03-25 13:17 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock Giel van Schijndel 2010-03-25 13:17 ` [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Giel van Schijndel 2010-03-25 13:17 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog Giel van Schijndel 2010-03-30 9:06 ` [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Giel van Schijndel 2010-03-30 9:06 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Giel van Schijndel 2010-05-20 7:52 ` [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Wim Van Sebroeck 2010-05-20 7:52 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Wim Van Sebroeck 2010-05-25 21:08 ` [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Giel van Schijndel 2010-05-25 21:08 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Giel van Schijndel 2010-05-26 7:38 ` [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Wim Van Sebroeck 2010-05-26 7:38 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Wim Van Sebroeck 2010-07-31 21:36 ` [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E Giel van Schijndel 2010-07-31 21:36 ` [lm-sensors] [PATCH 3/3] [RFC] watchdog: f71808e_wdt: new Giel van Schijndel 2010-03-25 21:10 ` [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Hans de Goede 2010-03-25 21:10 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource Hans de Goede 2010-04-25 10:35 ` [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Giel van Schijndel 2010-04-25 10:35 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource Giel van Schijndel 2010-07-31 21:21 ` [PATCH 2/3] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Giel van Schijndel 2010-07-31 21:21 ` [lm-sensors] [PATCH 2/3] hwmon: f71882fg: use a muxed resource Giel van Schijndel 2010-03-25 15:57 ` [PATCH 1/3] resource: shared I/O region support Alan Cox 2010-03-25 15:57 ` [lm-sensors] " Alan Cox 2010-03-25 18:03 ` Giel van Schijndel 2010-03-25 18:03 ` [lm-sensors] " Giel van Schijndel 2010-03-25 18:16 ` Alan Cox 2010-03-25 18:16 ` [lm-sensors] " Alan Cox 2010-03-29 8:18 ` Giel van Schijndel 2010-03-29 8:18 ` [lm-sensors] " Giel van Schijndel 2010-03-29 16:07 ` Jesse Barnes 2010-03-29 16:07 ` [lm-sensors] " Jesse Barnes 2010-03-29 17:38 ` Giel van Schijndel 2010-03-29 17:38 ` [lm-sensors] " Giel van Schijndel 2010-03-29 17:44 ` Giel van Schijndel 2010-03-29 17:44 ` [lm-sensors] " Giel van Schijndel 2010-03-29 17:45 ` H. Peter Anvin 2010-03-29 17:45 ` [lm-sensors] " H. Peter Anvin 2010-03-29 18:06 ` Jesse Barnes 2010-03-29 18:06 ` [lm-sensors] " Jesse Barnes 2010-03-29 18:17 ` H. Peter Anvin 2010-03-29 18:17 ` [lm-sensors] " H. Peter Anvin 2010-03-29 18:29 ` Alan Cox 2010-03-29 18:29 ` [lm-sensors] " Alan Cox 2010-04-02 20:29 ` Jesse Barnes 2010-04-02 20:29 ` [lm-sensors] " Jesse Barnes 2010-03-29 18:39 ` Alan Cox 2010-03-29 18:39 ` [lm-sensors] " Alan Cox 2010-03-29 18:56 ` H. Peter Anvin 2010-03-29 18:56 ` [lm-sensors] " H. Peter Anvin 2010-03-29 17:59 ` Jesse Barnes 2010-03-29 17:59 ` [lm-sensors] " Jesse Barnes 2010-03-29 17:59 ` Jesse Barnes 2010-03-29 17:59 ` [lm-sensors] " Jesse Barnes 2010-03-24 8:26 ` [PATCH 2/4] hwmon: f71882fg: prepare for addition of watchdog support Hans de Goede 2010-03-24 8:26 ` [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition Hans de Goede 2010-03-24 8:36 ` [PATCH 2/4] hwmon: f71882fg: prepare for addition of watchdog support Hans de Goede 2010-03-24 8:36 ` [lm-sensors] [PATCH 2/4] hwmon: f71882fg: prepare for addition Hans de Goede 2010-03-24 8:25 ` [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede 2010-03-24 8:25 ` [lm-sensors] [PATCH 1/4] [RFC] hwmon: f71882fg: Add support for Hans de Goede 2010-03-24 9:23 ` [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E Giel van Schijndel 2010-03-24 9:23 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Giel van Schijndel 2010-03-24 10:31 ` [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede 2010-03-24 10:31 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Hans de Goede 2010-07-31 23:31 ` [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E Giel van Schijndel 2010-07-31 23:31 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Giel van Schijndel 2010-08-01 6:12 ` [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede 2010-08-01 6:12 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Hans de Goede 2010-08-01 13:22 ` [PATCH 1/4] hwmon: f71882fg: Add support for the Fintek F71808E Giel van Schijndel 2010-08-01 13:22 ` [lm-sensors] [PATCH 1/4] hwmon: f71882fg: Add support for the Giel van Schijndel 2010-08-01 13:30 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Giel van Schijndel 2010-08-01 13:30 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Fintek Giel van Schijndel 2010-08-04 11:36 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede 2010-08-04 15:44 ` Giel van Schijndel 2010-08-13 10:56 ` Hans de Goede 2010-08-13 10:56 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Hans de Goede 2010-08-10 19:11 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Giel van Schijndel 2010-08-10 19:11 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Giel van Schijndel 2010-08-13 10:01 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede 2010-08-13 10:01 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Hans de Goede 2010-08-18 18:24 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Andrew Morton 2010-08-18 18:24 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Andrew Morton 2010-08-22 18:04 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Hans de Goede 2010-08-22 18:04 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Hans de Goede 2010-08-22 18:28 ` [PATCH] hwmon: f71882fg: Add support for the Fintek F71808E Giel van Schijndel 2010-08-22 18:28 ` [lm-sensors] [PATCH] hwmon: f71882fg: Add support for the Giel van Schijndel 2010-08-01 13:30 ` [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Giel van Schijndel 2010-08-01 13:30 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock Giel van Schijndel 2010-08-01 13:30 ` [PATCH 2/2] watchdog: f71808e_wdt: new watchdog driver for Fintek F71808E and F71882FG Giel van Schijndel 2010-08-01 13:30 ` Giel van Schijndel 2010-08-04 11:38 ` [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Hans de Goede 2010-10-02 22:59 ` Giel van Schijndel 2010-10-02 22:59 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource Giel van Schijndel 2010-10-03 1:06 ` [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Guenter Roeck 2010-10-03 1:06 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource Guenter Roeck 2010-10-03 9:01 ` [PATCH 1/2] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Jean Delvare 2010-10-03 9:01 ` [lm-sensors] [PATCH 1/2] hwmon: f71882fg: use a muxed resource Jean Delvare 2010-10-03 12:09 ` [PATCH] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Giel van Schijndel 2010-10-03 12:09 ` [lm-sensors] [PATCH] hwmon: f71882fg: use a muxed resource lock for Giel van Schijndel 2010-10-03 13:31 ` [PATCH] hwmon: f71882fg: use a muxed resource lock for the Super I/O port Guenter Roeck 2010-10-03 13:31 ` [lm-sensors] [PATCH] hwmon: f71882fg: use a muxed resource lock Guenter Roeck 2010-03-23 23:01 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Giel van Schijndel 2010-03-23 23:01 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel 2010-03-24 8:14 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Hans de Goede 2010-03-24 8:14 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Hans de Goede 2010-03-24 8:46 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Giel van Schijndel 2010-03-24 8:46 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel 2010-03-24 9:09 ` [PATCH] hwmon: f71882fg: code cleanup Giel van Schijndel 2010-03-24 9:09 ` [lm-sensors] " Giel van Schijndel 2010-03-24 12:54 ` Jean Delvare 2010-03-24 12:54 ` [lm-sensors] " Jean Delvare 2010-03-24 9:09 ` [PATCH] hwmon: f71882fg: acquire I/O regions while we're working with them Giel van Schijndel 2010-03-24 9:09 ` [lm-sensors] [PATCH] hwmon: f71882fg: acquire I/O regions while Giel van Schijndel 2010-03-24 9:28 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Jean Delvare 2010-03-24 9:28 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Jean Delvare 2010-03-24 9:29 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Jean Delvare 2010-03-24 9:29 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Jean Delvare 2010-03-24 9:34 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Giel van Schijndel 2010-03-24 9:34 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Giel van Schijndel 2010-03-24 12:54 ` [PATCH] hwmon: f71882fg: properly acquire I/O regions while probing Jean Delvare 2010-03-24 12:54 ` [lm-sensors] [PATCH] hwmon: f71882fg: properly acquire I/O Jean Delvare
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.