Skip to content

Commit f489c94

Browse files
Vanshidhar Kondarafaeljw
authored andcommitted
ACPI: CPPC: Fix access width used for PCC registers
commit 2f4a4d6 ("ACPI: CPPC: Use access_width over bit_width for system memory accesses") modified cpc_read()/cpc_write() to use access_width to read CPC registers. However, for PCC registers the access width field in the ACPI register macro specifies the PCC subspace ID. For non-zero PCC subspace ID it is incorrectly treated as access width. This causes errors when reading from PCC registers in the CPPC driver. For PCC registers, base the size of read/write on the bit width field. The debug message in cpc_read()/cpc_write() is updated to print relevant information for the address space type used to read the register. Fixes: 2f4a4d6 ("ACPI: CPPC: Use access_width over bit_width for system memory accesses") Signed-off-by: Vanshidhar Konda <[email protected]> Tested-by: Jarred White <[email protected]> Reviewed-by: Jarred White <[email protected]> Reviewed-by: Easwar Hariharan <[email protected]> Cc: 5.15+ <[email protected]> # 5.15+ Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 05d92ee commit f489c94

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

drivers/acpi/cppc_acpi.c

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

0 commit comments

Comments
 (0)