mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

1) unbalanced debugfs_file_get(). Not needed in the first place - file_operations are accessed only via debugfs_create_file(), so debugfs wrappers will take care of that itself. 2) kmalloc() for a buffer used only for duration of a function is not a problem, but for a buffer no longer than 16 bytes? 3) strstr() is for finding substrings; for finding a character there's strchr(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Acked-by: "Rafael J. Wysocki" <rafael@kernel.org> Link: https://lore.kernel.org/r/20250702212542.GH3406663@ZenIV Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
211 lines
5.3 KiB
C
211 lines
5.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright 2024, Intel Corporation
|
|
*
|
|
* Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
|
*
|
|
* Thermal subsystem testing facility.
|
|
*
|
|
* This facility allows the thermal core functionality to be exercised in a
|
|
* controlled way in order to verify its behavior.
|
|
*
|
|
* It resides in the "thermal-testing" directory under the debugfs root and
|
|
* starts with a single file called "command" which can be written a string
|
|
* representing a thermal testing facility command.
|
|
*
|
|
* The currently supported commands are listed in the tt_commands enum below.
|
|
*
|
|
* The "addtz" command causes a new test thermal zone template to be created,
|
|
* for example:
|
|
*
|
|
* # echo addtz > /sys/kernel/debug/thermal-testing/command
|
|
*
|
|
* That template will be represented as a subdirectory in the "thermal-testing"
|
|
* directory, for example
|
|
*
|
|
* # ls /sys/kernel/debug/thermal-testing/
|
|
* command tz0
|
|
*
|
|
* The thermal zone template can be populated with trip points with the help of
|
|
* the "tzaddtrip" command, for example:
|
|
*
|
|
* # echo tzaddtrip:0 > /sys/kernel/debug/thermal-testing/command
|
|
*
|
|
* which causes a trip point template to be added to the test thermal zone
|
|
* template 0 (represented by the tz0 subdirectory in "thermal-testing").
|
|
*
|
|
* # ls /sys/kernel/debug/thermal-testing/tz0
|
|
* init_temp temp trip_0_temp trip_0_hyst
|
|
*
|
|
* The temperature of a trip point template is initially THERMAL_TEMP_INVALID
|
|
* and its hysteresis is initially 0. They can be adjusted by writing to the
|
|
* "trip_x_temp" and "trip_x_hyst" files correspoinding to that trip point
|
|
* template, respectively.
|
|
*
|
|
* The initial temperature of a thermal zone based on a template can be set by
|
|
* writing to the "init_temp" file in its directory under "thermal-testing", for
|
|
* example:
|
|
*
|
|
* echo 50000 > /sys/kernel/debug/thermal-testing/tz0/init_temp
|
|
*
|
|
* When ready, "tzreg" command can be used for registering and enabling a
|
|
* thermal zone based on a given template with the thermal core, for example
|
|
*
|
|
* # echo tzreg:0 > /sys/kernel/debug/thermal-testing/command
|
|
*
|
|
* In this case, test thermal zone template 0 is used for registering a new
|
|
* thermal zone and the set of trip point templates associated with it is used
|
|
* for populating the new thermal zone's trip points table. The type of the new
|
|
* thermal zone is "test_tz".
|
|
*
|
|
* The temperature and hysteresis of all of the trip points in that new thermal
|
|
* zone are adjustable via sysfs, so they can be updated at any time.
|
|
*
|
|
* The current temperature of the new thermal zone can be set by writing to the
|
|
* "temp" file in the corresponding thermal zone template's directory under
|
|
* "thermal-testing", for example
|
|
*
|
|
* echo 10000 > /sys/kernel/debug/thermal-testing/tz0/temp
|
|
*
|
|
* which will also trigger a temperature update for this zone in the thermal
|
|
* core, including checking its trip points, sending notifications to user space
|
|
* if any of them have been crossed and so on.
|
|
*
|
|
* When it is not needed any more, a test thermal zone template can be deleted
|
|
* with the help of the "deltz" command, for example
|
|
*
|
|
* # echo deltz:0 > /sys/kernel/debug/thermal-testing/command
|
|
*
|
|
* which will also unregister the thermal zone based on it, if present.
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "thermal-testing: " fmt
|
|
|
|
#include <linux/debugfs.h>
|
|
#include <linux/module.h>
|
|
|
|
#include "thermal_testing.h"
|
|
|
|
struct dentry *d_testing;
|
|
|
|
#define TT_COMMAND_SIZE 16
|
|
|
|
enum tt_commands {
|
|
TT_CMD_ADDTZ,
|
|
TT_CMD_DELTZ,
|
|
TT_CMD_TZADDTRIP,
|
|
TT_CMD_TZREG,
|
|
TT_CMD_TZUNREG,
|
|
};
|
|
|
|
static const char *tt_command_strings[] = {
|
|
[TT_CMD_ADDTZ] = "addtz",
|
|
[TT_CMD_DELTZ] = "deltz",
|
|
[TT_CMD_TZADDTRIP] = "tzaddtrip",
|
|
[TT_CMD_TZREG] = "tzreg",
|
|
[TT_CMD_TZUNREG] = "tzunreg",
|
|
};
|
|
|
|
static int tt_command_exec(int index, const char *arg)
|
|
{
|
|
int ret;
|
|
|
|
switch (index) {
|
|
case TT_CMD_ADDTZ:
|
|
ret = tt_add_tz();
|
|
break;
|
|
|
|
case TT_CMD_DELTZ:
|
|
ret = tt_del_tz(arg);
|
|
break;
|
|
|
|
case TT_CMD_TZADDTRIP:
|
|
ret = tt_zone_add_trip(arg);
|
|
break;
|
|
|
|
case TT_CMD_TZREG:
|
|
ret = tt_zone_reg(arg);
|
|
break;
|
|
|
|
case TT_CMD_TZUNREG:
|
|
ret = tt_zone_unreg(arg);
|
|
break;
|
|
|
|
default:
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t tt_command_process(char *s)
|
|
{
|
|
char *arg;
|
|
int i;
|
|
|
|
strim(s);
|
|
|
|
arg = strchr(s, ':');
|
|
if (arg) {
|
|
*arg = '\0';
|
|
arg++;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tt_command_strings); i++) {
|
|
if (!strcmp(s, tt_command_strings[i]))
|
|
return tt_command_exec(i, arg);
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
static ssize_t tt_command_write(struct file *file, const char __user *user_buf,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
char buf[TT_COMMAND_SIZE];
|
|
ssize_t ret;
|
|
|
|
if (*ppos)
|
|
return -EINVAL;
|
|
|
|
if (count > TT_COMMAND_SIZE - 1)
|
|
return -E2BIG;
|
|
|
|
if (copy_from_user(buf, user_buf, count))
|
|
return -EFAULT;
|
|
buf[count] = '\0';
|
|
|
|
ret = tt_command_process(buf);
|
|
if (ret)
|
|
return ret;
|
|
|
|
return count;
|
|
}
|
|
|
|
static const struct file_operations tt_command_fops = {
|
|
.write = tt_command_write,
|
|
.open = simple_open,
|
|
.llseek = default_llseek,
|
|
};
|
|
|
|
static int __init thermal_testing_init(void)
|
|
{
|
|
d_testing = debugfs_create_dir("thermal-testing", NULL);
|
|
if (!IS_ERR(d_testing))
|
|
debugfs_create_file("command", 0200, d_testing, NULL,
|
|
&tt_command_fops);
|
|
|
|
return 0;
|
|
}
|
|
module_init(thermal_testing_init);
|
|
|
|
static void __exit thermal_testing_exit(void)
|
|
{
|
|
debugfs_remove(d_testing);
|
|
tt_zone_cleanup();
|
|
}
|
|
module_exit(thermal_testing_exit);
|
|
|
|
MODULE_DESCRIPTION("Thermal core testing facility");
|
|
MODULE_LICENSE("GPL v2");
|