diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-11-19 08:53:15 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-11-19 08:53:15 +0000 |
commit | a59f3b5d0b981afecf95eae91949bc1bc84b7e1d (patch) | |
tree | 2ae1dd9a09bdbebd8933bf080ce30a9772e69df2 /sys/dev/pci/drm/amd | |
parent | 7040da37fbccc7dcc2518aa5c8749ac19d1a137d (diff) |
The conversion of the IO BAR access did not completely mirror the
behaviour of Linux' implementation: arm64's bus space operations
have no barriers, so while Linux' iowrite32/ioread32 explicitly
contain barriers, using bus space read/write is not enough on arm64.
Add read barriers after a read to make sure that all reads have
completed before the following reads. Add write barriers before a
write to make sure all previous writes have completed before that
write. This fixes panics on the HoneyComb LX2K with amdgpu(4).
ok kettenis@
Diffstat (limited to 'sys/dev/pci/drm/amd')
-rw-r--r-- | sys/dev/pci/drm/amd/amdgpu/amdgpu_device.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/sys/dev/pci/drm/amd/amdgpu/amdgpu_device.c b/sys/dev/pci/drm/amd/amdgpu/amdgpu_device.c index b3e7d8da763..45eff483e86 100644 --- a/sys/dev/pci/drm/amd/amdgpu/amdgpu_device.c +++ b/sys/dev/pci/drm/amd/amdgpu/amdgpu_device.c @@ -378,14 +378,24 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, uint32_t reg, uint32_t */ u32 amdgpu_io_rreg(struct amdgpu_device *adev, u32 reg) { - if ((reg * 4) < adev->rio_mem_size) - return bus_space_read_4(adev->rio_mem_bst, adev->rio_mem_bsh, reg); - else { + u32 val; + + if ((reg * 4) < adev->rio_mem_size) { + val = bus_space_read_4(adev->rio_mem_bst, adev->rio_mem_bsh, reg); + bus_space_barrier(adev->rio_mem_bst, adev->rio_mem_bsh, 0, + adev->rio_mem_size, BUS_SPACE_BARRIER_READ); + } else { + bus_space_barrier(adev->rio_mem_bst, adev->rio_mem_bsh, 0, + adev->rio_mem_size, BUS_SPACE_BARRIER_WRITE); bus_space_write_4(adev->rio_mem_bst, adev->rio_mem_bsh, mmMM_INDEX * 4, reg * 4); - return bus_space_read_4(adev->rio_mem_bst, adev->rio_mem_bsh, + val = bus_space_read_4(adev->rio_mem_bst, adev->rio_mem_bsh, mmMM_INDEX * 4); + bus_space_barrier(adev->rio_mem_bst, adev->rio_mem_bsh, 0, + adev->rio_mem_size, BUS_SPACE_BARRIER_READ); } + + return val; } /** @@ -403,12 +413,18 @@ void amdgpu_io_wreg(struct amdgpu_device *adev, u32 reg, u32 v) adev->last_mm_index = v; } - if ((reg * 4) < adev->rio_mem_size) + if ((reg * 4) < adev->rio_mem_size) { + bus_space_barrier(adev->rio_mem_bst, adev->rio_mem_bsh, 0, + adev->rio_mem_size, BUS_SPACE_BARRIER_WRITE); bus_space_write_4(adev->rio_mem_bst, adev->rio_mem_bsh, reg * 4, v); - else { + } else { + bus_space_barrier(adev->rio_mem_bst, adev->rio_mem_bsh, 0, + adev->rio_mem_size, BUS_SPACE_BARRIER_WRITE); bus_space_write_4(adev->rio_mem_bst, adev->rio_mem_bsh, mmMM_INDEX * 4, reg * 4); + bus_space_barrier(adev->rio_mem_bst, adev->rio_mem_bsh, 0, + adev->rio_mem_size, BUS_SPACE_BARRIER_WRITE); bus_space_write_4(adev->rio_mem_bst, adev->rio_mem_bsh, mmMM_DATA * 4, v); |