Skip to content

Commit 0f49aec

Browse files
author
CKI KWF Bot
committed
Merge: Update amd-pstate
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7185 JIRA: https://issues.redhat.com/browse/RHEL-105422 amd-pstate is the cpu frequency driver for AMD processors and should be routinely updated. The following commits have been excluded from the backport: c895ecd x86/msr: Rename 'wrmsrl_on_cpu()' to 'wrmsrq_on_cpu()' d7484ba x86/msr: Rename 'rdmsrl_on_cpu()' to 'rdmsrq_on_cpu()' 27a23a5 x86/msr: Rename 'wrmsrl_safe_on_cpu()' to 'wrmsrq_safe_on_cpu()' 5e404cb x86/msr: Rename 'rdmsrl_safe_on_cpu()' to 'rdmsrq_safe_on_cpu()' 78255eb x86/msr: Rename 'wrmsrl()' to 'wrmsrq()' c435e60 x86/msr: Rename 'rdmsrl()' to 'rdmsrq()' eaff6b6 cpufreq: Pass policy pointer to ->update_limits() 8157fbc ("cpufreq/amd-pstate: Update asym_prefer_cpu when core rankings change") Signed-off-by: David Arcari <darcari@redhat.com> Approved-by: Steve Best <sbest@redhat.com> Approved-by: Lenny Szubowicz <lszubowi@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 5c8825c + 0c543d4 commit 0f49aec

File tree

7 files changed

+254
-198
lines changed

7 files changed

+254
-198
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@
485485
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* Clear branch history at vmexit using SW loop */
486486
#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */
487487
#define X86_FEATURE_AMD_HETEROGENEOUS_CORES (21*32 + 6) /* Heterogeneous Core Topology */
488+
#define X86_FEATURE_AMD_WORKLOAD_CLASS (21*32 + 7) /* Workload Classification */
488489
#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32 + 9) /* Use thunk for indirect branches in lower half of cacheline */
489490

