summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm/amd
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2020-11-19 08:53:15 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2020-11-19 08:53:15 +0000
commita59f3b5d0b981afecf95eae91949bc1bc84b7e1d (patch)
tree2ae1dd9a09bdbebd8933bf080ce30a9772e69df2 /sys/dev/pci/drm/amd
parent7040da37fbccc7dcc2518aa5c8749ac19d1a137d (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.c28
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);