2023-09-27 04:56:35

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 0/5] thermal: processor_thermal: Power floor status

Support power floor notifications for Meteor Lake processors.

The first change is to prepare for power floor status and others
add support for power floor.

Srinivas Pandruvada (5):
thermal: int340x: processor_thermal: Set feature mask before
proc_thermal_add
thermal: int340x: processor_thermal: Support power floor notifications
thermal: int340x: processor_thermal: Handle power floor interrupts
thermal: int340x: processor_thermal: Enable power floor support
selftests/thermel/intel: Add test to read power floor status

.../driver-api/thermal/intel_dptf.rst | 8 ++
.../thermal/intel/int340x_thermal/Makefile | 1 +
.../processor_thermal_device.c | 68 ++++++++++-
.../processor_thermal_device.h | 8 ++
.../processor_thermal_device_pci.c | 29 +++--
.../processor_thermal_power_floor.c | 114 ++++++++++++++++++
tools/testing/selftests/Makefile | 1 +
.../thermal/intel/power_floor/Makefile | 12 ++
.../intel/power_floor/power_floor_test.c | 108 +++++++++++++++++
9 files changed, 336 insertions(+), 13 deletions(-)
create mode 100644 drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
create mode 100644 tools/testing/selftests/thermal/intel/power_floor/Makefile
create mode 100644 tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c

--
2.41.0


2023-09-27 06:47:16

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 1/5] thermal: int340x: processor_thermal: Set feature mask before proc_thermal_add

The function proc_thermal_add() adds sysfs entries for power limits.
The feature mask of available features is not present by this time.
If feature mask is available, then this can be used to selectively
create attributes.

Feature mask is set during call to proc_thermal_mmio_add(). Change the
order of calls so that proc_thermal_mmio_add() is called before
proc_thermal_add().

There is no functional impact with this change.

Signed-off-by: Srinivas Pandruvada <[email protected]>
---
.../processor_thermal_device_pci.c | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
index 3c5ced79ead0..e2c7beb91c60 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
@@ -253,19 +253,19 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_

INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn);

- ret = proc_thermal_add(&pdev->dev, proc_priv);
- if (ret) {
- dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n");
- pci_info->no_legacy = 1;
- }
-
proc_priv->priv_data = pci_info;
pci_info->proc_priv = proc_priv;
pci_set_drvdata(pdev, proc_priv);

ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
if (ret)
- goto err_ret_thermal;
+ return ret;
+
+ ret = proc_thermal_add(&pdev->dev, proc_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n");
+ pci_info->no_legacy = 1;
+ }

psv_trip.temperature = get_trip_temp(pci_info);

@@ -275,7 +275,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
&tzone_params, 0, 0);
if (IS_ERR(pci_info->tzone)) {
ret = PTR_ERR(pci_info->tzone);
- goto err_ret_mmio;
+ goto err_del_legacy;
}