490491
/*

arch/x86/kernel/cpu/scattered.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ static const struct cpuid_bit cpuid_bits[] = {
4949
{ X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
5050
{ X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 },
5151
{ X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 },
52+
{ X86_FEATURE_AMD_WORKLOAD_CLASS, CPUID_EAX, 22, 0x80000021, 0 },
5253
{ X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 },
5354
{ X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 },
5455
{ X86_FEATURE_AMD_LBR_PMC_FREEZE, CPUID_EAX, 2, 0x80000022, 0 },

drivers/acpi/cppc_acpi.c

Lines changed: 115 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,20 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
124124
#define CPC_SUPPORTED(cpc) ((cpc)->type == ACPI_TYPE_INTEGER ? \
125125
!!(cpc)->cpc_entry.int_value : \
126126
!IS_NULL_REG(&(cpc)->cpc_entry.reg))
127+
128+
/*
129+
* Each bit indicates the optionality of the register in per-cpu
130+
* cpc_regs[] with the corresponding index. 0 means mandatory and 1
131+
* means optional.
132+
*/
133+
#define REG_OPTIONAL (0x1FC7D0)
134+
135+
/*
136+
* Use the index of the register in per-cpu cpc_regs[] to check if
137+
* it's an optional one.
138+
*/
139+
#define IS_OPTIONAL_CPC_REG(reg_idx) (REG_OPTIONAL & (1U << (reg_idx)))
140+
127141
/*
128142
* Arbitrary Retries in case the remote processor is slow to respond
129143
* to PCC commands. Keeping it high enough to cover emulators where
@@ -1128,43 +1142,106 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
11281142
return ret_val;
11291143
}
11301144

1131-
static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf)
1145+
static int cppc_get_reg_val_in_pcc(int cpu, struct cpc_register_resource *reg, u64 *val)
11321146
{
1133-
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
1147+
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
1148+
struct cppc_pcc_data *pcc_ss_data = NULL;
1149+
int ret;
1150+
1151+
if (pcc_ss_id < 0) {
1152+
pr_debug("Invalid pcc_ss_id\n");
1153+
return -ENODEV;
1154+
}
1155+
1156+
pcc_ss_data = pcc_data[pcc_ss_id];
1157+
1158+
down_write(&pcc_ss_data->pcc_lock);
1159+
1160+
if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0)
1161+
ret = cpc_read(cpu, reg, val);
1162+
else
1163+
ret = -EIO;
1164+
1165+
up_write(&pcc_ss_data->pcc_lock);
1166+
1167+
return ret;
1168+
}
1169+
1170+
static int cppc_get_reg_val(int cpu, enum cppc_regs reg_idx, u64 *val)
1171+
{
1172+
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
11341173
struct cpc_register_resource *reg;
11351174

1175+
if (val == NULL)
1176+
return -EINVAL;
1177+
11361178
if (!cpc_desc) {
1137-
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
1179+
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
11381180
return -ENODEV;
11391181
}
11401182

11411183
reg = &cpc_desc->cpc_regs[reg_idx];
11421184

1143-
if (CPC_IN_PCC(reg)) {
1144-
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
1145-
struct cppc_pcc_data *pcc_ss_data = NULL;
1146-
int ret = 0;
1147-
1148-
if (pcc_ss_id < 0)
1149-
return -EIO;
1185+
if ((reg->type == ACPI_TYPE_INTEGER && IS_OPTIONAL_CPC_REG(reg_idx) &&
1186+
!reg->cpc_entry.int_value) || (reg->type != ACPI_TYPE_INTEGER &&
1187+
IS_NULL_REG(&reg->cpc_entry.reg))) {
1188+
pr_debug("CPC register is not supported\n");
1189+
return -EOPNOTSUPP;
1190+
}
11501191

1151-
pcc_ss_data = pcc_data[pcc_ss_id];
1192+
if (CPC_IN_PCC(reg))
1193+
return cppc_get_reg_val_in_pcc(cpu, reg, val);
11521194

1153-
down_write(&pcc_ss_data->pcc_lock);
1195+
return cpc_read(cpu, reg, val);
1196+
}
11541197

1155-
if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0)
1156-
cpc_read(cpunum, reg, perf);
1157-
else
1158-
ret = -EIO;
1198+
static int cppc_set_reg_val_in_pcc(int cpu, struct cpc_register_resource *reg, u64 val)
1199+
{
1200+
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
1201+
struct cppc_pcc_data *pcc_ss_data = NULL;
1202+
int ret;
11591203

1160-
up_write(&pcc_ss_data->pcc_lock);
1204+
if (pcc_ss_id < 0) {
1205+
pr_debug("Invalid pcc_ss_id\n");
1206+
return -ENODEV;
1207+
}
11611208

1209+
ret = cpc_write(cpu, reg, val);
1210+
if (ret)
11621211
return ret;
1212+
1213+
pcc_ss_data = pcc_data[pcc_ss_id];
1214+
1215+
down_write(&pcc_ss_data->pcc_lock);
1216+
/* after writing CPC, transfer the ownership of PCC to platform */
1217+
ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
1218+
up_write(&pcc_ss_data->pcc_lock);
1219+
1220+
return ret;
1221+
}
1222+
1223+
static int cppc_set_reg_val(int cpu, enum cppc_regs reg_idx, u64 val)
1224+
{
1225+
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
1226+
struct cpc_register_resource *reg;
1227+
1228+
if (!cpc_desc) {
1229+
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
1230+
return -ENODEV;
11631231
}
11641232

1165-
cpc_read(cpunum, reg, perf);
1233+
reg = &cpc_desc->cpc_regs[reg_idx];
11661234

1167-
return 0;
1235+
/* if a register is writeable, it must be a buffer and not null */
1236+
if ((reg->type != ACPI_TYPE_BUFFER) || IS_NULL_REG(&reg->cpc_entry.reg)) {
1237+
pr_debug("CPC register is not supported\n");
1238+
return -EOPNOTSUPP;
1239+
}
1240+
1241+
if (CPC_IN_PCC(reg))
1242+
return cppc_set_reg_val_in_pcc(cpu, reg, val);
1243+
1244+
return cpc_write(cpu, reg, val);
11681245
}
11691246

11701247
/**
@@ -1176,7 +1253,7 @@ static int cppc_get_perf(int cpunum, enum cppc_regs reg_idx, u64 *perf)
11761253
*/
11771254
int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
11781255
{
1179-
return cppc_get_perf(cpunum, DESIRED_PERF, desired_perf);
1256+
return cppc_get_reg_val(cpunum, DESIRED_PERF, desired_perf);
11801257
}
11811258
EXPORT_SYMBOL_GPL(cppc_get_desired_perf);
11821259

@@ -1189,7 +1266,7 @@ EXPORT_SYMBOL_GPL(cppc_get_desired_perf);
11891266
*/
11901267
int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)
11911268
{
1192-
return cppc_get_perf(cpunum, NOMINAL_PERF, nominal_perf);
1269+
return cppc_get_reg_val(cpunum, NOMINAL_PERF, nominal_perf);
11931270
}
11941271

