[PATCH v1 4/7] ufs: rpmb: retry SECURITY PROTOCOL on power-on UNIT ATTENTION

Jorge Ramirez-Ortiz <[email protected]> Mon, 20 Jul 2026 10:51:44 +0200
Newsgroups de.denx.lists.u-boot
Message-ID <[email protected]>
The RPMB Well-Known LUN is untouched during boot, so its first SECURITY
PROTOCOL command after power-on is answered with a CHECK CONDITION
carrying a power-on UNIT ATTENTION, which ufs_scsi_exec() surfaces as
-EINVAL. U-Boot has no SCSI mid-layer to auto-retry, so the first RPMB
frame OP-TEE sends (the write-counter read that verifies the key) was
lost. Reporting the UNIT ATTENTION clears it, so retry the command once.

Signed-off-by: Jorge Ramirez-Ortiz <[email protected]>
---
 drivers/ufs/ufs-rpmb.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/ufs-rpmb.c b/drivers/ufs/ufs-rpmb.c
index 7919162ddae..1434161682b 100644
--- a/drivers/ufs/ufs-rpmb.c
+++ b/drivers/ufs/ufs-rpmb.c
@@ -19,6 +19,8 @@
 
 #define RPMB_FRAME_REQ_OFFSET	510
 
+#define UFS_RPMB_UA_RETRIES	3
+
 static u16 rpmb_frame_request(const void *frame)
 {
 	const u8 *p = frame;
@@ -34,6 +36,8 @@ static int ufs_rpmb_secprot(struct udevice *scsi_dev, unsigned int region,
 	struct scsi_cmd pccb;
 	u32 len = nframes * RPMB_FRAME_SIZE;
 	u16 spsp = (region << 8) | UFS_RPMB_SEC_PROTOCOL_ID;
+	int retries;
+	int ret = 0;
 
 	memset(&pccb, 0, sizeof(pccb));
 	pccb.lun = UFS_UPIU_RPMB_WLUN;
@@ -54,7 +58,13 @@ static int ufs_rpmb_secprot(struct udevice *scsi_dev, unsigned int region,
 	pccb.datalen = len;
 	pccb.dma_dir = dir;
 
-	return scsi_exec(scsi_dev, &pccb);
+	for (retries = UFS_RPMB_UA_RETRIES; retries > 0; retries--) {
+		ret = scsi_exec(scsi_dev, &pccb);
+		if (!ret)
+			break;
+	}
+
+	return ret;
 }
 
 static int ufs_rpmb_send(struct udevice *scsi_dev, unsigned int region,
-- 
2.54.0