[PATCH v1] drivers: scsi: fix inaccurate block count reporting in scsi operations
neil.armstrong at linaro.org
neil.armstrong at linaro.org
Tue Jul 29 10:25:42 CEST 2025
On 28/07/2025 18:21, Balaji Selvanathan wrote:
> The 'blks' variable in scsi_read/write/erase functions is updated
> regardless of pass/fail of the scsi operation . If the scsi operation
> fails, 'blkcnt' is updated using an incorrect value of 'blks'. This
> wrong 'blkcnt' is returned to the caller and it assumes all blocks were
> processed correctly.
>
> Fix this by updating the 'blks' variable only if the scsi operation
> succeeds.
>
> Signed-off-by: Balaji Selvanathan <balaji.selvanathan at oss.qualcomm.com>
> Signed-off-by: Varadarajan Narayanan <quic_varada at quicinc.com>
> ---
> drivers/scsi/scsi.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
> index 78efed6b66a..05608399be1 100644
> --- a/drivers/scsi/scsi.c
> +++ b/drivers/scsi/scsi.c
> @@ -228,13 +228,11 @@ static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
> blocks = max_blks;
> scsi_setup_read_ext(pccb, start, blocks);
> start += max_blks;
> - blks -= max_blks;
> } else {
> pccb->datalen = block_dev->blksz * blks;
> blocks = blks;
> scsi_setup_read_ext(pccb, start, blocks);
> start += blks;
> - blks = 0;
> }
> debug("scsi_read_ext: startblk " LBAF
> ", blccnt " LBAF " buffer %lX\n",
> @@ -244,6 +242,7 @@ static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
> blkcnt -= blks;
> break;
> }
> + blks -= blocks;
> buf_addr += pccb->datalen;
> } while (blks != 0);
> debug("scsi_read_ext: end startblk " LBAF
> @@ -286,13 +285,11 @@ static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
> blocks = max_blks;
> scsi_setup_write_ext(pccb, start, blocks);
> start += max_blks;
> - blks -= max_blks;
> } else {
> pccb->datalen = block_dev->blksz * blks;
> blocks = blks;
> scsi_setup_write_ext(pccb, start, blocks);
> start += blks;
> - blks = 0;
> }
> debug("%s: startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
> __func__, start, blocks, buf_addr);
> @@ -301,6 +298,7 @@ static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
> blkcnt -= blks;
> break;
> }
> + blks -= blocks;
> buf_addr += pccb->datalen;
> } while (blks != 0);
>
> @@ -322,7 +320,7 @@ static ulong scsi_erase(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt)
> struct blk_desc *block_dev = dev_get_uclass_plat(dev);
> struct udevice *bdev = dev->parent;
> struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev);
> - lbaint_t start, blks, max_blks;
> + lbaint_t start, blks, max_blks, blocks;
> struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb;
>
> /* Setup device */
> @@ -339,19 +337,20 @@ static ulong scsi_erase(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt)
> __func__, block_dev->devnum, start, blks);
> do {
> if (blks > max_blks) {
> + blocks = max_blks;
> scsi_setup_erase_ext(pccb, start, max_blks);
> start += max_blks;
> - blks -= max_blks;
> } else {
> + blocks = blks;
> scsi_setup_erase_ext(pccb, start, blks);
> start += blks;
> - blks = 0;
> }
> if (scsi_exec(bdev, pccb)) {
> scsi_print_error(pccb);
> blkcnt -= blks;
> break;
> }
> + blks -= blocks;
> } while (blks != 0);
> return blkcnt;
> }
Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>
More information about the U-Boot
mailing list