mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
hwmon fixes for v7.3-rc4
* cgbc-hwmon: Add missing sensors, and fix current sensors ID lookup
* gpioufan: Return IRQ_HANDLED from the shared alarm IRQ handler to fix
possible interrupt storm
* hp-wmi-sensors: Improve raw WMI string handling, and fix UaF in show
function
* k10temp: Fix model id range of Zen5 Turin to stop reporting temperature
data for non-existing CCDs
* pmbus
- core: Increase number of phases to fix UaF problems
- tps53679: Fix TPS53676 phase page decoding, and select page 0
for single-page applications
* pwm-fan: Stop RPM timer before freeing tach data to fix UaF problem
* w83793: Release probe data through kref to fix UaF problem
* w83791d: Remove fan/pwm 4-5 sysfs group on remove to fix UaF problem
-----BEGIN PGP SIGNATURE-----
iQIzBAABCAAdFiEEiHPvMQj9QTOCiqgVyx8mb86fmYEFAmqtY4YACgkQyx8mb86f
mYHX0Q//UmlkmqkHH3XdKi1QX/RV60f82HfzXRkMq98FYocEYv4TKnru3U5pRLY3
Vs/h4GcDWT16ApqKbciBxgoUj72XBohm/T0gv8rhC/gkx4w8F7/CPuCB6vq9kIAj
EIOHM3KoulfwUN6K1JeFdo5sIrTMxYGnQoJjS31/HfExEGbcBMZjA4eWLkqA0s18
zmtYKbCJbG2WFRkI8/HKeQ2MwFE3RLNrxPVNvWJNzwIPjMvaAD7eDSsRjgXpaH6s
A2OHpnGkDLE1qeyuYYx+nFYmMQDGDxnt6QvEjX5cVUYE+jDIXuzF5HJVfLCaXoSJ
cFJmyNVTNE6Is1g6qeBRwObSq/NJH3O6p7kXCf5qwO27XBXgt/7K4q751tMq8oEE
kXiYn3WfBL4WJjYqQw8kEh2/D18fyj9XmoS7iBXzf1qXgRSROm/9irMBjsWiw0WF
92iE9U7UaE/a5fGX+dbRnB7QmLZ33U5TzA3ERb+MwJQj6o8Llvb5gmJOmlYebpa1
zRiu285Y3oGnjjkFgzvpps9hsVw3kb2Xs2utMbTPrJ2z4SUO9KInl+ifOr5w9VI+
sNU0Rn3eQ6IT40NMO9FhHPciZygKmob6hNDYh/6e+OulMDW7XW46ES2e8jjwME30
fjDpfKDxoAU/xQ548XQJBRcUNjUhV8S6NYZr3H4PpyWlPVmSkOY=
=lG35
-----END PGP SIGNATURE-----
Merge tag 'hwmon-for-v7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon fixes from Guenter Roeck:
- Add missing sensors, and fix current sensors ID lookup (cgbc-hwmon)
- Return IRQ_HANDLED from the shared alarm IRQ handler to fix possible
interrupt storm (gpioufan)
- Improve raw WMI string handling, and fix UaF in show function
(hp-wmi-sensors)
- Fix k10temp model id range of Zen5 Turin to stop reporting
temperature data for non-existing CCDs
- pmbus:
- Increase number of phases to fix UaF problems
- Fix TPS53676 phase page decoding, and select page 0 for
single-page applications
- Stop pwm-fan RPM timer before freeing tach data to fix UaF
- Release w83793 probe data through kref to fix UaF
- Remove w83791d fan/pwm 4-5 sysfs group on remove to fix UaF
* tag 'hwmon-for-v7.3-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
hwmon: (hp-wmi-sensors) Improve raw WMI string handling
hwmon: (pmbus/tps53679) Select page 0 for single-page TPS53676
hwmon: (pmbus/tps53679) Fix TPS53676 phase page decoding
hwmon: (hp-wmi-sensors) Fix use-after-free in fungible_show()
hwmon: (w83793) release probe data through kref
hwmon: (w83791d) remove fan/pwm 4-5 sysfs group on remove
hwmon: (gpio-fan) return IRQ_HANDLED from the shared alarm IRQ handler
hwmon: (pmbus/core) increase number of phases and add new mask
hwmon: (cgbc-hwmon) Add missing sensors
hwmon: (cgbc-hwmon) Fix current sensors ID lookup
hwmon: (pwm-fan) Stop RPM timer before freeing tach data
hwmon: (k10temp) Fix model id range of Zen5 Turin
This commit is contained in:
commit
d24e3bf4c5
|
|
@ -28,34 +28,44 @@ system.
|
|||
Name Description
|
||||
============= ======================
|
||||
temp1_input CPU temperature
|
||||
temp2_input Box temperature
|
||||
temp2_input Case temperature
|
||||
temp3_input Ambient temperature
|
||||
temp4_input Board temperature
|
||||
temp5_input Carrier temperature
|
||||
temp6_input Chipset temperature
|
||||
temp7_input Video temperature
|
||||
temp4_input CPU Board temperature
|
||||
temp5_input Carrier Board temperature
|
||||
temp6_input System Chipset temperature
|
||||
temp7_input Video Controller/Board temperature
|
||||
temp8_input Other temperature
|
||||
temp9_input TOPDIM temperature
|
||||
temp10_input BOTTOMDIM temperature
|
||||
in0_input CPU voltage
|
||||
temp9_input Top DIMM 0 temperature
|
||||
temp10_input Bottom DIMM 0 temperature
|
||||
temp11_input Alternate Board temperature
|
||||
temp12_input Top DIMM 1 temperature
|
||||
temp13_input Top DIMM 2 temperature
|
||||
temp14_input Top DIMM 3 temperature
|
||||
temp15_input Top DIMM 4 temperature
|
||||
temp16_input Top DIMM 5 temperature
|
||||
temp17_input Top DIMM 6 temperature
|
||||
temp18_input Top DIMM 7 temperature
|
||||
temp19_input Bottom DIMM 1 temperature
|
||||
in0_input CPU Core voltage
|
||||
in1_input DC Runtime voltage
|
||||
in2_input DC Standby voltage
|
||||
in3_input CMOS Battery voltage
|
||||
in4_input Battery voltage
|
||||
in4_input Battery Supply voltage
|
||||
in5_input AC voltage
|
||||
in6_input Other voltage
|
||||
in7_input 5V voltage
|
||||
in7_input 5V Runtime voltage
|
||||
in8_input 5V Standby voltage
|
||||
in9_input 3V3 voltage
|
||||
in9_input 3V3 Runtime voltage
|
||||
in10_input 3V3 Standby voltage
|
||||
in11_input VCore A voltage
|
||||
in12_input VCore B voltage
|
||||
in13_input 12V voltage
|
||||
curr1_input DC current
|
||||
curr2_input 5V current
|
||||
curr3_input 12V current
|
||||
in13_input 12V Runtime voltage
|
||||
in14_input 12V Standby voltage
|
||||
curr1_input DC Runtime current
|
||||
curr2_input 5V Runtime current
|
||||
curr3_input 12V Runtime current
|
||||
fan1_input CPU fan
|
||||
fan2_input Box fan
|
||||
fan2_input Case fan
|
||||
fan3_input Ambient fan
|
||||
fan4_input Chiptset fan
|
||||
fan5_input Video fan
|
||||
|
|
|
|||
|
|
@ -41,45 +41,60 @@ enum cgbc_sensor_types {
|
|||
|
||||
static const char * const cgbc_hwmon_labels_temp[] = {
|
||||
"CPU Temperature",
|
||||
"Box Temperature",
|
||||
"Case Temperature",
|
||||
"Ambient Temperature",
|
||||
"Board Temperature",
|
||||
"Carrier Temperature",
|
||||
"Chipset Temperature",
|
||||
"Video Temperature",
|
||||
"CPU Board Temperature",
|
||||
"Carrier Board Temperature",
|
||||
"System Chipset Temperature",
|
||||
"Video Controller/Board Temperature",
|
||||
"Other Temperature",
|
||||
"TOPDIM Temperature",
|
||||
"BOTTOMDIM Temperature",
|
||||
"Top DIMM 0 Temperature",
|
||||
"Bottom DIMM 0 Temperature",
|
||||
"Alternate Board Temperature",
|
||||
"Top DIMM 1 Temperature",
|
||||
"Top DIMM 2 Temperature",
|
||||
"Top DIMM 3 Temperature",
|
||||
"Top DIMM 4 Temperature",
|
||||
"Top DIMM 5 Temperature",
|
||||
"Top DIMM 6 Temperature",
|
||||
"Top DIMM 7 Temperature",
|
||||
"Bottom DIMM 1 Temperature",
|
||||
};
|
||||
|
||||
static const char * const cgbc_hwmon_labels_in[] = {
|
||||
"CPU Core Voltage",
|
||||
"DC Runtime Voltage",
|
||||
"DC Standby Voltage",
|
||||
"CMOS Battery Voltage",
|
||||
"Battery Supply Voltage",
|
||||
"AC Voltage",
|
||||
"Other Voltage",
|
||||
"5V Runtime Voltage",
|
||||
"5V Standby Voltage",
|
||||
"3V3 Runtime Voltage",
|
||||
"3V3 Standby Voltage",
|
||||
"VCore A Voltage",
|
||||
"VCore B Voltage",
|
||||
"12V Runtime Voltage",
|
||||
"12V Standby Voltage",
|
||||
};
|
||||
|
||||
/*
|
||||
* Current sensors are a bit special, they don't have consecutive IDs like
|
||||
* other types of sensors. So they need to be defined explicitly.
|
||||
*/
|
||||
static const struct {
|
||||
enum hwmon_sensor_types type;
|
||||
const char *label;
|
||||
} cgbc_hwmon_labels_in[] = {
|
||||
{ hwmon_in, "CPU Voltage" },
|
||||
{ hwmon_in, "DC Runtime Voltage" },
|
||||
{ hwmon_in, "DC Standby Voltage" },
|
||||
{ hwmon_in, "CMOS Battery Voltage" },
|
||||
{ hwmon_in, "Battery Voltage" },
|
||||
{ hwmon_in, "AC Voltage" },
|
||||
{ hwmon_in, "Other Voltage" },
|
||||
{ hwmon_in, "5V Voltage" },
|
||||
{ hwmon_in, "5V Standby Voltage" },
|
||||
{ hwmon_in, "3V3 Voltage" },
|
||||
{ hwmon_in, "3V3 Standby Voltage" },
|
||||
{ hwmon_in, "VCore A Voltage" },
|
||||
{ hwmon_in, "VCore B Voltage" },
|
||||
{ hwmon_in, "12V Voltage" },
|
||||
{ hwmon_curr, "DC Current" },
|
||||
{ hwmon_curr, "5V Current" },
|
||||
{ hwmon_curr, "12V Current" },
|
||||
int id;
|
||||
} cgbc_hwmon_labels_curr[] = {
|
||||
{ "DC Runtime Current", 0x12 },
|
||||
{ "5V Runtime Current", 0x18 },
|
||||
{ "12V Runtime Current", 0x1E },
|
||||
};
|
||||
|
||||
#define CGBC_HWMON_NB_IN_SENSORS 14
|
||||
|
||||
static const char * const cgbc_hwmon_labels_fan[] = {
|
||||
"CPU Fan",
|
||||
"Box Fan",
|
||||
"Case Fan",
|
||||
"Ambient Fan",
|
||||
"Chipset Fan",
|
||||
"Video Fan",
|
||||
|
|
@ -114,7 +129,8 @@ static int cgbc_hwmon_probe_sensors(struct device *dev, struct cgbc_hwmon_data *
|
|||
|
||||
for (i = 0; i < nb_sensors; i++) {
|
||||
enum cgbc_sensor_types type;
|
||||
unsigned int channel;
|
||||
unsigned int channel, id;
|
||||
int j;
|
||||
|
||||
/*
|
||||
* No need to request data for the first sensor.
|
||||
|
|
@ -128,32 +144,49 @@ static int cgbc_hwmon_probe_sensors(struct device *dev, struct cgbc_hwmon_data *
|
|||
}
|
||||
|
||||
type = FIELD_GET(CGBC_HWMON_TYPE_MASK, data[1]);
|
||||
channel = FIELD_GET(CGBC_HWMON_ID_MASK, data[1]) - 1;
|
||||
id = FIELD_GET(CGBC_HWMON_ID_MASK, data[1]);
|
||||
channel = id - 1;
|
||||
|
||||
if (type == CGBC_HWMON_TYPE_TEMP && channel < ARRAY_SIZE(cgbc_hwmon_labels_temp)) {
|
||||
sensor->type = hwmon_temp;
|
||||
sensor->label = cgbc_hwmon_labels_temp[channel];
|
||||
} else if (type == CGBC_HWMON_TYPE_IN &&
|
||||
channel < ARRAY_SIZE(cgbc_hwmon_labels_in)) {
|
||||
} else if (type == CGBC_HWMON_TYPE_IN) {
|
||||
/*
|
||||
* The Board Controller doesn't differentiate current and voltage sensors.
|
||||
* Get the sensor type from cgbc_hwmon_labels_in[channel].type instead.
|
||||
* First check if it is a current sensor.
|
||||
*/
|
||||
sensor->type = cgbc_hwmon_labels_in[channel].type;
|
||||
sensor->label = cgbc_hwmon_labels_in[channel].label;
|
||||
for (j = 0; j < ARRAY_SIZE(cgbc_hwmon_labels_curr); j++) {
|
||||
if (id == cgbc_hwmon_labels_curr[j].id) {
|
||||
sensor->type = hwmon_curr;
|
||||
sensor->label = cgbc_hwmon_labels_curr[j].label;
|
||||
channel = j;
|
||||
}
|
||||
}
|
||||
|
||||
/* If it's not a current sensor, it may be a voltage sensor. */
|
||||
if (!sensor->label && channel < ARRAY_SIZE(cgbc_hwmon_labels_in)) {
|
||||
sensor->type = hwmon_in;
|
||||
sensor->label = cgbc_hwmon_labels_in[channel];
|
||||
}
|
||||
} else if (type == CGBC_HWMON_TYPE_FAN &&
|
||||
channel < ARRAY_SIZE(cgbc_hwmon_labels_fan)) {
|
||||
sensor->type = hwmon_fan;
|
||||
sensor->label = cgbc_hwmon_labels_fan[channel];
|
||||
} else {
|
||||
dev_warn(dev, "Board Controller returned an unknown sensor (type=%d, channel=%d), ignore it",
|
||||
type, channel);
|
||||
}
|
||||
|
||||
if (!sensor->label) {
|
||||
dev_warn(dev, "Board Controller returned an unknown sensor (bc_type=%d, bc_id=%d), ignore it",
|
||||
type, id);
|
||||
continue;
|
||||
}
|
||||
|
||||
sensor->active = FIELD_GET(CGBC_HWMON_ACTIVE_BIT, data[1]);
|
||||
sensor->channel = channel;
|
||||
sensor->index = i;
|
||||
|
||||
dev_dbg(dev, "Found sensor: bc_type=%d, bc_id=%d, hwmon_type=%d, hwmon_channel=%d, hwmon_label='%s', active=%d\n",
|
||||
type, id, sensor->type, sensor->channel, sensor->label, sensor->active);
|
||||
|
||||
sensor++;
|
||||
hwmon->nb_sensors++;
|
||||
}
|
||||
|
|
@ -167,14 +200,6 @@ static struct cgbc_hwmon_sensor *cgbc_hwmon_find_sensor(struct cgbc_hwmon_data *
|
|||
struct cgbc_hwmon_sensor *sensor = NULL;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* The Board Controller doesn't differentiate current and voltage sensors.
|
||||
* The channel value (from the Board Controller point of view) shall be computed for current
|
||||
* sensors.
|
||||
*/
|
||||
if (type == hwmon_curr)
|
||||
channel += CGBC_HWMON_NB_IN_SENSORS;
|
||||
|
||||
for (i = 0; i < hwmon->nb_sensors; i++) {
|
||||
if (hwmon->sensors[i].type == type && hwmon->sensors[i].channel == channel) {
|
||||
sensor = &hwmon->sensors[i];
|
||||
|
|
@ -240,7 +265,12 @@ static const struct hwmon_channel_info * const cgbc_hwmon_info[] = {
|
|||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL),
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_LABEL,
|
||||
HWMON_T_INPUT | HWMON_T_LABEL),
|
||||
HWMON_CHANNEL_INFO(in,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
|
|
@ -248,7 +278,8 @@ static const struct hwmon_channel_info * const cgbc_hwmon_info[] = {
|
|||
HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL),
|
||||
HWMON_I_INPUT | HWMON_I_LABEL, HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL),
|
||||
HWMON_CHANNEL_INFO(curr,
|
||||
HWMON_C_INPUT | HWMON_C_LABEL, HWMON_C_INPUT | HWMON_C_LABEL,
|
||||
HWMON_C_INPUT | HWMON_C_LABEL),
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id)
|
|||
|
||||
schedule_work(&fan_data->alarm_work);
|
||||
|
||||
return IRQ_NONE;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static ssize_t fan1_alarm_show(struct device *dev,
|
||||
|
|
@ -103,7 +103,7 @@ static int fan_alarm_init(struct gpio_fan_data *fan_data)
|
|||
|
||||
irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
|
||||
return devm_request_irq(dev, alarm_irq, fan_alarm_irq_handler,
|
||||
IRQF_SHARED, "GPIO fan alarm", fan_data);
|
||||
0, "GPIO fan alarm", fan_data);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -526,14 +526,12 @@ static int check_wobj(const union acpi_object *wobj,
|
|||
for (prop = 0; prop <= last_prop; prop++) {
|
||||
type = elements[prop].type;
|
||||
valid_type = property_map[prop];
|
||||
if (type != valid_type) {
|
||||
if (type == ACPI_TYPE_BUFFER &&
|
||||
valid_type == ACPI_TYPE_STRING &&
|
||||
is_raw_wmi_string(elements[prop].buffer.pointer,
|
||||
elements[prop].buffer.length))
|
||||
continue;
|
||||
if (type == ACPI_TYPE_BUFFER &&
|
||||
is_raw_wmi_string(elements[prop].buffer.pointer,
|
||||
elements[prop].buffer.length))
|
||||
type = ACPI_TYPE_STRING;
|
||||
if (type != valid_type)
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -579,6 +577,7 @@ static int check_numeric_sensor_wobj(const union acpi_object *wobj,
|
|||
int prop = HP_WMI_PROPERTY_NAME;
|
||||
acpi_object_type valid_type;
|
||||
union acpi_object *elements;
|
||||
union acpi_object *element;
|
||||
u32 elem_count;
|
||||
int last_prop;
|
||||
bool is_new;
|
||||
|
|
@ -602,13 +601,20 @@ static int check_numeric_sensor_wobj(const union acpi_object *wobj,
|
|||
elem_count > HP_WMI_MAX_PROPERTIES)
|
||||
return -EINVAL;
|
||||
|
||||
type = elements[HP_WMI_PROPERTY_SIZE].type;
|
||||
element = &elements[HP_WMI_PROPERTY_SIZE];
|
||||
type = element->type;
|
||||
switch (type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
is_new = true;
|
||||
last_prop = HP_WMI_PROPERTY_RATE_UNITS;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
if (!is_raw_wmi_string(element->buffer.pointer,
|
||||
element->buffer.length))
|
||||
return -EINVAL;
|
||||
fallthrough;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
is_new = false;
|
||||
last_prop = HP_WMI_PROPERTY_CURRENT_READING;
|
||||
|
|
@ -631,6 +637,10 @@ static int check_numeric_sensor_wobj(const union acpi_object *wobj,
|
|||
for (i = 0; i < elem_count && prop <= last_prop; i++, prop++) {
|
||||
type = elements[i].type;
|
||||
valid_type = hp_wmi_property_map[prop];
|
||||
if (type == ACPI_TYPE_BUFFER &&
|
||||
is_raw_wmi_string(elements[i].buffer.pointer,
|
||||
elements[i].buffer.length))
|
||||
type = ACPI_TYPE_STRING;
|
||||
if (type != valid_type)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -651,6 +661,10 @@ static int check_numeric_sensor_wobj(const union acpi_object *wobj,
|
|||
/* PossibleStates[0] has already been type-checked. */
|
||||
for (j = 0; i + 1 < elem_count && j + 1 < count; j++) {
|
||||
type = elements[++i].type;
|
||||
if (type == ACPI_TYPE_BUFFER &&
|
||||
is_raw_wmi_string(elements[i].buffer.pointer,
|
||||
elements[i].buffer.length))
|
||||
type = ACPI_TYPE_STRING;
|
||||
if (type != valid_type)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1247,7 +1261,9 @@ static int fungible_show(struct seq_file *seqf, enum hp_wmi_property prop)
|
|||
break;
|
||||
|
||||
case HP_WMI_PROPERTY_CURRENT_STATE:
|
||||
mutex_lock(&state->lock);
|
||||
seq_printf(seqf, "%s\n", nsensor->current_state);
|
||||
mutex_unlock(&state->lock);
|
||||
break;
|
||||
|
||||
case HP_WMI_PROPERTY_UNIT_MODIFIER:
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
}
|
||||
} else if (boot_cpu_data.x86 == 0x1a) {
|
||||
switch (boot_cpu_data.x86_model) {
|
||||
case 0x00 ... 0x2f: /* Zen5 Turin */
|
||||
case 0x00 ... 0x1f: /* Zen5 Turin */
|
||||
data->ccd_offset = 0x1F0;
|
||||
k10temp_get_ccd_support(data, 16);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ enum pmbus_regs {
|
|||
/*
|
||||
* OPERATION
|
||||
*/
|
||||
#define PB_OPERATION_CONTROL_V_SRC GENMASK(5, 4)
|
||||
#define PB_OPERATION_CONTROL_ON BIT(7)
|
||||
|
||||
/*
|
||||
|
|
@ -386,7 +387,7 @@ enum pmbus_sensor_classes {
|
|||
};
|
||||
|
||||
#define PMBUS_PAGES 32 /* Per PMBus specification */
|
||||
#define PMBUS_PHASES 10 /* Maximum number of phases per page */
|
||||
#define PMBUS_PHASES 16 /* Maximum number of phases per page */
|
||||
|
||||
/* Functionality bit mask */
|
||||
#define PMBUS_HAVE_VIN BIT(0)
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ static int tps53676_identify(struct i2c_client *client,
|
|||
return -EIO;
|
||||
for (i = 0; i < 2 * TPS53676_MAX_PHASES; i += 2) {
|
||||
if (buf[i + 1] & 0x80) {
|
||||
if (buf[i] & 0x08)
|
||||
if (buf[i] & BIT(4))
|
||||
phases_b++;
|
||||
else
|
||||
phases_a++;
|
||||
|
|
@ -200,6 +200,15 @@ static int tps53676_identify(struct i2c_client *client,
|
|||
if (phases_b > 0) {
|
||||
info->pages = 2;
|
||||
info->phases[1] = phases_b;
|
||||
} else {
|
||||
/*
|
||||
* pmbus_set_page() does not update the PAGE register on
|
||||
* single-page devices, so select page 0 explicitly in case
|
||||
* the boot firmware left the device on another page.
|
||||
*/
|
||||
ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -483,7 +483,6 @@ static void pwm_fan_cleanup(void *__ctx)
|
|||
{
|
||||
struct pwm_fan_ctx *ctx = __ctx;
|
||||
|
||||
timer_delete_sync(&ctx->rpm_timer);
|
||||
if (ctx->pwm_shutdown) {
|
||||
ctx->enable_mode = pwm_enable_reg_enable;
|
||||
__set_pwm(ctx, ctx->pwm_shutdown);
|
||||
|
|
@ -494,6 +493,13 @@ static void pwm_fan_cleanup(void *__ctx)
|
|||
}
|
||||
}
|
||||
|
||||
static void pwm_fan_timer_cleanup(void *__ctx)
|
||||
{
|
||||
struct pwm_fan_ctx *ctx = __ctx;
|
||||
|
||||
timer_shutdown_sync(&ctx->rpm_timer);
|
||||
}
|
||||
|
||||
static int pwm_fan_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct thermal_cooling_device *cdev;
|
||||
|
|
@ -644,6 +650,10 @@ static int pwm_fan_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (ctx->tach_count > 0) {
|
||||
ret = devm_add_action_or_reset(dev, pwm_fan_timer_cleanup, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctx->sample_start = ktime_get();
|
||||
mod_timer(&ctx->rpm_timer, jiffies + HZ);
|
||||
|
||||
|
|
@ -700,6 +710,7 @@ static void pwm_fan_shutdown(struct platform_device *pdev)
|
|||
{
|
||||
struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
pwm_fan_timer_cleanup(ctx);
|
||||
pwm_fan_cleanup(ctx);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1415,6 +1415,7 @@ static void w83791d_remove(struct i2c_client *client)
|
|||
struct w83791d_data *data = i2c_get_clientdata(client);
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &w83791d_group_fanpwm45);
|
||||
sysfs_remove_group(&client->dev.kobj, &w83791d_group);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1928,7 +1928,9 @@ static int w83793_probe(struct i2c_client *client)
|
|||
for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
|
||||
device_remove_file(dev, &w83793_temp[i].dev_attr);
|
||||
free_mem:
|
||||
kfree(data);
|
||||
mutex_lock(&watchdog_data_mutex);
|
||||
kref_put(&data->kref, w83793_release_resources);
|
||||
mutex_unlock(&watchdog_data_mutex);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user