Commit 4b029a81 authored by Srinivas Pandruvada's avatar Srinivas Pandruvada Committed by Rafael J. Wysocki
Browse files

thermal: int340x: processor_thermal: Add workload type hint interface



Prior to Meteor Lake processor generation, user space can pass workload
type request to the firmware. Then firmware can optimize power based on
the indicated workload type. User space also uses workload type requests
to implement its own heuristics.

The firmware in Meteor Lake processor generation is capable of predicting
workload type without software help.

To avoid duplicate processing, add a sysfs interface allowing user space
to obtain the workload hint from the firmware instead of trying to
predict the workload type by itself.

This workload hint is passed from the firmware via MMIO offset 0x5B18 of
the processor thermal PCI device. Before workload hints can be produced by
the firmware, it needs to be configured via a mailbox command.  This
mailbox command turns ON the workload hint and it allows to program a
notification delay to control the rate of notifications.

The notification delay can be changed from user space vis sysfs.

Attribute group 'workload_hint' in sysfs is used for implementing the
workload hints interface between user space and the kernel.

It contains the following attributes:

workload_type_enable:
	Enables/disables workload type hints from the firmware.

notification_delay_ms:
	Notification delay in milliseconds.

workload_type_index:
	The current workload type index predicted by the firmware (see
	the documentation changes below for supported index values and
	their meaning).

Signed-off-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
[ rjw: Changelog edits, documentation edits, whitespace adjustments ]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 2f0b31c0
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -315,3 +315,57 @@ DPTF Fan Control
----------------------------------------

Refer to Documentation/admin-guide/acpi/fan_performance_states.rst

Workload Type Hints
----------------------------------------

The firmware in Meteor Lake processor generation is capable of identifying
workload type and passing hints regarding it to the OS. A special sysfs
interface is provided to allow user space to obtain workload type hints from
the firmware and control the rate at which they are provided.

User space can poll attribute "workload_type_index" for the current hint or
can receive a notification whenever the value of this attribute is updated.

file:`/sys/bus/pci/devices/0000:00:04.0/workload_hint/`
Segment 0, bus 0, device 4, function 0 is reserved for the processor thermal
device on all Intel client processors. So, the above path doesn't change
based on the processor generation.

``workload_hint_enable`` (RW)
	Enable firmware to send workload type hints to user space.

``notification_delay_ms`` (RW)
	Minimum delay in milliseconds before firmware will notify OS. This is
	for the rate control of notifications. This delay is between changing
	the workload type prediction in the firmware and notifying the OS about
	the change. The default delay is 1024 ms. The delay of 0 is invalid.
	The delay is rounded up to the nearest power of 2 to simplify firmware
	programming of the delay value. The read of notification_delay_ms
	attribute shows the effective value used.

``workload_type_index`` (RO)
	Predicted workload type index. User space can get notification of
	change via existing sysfs attribute change notification mechanism.

	The supported index values and their meaning for the Meteor Lake
	processor generation are as follows:

	0 -  Idle: System performs no tasks, power and idle residency are
		consistently low for long periods of time.

	1 – Battery Life: Power is relatively low, but the processor may
		still be actively performing a task, such as video playback for
		a long period of time.

	2 – Sustained: Power level that is relatively high for a long period
		of time, with very few to no periods of idleness, which will
		eventually exhaust RAPL Power Limit 1 and 2.

	3 – Bursty: Consumes a relatively constant average amount of power, but
		periods of relative idleness are interrupted by bursts of
		activity. The bursts are relatively short and the periods of
		relative idleness between them typically prevent RAPL Power
		Limit 1 from being exhausted.

	4 – Unknown: Can't classify.
+1 −0
Original line number Diff line number Diff line
@@ -11,5 +11,6 @@ obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o
obj-$(CONFIG_INT340X_THERMAL)	+= processor_thermal_rfim.o
obj-$(CONFIG_INT340X_THERMAL)	+= processor_thermal_mbox.o
obj-$(CONFIG_INT340X_THERMAL)	+= processor_thermal_wt_req.o
obj-$(CONFIG_INT340X_THERMAL)	+= processor_thermal_wt_hint.o
obj-$(CONFIG_INT3406_THERMAL)	+= int3406_thermal.o
obj-$(CONFIG_ACPI_THERMAL_REL)	+= acpi_thermal_rel.o
+9 −0
Original line number Diff line number Diff line
@@ -352,6 +352,12 @@ int proc_thermal_mmio_add(struct pci_dev *pdev,
			dev_err(&pdev->dev, "failed to add MBOX interface\n");
			goto err_rem_rfim;
		}
	} else if (feature_mask & PROC_THERMAL_FEATURE_WT_HINT) {
		ret = proc_thermal_wt_hint_add(pdev, proc_priv);
		if (ret) {
			dev_err(&pdev->dev, "failed to add WT Hint\n");
			goto err_rem_rfim;
		}
	}

	return 0;
@@ -376,10 +382,13 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *

	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ)
		proc_thermal_wt_req_remove(pdev);
	else if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT)
		proc_thermal_wt_hint_remove(pdev);
}
EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);

MODULE_IMPORT_NS(INTEL_TCC);
MODULE_IMPORT_NS(INT340X_THERMAL);
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
MODULE_LICENSE("GPL v2");
+7 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct rapl_mmio_regs {
#define PROC_THERMAL_FEATURE_DVFS	0x04
#define PROC_THERMAL_FEATURE_WT_REQ	0x08
#define PROC_THERMAL_FEATURE_DLVR	0x10
#define PROC_THERMAL_FEATURE_WT_HINT	0x20

#if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL)
int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
@@ -95,6 +96,12 @@ int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, i
					    int time_window);
int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv);
void proc_thermal_remove(struct proc_thermal_device *proc_priv);

int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
void proc_thermal_wt_hint_remove(struct pci_dev *pdev);
void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv);

int proc_thermal_suspend(struct device *dev);
int proc_thermal_resume(struct device *dev);
int proc_thermal_mmio_add(struct pci_dev *pdev,
+2 −1
Original line number Diff line number Diff line
@@ -365,7 +365,8 @@ static const struct pci_device_id proc_thermal_pci_ids[] = {
	{ PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL |
	  PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) },
	{ PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL |
	  PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR) },
	  PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR |
	  PROC_THERMAL_FEATURE_WT_HINT) },
	{ PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL |
	  PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) },
	{ },
Loading