diff options
author | Prashanth Prakash <pprakash@codeaurora.org> | 2018-04-04 14:14:51 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2018-04-24 06:33:28 -0400 |
commit | 6fa12d584dcba18f67425ce17e9317311a624f81 (patch) | |
tree | deeea62992f02ba49125e04a198e136c9c487122 | |
parent | 4773e77cdc9b3af93ee1ae7bcf2acf94fde17166 (diff) |
ACPI / CPPC: Check for valid PCC subspace only if PCC is used
Changes the behavior where we return error if there are no valid PCC
subspace for a given performance domain.
The ACPI spec does not mandate the use PCC, so it is possible to have
platforms where a PCC subspace may not be present, so we need to check
for a valid PCC subspace ID only if the register is a PCC register.
Signed-off-by: Prashanth Prakash <pprakash@codeaurora.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/acpi/cppc_acpi.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 8fa3d3a6e5b6..4446fa6c820e 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c | |||
@@ -1075,15 +1075,14 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps) | |||
1075 | *low_freq_reg = NULL, *nom_freq_reg = NULL; | 1075 | *low_freq_reg = NULL, *nom_freq_reg = NULL; |
1076 | u64 high, low, nom, min_nonlinear, low_f = 0, nom_f = 0; | 1076 | u64 high, low, nom, min_nonlinear, low_f = 0, nom_f = 0; |
1077 | int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); | 1077 | int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); |
1078 | struct cppc_pcc_data *pcc_ss_data; | 1078 | struct cppc_pcc_data *pcc_ss_data = NULL; |
1079 | int ret = 0, regs_in_pcc = 0; | 1079 | int ret = 0, regs_in_pcc = 0; |
1080 | 1080 | ||
1081 | if (!cpc_desc || pcc_ss_id < 0) { | 1081 | if (!cpc_desc) { |
1082 | pr_debug("No CPC descriptor for CPU:%d\n", cpunum); | 1082 | pr_debug("No CPC descriptor for CPU:%d\n", cpunum); |
1083 | return -ENODEV; | 1083 | return -ENODEV; |
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | pcc_ss_data = pcc_data[pcc_ss_id]; | ||
1087 | highest_reg = &cpc_desc->cpc_regs[HIGHEST_PERF]; | 1086 | highest_reg = &cpc_desc->cpc_regs[HIGHEST_PERF]; |
1088 | lowest_reg = &cpc_desc->cpc_regs[LOWEST_PERF]; | 1087 | lowest_reg = &cpc_desc->cpc_regs[LOWEST_PERF]; |
1089 | lowest_non_linear_reg = &cpc_desc->cpc_regs[LOW_NON_LINEAR_PERF]; | 1088 | lowest_non_linear_reg = &cpc_desc->cpc_regs[LOW_NON_LINEAR_PERF]; |
@@ -1095,6 +1094,11 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps) | |||
1095 | if (CPC_IN_PCC(highest_reg) || CPC_IN_PCC(lowest_reg) || | 1094 | if (CPC_IN_PCC(highest_reg) || CPC_IN_PCC(lowest_reg) || |
1096 | CPC_IN_PCC(lowest_non_linear_reg) || CPC_IN_PCC(nominal_reg) || | 1095 | CPC_IN_PCC(lowest_non_linear_reg) || CPC_IN_PCC(nominal_reg) || |
1097 | CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg)) { | 1096 | CPC_IN_PCC(low_freq_reg) || CPC_IN_PCC(nom_freq_reg)) { |
1097 | if (pcc_ss_id < 0) { | ||
1098 | pr_debug("Invalid pcc_ss_id\n"); | ||
1099 | return -ENODEV; | ||
1100 | } | ||
1101 | pcc_ss_data = pcc_data[pcc_ss_id]; | ||
1098 | regs_in_pcc = 1; | 1102 | regs_in_pcc = 1; |
1099 | down_write(&pcc_ss_data->pcc_lock); | 1103 | down_write(&pcc_ss_data->pcc_lock); |
1100 | /* Ring doorbell once to update PCC subspace */ | 1104 | /* Ring doorbell once to update PCC subspace */ |
@@ -1150,16 +1154,15 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs) | |||
1150 | struct cpc_register_resource *delivered_reg, *reference_reg, | 1154 | struct cpc_register_resource *delivered_reg, *reference_reg, |
1151 | *ref_perf_reg, *ctr_wrap_reg; | 1155 | *ref_perf_reg, *ctr_wrap_reg; |
1152 | int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); | 1156 | int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); |
1153 | struct cppc_pcc_data *pcc_ss_data; | 1157 | struct cppc_pcc_data *pcc_ss_data = NULL; |
1154 | u64 delivered, reference, ref_perf, ctr_wrap_time; | 1158 | u64 delivered, reference, ref_perf, ctr_wrap_time; |
1155 | int ret = 0, regs_in_pcc = 0; | 1159 | int ret = 0, regs_in_pcc = 0; |
1156 | 1160 | ||
1157 | if (!cpc_desc || pcc_ss_id < 0) { | 1161 | if (!cpc_desc) { |
1158 | pr_debug("No CPC descriptor for CPU:%d\n", cpunum); | 1162 | pr_debug("No CPC descriptor for CPU:%d\n", cpunum); |
1159 | return -ENODEV; | 1163 | return -ENODEV; |
1160 | } | 1164 | } |
1161 | 1165 | ||
1162 | pcc_ss_data = pcc_data[pcc_ss_id]; | ||
1163 | delivered_reg = &cpc_desc->cpc_regs[DELIVERED_CTR]; | 1166 | delivered_reg = &cpc_desc->cpc_regs[DELIVERED_CTR]; |
1164 | reference_reg = &cpc_desc->cpc_regs[REFERENCE_CTR]; | 1167 | reference_reg = &cpc_desc->cpc_regs[REFERENCE_CTR]; |
1165 | ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF]; | 1168 | ref_perf_reg = &cpc_desc->cpc_regs[REFERENCE_PERF]; |
@@ -1175,6 +1178,11 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs) | |||
1175 | /* Are any of the regs PCC ?*/ | 1178 | /* Are any of the regs PCC ?*/ |
1176 | if (CPC_IN_PCC(delivered_reg) || CPC_IN_PCC(reference_reg) || | 1179 | if (CPC_IN_PCC(delivered_reg) || CPC_IN_PCC(reference_reg) || |
1177 | CPC_IN_PCC(ctr_wrap_reg) || CPC_IN_PCC(ref_perf_reg)) { | 1180 | CPC_IN_PCC(ctr_wrap_reg) || CPC_IN_PCC(ref_perf_reg)) { |
1181 | if (pcc_ss_id < 0) { | ||
1182 | pr_debug("Invalid pcc_ss_id\n"); | ||
1183 | return -ENODEV; | ||
1184 | } | ||
1185 | pcc_ss_data = pcc_data[pcc_ss_id]; | ||
1178 | down_write(&pcc_ss_data->pcc_lock); | 1186 | down_write(&pcc_ss_data->pcc_lock); |
1179 | regs_in_pcc = 1; | 1187 | regs_in_pcc = 1; |
1180 | /* Ring doorbell once to update PCC subspace */ | 1188 | /* Ring doorbell once to update PCC subspace */ |
@@ -1225,15 +1233,14 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls) | |||
1225 | struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu); | 1233 | struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpu); |
1226 | struct cpc_register_resource *desired_reg; | 1234 | struct cpc_register_resource *desired_reg; |
1227 | int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); | 1235 | int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); |
1228 | struct cppc_pcc_data *pcc_ss_data; | 1236 | struct cppc_pcc_data *pcc_ss_data = NULL; |
1229 | int ret = 0; | 1237 | int ret = 0; |
1230 | 1238 | ||
1231 | if (!cpc_desc || pcc_ss_id < 0) { | 1239 | if (!cpc_desc) { |
1232 | pr_debug("No CPC descriptor for CPU:%d\n", cpu); | 1240 | pr_debug("No CPC descriptor for CPU:%d\n", cpu); |
1233 | return -ENODEV; | 1241 | return -ENODEV; |
1234 | } | 1242 | } |
1235 | 1243 | ||
1236 | pcc_ss_data = pcc_data[pcc_ss_id]; | ||
1237 | desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF]; | 1244 | desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF]; |
1238 | 1245 | ||
1239 | /* | 1246 | /* |
@@ -1244,6 +1251,11 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls) | |||
1244 | * achieve that goal here | 1251 | * achieve that goal here |
1245 | */ | 1252 | */ |
1246 | if (CPC_IN_PCC(desired_reg)) { | 1253 | if (CPC_IN_PCC(desired_reg)) { |
1254 | if (pcc_ss_id < 0) { | ||
1255 | pr_debug("Invalid pcc_ss_id\n"); | ||
1256 | return -ENODEV; | ||
1257 | } | ||
1258 | pcc_ss_data = pcc_data[pcc_ss_id]; | ||
1247 | down_read(&pcc_ss_data->pcc_lock); /* BEGIN Phase-I */ | 1259 | down_read(&pcc_ss_data->pcc_lock); /* BEGIN Phase-I */ |
1248 | if (pcc_ss_data->platform_owns_pcc) { | 1260 | if (pcc_ss_data->platform_owns_pcc) { |
1249 | ret = check_pcc_chan(pcc_ss_id, false); | 1261 | ret = check_pcc_chan(pcc_ss_id, false); |