Skip to content

Commit c7ff297

Browse files
spandruvadarafaeljw
authored andcommitted
thermal: int340x: Update OS policy capability handshake
Update the firmware with OS supported policies mask, so that firmware can relinquish its internal controls. Without this update several Tiger Lake laptops gets performance limited with in few seconds of executing in turbo region. The existing way of enumerating firmware policies via IDSP method and selecting policy by directly writing those policy UUIDS via _OSC method is not supported in newer generation of hardware. There is a new UUID "B23BA85D-C8B7-3542-88DE-8DE2FFCFD698" is defined for updating policy capabilities. As part of ACPI _OSC method: Arg0 - UUID: B23BA85D-C8B7-3542-88DE-8DE2FFCFD698 Arg1 - Rev ID: 1 Arg2 - Count: 2 Arg3 - Capability buffers: Array of Arg2 DWORDS DWORD1: As defined in the ACPI 5.0 Specification - Bit 0: Query Flag - Bits 1-3: Always 0 - Bits 4-31: Reserved DWORD2 and beyond: - Bit0: set to 1 to indicate Intel(R) Dynamic Tuning is active, 0 to indicate it is disabled and legacy thermal mechanism should be enabled. - Bit1: set to 1 to indicate Intel(R) Dynamic Tuning is controlling active cooling, 0 to indicate bios shall enable legacy thermal zone with active trip point. - Bit2: set to 1 to indicate Intel(R) Dynamic Tuning is controlling passive cooling, 0 to indicate bios shall enable legacy thermal zone with passive trip point. - Bit3: set to 1 to indicate Intel(R) Dynamic Tuning is handling critical trip point, 0 to indicate bios shall enable legacy thermal zone with critical trip point. - Bits 4:31: Reserved From sysfs interface, there is an existing interface to update policy UUID using attribute "current_uuid". User space can write the same UUID for ACTIVE, PASSIVE and CRITICAL policy. Driver converts these UUIDs to DWORD2 Bit 1 to Bit 3. When any of the policy is activated by user space it is assumed that dynamic tuning is active. For example $cd /sys/bus/platform/devices/INTC1040:00/uuids To support active policy $echo "3A95C389-E4B8-4629-A526-C52C88626BAE" > current_uuid To support passive policy $echo "42A441D6-AE6A-462b-A84B-4A8CE79027D3" > current_uuid To support critical policy $echo "97C68AE7-15FA-499c-B8C9-5DA81D606E0A" > current_uuid To check all the supported policies $cat current_uuid 3A95C389-E4B8-4629-A526-C52C88626BAE 42A441D6-AE6A-462b-A84B-4A8CE79027D3 97C68AE7-15FA-499c-B8C9-5DA81D606E0A To match the bit format for DWORD2, rearranged enum int3400_thermal_uuid and int3400_thermal_uuids[] by swapping current INT3400_THERMAL_ACTIVE and INT3400_THERMAL_PASSIVE_1. If the policies are enumerated via IDSP method then legacy method is used, if not the new method is used to update policy support. Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 668f69a commit c7ff297

File tree

1 file changed

+97
-49
lines changed

1 file changed

+97
-49
lines changed

drivers/thermal/intel/int340x_thermal/int3400_thermal.c

Lines changed: 97 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#define INT3400_KEEP_ALIVE 0xA0
1818

1919
enum int3400_thermal_uuid {
20+
INT3400_THERMAL_ACTIVE = 0,
2021
INT3400_THERMAL_PASSIVE_1,
21-
INT3400_THERMAL_ACTIVE,
2222
INT3400_THERMAL_CRITICAL,
2323
INT3400_THERMAL_ADAPTIVE_PERFORMANCE,
2424
INT3400_THERMAL_EMERGENCY_CALL_MODE,
@@ -31,8 +31,8 @@ enum int3400_thermal_uuid {
3131
};
3232

3333
static char *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = {
34-
"42A441D6-AE6A-462b-A84B-4A8CE79027D3",
3534
"3A95C389-E4B8-4629-A526-C52C88626BAE",
35+
"42A441D6-AE6A-462b-A84B-4A8CE79027D3",
3636
"97C68AE7-15FA-499c-B8C9-5DA81D606E0A",
3737
"63BE270F-1C11-48FD-A6F7-3AF253FF3E2D",
3838
"5349962F-71E6-431D-9AE8-0A635B710AEE",
@@ -59,6 +59,7 @@ struct int3400_thermal_priv {
5959
char *data_vault;
6060
int odvp_count;
6161
int *odvp;
62+
u32 os_uuid_mask;
6263
struct odvp_attr *odvp_attrs;
6364
};
6465

@@ -142,12 +143,55 @@ static ssize_t current_uuid_show(struct device *dev,
142143
struct device_attribute *devattr, char *buf)
143144
{
144145
struct int3400_thermal_priv *priv = dev_get_drvdata(dev);
146+
int i, length = 0;
147+
148+
if (priv->current_uuid_index > 0)
149+
return sprintf(buf, "%s\n",
150+
int3400_thermal_uuids[priv->current_uuid_index]);
151+
152+
for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) {
153+
if (priv->os_uuid_mask & BIT(i))
154+
length += scnprintf(&buf[length],
155+
PAGE_SIZE - length,
156+
"%s\n",
157+
int3400_thermal_uuids[i]);
158+
}
145159

146-
if (priv->current_uuid_index == -1)
147-
return sprintf(buf, "INVALID\n");
160+
if (length)
161+
return length;
148162

149-
return sprintf(buf, "%s\n",
150-
int3400_thermal_uuids[priv->current_uuid_index]);
163+
return sprintf(buf, "INVALID\n");
164+
}
165+
166+
static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enable)
167+
{
168+
u32 ret, buf[2];
169+
acpi_status status;
170+
int result = 0;
171+
struct acpi_osc_context context = {
172+
.uuid_str = NULL,
173+
.rev = 1,
174+
.cap.length = 8,
175+
};
176+
177+
context.uuid_str = uuid_str;
178+
179+
buf[OSC_QUERY_DWORD] = 0;
180+
buf[OSC_SUPPORT_DWORD] = *enable;
181+
182+
context.cap.pointer = buf;
183+
184+
status = acpi_run_osc(handle, &context);
185+
if (ACPI_SUCCESS(status)) {
186+
ret = *((u32 *)(context.ret.pointer + 4));
187+
if (ret != *enable)
188+
result = -EPERM;
189+
} else
190+
result = -EPERM;
191+
192+
kfree(context.ret.pointer);
193+
194+
return result;
151195
}
152196