11951272
/**
@@ -1201,7 +1278,7 @@ int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)
12011278
*/
12021279
int cppc_get_highest_perf(int cpunum, u64 *highest_perf)
12031280
{
1204-
return cppc_get_perf(cpunum, HIGHEST_PERF, highest_perf);
1281+
return cppc_get_reg_val(cpunum, HIGHEST_PERF, highest_perf);
12051282
}
12061283
EXPORT_SYMBOL_GPL(cppc_get_highest_perf);
12071284

@@ -1214,7 +1291,7 @@ EXPORT_SYMBOL_GPL(cppc_get_highest_perf);
12141291
*/
12151292
int cppc_get_epp_perf(int cpunum, u64 *epp_perf)
12161293
{
1217-
return cppc_get_perf(cpunum, ENERGY_PERF, epp_perf);
1294+
return cppc_get_reg_val(cpunum, ENERGY_PERF, epp_perf);
12181295
}
12191296
EXPORT_SYMBOL_GPL(cppc_get_epp_perf);
12201297

@@ -1485,53 +1562,27 @@ int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable)
14851562
EXPORT_SYMBOL_GPL(cppc_set_epp_perf);
14861563

14871564
/**
1488-
* cppc_get_auto_sel_caps - Read autonomous selection register.
1489-
* @cpunum : CPU from which to read register.
1490-
* @perf_caps : struct where autonomous selection register value is updated.
1565+
* cppc_get_auto_sel() - Read autonomous selection register.
1566+
* @cpu: CPU from which to read register.
1567+
* @enable: Return address.
14911568
*/
1492-
int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
1569+
int cppc_get_auto_sel(int cpu, bool *enable)
14931570
{
1494-
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
1495-
struct cpc_register_resource *auto_sel_reg;
1496-
u64 auto_sel;
1497-
1498-
if (!cpc_desc) {
1499-
pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
1500-
return -ENODEV;
1501-
}
1502-
1503-
auto_sel_reg = &cpc_desc->cpc_regs[AUTO_SEL_ENABLE];
1504-
1505-
if (!CPC_SUPPORTED(auto_sel_reg))
1506-
pr_warn_once("Autonomous mode is not unsupported!\n");
1507-
1508-
if (CPC_IN_PCC(auto_sel_reg)) {
1509-
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum);
1510-
struct cppc_pcc_data *pcc_ss_data = NULL;
1511-
int ret = 0;
1512-
1513-
if (pcc_ss_id < 0)
1514-
return -ENODEV;
1515-
1516-
pcc_ss_data = pcc_data[pcc_ss_id];
1517-
1518-
down_write(&pcc_ss_data->pcc_lock);
1519-
1520-
if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0) {
1521-
cpc_read(cpunum, auto_sel_reg, &auto_sel);
1522-
perf_caps->auto_sel = (bool)auto_sel;
1523-
} else {
1524-
ret = -EIO;
1525-
}
1571+
u64 auto_sel;
1572+
int ret;
15261573

1527-
up_write(&pcc_ss_data->pcc_lock);
1574+
if (enable == NULL)
1575+
return -EINVAL;
15281576

1577+
ret = cppc_get_reg_val(cpu, AUTO_SEL_ENABLE, &auto_sel);
1578+
if (ret)
15291579
return ret;
1530-
}
1580+
1581+
*enable = (bool)auto_sel;
15311582

15321583
return 0;
15331584
}
1534-
EXPORT_SYMBOL_GPL(cppc_get_auto_sel_caps);
1585+
EXPORT_SYMBOL_GPL(cppc_get_auto_sel);
15351586

