Skip to content

Commit b1d03b7

Browse files
committed
Merge branches 'acpi-cppc', 'acpi-pcc', 'acpi-apei' and 'acpi-osi'
Merge new material related to CPPC, PCC, APEI and OSI strings handling for 6.1-rc1: - Disable frequency invariance in the CPPC library if registers used by cppc_get_perf_ctrs() are accessed via PCC (Jeremy Linton). - Add ACPI disabled check to acpi_cpc_valid() (Perry Yuan). - Fix Tx acknowledge in the PCC address space handler (Huisong Li). - Use wait_for_completion_timeout() for PCC mailbox operations (Huisong Li). - Release resources on PCC address space setup failure path (Rafael Mendonca). - Remove unneeded result variables from APEI code (ye xingchen). - Print total number of records found during BERT log parsing (Dmitry Monakhov). - Drop support for 3 _OSI strings that should not be necessary any more and update documentation on custom _OSI strings so that adding new ones is not encouraged any more (Mario Limonciello). * acpi-cppc: ACPI: CPPC: Disable FIE if registers in PCC regions ACPI: CPPC: Add ACPI disabled check to acpi_cpc_valid() * acpi-pcc: ACPI: PCC: Fix Tx acknowledge in the PCC address space handler ACPI: PCC: replace wait_for_completion() ACPI: PCC: Release resources on address space setup failure path * acpi-apei: ACPI: APEI: Remove unneeded result variables ACPI: APEI: Add BERT error log footer * acpi-osi: ACPI: OSI: Update Documentation on custom _OSI strings ACPI: OSI: Remove Linux-HPI-Hybrid-Graphics _OSI string ACPI: OSI: Remove Linux-Lenovo-NV-HDMI-Audio _OSI string ACPI: OSI: Remove Linux-Dell-Video _OSI string
5 parents e996c7e + ae2df91 + 1872910 + 382c5fe + 2f190ac commit b1d03b7

File tree

11 files changed

+115
-57
lines changed

11 files changed

+115
-57
lines changed

Documentation/firmware-guide/acpi/osi.rst

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,23 @@ But it is likely that they will all eventually be added.
4141
What should an OEM do if they want to support Linux and Windows
4242
using the same BIOS image? Often they need to do something different
4343
for Linux to deal with how Linux is different from Windows.
44-
Here the BIOS should ask exactly what it wants to know:
4544

45+
In this case, the OEM should create custom ASL to be executed by the
46+
Linux kernel and changes to Linux kernel drivers to execute this custom
47+
ASL. The easiest way to accomplish this is to introduce a device specific
48+
method (_DSM) that is called from the Linux kernel.
49+
50+
In the past the kernel used to support something like:
4651
_OSI("Linux-OEM-my_interface_name")
4752
where 'OEM' is needed if this is an OEM-specific hook,
4853
and 'my_interface_name' describes the hook, which could be a
4954
quirk, a bug, or a bug-fix.
5055

51-
In addition, the OEM should send a patch to upstream Linux
52-
via the [email protected] mailing list. When that patch
53-
is checked into Linux, the OS will answer "YES" when the BIOS
54-
on the OEM's system uses _OSI to ask if the interface is supported
55-
by the OS. Linux distributors can back-port that patch for Linux
56-
pre-installs, and it will be included by all distributions that
57-
re-base to upstream. If the distribution can not update the kernel binary,
58-
they can also add an acpi_osi=Linux-OEM-my_interface_name
59-
cmdline parameter to the boot loader, as needed.
60-
61-
If the string refers to a feature where the upstream kernel
62-
eventually grows support, a patch should be sent to remove
63-
the string when that support is added to the kernel.
56+
However this was discovered to be abused by other BIOS vendors to change
57+
completely unrelated code on completely unrelated systems. This prompted
58+
an evaluation of all of it's uses. This uncovered that they aren't needed
59+
for any of the original reasons. As such, the kernel will not respond to
60+
any custom Linux-* strings by default.
6461

