Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

platform/x86: ISST: Process read/write blocked feature status

When a feature is read blocked, don't continue to read SST information
and register with SST core.

When the feature is write blocked, continue to offer read interface for
SST parameters, but don't allow any operation to change state. A state
change results from SST level change, feature change or class of service
change.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20231204221740.3645130-5-srinivas.pandruvada@linux.intel.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Srinivas Pandruvada and committed by
Hans de Goede
8bed9ff7 046d7be6

+25
+25
drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
··· 234 234 * @saved_clos_configs: Save SST-CP CLOS configuration to store restore for suspend/resume 235 235 * @saved_clos_assocs: Save SST-CP CLOS association to store restore for suspend/resume 236 236 * @saved_pp_control: Save SST-PP control information to store restore for suspend/resume 237 + * @write_blocked: Write operation is blocked, so can't change SST state 237 238 * 238 239 * This structure is used store complete SST information for a power_domain. This information 239 240 * is used to read/write request for any SST IOCTL. Each physical CPU package can have multiple ··· 260 259 u64 saved_clos_configs[4]; 261 260 u64 saved_clos_assocs[4]; 262 261 u64 saved_pp_control; 262 + bool write_blocked; 263 263 }; 264 264 265 265 /** ··· 517 515 return -EINVAL; 518 516 519 517 if (clos_param.get_set) { 518 + if (power_domain_info->write_blocked) 519 + return -EPERM; 520 + 520 521 _write_cp_info("clos.min_freq", clos_param.min_freq_mhz, 521 522 (SST_CLOS_CONFIG_0_OFFSET + clos_param.clos * SST_REG_SIZE), 522 523 SST_CLOS_CONFIG_MIN_START, SST_CLOS_CONFIG_MIN_WIDTH, ··· 606 601 return -EINVAL; 607 602 608 603 power_domain_info = &sst_inst->power_domain_info[punit_id]; 604 + 605 + if (assoc_cmds.get_set && power_domain_info->write_blocked) 606 + return -EPERM; 609 607 610 608 offset = SST_CLOS_ASSOC_0_OFFSET + 611 609 (punit_cpu_no / SST_CLOS_ASSOC_CPUS_PER_REG) * SST_REG_SIZE; ··· 760 752 if (!power_domain_info) 761 753 return -EINVAL; 762 754 755 + if (power_domain_info->write_blocked) 756 + return -EPERM; 757 + 763 758 if (!(power_domain_info->pp_header.allowed_level_mask & BIT(perf_level.level))) 764 759 return -EINVAL; 765 760 ··· 819 808 power_domain_info = get_instance(perf_feature.socket_id, perf_feature.power_domain_id); 820 809 if (!power_domain_info) 821 810 return -EINVAL; 811 + 812 + if (power_domain_info->write_blocked) 813 + return -EPERM; 822 814 823 815 _write_pp_info("perf_feature", perf_feature.feature, SST_PP_CONTROL_OFFSET, 824 816 SST_PP_FEATURE_STATE_START, SST_PP_FEATURE_STATE_WIDTH, ··· 1271 1257 1272 1258 int tpmi_sst_dev_add(struct auxiliary_device *auxdev) 1273 1259 { 1260 + bool read_blocked = 0, write_blocked = 0; 1274 1261 struct intel_tpmi_plat_info *plat_info; 1275 1262 struct tpmi_sst_struct *tpmi_sst; 1276 1263 int i, ret, pkg = 0, inst = 0; 1277 1264 int num_resources; 1265 + 1266 + ret = tpmi_get_feature_status(auxdev, TPMI_ID_SST, &read_blocked, &write_blocked); 1267 + if (ret) 1268 + dev_info(&auxdev->dev, "Can't read feature status: ignoring read/write blocked status\n"); 1269 + 1270 + if (read_blocked) { 1271 + dev_info(&auxdev->dev, "Firmware has blocked reads, exiting\n"); 1272 + return -ENODEV; 1273 + } 1278 1274 1279 1275 plat_info = tpmi_get_platform_data(auxdev); 1280 1276 if (!plat_info) { ··· 1330 1306 tpmi_sst->power_domain_info[i].package_id = pkg; 1331 1307 tpmi_sst->power_domain_info[i].power_domain_id = i; 1332 1308 tpmi_sst->power_domain_info[i].auxdev = auxdev; 1309 + tpmi_sst->power_domain_info[i].write_blocked = write_blocked; 1333 1310 tpmi_sst->power_domain_info[i].sst_base = devm_ioremap_resource(&auxdev->dev, res); 1334 1311 if (IS_ERR(tpmi_sst->power_domain_info[i].sst_base)) 1335 1312 return PTR_ERR(tpmi_sst->power_domain_info[i].sst_base);