Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b95e797 authored by Felix Kuehling's avatar Felix Kuehling Committed by Oded Gabbay
Browse files

drm/amdkfd: Add quiesce_mm and resume_mm to kgd2kfd_calls



These interfaces allow KGD to stop and resume all GPU user mode queue
access to a process address space. This is needed for handling MMU
notifiers of userptrs mapped for GPU access in KFD VMs.

Signed-off-by: default avatarFelix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent d1853f42
Loading
Loading
Loading
Loading
+38 −0
Original line number Original line Diff line number Diff line
@@ -541,6 +541,44 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
	spin_unlock(&kfd->interrupt_lock);
	spin_unlock(&kfd->interrupt_lock);
}
}


int kgd2kfd_quiesce_mm(struct mm_struct *mm)
{
	struct kfd_process *p;
	int r;

	/* Because we are called from arbitrary context (workqueue) as opposed
	 * to process context, kfd_process could attempt to exit while we are
	 * running so the lookup function increments the process ref count.
	 */
	p = kfd_lookup_process_by_mm(mm);
	if (!p)
		return -ESRCH;

	r = kfd_process_evict_queues(p);

	kfd_unref_process(p);
	return r;
}

int kgd2kfd_resume_mm(struct mm_struct *mm)
{
	struct kfd_process *p;
	int r;

	/* Because we are called from arbitrary context (workqueue) as opposed
	 * to process context, kfd_process could attempt to exit while we are
	 * running so the lookup function increments the process ref count.
	 */
	p = kfd_lookup_process_by_mm(mm);
	if (!p)
		return -ESRCH;

	r = kfd_process_restore_queues(p);

	kfd_unref_process(p);
	return r;
}

/** kgd2kfd_schedule_evict_and_restore_process - Schedules work queue that will
/** kgd2kfd_schedule_evict_and_restore_process - Schedules work queue that will
 *   prepare for safe eviction of KFD BOs that belong to the specified
 *   prepare for safe eviction of KFD BOs that belong to the specified
 *   process.
 *   process.
+2 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,8 @@ static const struct kgd2kfd_calls kgd2kfd = {
	.interrupt	= kgd2kfd_interrupt,
	.interrupt	= kgd2kfd_interrupt,
	.suspend	= kgd2kfd_suspend,
	.suspend	= kgd2kfd_suspend,
	.resume		= kgd2kfd_resume,
	.resume		= kgd2kfd_resume,
	.quiesce_mm	= kgd2kfd_quiesce_mm,
	.resume_mm	= kgd2kfd_resume_mm,
	.schedule_evict_and_restore_process =
	.schedule_evict_and_restore_process =
			  kgd2kfd_schedule_evict_and_restore_process,
			  kgd2kfd_schedule_evict_and_restore_process,
};
};
+4 −0
Original line number Original line Diff line number Diff line
@@ -512,6 +512,8 @@ struct qcm_process_device {
/* Approx. time before evicting the process again */
/* Approx. time before evicting the process again */
#define PROCESS_ACTIVE_TIME_MS 10
#define PROCESS_ACTIVE_TIME_MS 10


int kgd2kfd_quiesce_mm(struct mm_struct *mm);
int kgd2kfd_resume_mm(struct mm_struct *mm);
int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
int kgd2kfd_schedule_evict_and_restore_process(struct mm_struct *mm,
					       struct dma_fence *fence);
					       struct dma_fence *fence);


@@ -681,6 +683,8 @@ struct kfd_process *kfd_get_process(const struct task_struct *);
struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid);
struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid);
struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm);
struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm);
void kfd_unref_process(struct kfd_process *p);
void kfd_unref_process(struct kfd_process *p);
int kfd_process_evict_queues(struct kfd_process *p);
int kfd_process_restore_queues(struct kfd_process *p);
void kfd_suspend_all_processes(void);
void kfd_suspend_all_processes(void);
int kfd_resume_all_processes(void);
int kfd_resume_all_processes(void);


+5 −5
Original line number Original line Diff line number Diff line
@@ -808,7 +808,7 @@ struct kfd_process *kfd_lookup_process_by_mm(const struct mm_struct *mm)
 * Eviction is reference-counted per process-device. This means multiple
 * Eviction is reference-counted per process-device. This means multiple
 * evictions from different sources can be nested safely.
 * evictions from different sources can be nested safely.
 */
 */
