@@ -34,6 +34,11 @@
#define AMDGPU_SVM_RANGE_RESTORE_DELAY_MS 1
+/* Long enough to ensure no retry fault comes after svm range is restored and
+ * page table is updated.
+ */
+#define AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING 2000
+
static void svm_range_evict_svm_bo_worker(struct work_struct *work);
static bool
svm_range_cpu_invalidate_pagetables(struct mmu_interval_notifier *mni,
@@ -246,6 +251,7 @@ svm_range *svm_range_new(struct svm_range_list *svms, uint64_t start,
INIT_LIST_HEAD(&prange->deferred_list);
INIT_LIST_HEAD(&prange->child_list);
atomic_set(&prange->invalid, 0);
+ prange->validate_timestamp = ktime_to_us(ktime_get());
mutex_init(&prange->migrate_mutex);
mutex_init(&prange->lock);
svm_range_set_default_attributes(&prange->preferred_loc,
@@ -578,19 +584,25 @@ static int svm_range_validate_vram(struct svm_range *prange)
static int
svm_range_validate(struct mm_struct *mm, struct svm_range *prange)
{
+ struct kfd_process *p;
int r;
pr_debug("svms 0x%p prange 0x%p [0x%lx 0x%lx] actual loc 0x%x\n",
prange->svms, prange, prange->start, prange->last,
prange->actual_loc);
+ p = container_of(prange->svms, struct kfd_process, svms);
+
if (!prange->actual_loc)
r = svm_range_validate_ram(mm, prange);
else
r = svm_range_validate_vram(prange);
- pr_debug("svms 0x%p [0x%lx 0x%lx] ret %d invalid %d\n", prange->svms,
- prange->start, prange->last, r, atomic_read(&prange->invalid));
+ if (!r)
+ prange->validate_timestamp = ktime_to_us(ktime_get());
+
+ pr_debug("svms 0x%p [0x%lx 0x%lx] ret %d\n", prange->svms,
+ prange->start, prange->last, r);
return r;
}
@@ -2086,6 +2098,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
struct svm_range_list *svms;
struct svm_range *prange;
struct kfd_process *p;
+ uint64_t timestamp;
int32_t best_loc;
int r = 0;
@@ -2119,6 +2132,13 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid,
}
mutex_lock(&prange->migrate_mutex);
+ timestamp = ktime_to_us(ktime_get()) - prange->validate_timestamp;
+ /* skip duplicate vm fault on different pages of same range */
+ if (timestamp < AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING) {
+ pr_debug("svms 0x%p [0x%lx %lx] already restored\n",
+ svms, prange->start, prange->last);
+ goto out_unlock_range;
+ }
best_loc = svm_range_best_restore_location(prange, adev);
if (best_loc == -1) {
@@ -87,6 +87,7 @@ struct svm_work_list_item {
* @actual_loc: the actual location, 0 for CPU, or GPU id
* @granularity:migration granularity, log2 num pages
* @invalid: not 0 means cpu page table is invalidated
+ * @validate_timestamp: system timestamp when range is validated
* @notifier: register mmu interval notifier
* @work_item: deferred work item information
* @deferred_list: list header used to add range to deferred list
@@ -125,6 +126,7 @@ struct svm_range {
uint32_t actual_loc;
uint8_t granularity;
atomic_t invalid;
+ uint64_t validate_timestamp;
struct mmu_interval_notifier notifier;
struct svm_work_list_item work_item;
struct list_head deferred_list;