aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/1465-drm-amdgpu-Add-support-for-resuming-SDMA-queues-w-o-.patch
blob: dc733821dbbc7223dda1bac2b0059d7723ad6b93 (plain)
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