[PATCH v9 7/9] scsi: mvumi: free the internal command buffer by what was allocated
From: Yehyeong Lee
Date: Thu Oct 15 2026 - 00:53:55 EST
mvumi_internal_cmd_sgl() allocates the internal command's data buffer
with dma_alloc_coherent() and then publishes the address and the length
to the controller by writing them into the command frame: lower_32_bits()
in baseaddr_l, upper_32_bits() in baseaddr_h and the length through
sgd_setsz().
mvumi_delete_internal_cmd() did not keep any of that. It read the frame
back to work out what to free -- sg_counts to decide whether there was a
buffer at all, sgd_getsz() for the length, baseaddr_h and baseaddr_l for
the address -- and handed the three results to dma_free_coherent().
That rebuild does not say what it means to say:
phy_addr = (dma_addr_t) m_sg->baseaddr_l |
(dma_addr_t) ((m_sg->baseaddr_h << 16) << 16);
baseaddr_h is a u32, so both shifts happen in 32-bit arithmetic and the
term is always zero; the upper half is never put back. That is not
visible today, because the driver never raises this device's coherent DMA
mask above the 32 bits pci_device_add() gives it -- dma_set_mask() moves
only the streaming mask -- so dma_alloc_coherent() cannot hand out an
address with an upper half to lose. It is still not the address the
expression is written to produce.
Rather than widen the shift, stop reading the frame back. The driver
already has every value it needs: keep the address and the length in
struct mvumi_cmd next to the virtual address it keeps there now, free by
those, and decide whether there is a buffer from data_buf instead of from
sg_counts.
sgd_getsz() and GET_COMPACT_SGD_SIZE() had no other caller, so they go
too. sgd_setsz(), which writes the field, is unchanged.
Fixes: f0c568a478f0 ("[SCSI] mvumi: Add Marvell UMI driver")
Signed-off-by: Yehyeong Lee <yhlee@xxxxxxxxxxxxxxxxxx>
---
drivers/scsi/mvumi.c | 19 +++++--------------
drivers/scsi/mvumi.h | 12 ++----------
2 files changed, 7 insertions(+), 24 deletions(-)
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index 2410d2aa147d9..133e53bc2cb37 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -238,6 +238,8 @@ static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0];
cmd->frame->sg_counts = 1;
cmd->data_buf = virt_addr;
+ cmd->data_buf_phys = phy_addr;
+ cmd->data_buf_size = size;
m_sg->baseaddr_l = cpu_to_le32(lower_32_bits(phy_addr));
m_sg->baseaddr_h = cpu_to_le32(upper_32_bits(phy_addr));
@@ -286,21 +288,10 @@ static struct mvumi_cmd *mvumi_create_internal_cmd(struct mvumi_hba *mhba,
static void mvumi_delete_internal_cmd(struct mvumi_hba *mhba,
struct mvumi_cmd *cmd)
{
- struct mvumi_sgl *m_sg;
- unsigned int size;
- dma_addr_t phy_addr;
-
if (cmd && cmd->frame) {
- if (cmd->frame->sg_counts) {
- m_sg = (struct mvumi_sgl *) &cmd->frame->payload[0];
- sgd_getsz(mhba, m_sg, size);
-
- phy_addr = (dma_addr_t) m_sg->baseaddr_l |
- (dma_addr_t) ((m_sg->baseaddr_h << 16) << 16);
-
- dma_free_coherent(&mhba->pdev->dev, size, cmd->data_buf,
- phy_addr);
- }
+ if (cmd->data_buf)
+ dma_free_coherent(&mhba->pdev->dev, cmd->data_buf_size,
+ cmd->data_buf, cmd->data_buf_phys);
dma_free_coherent(&mhba->pdev->dev, mhba->ib_max_size,
cmd->frame, cmd->frame_phys);
kfree(cmd);
diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h
index d20eea2b61a31..3fc76addbf304 100644
--- a/drivers/scsi/mvumi.h
+++ b/drivers/scsi/mvumi.h
@@ -189,20 +189,10 @@ struct mvumi_compact_sgl {
u32 flags;
};
-#define GET_COMPACT_SGD_SIZE(sgd) \
- ((((struct mvumi_compact_sgl *)(sgd))->flags) & 0x3FFFFFL)
-
#define SET_COMPACT_SGD_SIZE(sgd, sz) do { \
(((struct mvumi_compact_sgl *)(sgd))->flags) &= ~0x3FFFFFL; \
(((struct mvumi_compact_sgl *)(sgd))->flags) |= (sz); \
} while (0)
-#define sgd_getsz(_mhba, sgd, sz) do { \
- if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
- (sz) = GET_COMPACT_SGD_SIZE(sgd); \
- else \
- (sz) = (sgd)->size; \
-} while (0)
-
#define sgd_setsz(_mhba, sgd, sz) do { \
if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
SET_COMPACT_SGD_SIZE(sgd, sz); \
@@ -259,6 +249,8 @@ struct mvumi_cmd {
struct scsi_cmnd *scmd;
atomic_t sync_cmd;
void *data_buf;
+ dma_addr_t data_buf_phys;
+ unsigned int data_buf_size;
unsigned short request_id;
unsigned char cmd_status;
};
--
2.43.0