Commit fbe7ef3f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'thermal-6.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control fixes from Rafael Wysocki:
 "These fix the Mediatek lvts_thermal driver, the Intel int340x driver,
  and the thermal core (two issues related to system suspend).

  Specifics:

   - Remove the filtered mode for mt8188 from lvts_thermal as it is not
     supported on this platform and fail the lvts_thermal initialization
     when the golden temperature is zero as that means the efuse data is
     not correctly set (Julien Panis)

   - Update the processor_thermal part of the Intel int340x driver to
     support shared interrupts as the processor thermal device interrupt
     may in fact be shared with PCI devices (Srinivas Pandruvada)

   - Synchronize the suspend-prepare and post-suspend actions of the
     thermal PM notifier to avoid a destructive race condition and
     change the priority of that notifier to the minimum to avoid
     interference between the work items spawned by it and the other
     PM notifiers during system resume (Rafael Wysocki)"

* tag 'thermal-6.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  thermal: int340x: processor_thermal: Support shared interrupts
  thermal: core: Change PM notifier priority to the minimum
  thermal: core: Synchronize suspend-prepare and post-suspend actions
  thermal/drivers/mediatek/lvts_thermal: Return error in case of invalid efuse data
  thermal/drivers/mediatek/lvts_thermal: Remove filtered mode for mt8188
parents 66cc544f 096597cf
......@@ -150,7 +150,7 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
{
struct proc_thermal_pci *pci_info = devid;
struct proc_thermal_device *proc_priv;
int ret = IRQ_HANDLED;
int ret = IRQ_NONE;
u32 status;
proc_priv = pci_info->proc_priv;
......@@ -175,6 +175,7 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
/* Disable enable interrupt flag */
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
pkg_thermal_schedule_work(&pci_info->work);
ret = IRQ_HANDLED;
}
pci_write_config_byte(pci_info->pdev, 0xdc, 0x01);
......
......@@ -769,7 +769,11 @@ static int lvts_golden_temp_init(struct device *dev, u8 *calib,
*/
gt = (((u32 *)calib)[0] >> lvts_data->gt_calib_bit_offset) & 0xff;
if (gt && gt < LVTS_GOLDEN_TEMP_MAX)
/* A zero value for gt means that device has invalid efuse data */
if (!gt)
return -ENODATA;
if (gt < LVTS_GOLDEN_TEMP_MAX)
golden_temp = gt;
golden_temp_offset = golden_temp * 500 + lvts_data->temp_offset;
......@@ -1458,7 +1462,6 @@ static const struct lvts_ctrl_data mt8188_lvts_mcu_data_ctrl[] = {
},
VALID_SENSOR_MAP(1, 1, 1, 1),
.offset = 0x0,
.mode = LVTS_MSR_FILTERED_MODE,
},
{
.lvts_sensor = {
......@@ -1469,7 +1472,6 @@ static const struct lvts_ctrl_data mt8188_lvts_mcu_data_ctrl[] = {
},
VALID_SENSOR_MAP(1, 1, 0, 0),
.offset = 0x100,
.mode = LVTS_MSR_FILTERED_MODE,
}
};
......@@ -1483,7 +1485,6 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
},
VALID_SENSOR_MAP(0, 1, 0, 0),
.offset = 0x0,
.mode = LVTS_MSR_FILTERED_MODE,
},
{
.lvts_sensor = {
......@@ -1496,7 +1497,6 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
},
VALID_SENSOR_MAP(1, 1, 1, 0),
.offset = 0x100,
.mode = LVTS_MSR_FILTERED_MODE,
},
{
.lvts_sensor = {
......@@ -1507,7 +1507,6 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
},
VALID_SENSOR_MAP(1, 1, 0, 0),
.offset = 0x200,
.mode = LVTS_MSR_FILTERED_MODE,
},
{
.lvts_sensor = {
......@@ -1518,7 +1517,6 @@ static const struct lvts_ctrl_data mt8188_lvts_ap_data_ctrl[] = {
},
VALID_SENSOR_MAP(1, 1, 0, 0),
.offset = 0x300,
.mode = LVTS_MSR_FILTERED_MODE,
}
};
......
......@@ -1406,6 +1406,7 @@ thermal_zone_device_register_with_trips(const char *type,
ida_init(&tz->ida);
mutex_init(&tz->lock);
init_completion(&tz->removal);
init_completion(&tz->resume);
id = ida_alloc(&thermal_tz_ida, GFP_KERNEL);
if (id < 0) {
result = id;
......@@ -1651,6 +1652,9 @@ static void thermal_zone_device_resume(struct work_struct *work)
thermal_zone_device_init(tz);
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
complete(&tz->resume);
tz->resuming = false;
mutex_unlock(&tz->lock);
}
......@@ -1668,6 +1672,20 @@ static int thermal_pm_notify(struct notifier_block *nb,
list_for_each_entry(tz, &thermal_tz_list, node) {
mutex_lock(&tz->lock);
if (tz->resuming) {
/*
* thermal_zone_device_resume() queued up for
* this zone has not acquired the lock yet, so
* release it to let the function run and wait
* util it has done the work.
*/
mutex_unlock(&tz->lock);
wait_for_completion(&tz->resume);
mutex_lock(&tz->lock);
}
tz->suspended = true;
mutex_unlock(&tz->lock);
......@@ -1685,6 +1703,9 @@ static int thermal_pm_notify(struct notifier_block *nb,
cancel_delayed_work(&tz->poll_queue);
reinit_completion(&tz->resume);
tz->resuming = true;
/*
* Replace the work function with the resume one, which
* will restore the original work function and schedule
......@@ -1709,6 +1730,12 @@ static int thermal_pm_notify(struct notifier_block *nb,
static struct notifier_block thermal_pm_nb = {
.notifier_call = thermal_pm_notify,
/*
* Run at the lowest priority to avoid interference between the thermal
* zone resume work items spawned by thermal_pm_notify() and the other
* PM notifiers.
*/
.priority = INT_MIN,
};
static int __init thermal_init(void)
......
......@@ -55,6 +55,7 @@ struct thermal_governor {
* @type: the thermal zone device type
* @device: &struct device for this thermal zone
* @removal: removal completion
* @resume: resume completion
* @trip_temp_attrs: attributes for trip points for sysfs: trip temperature
* @trip_type_attrs: attributes for trip points for sysfs: trip type
* @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis
......@@ -89,6 +90,7 @@ struct thermal_governor {
* @poll_queue: delayed work for polling
* @notify_event: Last notification event
* @suspended: thermal zone suspend indicator
* @resuming: indicates whether or not thermal zone resume is in progress
* @trips: array of struct thermal_trip objects
*/
struct thermal_zone_device {
......@@ -96,6 +98,7 @@ struct thermal_zone_device {
char type[THERMAL_NAME_LENGTH];
struct device device;
struct completion removal;
struct completion resume;
struct attribute_group trips_attribute_group;
struct thermal_attr *trip_temp_attrs;
struct thermal_attr *trip_type_attrs;
......@@ -123,6 +126,7 @@ struct thermal_zone_device {
struct delayed_work poll_queue;
enum thermal_notify_event notify_event;
bool suspended;
bool resuming;
#ifdef CONFIG_THERMAL_DEBUGFS
struct thermal_debugfs *debugfs;
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment