mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-13 14:04:05 +08:00
hwmon fixes for v6.3-rc3
- ltc2992, adm1266: Set missing can_sleep flag - tmp512/tmp513: Drop of_match_ptr for ID table to fix build with !CONFIG_OF - ucd90320: Fix back-to-back access problem - ina3221: Fix bad error return from probe function - xgene: Fix use-after-free bug in remove function - adt7475: Fix hysteresis register bit masks, and fix association of 'smoothing' attributes -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmQVrfAACgkQyx8mb86f mYEJcw/9GvMx2JkNSFWO/ZEEhwDX2q4GAdOtH9qI/ZbQ6hJTxW8RjXi4vJEvxXuI iFDE1d/xkgorec5mGazhHlXmw2rmnQ4g0XCSSHAn7SMZpK1T6AjHwohdZUBEZRWl fRik0zVaRZnmpOuH4X8vO0MQmBvddlaSXgfwoAjNP8V0mc6VNyCjvlSLjHNN5V0h PH+F3YlCU/N6RCs84qzXV5dZDnO854b7KvqgaXALqLkqh9BRoUwV6EsuqAAbsIwJ nwW1qSLhPzL6aO8Sp7cW2I36QccX5Uv9Bq+n66FJWqXlP9cl5rAksuk2XqUX4pi7 oQ+OVfmbM1K8BYCXKvo2FS5gmt3Vmcx2Mr72KdAuGZrFG5eUDOnKyGaSvsJW1tNf d/w7BE1Rg8Uix228BiMm76h9ogyZt8oMYyr5YmvK7Wt8JQCZV3NyXhRb5hDQAADk nJsdkH7emT/2ggdiwxAKTuiwbCw6W/bwvFEN1iT9UfxElxdfLuevWnBRSbiHxQga hRCegp9pasul8o4NLjYpH3/L+YFMxdvbegfd09lpRPoZXBSKlPrwfOT/L4HPF7zp kuR6enuARuJEtqojHs9at+PrkohleDDMNgRu5oVVUV7YC2RIDrIoYc+hLIAYR8E8 /1juBEnOC87Y3+9tPUwanZRSznQ/wXFnf/tiI9U/YYrRbz8qsq8= =JwY7 -----END PGP SIGNATURE----- Merge tag 'hwmon-for-v6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon fixes from Guenter Roeck: - ltc2992, adm1266: Set missing can_sleep flag - tmp512/tmp513: Drop of_match_ptr for ID table to fix build with !CONFIG_OF - ucd90320: Fix back-to-back access problem - ina3221: Fix bad error return from probe function - xgene: Fix use-after-free bug in remove function - adt7475: Fix hysteresis register bit masks, and fix association of 'smoothing' attributes * tag 'hwmon-for-v6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: hwmon: (ltc2992) Set `can_sleep` flag for GPIO chip hwmon: (adm1266) Set `can_sleep` flag for GPIO chip hwmon: tmp512: drop of_match_ptr for ID table hwmon: (ucd90320) Add minimum delay between bus accesses hwmon: (ina3221) return prober error code hwmon: (xgene) Fix use after free bug in xgene_hwmon_remove due to race condition hwmon: (adt7475) Fix masking of hysteresis registers hwmon: (adt7475) Display smoothing attributes in correct order
This commit is contained in:
commit
2a3e75a7ab
@ -488,10 +488,10 @@ static ssize_t temp_store(struct device *dev, struct device_attribute *attr,
|
||||
val = (temp - val) / 1000;
|
||||
|
||||
if (sattr->index != 1) {
|
||||
data->temp[HYSTERSIS][sattr->index] &= 0xF0;
|
||||
data->temp[HYSTERSIS][sattr->index] &= 0x0F;
|
||||
data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4;
|
||||
} else {
|
||||
data->temp[HYSTERSIS][sattr->index] &= 0x0F;
|
||||
data->temp[HYSTERSIS][sattr->index] &= 0xF0;
|
||||
data->temp[HYSTERSIS][sattr->index] |= (val & 0xF);
|
||||
}
|
||||
|
||||
@ -556,11 +556,11 @@ static ssize_t temp_st_show(struct device *dev, struct device_attribute *attr,
|
||||
val = data->enh_acoustics[0] & 0xf;
|
||||
break;
|
||||
case 1:
|
||||
val = (data->enh_acoustics[1] >> 4) & 0xf;
|
||||
val = data->enh_acoustics[1] & 0xf;
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
val = data->enh_acoustics[1] & 0xf;
|
||||
val = (data->enh_acoustics[1] >> 4) & 0xf;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -772,7 +772,7 @@ static int ina3221_probe_child_from_dt(struct device *dev,
|
||||
return ret;
|
||||
} else if (val > INA3221_CHANNEL3) {
|
||||
dev_err(dev, "invalid reg %d of %pOFn\n", val, child);
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
input = &ina->inputs[val];
|
||||
|
@ -323,6 +323,7 @@ static int ltc2992_config_gpio(struct ltc2992_state *st)
|
||||
st->gc.label = name;
|
||||
st->gc.parent = &st->client->dev;
|
||||
st->gc.owner = THIS_MODULE;
|
||||
st->gc.can_sleep = true;
|
||||
st->gc.base = -1;
|
||||
st->gc.names = st->gpio_names;
|
||||
st->gc.ngpio = ARRAY_SIZE(st->gpio_names);
|
||||
|
@ -301,6 +301,7 @@ static int adm1266_config_gpio(struct adm1266_data *data)
|
||||
data->gc.label = name;
|
||||
data->gc.parent = &data->client->dev;
|
||||
data->gc.owner = THIS_MODULE;
|
||||
data->gc.can_sleep = true;
|
||||
data->gc.base = -1;
|
||||
data->gc.names = data->gpio_names;
|
||||
data->gc.ngpio = ARRAY_SIZE(data->gpio_names);
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
@ -16,6 +17,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/pmbus.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include "pmbus.h"
|
||||
|
||||
enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd90320, ucd9090,
|
||||
@ -65,6 +67,7 @@ struct ucd9000_data {
|
||||
struct gpio_chip gpio;
|
||||
#endif
|
||||
struct dentry *debugfs;
|
||||
ktime_t write_time;
|
||||
};
|
||||
#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info)
|
||||
|
||||
@ -73,6 +76,73 @@ struct ucd9000_debugfs_entry {
|
||||
u8 index;
|
||||
};
|
||||
|
||||
/*
|
||||
* It has been observed that the UCD90320 randomly fails register access when
|
||||
* doing another access right on the back of a register write. To mitigate this
|
||||
* make sure that there is a minimum delay between a write access and the
|
||||
* following access. The 250us is based on experimental data. At a delay of
|
||||
* 200us the issue seems to go away. Add a bit of extra margin to allow for
|
||||
* system to system differences.
|
||||
*/
|
||||
#define UCD90320_WAIT_DELAY_US 250
|
||||
|
||||
static inline void ucd90320_wait(const struct ucd9000_data *data)
|
||||
{
|
||||
s64 delta = ktime_us_delta(ktime_get(), data->write_time);
|
||||
|
||||
if (delta < UCD90320_WAIT_DELAY_US)
|
||||
udelay(UCD90320_WAIT_DELAY_US - delta);
|
||||
}
|
||||
|
||||
static int ucd90320_read_word_data(struct i2c_client *client, int page,
|
||||
int phase, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct ucd9000_data *data = to_ucd9000_data(info);
|
||||
|
||||
if (reg >= PMBUS_VIRT_BASE)
|
||||
return -ENXIO;
|
||||
|
||||
ucd90320_wait(data);
|
||||
return pmbus_read_word_data(client, page, phase, reg);
|
||||
}
|
||||
|
||||
static int ucd90320_read_byte_data(struct i2c_client *client, int page, int reg)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct ucd9000_data *data = to_ucd9000_data(info);
|
||||
|
||||
ucd90320_wait(data);
|
||||
return pmbus_read_byte_data(client, page, reg);
|
||||
}
|
||||
|
||||
static int ucd90320_write_word_data(struct i2c_client *client, int page,
|
||||
int reg, u16 word)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct ucd9000_data *data = to_ucd9000_data(info);
|
||||
int ret;
|
||||
|
||||
ucd90320_wait(data);
|
||||
ret = pmbus_write_word_data(client, page, reg, word);
|
||||
data->write_time = ktime_get();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ucd90320_write_byte(struct i2c_client *client, int page, u8 value)
|
||||
{
|
||||
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
|
||||
struct ucd9000_data *data = to_ucd9000_data(info);
|
||||
int ret;
|
||||
|
||||
ucd90320_wait(data);
|
||||
ret = pmbus_write_byte(client, page, value);
|
||||
data->write_time = ktime_get();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ucd9000_get_fan_config(struct i2c_client *client, int fan)
|
||||
{
|
||||
int fan_config = 0;
|
||||
@ -598,6 +668,11 @@ static int ucd9000_probe(struct i2c_client *client)
|
||||
info->read_byte_data = ucd9000_read_byte_data;
|
||||
info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
|
||||
| PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
|
||||
} else if (mid->driver_data == ucd90320) {
|
||||
info->read_byte_data = ucd90320_read_byte_data;
|
||||
info->read_word_data = ucd90320_read_word_data;
|
||||
info->write_byte = ucd90320_write_byte;
|
||||
info->write_word_data = ucd90320_write_word_data;
|
||||
}
|
||||
|
||||
ucd9000_probe_gpio(client, mid, data);
|
||||
|
@ -758,7 +758,7 @@ static int tmp51x_probe(struct i2c_client *client)
|
||||
static struct i2c_driver tmp51x_driver = {
|
||||
.driver = {
|
||||
.name = "tmp51x",
|
||||
.of_match_table = of_match_ptr(tmp51x_of_match),
|
||||
.of_match_table = tmp51x_of_match,
|
||||
},
|
||||
.probe_new = tmp51x_probe,
|
||||
.id_table = tmp51x_id,
|
||||
|
@ -761,6 +761,7 @@ static int xgene_hwmon_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
cancel_work_sync(&ctx->workq);
|
||||
hwmon_device_unregister(ctx->hwmon_dev);
|
||||
kfifo_free(&ctx->async_msg_fifo);
|
||||
if (acpi_disabled)
|
||||
|
Loading…
Reference in New Issue
Block a user