Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 38f5359354d4 ("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 5728d064190e ("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 <ttabi@nvidia.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patch.msgid.link/20251014174512.3172102-1-ttabi@nvidia.com

authored by

Timur Tabi and committed by
Dave Airlie
ebe75560 487df8b6

+12 -12
+12 -12
drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
··· 1695 1695 *pdevice = &pdev->device; 1696 1696 pdev->pdev = pci_dev; 1697 1697 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 + 1698 1710 ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev, 1699 1711 pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE : 1700 1712 pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ? ··· 1719 1707 1720 1708 if (ret) 1721 1709 return ret; 1722 - 1723 - /* Set DMA mask based on capabilities reported by the MMU subdev. */ 1724 - if (pdev->device.mmu && !pdev->device.pci->agp.bridge) 1725 - bits = pdev->device.mmu->dma_bits; 1726 - else 1727 - bits = 32; 1728 - 1729 - ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(bits)); 1730 - if (ret && bits != 32) { 1731 - dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32)); 1732 - pdev->device.mmu->dma_bits = 32; 1733 - } 1734 1710 1735 1711 return 0; 1736 1712 }