6562
That was easy. Read on, to find out how to do it wrong.
6663

drivers/acpi/acpi_pcc.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323

2424
#include <acpi/pcc.h>
2525

26+
/*
27+
* Arbitrary retries in case the remote processor is slow to respond
28+
* to PCC commands
29+
*/
30+
#define PCC_CMD_WAIT_RETRIES_NUM 500
31+
2632
struct pcc_data {
2733
struct pcc_mbox_chan *pcc_chan;
2834
void __iomem *pcc_comm_addr;
@@ -63,6 +69,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
6369
if (IS_ERR(data->pcc_chan)) {
6470
pr_err("Failed to find PCC channel for subspace %d\n",
6571
ctx->subspace_id);
72+
kfree(data);
6673
return AE_NOT_FOUND;
6774
}
6875

@@ -72,6 +79,8 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
7279
if (!data->pcc_comm_addr) {
7380
pr_err("Failed to ioremap PCC comm region mem for %d\n",
7481
ctx->subspace_id);
82+
pcc_mbox_free_channel(data->pcc_chan);
83+
kfree(data);
7584
return AE_NO_MEMORY;
7685
}
7786

@@ -86,6 +95,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
8695
{
8796
int ret;
8897
struct pcc_data *data = region_context;
98+
u64 usecs_lat;
8999

90100
reinit_completion(&data->done);
91101

@@ -96,10 +106,22 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
96106
if (ret < 0)
97107
return AE_ERROR;
98108

99-
if (data->pcc_chan->mchan->mbox->txdone_irq)
100-
wait_for_completion(&data->done);
109+
if (data->pcc_chan->mchan->mbox->txdone_irq) {
110+
/*
111+
* pcc_chan->latency is just a Nominal value. In reality the remote
112+
* processor could be much slower to reply. So add an arbitrary
113+
* amount of wait on top of Nominal.
114+
*/
115+
usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency;
116+
ret = wait_for_completion_timeout(&data->done,
117+
usecs_to_jiffies(usecs_lat));
118+
if (ret == 0) {
119+
pr_err("PCC command executed timeout!\n");
120+
return AE_TIME;
121+
}
122+
}
101123

102-
mbox_client_txdone(data->pcc_chan->mchan, ret);
124+
mbox_chan_txdone(data->pcc_chan->mchan, ret);
103125

104126
memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length);
105127

drivers/acpi/apei/apei-base.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,9 @@ EXPORT_SYMBOL_GPL(apei_exec_write_register);
125125
int apei_exec_write_register_value(struct apei_exec_context *ctx,
126126
struct acpi_whea_header *entry)
127127
{
128-
int rc;
129-
130128
ctx->value = entry->value;
131-
rc = apei_exec_write_register(ctx, entry);
132129

133-
return rc;
130+
return apei_exec_write_register(ctx, entry);
134131
}
135132
EXPORT_SYMBOL_GPL(apei_exec_write_register_value);
136133

drivers/acpi/apei/bert.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ static void __init bert_print_all(struct acpi_bert_region *region,
9090

9191
if (skipped)
9292
pr_info(HW_ERR "Skipped %d error records\n", skipped);
93+
94+
if (printed + skipped)
95+
pr_info("Total records found: %d\n", printed + skipped);
9396
}
9497

9598
static int __init setup_bert_disable(char *str)

drivers/acpi/apei/erst.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,14 +1020,10 @@ static int reader_pos;
10201020

10211021
static int erst_open_pstore(struct pstore_info *psi)
10221022
{
1023-
int rc;
1024-
10251023
if (erst_disable)
10261024
return -ENODEV;
10271025

1028-
rc = erst_get_record_id_begin(&reader_pos);
1029-
1030-
return rc;
1026+
return erst_get_record_id_begin(&reader_pos);
10311027
}
10321028

10331029
static int erst_close_pstore(struct pstore_info *psi)

drivers/acpi/cppc_acpi.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,9 @@ bool acpi_cpc_valid(void)
424424
struct cpc_desc *cpc_ptr;
425425
int cpu;
426426

427+
if (acpi_disabled)
428+
return false;
429+
427430
for_each_present_cpu(cpu) {
428431
cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
429432
if (!cpc_ptr)
@@ -1240,6 +1243,48 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
12401243
}
12411244
EXPORT_SYMBOL_GPL(cppc_get_perf_caps);
12421245

1246+
/**
1247+
* cppc_perf_ctrs_in_pcc - Check if any perf counters are in a PCC region.
1248+
*
1249+
* CPPC has flexibility about how CPU performance counters are accessed.
1250+
* One of the choices is PCC regions, which can have a high access latency. This
1251+
* routine allows callers of cppc_get_perf_ctrs() to know this ahead of time.
1252+
*
1253+
* Return: true if any of the counters are in PCC regions, false otherwise
1254+
*/
1255+
bool cppc_perf_ctrs_in_pcc(void)
1256+
{
1257+
int cpu;
1258+
1259+
for_each_present_cpu(cpu) {
1260+
struct cpc_register_resource *ref_perf_reg;
1261+
struct cpc_desc *cpc_desc;
1262+
1263+
cpc_desc = per_cpu(cpc_desc_ptr, cpu);
1264+
1265+
if (CPC_IN_PCC(&cpc_desc->cpc_regs[DELIVERED_CTR]) ||
1266+
CPC_IN_PCC(&cpc_desc->cpc_regs[REFERENCE_CTR]) ||
1267+
CPC_IN_PCC(&cpc_desc->cpc_regs[CTR_WRAP_TIME]))
1268+
return true;
1269+
1270+
1271+
ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF];
1272+
1273+
/*
1274+
* If reference perf register is not supported then we should
1275+
* use the nominal perf value
1276+
*/
1277+
if (!CPC_SUPPORTED(ref_perf_reg))
1278+
ref_perf_reg = &cpc_desc->cpc_regs[NOMINAL_PERF];
1279+
1280+
if (CPC_IN_PCC(ref_perf_reg))
1281+
return true;
1282+
}
1283+
1284+
return false;
1285+
}
1286+
EXPORT_SYMBOL_GPL(cppc_perf_ctrs_in_pcc);
1287+
12431288
/**
12441289
* cppc_get_perf_ctrs - Read a CPU's performance feedback counters.
12451290
* @cpunum: CPU from which to read counters.

drivers/acpi/osi.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,6 @@ osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
4444
{"Processor Device", true},
4545
{"3.0 _SCP Extensions", true},
4646
{"Processor Aggregator Device", true},
47-
/*
48-
* Linux-Dell-Video is used by BIOS to disable RTD3 for NVidia graphics
49-
* cards as RTD3 is not supported by drivers now. Systems with NVidia
50-
* cards will hang without RTD3 disabled.
51-
*
52-
* Once NVidia drivers officially support RTD3, this _OSI strings can
53-
* be removed if both new and old graphics cards are supported.
54-
*/
55-
{"Linux-Dell-Video", true},
56-
/*
57-
* Linux-Lenovo-NV-HDMI-Audio is used by BIOS to power on NVidia's HDMI
58-
* audio device which is turned off for power-saving in Windows OS.
59-
* This power management feature observed on some Lenovo Thinkpad
60-
* systems which will not be able to output audio via HDMI without
61-
* a BIOS workaround.
62-
*/
63-
{"Linux-Lenovo-NV-HDMI-Audio", true},
64-
/*
65-
* Linux-HPI-Hybrid-Graphics is used by BIOS to enable dGPU to
66-
* output video directly to external monitors on HP Inc. mobile
67-
* workstations as Nvidia and AMD VGA drivers provide limited
68-
* hybrid graphics supports.
69-
*/
70-
{"Linux-HPI-Hybrid-Graphics", true},
7147
};
7248