if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) {
@@ -312,11 +312,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
pci_free_irq_vectors(pdev);
err_ret_tzone:
thermal_zone_device_unregister(pci_info->tzone);
-err_ret_mmio:
- proc_thermal_mmio_remove(pdev, proc_priv);
-err_ret_thermal:
+err_del_legacy:
if (!pci_info->no_legacy)
proc_thermal_remove(proc_priv);
+ proc_thermal_mmio_remove(pdev, proc_priv);
pci_disable_device(pdev);

return ret;
--
2.41.0

2023-09-27 10:22:20

by srinivas pandruvada

[permalink] [raw]
Subject: [PATCH 5/5] selftests/thermel/intel: Add test to read power floor status

Some SoCs have firmware support to notify, if the system can't lower
power limit to a value requested from user space via RAPL constraints.

This test program waits for notification of power floor and prints. This
program can be used to test this feature and also allows other user space
programs to use as a reference.

Signed-off-by: Srinivas Pandruvada <[email protected]>
---
tools/testing/selftests/Makefile | 1 +
.../thermal/intel/power_floor/Makefile | 12 ++
.../intel/power_floor/power_floor_test.c | 108 ++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 tools/testing/selftests/thermal/intel/power_floor/Makefile
create mode 100644 tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 725ce59e4637..c99de76fb20d 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -85,6 +85,7 @@ TARGETS += syscall_user_dispatch
TARGETS += sysctl
TARGETS += tc-testing
TARGETS += tdx
+TARGETS += thermal/intel/power_floor
TARGETS += thermal/intel/workload_hint
TARGETS += timens
ifneq (1, $(quicktest))
diff --git a/tools/testing/selftests/thermal/intel/power_floor/Makefile b/tools/testing/selftests/thermal/intel/power_floor/Makefile
new file mode 100644
index 000000000000..9b88e57dbba5
--- /dev/null
+++ b/tools/testing/selftests/thermal/intel/power_floor/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+ifndef CROSS_COMPILE
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
+
+ifeq ($(ARCH),x86)
+TEST_GEN_PROGS := power_floor_test
+
+include ../../../lib.mk
+
+endif
+endif
diff --git a/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c b/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c
new file mode 100644
index 000000000000..0326b39a11b9
--- /dev/null
+++ b/tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+
+#define POWER_FLOOR_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_enable"
+#define POWER_FLOOR_STATUS_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_status"
+
+void power_floor_exit(int signum)
+{
+ int fd;
+
+ /* Disable feature via sysfs knob */
+
+ fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR);
+ if (fd < 0) {
+ perror("Unable to open power floor enable file\n");
+ exit(1);
+ }
+
+ if (write(fd, "0\n", 2) < 0) {
+ perror("Can' disable power floor notifications\n");
+ exit(1);
+ }
+
+ printf("Disabled power floor notifications\n");
+
+ close(fd);
+}
+
+int main(int argc, char **argv)
+{
+ struct pollfd ufd;
+ char status_str[3];
+ int fd, ret;
+
+ if (signal(SIGINT, power_floor_exit) == SIG_IGN)
+ signal(SIGINT, SIG_IGN);
+ if (signal(SIGHUP, power_floor_exit) == SIG_IGN)
+ signal(SIGHUP, SIG_IGN);
+ if (signal(SIGTERM, power_floor_exit) == SIG_IGN)
+ signal(SIGTERM, SIG_IGN);
+
+ /* Enable feature via sysfs knob */
+ fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR);
+ if (fd < 0) {
+ perror("Unable to open power floor enable file\n");
+ exit(1);
+ }
+
+ if (write(fd, "1\n", 2) < 0) {
+ perror("Can' enable power floor notifications\n");
+ exit(1);
+ }
+
+ close(fd);
+
+ printf("Enabled power floor notifications\n");
+
+ while (1) {
+ fd = open(POWER_FLOOR_STATUS_ATTRIBUTE, O_RDONLY);
+ if (fd < 0) {
+ perror("Unable to power floor status file\n");
+ exit(1);
+ }
+
+ if ((lseek(fd, 0L, SEEK_SET)) < 0) {
+ fprintf(stderr, "Failed to set pointer to beginning\n");
+ exit(1);
+ }
+
+ if (read(fd, status_str, sizeof(status_str)) < 0) {
+ fprintf(stderr, "Failed to read from:%s\n",
+ POWER_FLOOR_STATUS_ATTRIBUTE);
+ exit(1);
+ }
+
+ ufd.fd = fd;
+ ufd.events = POLLPRI;
+
+ ret = poll(&ufd, 1, -1);
+ if (ret < 0) {
+ perror("poll error");
+ exit(1);
+ } else if (ret == 0) {
+ printf("Poll Timeout\n");
+ } else {
+ if ((lseek(fd, 0L, SEEK_SET)) < 0) {
+ fprintf(stderr, "Failed to set pointer to beginning\n");
+ exit(1);
+ }
+
+ if (read(fd, status_str, sizeof(status_str)) < 0)
+ exit(0);
+
+ printf("power floor status: %s\n", status_str);
+ }
+
+ close(fd);
+ }
+}
--
2.41.0