* [Patch v6 1/7] firmware_loader: Stop pinning modules on registration
[not found] <cover.1794531772.git.prsampat@amd.com>
@ 2026-11-13 17:31 ` Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 2/7] firmware_loader: Stop pinning parent device per workqueue invocation Pratik R. Sampat
` (3 subsequent siblings)
4 siblings, 0 replies; 5+ messages in thread
From: Pratik R. Sampat @ 2026-11-13 17:31 UTC (permalink / raw)
To: mcgrof, russ.weight, dakr, ashish.kalra, thomas.lendacky, herbert, davem
Cc: linux-crypto, linux-kernel, gregkh, rafael, chao.gao, aik, tycho,
nikunj, michael.roth, shansinha, prsampat
From: Dan Williams <djbw@kernel.org>
The module reference counting can result in callers pinning themselves in a
circular loop. The module reference counting is unnecessary.
firmware_upload_unregister() must be able to guarantee that all ops are
idle at return.
All ops are either called from sysfs or the workqueue, so unregister sysfs
to stop submissions, cancel any started transfers, flush cancelled
transfers, and then release the device.
This also solves a theoretical race of new submissions starting between
flush_work() and device_unregister(). The module reference was not
protecting against that race.
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Russ Weight <russ.weight@linux.dev>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Reported-by: Chao Gao <chao.gao@intel.com>
Tested-by: Chao Gao <chao.gao@intel.com>
Closes: https://sashiko.dev/#/patchset/20260326084448.29947-1-chao.gao%40intel.com?patch=10705
Fixes: 97730bbb242c ("firmware_loader: Add firmware-upload support")
Signed-off-by: Dan Williams <djbw@kernel.org>
Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
v5..v6:
No change
---
drivers/base/firmware_loader/sysfs_upload.c | 31 ++++++++++-----------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/drivers/base/firmware_loader/sysfs_upload.c b/drivers/base/firmware_loader/sysfs_upload.c
index efc33294212f..6f2123538682 100644
--- a/drivers/base/firmware_loader/sysfs_upload.c
+++ b/drivers/base/firmware_loader/sysfs_upload.c
@@ -312,14 +312,9 @@ firmware_upload_register(struct module *module, struct device *parent,
return ERR_PTR(-EINVAL);
}
- if (!try_module_get(module))
- return ERR_PTR(-EFAULT);
-
fw_upload = kzalloc_obj(*fw_upload);
- if (!fw_upload) {
- ret = -ENOMEM;
- goto exit_module_put;
- }
+ if (!fw_upload)
+ return ERR_PTR(-ENOMEM);
fw_upload_priv = kzalloc_obj(*fw_upload_priv);
if (!fw_upload_priv) {
@@ -361,7 +356,7 @@ firmware_upload_register(struct module *module, struct device *parent,
if (ret) {
dev_err(fw_dev, "%s: device_register failed\n", __func__);
put_device(fw_dev);
- goto exit_module_put;
+ return ERR_PTR(ret);
}
return fw_upload;
@@ -372,9 +367,6 @@ firmware_upload_register(struct module *module, struct device *parent,
free_fw_upload:
kfree(fw_upload);
-exit_module_put:
- module_put(module);
-
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(firmware_upload_register);
@@ -386,23 +378,28 @@ EXPORT_SYMBOL_GPL(firmware_upload_register);
void firmware_upload_unregister(struct fw_upload *fw_upload)
{
struct fw_sysfs *fw_sysfs = fw_upload->priv;
+ struct device *parent = fw_sysfs->dev.parent;
struct fw_upload_priv *fw_upload_priv = fw_sysfs->fw_upload_priv;
- struct module *module = fw_upload_priv->module;
+
+ /* hold a parent reference while child is unregistered */
+ get_device(parent);
+
+ /* shutdown the sysfs interface to block new requests */
+ device_del(&fw_sysfs->dev);
mutex_lock(&fw_upload_priv->lock);
if (fw_upload_priv->progress == FW_UPLOAD_PROG_IDLE) {
mutex_unlock(&fw_upload_priv->lock);
- goto unregister;
+ goto release;
}
fw_upload_priv->ops->cancel(fw_upload);
mutex_unlock(&fw_upload_priv->lock);
+release:
/* Ensure lower-level device-driver is finished */
flush_work(&fw_upload_priv->work);
-
-unregister:
- device_unregister(&fw_sysfs->dev);
- module_put(module);
+ put_device(&fw_sysfs->dev);
+ put_device(parent);
}
EXPORT_SYMBOL_GPL(firmware_upload_unregister);
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch v6 2/7] firmware_loader: Stop pinning parent device per workqueue invocation
[not found] <cover.1794531772.git.prsampat@amd.com>
2026-11-13 17:31 ` [Patch v6 1/7] firmware_loader: Stop pinning modules on registration Pratik R. Sampat
@ 2026-11-13 17:31 ` Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 4/7] crypto: ccp - Factor out the release of the SEV firmware buffers Pratik R. Sampat
` (2 subsequent siblings)
4 siblings, 0 replies; 5+ messages in thread
From: Pratik R. Sampat @ 2026-11-13 17:31 UTC (permalink / raw)
To: mcgrof, russ.weight, dakr, ashish.kalra, thomas.lendacky, herbert, davem
Cc: linux-crypto, linux-kernel, gregkh, rafael, chao.gao, aik, tycho,
nikunj, michael.roth, shansinha, prsampat
From: Dan Williams <djbw@kernel.org>
The device core pins parent devices while children are registered. As long
as all usage of the parent device by the firmware_loader ends at
firmware_upload_unregister(), no per queue_work() reference is needed.
Now that firmware_upload_unregister() holds its own parent device reference
over the child device_del() and flush_work() events, the per queue_work()
reference can be deleted.
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Russ Weight <russ.weight@linux.dev>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Chao Gao <chao.gao@intel.com>
Signed-off-by: Dan Williams <djbw@kernel.org>
[chao.gao@intel.com: drop unused fw_dev in fw_upload_start()]
Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
v5..v6:
No change
---
drivers/base/firmware_loader/sysfs_upload.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/base/firmware_loader/sysfs_upload.c b/drivers/base/firmware_loader/sysfs_upload.c
index 6f2123538682..890a242a7c20 100644
--- a/drivers/base/firmware_loader/sysfs_upload.c
+++ b/drivers/base/firmware_loader/sysfs_upload.c
@@ -176,7 +176,7 @@ static void fw_upload_main(struct work_struct *work)
ret = fwlp->ops->prepare(fwl, fwlp->data, fwlp->remaining_size);
if (ret != FW_UPLOAD_ERR_NONE) {
fw_upload_set_error(fwlp, ret);
- goto putdev_exit;
+ goto out;
}
fw_upload_update_progress(fwlp, FW_UPLOAD_PROG_TRANSFERRING);
@@ -205,9 +205,7 @@ static void fw_upload_main(struct work_struct *work)
if (fwlp->ops->cleanup)
fwlp->ops->cleanup(fwl);
-putdev_exit:
- put_device(fw_dev->parent);
-
+out:
/*
* Note: fwlp->remaining_size is left unmodified here to provide
* additional information on errors. It will be reinitialized when
@@ -228,7 +226,6 @@ static void fw_upload_main(struct work_struct *work)
int fw_upload_start(struct fw_sysfs *fw_sysfs)
{
struct fw_priv *fw_priv = fw_sysfs->fw_priv;
- struct device *fw_dev = &fw_sysfs->dev;
struct fw_upload_priv *fwlp;
if (!fw_sysfs->fw_upload_priv)
@@ -249,8 +246,6 @@ int fw_upload_start(struct fw_sysfs *fw_sysfs)
return -EBUSY;
}
- get_device(fw_dev->parent); /* released in fw_upload_main */
-
fwlp->progress = FW_UPLOAD_PROG_RECEIVING;
fwlp->err_code = 0;
fwlp->remaining_size = fw_priv->size;
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch v6 4/7] crypto: ccp - Factor out the release of the SEV firmware buffers
[not found] <cover.1794531772.git.prsampat@amd.com>
2026-11-13 17:31 ` [Patch v6 1/7] firmware_loader: Stop pinning modules on registration Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 2/7] firmware_loader: Stop pinning parent device per workqueue invocation Pratik R. Sampat
@ 2026-11-13 17:31 ` Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 5/7] crypto: ccp - Allow SNP platform data to be queried after SNP INIT Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 6/7] crypto: ccp - Register with fw_uploader and always fail Pratik R. Sampat
4 siblings, 0 replies; 5+ messages in thread
From: Pratik R. Sampat @ 2026-11-13 17:31 UTC (permalink / raw)
To: mcgrof, russ.weight, dakr, ashish.kalra, thomas.lendacky, herbert, davem
Cc: linux-crypto, linux-kernel, gregkh, rafael, chao.gao, aik, tycho,
nikunj, michael.roth, shansinha, prsampat
__sev_firmware_shutdown() reclaims and frees the TMR and the INIT_EX NV
area once the platform has been taken down. Move that into a helper so
that other paths which de-initialize the platform can reuse the same
path.
No functional change intended.
Suggested-by: Shantanu Sinha <shansinha@google.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
v5..v6:
No change
---
drivers/crypto/ccp/sev-dev.c | 55 ++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 25 deletions(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index b980dfc7f3a3..888d960f68a9 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1883,6 +1883,35 @@ static int __sev_platform_shutdown_locked(int *error)
return ret;
}
+static void __sev_release_firmware_buffers(bool panic)
+{
+ if (sev_es_tmr) {
+ /*
+ * The TMR area was encrypted, flush it from the cache.
+ *
+ * If invoked during panic handling, local interrupts are
+ * disabled and all CPUs are stopped, so wbinvd_on_all_cpus()
+ * can't be used. In that case, wbinvd() is done on remote CPUs
+ * via the NMI callback, and done for this CPU later during
+ * SNP shutdown, so wbinvd_on_all_cpus() can be skipped.
+ */
+ if (!panic)
+ wbinvd_on_all_cpus();
+
+ __snp_free_firmware_pages(virt_to_page(sev_es_tmr),
+ get_order(sev_es_tmr_size),
+ true);
+ sev_es_tmr = NULL;
+ }
+
+ if (sev_init_ex_buffer) {
+ __snp_free_firmware_pages(virt_to_page(sev_init_ex_buffer),
+ get_order(NV_LENGTH),
+ true);
+ sev_init_ex_buffer = NULL;
+ }
+}
+
static int sev_get_platform_state(int *state, int *error)
{
struct sev_user_data_status data;
@@ -2963,31 +2992,7 @@ static void __sev_firmware_shutdown(struct sev_device *sev, bool panic)
__sev_platform_shutdown_locked(&error);
- if (sev_es_tmr) {
- /*
- * The TMR area was encrypted, flush it from the cache.
- *
- * If invoked during panic handling, local interrupts are
- * disabled and all CPUs are stopped, so wbinvd_on_all_cpus()
- * can't be used. In that case, wbinvd() is done on remote CPUs
- * via the NMI callback, and done for this CPU later during
- * SNP shutdown, so wbinvd_on_all_cpus() can be skipped.
- */
- if (!panic)
- wbinvd_on_all_cpus();
-
- __snp_free_firmware_pages(virt_to_page(sev_es_tmr),
- get_order(sev_es_tmr_size),
- true);
- sev_es_tmr = NULL;
- }
-
- if (sev_init_ex_buffer) {
- __snp_free_firmware_pages(virt_to_page(sev_init_ex_buffer),
- get_order(NV_LENGTH),
- true);
- sev_init_ex_buffer = NULL;
- }
+ __sev_release_firmware_buffers(panic);
__sev_snp_shutdown_locked(&error, panic);
}
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch v6 5/7] crypto: ccp - Allow SNP platform data to be queried after SNP INIT
[not found] <cover.1794531772.git.prsampat@amd.com>
` (2 preceding siblings ...)
2026-11-13 17:31 ` [Patch v6 4/7] crypto: ccp - Factor out the release of the SEV firmware buffers Pratik R. Sampat
@ 2026-11-13 17:31 ` Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 6/7] crypto: ccp - Register with fw_uploader and always fail Pratik R. Sampat
4 siblings, 0 replies; 5+ messages in thread
From: Pratik R. Sampat @ 2026-11-13 17:31 UTC (permalink / raw)
To: mcgrof, russ.weight, dakr, ashish.kalra, thomas.lendacky, herbert, davem
Cc: linux-crypto, linux-kernel, gregkh, rafael, chao.gao, aik, tycho,
nikunj, michael.roth, shansinha, prsampat
In preparation for refreshing the cached SNP platform status and feature
information after a successful firmware live update from
DOWNLOAD_FIRMWARE_EX, allow snp_get_platform_data() to be called while
the SNP firmware is in the INIT state.
Once SNP is initialized the firmware requires the output page of both
commands to be firmware-owned. sev->snp_plat_status cannot satisfy that
as it is embedded in struct sev_device, so stage the SNP_PLATFORM_STATUS
output through a dedicated page. Allocate the output pages of both
commands with __snp_alloc_firmware_pages(), which transitions the page
to firmware-owned when SNP is initialized, and release them with
__snp_free_firmware_pages(), which reclaims them before freeing.
__sev_do_snp_platform_status() is not used as it takes sev_cmd_mutex
itself.
Typically this was only ever exercised during initialization. However
DOWNLOAD_FIRMWARE_EX can change that. Live firmware update can race with
IOCTLs such as SEV_FACTORY_RESET which could cause operations performed
on incorrect cached platform states. Avoid this race by holding
sev_cmd_mutex across the whole of sev_get_api_version(), and split its
body out into __sev_get_api_version_locked() for callers that already
hold the mutex.
Co-developed-by: Tycho Andersen (AMD) <tycho@kernel.org>
Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
v5..v6:
* Since "crypto: ccp - Make usage of sev_cmd_mutex more granular" is
merged, __sev_do_snp_platform_status() takes a sev_cmd_mutex itself,
so calling it from snp_get_platform_data() with the mutex held would
deadlock. Instead, stage the SNP_PLATFORM_STATUS output through a page
from __snp_alloc_firmware_pages() and issue the command directly, the
same way as SNP_FEATURE_INFO.
* Introduce __sev_get_api_version_locked variant to be used when the
firmware is updated under a lock. - Sashiko
v4..v5:
No change
---
drivers/crypto/ccp/sev-dev.c | 40 ++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 888d960f68a9..d8a4da1a29d1 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -1265,15 +1265,20 @@ static int snp_get_platform_data(struct sev_device *sev, int *error)
struct page *page;
int rc;
- /*
- * This function is expected to be called before SNP is
- * initialized.
- */
- if (sev->snp_initialized)
- return -EINVAL;
+ lockdep_assert_held(&sev_cmd_mutex);
+
+ page = __snp_alloc_firmware_pages(GFP_KERNEL, 0, true);
+ if (!page)
+ return -ENOMEM;
+
+ buf.address = __psp_pa(page_address(page));
+ rc = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, error);
+ if (!rc)
+ memcpy(&sev->snp_plat_status, page_address(page),
+ sizeof(sev->snp_plat_status));
+
+ __snp_free_firmware_pages(page, 0, true);
- buf.address = __psp_pa(&sev->snp_plat_status);
- rc = sev_do_cmd(SEV_CMD_SNP_PLATFORM_STATUS, &buf, error);
if (rc) {
dev_err(sev->dev, "SNP PLATFORM_STATUS command failed, ret = %d, error = %#x\n",
rc, *error);
@@ -1297,7 +1302,7 @@ static int snp_get_platform_data(struct sev_device *sev, int *error)
* command to ensure structure is 8-byte aligned, and does not
* cross a page boundary.
*/
- page = alloc_page(GFP_KERNEL);
+ page = __snp_alloc_firmware_pages(GFP_KERNEL, 0, true);
if (!page)
return -ENOMEM;
@@ -1306,14 +1311,14 @@ static int snp_get_platform_data(struct sev_device *sev, int *error)
snp_feat_info.ecx_in = 0;
snp_feat_info.feature_info_paddr = __psp_pa(feat_info);
- rc = sev_do_cmd(SEV_CMD_SNP_FEATURE_INFO, &snp_feat_info, error);
+ rc = __sev_do_cmd_locked(SEV_CMD_SNP_FEATURE_INFO, &snp_feat_info, error);
if (!rc)
sev->snp_feat_info_0 = *feat_info;
else
dev_err(sev->dev, "SNP FEATURE_INFO command failed, ret = %d, error = %#x\n",
rc, *error);
- __free_page(page);
+ __snp_free_firmware_pages(page, 0, true);
return rc;
}
@@ -2115,12 +2120,14 @@ void *psp_copy_user_blob(u64 uaddr, u32 len)
}
EXPORT_SYMBOL_GPL(psp_copy_user_blob);
-static int sev_get_api_version(void)
+static int __sev_get_api_version_locked(void)
{
struct sev_device *sev = psp_master->sev_data;
struct sev_user_data_status status;
int error = 0, ret;
+ lockdep_assert_held(&sev_cmd_mutex);
+
/*
* Cache SNP platform status and SNP feature information
* if SNP is available.
@@ -2131,7 +2138,7 @@ static int sev_get_api_version(void)
return 1;
}
- ret = sev_platform_status(&status, &error);
+ ret = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, &status, &error);
if (ret) {
dev_err(sev->dev,
"SEV: failed to get status. Error: %#x\n", error);
@@ -2148,6 +2155,13 @@ static int sev_get_api_version(void)
return 0;
}
+static int sev_get_api_version(void)
+{
+ guard(mutex)(&sev_cmd_mutex);
+
+ return __sev_get_api_version_locked();
+}
+
static int sev_get_firmware(struct device *dev,
const struct firmware **firmware)
{
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Patch v6 6/7] crypto: ccp - Register with fw_uploader and always fail
[not found] <cover.1794531772.git.prsampat@amd.com>
` (3 preceding siblings ...)
2026-11-13 17:31 ` [Patch v6 5/7] crypto: ccp - Allow SNP platform data to be queried after SNP INIT Pratik R. Sampat
@ 2026-11-13 17:31 ` Pratik R. Sampat
4 siblings, 0 replies; 5+ messages in thread
From: Pratik R. Sampat @ 2026-11-13 17:31 UTC (permalink / raw)
To: mcgrof, russ.weight, dakr, ashish.kalra, thomas.lendacky, herbert, davem
Cc: linux-crypto, linux-kernel, gregkh, rafael, chao.gao, aik, tycho,
nikunj, michael.roth, shansinha, prsampat
In preparation for SEV-SNP DOWNLOAD_FIRMWARE_EX live firmware update
support, add an 'sev' firmware loader that always fails with EBUSY.
Co-developed-by: Tycho Andersen (AMD) <tycho@kernel.org>
Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
v5..v6:
No change
---
drivers/crypto/ccp/Kconfig | 2 +
drivers/crypto/ccp/sev-dev.c | 72 ++++++++++++++++++++++++++++++++++++
drivers/crypto/ccp/sev-dev.h | 2 +
3 files changed, 76 insertions(+)
diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig
index f16a0f611317..8544533a962a 100644
--- a/drivers/crypto/ccp/Kconfig
+++ b/drivers/crypto/ccp/Kconfig
@@ -40,6 +40,8 @@ config CRYPTO_DEV_SP_PSP
default y
depends on CRYPTO_DEV_CCP_DD && X86_64 && AMD_IOMMU
select PCI_TSM if PCI
+ select FW_LOADER
+ select FW_UPLOAD
help
Provide support for the AMD Platform Security Processor (PSP).
The PSP is a dedicated processor that provides support for key
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index d8a4da1a29d1..c5d9fe7e23d7 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -2253,6 +2253,72 @@ static int sev_update_firmware(struct device *dev)
return ret;
}
+static enum fw_upload_err sev_fw_upload_prepare(struct fw_upload *fw_upload,
+ const u8 *data, u32 size)
+{
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static enum fw_upload_err sev_fw_upload_write(struct fw_upload *fw_upload,
+ const u8 *data, u32 offset,
+ u32 size, u32 *written)
+{
+ return FW_UPLOAD_ERR_BUSY;
+}
+
+static enum fw_upload_err sev_fw_upload_poll_complete(struct fw_upload *fw_upload)
+{
+ return FW_UPLOAD_ERR_NONE;
+}
+
+static void sev_fw_upload_cancel(struct fw_upload *fw_upload)
+{
+ /* intentional no-op */
+}
+
+static const struct fw_upload_ops sev_fw_upload_ops = {
+ .prepare = sev_fw_upload_prepare,
+ .write = sev_fw_upload_write,
+ .poll_complete = sev_fw_upload_poll_complete,
+ .cancel = sev_fw_upload_cancel,
+};
+
+/* Serializes registration and unregistration of sev->fwl */
+static DEFINE_MUTEX(sev_fwl_lock);
+
+static void register_sev_fw_uploader(struct sev_device *sev)
+{
+ struct fw_upload *fwl;
+
+ guard(mutex)(&sev_fwl_lock);
+
+ /*
+ * The interface only drives DLFW_EX, which is an SNP command, so do not
+ * advertise it where SNP is unavailable or the interface already exists
+ */
+ if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP) || sev->fwl)
+ return;
+
+ fwl = firmware_upload_register(sev->dev, "sev", &sev_fw_upload_ops, sev);
+ if (IS_ERR(fwl)) {
+ dev_err(sev->dev, "SEV firmware upload registration failure: %ld\n", PTR_ERR(fwl));
+ return;
+ }
+
+ sev->fwl = fwl;
+}
+
+static void unregister_sev_fw_uploader(struct sev_device *sev)
+{
+ guard(mutex)(&sev_fwl_lock);
+
+ if (!sev->fwl)
+ return;
+
+ firmware_upload_unregister(sev->fwl);
+ sev->fwl = NULL;
+}
+
static int __sev_snp_shutdown_locked(int *error, bool panic)
{
struct psp_device *psp = psp_master;
@@ -3092,6 +3158,8 @@ void sev_dev_destroy(struct psp_device *psp)
if (!sev)
return;
+ unregister_sev_fw_uploader(sev);
+
sev_firmware_shutdown(sev);
if (sev->misc)
@@ -3155,6 +3223,8 @@ void sev_pci_init(void)
api_major, api_minor, build,
sev->api_major, sev->api_minor, sev->build);
+ register_sev_fw_uploader(sev);
+
return;
err:
@@ -3170,6 +3240,8 @@ void sev_pci_exit(void)
if (!sev)
return;
+ unregister_sev_fw_uploader(sev);
+
sev_firmware_shutdown(sev);
}
diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
index d5e596606def..7ec692e2147e 100644
--- a/drivers/crypto/ccp/sev-dev.h
+++ b/drivers/crypto/ccp/sev-dev.h
@@ -69,6 +69,8 @@ struct sev_device {
struct tsm_dev *tsmdev;
struct sev_tio_status *tio_status;
+
+ struct fw_upload *fwl;
};
int sev_dev_init(struct psp_device *psp);
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-13 17:52 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <cover.1794531772.git.prsampat@amd.com>
2026-11-13 17:31 ` [Patch v6 1/7] firmware_loader: Stop pinning modules on registration Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 2/7] firmware_loader: Stop pinning parent device per workqueue invocation Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 4/7] crypto: ccp - Factor out the release of the SEV firmware buffers Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 5/7] crypto: ccp - Allow SNP platform data to be queried after SNP INIT Pratik R. Sampat
2026-11-13 17:31 ` [Patch v6 6/7] crypto: ccp - Register with fw_uploader and always fail Pratik R. Sampat
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®