]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
drivers: scsi: fix inaccurate block count reporting in scsi operations
authorBalaji Selvanathan <balaji.selvanathan@oss.qualcomm.com>
Mon, 28 Jul 2025 16:21:05 +0000 (21:51 +0530)
committerTom Rini <trini@konsulko.com>
Thu, 7 Aug 2025 17:14:23 +0000 (11:14 -0600)
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@oss.qualcomm.com>
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
drivers/scsi/scsi.c

index 78efed6b66ac0f62292e192b413d9262b787d30a..05608399be13b05de1d1cc3c12db8d533e458452 100644 (file)
@@ -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;
 }