static int process_evict_queues(struct kfd_process *p)
int kfd_process_evict_queues(struct kfd_process *p)
{
{
	struct kfd_process_device *pdd;
	struct kfd_process_device *pdd;
	int r = 0;
	int r = 0;
@@ -844,7 +844,7 @@ static int process_evict_queues(struct kfd_process *p)
}
}


/* process_restore_queues - Restore all user queues of a process */
/* process_restore_queues - Restore all user queues of a process */
static  int process_restore_queues(struct kfd_process *p)
int kfd_process_restore_queues(struct kfd_process *p)
{
{
	struct kfd_process_device *pdd;
	struct kfd_process_device *pdd;
	int r, ret = 0;
	int r, ret = 0;
@@ -886,7 +886,7 @@ static void evict_process_worker(struct work_struct *work)
	flush_delayed_work(&p->restore_work);
	flush_delayed_work(&p->restore_work);


	pr_debug("Started evicting pasid %d\n", p->pasid);
	pr_debug("Started evicting pasid %d\n", p->pasid);
	ret = process_evict_queues(p);
	ret = kfd_process_evict_queues(p);
	if (!ret) {
	if (!ret) {
		dma_fence_signal(p->ef);
		dma_fence_signal(p->ef);
		dma_fence_put(p->ef);
		dma_fence_put(p->ef);
@@ -946,7 +946,7 @@ static void restore_process_worker(struct work_struct *work)
		return;
		return;
	}
	}


	ret = process_restore_queues(p);
	ret = kfd_process_restore_queues(p);
	if (!ret)
	if (!ret)
		pr_debug("Finished restoring pasid %d\n", p->pasid);
		pr_debug("Finished restoring pasid %d\n", p->pasid);
	else
	else
@@ -963,7 +963,7 @@ void kfd_suspend_all_processes(void)
		cancel_delayed_work_sync(&p->eviction_work);
		cancel_delayed_work_sync(&p->eviction_work);
		cancel_delayed_work_sync(&p->restore_work);
		cancel_delayed_work_sync(&p->restore_work);


		if (process_evict_queues(p))
		if (kfd_process_evict_queues(p))
			pr_err("Failed to suspend process %d\n", p->pasid);
			pr_err("Failed to suspend process %d\n", p->pasid);
		dma_fence_signal(p->ef);
		dma_fence_signal(p->ef);
		dma_fence_put(p->ef);
		dma_fence_put(p->ef);
+6 −0
Original line number Original line Diff line number Diff line
@@ -382,6 +382,10 @@ struct kfd2kgd_calls {
 *
 *
 * @resume: Notifies amdkfd about a resume action done to a kgd device
 * @resume: Notifies amdkfd about a resume action done to a kgd device
 *
 *
 * @quiesce_mm: Quiesce all user queue access to specified MM address space
 *
 * @resume_mm: Resume user queue access to specified MM address space
 *
 * @schedule_evict_and_restore_process: Schedules work queue that will prepare
 * @schedule_evict_and_restore_process: Schedules work queue that will prepare
 * for safe eviction of KFD BOs that belong to the specified process.
 * for safe eviction of KFD BOs that belong to the specified process.
 *
 *
@@ -399,6 +403,8 @@ struct kgd2kfd_calls {
	void (*interrupt)(struct kfd_dev *kfd, const void *ih_ring_entry);
	void (*interrupt)(struct kfd_dev *kfd, const void *ih_ring_entry);
	void (*suspend)(struct kfd_dev *kfd);
	void (*suspend)(struct kfd_dev *kfd);
	int (*resume)(struct kfd_dev *kfd);
	int (*resume)(struct kfd_dev *kfd);
	int (*quiesce_mm)(struct mm_struct *mm);
	int (*resume_mm)(struct mm_struct *mm);
	int (*schedule_evict_and_restore_process)(struct mm_struct *mm,
	int (*schedule_evict_and_restore_process)(struct mm_struct *mm,
			struct dma_fence *fence);
			struct dma_fence *fence);
};
};