153197
static ssize_t current_uuid_store(struct device *dev,
@@ -164,16 +208,47 @@ static ssize_t current_uuid_store(struct device *dev,
164208
* If we have a list of supported UUIDs, make sure
165209
* this one is supported.
166210
*/
167-
if (priv->uuid_bitmap &&
168-
!(priv->uuid_bitmap & (1 << i)))
211+
if (priv->uuid_bitmap & BIT(i)) {
212+
priv->current_uuid_index = i;
213+
return count;
214+
}
215+
216+
/*
217+
* There is support of only 3 policies via the new
218+
* _OSC to inform OS capability:
219+
* INT3400_THERMAL_ACTIVE
220+
* INT3400_THERMAL_PASSIVE_1
221+
* INT3400_THERMAL_CRITICAL
222+
*/
223+
224+
if (i > INT3400_THERMAL_CRITICAL)
169225
return -EINVAL;
170226

171-
priv->current_uuid_index = i;
172-
return count;
227+
priv->os_uuid_mask |= BIT(i);
228+
229+
break;
173230
}
174231
}
175232

176-
return -EINVAL;
233+
if (priv->os_uuid_mask) {
234+
int cap, ret;
235+
236+
/*
237+
* Capability bits:
238+
* Bit 0: set to 1 to indicate DPTF is active
239+
* Bi1 1: set to 1 to active cooling is supported by user space daemon
240+
* Bit 2: set to 1 to passive cooling is supported by user space daemon
241+
* Bit 3: set to 1 to critical trip is handled by user space daemon
242+
*/
243+
cap = ((priv->os_uuid_mask << 1) | 0x01);
244+
ret = int3400_thermal_run_osc(priv->adev->handle,
245+
"b23ba85d-c8b7-3542-88de-8de2ffcfd698",
246+
&cap);
247+
if (ret)
248+
return ret;
249+
}
250+
251+
return count;
177252
}
178253

179254
static DEVICE_ATTR_RW(current_uuid);
@@ -236,41 +311,6 @@ static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
236311
return result;
237312
}
238313

239-
static int int3400_thermal_run_osc(acpi_handle handle,
240-
enum int3400_thermal_uuid uuid, bool enable)
241-
{
242-
u32 ret, buf[2];
243-
acpi_status status;
244-
int result = 0;
245-
struct acpi_osc_context context = {
246-
.uuid_str = NULL,
247-
.rev = 1,
248-
.cap.length = 8,
249-
};
250-
251-
if (uuid < 0 || uuid >= INT3400_THERMAL_MAXIMUM_UUID)
252-
return -EINVAL;
253-
254-
context.uuid_str = int3400_thermal_uuids[uuid];
255-
256-
buf[OSC_QUERY_DWORD] = 0;
257-
buf[OSC_SUPPORT_DWORD] = enable;
258-
259-
context.cap.pointer = buf;
260-
261-
status = acpi_run_osc(handle, &context);
262-
if (ACPI_SUCCESS(status)) {
263-
ret = *((u32 *)(context.ret.pointer + 4));
264-
if (ret != enable)
265-
result = -EPERM;
266-
} else
267-
result = -EPERM;
268-
269-
kfree(context.ret.pointer);
270-
271-
return result;
272-
}
273-
274314
static ssize_t odvp_show(struct kobject *kobj, struct kobj_attribute *attr,
275315
char *buf)
276316
{
@@ -426,10 +466,18 @@ static int int3400_thermal_change_mode(struct thermal_zone_device *thermal,
426466
if (!priv)
427467
return -EINVAL;
428468

429-
if (mode != thermal->mode)
469+
if (mode != thermal->mode) {
470+
int enabled;
471+
472+
if (priv->current_uuid_index < 0 ||
473+
priv->current_uuid_index >= INT3400_THERMAL_MAXIMUM_UUID)
474+
return -EINVAL;
475+
476+
enabled = (mode == THERMAL_DEVICE_ENABLED);
430477
result = int3400_thermal_run_osc(priv->adev->handle,
431-
priv->current_uuid_index,
432-
mode == THERMAL_DEVICE_ENABLED);
478+
int3400_thermal_uuids[priv->current_uuid_index],
479+
&enabled);
480+
}
433481

434482

435483
evaluate_odvp(priv);

0 commit comments

Comments
 (0)