Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'hwmon-for-v7.0-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon fixes from Guenter Roeck:

- PMBus driver fixes:
- Add mutex protection for regulator operations
- Fix reading from "write-only" attributes
- Mark lowest/average/highest/rated attributes as read-only
- isl68137: Add mutex protection for AVS enable sysfs attributes
- ina233: Fix error handling and sign extension when reading shunt voltage

- adm1177: Fix sysfs ABI violation and current unit conversion

- peci: Fix off-by-one in cputemp_is_visible(), and crit_hyst returning
delta instead of absolute temperature

* tag 'hwmon-for-v7.0-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
hwmon: (pmbus/core) Protect regulator operations with mutex
hwmon: (pmbus) Introduce the concept of "write-only" attributes
hwmon: (pmbus) Mark lowest/average/highest/rated attributes as read-only
hwmon: (adm1177) fix sysfs ABI violation and current unit conversion
hwmon: (peci/cputemp) Fix off-by-one in cputemp_is_visible()
hwmon: (peci/cputemp) Fix crit_hyst returning delta instead of absolute temperature
hwmon: (pmbus/isl68137) Add mutex protection for AVS enable sysfs attributes
hwmon: (pmbus/ina233) Fix error handling and sign extension in shunt voltage read

+217 -75
+4 -4
Documentation/hwmon/adm1177.rst
··· 27 27 Sysfs entries 28 28 ------------- 29 29 30 - The following attributes are supported. Current maxim attribute 30 + The following attributes are supported. Current maximum attribute 31 31 is read-write, all other attributes are read-only. 32 32 33 - in0_input Measured voltage in microvolts. 33 + in0_input Measured voltage in millivolts. 34 34 35 - curr1_input Measured current in microamperes. 36 - curr1_max_alarm Overcurrent alarm in microamperes. 35 + curr1_input Measured current in milliamperes. 36 + curr1_max Overcurrent shutdown threshold in milliamperes.
+6 -4
Documentation/hwmon/peci-cputemp.rst
··· 51 51 temp1_crit Provides shutdown temperature of the CPU package which 52 52 is also known as the maximum processor junction 53 53 temperature, Tjmax or Tprochot. 54 - temp1_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of 55 - the CPU package. 54 + temp1_crit_hyst Provides the hysteresis temperature of the CPU 55 + package. Returns Tcontrol, the temperature at which 56 + the critical condition clears. 56 57 57 58 temp2_label "DTS" 58 59 temp2_input Provides current temperature of the CPU package scaled ··· 63 62 temp2_crit Provides shutdown temperature of the CPU package which 64 63 is also known as the maximum processor junction 65 64 temperature, Tjmax or Tprochot. 66 - temp2_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of 67 - the CPU package. 65 + temp2_crit_hyst Provides the hysteresis temperature of the CPU 66 + package. Returns Tcontrol, the temperature at which 67 + the critical condition clears. 68 68 69 69 temp3_label "Tcontrol" 70 70 temp3_input Provides current Tcontrol temperature of the CPU
+31 -23
drivers/hwmon/adm1177.c
··· 10 10 #include <linux/hwmon.h> 11 11 #include <linux/i2c.h> 12 12 #include <linux/init.h> 13 + #include <linux/math64.h> 14 + #include <linux/minmax.h> 13 15 #include <linux/module.h> 14 16 #include <linux/regulator/consumer.h> 15 17 ··· 35 33 struct adm1177_state { 36 34 struct i2c_client *client; 37 35 u32 r_sense_uohm; 38 - u32 alert_threshold_ua; 36 + u64 alert_threshold_ua; 39 37 bool vrange_high; 40 38 }; 41 39 ··· 50 48 } 51 49 52 50 static int adm1177_write_alert_thr(struct adm1177_state *st, 53 - u32 alert_threshold_ua) 51 + u64 alert_threshold_ua) 54 52 { 55 53 u64 val; 56 54 int ret; ··· 93 91 *val = div_u64((105840000ull * dummy), 94 92 4096 * st->r_sense_uohm); 95 93 return 0; 96 - case hwmon_curr_max_alarm: 97 - *val = st->alert_threshold_ua; 94 + case hwmon_curr_max: 95 + *val = div_u64(st->alert_threshold_ua, 1000); 98 96 return 0; 99 97 default: 100 98 return -EOPNOTSUPP; ··· 128 126 switch (type) { 129 127 case hwmon_curr: 130 128 switch (attr) { 131 - case hwmon_curr_max_alarm: 132 - adm1177_write_alert_thr(st, val); 133 - return 0; 129 + case hwmon_curr_max: 130 + val = clamp_val(val, 0, 131 + div_u64(105840000ULL, st->r_sense_uohm)); 132 + return adm1177_write_alert_thr(st, (u64)val * 1000); 134 133 default: 135 134 return -EOPNOTSUPP; 136 135 } ··· 159 156 if (st->r_sense_uohm) 160 157 return 0444; 161 158 return 0; 162 - case hwmon_curr_max_alarm: 159 + case hwmon_curr_max: 163 160 if (st->r_sense_uohm) 164 161 return 0644; 165 162 return 0; ··· 173 170 174 171 static const struct hwmon_channel_info * const adm1177_info[] = { 175 172 HWMON_CHANNEL_INFO(curr, 176 - HWMON_C_INPUT | HWMON_C_MAX_ALARM), 173 + HWMON_C_INPUT | HWMON_C_MAX), 177 174 HWMON_CHANNEL_INFO(in, 178 175 HWMON_I_INPUT), 179 176 NULL ··· 195 192 struct device *dev = &client->dev; 196 193 struct device *hwmon_dev; 197 194 struct adm1177_state *st; 198 - u32 alert_threshold_ua; 195 + u64 alert_threshold_ua; 196 + u32 prop; 199 197 int ret; 200 198 201 199 st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); ··· 212 208 if (device_property_read_u32(dev, "shunt-resistor-micro-ohms", 213 209 &st->r_sense_uohm)) 214 210 st->r_sense_uohm = 0; 215 - if (device_property_read_u32(dev, "adi,shutdown-threshold-microamp", 216 - &alert_threshold_ua)) { 217 - if (st->r_sense_uohm) 218 - /* 219 - * set maximum default value from datasheet based on 220 - * shunt-resistor 221 - */ 222 - alert_threshold_ua = div_u64(105840000000, 223 - st->r_sense_uohm); 224 - else 225 - alert_threshold_ua = 0; 211 + if (!device_property_read_u32(dev, "adi,shutdown-threshold-microamp", 212 + &prop)) { 213 + alert_threshold_ua = prop; 214 + } else if (st->r_sense_uohm) { 215 + /* 216 + * set maximum default value from datasheet based on 217 + * shunt-resistor 218 + */ 219 + alert_threshold_ua = div_u64(105840000000ULL, 220 + st->r_sense_uohm); 221 + } else { 222 + alert_threshold_ua = 0; 226 223 } 227 224 st->vrange_high = device_property_read_bool(dev, 228 225 "adi,vrange-high-enable"); 229 - if (alert_threshold_ua && st->r_sense_uohm) 230 - adm1177_write_alert_thr(st, alert_threshold_ua); 226 + if (alert_threshold_ua && st->r_sense_uohm) { 227 + ret = adm1177_write_alert_thr(st, alert_threshold_ua); 228 + if (ret) 229 + return ret; 230 + } 231 231 232 232 ret = adm1177_write_cmd(st, ADM1177_CMD_V_CONT | 233 233 ADM1177_CMD_I_CONT |
+2 -2
drivers/hwmon/peci/cputemp.c
··· 131 131 *val = priv->temp.target.tjmax; 132 132 break; 133 133 case crit_hyst_type: 134 - *val = priv->temp.target.tjmax - priv->temp.target.tcontrol; 134 + *val = priv->temp.target.tcontrol; 135 135 break; 136 136 default: 137 137 ret = -EOPNOTSUPP; ··· 319 319 { 320 320 const struct peci_cputemp *priv = data; 321 321 322 - if (channel > CPUTEMP_CHANNEL_NUMS) 322 + if (channel >= CPUTEMP_CHANNEL_NUMS) 323 323 return 0; 324 324 325 325 if (channel < channel_core)
+2 -1
drivers/hwmon/pmbus/ina233.c
··· 72 72 73 73 /* Adjust returned value to match VIN coefficients */ 74 74 /* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */ 75 - ret = DIV_ROUND_CLOSEST(ret * 25, 12500); 75 + ret = clamp_val(DIV_ROUND_CLOSEST((s16)ret * 25, 12500), 76 + S16_MIN, S16_MAX) & 0xffff; 76 77 break; 77 78 default: 78 79 ret = -ENODATA;
+18 -3
drivers/hwmon/pmbus/isl68137.c
··· 96 96 int page, 97 97 char *buf) 98 98 { 99 - int val = pmbus_read_byte_data(client, page, PMBUS_OPERATION); 99 + int val; 100 + 101 + val = pmbus_lock_interruptible(client); 102 + if (val) 103 + return val; 104 + 105 + val = pmbus_read_byte_data(client, page, PMBUS_OPERATION); 106 + 107 + pmbus_unlock(client); 100 108 101 109 if (val < 0) 102 110 return val; ··· 126 118 127 119 op_val = result ? ISL68137_VOUT_AVS : 0; 128 120 121 + rc = pmbus_lock_interruptible(client); 122 + if (rc) 123 + return rc; 124 + 129 125 /* 130 126 * Writes to VOUT setpoint over AVSBus will persist after the VRM is 131 127 * switched to PMBus control. Switching back to AVSBus control ··· 141 129 rc = pmbus_read_word_data(client, page, 0xff, 142 130 PMBUS_VOUT_COMMAND); 143 131 if (rc < 0) 144 - return rc; 132 + goto unlock; 145 133 146 134 rc = pmbus_write_word_data(client, page, PMBUS_VOUT_COMMAND, 147 135 rc); 148 136 if (rc < 0) 149 - return rc; 137 + goto unlock; 150 138 } 151 139 152 140 rc = pmbus_update_byte_data(client, page, PMBUS_OPERATION, 153 141 ISL68137_VOUT_AVS, op_val); 142 + 143 + unlock: 144 + pmbus_unlock(client); 154 145 155 146 return (rc < 0) ? rc : count; 156 147 }
+154 -38
drivers/hwmon/pmbus/pmbus_core.c
··· 6 6 * Copyright (c) 2012 Guenter Roeck 7 7 */ 8 8 9 + #include <linux/atomic.h> 9 10 #include <linux/debugfs.h> 10 11 #include <linux/delay.h> 11 12 #include <linux/dcache.h> ··· 22 21 #include <linux/pmbus.h> 23 22 #include <linux/regulator/driver.h> 24 23 #include <linux/regulator/machine.h> 25 - #include <linux/of.h> 26 24 #include <linux/thermal.h> 25 + #include <linux/workqueue.h> 27 26 #include "pmbus.h" 28 27 29 28 /* ··· 112 111 struct pmbus_sensor *sensors; 113 112 114 113 struct mutex update_lock; 114 + 115 + #if IS_ENABLED(CONFIG_REGULATOR) 116 + atomic_t regulator_events[PMBUS_PAGES]; 117 + struct work_struct regulator_notify_work; 118 + #endif 115 119 116 120 bool has_status_word; /* device uses STATUS_WORD register */ 117 121 int (*read_status)(struct i2c_client *client, int page); ··· 1215 1209 return sysfs_emit(buf, "%d\n", val); 1216 1210 } 1217 1211 1212 + static ssize_t pmbus_show_zero(struct device *dev, 1213 + struct device_attribute *devattr, char *buf) 1214 + { 1215 + return sysfs_emit(buf, "0\n"); 1216 + } 1217 + 1218 1218 static ssize_t pmbus_show_sensor(struct device *dev, 1219 1219 struct device_attribute *devattr, char *buf) 1220 1220 { ··· 1419 1407 int reg, 1420 1408 enum pmbus_sensor_classes class, 1421 1409 bool update, bool readonly, 1422 - bool convert) 1410 + bool writeonly, bool convert) 1423 1411 { 1424 1412 struct pmbus_sensor *sensor; 1425 1413 struct device_attribute *a; ··· 1448 1436 sensor->data = -ENODATA; 1449 1437 pmbus_dev_attr_init(a, sensor->name, 1450 1438 readonly ? 0444 : 0644, 1451 - pmbus_show_sensor, pmbus_set_sensor); 1439 + writeonly ? pmbus_show_zero : pmbus_show_sensor, 1440 + pmbus_set_sensor); 1452 1441 1453 1442 if (pmbus_add_attribute(data, &a->attr)) 1454 1443 return NULL; ··· 1508 1495 struct pmbus_limit_attr { 1509 1496 u16 reg; /* Limit register */ 1510 1497 u16 sbit; /* Alarm attribute status bit */ 1511 - bool update; /* True if register needs updates */ 1512 - bool low; /* True if low limit; for limits with compare functions only */ 1498 + bool readonly:1; /* True if the attribute is read-only */ 1499 + bool writeonly:1; /* True if the attribute is write-only */ 1500 + bool update:1; /* True if register needs updates */ 1501 + bool low:1; /* True if low limit; for limits with compare functions only */ 1513 1502 const char *attr; /* Attribute name */ 1514 1503 const char *alarm; /* Alarm attribute name */ 1515 1504 }; ··· 1526 1511 u8 nlimit; /* # of limit registers */ 1527 1512 enum pmbus_sensor_classes class;/* sensor class */ 1528 1513 const char *label; /* sensor label */ 1529 - bool paged; /* true if paged sensor */ 1530 - bool update; /* true if update needed */ 1531 - bool compare; /* true if compare function needed */ 1514 + bool paged:1; /* true if paged sensor */ 1515 + bool update:1; /* true if update needed */ 1516 + bool compare:1; /* true if compare function needed */ 1532 1517 u32 func; /* sensor mask */ 1533 1518 u32 sfunc; /* sensor status mask */ 1534 1519 int sreg; /* status register */ ··· 1559 1544 curr = pmbus_add_sensor(data, name, l->attr, index, 1560 1545 page, 0xff, l->reg, attr->class, 1561 1546 attr->update || l->update, 1562 - false, true); 1547 + l->readonly, l->writeonly, true); 1563 1548 if (!curr) 1564 1549 return -ENOMEM; 1565 1550 if (l->sbit && (info->func[page] & attr->sfunc)) { ··· 1599 1584 return ret; 1600 1585 } 1601 1586 base = pmbus_add_sensor(data, name, "input", index, page, phase, 1602 - attr->reg, attr->class, true, true, true); 1587 + attr->reg, attr->class, true, true, false, true); 1603 1588 if (!base) 1604 1589 return -ENOMEM; 1605 1590 /* No limit and alarm attributes for phase specific sensors */ ··· 1722 1707 }, { 1723 1708 .reg = PMBUS_VIRT_READ_VIN_AVG, 1724 1709 .update = true, 1710 + .readonly = true, 1725 1711 .attr = "average", 1726 1712 }, { 1727 1713 .reg = PMBUS_VIRT_READ_VIN_MIN, 1728 1714 .update = true, 1715 + .readonly = true, 1729 1716 .attr = "lowest", 1730 1717 }, { 1731 1718 .reg = PMBUS_VIRT_READ_VIN_MAX, 1732 1719 .update = true, 1720 + .readonly = true, 1733 1721 .attr = "highest", 1734 1722 }, { 1735 1723 .reg = PMBUS_VIRT_RESET_VIN_HISTORY, 1724 + .writeonly = true, 1736 1725 .attr = "reset_history", 1737 1726 }, { 1738 1727 .reg = PMBUS_MFR_VIN_MIN, 1728 + .readonly = true, 1739 1729 .attr = "rated_min", 1740 1730 }, { 1741 1731 .reg = PMBUS_MFR_VIN_MAX, 1732 + .readonly = true, 1742 1733 .attr = "rated_max", 1743 1734 }, 1744 1735 }; ··· 1797 1776 }, { 1798 1777 .reg = PMBUS_VIRT_READ_VOUT_AVG, 1799 1778 .update = true, 1779 + .readonly = true, 1800 1780 .attr = "average", 1801 1781 }, { 1802 1782 .reg = PMBUS_VIRT_READ_VOUT_MIN, 1803 1783 .update = true, 1784 + .readonly = true, 1804 1785 .attr = "lowest", 1805 1786 }, { 1806 1787 .reg = PMBUS_VIRT_READ_VOUT_MAX, 1807 1788 .update = true, 1789 + .readonly = true, 1808 1790 .attr = "highest", 1809 1791 }, { 1810 1792 .reg = PMBUS_VIRT_RESET_VOUT_HISTORY, 1793 + .writeonly = true, 1811 1794 .attr = "reset_history", 1812 1795 }, { 1813 1796 .reg = PMBUS_MFR_VOUT_MIN, 1797 + .readonly = true, 1814 1798 .attr = "rated_min", 1815 1799 }, { 1816 1800 .reg = PMBUS_MFR_VOUT_MAX, 1801 + .readonly = true, 1817 1802 .attr = "rated_max", 1818 1803 }, 1819 1804 }; ··· 1879 1852 }, { 1880 1853 .reg = PMBUS_VIRT_READ_IIN_AVG, 1881 1854 .update = true, 1855 + .readonly = true, 1882 1856 .attr = "average", 1883 1857 }, { 1884 1858 .reg = PMBUS_VIRT_READ_IIN_MIN, 1885 1859 .update = true, 1860 + .readonly = true, 1886 1861 .attr = "lowest", 1887 1862 }, { 1888 1863 .reg = PMBUS_VIRT_READ_IIN_MAX, 1889 1864 .update = true, 1865 + .readonly = true, 1890 1866 .attr = "highest", 1891 1867 }, { 1892 1868 .reg = PMBUS_VIRT_RESET_IIN_HISTORY, 1869 + .writeonly = true, 1893 1870 .attr = "reset_history", 1894 1871 }, { 1895 1872 .reg = PMBUS_MFR_IIN_MAX, 1873 + .readonly = true, 1896 1874 .attr = "rated_max", 1897 1875 }, 1898 1876 }; ··· 1921 1889 }, { 1922 1890 .reg = PMBUS_VIRT_READ_IOUT_AVG, 1923 1891 .update = true, 1892 + .readonly = true, 1924 1893 .attr = "average", 1925 1894 }, { 1926 1895 .reg = PMBUS_VIRT_READ_IOUT_MIN, 1927 1896 .update = true, 1897 + .readonly = true, 1928 1898 .attr = "lowest", 1929 1899 }, { 1930 1900 .reg = PMBUS_VIRT_READ_IOUT_MAX, 1931 1901 .update = true, 1902 + .readonly = true, 1932 1903 .attr = "highest", 1933 1904 }, { 1934 1905 .reg = PMBUS_VIRT_RESET_IOUT_HISTORY, 1906 + .writeonly = true, 1935 1907 .attr = "reset_history", 1936 1908 }, { 1937 1909 .reg = PMBUS_MFR_IOUT_MAX, 1910 + .readonly = true, 1938 1911 .attr = "rated_max", 1939 1912 }, 1940 1913 }; ··· 1980 1943 }, { 1981 1944 .reg = PMBUS_VIRT_READ_PIN_AVG, 1982 1945 .update = true, 1946 + .readonly = true, 1983 1947 .attr = "average", 1984 1948 }, { 1985 1949 .reg = PMBUS_VIRT_READ_PIN_MIN, 1986 1950 .update = true, 1951 + .readonly = true, 1987 1952 .attr = "input_lowest", 1988 1953 }, { 1989 1954 .reg = PMBUS_VIRT_READ_PIN_MAX, 1990 1955 .update = true, 1956 + .readonly = true, 1991 1957 .attr = "input_highest", 1992 1958 }, { 1993 1959 .reg = PMBUS_VIRT_RESET_PIN_HISTORY, 1960 + .writeonly = true, 1994 1961 .attr = "reset_history", 1995 1962 }, { 1996 1963 .reg = PMBUS_MFR_PIN_MAX, 1964 + .readonly = true, 1997 1965 .attr = "rated_max", 1998 1966 }, 1999 1967 }; ··· 2022 1980 }, { 2023 1981 .reg = PMBUS_VIRT_READ_POUT_AVG, 2024 1982 .update = true, 1983 + .readonly = true, 2025 1984 .attr = "average", 2026 1985 }, { 2027 1986 .reg = PMBUS_VIRT_READ_POUT_MIN, 2028 1987 .update = true, 1988 + .readonly = true, 2029 1989 .attr = "input_lowest", 2030 1990 }, { 2031 1991 .reg = PMBUS_VIRT_READ_POUT_MAX, 2032 1992 .update = true, 1993 + .readonly = true, 2033 1994 .attr = "input_highest", 2034 1995 }, { 2035 1996 .reg = PMBUS_VIRT_RESET_POUT_HISTORY, 1997 + .writeonly = true, 2036 1998 .attr = "reset_history", 2037 1999 }, { 2038 2000 .reg = PMBUS_MFR_POUT_MAX, 2001 + .readonly = true, 2039 2002 .attr = "rated_max", 2040 2003 }, 2041 2004 }; ··· 2096 2049 .sbit = PB_TEMP_OT_FAULT, 2097 2050 }, { 2098 2051 .reg = PMBUS_VIRT_READ_TEMP_MIN, 2052 + .readonly = true, 2099 2053 .attr = "lowest", 2100 2054 }, { 2101 2055 .reg = PMBUS_VIRT_READ_TEMP_AVG, 2056 + .readonly = true, 2102 2057 .attr = "average", 2103 2058 }, { 2104 2059 .reg = PMBUS_VIRT_READ_TEMP_MAX, 2060 + .readonly = true, 2105 2061 .attr = "highest", 2106 2062 }, { 2107 2063 .reg = PMBUS_VIRT_RESET_TEMP_HISTORY, 2064 + .writeonly = true, 2108 2065 .attr = "reset_history", 2109 2066 }, { 2110 2067 .reg = PMBUS_MFR_MAX_TEMP_1, 2068 + .readonly = true, 2111 2069 .attr = "rated_max", 2112 2070 }, 2113 2071 }; ··· 2142 2090 .sbit = PB_TEMP_OT_FAULT, 2143 2091 }, { 2144 2092 .reg = PMBUS_VIRT_READ_TEMP2_MIN, 2093 + .readonly = true, 2145 2094 .attr = "lowest", 2146 2095 }, { 2147 2096 .reg = PMBUS_VIRT_READ_TEMP2_AVG, 2097 + .readonly = true, 2148 2098 .attr = "average", 2149 2099 }, { 2150 2100 .reg = PMBUS_VIRT_READ_TEMP2_MAX, 2101 + .readonly = true, 2151 2102 .attr = "highest", 2152 2103 }, { 2153 2104 .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY, 2105 + .writeonly = true, 2154 2106 .attr = "reset_history", 2155 2107 }, { 2156 2108 .reg = PMBUS_MFR_MAX_TEMP_2, 2109 + .readonly = true, 2157 2110 .attr = "rated_max", 2158 2111 }, 2159 2112 }; ··· 2188 2131 .sbit = PB_TEMP_OT_FAULT, 2189 2132 }, { 2190 2133 .reg = PMBUS_MFR_MAX_TEMP_3, 2134 + .readonly = true, 2191 2135 .attr = "rated_max", 2192 2136 }, 2193 2137 }; ··· 2272 2214 2273 2215 sensor = pmbus_add_sensor(data, "fan", "target", index, page, 2274 2216 0xff, PMBUS_VIRT_FAN_TARGET_1 + id, PSC_FAN, 2275 - false, false, true); 2217 + false, false, false, true); 2276 2218 2277 2219 if (!sensor) 2278 2220 return -ENOMEM; ··· 2283 2225 2284 2226 sensor = pmbus_add_sensor(data, "pwm", NULL, index, page, 2285 2227 0xff, PMBUS_VIRT_PWM_1 + id, PSC_PWM, 2286 - false, false, true); 2228 + false, false, false, true); 2287 2229 2288 2230 if (!sensor) 2289 2231 return -ENOMEM; 2290 2232 2291 2233 sensor = pmbus_add_sensor(data, "pwm", "enable", index, page, 2292 2234 0xff, PMBUS_VIRT_PWM_ENABLE_1 + id, PSC_PWM, 2293 - true, false, false); 2235 + true, false, false, false); 2294 2236 2295 2237 if (!sensor) 2296 2238 return -ENOMEM; ··· 2332 2274 2333 2275 if (pmbus_add_sensor(data, "fan", "input", index, 2334 2276 page, 0xff, pmbus_fan_registers[f], 2335 - PSC_FAN, true, true, true) == NULL) 2277 + PSC_FAN, true, true, false, true) == NULL) 2336 2278 return -ENOMEM; 2337 2279 2338 2280 /* Fan control */ ··· 3234 3176 .class = PSC_VOLTAGE_OUT, 3235 3177 .convert = true, 3236 3178 }; 3179 + int ret; 3237 3180 3181 + mutex_lock(&data->update_lock); 3238 3182 s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT); 3239 - if (s.data < 0) 3240 - return s.data; 3183 + if (s.data < 0) { 3184 + ret = s.data; 3185 + goto unlock; 3186 + } 3241 3187 3242 - return (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */ 3188 + ret = (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */ 3189 + unlock: 3190 + mutex_unlock(&data->update_lock); 3191 + return ret; 3243 3192 } 3244 3193 3245 3194 static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv, ··· 3263 3198 }; 3264 3199 int val = DIV_ROUND_CLOSEST(min_uv, 1000); /* convert to mV */ 3265 3200 int low, high; 3201 + int ret; 3266 3202 3267 3203 *selector = 0; 3268 3204 3205 + mutex_lock(&data->update_lock); 3269 3206 low = pmbus_regulator_get_low_margin(client, s.page); 3270 - if (low < 0) 3271 - return low; 3207 + if (low < 0) { 3208 + ret = low; 3209 + goto unlock; 3210 + } 3272 3211 3273 3212 high = pmbus_regulator_get_high_margin(client, s.page); 3274 - if (high < 0) 3275 - return high; 3213 + if (high < 0) { 3214 + ret = high; 3215 + goto unlock; 3216 + } 3276 3217 3277 3218 /* Make sure we are within margins */ 3278 3219 if (low > val) ··· 3288 3217 3289 3218 val = pmbus_data2reg(data, &s, val); 3290 3219 3291 - return _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val); 3220 + ret = _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val); 3221 + unlock: 3222 + mutex_unlock(&data->update_lock); 3223 + return ret; 3292 3224 } 3293 3225 3294 3226 static int pmbus_regulator_list_voltage(struct regulator_dev *rdev, ··· 3301 3227 struct i2c_client *client = to_i2c_client(dev->parent); 3302 3228 struct pmbus_data *data = i2c_get_clientdata(client); 3303 3229 int val, low, high; 3230 + int ret; 3304 3231 3305 3232 if (data->flags & PMBUS_VOUT_PROTECTED) 3306 3233 return 0; ··· 3314 3239 val = DIV_ROUND_CLOSEST(rdev->desc->min_uV + 3315 3240 (rdev->desc->uV_step * selector), 1000); /* convert to mV */ 3316 3241 3242 + mutex_lock(&data->update_lock); 3243 + 3317 3244 low = pmbus_regulator_get_low_margin(client, rdev_get_id(rdev)); 3318 - if (low < 0) 3319 - return low; 3245 + if (low < 0) { 3246 + ret = low; 3247 + goto unlock; 3248 + } 3320 3249 3321 3250 high = pmbus_regulator_get_high_margin(client, rdev_get_id(rdev)); 3322 - if (high < 0) 3323 - return high; 3251 + if (high < 0) { 3252 + ret = high; 3253 + goto unlock; 3254 + } 3324 3255 3325 - if (val >= low && val <= high) 3326 - return val * 1000; /* unit is uV */ 3256 + if (val >= low && val <= high) { 3257 + ret = val * 1000; /* unit is uV */ 3258 + goto unlock; 3259 + } 3327 3260 3328 - return 0; 3261 + ret = 0; 3262 + unlock: 3263 + mutex_unlock(&data->update_lock); 3264 + return ret; 3329 3265 } 3330 3266 3331 3267 const struct regulator_ops pmbus_regulator_ops = { ··· 3367 3281 } 3368 3282 EXPORT_SYMBOL_NS_GPL(pmbus_regulator_init_cb, "PMBUS"); 3369 3283 3284 + static void pmbus_regulator_notify_work_cancel(void *data) 3285 + { 3286 + struct pmbus_data *pdata = data; 3287 + 3288 + cancel_work_sync(&pdata->regulator_notify_work); 3289 + } 3290 + 3291 + static void pmbus_regulator_notify_worker(struct work_struct *work) 3292 + { 3293 + struct pmbus_data *data = 3294 + container_of(work, struct pmbus_data, regulator_notify_work); 3295 + int i, j; 3296 + 3297 + for (i = 0; i < data->info->pages; i++) { 3298 + int event; 3299 + 3300 + event = atomic_xchg(&data->regulator_events[i], 0); 3301 + if (!event) 3302 + continue; 3303 + 3304 + for (j = 0; j < data->info->num_regulators; j++) { 3305 + if (i == rdev_get_id(data->rdevs[j])) { 3306 + regulator_notifier_call_chain(data->rdevs[j], 3307 + event, NULL); 3308 + break; 3309 + } 3310 + } 3311 + } 3312 + } 3313 + 3370 3314 static int pmbus_regulator_register(struct pmbus_data *data) 3371 3315 { 3372 3316 struct device *dev = data->dev; 3373 3317 const struct pmbus_driver_info *info = data->info; 3374 3318 const struct pmbus_platform_data *pdata = dev_get_platdata(dev); 3375 - int i; 3319 + int i, ret; 3376 3320 3377 3321 data->rdevs = devm_kzalloc(dev, sizeof(struct regulator_dev *) * info->num_regulators, 3378 3322 GFP_KERNEL); ··· 3426 3310 info->reg_desc[i].name); 3427 3311 } 3428 3312 3313 + INIT_WORK(&data->regulator_notify_work, pmbus_regulator_notify_worker); 3314 + 3315 + ret = devm_add_action_or_reset(dev, pmbus_regulator_notify_work_cancel, data); 3316 + if (ret) 3317 + return ret; 3318 + 3429 3319 return 0; 3430 3320 } 3431 3321 3432 3322 static void pmbus_regulator_notify(struct pmbus_data *data, int page, int event) 3433 3323 { 3434 - int j; 3435 - 3436 - for (j = 0; j < data->info->num_regulators; j++) { 3437 - if (page == rdev_get_id(data->rdevs[j])) { 3438 - regulator_notifier_call_chain(data->rdevs[j], event, NULL); 3439 - break; 3440 - } 3441 - } 3324 + atomic_or(event, &data->regulator_events[page]); 3325 + schedule_work(&data->regulator_notify_work); 3442 3326 } 3443 3327 #else 3444 3328 static int pmbus_regulator_register(struct pmbus_data *data)