aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/4278-drm-amdkfd-Align-CIK-interrupt-processing-with-upstr.patch
blob: 728a6986f090b7fecec835bfead2a6f43b03c6b1 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
From d8dbdbca8ea2222761e366560ba69901a861f1a0 Mon Sep 17 00:00:00 2001
From: Felix Kuehling <Felix.Kuehling@amd.com>
Date: Mon, 23 Apr 2018 21:59:05 -0400
Subject: [PATCH 4278/5725] drm/amdkfd: Align CIK interrupt processing with
 upstream

Remove bitfields from struct cik_ih_ring_entry and use shiftr and
masks instead. Reorder the INTSRC definitions to match upstream.
Minor clean-up and simplification of VM-fault related code that
hasn't been upstreamed yet.

Change-Id: I23ded8d8b3b2731bf28517bb84023fa8d1d893cf
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c | 73 +++++++++++++-----------
 drivers/gpu/drm/amd/amdkfd/cik_int.h             | 25 ++------
 2 files changed, 46 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
index 751c004..1261432 100644
--- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
+++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
@@ -24,18 +24,13 @@
 #include "kfd_events.h"
 #include "cik_int.h"
 
-static bool is_cpc_vm_fault(struct kfd_dev *dev,
-					const uint32_t *ih_ring_entry)
+static bool is_cpc_vm_fault(struct kfd_dev *dev, uint32_t source_id,
+			    unsigned int vmid)
 {
-	const struct cik_ih_ring_entry *ihre =
-			(const struct cik_ih_ring_entry *)ih_ring_entry;
-
-	if ((ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
-		ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) &&
-	    ihre->vmid >= dev->vm_info.first_vmid_kfd &&
-	    ihre->vmid <= dev->vm_info.last_vmid_kfd)
-		return true;
-	return false;
+	return (source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
+		source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) &&
+		vmid >= dev->vm_info.first_vmid_kfd &&
+		vmid <= dev->vm_info.last_vmid_kfd;
 }
 
 static bool cik_event_interrupt_isr(struct kfd_dev *dev,
@@ -46,8 +41,7 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev,
 	const struct cik_ih_ring_entry *ihre =
 			(const struct cik_ih_ring_entry *)ih_ring_entry;
 	const struct kfd2kgd_calls *f2g = dev->kfd2kgd;
-	struct cik_ih_ring_entry *tmp_ihre =
-			(struct cik_ih_ring_entry *) patched_ihre;
+	unsigned int vmid, pasid;
 
 	/* This workaround is due to HW/FW limitation on Hawaii that
 	 * VMID and PASID are not written into ih_ring_entry
@@ -55,23 +49,34 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev,
 	if ((ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
 		ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) &&
 		dev->device_info->asic_family == CHIP_HAWAII) {
+		struct cik_ih_ring_entry *tmp_ihre =
+			(struct cik_ih_ring_entry *)patched_ihre;
+
 		*patched_flag = true;
 		*tmp_ihre = *ihre;
 
-		tmp_ihre->vmid = f2g->read_vmid_from_vmfault_reg(dev->kgd);
-		tmp_ihre->pasid = f2g->get_atc_vmid_pasid_mapping_pasid(
-						 dev->kgd, tmp_ihre->vmid);
-		return (tmp_ihre->pasid != 0) &&
-			tmp_ihre->vmid >= dev->vm_info.first_vmid_kfd &&
-			tmp_ihre->vmid <= dev->vm_info.last_vmid_kfd;
+		vmid = f2g->read_vmid_from_vmfault_reg(dev->kgd);
+		pasid = f2g->get_atc_vmid_pasid_mapping_pasid(dev->kgd, vmid);
+
+		tmp_ihre->ring_id &= 0x000000ff;
+		tmp_ihre->ring_id |= vmid << 8;
+		tmp_ihre->ring_id |= pasid << 16;
+
+		return (pasid != 0) &&
+			vmid >= dev->vm_info.first_vmid_kfd &&
+			vmid <= dev->vm_info.last_vmid_kfd;
 	}
+
+	vmid  = (ihre->ring_id & 0x0000ff00) >> 8;
+	pasid = (ihre->ring_id & 0xffff0000) >> 16;
+
 	/* Do not process in ISR, just request it to be forwarded to WQ. */
-	return (ihre->pasid != 0) &&
+	return (pasid != 0) &&
 		(ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE ||
-		ihre->source_id == CIK_INTSRC_SDMA_TRAP ||
-		ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG ||
-		ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE ||
-		is_cpc_vm_fault(dev, ih_ring_entry));
+		 ihre->source_id == CIK_INTSRC_SDMA_TRAP ||
+		 ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG ||
+		 ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE ||
+		 is_cpc_vm_fault(dev, ihre->source_id, vmid));
 }
 
 static void cik_event_interrupt_wq(struct kfd_dev *dev,
@@ -80,33 +85,35 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev,
 	const struct cik_ih_ring_entry *ihre =
 			(const struct cik_ih_ring_entry *)ih_ring_entry;
 	uint32_t context_id = ihre->data & 0xfffffff;
+	unsigned int vmid  = (ihre->ring_id & 0x0000ff00) >> 8;
+	unsigned int pasid = (ihre->ring_id & 0xffff0000) >> 16;
 
-	if (ihre->pasid == 0)
+	if (pasid == 0)
 		return;
 
 	if (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE)
-		kfd_signal_event_interrupt(ihre->pasid, context_id, 28);
+		kfd_signal_event_interrupt(pasid, context_id, 28);
 	else if (ihre->source_id == CIK_INTSRC_SDMA_TRAP)
-		kfd_signal_event_interrupt(ihre->pasid, context_id, 28);
+		kfd_signal_event_interrupt(pasid, context_id, 28);
 	else if (ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG)
-		kfd_signal_event_interrupt(ihre->pasid, context_id & 0xff, 8);
+		kfd_signal_event_interrupt(pasid, context_id & 0xff, 8);
 	else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE)
