]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
platform/x86/amd/pmf: Prevent TEE errors after hibernate
authorShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Fri, 16 Jan 2026 04:11:28 +0000 (22:11 -0600)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Wed, 21 Jan 2026 08:51:56 +0000 (10:51 +0200)
After resuming from hibernate, TEE commands can time out and cause PSP
disables. Fix this by reinitializing the Trusted Application (TA) and
cancelling the pb workqueue in the hibernate callbacks to avoid these
errors.

ccp 0000:c4:00.2: tee: command 0x5 timed out, disabling PSP
amd-pmf AMDI0107:00: TEE enact cmd failed. err: ffff000e, ret:0
amd-pmf AMDI0107:00: TEE enact cmd failed. err: ffff000e, ret:0
amd-pmf AMDI0107:00: TEE enact cmd failed. err: ffff000e, ret:0

Fixes: ae82cef7d9c5 ("platform/x86/amd/pmf: Add support for PMF-TA interaction")
Reported-by: Lars Francke <lars.francke@gmail.com>
Closes: https://lore.kernel.org/platform-driver-x86/CAD-Ua_gfJnQSo8ucS_7ZwzuhoBRJ14zXP7s8b-zX3ZcxcyWePw@mail.gmail.com/
Tested-by: Yijun Shen <Yijun.Shen@Dell.com>
Co-developed-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Patil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
[ML: Add more tags]
Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
Link: https://patch.msgid.link/20260116041132.153674-2-superm1@kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/amd/pmf/pmf.h
drivers/platform/x86/amd/pmf/tee-if.c

index 9f4a1f79459a5bb5e1b0ebf882b8df1253f8d6b7..1a59e9ea9fb36ae200f4609d6b857fc356267cec 100644 (file)
@@ -315,6 +315,61 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
        return 0;
 }
 
+static int amd_pmf_reinit_ta(struct amd_pmf_dev *pdev)
+{
+       bool status;
+       int ret, i;
+
+       for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) {
+               ret = amd_pmf_tee_init(pdev, &amd_pmf_ta_uuid[i]);
+               if (ret) {
+                       dev_err(pdev->dev, "TEE init failed for UUID[%d] ret: %d\n", i, ret);
+                       return ret;
+               }
+
+               ret = amd_pmf_start_policy_engine(pdev);
+               dev_dbg(pdev->dev, "start policy engine ret: %d (UUID idx: %d)\n", ret, i);
+               status = ret == TA_PMF_TYPE_SUCCESS;
+               if (status)
+                       break;
+               amd_pmf_tee_deinit(pdev);
+       }
+
+       return 0;
+}
+
+static int amd_pmf_restore_handler(struct device *dev)
+{
+       struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+       int ret;
+
+       if (pdev->buf) {
+               ret = amd_pmf_set_dram_addr(pdev, false);
+               if (ret)
+                       return ret;
+       }
+
+       if (pdev->smart_pc_enabled)
+               amd_pmf_reinit_ta(pdev);
+
+       return 0;
+}
+
+static int amd_pmf_freeze_handler(struct device *dev)
+{
+       struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
+
+       if (!pdev->smart_pc_enabled)
+               return 0;
+
+       cancel_delayed_work_sync(&pdev->pb_work);
+       /* Clear all TEE resources */
+       amd_pmf_tee_deinit(pdev);
+       pdev->session_id = 0;
+
+       return 0;
+}
+
 static int amd_pmf_suspend_handler(struct device *dev)
 {
        struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
@@ -348,7 +403,12 @@ static int amd_pmf_resume_handler(struct device *dev)
        return 0;
 }
 
-static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, amd_pmf_suspend_handler, amd_pmf_resume_handler);
+static const struct dev_pm_ops amd_pmf_pm = {
+       .suspend = amd_pmf_suspend_handler,
+       .resume = amd_pmf_resume_handler,
+       .freeze = amd_pmf_freeze_handler,
+       .restore = amd_pmf_restore_handler,
+};
 
 static void amd_pmf_init_features(struct amd_pmf_dev *dev)
 {
index e65a7eca05088c6bdbcb48a895464c9c09f3cbb6..78dc7706607d77a5582cf0b8170a3fb4fd68d923 100644 (file)
@@ -132,6 +132,12 @@ struct cookie_header {
 
 typedef void (*apmf_event_handler_t)(acpi_handle handle, u32 event, void *data);
 
+static const uuid_t amd_pmf_ta_uuid[] __used = { UUID_INIT(0xd9b39bf2, 0x66bd, 0x4154, 0xaf, 0xb8,
+                                                          0x8a, 0xcc, 0x2b, 0x2b, 0x60, 0xd6),
+                                                UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, 0xb1, 0x2d,
+                                                          0xc5, 0x29, 0xb1, 0x3d, 0x85, 0x43),
+                                              };
+
 /* APTS PMF BIOS Interface */
 struct amd_pmf_apts_output {
        u16 table_version;
@@ -916,4 +922,8 @@ void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_tab
 void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in);
 int amd_pmf_invoke_cmd_enact(struct amd_pmf_dev *dev);
 
+int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid);
+void amd_pmf_tee_deinit(struct amd_pmf_dev *dev);
+int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev);
+
 #endif /* PMF_H */
index cec8b38c1afed015b0d39f950952fad909883b25..7ccd93f506b25e8dbec9246721e5896ec93b436b 100644 (file)
@@ -27,12 +27,6 @@ module_param(pb_side_load, bool, 0444);
 MODULE_PARM_DESC(pb_side_load, "Sideload policy binaries debug policy failures");
 #endif
 
-static const uuid_t amd_pmf_ta_uuid[] = { UUID_INIT(0xd9b39bf2, 0x66bd, 0x4154, 0xaf, 0xb8, 0x8a,
-                                                   0xcc, 0x2b, 0x2b, 0x60, 0xd6),
-                                         UUID_INIT(0x6fd93b77, 0x3fb8, 0x524d, 0xb1, 0x2d, 0xc5,
-                                                   0x29, 0xb1, 0x3d, 0x85, 0x43),
-                                       };
-
 static const char *amd_pmf_uevent_as_str(unsigned int state)
 {
        switch (state) {
@@ -324,7 +318,7 @@ static void amd_pmf_invoke_cmd(struct work_struct *work)
        schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms));
 }
 
-static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
+int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
 {
        struct cookie_header *header;
        int res;
@@ -480,7 +474,7 @@ static int amd_pmf_register_input_device(struct amd_pmf_dev *dev)
        return 0;
 }
 
-static int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid)
+int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid)
 {
        u32 size;
        int ret;
@@ -528,7 +522,7 @@ out_ctx:
        return ret;
 }
 
-static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
+void amd_pmf_tee_deinit(struct amd_pmf_dev *dev)
 {
        if (!dev->tee_ctx)
                return;