[PATCH v6 2/4] pmbus (max31785): Add fan control
The implementation makes use of the new fan control virtual registers exposed by the pmbus core. It mixes use of the default implementations with some overrides via the read/write handlers to handle FAN_COMMAND_1 on the MAX31785, whose definition breaks the value range into various control bands dependent on RPM or PWM mode. Signed-off-by: Andrew Jeffery--- Documentation/hwmon/max31785 | 7 ++- drivers/hwmon/pmbus/max31785.c | 138 +- 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/Documentation/hwmon/max31785 b/Documentation/hwmon/max31785 index 45fb6093dec2..7b0a0a8cdb6b 100644 --- a/Documentation/hwmon/max31785 +++ b/Documentation/hwmon/max31785 @@ -32,6 +32,7 @@ Sysfs attributes fan[1-4]_alarm Fan alarm. fan[1-4]_fault Fan fault. fan[1-4]_input Fan RPM. +fan[1-4]_targetFan input target in[1-6]_crit Critical maximum output voltage in[1-6]_crit_alarm Output voltage critical high alarm @@ -44,6 +45,12 @@ in[1-6]_max_alarmOutput voltage high alarm in[1-6]_minMinimum output voltage in[1-6]_min_alarm Output voltage low alarm +pwm[1-4] Fan target duty cycle (0..255) +pwm[1-4]_enable0: Full-speed + 1: Manual PWM control + 2: Automatic PWM (tach-feedback RPM fan-control) + 3: Automatic closed-loop (temp-feedback fan-control) + temp[1-11]_critCritical high temperature temp[1-11]_crit_alarm Chip temperature critical high alarm temp[1-11]_input Measured temperature diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c index 9313849d5160..8706a696c89a 100644 --- a/drivers/hwmon/pmbus/max31785.c +++ b/drivers/hwmon/pmbus/max31785.c @@ -20,8 +20,136 @@ enum max31785_regs { #define MAX31785_NR_PAGES 23 +static int max31785_get_pwm(struct i2c_client *client, int page) +{ + int rv; + + rv = pmbus_get_fan_rate_device(client, page, 0, percent); + if (rv < 0) + return rv; + else if (rv >= 0x8000) + return 0; + else if (rv >= 0x2711) + return 0x2710; + + return rv; +} + +static int max31785_get_pwm_mode(struct i2c_client *client, int page) +{ + int config; + int command; + + config = pmbus_read_byte_data(client, page, PMBUS_FAN_CONFIG_12); + if (config < 0) + return config; + + command = pmbus_read_word_data(client, page, PMBUS_FAN_COMMAND_1); + if (command < 0) + return command; + + if (config & PB_FAN_1_RPM) + return (command >= 0x8000) ? 3 : 2; + + if (command >= 0x8000) + return 3; + else if (command >= 0x2711) + return 0; + + return 1; +} + +static int max31785_read_word_data(struct i2c_client *client, int page, + int reg) +{ + int rv; + + switch (reg) { + case PMBUS_VIRT_PWM_1: + rv = max31785_get_pwm(client, page); + break; + case PMBUS_VIRT_PWM_ENABLE_1: + rv = max31785_get_pwm_mode(client, page); + break; + default: + rv = -ENODATA; + break; + } + + return rv; +} + +static inline u32 max31785_scale_pwm(u32 sensor_val) +{ + /* +* The datasheet describes the accepted value range for manual PWM as +* [0, 0x2710], while the hwmon pwmX sysfs interface accepts values in +* [0, 255]. The MAX31785 uses DIRECT mode to scale the FAN_COMMAND +* registers and in PWM mode the coefficients are m=1, b=0, R=2. The +* important observation here is that 0x2710 == 1 == 100 * 100. +* +* R=2 (== 10^2 == 100) accounts for scaling the value provided at the +* sysfs interface into the required hardware resolution, but it does +* not yet yield a value that we can write to the device (this initial +* scaling is handled by pmbus_data2reg()). Multiplying by 100 below +* translates the parameter value into the percentage units required by +* PMBus, and then we scale back by 255 as required by the hwmon pwmX +* interface to yield the percentage value at the appropriate +* resolution for hardware. +*/ + return (sensor_val * 100) / 255; +} + +static int max31785_pwm_enable(struct i2c_client *client, int page, + u16 word) +{ + int config = 0; + int rate; + + switch (word) { + case 0: + rate = 0x7fff; + break; + case 1: + rate = pmbus_get_fan_rate_cached(client, page, 0, percent); + if (rate < 0) + return rate; + rate = max31785_scale_pwm(rate); + break; + case 2: +
[PATCH v6 3/4] pmbus (core): Add virtual page config bit
Some circumstances call for virtual pages, to expose multiple values packed into an extended PMBus register in a manner non-compliant with the PMBus standard. An example of this is the Maxim MAX31785 controller, which extends the READ_FAN_SPEED_1 PMBus register from two to four bytes to support tach readings for both rotors of a dual rotor fan. This extended register contains two word-sized values, one reporting the rate of the fastest rotor, the other the rate of the slowest. The concept of virtual pages aids this situation by mapping the page number onto the value to be selected from the vectored result. We should not try to set virtual pages on the device as such a page explicitly doesn't exist; add a flag so we can avoid doing so. Signed-off-by: Andrew Jeffery--- drivers/hwmon/pmbus/pmbus.h | 2 ++ drivers/hwmon/pmbus/pmbus_core.c | 27 ++- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index b54d7604d3ef..d39d506aa63e 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -372,6 +372,8 @@ enum pmbus_sensor_classes { #define PMBUS_HAVE_PWM12 BIT(20) #define PMBUS_HAVE_PWM34 BIT(21) +#define PMBUS_PAGE_VIRTUAL BIT(31) + enum pmbus_data_format { linear = 0, direct, vid }; enum vrm_version { vr11 = 0, vr12, vr13 }; diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index edc25efe7552..e215bbd403a5 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -161,18 +161,27 @@ EXPORT_SYMBOL_GPL(pmbus_clear_cache); int pmbus_set_page(struct i2c_client *client, int page) { struct pmbus_data *data = i2c_get_clientdata(client); - int rv = 0; - int newpage; + int rv; + + if (page < 0 || page == data->currpage) + return 0; - if (page >= 0 && page != data->currpage) { + if (!(data->info->func[page] & PMBUS_PAGE_VIRTUAL)) { rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); - newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); - if (newpage != page) - rv = -EIO; - else - data->currpage = page; + if (rv < 0) + return rv; + + rv = i2c_smbus_read_byte_data(client, PMBUS_PAGE); + if (rv < 0) + return rv; + + if (rv != page) + return -EIO; } - return rv; + + data->currpage = page; + + return 0; } EXPORT_SYMBOL_GPL(pmbus_set_page); -- git-series 0.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 4/4] pmbus (max31785): Add dual tachometer support
The dual tachometer feature is implemented in hardware with a TACHSEL input to indicate the rotor under measurement, and exposed on the device by extending the READ_FAN_SPEED_1 word with two extra bytes*. The need to read the non-standard four-byte response leads to a cut-down implementation of i2c_smbus_xfer_emulated() included in the driver. Further, to expose the second rotor tachometer value to userspace the values are exposed through virtual pages. We re-route accesses to FAN_CONFIG_1_2 and READ_FAN_SPEED_1 on pages 23-28 (not defined by the hardware) to the same registers on pages 0-5, and with the latter command we extract the value from the second word of the four-byte response. * The documentation recommends the slower rotor be associated with TACHSEL=0, which corresponds to the first word of the response. The TACHSEL=0 measurement is used by the controller's closed-loop fan management to judge target fan rate. Signed-off-by: Andrew Jeffery--- Documentation/hwmon/max31785 | 8 +- drivers/hwmon/pmbus/max31785.c | 147 ++- 2 files changed, 152 insertions(+), 3 deletions(-) diff --git a/Documentation/hwmon/max31785 b/Documentation/hwmon/max31785 index 7b0a0a8cdb6b..270c5f865261 100644 --- a/Documentation/hwmon/max31785 +++ b/Documentation/hwmon/max31785 @@ -17,8 +17,9 @@ management with temperature and remote voltage sensing. Various fan control features are provided, including PWM frequency control, temperature hysteresis, dual tachometer measurements, and fan health monitoring. -For dual rotor fan configuration, the MAX31785 exposes the slowest rotor of the -two in the fan[1-4]_input attributes. +For dual-rotor configurations the MAX31785A exposes the second rotor tachometer +readings in attributes fan[5-8]_input. By contrast the MAX31785 only exposes +the slowest rotor measurement, and does so in the fan[1-4]_input attributes. Usage Notes --- @@ -31,7 +32,8 @@ Sysfs attributes fan[1-4]_alarm Fan alarm. fan[1-4]_fault Fan fault. -fan[1-4]_input Fan RPM. +fan[1-8]_input Fan RPM. On the MAX31785A, inputs 5-8 correspond to the + second rotor of fans 1-4 fan[1-4]_targetFan input target in[1-6]_crit Critical maximum output voltage diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c index 8706a696c89a..bffab449be39 100644 --- a/drivers/hwmon/pmbus/max31785.c +++ b/drivers/hwmon/pmbus/max31785.c @@ -16,9 +16,79 @@ enum max31785_regs { MFR_REVISION= 0x9b, + MFR_FAN_CONFIG = 0xf1, }; +#define MAX31785 0x3030 +#define MAX31785A 0x3040 + +#define MFR_FAN_CONFIG_DUAL_TACH BIT(12) + #define MAX31785_NR_PAGES 23 +#define MAX31785_NR_FAN_PAGES 6 + +static int max31785_read_byte_data(struct i2c_client *client, int page, + int reg) +{ + if (page < MAX31785_NR_PAGES) + return -ENODATA; + + switch (reg) { + case PMBUS_VOUT_MODE: + return -ENOTSUPP; + case PMBUS_FAN_CONFIG_12: + return pmbus_read_byte_data(client, page - MAX31785_NR_PAGES, + reg); + } + + return -ENODATA; +} + +static int max31785_write_byte(struct i2c_client *client, int page, u8 value) +{ + if (page < MAX31785_NR_PAGES) + return -ENODATA; + + return -ENOTSUPP; +} + +static int max31785_read_long_data(struct i2c_client *client, int page, + int reg, u32 *data) +{ + unsigned char cmdbuf[1]; + unsigned char rspbuf[4]; + int rc; + + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = sizeof(cmdbuf), + .buf = cmdbuf, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = sizeof(rspbuf), + .buf = rspbuf, + }, + }; + + cmdbuf[0] = reg; + + rc = pmbus_set_page(client, page); + if (rc < 0) + return rc; + + rc = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); + if (rc < 0) + return rc; + + *data = (rspbuf[0] << (0 * 8)) | (rspbuf[1] << (1 * 8)) | + (rspbuf[2] << (2 * 8)) | (rspbuf[3] << (3 * 8)); + + return rc; +} static int max31785_get_pwm(struct i2c_client *client, int page) { @@ -62,9 +132,30 @@ static int max31785_get_pwm_mode(struct i2c_client *client, int page) static int max31785_read_word_data(struct i2c_client *client, int page, int reg) { + u32 val; int rv; switch (reg) { + case
[PATCH v6 0/4] pmbus: Expand fan support and add MAX31785 driver
Hello, This series introduces support for the MAX31785 intelligent fan controller, a PMBus device providing closed-loop fan control among a number of other features. Along the way the series adds support to control fans and create virtual pages to the PMBus core, the latter to support some of the more annoying design decisions found in the 'A' variant of the chip. This is the sixth spin of the series. v5 can be found here: https://lkml.org/lkml/2017/11/17/910 v6 fixes an error-handling bug I introduced in pmbus_set_page() with PATCH 3/4, as pointed out by Guenter on v5[1]. The rework implements his suggested solution. A few other other minor fixes are included: * PATCH 1/4: * Avoid potential NULL dereference in pmbus_get_fan_rate(). It amounts to being an error path that should never happen in practice, but lets make sure we don't die if we do hit it. * Drop a redundant test for the presence of FAN_COMMAND_x in pmbus_add_fan_ctrl(); document that its presence is a precondition to calling it (this was already tested at the one call-site). * PATCH 2/4: Avoid scaling an error code in pmbus_pwm_enable(). Rather, test the result of pmbus_get_fan_rate_cached() before performing the scaling when switching to PWM mode. [1] https://lkml.org/lkml/2017/11/19/280 Please review! Andrew Andrew Jeffery (4): pmbus (core): Add fan control support pmbus (max31785): Add fan control pmbus (core): Add virtual page config bit pmbus (max31785): Add dual tachometer support Documentation/hwmon/max31785 | 15 +- drivers/hwmon/pmbus/max31785.c | 285 +++- drivers/hwmon/pmbus/pmbus.h | 41 - drivers/hwmon/pmbus/pmbus_core.c | 265 +++--- 4 files changed, 575 insertions(+), 31 deletions(-) base-commit: ded0eb83449e8fcba22fd2736826336e101ffbcb -- git-series 0.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 3/4] pmbus (core): Add virtual page config bit
On Sun, 2017-11-19 at 08:49 -0800, Guenter Roeck wrote: > On 11/17/2017 07:26 PM, Andrew Jeffery wrote: > > Some circumstances call for virtual pages, to expose multiple values > > packed into an extended PMBus register in a manner non-compliant with > > the PMBus standard. An example of this is the Maxim MAX31785 controller, > > which > > extends the READ_FAN_SPEED_1 PMBus register from two to four bytes to > > support > > tach readings for both rotors of a dual rotor fan. This extended register > > contains two word-sized values, one reporting the rate of the fastest rotor, > > the other the rate of the slowest. The concept of virtual pages aids this > > situation by mapping the page number onto the value to be selected from the > > vectored result. > > > > We should not try to set virtual pages on the device as such a page > > explicitly > > doesn't exist; add a flag so we can avoid doing so. > > > > Signed-off-by: Andrew Jeffery> > --- > > drivers/hwmon/pmbus/pmbus.h | 2 ++ > > drivers/hwmon/pmbus/pmbus_core.c | 10 +++--- > > 2 files changed, 9 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h > > index b54d7604d3ef..d39d506aa63e 100644 > > --- a/drivers/hwmon/pmbus/pmbus.h > > +++ b/drivers/hwmon/pmbus/pmbus.h > > @@ -372,6 +372,8 @@ enum pmbus_sensor_classes { > > #define PMBUS_HAVE_PWM12 BIT(20) > > #define PMBUS_HAVE_PWM34 BIT(21) > > > > +#define PMBUS_PAGE_VIRTUAL BIT(31) > > + > > enum pmbus_data_format { linear = 0, direct, vid }; > > enum vrm_version { vr11 = 0, vr12, vr13 }; > > > > diff --git a/drivers/hwmon/pmbus/pmbus_core.c > > b/drivers/hwmon/pmbus/pmbus_core.c > > index 631db88526b6..ba97230fcde7 100644 > > --- a/drivers/hwmon/pmbus/pmbus_core.c > > +++ b/drivers/hwmon/pmbus/pmbus_core.c > > @@ -164,14 +164,18 @@ int pmbus_set_page(struct i2c_client *client, int > > page) > > int rv = 0; > > int newpage; > > > > - if (page >= 0 && page != data->currpage) { > > + if (page < 0 || page == data->currpage) > > + return 0; > > + > > + if (!(data->info->func[page] & PMBUS_PAGE_VIRTUAL)) { > > rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); > > newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); > > if (newpage != page) > > rv = -EIO; > > This should probably be something like > rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); > if (rv < 0) > return rv; > newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); > if (newpage < 0) > return newpage; > if (newpage != page) > return -EIO; > > We can actually drop 'newpage' and just use 'rv'. > > > - else > > - data->currpage = page; > > } > > + > > + data->currpage = page; > > + > > ... otherwise currpage is set even on error. Thanks for catching that, clearly I needed to pay more attention resolving the conflicts when rebasing on hwmon-next. I'll address all your points. Cheers, Andrew > > > return rv; > > this can then be > return 0; > > > } > > EXPORT_SYMBOL_GPL(pmbus_set_page); > > > > signature.asc Description: This is a digitally signed message part
Re: [PATCH] hwmon: Drop unnecessary 'default n' from Kconfig
Hi Guenter, On Sun, 19 Nov 2017 09:16:02 -0800, Guenter Roeck wrote: > 'default n' is default, so there is no need to specify it explicitly. > > Signed-off-by: Guenter Roeck> --- > drivers/hwmon/Kconfig | 16 > 1 file changed, 16 deletions(-) > (...) Reviewed-by: Jean Delvare (and heartily approved - thanks for doing that) -- Jean Delvare SUSE L3 Support -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] hwmon: Drop unnecessary 'default n' from Kconfig
'default n' is default, so there is no need to specify it explicitly. Signed-off-by: Guenter Roeck--- drivers/hwmon/Kconfig | 16 1 file changed, 16 deletions(-) diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 530ff7c9234c..ef23553ff5cb 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -26,11 +26,9 @@ if HWMON config HWMON_VID tristate - default n config HWMON_DEBUG_CHIP bool "Hardware Monitoring Chip debugging messages" - default n help Say Y here if you want the I2C chip drivers to produce a bunch of debug messages to the system log. Select this if you are having @@ -42,7 +40,6 @@ comment "Native drivers" config SENSORS_AB8500 tristate "AB8500 thermal monitoring" depends on AB8500_GPADC && AB8500_BM - default n help If you say yes here you get support for the thermal sensor part of the AB8500 chip. The driver includes thermal management for @@ -302,7 +299,6 @@ config SENSORS_APPLESMC select NEW_LEDS select LEDS_CLASS select INPUT_POLLDEV - default n help This driver provides support for the Apple System Management Controller, which provides an accelerometer (Apple Sudden Motion @@ -678,7 +674,6 @@ config SENSORS_JC42 config SENSORS_POWR1220 tristate "Lattice POWR1220 Power Monitoring" depends on I2C - default n help If you say yes here you get access to the hardware monitoring functions of the Lattice POWR1220 isp Power Supply Monitoring, @@ -702,7 +697,6 @@ config SENSORS_LTC2945 tristate "Linear Technology LTC2945" depends on I2C select REGMAP_I2C - default n help If you say yes here you get support for Linear Technology LTC2945 I2C System Monitor. @@ -727,7 +721,6 @@ config SENSORS_LTC2990 config SENSORS_LTC4151 tristate "Linear Technology LTC4151" depends on I2C - default n help If you say yes here you get support for Linear Technology LTC4151 High Voltage I2C Current and Voltage Monitor interface. @@ -738,7 +731,6 @@ config SENSORS_LTC4151 config SENSORS_LTC4215 tristate "Linear Technology LTC4215" depends on I2C - default n help If you say yes here you get support for Linear Technology LTC4215 Hot Swap Controller I2C interface. @@ -750,7 +742,6 @@ config SENSORS_LTC4222 tristate "Linear Technology LTC4222" depends on I2C select REGMAP_I2C - default n help If you say yes here you get support for Linear Technology LTC4222 Dual Hot Swap Controller I2C interface. @@ -761,7 +752,6 @@ config SENSORS_LTC4222 config SENSORS_LTC4245 tristate "Linear Technology LTC4245" depends on I2C - default n help If you say yes here you get support for Linear Technology LTC4245 Multiple Supply Hot Swap Controller I2C interface. @@ -773,7 +763,6 @@ config SENSORS_LTC4260 tristate "Linear Technology LTC4260" depends on I2C select REGMAP_I2C - default n help If you say yes here you get support for Linear Technology LTC4260 Positive Voltage Hot Swap Controller I2C interface. @@ -784,7 +773,6 @@ config SENSORS_LTC4260 config SENSORS_LTC4261 tristate "Linear Technology LTC4261" depends on I2C - default n help If you say yes here you get support for Linear Technology LTC4261 Negative Voltage Hot Swap Controller I2C interface. @@ -1276,7 +1264,6 @@ config SENSORS_NSA320 config SENSORS_PCF8591 tristate "Philips PCF8591 ADC/DAC" depends on I2C - default n help If you say yes here you get support for Philips PCF8591 4-channel ADC, 1-channel DAC chips. @@ -1459,7 +1446,6 @@ config SENSORS_SMSC47B397 config SENSORS_SCH56XX_COMMON tristate - default n config SENSORS_SCH5627 tristate "SMSC SCH5627" @@ -1505,7 +1491,6 @@ config SENSORS_STTS751 config SENSORS_SMM665 tristate "Summit Microelectronics SMM665" depends on I2C - default n help If you say yes here you get support for the hardware monitoring features of the Summit Microelectronics SMM665/SMM665B Six-Channel @@ -1792,7 +1777,6 @@ config SENSORS_W83795 config SENSORS_W83795_FANCTRL bool "Include automatic fan control support (DANGEROUS)" depends on SENSORS_W83795 - default n help If you say yes here, support for automatic fan speed control will be included in the driver. -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at
Re: [PATCH v5 3/4] pmbus (core): Add virtual page config bit
On 11/17/2017 07:26 PM, Andrew Jeffery wrote: Some circumstances call for virtual pages, to expose multiple values packed into an extended PMBus register in a manner non-compliant with the PMBus standard. An example of this is the Maxim MAX31785 controller, which extends the READ_FAN_SPEED_1 PMBus register from two to four bytes to support tach readings for both rotors of a dual rotor fan. This extended register contains two word-sized values, one reporting the rate of the fastest rotor, the other the rate of the slowest. The concept of virtual pages aids this situation by mapping the page number onto the value to be selected from the vectored result. We should not try to set virtual pages on the device as such a page explicitly doesn't exist; add a flag so we can avoid doing so. Signed-off-by: Andrew Jeffery--- drivers/hwmon/pmbus/pmbus.h | 2 ++ drivers/hwmon/pmbus/pmbus_core.c | 10 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index b54d7604d3ef..d39d506aa63e 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -372,6 +372,8 @@ enum pmbus_sensor_classes { #define PMBUS_HAVE_PWM12 BIT(20) #define PMBUS_HAVE_PWM34 BIT(21) +#define PMBUS_PAGE_VIRTUAL BIT(31) + enum pmbus_data_format { linear = 0, direct, vid }; enum vrm_version { vr11 = 0, vr12, vr13 }; diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 631db88526b6..ba97230fcde7 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -164,14 +164,18 @@ int pmbus_set_page(struct i2c_client *client, int page) int rv = 0; int newpage; - if (page >= 0 && page != data->currpage) { + if (page < 0 || page == data->currpage) + return 0; + + if (!(data->info->func[page] & PMBUS_PAGE_VIRTUAL)) { rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); if (newpage != page) rv = -EIO; This should probably be something like rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); if (rv < 0) return rv; newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); if (newpage < 0) return newpage; if (newpage != page) return -EIO; We can actually drop 'newpage' and just use 'rv'. - else - data->currpage = page; } + + data->currpage = page; + ... otherwise currpage is set even on error. return rv; this can then be return 0; } EXPORT_SYMBOL_GPL(pmbus_set_page); -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html