Commit dd299441 authored by Mukul Joshi's avatar Mukul Joshi Committed by Alex Deucher

drm/amdgpu: Rework retry fault removal

Rework retry fault removal from the software filter by
storing an expired timestamp for a fault that is being removed.
When a new fault comes, and it matches an entry in the sw filter,
it will be added as a new fault only when its timestamp is greater
than the timestamp expiry of the fault in the sw filter.
This helps in avoiding stale faults being added back into the
filter and preventing legitimate faults from being handled.
Suggested-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: default avatarMukul Joshi <mukul.joshi@amd.com>
Reviewed-by: default avatarPhilip Yang <Philip.Yang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 318e431b
...@@ -395,8 +395,21 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, ...@@ -395,8 +395,21 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
while (fault->timestamp >= stamp) { while (fault->timestamp >= stamp) {
uint64_t tmp; uint64_t tmp;
if (atomic64_read(&fault->key) == key) if (atomic64_read(&fault->key) == key) {
return true; /*
* if we get a fault which is already present in
* the fault_ring and the timestamp of
* the fault is after the expired timestamp,
* then this is a new fault that needs to be added
* into the fault ring.
*/
if (fault->timestamp_expiry != 0 &&
amdgpu_ih_ts_after(fault->timestamp_expiry,
timestamp))
break;
else
return true;
}
tmp = fault->timestamp; tmp = fault->timestamp;
fault = &gmc->fault_ring[fault->next]; fault = &gmc->fault_ring[fault->next];
...@@ -432,15 +445,32 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr, ...@@ -432,15 +445,32 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
{ {
struct amdgpu_gmc *gmc = &adev->gmc; struct amdgpu_gmc *gmc = &adev->gmc;
uint64_t key = amdgpu_gmc_fault_key(addr, pasid); uint64_t key = amdgpu_gmc_fault_key(addr, pasid);
struct amdgpu_ih_ring *ih;
struct amdgpu_gmc_fault *fault; struct amdgpu_gmc_fault *fault;
uint32_t last_wptr;
uint64_t last_ts;
uint32_t hash; uint32_t hash;
uint64_t tmp; uint64_t tmp;
ih = adev->irq.retry_cam_enabled ? &adev->irq.ih_soft : &adev->irq.ih1;
/* Get the WPTR of the last entry in IH ring */
last_wptr = amdgpu_ih_get_wptr(adev, ih);
/* Order wptr with ring data. */
rmb();
/* Get the timetamp of the last entry in IH ring */
last_ts = amdgpu_ih_decode_iv_ts(adev, ih, last_wptr, -1);
hash = hash_64(key, AMDGPU_GMC_FAULT_HASH_ORDER); hash = hash_64(key, AMDGPU_GMC_FAULT_HASH_ORDER);
fault = &gmc->fault_ring[gmc->fault_hash[hash].idx]; fault = &gmc->fault_ring[gmc->fault_hash[hash].idx];
do { do {
if (atomic64_cmpxchg(&fault->key, key, 0) == key) if (atomic64_read(&fault->key) == key) {
/*
* Update the timestamp when this fault
* expired.
*/
fault->timestamp_expiry = last_ts;
break; break;
}
tmp = fault->timestamp; tmp = fault->timestamp;
fault = &gmc->fault_ring[fault->next]; fault = &gmc->fault_ring[fault->next];
......
...@@ -70,6 +70,7 @@ struct amdgpu_gmc_fault { ...@@ -70,6 +70,7 @@ struct amdgpu_gmc_fault {
uint64_t timestamp:48; uint64_t timestamp:48;
uint64_t next:AMDGPU_GMC_FAULT_RING_ORDER; uint64_t next:AMDGPU_GMC_FAULT_RING_ORDER;
atomic64_t key; atomic64_t key;
uint64_t timestamp_expiry:48;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment