[PATCH v2 1/2] scsi: ufs: core: unregister RPMB devices before their parent

From: shao.mingyin

Date: Tue Nov 03 2026 - 14:05:07 EST


ufs_rpmb_probe() registers a child device whose parent is the UFS RPMB
device and then registers an rpmb_dev on top of it. device_add() takes a
reference on the parent, and rpmb_dev_unregister() is only called from
ufs_rpmb_device_release(), i.e. when the parent's reference count drops to
zero. ufs_rpmb_remove() and the probe error path call
device_unregister(&ufs_rpmb->dev) directly, which leaves the reference
held by the rpmb_dev and the release callback never runs: the RPMB child
stays registered while the devm-allocated ufs_rpmb is freed together with
the host.

Unregister the rpmb_dev first, as mmc_blk_remove_rpmb_part() does, and let
the release callback tolerate an already unregistered device.

Fixes: b06b8c421485 ("scsi: ufs: core: Add OP-TEE based RPMB driver for UFS devices")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
v2: rebased onto v7.4-rc1 (for-next); no code changes.

drivers/ufs/core/ufs-rpmb.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/ufs/core/ufs-rpmb.c b/drivers/ufs/core/ufs-rpmb.c
index 65f2d71cf073..1ed57d50c3ff 100644
--- a/drivers/ufs/core/ufs-rpmb.c
+++ b/drivers/ufs/core/ufs-rpmb.c
@@ -149,11 +149,19 @@ static int ufs_rpmb_route_frames(struct device *dev, u8 *req, unsigned int req_l
return ret;
}

+static void ufs_rpmb_unregister_device(struct ufs_rpmb_dev *ufs_rpmb)
+{
+ rpmb_dev_unregister(ufs_rpmb->rdev);
+ ufs_rpmb->rdev = NULL;
+ device_unregister(&ufs_rpmb->dev);
+}
+
static void ufs_rpmb_device_release(struct device *dev)
{
struct ufs_rpmb_dev *ufs_rpmb = dev_get_drvdata(dev);

- rpmb_dev_unregister(ufs_rpmb->rdev);
+ if (ufs_rpmb->rdev)
+ rpmb_dev_unregister(ufs_rpmb->rdev);
}

/* UFS RPMB device registration */
@@ -250,7 +258,7 @@ int ufs_rpmb_probe(struct ufs_hba *hba)
kfree(cid);
list_for_each_entry_safe(it, tmp, &hba->rpmbs, node) {
list_del(&it->node);
- device_unregister(&it->dev);
+ ufs_rpmb_unregister_device(it);
}

return ret;
@@ -270,7 +278,7 @@ void ufs_rpmb_remove(struct ufs_hba *hba)
/* Remove from list first */
list_del(&ufs_rpmb->node);
/* Unregister device */
- device_unregister(&ufs_rpmb->dev);
+ ufs_rpmb_unregister_device(ufs_rpmb);
}

dev_info(hba->dev, "All UFS RPMB devices unregistered\n");