aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2018-09-26 05:50:09 -0400
committerAlex Deucher <alexander.deucher@amd.com>2018-12-07 18:14:26 -0500
commit22666cc1481ae3814d9c7718418cc4a3aa7d90c3 (patch)
treec6cb16880499a8ad82addb0b1936ec8e692b1db0
parenta655dad4b2f94e0d880f2e4ea45251092d836f36 (diff)
drm/amdgpu: move IV prescreening into the GMC code
The GMC/VM subsystem is causing the faults, so move the handling here as well. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik_ih.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cz_ih.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c59
-rw-r--r--drivers/gpu/drm/amd/amdgpu/iceland_ih.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_ih.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/tonga_ih.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vega10_ih.c82
9 files changed, 59 insertions, 154 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
index 9ce8c93ec19b..f877bb78d10a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
@@ -51,14 +51,12 @@ struct amdgpu_ih_ring {
51struct amdgpu_ih_funcs { 51struct amdgpu_ih_funcs {
52 /* ring read/write ptr handling, called from interrupt context */ 52 /* ring read/write ptr handling, called from interrupt context */
53 u32 (*get_wptr)(struct amdgpu_device *adev); 53 u32 (*get_wptr)(struct amdgpu_device *adev);
54 bool (*prescreen_iv)(struct amdgpu_device *adev);
55 void (*decode_iv)(struct amdgpu_device *adev, 54 void (*decode_iv)(struct amdgpu_device *adev,
56 struct amdgpu_iv_entry *entry); 55 struct amdgpu_iv_entry *entry);
57 void (*set_rptr)(struct amdgpu_device *adev); 56 void (*set_rptr)(struct amdgpu_device *adev);
58}; 57};
59 58
60#define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev)) 59#define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev))
61#define amdgpu_ih_prescreen_iv(adev) (adev)->irq.ih_funcs->prescreen_iv((adev))
62#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv)) 60#define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
63#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev)) 61#define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
64 62
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 79b6f456f2c5..b7968f426862 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -145,10 +145,6 @@ static void amdgpu_irq_callback(struct amdgpu_device *adev,
145 u32 ring_index = ih->rptr >> 2; 145 u32 ring_index = ih->rptr >> 2;
146 struct amdgpu_iv_entry entry; 146 struct amdgpu_iv_entry entry;
147 147
148 /* Prescreening of high-frequency interrupts */
149 if (!amdgpu_ih_prescreen_iv(adev))
150 return;
151
152 entry.iv_entry = (const uint32_t *)&ih->ring[ring_index]; 148 entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
153 amdgpu_ih_decode_iv(adev, &entry); 149 amdgpu_ih_decode_iv(adev, &entry);
154 150
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
index 3e6c8c4067cb..8a8b4967a101 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
@@ -228,18 +228,6 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev)
228 * [127:96] - reserved 228 * [127:96] - reserved
229 */ 229 */
230 230
231/**
232 * cik_ih_prescreen_iv - prescreen an interrupt vector
233 *
234 * @adev: amdgpu_device pointer
235 *
236 * Returns true if the interrupt vector should be further processed.
237 */
238static bool cik_ih_prescreen_iv(struct amdgpu_device *adev)
239{
240 return true;
241}
242
243 /** 231 /**
244 * cik_ih_decode_iv - decode an interrupt vector 232 * cik_ih_decode_iv - decode an interrupt vector
245 * 233 *
@@ -445,7 +433,6 @@ static const struct amd_ip_funcs cik_ih_ip_funcs = {
445 433
446static const struct amdgpu_ih_funcs cik_ih_funcs = { 434static const struct amdgpu_ih_funcs cik_ih_funcs = {
447 .get_wptr = cik_ih_get_wptr, 435 .get_wptr = cik_ih_get_wptr,
448 .prescreen_iv = cik_ih_prescreen_iv,
449 .decode_iv = cik_ih_decode_iv, 436 .decode_iv = cik_ih_decode_iv,
450 .set_rptr = cik_ih_set_rptr 437 .set_rptr = cik_ih_set_rptr
451}; 438};
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
index 447b3cbc47e5..9d3ea298e116 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
@@ -208,18 +208,6 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev)
208} 208}
209 209
210/** 210/**
211 * cz_ih_prescreen_iv - prescreen an interrupt vector
212 *
213 * @adev: amdgpu_device pointer
214 *
215 * Returns true if the interrupt vector should be further processed.
216 */
217static bool cz_ih_prescreen_iv(struct amdgpu_device *adev)
218{
219 return true;
220}
221
222/**
223 * cz_ih_decode_iv - decode an interrupt vector 211 * cz_ih_decode_iv - decode an interrupt vector
224 * 212 *
225 * @adev: amdgpu_device pointer 213 * @adev: amdgpu_device pointer
@@ -426,7 +414,6 @@ static const struct amd_ip_funcs cz_ih_ip_funcs = {
426 414
427static const struct amdgpu_ih_funcs cz_ih_funcs = { 415static const struct amdgpu_ih_funcs cz_ih_funcs = {
428 .get_wptr = cz_ih_get_wptr, 416 .get_wptr = cz_ih_get_wptr,
429 .prescreen_iv = cz_ih_prescreen_iv,
430 .decode_iv = cz_ih_decode_iv, 417 .decode_iv = cz_ih_decode_iv,
431 .set_rptr = cz_ih_set_rptr 418 .set_rptr = cz_ih_set_rptr
432}; 419};
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 016c7aab4a29..ce150de723c9 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -244,6 +244,62 @@ static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
244 return 0; 244 return 0;
245} 245}
246 246
247/**
248 * vega10_ih_prescreen_iv - prescreen an interrupt vector
249 *
250 * @adev: amdgpu_device pointer
251 *
252 * Returns true if the interrupt vector should be further processed.
253 */
254static bool gmc_v9_0_prescreen_iv(struct amdgpu_device *adev,
255 struct amdgpu_iv_entry *entry,
256 uint64_t addr)
257{
258 struct amdgpu_vm *vm;
259 u64 key;
260 int r;
261
262 /* No PASID, can't identify faulting process */
263 if (!entry->pasid)
264 return true;
265
266 /* Not a retry fault */
267 if (!(entry->src_data[1] & 0x80))
268 return true;
269
270 /* Track retry faults in per-VM fault FIFO. */
271 spin_lock(&adev->vm_manager.pasid_lock);
272 vm = idr_find(&adev->vm_manager.pasid_idr, entry->pasid);
273 if (!vm) {
274 /* VM not found, process it normally */
275 spin_unlock(&adev->vm_manager.pasid_lock);
276 return true;
277 }
278
279 key = AMDGPU_VM_FAULT(entry->pasid, addr);
280 r = amdgpu_vm_add_fault(vm->fault_hash, key);
281
282 /* Hash table is full or the fault is already being processed,
283 * ignore further page faults
284 */
285 if (r != 0) {
286 spin_unlock(&adev->vm_manager.pasid_lock);
287 return false;
288 }
289 /* No locking required with single writer and single reader */
290 r = kfifo_put(&vm->faults, key);
291 if (!r) {
292 /* FIFO is full. Ignore it until there is space */
293 amdgpu_vm_clear_fault(vm->fault_hash, key);
294 spin_unlock(&adev->vm_manager.pasid_lock);
295 return false;
296 }
297
298 spin_unlock(&adev->vm_manager.pasid_lock);
299 /* It's the first fault for this address, process it normally */
300 return true;
301}
302
247static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, 303static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
248 struct amdgpu_irq_src *source, 304 struct amdgpu_irq_src *source,
249 struct amdgpu_iv_entry *entry) 305 struct amdgpu_iv_entry *entry)
@@ -255,6 +311,9 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev,
255 addr = (u64)entry->src_data[0] << 12; 311 addr = (u64)entry->src_data[0] << 12;
256 addr |= ((u64)entry->src_data[1] & 0xf) << 44; 312 addr |= ((u64)entry->src_data[1] & 0xf) << 44;
257 313
314 if (!gmc_v9_0_prescreen_iv(adev, entry, addr))
315 return 1; /* This also prevents sending it to KFD */
316
258 if (!amdgpu_sriov_vf(adev)) { 317 if (!amdgpu_sriov_vf(adev)) {
259 status = RREG32(hub->vm_l2_pro_fault_status); 318 status = RREG32(hub->vm_l2_pro_fault_status);
260 WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); 319 WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1);
diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
index 2b94a6d1550e..a3984d10b604 100644
--- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
@@ -208,18 +208,6 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev)
208} 208}
209 209
210/** 210/**
211 * iceland_ih_prescreen_iv - prescreen an interrupt vector
212 *
213 * @adev: amdgpu_device pointer
214 *
215 * Returns true if the interrupt vector should be further processed.
216 */
217static bool iceland_ih_prescreen_iv(struct amdgpu_device *adev)
218{
219 return true;
220}
221
222/**
223 * iceland_ih_decode_iv - decode an interrupt vector 211 * iceland_ih_decode_iv - decode an interrupt vector
224 * 212 *
225 * @adev: amdgpu_device pointer 213 * @adev: amdgpu_device pointer
@@ -424,7 +412,6 @@ static const struct amd_ip_funcs iceland_ih_ip_funcs = {
424 412
425static const struct amdgpu_ih_funcs iceland_ih_funcs = { 413static const struct amdgpu_ih_funcs iceland_ih_funcs = {
426 .get_wptr = iceland_ih_get_wptr, 414 .get_wptr = iceland_ih_get_wptr,
427 .prescreen_iv = iceland_ih_prescreen_iv,
428 .decode_iv = iceland_ih_decode_iv, 415 .decode_iv = iceland_ih_decode_iv,
429 .set_rptr = iceland_ih_set_rptr 416 .set_rptr = iceland_ih_set_rptr
430}; 417};
diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c
index b3d7d9f83202..2938fb9f17cc 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c
@@ -118,19 +118,6 @@ static u32 si_ih_get_wptr(struct amdgpu_device *adev)
118 return (wptr & adev->irq.ih.ptr_mask); 118 return (wptr & adev->irq.ih.ptr_mask);
119} 119}
120 120
121/**
122 * si_ih_prescreen_iv - prescreen an interrupt vector
123 *
124 * @adev: amdgpu_device pointer
125 *
126 * Returns true if the interrupt vector should be further processed.
127 */
128static bool si_ih_prescreen_iv(struct amdgpu_device *adev)
129{
130 /* Process all interrupts */
131 return true;
132}
133
134static void si_ih_decode_iv(struct amdgpu_device *adev, 121static void si_ih_decode_iv(struct amdgpu_device *adev,
135 struct amdgpu_iv_entry *entry) 122 struct amdgpu_iv_entry *entry)
136{ 123{
@@ -301,7 +288,6 @@ static const struct amd_ip_funcs si_ih_ip_funcs = {
301 288
302static const struct amdgpu_ih_funcs si_ih_funcs = { 289static const struct amdgpu_ih_funcs si_ih_funcs = {
303 .get_wptr = si_ih_get_wptr, 290 .get_wptr = si_ih_get_wptr,
304 .prescreen_iv = si_ih_prescreen_iv,
305 .decode_iv = si_ih_decode_iv, 291 .decode_iv = si_ih_decode_iv,
306 .set_rptr = si_ih_set_rptr 292 .set_rptr = si_ih_set_rptr
307}; 293};
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
index 9d7b43da6acc..15da06ddeb75 100644
--- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
@@ -219,18 +219,6 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev)
219} 219}
220 220
221/** 221/**
222 * tonga_ih_prescreen_iv - prescreen an interrupt vector
223 *
224 * @adev: amdgpu_device pointer
225 *
226 * Returns true if the interrupt vector should be further processed.
227 */
228static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev)
229{
230 return true;
231}
232
233/**
234 * tonga_ih_decode_iv - decode an interrupt vector 222 * tonga_ih_decode_iv - decode an interrupt vector
235 * 223 *
236 * @adev: amdgpu_device pointer 224 * @adev: amdgpu_device pointer
@@ -490,7 +478,6 @@ static const struct amd_ip_funcs tonga_ih_ip_funcs = {
490 478
491static const struct amdgpu_ih_funcs tonga_ih_funcs = { 479static const struct amdgpu_ih_funcs tonga_ih_funcs = {
492 .get_wptr = tonga_ih_get_wptr, 480 .get_wptr = tonga_ih_get_wptr,
493 .prescreen_iv = tonga_ih_prescreen_iv,
494 .decode_iv = tonga_ih_decode_iv, 481 .decode_iv = tonga_ih_decode_iv,
495 .set_rptr = tonga_ih_set_rptr 482 .set_rptr = tonga_ih_set_rptr
496}; 483};
diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
index b49290bcf109..2c250b01a903 100644
--- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
@@ -220,87 +220,6 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev)
220} 220}
221 221
222/** 222/**
223 * vega10_ih_prescreen_iv - prescreen an interrupt vector
224 *
225 * @adev: amdgpu_device pointer
226 *
227 * Returns true if the interrupt vector should be further processed.
228 */
229static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev)
230{
231 u32 ring_index = adev->irq.ih.rptr >> 2;
232 u32 dw0, dw3, dw4, dw5;
233 u16 pasid;
234 u64 addr, key;
235 struct amdgpu_vm *vm;
236 int r;
237
238 dw0 = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
239 dw3 = le32_to_cpu(adev->irq.ih.ring[ring_index + 3]);
240 dw4 = le32_to_cpu(adev->irq.ih.ring[ring_index + 4]);
241 dw5 = le32_to_cpu(adev->irq.ih.ring[ring_index + 5]);
242
243 /* Filter retry page faults, let only the first one pass. If
244 * there are too many outstanding faults, ignore them until
245 * some faults get cleared.
246 */
247 switch (dw0 & 0xff) {
248 case SOC15_IH_CLIENTID_VMC:
249 case SOC15_IH_CLIENTID_UTCL2:
250 break;
251 default:
252 /* Not a VM fault */
253 return true;
254 }
255
256 pasid = dw3 & 0xffff;
257 /* No PASID, can't identify faulting process */
258 if (!pasid)
259 return true;
260
261 /* Not a retry fault */
262 if (!(dw5 & 0x80))
263 return true;
264
265 /* Track retry faults in per-VM fault FIFO. */
266 spin_lock(&adev->vm_manager.pasid_lock);
267 vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
268 addr = ((u64)(dw5 & 0xf) << 44) | ((u64)dw4 << 12);
269 key = AMDGPU_VM_FAULT(pasid, addr);
270 if (!vm) {
271 /* VM not found, process it normally */
272 spin_unlock(&adev->vm_manager.pasid_lock);
273 return true;
274 } else {
275 r = amdgpu_vm_add_fault(vm->fault_hash, key);
276
277 /* Hash table is full or the fault is already being processed,
278 * ignore further page faults
279 */
280 if (r != 0) {
281 spin_unlock(&adev->vm_manager.pasid_lock);
282 goto ignore_iv;
283 }
284 }
285 /* No locking required with single writer and single reader */
286 r = kfifo_put(&vm->faults, key);
287 if (!r) {
288 /* FIFO is full. Ignore it until there is space */
289 amdgpu_vm_clear_fault(vm->fault_hash, key);
290 spin_unlock(&adev->vm_manager.pasid_lock);
291 goto ignore_iv;
292 }
293
294 spin_unlock(&adev->vm_manager.pasid_lock);
295 /* It's the first fault for this address, process it normally */
296 return true;
297
298ignore_iv:
299 adev->irq.ih.rptr += 32;
300 return false;
301}
302
303/**
304 * vega10_ih_decode_iv - decode an interrupt vector 223 * vega10_ih_decode_iv - decode an interrupt vector
305 * 224 *
306 * @adev: amdgpu_device pointer 225 * @adev: amdgpu_device pointer
@@ -484,7 +403,6 @@ const struct amd_ip_funcs vega10_ih_ip_funcs = {
484 403
485static const struct amdgpu_ih_funcs vega10_ih_funcs = { 404static const struct amdgpu_ih_funcs vega10_ih_funcs = {
486 .get_wptr = vega10_ih_get_wptr, 405 .get_wptr = vega10_ih_get_wptr,
487 .prescreen_iv = vega10_ih_prescreen_iv,
488 .decode_iv = vega10_ih_decode_iv, 406 .decode_iv = vega10_ih_decode_iv,
489 .set_rptr = vega10_ih_set_rptr 407 .set_rptr = vega10_ih_set_rptr
490}; 408};