1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
From 11ad77a401121948f441d1559cf9695361a7fab5 Mon Sep 17 00:00:00 2001
From: Felix Kuehling <Felix.Kuehling@amd.com>
Date: Thu, 30 Jun 2016 16:41:32 -0400
Subject: [PATCH 1465/4131] drm/amdgpu: Add support for resuming SDMA queues
w/o HWS
Save wptr in hqd_sdma_destroy, restore it in hqd_sdma_load. Also
read updated wptr from user mode when resuming an SDMA queue.
Change-Id: Iea14fd8a3b4563c52c789d42fbad6d56a51684f7
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 25 ++++++++++++++++++++--
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 26 ++++++++++++++++++++---
2 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
index a67c20a..3e42eaa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
@@ -498,8 +498,26 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
}
WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, m->sdma_rlc_doorbell);
- WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, 0);
- WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, 0);
+ WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdma_rlc_rb_rptr);
+
+ if (mm && mm == current->mm)
+ wptr_valid = !get_user(data, wptr);
+ else if (mm) {
+ struct vm_area_struct *vma;
+
+ vma = find_vma(mm, (unsigned long)wptr);
+ if (vma && vma->vm_start <= (unsigned long)wptr &&
+ vma->vm_ops && vma->vm_ops->access)
+ wptr_valid = (sizeof(data) == vma->vm_ops->access(
+ vma, (unsigned long)wptr,
+ &data, sizeof(data), 0));
+ }
+ if (wptr_valid)
+ WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, data);
+ else
+ WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+ m->sdma_rlc_rb_rptr);
+
WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR, m->sdma_rlc_virtual_addr);
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdma_rlc_rb_base);
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI, m->sdma_rlc_rb_base_hi);
@@ -765,6 +783,7 @@ static int kgd_wave_control_execute(struct kgd_dev *kgd,
{
struct amdgpu_device *adev = get_amdgpu_device(kgd);
uint32_t data;
+ bool wptr_valid = false;
mutex_lock(&adev->grbm_idx_mutex);
@@ -841,6 +860,8 @@ static int alloc_memory_of_scratch(struct kgd_dev *kgd,
WREG32(mmSH_HIDDEN_PRIVATE_BASE_VMID, va);
unlock_srbm(kgd);
+ m->sdma_rlc_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
index 7d71727..ad92de6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
@@ -466,7 +466,7 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
uint32_t sdma_base_addr;
uint32_t temp, timeout = 2000;
uint32_t data;
-
+ bool wptr_valid = false;
m = get_sdma_mqd(mqd);
sdma_base_addr = get_sdma_base_addr(m);
@@ -495,8 +495,26 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
}
WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, m->sdmax_rlcx_doorbell);
- WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, 0);
- WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, 0);
+ WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdmax_rlcx_rb_rptr);
+
+ if (mm && mm == current->mm)
+ wptr_valid = !get_user(data, wptr);
+ else if (mm) {
+ struct vm_area_struct *vma;
+
+ vma = find_vma(mm, (unsigned long)wptr);
+ if (vma && vma->vm_start <= (unsigned long)wptr &&
+ vma->vm_ops && vma->vm_ops->access)
+ wptr_valid = (sizeof(data) == vma->vm_ops->access(
+ vma, (unsigned long)wptr,
+ &data, sizeof(data), 0));
+ }
+ if (wptr_valid)
+ WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, data);
+ else
+ WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR,
+ m->sdmax_rlcx_rb_rptr);
+
WREG32(sdma_base_addr + mmSDMA0_RLC0_VIRTUAL_ADDR, m->sdmax_rlcx_virtual_addr);
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE, m->sdmax_rlcx_rb_base);
WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_BASE_HI, m->sdmax_rlcx_rb_base_hi);
@@ -711,6 +729,8 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_CNTL) |
SDMA0_RLC0_RB_CNTL__RB_ENABLE_MASK);
+ m->sdmax_rlcx_rb_rptr = RREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR);
+
return 0;
}
--
2.7.4
|