Skip to content

Commit

Permalink
drm/amdgpu: Rework retry fault removal
Browse files Browse the repository at this point in the history
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: Felix Kuehling <[email protected]>
Signed-off-by: Mukul Joshi <[email protected]>
Reviewed-by: Philip Yang <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
  • Loading branch information
mukjoshi authored and alexdeucher committed Apr 13, 2023
1 parent 318e431 commit dd29944
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
36 changes: 33 additions & 3 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,21 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev,
while (fault->timestamp >= stamp) {
uint64_t tmp;

if (atomic64_read(&fault->key) == key)
return true;
if (atomic64_read(&fault->key) == key) {
/*
* 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;
fault = &gmc->fault_ring[fault->next];
Expand Down Expand Up @@ -432,15 +445,32 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr,
{
struct amdgpu_gmc *gmc = &adev->gmc;
uint64_t key = amdgpu_gmc_fault_key(addr, pasid);
struct amdgpu_ih_ring *ih;
struct amdgpu_gmc_fault *fault;
uint32_t last_wptr;
uint64_t last_ts;
uint32_t hash;
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);
fault = &gmc->fault_ring[gmc->fault_hash[hash].idx];
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;
}

tmp = fault->timestamp;
fault = &gmc->fault_ring[fault->next];
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct amdgpu_gmc_fault {
uint64_t timestamp:48;
uint64_t next:AMDGPU_GMC_FAULT_RING_ORDER;
atomic64_t key;
uint64_t timestamp_expiry:48;
};

/*
Expand Down

0 comments on commit dd29944

Please sign in to comment.