summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJae Hyun Yoo <jae.hyun.yoo@linux.intel.com>2021-10-22 00:08:58 +0300
committerJae Hyun Yoo <jae.hyun.yoo@linux.intel.com>2021-10-28 00:37:48 +0300
commitfa9aaca01cecd4286b54dd2b96ce82ac89c54354 (patch)
tree97e64a692af0562ad9e6d2b4f7c988d693ae5db5
parent837535351698d45c135cdcc0676f304773adac7b (diff)
downloadlinux-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.c39
-rw-r--r--drivers/hwmon/peci-dimmtemp.c38
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: