Thermal control fixes for 7.2-rc1

- Fix dangling resources on thermal_throttle_online() failure in the
    Intel thermal_throttle driver (Ricardo Neri)
 
  - Eliminate a possibility of running thermal testing module code after
    that module has been removed (Rafael Wysocki)
 -----BEGIN PGP SIGNATURE-----
 
 iQFGBAABCAAwFiEEcM8Aw/RY0dgsiRUR7l+9nS/U47UFAmo+uqQSHHJqd0Byand5
 c29ja2kubmV0AAoJEO5fvZ0v1OO1IRIH/iMuMYJuLL574TDOjxCjCCXzHthbp+vU
 SQP24sEV8cRkpHu7Pf6LtqI4ofamyxlLRx0HbVEPaZieQRR/MdQAMbDXthDbWsDp
 sJn7aWzWkyZLnkS/5f22SLqspgRIIYWxUPuLFEevCFo0RGQwneXIbTABYtJNgKJA
 jmlvQNADX4w8NbEEXtdT08FGJt9xjn+X3VCrmLj1dU039hxVFzuKnABxFJsGiyqX
 EV5DEOnlnEUA9uGZT7DeGO4oH+5XNkXEN9UAXXefh7hWesZZpOV+eDbANAiF/YTM
 I2uCRuPImGffL6IWv5Vn8bnutBVKoys3BP5XZjKGoIfYopFGiwmXtcY=
 =6VOr
 -----END PGP SIGNATURE-----

Merge tag 'thermal-7.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control fixes from Rafael Wysocki:
 "These fix a failure path in an Intel thermal driver and prevent
  thermal testing module code from being executed after it has been
  freed:

   - Fix dangling resources on thermal_throttle_online() failure in the
     Intel thermal_throttle driver (Ricardo Neri)

   - Eliminate a possibility of running thermal testing module code
     after that module has been removed (Rafael Wysocki)"

* tag 'thermal-7.2-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  thermal: testing: zone: Flush work items during cleanup
  thermal: intel: Fix dangling resources on thermal_throttle_online() failure
This commit is contained in:
Linus Torvalds 2026-06-26 13:24:59 -07:00
commit 2dec87d0b1
4 changed files with 49 additions and 9 deletions

View File

@ -529,8 +529,13 @@ static int thermal_throttle_online(unsigned int cpu)
{
struct thermal_state *state = &per_cpu(thermal_state, cpu);
struct device *dev = get_cpu_device(cpu);
int err;
u32 l;
err = thermal_throttle_add_dev(dev, cpu);
if (err)
return err;
state->package_throttle.level = PACKAGE_LEVEL;
state->core_throttle.level = CORE_LEVEL;
@ -548,7 +553,7 @@ static int thermal_throttle_online(unsigned int cpu)
l = apic_read(APIC_LVTTHMR);
apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
return thermal_throttle_add_dev(dev, cpu);
return err;
}
static int thermal_throttle_offline(unsigned int cpu)

View File

@ -86,7 +86,10 @@
#include "thermal_testing.h"
struct dentry *d_testing;
struct workqueue_struct *tt_wq __ro_after_init;
struct dentry *d_testing __ro_after_init;
static struct dentry *d_command __ro_after_init;
#define TT_COMMAND_SIZE 16
@ -203,17 +206,42 @@ static const struct file_operations tt_command_fops = {
static int __init thermal_testing_init(void)
{
int error;
tt_wq = alloc_workqueue("thermal_testing", WQ_UNBOUND, 0);
if (!tt_wq)
return -ENOMEM;
d_testing = debugfs_create_dir("thermal-testing", NULL);
if (!IS_ERR(d_testing))
debugfs_create_file("command", 0200, d_testing, NULL,
&tt_command_fops);
if (IS_ERR(d_testing)) {
error = PTR_ERR(d_testing);
goto destroy_wq;
}
d_command = debugfs_create_file("command", 0200, d_testing, NULL, &tt_command_fops);
if (IS_ERR(d_command)) {
error = PTR_ERR(d_command);
goto remove_d_testing;
}
return 0;
remove_d_testing:
debugfs_remove(d_testing);
destroy_wq:
destroy_workqueue(tt_wq);
return error;
}
module_init(thermal_testing_init);
static void __exit thermal_testing_exit(void)
{
/* First, prevent new commands from being entered. */
debugfs_remove(d_command);
/* Flush commands in progress (if any). */
flush_workqueue(tt_wq);
destroy_workqueue(tt_wq);
/* Remove the directory structure and clean up. */
debugfs_remove(d_testing);
tt_zone_cleanup();
}

View File

@ -1,4 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/workqueue.h>
extern struct workqueue_struct *tt_wq;
static inline void tt_queue_work(struct work_struct *work)
{
queue_work(tt_wq, work);
}
extern struct dentry *d_testing;

View File

@ -13,7 +13,6 @@
#include <linux/idr.h>
#include <linux/list.h>
#include <linux/thermal.h>
#include <linux/workqueue.h>
#include "thermal_testing.h"
@ -207,7 +206,7 @@ int tt_add_tz(void)
INIT_WORK(&tt_work->work, tt_add_tz_work_fn);
tt_work->tt_zone = no_free_ptr(tt_zone);
schedule_work(&(no_free_ptr(tt_work)->work));
tt_queue_work(&(no_free_ptr(tt_work)->work));
return 0;
}
@ -269,7 +268,7 @@ int tt_del_tz(const char *arg)
INIT_WORK(&tt_work->work, tt_del_tz_work_fn);
tt_work->tt_zone = tt_zone;
schedule_work(&(no_free_ptr(tt_work)->work));
tt_queue_work(&(no_free_ptr(tt_work)->work));
return 0;
}
@ -358,7 +357,7 @@ int tt_zone_add_trip(const char *arg)
INIT_WORK(&tt_work->work, tt_zone_add_trip_work_fn);
tt_work->tt_zone = no_free_ptr(tt_zone);
tt_work->tt_trip = no_free_ptr(tt_trip);
schedule_work(&(no_free_ptr(tt_work)->work));
tt_queue_work(&(no_free_ptr(tt_work)->work));
return 0;
}