7349
static u32 acpi_osi_handler(acpi_string interface, u32 supported)

drivers/base/arch_topology.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ void topology_init_cpu_capacity_cppc(void)
353353
struct cppc_perf_caps perf_caps;
354354
int cpu;
355355

356-
if (likely(acpi_disabled || !acpi_cpc_valid()))
356+
if (likely(!acpi_cpc_valid()))
357357
return;
358358

359359
raw_capacity = kcalloc(num_possible_cpus(), sizeof(*raw_capacity),

drivers/cpufreq/amd-pstate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ static int __init amd_pstate_init(void)
673673
return -ENODEV;
674674

675675
if (!acpi_cpc_valid()) {
676-
pr_debug("the _CPC object is not present in SBIOS\n");
676+
pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n");
677677
return -ENODEV;
678678
}
679679

drivers/cpufreq/cppc_cpufreq.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,15 @@ static struct cppc_workaround_oem_info wa_info[] = {
6363

6464
static struct cpufreq_driver cppc_cpufreq_driver;
6565

66+
static enum {
67+
FIE_UNSET = -1,
68+
FIE_ENABLED,
69+
FIE_DISABLED
70+
} fie_disabled = FIE_UNSET;
71+
6672
#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
73+
module_param(fie_disabled, int, 0444);
74+
MODULE_PARM_DESC(fie_disabled, "Disable Frequency Invariance Engine (FIE)");
6775

6876
/* Frequency invariance support */
6977
struct cppc_freq_invariance {
@@ -158,7 +166,7 @@ static void cppc_cpufreq_cpu_fie_init(struct cpufreq_policy *policy)
158166
struct cppc_freq_invariance *cppc_fi;
159167
int cpu, ret;
160168

161-
if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
169+
if (fie_disabled)
162170
return;
163171

164172
for_each_cpu(cpu, policy->cpus) {
@@ -199,7 +207,7 @@ static void cppc_cpufreq_cpu_fie_exit(struct cpufreq_policy *policy)
199207
struct cppc_freq_invariance *cppc_fi;
200208
int cpu;
201209

202-
if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
210+
if (fie_disabled)
203211
return;
204212

205213
/* policy->cpus will be empty here, use related_cpus instead */
@@ -229,7 +237,15 @@ static void __init cppc_freq_invariance_init(void)
229237
};
230238
int ret;
231239

232-
if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
240+
if (fie_disabled != FIE_ENABLED && fie_disabled != FIE_DISABLED) {
241+
fie_disabled = FIE_ENABLED;
242+
if (cppc_perf_ctrs_in_pcc()) {
243+
pr_info("FIE not enabled on systems with registers in PCC\n");
244+
fie_disabled = FIE_DISABLED;
245+
}
246+
}
247+
248+
if (fie_disabled)
233249
return;
234250

235251
kworker_fie = kthread_create_worker(0, "cppc_fie");
@@ -247,7 +263,7 @@ static void __init cppc_freq_invariance_init(void)
247263

248264
static void cppc_freq_invariance_exit(void)
249265
{
250-
if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
266+
if (fie_disabled)
251267
return;
252268

253269
kthread_destroy_worker(kworker_fie);
@@ -936,6 +952,7 @@ static void cppc_check_hisi_workaround(void)
936952
wa_info[i].oem_revision == tbl->oem_revision) {
937953
/* Overwrite the get() callback */
938954
cppc_cpufreq_driver.get = hisi_cppc_cpufreq_get_rate;
955+
fie_disabled = FIE_DISABLED;
939956
break;
940957
}
941958
}
@@ -947,7 +964,7 @@ static int __init cppc_cpufreq_init(void)
947964
{
948965
int ret;
949966

950-
if ((acpi_disabled) || !acpi_cpc_valid())
967+
if (!acpi_cpc_valid())
951968
return -ENODEV;
952969

953970
cppc_check_hisi_workaround();

0 commit comments

Comments
 (0)