[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250903203502.1155-2-linmag7@gmail.com>
Date: Wed, 3 Sep 2025 22:29:44 +0200
From: Magnus Lindholm <linmag7@...il.com>
To: linux-kernel@...r.kernel.org,
linux-alpha@...r.kernel.org,
hch@...radead.org,
macro@...am.me.uk,
glaubitz@...sik.fu-berlin.de,
mattst88@...il.com,
richard.henderson@...aro.org
Cc: Magnus Lindholm <linmag7@...il.com>
Subject: [PATCH 1/1] alpha: disable DAC for 32-bit PCI on tsunami
Disable DAC for 32-bit PCI cards on Tsunami.
This patch will effectively disable DAC for 32-bit PCI cards on
Tsunami based Alphas. This is done by setting bus_dma_limit to 32 bits
for devices that have no 64-bit memory BARs. Relevant functions in
pci_iommu.c are modified to take 'dev->bus_dma_limit' into
account.
Suggested-by: Maciej Rozycki <macro@...am.me.uk>
Signed-off-by: Magnus Lindholm <linmag7@...il.com>
---
arch/alpha/kernel/pci.c | 25 +++++++++++++++++++++++++
arch/alpha/kernel/pci_iommu.c | 18 ++++++++++++------
2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 8e9b4ac86b7e..5b1e4782294b 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -117,6 +117,31 @@ static void pcibios_fixup_final(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
+static void tsunami_dac_quirk(struct pci_dev *pdev)
+{
+ unsigned long flags;
+ int i;
+ bool mem64 = false;
+
+ /* If we're not on a Tsunami based system, do nothing */
+ if (hwrpb->sys_type != 34)
+ return;
+
+ for (i = 0; i < PCI_STD_RESOURCE_END + 1; i++) {
+ flags = pci_resource_flags(pdev, i);
+ if (flags & IORESOURCE_MEM)
+ mem64 |= flags & IORESOURCE_MEM_64;
+ }
+
+ /* Limit DMA to 32 bits effectively disabling DAC */
+ if (!mem64) {
+ pdev->dev.bus_dma_limit = DMA_BIT_MASK(32);
+ dev_dbg(&pdev->dev, "disabling DAC for device");
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tsunami_dac_quirk);
+
+
/* Just declaring that the power-of-ten prefixes are actually the
power-of-two ones doesn't make it true :) */
#define KB 1024
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index dc91de50f906..caf2407f80d3 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -208,7 +208,8 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
ok = 0;
/* The device has to be able to address our DAC bit. */
- if ((dac_offset & dev->dma_mask) != dac_offset)
+ if ((dac_offset & min_not_zero(mask,
+ dev->dev.bus_dma_limit)) != dac_offset)
ok = 0;
/* If both conditions above are met, we are fine. */
@@ -228,7 +229,8 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
int dac_allowed)
{
struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
- dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+ dma_addr_t max_dma = pdev ? min_not_zero(pdev->dma_mask,
+ pdev->dev.bus_dma_limit) : ISA_DMA_MASK;
struct pci_iommu_arena *arena;
long npages, dma_ofs, i;
unsigned long paddr;
@@ -332,7 +334,8 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
BUG_ON(dir == DMA_NONE);
- dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ dac_allowed = pdev ? pci_dac_dma_supported(pdev,
+ min_not_zero(pdev->dma_mask, pdev->dev.bus_dma_limit)) : 0;
return pci_map_single_1(pdev, (char *)page_address(page) + offset,
size, dac_allowed);
}
@@ -638,7 +641,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
BUG_ON(dir == DMA_NONE);
- dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ dac_allowed = dev ? pci_dac_dma_supported(pdev,
+ min_not_zero(pdev->dma_mask, pdev->dev.bus_dma_limit)) : 0;
/* Fast path single entry scatterlists. */
if (nents == 1) {
@@ -660,7 +664,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
/* Second, figure out where we're going to map things. */
if (alpha_mv.mv_pci_tbi) {
hose = pdev ? pdev->sysdata : pci_isa_hose;
- max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+ max_dma = pdev ? min_not_zero(pdev->dma_mask,
+ pdev->dev.bus_dma_limit) : ISA_DMA_MASK;
arena = hose->sg_pci;
if (!arena || arena->dma_base + arena->size - 1 > max_dma)
arena = hose->sg_isa;
@@ -725,7 +730,8 @@ static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
return;
hose = pdev ? pdev->sysdata : pci_isa_hose;
- max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+ max_dma = pdev ? min_not_zero(pdev->dma_mask,
+ pdev->dev.bus_dma_limit) : ISA_DMA_MASK;
arena = hose->sg_pci;
if (!arena || arena->dma_base + arena->size - 1 > max_dma)
arena = hose->sg_isa;
--
2.49.0
Powered by blists - more mailing lists