-		kfd_signal_hw_exception_event(ihre->pasid);
+		kfd_signal_hw_exception_event(pasid);
 	else if (ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
 		ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) {
 		struct kfd_vm_fault_info info;
 
-		kfd_process_vm_fault(dev->dqm, ihre->pasid);
+		kfd_process_vm_fault(dev->dqm, pasid);
 
 		memset(&info, 0, sizeof(info));
 		dev->kfd2kgd->get_vm_fault_info(dev->kgd, &info);
 		if (!info.page_addr && !info.status)
 			return;
 
-		if (info.vmid == ihre->vmid)
-			kfd_signal_vm_fault_event(dev, ihre->pasid, &info);
+		if (info.vmid == vmid)
+			kfd_signal_vm_fault_event(dev, pasid, &info);
 		else
-			kfd_signal_vm_fault_event(dev, ihre->pasid, NULL);
+			kfd_signal_vm_fault_event(dev, pasid, NULL);
 	}
 }
 
diff --git a/drivers/gpu/drm/amd/amdkfd/cik_int.h b/drivers/gpu/drm/amd/amdkfd/cik_int.h
index ff8255d..a2079a0 100644
--- a/drivers/gpu/drm/amd/amdkfd/cik_int.h
+++ b/drivers/gpu/drm/amd/amdkfd/cik_int.h
@@ -26,32 +26,19 @@
 #include <linux/types.h>
 
 struct cik_ih_ring_entry {
-	uint32_t source_id:8;
-	uint32_t reserved1:8;
-	uint32_t reserved2:16;
-
-	uint32_t data:28;
-	uint32_t reserved3:4;
-
-	/* pipeid, meid and unused3 are officially called RINGID,
-	 * but for our purposes, they always decode into pipe and ME.
-	 */
-	uint32_t pipeid:2;
-	uint32_t meid:2;
-	uint32_t reserved4:4;
-	uint32_t vmid:8;
-	uint32_t pasid:16;
-
-	uint32_t reserved5;
+	uint32_t source_id;
+	uint32_t data;
+	uint32_t ring_id;
+	uint32_t reserved;
 };
 
-#define CIK_INTSRC_DEQUEUE_COMPLETE	0xC6
 #define CIK_INTSRC_CP_END_OF_PIPE	0xB5
 #define CIK_INTSRC_CP_BAD_OPCODE	0xB7
+#define CIK_INTSRC_DEQUEUE_COMPLETE	0xC6
+#define CIK_INTSRC_SDMA_TRAP		0xE0
 #define CIK_INTSRC_SQ_INTERRUPT_MSG	0xEF
 #define CIK_INTSRC_GFX_PAGE_INV_FAULT	0x92
 #define CIK_INTSRC_GFX_MEM_PROT_FAULT	0x93
-#define CIK_INTSRC_SDMA_TRAP		0xE0
 
 #endif
 
-- 
2.7.4