thermal/drivers/int340x: Improve the tcc offset saving for suspend/resume
authorAntoine Tenart <atenart@kernel.org>
Thu, 9 Sep 2021 08:56:13 +0000 (10:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Feb 2022 11:56:07 +0000 (12:56 +0100)
commit c4fcf1ada4ae63e0aab6afd19ca2e7d16833302c upstream.

When the driver resumes, the tcc offset is set back to its previous
value. But this only works if the value was user defined as otherwise
the offset isn't saved. This asymmetric logic is harder to maintain and
introduced some issues.

Improve the logic by saving the tcc offset in a suspend op, so the right
value is always restored after a resume.

Signed-off-by: Antoine Tenart <atenart@kernel.org>
Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Tested-by: Srinivas Pandruvada <srinivas.pI andruvada@linux.intel.com>
Link: https://lore.kernel.org/r/20210909085613.5577-3-atenart@kernel.org
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Sumeet Pawnikar <sumeet.r.pawnikar@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/thermal/intel/int340x_thermal/int3401_thermal.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c

index acebc8ba94e2920545fead3c7c0c1dbe6019f4fe..217786fba185cb0211662863eb619602ed539293 100644 (file)
@@ -44,15 +44,21 @@ static int int3401_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static int int3401_thermal_suspend(struct device *dev)
+{
+       return proc_thermal_suspend(dev);
+}
 static int int3401_thermal_resume(struct device *dev)
 {
        return proc_thermal_resume(dev);
 }
 #else
+#define int3401_thermal_suspend NULL
 #define int3401_thermal_resume NULL
 #endif
 
-static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, NULL, int3401_thermal_resume);
+static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, int3401_thermal_suspend,
+                        int3401_thermal_resume);
 
 static struct platform_driver int3401_driver = {
        .probe = int3401_add,
index fb64acfd5e07d6eb295816cd7efe481cfc9f4966..a8d98f1bd6c67c402ad31eb78dd5ac352125abd0 100644 (file)
@@ -68,8 +68,7 @@ static const struct attribute_group power_limit_attribute_group = {
        .name = "power_limits"
 };
 
-static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
+static int tcc_get_offset(void)
 {
        u64 val;
        int err;
@@ -78,8 +77,20 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
        if (err)
                return err;
 
-       val = (val >> 24) & 0x3f;
-       return sprintf(buf, "%d\n", (int)val);
+       return (val >> 24) & 0x3f;
+}
+
+static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf)
+{
+       int tcc;
+
+       tcc = tcc_get_offset();
+       if (tcc < 0)
+               return tcc;
+
+       return sprintf(buf, "%d\n", tcc);
 }
 
 static int tcc_offset_update(unsigned int tcc)
@@ -107,8 +118,6 @@ static int tcc_offset_update(unsigned int tcc)
        return 0;
 }
 
-static int tcc_offset_save = -1;
-
 static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
                                struct device_attribute *attr, const char *buf,
                                size_t count)
@@ -131,8 +140,6 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
        if (err)
                return err;
 
-       tcc_offset_save = tcc;
-
        return count;
 }
 
@@ -345,6 +352,18 @@ void proc_thermal_remove(struct proc_thermal_device *proc_priv)
 }
 EXPORT_SYMBOL_GPL(proc_thermal_remove);
 
+static int tcc_offset_save = -1;
+
+int proc_thermal_suspend(struct device *dev)
+{
+       tcc_offset_save = tcc_get_offset();
+       if (tcc_offset_save < 0)
+               dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(proc_thermal_suspend);
+
 int proc_thermal_resume(struct device *dev)
 {
        struct proc_thermal_device *proc_dev;
@@ -352,6 +371,7 @@ int proc_thermal_resume(struct device *dev)
        proc_dev = dev_get_drvdata(dev);
        proc_thermal_read_ppcc(proc_dev);
 
+       /* Do not update if saving failed */
        if (tcc_offset_save >= 0)
                tcc_offset_update(tcc_offset_save);
 
index 5a1cfe4864f161d69c86eaa3b53ec1e49d9b5f96..c1d8de6dc3d10d3ded1200a4d7a188428ce49351 100644 (file)
@@ -83,6 +83,7 @@ void proc_thermal_mbox_remove(struct pci_dev *pdev);
 int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp);
 int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv);
 void proc_thermal_remove(struct proc_thermal_device *proc_priv);
+int proc_thermal_suspend(struct device *dev);
 int proc_thermal_resume(struct device *dev);
 int proc_thermal_mmio_add(struct pci_dev *pdev,
                          struct proc_thermal_device *proc_priv,
index 11dd2e825f4ffe20ceec111f31197b9b9badbf73..b4bcd3fe9eb2f9339a9b780f60cc0d1ad1028cfe 100644 (file)
@@ -314,6 +314,20 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static int proc_thermal_pci_suspend(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct proc_thermal_device *proc_priv;
+       struct proc_thermal_pci *pci_info;
+
+       proc_priv = pci_get_drvdata(pdev);
+       pci_info = proc_priv->priv_data;
+
+       if (!pci_info->no_legacy)
+               return proc_thermal_suspend(dev);
+
+       return 0;
+}
 static int proc_thermal_pci_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -335,10 +349,12 @@ static int proc_thermal_pci_resume(struct device *dev)
        return 0;
 }
 #else
+#define proc_thermal_pci_suspend NULL
 #define proc_thermal_pci_resume NULL
 #endif
 
-static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
+static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
+                        proc_thermal_pci_resume);
 
 static const struct pci_device_id proc_thermal_pci_ids[] = {
        { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },
index f5fc1791b11efbe54c9bf14dd58e988fa6b823b5..4571a1a53b841f22eba3a7c0fada9503fe2287bd 100644 (file)
@@ -107,15 +107,21 @@ static void proc_thermal_pci_remove(struct pci_dev *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static int proc_thermal_pci_suspend(struct device *dev)
+{
+       return proc_thermal_suspend(dev);
+}
 static int proc_thermal_pci_resume(struct device *dev)
 {
        return proc_thermal_resume(dev);
 }
 #else
+#define proc_thermal_pci_suspend NULL
 #define proc_thermal_pci_resume NULL
 #endif
 
-static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
+static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
+                        proc_thermal_pci_resume);
 
 static const struct pci_device_id proc_thermal_pci_ids[] = {
        { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) },