Download raw body.
radeondrm: fix CAFEDEAD failure during boot for old Radeons
> Date: Thu, 8 Oct 2026 19:44:09 +1100
> From: Jonathan Gray <jsg@jsg.id.au>
>
> On Thu, Oct 08, 2026 at 12:24:06AM -0600, Ted Bullock wrote:
> > Hello,
> >
> > I think this is a plausible fix for a very longstanding bug with
> > regards to older Radeon GPUs on a variety of platforms.
> >
> > The telltale dmesg line looks something like
> > [drm] *ERROR* radeon: ring test failed (scratch(0x15E4)=0xCAFEDEAD)
> >
> > https://marc.info/?l=openbsd-bugs&m=162447131102854
> > https://marc.info/?l=openbsd-bugs&m=177938265735653
> > https://marc.info/?l=openbsd-misc&m=155873575216626&w=2
> >
> > The call to the stubbed linux dma selection logic in
> > dma_addressing_limited() has been removed (always false), but according
> > to radeon_device.c, the older Radeon chips should be using the driver's
> > 32 bit DMA logic.
> >
> > /* set DMA mask.
> > * PCIE - can handle 40-bits.
> > * IGP - can handle 40-bits
> > * AGP - generally dma32 is safest
> > * PCI - dma32 for legacy pci gart, 40 bits on newer asics
> > */
> > dma_bits = 40;
> > if (rdev->flags & RADEON_IS_AGP)
> > dma_bits = 32;
> > if ((rdev->flags & RADEON_IS_PCI) &&
> > (rdev->family <= CHIP_RS740))
> > dma_bits = 32;
> > #ifdef CONFIG_PPC64
> > if (rdev->family == CHIP_CEDAR)
> > dma_bits = 32;
> > #endif
> >
> > I have no idea about the PPC64 flag, nor do I have one of those fancy
> > Talos machines to play around with. Since AGP is disabled by default
> > for this driver, I'm speculating we can just use the PCI logic in lieu
> > of the dma_addressing_limited() function.
> >
> > I can confirm that my Sun Blade 100 with the XVR-100 finally boots
> > without the CAFEDEAD warning in dmesg, and it also lets me enable
> > accelerated X.
> >
> > Ted
>
> The Linux documentation for dma_addressing_limited() describes it as a
> test against the amount of physical memory.
>
> The Linux function arguments are awkward to derive other types from,
> so here is a radeon specific alternative.
>
> Index: sys/dev/pci/drm/radeon/radeon.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon.h,v
> diff -u -p -r1.33 radeon.h
> --- sys/dev/pci/drm/radeon/radeon.h 9 Mar 2026 23:58:03 -0000 1.33
> +++ sys/dev/pci/drm/radeon/radeon.h 8 Oct 2026 08:22:09 -0000
> @@ -2326,6 +2326,7 @@ struct radeon_device {
> bus_space_tag_t memt;
> bus_dma_tag_t dmat;
> void *irqh;
> + bool dma_limited;
>
> void (*switchcb)(void *, int, int);
> void *switchcbarg;
> Index: sys/dev/pci/drm/radeon/radeon_device.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon_device.c,v
> diff -u -p -r1.34 radeon_device.c
> --- sys/dev/pci/drm/radeon/radeon_device.c 5 Oct 2026 08:14:58 -0000 1.34
> +++ sys/dev/pci/drm/radeon/radeon_device.c 8 Oct 2026 08:25:35 -0000
> @@ -1392,6 +1392,9 @@ int radeon_device_init(struct radeon_dev
> }
> rdev->need_swiotlb = drm_need_swiotlb(dma_bits);
>
> + if (ptoa(physmem) > (1ULL << dma_bits))
> + rdev->dma_limited = true;
> +
This can't be correct. The physmem variable contains the amount of
physical memory, not the address of the highest bit of RAM.
To do this correctly, you'd need to do something like what we do in
bus_dma_init() where you set constraint.ucr_low based on dma_bits and
count the number of high pages.
However, this check should only matter if there is no IOMMU. But
sparc64 does have an IOMMU. So what's going on here?
Ultimately the flag ends up being passed to ttm_pool_init(). Without
the flag being set bus_dma memory allocations will be done with the
BUS_DMA_64BIT flag set. But on sparc64 this means the IOMMU gets
bypassed and DVAs have the high bit set, even if the memory itself is
below the 4G limit. This means that on sparc64 we always need to set
the dma_limited flag unless full 64-bit addresses are supported.
> /* Registers mapping */
> /* TODO: block userspace mapping of io register */
> mtx_init(&rdev->mmio_idx_lock, IPL_TTY);
> Index: sys/dev/pci/drm/radeon/radeon_ttm.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/drm/radeon/radeon_ttm.c,v
> diff -u -p -r1.28 radeon_ttm.c
> --- sys/dev/pci/drm/radeon/radeon_ttm.c 9 Mar 2026 23:58:03 -0000 1.28
> +++ sys/dev/pci/drm/radeon/radeon_ttm.c 8 Oct 2026 08:29:30 -0000
> @@ -717,7 +717,7 @@ int radeon_ttm_init(struct radeon_device
> /*rdev_to_drm(rdev)->anon_inode->i_mapping*/NULL,
> rdev_to_drm(rdev)->vma_offset_manager,
> rdev->need_swiotlb,
> - dma_addressing_limited(&rdev->pdev->dev));
> + rdev->dma_limited);
> #endif
> if (r) {
> DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
>
>
radeondrm: fix CAFEDEAD failure during boot for old Radeons