diff options
author | Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> | 2021-10-22 00:08:58 +0300 |
---|---|---|
committer | Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com> | 2021-10-28 00:37:48 +0300 |
commit | fa9aaca01cecd4286b54dd2b96ce82ac89c54354 (patch) | |
tree | 97e64a692af0562ad9e6d2b4f7c988d693ae5db5 | |
parent | 837535351698d45c135cdcc0676f304773adac7b (diff) | |
download | linux-fa9aaca01cecd4286b54dd2b96ce82ac89c54354.tar.xz |
hwmon: (peci) add invalid reading filtering logic
CPU can return invalid temperature readings prior to BIOS-PCU
handshake RST_CPL3 or RST_CPL4 completion so add a fix to filter
the invalid readings out.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
-rw-r--r-- | drivers/hwmon/peci-cputemp.c | 39 | ||||
-rw-r--r-- | drivers/hwmon/peci-dimmtemp.c | 38 |
2 files changed, 77 insertions, 0 deletions
diff --git a/drivers/hwmon/peci-cputemp.c b/drivers/hwmon/peci-cputemp.c index c5d92d1d2c25..b628dbfff6b5 100644 --- a/drivers/hwmon/peci-cputemp.c +++ b/drivers/hwmon/peci-cputemp.c @@ -12,6 +12,7 @@ #define DEFAULT_CHANNEL_NUMS 5 #define MODTEMP_CHANNEL_NUMS CORE_MASK_BITS_MAX #define CPUTEMP_CHANNEL_NUMS (DEFAULT_CHANNEL_NUMS + MODTEMP_CHANNEL_NUMS) +#define BIOS_RST_CPL3 BIT(3) struct temp_group { struct peci_sensor_data die; @@ -83,6 +84,8 @@ static s32 ten_dot_six_to_millidegree(s32 val) static int get_temp_targets(struct peci_cputemp *priv) { + struct peci_rd_end_pt_cfg_msg re_msg; + u32 bios_reset_cpl_cfg; s32 tthrottle_offset; s32 tcontrol_margin; u8 pkg_cfg[4]; @@ -95,6 +98,42 @@ static int get_temp_targets(struct peci_cputemp *priv) if (!peci_sensor_need_update(&priv->temp.tcontrol)) return 0; + /* + * CPU can return invalid temperatures prior to BIOS-PCU handshake + * RST_CPL3 completion so filter the invalid readings out. + */ + switch (priv->gen_info->model) { + case INTEL_FAM6_ICELAKE_X: + case INTEL_FAM6_ICELAKE_XD: + re_msg.addr = priv->mgr->client->addr; + re_msg.msg_type = PECI_ENDPTCFG_TYPE_LOCAL_PCI; + re_msg.params.pci_cfg.seg = 0; + re_msg.params.pci_cfg.bus = 31; + re_msg.params.pci_cfg.device = 30; + re_msg.params.pci_cfg.function = 1; + re_msg.params.pci_cfg.reg = 0x94; + re_msg.rx_len = 4; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_END_PT_CFG, &re_msg); + if (ret || re_msg.cc != PECI_DEV_CC_SUCCESS) + ret = -EAGAIN; + if (ret) + return ret; + + bios_reset_cpl_cfg = le32_to_cpup((__le32 *)re_msg.data); + if (!(bios_reset_cpl_cfg & BIOS_RST_CPL3)) { + dev_dbg(priv->dev, "BIOS and Pcode Node ID isn't configured, BIOS_RESET_CPL_CFG: 0x%x\n", + bios_reset_cpl_cfg); + return -EAGAIN; + } + + break; + default: + /* TODO: Check reset completion for other CPUs if needed */ + break; + } + ret = peci_client_read_package_config(priv->mgr, PECI_MBX_INDEX_TEMP_TARGET, 0, pkg_cfg); diff --git a/drivers/hwmon/peci-dimmtemp.c b/drivers/hwmon/peci-dimmtemp.c index 8b3a265355e0..a50902ceb70a 100644 --- a/drivers/hwmon/peci-dimmtemp.c +++ b/drivers/hwmon/peci-dimmtemp.c @@ -15,6 +15,7 @@ /* -1 = no timeout */ #define DIMM_TEMP_MAX_DEFAULT 90000 #define DIMM_TEMP_CRIT_DEFAULT 100000 +#define BIOS_RST_CPL4 BIT(4) struct peci_dimmtemp { struct peci_client_manager *mgr; @@ -59,6 +60,7 @@ static int get_dimm_temp(struct peci_dimmtemp *priv, int dimm_no) int chan_rank = dimm_no / priv->gen_info->dimm_idx_max; struct peci_rd_pci_cfg_local_msg rp_msg; struct peci_rd_end_pt_cfg_msg re_msg; + u32 bios_reset_cpl_cfg; u8 cfg_data[4]; u8 cpu_seg, cpu_bus; int ret; @@ -72,6 +74,42 @@ static int get_dimm_temp(struct peci_dimmtemp *priv, int dimm_no) priv->temp[dimm_no].value = cfg_data[dimm_order] * 1000; + /* + * CPU can return invalid temperatures prior to BIOS-PCU handshake + * RST_CPL4 completion so filter the invalid readings out. + */ + switch (priv->gen_info->model) { + case INTEL_FAM6_ICELAKE_X: + case INTEL_FAM6_ICELAKE_XD: + re_msg.addr = priv->mgr->client->addr; + re_msg.msg_type = PECI_ENDPTCFG_TYPE_LOCAL_PCI; + re_msg.params.pci_cfg.seg = 0; + re_msg.params.pci_cfg.bus = 31; + re_msg.params.pci_cfg.device = 30; + re_msg.params.pci_cfg.function = 1; + re_msg.params.pci_cfg.reg = 0x94; + re_msg.rx_len = 4; + + ret = peci_command(priv->mgr->client->adapter, + PECI_CMD_RD_END_PT_CFG, &re_msg); + if (ret || re_msg.cc != PECI_DEV_CC_SUCCESS) + ret = -EAGAIN; + if (ret) + return ret; + + bios_reset_cpl_cfg = le32_to_cpup((__le32 *)re_msg.data); + if (!(bios_reset_cpl_cfg & BIOS_RST_CPL4)) { + dev_dbg(priv->dev, "DRAM parameters aren't calibrated, BIOS_RESET_CPL_CFG: 0x%x\n", + bios_reset_cpl_cfg); + return -EAGAIN; + } + + break; + default: + /* TODO: Check reset completion for other CPUs if needed */ + break; + } + switch (priv->gen_info->model) { case INTEL_FAM6_ICELAKE_X: case INTEL_FAM6_ICELAKE_XD: |