[PATCH v3 2/2] fpga: altera-cvp: Retry teardown and reset CVP state on failure
From: muhammad . nazim . amirul . nazle . asmade
Date: Wed Sep 23 2026 - 01:32:51 EST
From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@xxxxxxxxxx>
The driver polls CFG_RDY for 0 as notification that the endpoint has
finished teardown and a new session can start safely. After a bad
bitstream that poll can time out: CFG_RDY may stay stuck when
HIP_CLK_SEL=0 if the device has already left usermode before the poll.
Retrying teardown alone is not enough. Exit CvP mode and switch the HIP
clock that feeds CFG_RDY so CVP_STATUS becomes responsive again, then
try the teardown once more.
Introduce altera_cvp_recovery() to wrap this cleanup and single retry.
Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@xxxxxxxxxx>
---
drivers/fpga/altera-cvp.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c
index 559191180825..549e0ce1545f 100644
--- a/drivers/fpga/altera-cvp.c
+++ b/drivers/fpga/altera-cvp.c
@@ -316,7 +316,29 @@ static int altera_cvp_teardown(struct fpga_manager *mgr,
ret = altera_cvp_wait_status(conf, VSE_CVP_STATUS_CFG_RDY, 0,
conf->priv->poll_time_us);
if (ret)
- dev_err(&mgr->dev, "CFG_RDY == 0 timeout\n");
+ dev_warn(&mgr->dev, "CFG_RDY == 0 timeout\n");
+
+ return ret;
+}
+
+static int altera_cvp_recovery(struct fpga_manager *mgr,
+ struct fpga_image_info *info)
+{
+ struct altera_cvp_conf *conf = mgr->priv;
+ int ret;
+
+ ret = altera_cvp_teardown(mgr, info);
+ if (ret) {
+ /*
+ * CVP_STATUS may get stuck if the device left user mode
+ * before the poll. Exit CvP mode to switch back the clock
+ * feeding CVP_STATUS, then try the teardown again.
+ */
+ altera_cvp_disable_cvp_mode(conf);
+ ret = altera_cvp_teardown(mgr, info);
+ if (ret)
+ dev_err(&mgr->dev, "Tear-down failed\n");
+ }
return ret;
}
@@ -353,7 +375,7 @@ static int altera_cvp_write_init(struct fpga_manager *mgr,
if (val & VSE_CVP_STATUS_CFG_RDY) {
dev_warn(&mgr->dev, "CvP already started, tear down first\n");
- ret = altera_cvp_teardown(mgr, info);
+ ret = altera_cvp_recovery(mgr, info);
if (ret)
return ret;
}
@@ -494,7 +516,7 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr,
u32 mask, val;
int ret;
- ret = altera_cvp_teardown(mgr, info);
+ ret = altera_cvp_recovery(mgr, info);
if (ret)
return ret;
--
2.43.7