15361587
/**
15371588
* cppc_set_auto_sel - Write autonomous selection register.
@@ -1540,43 +1591,7 @@ EXPORT_SYMBOL_GPL(cppc_get_auto_sel_caps);
15401591
*/
15411592
int cppc_set_auto_sel(int cpu, bool enable)
15421593
{
1543-
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
1544-
struct cpc_register_resource *auto_sel_reg;
1545-
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
1546-
struct cppc_pcc_data *pcc_ss_data = NULL;
1547-
int ret = -EINVAL;
1548-
1549-
if (!cpc_desc) {
1550-
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
1551-
return -ENODEV;
1552-
}
1553-
1554-
auto_sel_reg = &cpc_desc->cpc_regs[AUTO_SEL_ENABLE];
1555-
1556-
if (CPC_IN_PCC(auto_sel_reg)) {
1557-
if (pcc_ss_id < 0) {
1558-
pr_debug("Invalid pcc_ss_id\n");
1559-
return -ENODEV;
1560-
}
1561-
1562-
if (CPC_SUPPORTED(auto_sel_reg)) {
1563-
ret = cpc_write(cpu, auto_sel_reg, enable);
1564-
if (ret)
1565-
return ret;
1566-
}
1567-
1568-
pcc_ss_data = pcc_data[pcc_ss_id];
1569-
1570-
down_write(&pcc_ss_data->pcc_lock);
1571-
/* after writing CPC, transfer the ownership of PCC to platform */
1572-
ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
1573-
up_write(&pcc_ss_data->pcc_lock);
1574-
} else {
1575-
ret = -ENOTSUPP;
1576-
pr_debug("_CPC in PCC is not supported\n");
1577-
}
1578-
1579-
return ret;
1594+
return cppc_set_reg_val(cpu, AUTO_SEL_ENABLE, enable);
15801595
}
15811596
EXPORT_SYMBOL_GPL(cppc_set_auto_sel);
15821597

@@ -1590,38 +1605,7 @@ EXPORT_SYMBOL_GPL(cppc_set_auto_sel);
15901605
*/
15911606
int cppc_set_enable(int cpu, bool enable)
15921607
{
1593-
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
1594-
struct cpc_register_resource *enable_reg;
1595-
struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu);
1596-
struct cppc_pcc_data *pcc_ss_data = NULL;
1597-
int ret = -EINVAL;
1598-
1599-
if (!cpc_desc) {
1600-
pr_debug("No CPC descriptor for CPU:%d\n", cpu);
1601-
return -EINVAL;
1602-
}
1603-
1604-
enable_reg = &cpc_desc->cpc_regs[ENABLE];
1605-
1606-
if (CPC_IN_PCC(enable_reg)) {
1607-
1608-
if (pcc_ss_id < 0)
1609-
return -EIO;
1610-
1611-
ret = cpc_write(cpu, enable_reg, enable);
1612-
if (ret)
1613-
return ret;
1614-
1615-
pcc_ss_data = pcc_data[pcc_ss_id];
1616-
1617-
down_write(&pcc_ss_data->pcc_lock);
1618-
/* after writing CPC, transfer the ownership of PCC to platfrom */
1619-
ret = send_pcc_cmd(pcc_ss_id, CMD_WRITE);
1620-
up_write(&pcc_ss_data->pcc_lock);
1621-
return ret;
1622-
}
1623-
1624-
return cpc_write(cpu, enable_reg, enable);
1608+
return cppc_set_reg_val(cpu, ENABLE, enable);
16251609
}
16261610
EXPORT_SYMBOL_GPL(cppc_set_enable);
16271611

drivers/cpufreq/amd-pstate-ut.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,25 +242,30 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode)
242242
static int amd_pstate_ut_check_driver(u32 index)
243243
{
244244
enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE;
245+
enum amd_pstate_mode orig_mode = amd_pstate_get_status();
246+
int ret;
245247

246248
for (mode1 = AMD_PSTATE_DISABLE; mode1 < AMD_PSTATE_MAX; mode1++) {
247-
int ret = amd_pstate_set_mode(mode1);
249+
ret = amd_pstate_set_mode(mode1);
248250
if (ret)
249251
return ret;
250252
for (mode2 = AMD_PSTATE_DISABLE; mode2 < AMD_PSTATE_MAX; mode2++) {
251253
if (mode1 == mode2)
252254
continue;
253255
ret = amd_pstate_set_mode(mode2);
254-
if (ret) {
255-
pr_err("%s: failed to update status for %s->%s\n", __func__,
256-
amd_pstate_get_mode_string(mode1),
257-
amd_pstate_get_mode_string(mode2));
258-
return ret;
259-
}
256+
if (ret)
257+
goto out;
260258
}
261259
}
262260

263-
return 0;
261+
out:
262+
if (ret)
263+
pr_warn("%s: failed to update status for %s->%s: %d\n", __func__,
264+
amd_pstate_get_mode_string(mode1),
265+
amd_pstate_get_mode_string(mode2), ret);
266+
267+
amd_pstate_set_mode(orig_mode);
268+
return ret;
264269
}
265270

266271
static int __init amd_pstate_ut_init(void)

0 commit comments

Comments
 (0)