| From 9093c9577410f6036c8e85dd3d63ceba5108062f Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 15 Jan 2026 22:11:30 -0600 |
| Subject: crypto: ccp - Add an S4 restore flow |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Mario Limonciello (AMD) <superm1@kernel.org> |
| |
| [ Upstream commit 0ba2035026d0ab6c7c7e65ad8b418dc73d5700d9 ] |
| |
| The system will have lost power during S4. The ring used for TEE |
| communications needs to be initialized before use. |
| |
| Fixes: f892a21f51162 ("crypto: ccp - use generic power management") |
| 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> |
| Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org> |
| Reviewed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> |
| Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> |
| Link: https://patch.msgid.link/20260116041132.153674-4-superm1@kernel.org |
| Signed-off-by: Ilpo Jรคrvinen <ilpo.jarvinen@linux.intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/crypto/ccp/psp-dev.c | 11 +++++++++++ |
| drivers/crypto/ccp/sp-dev.c | 12 ++++++++++++ |
| drivers/crypto/ccp/sp-dev.h | 3 +++ |
| drivers/crypto/ccp/sp-pci.c | 16 +++++++++++++++- |
| drivers/crypto/ccp/tee-dev.c | 5 +++++ |
| drivers/crypto/ccp/tee-dev.h | 1 + |
| 6 files changed, 47 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c |
| index 949a3fa0b94a9..4bdf99f9a1094 100644 |
| --- a/drivers/crypto/ccp/psp-dev.c |
| +++ b/drivers/crypto/ccp/psp-dev.c |
| @@ -238,6 +238,17 @@ struct psp_device *psp_get_master_device(void) |
| return sp ? sp->psp_data : NULL; |
| } |
| |
| +int psp_restore(struct sp_device *sp) |
| +{ |
| + struct psp_device *psp = sp->psp_data; |
| + int ret = 0; |
| + |
| + if (psp->tee_data) |
| + ret = tee_restore(psp); |
| + |
| + return ret; |
| +} |
| + |
| void psp_pci_init(void) |
| { |
| psp_master = psp_get_master_device(); |
| diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c |
| index 7eb3e46682860..ccbe009ad6e58 100644 |
| --- a/drivers/crypto/ccp/sp-dev.c |
| +++ b/drivers/crypto/ccp/sp-dev.c |
| @@ -229,6 +229,18 @@ int sp_resume(struct sp_device *sp) |
| return 0; |
| } |
| |
| +int sp_restore(struct sp_device *sp) |
| +{ |
| + if (sp->psp_data) { |
| + int ret = psp_restore(sp); |
| + |
| + if (ret) |
| + return ret; |
| + } |
| + |
| + return sp_resume(sp); |
| +} |
| + |
| struct sp_device *sp_get_psp_master_device(void) |
| { |
| struct sp_device *i, *ret = NULL; |
| diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h |
| index 20377e67f65df..731e34a65b640 100644 |
| --- a/drivers/crypto/ccp/sp-dev.h |
| +++ b/drivers/crypto/ccp/sp-dev.h |
| @@ -121,6 +121,7 @@ struct sp_device *sp_get_master(void); |
| |
| int sp_suspend(struct sp_device *sp); |
| int sp_resume(struct sp_device *sp); |
| +int sp_restore(struct sp_device *sp); |
| int sp_request_ccp_irq(struct sp_device *sp, irq_handler_t handler, |
| const char *name, void *data); |
| void sp_free_ccp_irq(struct sp_device *sp, void *data); |
| @@ -154,6 +155,7 @@ int psp_dev_init(struct sp_device *sp); |
| void psp_pci_init(void); |
| void psp_dev_destroy(struct sp_device *sp); |
| void psp_pci_exit(void); |
| +int psp_restore(struct sp_device *sp); |
| |
| #else /* !CONFIG_CRYPTO_DEV_SP_PSP */ |
| |
| @@ -161,6 +163,7 @@ static inline int psp_dev_init(struct sp_device *sp) { return 0; } |
| static inline void psp_pci_init(void) { } |
| static inline void psp_dev_destroy(struct sp_device *sp) { } |
| static inline void psp_pci_exit(void) { } |
| +static inline int psp_restore(struct sp_device *sp) { return 0; } |
| |
| #endif /* CONFIG_CRYPTO_DEV_SP_PSP */ |
| |
| diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c |
| index 32c0b27446540..d3636c2212fe3 100644 |
| --- a/drivers/crypto/ccp/sp-pci.c |
| +++ b/drivers/crypto/ccp/sp-pci.c |
| @@ -343,6 +343,13 @@ static int __maybe_unused sp_pci_resume(struct device *dev) |
| return sp_resume(sp); |
| } |
| |
| +static int __maybe_unused sp_pci_restore(struct device *dev) |
| +{ |
| + struct sp_device *sp = dev_get_drvdata(dev); |
| + |
| + return sp_restore(sp); |
| +} |
| + |
| #ifdef CONFIG_CRYPTO_DEV_SP_PSP |
| static const struct sev_vdata sevv1 = { |
| .cmdresp_reg = 0x10580, |
| @@ -462,7 +469,14 @@ static const struct pci_device_id sp_pci_table[] = { |
| }; |
| MODULE_DEVICE_TABLE(pci, sp_pci_table); |
| |
| -static SIMPLE_DEV_PM_OPS(sp_pci_pm_ops, sp_pci_suspend, sp_pci_resume); |
| +static const struct dev_pm_ops sp_pci_pm_ops = { |
| + .suspend = pm_sleep_ptr(sp_pci_suspend), |
| + .resume = pm_sleep_ptr(sp_pci_resume), |
| + .freeze = pm_sleep_ptr(sp_pci_suspend), |
| + .thaw = pm_sleep_ptr(sp_pci_resume), |
| + .poweroff = pm_sleep_ptr(sp_pci_suspend), |
| + .restore_early = pm_sleep_ptr(sp_pci_restore), |
| +}; |
| |
| static struct pci_driver sp_pci_driver = { |
| .name = "ccp", |
| diff --git a/drivers/crypto/ccp/tee-dev.c b/drivers/crypto/ccp/tee-dev.c |
| index 5c9d47f3be375..c0dc462a94288 100644 |
| --- a/drivers/crypto/ccp/tee-dev.c |
| +++ b/drivers/crypto/ccp/tee-dev.c |
| @@ -394,3 +394,8 @@ int psp_check_tee_status(void) |
| return 0; |
| } |
| EXPORT_SYMBOL(psp_check_tee_status); |
| + |
| +int tee_restore(struct psp_device *psp) |
| +{ |
| + return tee_init_ring(psp->tee_data); |
| +} |
| diff --git a/drivers/crypto/ccp/tee-dev.h b/drivers/crypto/ccp/tee-dev.h |
| index 49d26158b71e3..b0bf1de94ea6f 100644 |
| --- a/drivers/crypto/ccp/tee-dev.h |
| +++ b/drivers/crypto/ccp/tee-dev.h |
| @@ -122,5 +122,6 @@ struct tee_ring_cmd { |
| |
| int tee_dev_init(struct psp_device *psp); |
| void tee_dev_destroy(struct psp_device *psp); |
| +int tee_restore(struct psp_device *psp); |
| |
| #endif /* __TEE_DEV_H__ */ |
| -- |
| 2.51.0 |
| |