Skip to content

Commit a93289b

Browse files
committed
Merge tag 'acpi-6.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI fixes from Rafael Wysocki: "These fix three recent regressions, one introduced while enabling a new platform firmware feature for power management, and two introduced by a recent CPPC library update. Specifics: - Allow two overlapping Low-Power S0 Idle _DSM function sets to be used at the same time (Rafael Wysocki) - Fix bit offset computation in MASK_VAL() macro used for applying a bitmask to a new CPPC register value (Jarred White) - Fix access width field usage for PCC registers in CPPC (Vanshidhar Konda)" * tag 'acpi-6.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI: PM: s2idle: Evaluate all Low-Power S0 Idle _DSM functions ACPI: CPPC: Fix access width used for PCC registers ACPI: CPPC: Fix bit_offset shift in MASK_VAL() macro
2 parents 52afb15 + 2ad9846 commit a93289b

File tree

2 files changed

+42
-23
lines changed

2 files changed

+42
-23
lines changed

drivers/acpi/cppc_acpi.c

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time);
170170
#define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width)
171171

172172
/* Shift and apply the mask for CPC reads/writes */
173-
#define MASK_VAL(reg, val) ((val) >> ((reg)->bit_offset & \
174-
GENMASK(((reg)->bit_width), 0)))
173+
#define MASK_VAL(reg, val) (((val) >> (reg)->bit_offset) & \
174+
GENMASK(((reg)->bit_width) - 1, 0))
175175

176176
static ssize_t show_feedback_ctrs(struct kobject *kobj,
177177
struct kobj_attribute *attr, char *buf)
@@ -1002,14 +1002,14 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
10021002
}
10031003

10041004
*val = 0;
1005+
size = GET_BIT_WIDTH(reg);
10051006

10061007
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
1007-
u32 width = GET_BIT_WIDTH(reg);
10081008
u32 val_u32;
10091009
acpi_status status;
10101010

10111011
status = acpi_os_read_port((acpi_io_address)reg->address,
1012-
&val_u32, width);
1012+
&val_u32, size);
10131013
if (ACPI_FAILURE(status)) {
10141014
pr_debug("Error: Failed to read SystemIO port %llx\n",
10151015
reg->address);
@@ -1018,17 +1018,22 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
10181018

10191019
*val = val_u32;
10201020
return 0;
1021-
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
1021+
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
1022+
/*
1023+
* For registers in PCC space, the register size is determined
1024+
* by the bit width field; the access size is used to indicate
1025+
* the PCC subspace id.
1026+
*/
1027+
size = reg->bit_width;
10221028
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
1029+
}
10231030
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
10241031
vaddr = reg_res->sys_mem_vaddr;
10251032
else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
10261033
return cpc_read_ffh(cpu, reg, val);
10271034
else
10281035
return acpi_os_read_memory((acpi_physical_address)reg->address,
1029-
val, reg->bit_width);
1030-
1031-
size = GET_BIT_WIDTH(reg);
1036+
val, size);
10321037

10331038
switch (size) {
10341039
case 8:
@@ -1044,8 +1049,13 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
10441049
*val = readq_relaxed(vaddr);
10451050
break;
10461051
default:
1047-
pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
1048-
reg->bit_width, pcc_ss_id);
1052+
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
1053+
pr_debug("Error: Cannot read %u bit width from system memory: 0x%llx\n",
1054+
size, reg->address);
1055+
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
1056+
pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
1057+
size, pcc_ss_id);
1058+
}
10491059
return -EFAULT;
10501060
}
10511061

@@ -1063,30 +1073,36 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
10631073
int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
10641074
struct cpc_reg *reg = &reg_res->cpc_entry.reg;
10651075

1076+
size = GET_BIT_WIDTH(reg);
1077+
10661078
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
1067-
u32 width = GET_BIT_WIDTH(reg);
10681079
acpi_status status;
10691080

10701081
status = acpi_os_write_port((acpi_io_address)reg->address,
1071-
(u32)val, width);
1082+
(u32)val, size);
10721083
if (ACPI_FAILURE(status)) {
10731084
pr_debug("Error: Failed to write SystemIO port %llx\n",
10741085
reg->address);
10751086
return -EFAULT;
10761087
}
10771088

10781089
return 0;
1079-
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
1090+
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
1091+
/*
1092+
* For registers in PCC space, the register size is determined
1093+
* by the bit width field; the access size is used to indicate
1094+
* the PCC subspace id.
1095+
*/
1096+
size = reg->bit_width;
10801097
vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
1098+
}
10811099
else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
10821100
vaddr = reg_res->sys_mem_vaddr;
10831101
else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
10841102
return cpc_write_ffh(cpu, reg, val);
10851103
else
10861104
return acpi_os_write_memory((acpi_physical_address)reg->address,
1087-
val, reg->bit_width);
1088-
1089-
size = GET_BIT_WIDTH(reg);
1105+
val, size);
10901106

10911107
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
10921108
val = MASK_VAL(reg, val);
@@ -1105,8 +1121,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
11051121
writeq_relaxed(val, vaddr);
11061122
break;
11071123
default:
1108-
pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
1109-
reg->bit_width, pcc_ss_id);
1124+
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
1125+
pr_debug("Error: Cannot write %u bit width to system memory: 0x%llx\n",
1126+
size, reg->address);
1127+
} else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
1128+
pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
1129+
size, pcc_ss_id);
1130+
}
11101131
ret_val = -EFAULT;
11111132
break;
11121133
}

drivers/acpi/x86/s2idle.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -492,16 +492,14 @@ static int lps0_device_attach(struct acpi_device *adev,
492492
unsigned int func_mask;
493493

494494
/*
495-
* Avoid evaluating the same _DSM function for two
496-
* different UUIDs and prioritize the MSFT one.
495+
* Log a message if the _DSM function sets for two
496+
* different UUIDs overlap.
497497
*/
498498
func_mask = lps0_dsm_func_mask & lps0_dsm_func_mask_microsoft;
499-
if (func_mask) {
499+
if (func_mask)
500500
acpi_handle_info(adev->handle,
501501
"Duplicate LPS0 _DSM functions (mask: 0x%x)\n",
502502
func_mask);
503-
lps0_dsm_func_mask &= ~func_mask;
504-
}
505503
}
506504
}
507505

0 commit comments

Comments
 (0)