| From 8e8ea763c8898eb1a42794c1399d9e40f5073efa 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 9e21da0e298ad..5c7f7e02a7d8a 100644 |
| --- a/drivers/crypto/ccp/psp-dev.c |
| +++ b/drivers/crypto/ccp/psp-dev.c |
| @@ -351,6 +351,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 3467f6db4f505..f204aa5df96e2 100644 |
| --- a/drivers/crypto/ccp/sp-dev.c |
| +++ b/drivers/crypto/ccp/sp-dev.c |
| @@ -230,6 +230,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 1335a83fe052e..a83751cfd0060 100644 |
| --- a/drivers/crypto/ccp/sp-dev.h |
| +++ b/drivers/crypto/ccp/sp-dev.h |
| @@ -141,6 +141,7 @@ void sp_destroy(struct sp_device *sp); |
| |
| 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); |
| @@ -174,6 +175,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 */ |
| |
| @@ -181,6 +183,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 8891ceee1d7d0..6ac805d99ccb3 100644 |
| --- a/drivers/crypto/ccp/sp-pci.c |
| +++ b/drivers/crypto/ccp/sp-pci.c |
| @@ -353,6 +353,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, /* C2PMSG_32 */ |
| @@ -563,7 +570,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 af881daa5855b..11c4b05e2f3a2 100644 |
| --- a/drivers/crypto/ccp/tee-dev.c |
| +++ b/drivers/crypto/ccp/tee-dev.c |
| @@ -366,3 +366,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 ea9a2b7c05f57..c23416cb7bb37 100644 |
| --- a/drivers/crypto/ccp/tee-dev.h |
| +++ b/drivers/crypto/ccp/tee-dev.h |
| @@ -111,5 +111,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 |
| |