summaryrefslogtreecommitdiff
path: root/drivers/thermal/intel/int340x_thermal
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thermal/intel/int340x_thermal')
-rw-r--r--drivers/thermal/intel/int340x_thermal/Kconfig4
-rw-r--r--drivers/thermal/intel/int340x_thermal/Makefile1
-rw-r--r--drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c5
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3400_thermal.c34
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3401_thermal.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3402_thermal.c5
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3403_thermal.c15
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3406_thermal.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c29
-rw-r--r--drivers/thermal/intel/int340x_thermal/platform_temperature_control.c243
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.c25
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.h5
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c144
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c7
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c13
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c71
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c121
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c11
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c3
19 files changed, 571 insertions, 169 deletions
diff --git a/drivers/thermal/intel/int340x_thermal/Kconfig b/drivers/thermal/intel/int340x_thermal/Kconfig
index e76b13e44d03..4c699f0896b5 100644
--- a/drivers/thermal/intel/int340x_thermal/Kconfig
+++ b/drivers/thermal/intel/int340x_thermal/Kconfig
@@ -5,8 +5,8 @@
config INT340X_THERMAL
tristate "ACPI INT340X thermal drivers"
- depends on X86_64 && ACPI && PCI
- select THERMAL_GOV_USER_SPACE
+ depends on X86_64 && ACPI && PCI && NET
+ select THERMAL_NETLINK
select ACPI_THERMAL_REL
select ACPI_FAN
select ACPI_THERMAL_LIB
diff --git a/drivers/thermal/intel/int340x_thermal/Makefile b/drivers/thermal/intel/int340x_thermal/Makefile
index fe3f43924525..184318d1792b 100644
--- a/drivers/thermal/intel/int340x_thermal/Makefile
+++ b/drivers/thermal/intel/int340x_thermal/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci_legacy.o
obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci.o
obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o
obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o
+obj-$(CONFIG_INT340X_THERMAL) += platform_temperature_control.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
diff --git a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
index dc519a665c18..cb149bcdd7d5 100644
--- a/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
+++ b/drivers/thermal/intel/int340x_thermal/acpi_thermal_rel.c
@@ -309,7 +309,7 @@ static int acpi_parse_psvt(acpi_handle handle, int *psvt_count, struct psvt **ps
if (knob->type == ACPI_TYPE_STRING) {
memset(&psvt->limit, 0, sizeof(u64));
- strncpy(psvt->limit.string, psvt_ptr->limit.str_ptr, knob->string.length);
+ strscpy(psvt->limit.string, psvt_ptr->limit.str_ptr, ACPI_LIMIT_STR_MAX_LEN);
} else {
psvt->limit.integer = psvt_ptr->limit.integer;
}
@@ -468,7 +468,7 @@ static int fill_psvt(char __user *ubuf)
psvt_user[i].unlimit_coeff = psvts[i].unlimit_coeff;
psvt_user[i].control_knob_type = psvts[i].control_knob_type;
if (psvt_user[i].control_knob_type == ACPI_TYPE_STRING)
- strncpy(psvt_user[i].limit.string, psvts[i].limit.string,
+ strscpy(psvt_user[i].limit.string, psvts[i].limit.string,
ACPI_LIMIT_STR_MAX_LEN);
else
psvt_user[i].limit.integer = psvts[i].limit.integer;
@@ -564,7 +564,6 @@ static const struct file_operations acpi_thermal_rel_fops = {
.open = acpi_thermal_rel_open,
.release = acpi_thermal_rel_release,
.unlocked_ioctl = acpi_thermal_rel_ioctl,
- .llseek = no_llseek,
};
static struct miscdevice acpi_thermal_rel_misc_device = {
diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
index 427d370648d5..0e07693ecf59 100644
--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
@@ -73,19 +73,7 @@ struct odvp_attr {
struct device_attribute attr;
};
-static ssize_t data_vault_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf, loff_t off, size_t count)
-{
- memcpy(buf, attr->private + off, count);
- return count;
-}
-
-static BIN_ATTR_RO(data_vault, 0);
-
-static struct bin_attribute *data_attributes[] = {
- &bin_attr_data_vault,
- NULL,
-};
+static BIN_ATTR_SIMPLE_RO(data_vault);
static ssize_t imok_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -115,10 +103,6 @@ static const struct attribute_group imok_attribute_group = {
.attrs = imok_attr,
};
-static const struct attribute_group data_attribute_group = {
- .bin_attrs = data_attributes,
-};
-
static ssize_t available_uuids_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -144,7 +128,7 @@ static ssize_t current_uuid_show(struct device *dev,
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
int i, length = 0;
- if (priv->current_uuid_index > 0)
+ if (priv->current_uuid_index >= 0)
return sprintf(buf, "%s\n",
int3400_thermal_uuids[priv->current_uuid_index]);
@@ -537,7 +521,6 @@ static struct thermal_zone_device_ops int3400_thermal_ops = {
};
static struct thermal_zone_params int3400_thermal_params = {
- .governor_name = "user_space",
.no_hwmon = true,
};
@@ -578,7 +561,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)
if (!adev)
return -ENODEV;
- priv = kzalloc(sizeof(struct int3400_thermal_priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -631,8 +614,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)
}
if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
- result = sysfs_create_group(&pdev->dev.kobj,
- &data_attribute_group);
+ result = device_create_bin_file(&pdev->dev, &bin_attr_data_vault);
if (result)
goto free_uuid;
}
@@ -655,7 +637,7 @@ free_notify:
free_sysfs:
cleanup_odvp(priv);
if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
- sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
+ device_remove_bin_file(&pdev->dev, &bin_attr_data_vault);
kfree(priv->data_vault);
}
free_uuid:
@@ -690,7 +672,7 @@ static void int3400_thermal_remove(struct platform_device *pdev)
acpi_thermal_rel_misc_device_remove(priv->adev->handle);
if (!ZERO_OR_NULL_PTR(priv->data_vault))
- sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
+ device_remove_bin_file(&pdev->dev, &bin_attr_data_vault);
sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group);
thermal_zone_device_unregister(priv->thermal);
@@ -705,7 +687,9 @@ static const struct acpi_device_id int3400_thermal_match[] = {
{"INTC1040", 0},
{"INTC1041", 0},
{"INTC1042", 0},
+ {"INTC1068", 0},
{"INTC10A0", 0},
+ {"INTC10D4", 0},
{}
};
@@ -713,7 +697,7 @@ MODULE_DEVICE_TABLE(acpi, int3400_thermal_match);
static struct platform_driver int3400_thermal_driver = {
.probe = int3400_thermal_probe,
- .remove_new = int3400_thermal_remove,
+ .remove = int3400_thermal_remove,
.driver = {
.name = "int3400 thermal",
.acpi_match_table = ACPI_PTR(int3400_thermal_match),
diff --git a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c
index 193645a73861..96d6277a5a8c 100644
--- a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c
@@ -60,7 +60,7 @@ static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, int3401_thermal_suspend,
static struct platform_driver int3401_driver = {
.probe = int3401_add,
- .remove_new = int3401_remove,
+ .remove = int3401_remove,
.driver = {
.name = "int3401 thermal",
.acpi_match_table = int3401_device_ids,
diff --git a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c
index ab8bfb5a3946..57b90005888a 100644
--- a/drivers/thermal/intel/int340x_thermal/int3402_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3402_thermal.c
@@ -45,6 +45,9 @@ static int int3402_thermal_probe(struct platform_device *pdev)
struct int3402_thermal_data *d;
int ret;
+ if (!adev)
+ return -ENODEV;
+
if (!acpi_has_method(adev->handle, "_TMP"))
return -ENODEV;
@@ -89,7 +92,7 @@ MODULE_DEVICE_TABLE(acpi, int3402_thermal_match);
static struct platform_driver int3402_thermal_driver = {
.probe = int3402_thermal_probe,
- .remove_new = int3402_thermal_remove,
+ .remove = int3402_thermal_remove,
.driver = {
.name = "int3402 thermal",
.acpi_match_table = int3402_thermal_match,
diff --git a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c
index 9b33fd3a66da..5a925a8df7b3 100644
--- a/drivers/thermal/intel/int340x_thermal/int3403_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3403_thermal.c
@@ -25,17 +25,6 @@ struct int3403_sensor {
struct int34x_thermal_zone *int340x_zone;
};
-struct int3403_performance_state {
- u64 performance;
- u64 power;
- u64 latency;
- u64 linear;
- u64 control;
- u64 raw_performace;
- char *raw_unit;
- int reserved;
-};
-
struct int3403_cdev {
struct thermal_cooling_device *cdev;
unsigned long max_state;
@@ -284,14 +273,16 @@ static const struct acpi_device_id int3403_device_ids[] = {
{"INTC1043", 0},
{"INTC1046", 0},
{"INTC1062", 0},
+ {"INTC1069", 0},
{"INTC10A1", 0},
+ {"INTC10D5", 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, int3403_device_ids);
static struct platform_driver int3403_driver = {
.probe = int3403_add,
- .remove_new = int3403_remove,
+ .remove = int3403_remove,
.driver = {
.name = "int3403 thermal",
.acpi_match_table = int3403_device_ids,
diff --git a/drivers/thermal/intel/int340x_thermal/int3406_thermal.c b/drivers/thermal/intel/int340x_thermal/int3406_thermal.c
index 1c266493c1aa..e21fcbccf4ba 100644
--- a/drivers/thermal/intel/int340x_thermal/int3406_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3406_thermal.c
@@ -195,7 +195,7 @@ MODULE_DEVICE_TABLE(acpi, int3406_thermal_match);
static struct platform_driver int3406_thermal_driver = {
.probe = int3406_thermal_probe,
- .remove_new = int3406_thermal_remove,
+ .remove = int3406_thermal_remove,
.driver = {
.name = "int3406 thermal",
.acpi_match_table = int3406_thermal_match,
diff --git a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
index 400fde7cb3b1..3d9efe69d562 100644
--- a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
+++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
@@ -39,13 +39,14 @@ static int int340x_thermal_get_zone_temp(struct thermal_zone_device *zone,
}
static int int340x_thermal_set_trip_temp(struct thermal_zone_device *zone,
- int trip, int temp)
+ const struct thermal_trip *trip, int temp)
{
struct int34x_thermal_zone *d = thermal_zone_device_priv(zone);
- char name[] = {'P', 'A', 'T', '0' + trip, '\0'};
+ unsigned int trip_index = THERMAL_TRIP_PRIV_TO_INT(trip->priv);
+ char name[] = {'P', 'A', 'T', '0' + trip_index, '\0'};
acpi_status status;
- if (trip > 9)
+ if (trip_index > 9)
return -EINVAL;
status = acpi_execute_simple_method(d->adev->handle, name,
@@ -62,16 +63,6 @@ static void int340x_thermal_critical(struct thermal_zone_device *zone)
thermal_zone_device_type(zone));
}
-static inline void *int_to_trip_priv(int i)
-{
- return (void *)(long)i;
-}
-
-static inline int trip_priv_to_int(const struct thermal_trip *trip)
-{
- return (long)trip->priv;
-}
-
static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
struct thermal_trip *zone_trips,
int trip_cnt)
@@ -106,7 +97,7 @@ static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
break;
zone_trips[trip_cnt].type = THERMAL_TRIP_ACTIVE;
- zone_trips[trip_cnt].priv = int_to_trip_priv(i);
+ zone_trips[trip_cnt].priv = THERMAL_INT_TO_TRIP_PRIV(i);
trip_cnt++;
}
@@ -114,7 +105,6 @@ static int int340x_thermal_read_trips(struct acpi_device *zone_adev,
}
static struct thermal_zone_params int340x_thermal_params = {
- .governor_name = "user_space",
.no_hwmon = true,
};
@@ -143,8 +133,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
if (ACPI_SUCCESS(status))
int34x_zone->aux_trip_nr = trip_cnt;
- zone_trips = kzalloc(sizeof(*zone_trips) * (trip_cnt + INT340X_THERMAL_MAX_TRIP_COUNT),
- GFP_KERNEL);
+ zone_trips = kcalloc(trip_cnt + INT340X_THERMAL_MAX_TRIP_COUNT,
+ sizeof(*zone_trips), GFP_KERNEL);
if (!zone_trips) {
ret = -ENOMEM;
goto err_trips_alloc;
@@ -153,7 +143,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
for (i = 0; i < trip_cnt; i++) {
zone_trips[i].type = THERMAL_TRIP_PASSIVE;
zone_trips[i].temperature = THERMAL_TEMP_INVALID;
- zone_trips[i].flags |= THERMAL_TRIP_FLAG_RW_TEMP;
+ zone_trips[i].flags = THERMAL_TRIP_FLAG_RW_TEMP;
+ zone_trips[i].priv = THERMAL_INT_TO_TRIP_PRIV(i);
}
trip_cnt = int340x_thermal_read_trips(adev, zone_trips, trip_cnt);
@@ -224,7 +215,7 @@ static int int340x_update_one_trip(struct thermal_trip *trip, void *arg)
break;
case THERMAL_TRIP_ACTIVE:
err = thermal_acpi_active_trip_temp(zone_adev,
- trip_priv_to_int(trip),
+ THERMAL_TRIP_PRIV_TO_INT(trip->priv),
&temp);
break;
default:
diff --git a/drivers/thermal/intel/int340x_thermal/platform_temperature_control.c b/drivers/thermal/intel/int340x_thermal/platform_temperature_control.c
new file mode 100644
index 000000000000..2d6504514893
--- /dev/null
+++ b/drivers/thermal/intel/int340x_thermal/platform_temperature_control.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * processor thermal device platform temperature controls
+ * Copyright (c) 2025, Intel Corporation.
+ */
+
+/*
+ * Platform temperature controls hardware interface
+ *
+ * The hardware control interface is via MMIO offsets in the processor
+ * thermal device MMIO space. There are three instances of MMIO registers.
+ * All registers are 64 bit wide with RW access.
+ *
+ * Name: PLATFORM_TEMPERATURE_CONTROL
+ * Offsets: 0x5B20, 0x5B28, 0x5B30
+ *
+ * Bits Description
+ * 7:0 TARGET_TEMP : Target temperature limit to which the control
+ * mechanism is regulating. Units: 0.5C.
+ * 8:8 ENABLE: Read current enable status of the feature or enable
+ * feature.
+ * 11:9 GAIN: Sets the aggressiveness of control loop from 0 to 7
+ * 7 graceful, favors performance at the expense of temperature
+ * overshoots
+ * 0 aggressive, favors tight regulation over performance
+ * 12:12 TEMPERATURE_OVERRIDE_EN
+ * When set, hardware will use TEMPERATURE_OVERRIDE values instead
+ * of reading from corresponding sensor.
+ * 15:13 RESERVED
+ * 23:16 MIN_PERFORMANCE_LEVEL: Minimum Performance level below which the
+ * there will be no throttling. 0 - all levels of throttling allowed
+ * including survivability actions. 255 - no throttling allowed.
+ * 31:24 TEMPERATURE_OVERRIDE: Allows SW to override the input temperature.
+ * hardware will use this value instead of the sensor temperature.
+ * Units: 0.5C.
+ * 63:32 RESERVED
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include "processor_thermal_device.h"
+
+struct mmio_reg {
+ int bits;
+ u16 mask;
+ u16 shift;
+ u16 units;
+};
+
+#define MAX_ATTR_GROUP_NAME_LEN 32
+#define PTC_MAX_ATTRS 3
+
+struct ptc_data {
+ u32 offset;
+ struct attribute_group ptc_attr_group;
+ struct attribute *ptc_attrs[PTC_MAX_ATTRS];
+ struct device_attribute temperature_target_attr;
+ struct device_attribute enable_attr;
+ char group_name[MAX_ATTR_GROUP_NAME_LEN];
+};
+
+static const struct mmio_reg ptc_mmio_regs[] = {
+ { 8, 0xFF, 0, 500}, /* temperature_target, units 0.5C*/
+ { 1, 0x01, 8, 0}, /* enable */
+ { 3, 0x7, 9, 0}, /* gain */
+ { 8, 0xFF, 16, 0}, /* min_performance_level */
+ { 1, 0x1, 12, 0}, /* temperature_override_enable */
+ { 8, 0xFF, 24, 500}, /* temperature_override, units 0.5C */
+};
+
+#define PTC_MAX_INSTANCES 3
+
+/* Unique offset for each PTC instance */
+static u32 ptc_offsets[PTC_MAX_INSTANCES] = {0x5B20, 0x5B28, 0x5B30};
+
+/* These will represent sysfs attribute names */
+static const char * const ptc_strings[] = {
+ "temperature_target",
+ "enable",
+ NULL
+};
+
+/* Lock to protect concurrent read/write and read-modify-write */
+static DEFINE_MUTEX(ptc_lock);
+
+static ssize_t ptc_mmio_show(struct ptc_data *data, struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct proc_thermal_device *proc_priv;
+ const struct mmio_reg *mmio_regs;
+ int ret, units;
+ u64 reg_val;
+
+ proc_priv = pci_get_drvdata(pdev);
+ mmio_regs = ptc_mmio_regs;
+ ret = match_string(ptc_strings, -1, attr->attr.name);
+ if (ret < 0)
+ return ret;
+
+ units = mmio_regs[ret].units;
+
+ guard(mutex)(&ptc_lock);
+
+ reg_val = readq((void __iomem *) (proc_priv->mmio_base + data->offset));
+ ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;
+ if (units)
+ ret *= units;
+
+ return sysfs_emit(buf, "%d\n", ret);
+}
+
+#define PTC_SHOW(suffix)\
+static ssize_t suffix##_show(struct device *dev,\
+ struct device_attribute *attr,\
+ char *buf)\
+{\
+ struct ptc_data *data = container_of(attr, struct ptc_data, suffix##_attr);\
+ return ptc_mmio_show(data, dev, attr, buf);\
+}
+
+static void ptc_mmio_write(struct pci_dev *pdev, u32 offset, int index, u32 value)
+{
+ struct proc_thermal_device *proc_priv;
+ u64 mask, reg_val;
+
+ proc_priv = pci_get_drvdata(pdev);
+
+ mask = GENMASK_ULL(ptc_mmio_regs[index].shift + ptc_mmio_regs[index].bits - 1,
+ ptc_mmio_regs[index].shift);
+
+ guard(mutex)(&ptc_lock);
+
+ reg_val = readq((void __iomem *) (proc_priv->mmio_base + offset));
+ reg_val &= ~mask;
+ reg_val |= (value << ptc_mmio_regs[index].shift);
+ writeq(reg_val, (void __iomem *) (proc_priv->mmio_base + offset));
+}
+
+static int ptc_store(struct ptc_data *data, struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ unsigned int input;
+ int ret;
+
+ ret = kstrtouint(buf, 10, &input);
+ if (ret)
+ return ret;
+
+ ret = match_string(ptc_strings, -1, attr->attr.name);
+ if (ret < 0)
+ return ret;
+
+ if (ptc_mmio_regs[ret].units)
+ input /= ptc_mmio_regs[ret].units;
+
+ if (input > ptc_mmio_regs[ret].mask)
+ return -EINVAL;
+
+ ptc_mmio_write(pdev, data->offset, ret, input);
+
+ return count;
+}
+
+#define PTC_STORE(suffix)\
+static ssize_t suffix##_store(struct device *dev,\
+ struct device_attribute *attr,\
+ const char *buf, size_t count)\
+{\
+ struct ptc_data *data = container_of(attr, struct ptc_data, suffix##_attr);\
+ return ptc_store(data, dev, attr, buf, count);\
+}
+
+PTC_SHOW(temperature_target);
+PTC_STORE(temperature_target);
+PTC_SHOW(enable);
+PTC_STORE(enable);
+
+#define ptc_init_attribute(_name)\
+ do {\
+ sysfs_attr_init(&data->_name##_attr.attr);\
+ data->_name##_attr.show = _name##_show;\
+ data->_name##_attr.store = _name##_store;\
+ data->_name##_attr.attr.name = #_name;\
+ data->_name##_attr.attr.mode = 0644;\
+ } while (0)
+
+static int ptc_create_groups(struct pci_dev *pdev, int instance, struct ptc_data *data)
+{
+ int ret, index = 0;
+
+ ptc_init_attribute(temperature_target);
+ ptc_init_attribute(enable);
+
+ data->ptc_attrs[index++] = &data->temperature_target_attr.attr;
+ data->ptc_attrs[index++] = &data->enable_attr.attr;
+ data->ptc_attrs[index] = NULL;
+
+ snprintf(data->group_name, MAX_ATTR_GROUP_NAME_LEN,
+ "ptc_%d_control", instance);
+ data->ptc_attr_group.name = data->group_name;
+ data->ptc_attr_group.attrs = data->ptc_attrs;
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &data->ptc_attr_group);
+
+ return ret;
+}
+
+static struct ptc_data ptc_instance[PTC_MAX_INSTANCES];
+
+int proc_thermal_ptc_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
+{
+ if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_PTC) {
+ int i;
+
+ for (i = 0; i < PTC_MAX_INSTANCES; i++) {
+ ptc_instance[i].offset = ptc_offsets[i];
+ ptc_create_groups(pdev, i, &ptc_instance[i]);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(proc_thermal_ptc_add);
+
+void proc_thermal_ptc_remove(struct pci_dev *pdev)
+{
+ struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
+
+ if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_PTC) {
+ int i;
+
+ for (i = 0; i < PTC_MAX_INSTANCES; i++)
+ sysfs_remove_group(&pdev->dev.kobj, &ptc_instance[i].ptc_attr_group);
+ }
+}
+EXPORT_SYMBOL_GPL(proc_thermal_ptc_remove);
+
+MODULE_IMPORT_NS("INT340X_THERMAL");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Processor Thermal PTC Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
index d75fae7b7ed2..29fcece48cad 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/thermal.h>
+#include <asm/msr.h>
#include "int340x_thermal_zone.h"
#include "processor_thermal_device.h"
#include "../intel_soc_dts_iosf.h"
@@ -153,7 +154,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
u64 val;
int err;
- err = rdmsrl_safe(MSR_PLATFORM_INFO, &val);
+ err = rdmsrq_safe(MSR_PLATFORM_INFO, &val);
if (err)
return err;
@@ -399,13 +400,21 @@ int proc_thermal_mmio_add(struct pci_dev *pdev,
}
}
+ if (feature_mask & PROC_THERMAL_FEATURE_PTC) {
+ ret = proc_thermal_ptc_add(pdev, proc_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add PTC MMIO interface\n");
+ goto err_rem_rapl;
+ }
+ }
+
if (feature_mask & PROC_THERMAL_FEATURE_FIVR ||
feature_mask & PROC_THERMAL_FEATURE_DVFS ||
feature_mask & PROC_THERMAL_FEATURE_DLVR) {
ret = proc_thermal_rfim_add(pdev, proc_priv);
if (ret) {
dev_err(&pdev->dev, "failed to add RFIM interface\n");
- goto err_rem_rapl;
+ goto err_rem_ptc;
}
}
@@ -427,6 +436,8 @@ int proc_thermal_mmio_add(struct pci_dev *pdev,
err_rem_rfim:
proc_thermal_rfim_remove(pdev);
+err_rem_ptc:
+ proc_thermal_ptc_remove(pdev);
err_rem_rapl:
proc_thermal_rapl_remove();
@@ -439,8 +450,12 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_RAPL)
proc_thermal_rapl_remove();
+ if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_PTC)
+ proc_thermal_ptc_remove(pdev);
+
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR ||
- proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS)
+ proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS ||
+ proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR)
proc_thermal_rfim_remove(pdev);
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR)
@@ -453,8 +468,8 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
}
EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);
-MODULE_IMPORT_NS(INTEL_TCC);
-MODULE_IMPORT_NS(INT340X_THERMAL);
+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");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
index 674f3c85dfbc..9a6ca43b6fa2 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
@@ -30,6 +30,7 @@
#define PCI_DEVICE_ID_INTEL_RPL_THERMAL 0xA71D
#define PCI_DEVICE_ID_INTEL_SKL_THERMAL 0x1903
#define PCI_DEVICE_ID_INTEL_TGL_THERMAL 0x9A03
+#define PCI_DEVICE_ID_INTEL_PTL_THERMAL 0xB01D
struct power_config {
u32 index;
@@ -65,6 +66,8 @@ struct rapl_mmio_regs {
#define PROC_THERMAL_FEATURE_DLVR 0x10
#define PROC_THERMAL_FEATURE_WT_HINT 0x20
#define PROC_THERMAL_FEATURE_POWER_FLOOR 0x40
+#define PROC_THERMAL_FEATURE_MSI_SUPPORT 0x80
+#define PROC_THERMAL_FEATURE_PTC 0x100
#if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL)
int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
@@ -121,4 +124,6 @@ int proc_thermal_mmio_add(struct pci_dev *pdev,
struct proc_thermal_device *proc_priv,
kernel_ulong_t feature_mask);
void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
+int proc_thermal_ptc_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
+void proc_thermal_ptc_remove(struct pci_dev *pdev);
#endif
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 14e34eabc419..00160936070a 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
@@ -63,6 +63,18 @@ static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = {
{ PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 },
};
+/* List of supported MSI IDs (sources) */
+enum proc_thermal_msi_ids {
+ PKG_THERMAL,
+ DDR_THERMAL,
+ THERM_POWER_FLOOR,
+ WORKLOAD_CHANGE,
+ MSI_THERMAL_MAX
+};
+
+/* Stores IRQ associated with a MSI ID */
+static int proc_thermal_msi_map[MSI_THERMAL_MAX];
+
#define B0D4_THERMAL_NOTIFY_DELAY 1000
static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY;
@@ -146,22 +158,41 @@ static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid)
return IRQ_HANDLED;
}
+static int proc_thermal_match_msi_irq(int irq)
+{
+ int i;
+
+ if (!use_msi)
+ goto msi_fail;
+
+ for (i = 0; i < MSI_THERMAL_MAX; i++) {
+ if (proc_thermal_msi_map[i] == irq)
+ return i;
+ }
+
+msi_fail:
+ return -EOPNOTSUPP;
+}
+
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, msi_id;
u32 status;
proc_priv = pci_info->proc_priv;
+ msi_id = proc_thermal_match_msi_irq(irq);
+
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) {
- if (proc_thermal_check_wt_intr(pci_info->proc_priv))
+ if (msi_id == WORKLOAD_CHANGE || proc_thermal_check_wt_intr(pci_info->proc_priv))
ret = IRQ_WAKE_THREAD;
}
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) {
- if (proc_thermal_check_power_floor_intr(pci_info->proc_priv))
+ if (msi_id == THERM_POWER_FLOOR ||
+ proc_thermal_check_power_floor_intr(pci_info->proc_priv))
ret = IRQ_WAKE_THREAD;
}
@@ -171,10 +202,11 @@ static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
* interrupt before scheduling work function for thermal threshold.
*/
proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status);
- if (status) {
+ if (msi_id == PKG_THERMAL || status) {
/* 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);
@@ -193,7 +225,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
return 0;
}
-static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
+static int sys_set_trip_temp(struct thermal_zone_device *tzd,
+ const struct thermal_trip *trip, int temp)
{
struct proc_thermal_pci *pci_info = thermal_zone_device_priv(tzd);
int tjmax, _temp;
@@ -239,10 +272,60 @@ static const struct thermal_zone_device_ops tzone_ops = {
};
static struct thermal_zone_params tzone_params = {
- .governor_name = "user_space",
.no_hwmon = true,
};
+static bool msi_irq;
+
+static void proc_thermal_free_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info)
+{
+ int i;
+
+ for (i = 0; i < MSI_THERMAL_MAX; i++) {
+ if (proc_thermal_msi_map[i])
+ devm_free_irq(&pdev->dev, proc_thermal_msi_map[i], pci_info);
+ }
+
+ pci_free_irq_vectors(pdev);
+}
+
+static int proc_thermal_setup_msi(struct pci_dev *pdev, struct proc_thermal_pci *pci_info)
+{
+ int ret, i, irq, count;
+
+ count = pci_alloc_irq_vectors(pdev, 1, MSI_THERMAL_MAX, PCI_IRQ_MSI | PCI_IRQ_MSIX);
+ if (count < 0) {
+ dev_err(&pdev->dev, "Failed to allocate vectors!\n");
+ return count;
+ }
+
+ dev_info(&pdev->dev, "msi enabled:%d msix enabled:%d\n", pdev->msi_enabled,
+ pdev->msix_enabled);
+
+ for (i = 0; i < count; i++) {
+ irq = pci_irq_vector(pdev, i);
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler,
+ proc_thermal_irq_thread_handler,
+ 0, KBUILD_MODNAME, pci_info);
+ if (ret) {
+ dev_err(&pdev->dev, "Request IRQ %d failed\n", irq);
+ goto err_free_msi_vectors;
+ }
+
+ proc_thermal_msi_map[i] = irq;
+ }
+
+ msi_irq = true;
+
+ return 0;
+
+err_free_msi_vectors:
+ proc_thermal_free_msi(pdev, pci_info);
+
+ return ret;
+}
+
static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct proc_thermal_device *proc_priv;
@@ -252,7 +335,6 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
.flags = THERMAL_TRIP_FLAG_RW_TEMP,
};
int irq_flag = 0, irq, ret;
- bool msi_irq = false;
proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
if (!proc_priv)
@@ -298,27 +380,24 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
goto err_del_legacy;
}
- if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) {
- /* request and enable interrupt */
- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to allocate vectors!\n");
- goto err_ret_tzone;
- }
+ if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MSI_SUPPORT)
+ use_msi = true;
- irq = pci_irq_vector(pdev, 0);
- msi_irq = true;
+ if (use_msi) {
+ ret = proc_thermal_setup_msi(pdev, pci_info);
+ if (ret)
+ goto err_ret_tzone;
} else {
irq_flag = IRQF_SHARED;
irq = pdev->irq;
- }
- ret = devm_request_threaded_irq(&pdev->dev, irq,
- proc_thermal_irq_handler, proc_thermal_irq_thread_handler,
- irq_flag, KBUILD_MODNAME, pci_info);
- if (ret) {
- dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq);
- goto err_free_vectors;
+ ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler,
+ proc_thermal_irq_thread_handler, irq_flag,
+ KBUILD_MODNAME, pci_info);
+ if (ret) {
+ dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq);
+ goto err_ret_tzone;
+ }
}
ret = thermal_zone_device_enable(pci_info->tzone);
@@ -329,14 +408,13 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
err_free_vectors:
if (msi_irq)
- pci_free_irq_vectors(pdev);
+ proc_thermal_free_msi(pdev, pci_info);
err_ret_tzone:
thermal_zone_device_unregister(pci_info->tzone);
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;
}
@@ -351,14 +429,13 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
- devm_free_irq(&pdev->dev, pdev->irq, pci_info);
- pci_free_irq_vectors(pdev);
+ if (msi_irq)
+ proc_thermal_free_msi(pdev, pci_info);
thermal_zone_device_unregister(pci_info->tzone);
proc_thermal_mmio_remove(pdev, pci_info->proc_priv);
if (!pci_info->no_legacy)
proc_thermal_remove(proc_priv);
- pci_disable_device(pdev);
}
#ifdef CONFIG_PM_SLEEP
@@ -407,7 +484,10 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
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, LNLM_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
+ { PCI_DEVICE_DATA(INTEL, LNLM_THERMAL, PROC_THERMAL_FEATURE_MSI_SUPPORT |
+ PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS |
+ PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR |
+ PROC_THERMAL_FEATURE_PTC) },
{ 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_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) },
@@ -415,6 +495,10 @@ static const struct pci_device_id proc_thermal_pci_ids[] = {
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) },
+ { PCI_DEVICE_DATA(INTEL, PTL_THERMAL, PROC_THERMAL_FEATURE_RAPL |
+ PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_DVFS |
+ PROC_THERMAL_FEATURE_MSI_SUPPORT | PROC_THERMAL_FEATURE_WT_HINT |
+ PROC_THERMAL_FEATURE_POWER_FLOOR | PROC_THERMAL_FEATURE_PTC) },
{ },
};
@@ -430,7 +514,7 @@ static struct pci_driver proc_thermal_pci_driver = {
module_pci_driver(proc_thermal_pci_driver);
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
index 4d3bd32ff9ea..b1d531ef440f 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
@@ -94,7 +94,7 @@ int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp
return ret;
}
-EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, "INT340X_THERMAL");
int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data)
{
@@ -106,7 +106,7 @@ int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data
return ret;
}
-EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, "INT340X_THERMAL");
#define MBOX_CAMARILLO_RD_INTR_CONFIG 0x1E
#define MBOX_CAMARILLO_WR_INTR_CONFIG 0x1F
@@ -153,6 +153,7 @@ unlock:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, "INT340X_THERMAL");
MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Processor Thermal Mail Box Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
index a1a108407f0f..25cdbb6d91a6 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
@@ -42,7 +42,7 @@ int proc_thermal_read_power_floor_status(struct proc_thermal_device *proc_priv)
status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
return (status & SOC_POWER_FLOOR_STATUS) >> SOC_POWER_FLOOR_SHIFT;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_read_power_floor_status, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_read_power_floor_status, "INT340X_THERMAL");
static bool enable_state;
static DEFINE_MUTEX(pf_lock);
@@ -69,13 +69,13 @@ pf_unlock:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_set_state, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_set_state, "INT340X_THERMAL");
bool proc_thermal_power_floor_get_state(struct proc_thermal_device *proc_priv)
{
return enable_state;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_get_state, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_get_state, "INT340X_THERMAL");
/**
* proc_thermal_check_power_floor_intr() - Check power floor interrupt.
@@ -94,7 +94,7 @@ bool proc_thermal_check_power_floor_intr(struct proc_thermal_device *proc_priv)
int_status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
return !!(int_status & SOC_POWER_FLOOR_INT_ACTIVE);
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_check_power_floor_intr, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_check_power_floor_intr, "INT340X_THERMAL");
/**
* proc_thermal_power_floor_intr_callback() - Process power floor notification
@@ -120,7 +120,8 @@ void proc_thermal_power_floor_intr_callback(struct pci_dev *pdev,
sysfs_notify(&pdev->dev.kobj, "power_limits", "power_floor_status");
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_intr_callback, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_intr_callback, "INT340X_THERMAL");
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Processor Thermal power floor notification Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
index e964a9375722..bde2cc386afd 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
@@ -13,48 +13,12 @@ static struct rapl_if_priv rapl_mmio_priv;
static const struct rapl_mmio_regs rapl_mmio_default = {
.reg_unit = 0x5938,
- .regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930},
+ .regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930, 0x59b0},
.regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
- .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2),
+ .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2) | BIT(POWER_LIMIT4),
.limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2),
};
-static int rapl_mmio_cpu_online(unsigned int cpu)
-{
- struct rapl_package *rp;
-
- /* mmio rapl supports package 0 only for now */
- if (topology_physical_package_id(cpu))
- return 0;
-
- rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
- if (!rp) {
- rp = rapl_add_package_cpuslocked(cpu, &rapl_mmio_priv, true);
- if (IS_ERR(rp))
- return PTR_ERR(rp);
- }
- cpumask_set_cpu(cpu, &rp->cpumask);
- return 0;
-}
-
-static int rapl_mmio_cpu_down_prep(unsigned int cpu)
-{
- struct rapl_package *rp;
- int lead_cpu;
-
- rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
- if (!rp)
- return 0;
-
- cpumask_clear_cpu(cpu, &rp->cpumask);
- lead_cpu = cpumask_first(&rp->cpumask);
- if (lead_cpu >= nr_cpu_ids)
- rapl_remove_package_cpuslocked(rp);
- else if (rp->lead_cpu == cpu)
- rp->lead_cpu = lead_cpu;
- return 0;
-}
-
static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
{
if (!ra->reg.mmio)
@@ -82,6 +46,7 @@ static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
{
const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default;
+ struct rapl_package *rp;
enum rapl_domain_reg_id reg;
enum rapl_domain_type domain;
int ret;
@@ -109,27 +74,41 @@ int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc
return PTR_ERR(rapl_mmio_priv.control_type);
}
- ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online",
- rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
- if (ret < 0) {
- powercap_unregister_control_type(rapl_mmio_priv.control_type);
- rapl_mmio_priv.control_type = NULL;
- return ret;
+ /* Register a RAPL package device for package 0 which is always online */
+ rp = rapl_find_package_domain(0, &rapl_mmio_priv, false);
+ if (rp) {
+ ret = -EEXIST;
+ goto err;
+ }
+
+ rp = rapl_add_package(0, &rapl_mmio_priv, false);
+ if (IS_ERR(rp)) {
+ ret = PTR_ERR(rp);
+ goto err;
}
- rapl_mmio_priv.pcap_rapl_online = ret;
return 0;
+
+err:
+ powercap_unregister_control_type(rapl_mmio_priv.control_type);
+ rapl_mmio_priv.control_type = NULL;
+ return ret;
}
EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);
void proc_thermal_rapl_remove(void)
{
+ struct rapl_package *rp;
+
if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
return;
- cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
+ rp = rapl_find_package_domain(0, &rapl_mmio_priv, false);
+ if (rp)
+ rapl_remove_package(rp);
powercap_unregister_control_type(rapl_mmio_priv.control_type);
}
EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);
MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("RAPL interface using MMIO");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
index 546b70434004..3a028b78d9af 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
@@ -9,7 +9,7 @@
#include <linux/pci.h>
#include "processor_thermal_device.h"
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
struct mmio_reg {
int read_only;
@@ -19,6 +19,12 @@ struct mmio_reg {
u16 shift;
};
+struct mapping_table {
+ const char *attr_name;
+ const u32 value;
+ const char *mapped_str;
+};
+
/* These will represent sysfs attribute names */
static const char * const fivr_strings[] = {
"vco_ref_code_lo",
@@ -62,6 +68,78 @@ static const struct mmio_reg dlvr_mmio_regs[] = {
{ 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */
};
+static const struct mmio_reg lnl_dlvr_mmio_regs[] = {
+ { 0, 0x5A08, 5, 0x1F, 0}, /* dlvr_spread_spectrum_pct */
+ { 0, 0x5A08, 1, 0x1, 5}, /* dlvr_control_mode */
+ { 0, 0x5A08, 1, 0x1, 6}, /* dlvr_control_lock */
+ { 0, 0x5A08, 1, 0x1, 7}, /* dlvr_rfim_enable */
+ { 0, 0x5A08, 2, 0x3, 8}, /* dlvr_freq_select */
+ { 1, 0x5A10, 2, 0x3, 30}, /* dlvr_hardware_rev */
+ { 1, 0x5A10, 2, 0x3, 0}, /* dlvr_freq_mhz */
+ { 1, 0x5A10, 1, 0x1, 23}, /* dlvr_pll_busy */
+};
+
+static const struct mapping_table lnl_dlvr_mapping[] = {
+ {"dlvr_freq_select", 0, "2227.2"},
+ {"dlvr_freq_select", 1, "2140"},
+ {"dlvr_freq_mhz", 0, "2227.2"},
+ {"dlvr_freq_mhz", 1, "2140"},
+ {NULL, 0, NULL},
+};
+
+static int match_mapping_table(const struct mapping_table *table, const char *attr_name,
+ bool match_int_value, const u32 value, const char *value_str,
+ char **result_str, u32 *result_int)
+{
+ bool attr_matched = false;
+ int i = 0;
+
+ if (!table)
+ return -EOPNOTSUPP;
+
+ while (table[i].attr_name) {
+ if (strncmp(table[i].attr_name, attr_name, strlen(attr_name)))
+ goto match_next;
+
+ attr_matched = true;
+
+ if (match_int_value) {
+ if (table[i].value != value)
+ goto match_next;
+
+ *result_str = (char *)table[i].mapped_str;
+ return 0;
+ }
+
+ if (strncmp(table[i].mapped_str, value_str, strlen(table[i].mapped_str)))
+ goto match_next;
+
+ *result_int = table[i].value;
+
+ return 0;
+match_next:
+ i++;
+ }
+
+ /* If attribute name is matched, then the user space value is invalid */
+ if (attr_matched)
+ return -EINVAL;
+
+ return -EOPNOTSUPP;
+}
+
+static int get_mapped_string(const struct mapping_table *table, const char *attr_name,
+ u32 value, char **result)
+{
+ return match_mapping_table(table, attr_name, true, value, NULL, result, NULL);
+}
+
+static int get_mapped_value(const struct mapping_table *table, const char *attr_name,
+ const char *value, unsigned int *result)
+{
+ return match_mapping_table(table, attr_name, false, 0, value, NULL, result);
+}
+
/* These will represent sysfs attribute names */
static const char * const dvfs_strings[] = {
"rfi_restriction_run_busy",
@@ -88,17 +166,22 @@ static const struct mmio_reg adl_dvfs_mmio_regs[] = {
{ 0, 0x5A40, 1, 0x1, 0}, /* rfi_disable */
};
+static const struct mapping_table *dlvr_mapping;
+static const struct mmio_reg *dlvr_mmio_regs_table;
+
#define RFIM_SHOW(suffix, table)\
static ssize_t suffix##_show(struct device *dev,\
struct device_attribute *attr,\
char *buf)\
{\
+ const struct mmio_reg *mmio_regs = dlvr_mmio_regs_table;\
+ const struct mapping_table *mapping = dlvr_mapping;\
struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\
- const struct mmio_reg *mmio_regs;\
const char **match_strs;\
+ int ret, err;\
u32 reg_val;\
- int ret;\
+ char *str;\
\
proc_priv = pci_get_drvdata(pdev);\
if (table == 1) {\
@@ -106,7 +189,6 @@ static ssize_t suffix##_show(struct device *dev,\
mmio_regs = adl_dvfs_mmio_regs;\
} else if (table == 2) { \
match_strs = (const char **)dlvr_strings;\
- mmio_regs = dlvr_mmio_regs;\
} else {\
match_strs = (const char **)fivr_strings;\
mmio_regs = tgl_fivr_mmio_regs;\
@@ -116,7 +198,12 @@ static ssize_t suffix##_show(struct device *dev,\
return ret;\
reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\
- return sprintf(buf, "%u\n", ret);\
+ err = get_mapped_string(mapping, attr->attr.name, ret, &str);\
+ if (!err)\
+ return sprintf(buf, "%s\n", str);\
+ if (err == -EOPNOTSUPP)\
+ return sprintf(buf, "%u\n", ret);\
+ return err;\
}
#define RFIM_STORE(suffix, table)\
@@ -124,11 +211,12 @@ static ssize_t suffix##_store(struct device *dev,\
struct device_attribute *attr,\
const char *buf, size_t count)\
{\
+ const struct mmio_reg *mmio_regs = dlvr_mmio_regs_table;\
+ const struct mapping_table *mapping = dlvr_mapping;\
struct proc_thermal_device *proc_priv;\
struct pci_dev *pdev = to_pci_dev(dev);\
unsigned int input;\
const char **match_strs;\
- const struct mmio_reg *mmio_regs;\
int ret, err;\
u32 reg_val;\
u32 mask;\
@@ -139,7 +227,6 @@ static ssize_t suffix##_store(struct device *dev,\
mmio_regs = adl_dvfs_mmio_regs;\
} else if (table == 2) { \
match_strs = (const char **)dlvr_strings;\
- mmio_regs = dlvr_mmio_regs;\
} else {\
match_strs = (const char **)fivr_strings;\
mmio_regs = tgl_fivr_mmio_regs;\
@@ -150,9 +237,14 @@ static ssize_t suffix##_store(struct device *dev,\
return ret;\
if (mmio_regs[ret].read_only)\
return -EPERM;\
- err = kstrtouint(buf, 10, &input);\
- if (err)\
+ err = get_mapped_value(mapping, attr->attr.name, buf, &input);\
+ if (err == -EINVAL)\
return err;\
+ if (err == -EOPNOTSUPP) {\
+ err = kstrtouint(buf, 10, &input);\
+ if (err)\
+ return err;\
+ } \
mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\
reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
reg_val &= ~mask;\
@@ -347,6 +439,16 @@ int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc
}
if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) {
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_LNLM_THERMAL:
+ case PCI_DEVICE_ID_INTEL_PTL_THERMAL:
+ dlvr_mmio_regs_table = lnl_dlvr_mmio_regs;
+ dlvr_mapping = lnl_dlvr_mapping;
+ break;
+ default:
+ dlvr_mmio_regs_table = dlvr_mmio_regs;
+ break;
+ }
ret = sysfs_create_group(&pdev->dev.kobj, &dlvr_attribute_group);
if (ret)
return ret;
@@ -384,3 +486,4 @@ void proc_thermal_rfim_remove(struct pci_dev *pdev)
EXPORT_SYMBOL_GPL(proc_thermal_rfim_remove);
MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Processor Thermal RFIM Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
index 9d5e4c169d1b..68e8391af8f4 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
@@ -204,7 +204,7 @@ bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv)
return false;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_check_wt_intr, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_check_wt_intr, "INT340X_THERMAL");
/* Callback to notify user space */
void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
@@ -217,7 +217,7 @@ void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_dev
sysfs_notify(&pdev->dev.kobj, "workload_hint", "workload_type_index");
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, "INT340X_THERMAL");
static bool workload_hint_created;
@@ -233,7 +233,7 @@ int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *p
return 0;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_add, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_add, "INT340X_THERMAL");
void proc_thermal_wt_hint_remove(struct pci_dev *pdev)
{
@@ -249,7 +249,8 @@ void proc_thermal_wt_hint_remove(struct pci_dev *pdev)
workload_hint_created = false;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_remove, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_remove, "INT340X_THERMAL");
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Processor Thermal Work Load type hint Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
index 711c4f761c9a..b95810f4a011 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
@@ -132,5 +132,6 @@ void proc_thermal_wt_req_remove(struct pci_dev *pdev)
}
EXPORT_SYMBOL_GPL(proc_thermal_wt_req_remove);
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Processor Thermal Work Load type request Interface");