[Devel] [PATCH rh7 v2 3/3] scsi: mpt3sas: Don't widen coherent DMA mask after RDPQ allocation

Konstantin Khorenko khorenko at virtuozzo.com
Tue Apr 21 17:23:44 MSK 2026


The mpt3sas firmware uses a "shared upper-32-bit base + 32-bit offset"
addressing model for several buffer types.  In the IOCInit message:

  - SenseBufferAddressHigh is a single 32-bit value for ALL sense buffers
  - SystemReplyAddressHigh is a single 32-bit value for ALL reply buffers

This means every coherent buffer pool (sense, reply, reply_free, chains,
PCIe SGL, RDPQ) must reside entirely within a single 4 GB region -
otherwise the firmware computes wrong addresses and corrupts memory,
causes double bio completions, etc.

The problem:

  _base_config_dma_addressing() correctly sets the coherent DMA mask to
  32-bit on the first call (when ioc->dma_mask == 0).  RDPQ pools are
  then allocated within that 32-bit space - fine.

  But immediately after RDPQ allocation, _base_change_consistent_dma_mask()
  widens the coherent mask back to 63/64-bit:

    if (ioc->dma_mask > 32)
        _base_change_consistent_dma_mask(ioc, ioc->pdev);
            -> pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(63))

  All subsequent coherent allocations - request pool, PCIe SGL pool,
  chain buffers, sense buffers, reply pool, reply_free pool - now use
  63/64-bit coherent DMA and can land above 4 GB or cross a 4 GB
  boundary.

  The existing is_MSB_are_same() check for the sense pool is insufficient:
  it only covers sense buffers (not reply, chain, etc.) and checks the
  virtual address instead of the DMA address (a separate bug).

The proper upstream fix is a series of 15 patches that add per-pool
boundary checks with allocate-check-retry logic:

  - scsi: mpt3sas: Rename function name is_MSB_are_same
  - scsi: mpt3sas: Don't change the DMA coherent mask after allocations
  - scsi: mpt3sas: Separate out RDPQ allocation to new function
  - scsi: mpt3sas: Handle RDPQ DMA allocation in same 4G region
  - scsi: mpt3sas: Fix ReplyPostFree pool allocation
  - scsi: mpt3sas: Force PCIe scatterlist allocations to be within same 4 GB region
  - scsi: mpt3sas: Force chain buffer allocations to be within same 4 GB region
  - scsi: mpt3sas: Force sense buffer allocations to be within same 4 GB region
  - scsi: mpt3sas: Force reply buffer allocations to be within same 4 GB region
  - scsi: mpt3sas: Force reply post buffer allocations to be within same 4 GB region
  - scsi: mpt3sas: Force reply post array allocations to be within same 4 GB region
  - scsi: mpt3sas: Fix incorrect 4GB boundary check
  - scsi: mpt3sas: Don't change DMA mask while reallocating pools
  - scsi: mpt3sas: re-do lost mpt3sas DMA mask fix
  - scsi: mpt3sas: Remove usage of dma_get_required_mask() API

That is a very intrusive backport (488 insertions, 284 deletions) with
significant conflict resolution due to the 3.10 kernel base.

This patch takes a simpler approach: remove the
_base_change_consistent_dma_mask() call that widens the coherent mask
after RDPQ allocation.  Since _base_config_dma_addressing() already
sets coherent to 32-bit on the first call, simply not widening it keeps
ALL coherent allocations below 4 GB for the entire driver lifetime.
Streaming DMA (scatter-gather for data I/O) remains 63/64-bit, so
there is no performance impact on the data path.

Pros:
  - Minimal, obviously correct change (19 lines removed, 0 added)
  - Eliminates the entire class of 4 GB boundary bugs at once
  - No risk of regression from a large, conflict-heavy backport
  - Streaming DMA stays wide - no data path performance impact

Cons:
  - Coherent allocations are restricted to the first 4 GB of DMA
    address space.  On systems with very heavy 32-bit DMA pressure
    from multiple devices this could theoretically make allocation
    harder.  In practice mpt3sas coherent pools total a few MB -
    negligible for any real server.

https://virtuozzo.atlassian.net/browse/PSBM-161670
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 19 -------------------
 1 file changed, 19 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 054e3c22f1afa..7404d8ee61ba6 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2747,17 +2747,6 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
 	return 0;
 }
 
-static int
-_base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc,
-				      struct pci_dev *pdev)
-{
-	if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ioc->dma_mask))) {
-		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))
-			return -ENODEV;
-	}
-	return 0;
-}
-
 /**
  * _base_check_enable_msix - checks MSIX capabable.
  * @ioc: per adapter object
@@ -5046,14 +5035,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
 		total_sz += sz;
 	} while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count));
 
-	if (ioc->dma_mask > 32) {
-		if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) {
-			ioc_warn(ioc, "no suitable consistent DMA mask for %s\n",
-				 pci_name(ioc->pdev));
-			goto out;
-		}
-	}
-
 	ioc->scsiio_depth = ioc->hba_queue_depth -
 	    ioc->hi_priority_depth - ioc->internal_depth;
 
-- 
2.24.3



More information about the Devel mailing list