[PATCH] fpga: altera-cvp: Handle truncated bitstream with padding buffer

From: muhammad . nazim . amirul . nazle . asmade

Date: Fri Jun 19 2026 - 00:11:43 EST


From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@xxxxxxxxxx>

The AIB CvP firmware requires a minimum transfer size of 4096 bytes.
When a bitstream smaller than this is sent, the firmware DMA engine
stalls waiting for the remaining data, causing a hang.

Allocate a 4096-byte send_buf at probe time and copy host data into
it before each block transfer, ensuring the full block size is always
sent regardless of the actual data length. Also improve error
detection in write_complete() by checking VSE_CVP_STATUS_CFG_ERR
instead of VSE_UNCOR_ERR_CVP_CFG_ERR to catch truncated or
mismatched bitstream errors.

Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@xxxxxxxxxx>
---
drivers/fpga/altera-cvp.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c
index 44badfd11e1b..36557c5a0c3f 100644
--- a/drivers/fpga/altera-cvp.c
+++ b/drivers/fpga/altera-cvp.c
@@ -77,6 +77,7 @@ struct altera_cvp_conf {
u8 numclks;
u32 sent_packets;
u32 vsec_offset;
+ u8 *send_buf;
const struct cvp_priv *priv;
};

@@ -449,7 +450,9 @@ static int altera_cvp_write(struct fpga_manager *mgr, const char *buf,
}

len = min(conf->priv->block_size, remaining);
- altera_cvp_send_block(conf, data, len);
+ memcpy(conf->send_buf, data, len);
+ altera_cvp_send_block(conf, (const u32 *)conf->send_buf,
+ conf->priv->block_size);
data += len / sizeof(u32);
done += len;
remaining -= len;
@@ -488,10 +491,10 @@ static int altera_cvp_write_complete(struct fpga_manager *mgr,
if (ret)
return ret;

- /* STEP 16 - check CVP_CONFIG_ERROR_LATCHED bit */
- altera_read_config_dword(conf, VSE_UNCOR_ERR_STATUS, &val);
- if (val & VSE_UNCOR_ERR_CVP_CFG_ERR) {
- dev_err(&mgr->dev, "detected CVP_CONFIG_ERROR_LATCHED!\n");
+ /* STEP 16 - check CVP_CONFIG_ERROR bit */
+ ret = altera_read_config_dword(conf, VSE_CVP_STATUS, &val);
+ if (ret || (val & VSE_CVP_STATUS_CFG_ERR)) {
+ dev_err(&mgr->dev, "CVP_CONFIG_ERROR!\n");
return -EPROTO;
}

@@ -650,6 +653,11 @@ static int altera_cvp_probe(struct pci_dev *pdev,

pci_set_drvdata(pdev, mgr);

+ conf->send_buf = devm_kzalloc(&pdev->dev, conf->priv->block_size, GFP_KERNEL);
+ if (!conf->send_buf) {
+ ret = -ENOMEM;
+ goto err_unmap;
+ }
return 0;

err_unmap:
--
2.43.7