Skip to content

Commit ebe7556

Browse files
ttabiairlied
authored andcommitted
drm/nouveau: set DMA mask before creating the flush page
Set the DMA mask before calling nvkm_device_ctor(), so that when the flush page is created in nvkm_fb_ctor(), the allocation will not fail if the page is outside of DMA address space, which can easily happen if IOMMU is disable. In such situations, you will get an error like this: nouveau 0000:65:00.0: DMA addr 0x0000000107c56000+4096 overflow (mask ffffffff, bus limit 0). Commit 38f5359 ("rm/nouveau/pci: set streaming DMA mask early") set the mask after calling nvkm_device_ctor(), but back then there was no flush page being created, which might explain why the mask wasn't set earlier. Flush page allocation was added in commit 5728d06 ("drm/nouveau/fb: handle sysmem flush page from common code"). nvkm_fb_ctor() calls alloc_page(), which can allocate a page anywhere in system memory, but then calls dma_map_page() on that page. But since the DMA mask is still set to 32, the map can fail if the page is allocated above 4GB. This is easy to reproduce on systems with a lot of memory and IOMMU disabled. An alternative approach would be to force the allocation of the flush page to low memory, by specifying __GFP_DMA32. However, this would always allocate the page in low memory, even though the hardware can access high memory. Signed-off-by: Timur Tabi <[email protected]> Reviewed-by: Dave Airlie <[email protected]> Signed-off-by: Dave Airlie <[email protected]> Link: https://patch.msgid.link/[email protected]
1 parent 487df8b commit ebe7556

File tree

1 file changed

+12
-12
lines changed
  • drivers/gpu/drm/nouveau/nvkm/engine/device

1 file changed

+12
-12
lines changed

drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,18 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
16951695
*pdevice = &pdev->device;
16961696
pdev->pdev = pci_dev;
16971697

1698+
/* Set DMA mask based on capabilities reported by the MMU subdev. */
1699+
if (pdev->device.mmu && !pdev->device.pci->agp.bridge)
1700+
bits = pdev->device.mmu->dma_bits;
1701+
else
1702+
bits = 32;
1703+
1704+
ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(bits));
1705+
if (ret && bits != 32) {
1706+
dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
1707+
pdev->device.mmu->dma_bits = 32;
1708+
}
1709+
16981710
ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev,
16991711
pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE :
17001712
pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ?
@@ -1708,17 +1720,5 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
17081720
if (ret)
17091721
return ret;
17101722

1711-
/* Set DMA mask based on capabilities reported by the MMU subdev. */
1712-
if (pdev->device.mmu && !pdev->device.pci->agp.bridge)
1713-
bits = pdev->device.mmu->dma_bits;
1714-
else
1715-
bits = 32;
1716-
1717-
ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(bits));
1718-
if (ret && bits != 32) {
1719-
dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
1720-
pdev->device.mmu->dma_bits = 32;
1721-
}
1722-
17231723
return 0;
17241724
}

0 commit comments

Comments
 (0)