#include <drm/ttm/ttm_execbuf_util.h>
#include <drm/ttm/ttm_tt.h>
#include <drm/xe_drm.h>
+#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/mm.h>
#include <linux/swap.h>
kvfree(tv);
}
+#define XE_VM_REBIND_RETRY_TIMEOUT_MS 1000
+
static void preempt_rebind_work_func(struct work_struct *w)
{
struct xe_vm *vm = container_of(w, struct xe_vm, preempt.rebind_work);
struct dma_fence *rebind_fence;
unsigned int fence_count = 0;
LIST_HEAD(preempt_fences);
+ ktime_t end = 0;
int err;
long wait;
int __maybe_unused tries = 0;
trace_xe_vm_rebind_worker_retry(vm);
goto retry;
}
+
+ /*
+ * With multiple active VMs, under memory pressure, it is possible that
+ * ttm_bo_validate() run into -EDEADLK and in such case returns -ENOMEM.
+ * Until ttm properly handles locking in such scenarios, best thing the
+ * driver can do is retry with a timeout. Killing the VM or putting it
+ * in error state after timeout or other error scenarios is still TBD.
+ */
+ if (err == -ENOMEM) {
+ ktime_t cur = ktime_get();
+
+ end = end ? : ktime_add_ms(cur, XE_VM_REBIND_RETRY_TIMEOUT_MS);
+ if (ktime_before(cur, end)) {
+ msleep(20);
+ trace_xe_vm_rebind_worker_retry(vm);
+ goto retry;
+ }
+ }
up_write(&vm->lock);
free_preempt_fences(&preempt_fences);