drm/xe/vm: Fix ASID XA usage
authorThomas Hellström <thomas.hellstrom@linux.intel.com>
Fri, 24 Nov 2023 15:33:45 +0000 (16:33 +0100)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:44:57 +0000 (11:44 -0500)
xa_alloc_cyclic() returns 1 on successful allocation, if wrapping occurs,
but the code incorrectly treats that as an error. Fix that.
Also, xa_alloc_cyclic() requires xa_init_flags(..., XA_FLAGS_ALLOC), so
fix that, and assuming we don't want a zero ASID, instead of using
XA_FLAGS_ALLOC1, adjust the xa limits at alloc_cyclic time.

v2:
- On CONFIG_DRM_XE_DEBUG, Initialize the cyclic ASID allocation in such a
  way that the next allocated ASID will be the maximum one, and the one
  following will cause an ASID wrap, (all to have CI test high ASIDs
  and ASID wraps).
v3:
- Stricter return value checking from xa_alloc_cyclic() (Matthew Auld)

Suggested-by: Ohad Sharabi <osharabi@habana.ai>
Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/946
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Ohad Sharabi <osharabi@habana.ai> #v1
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231124153345.97385-5-thomas.hellstrom@linux.intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_device.c
drivers/gpu/drm/xe/xe_vm.c

index 8be765adf702dc24530e05de7a50ceec38ec3d7c..d60379d844d2addad19efbd223be09ed7869157d 100644 (file)
@@ -230,7 +230,20 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
        init_waitqueue_head(&xe->ufence_wq);
 
        drmm_mutex_init(&xe->drm, &xe->usm.lock);
-       xa_init_flags(&xe->usm.asid_to_vm, XA_FLAGS_ALLOC1);
+       xa_init_flags(&xe->usm.asid_to_vm, XA_FLAGS_ALLOC);
+
+       if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) {
+               /* Trigger a large asid and an early asid wrap. */
+               u32 asid;
+
+               BUILD_BUG_ON(XE_MAX_ASID < 2);
+               err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, NULL,
+                                     XA_LIMIT(XE_MAX_ASID - 2, XE_MAX_ASID - 1),
+                                     &xe->usm.next_asid, GFP_KERNEL);
+               drm_WARN_ON(&xe->drm, err);
+               if (err >= 0)
+                       xa_erase(&xe->usm.asid_to_vm, asid);
+       }
 
        drmm_mutex_init(&xe->drm, &xe->persistent_engines.lock);
        INIT_LIST_HEAD(&xe->persistent_engines.list);
index 1b4d340d06047bddf5ab7d232649d4e5f330da01..7c0ae43731803bb97217fd3e6d4721d11a8b2bf7 100644 (file)
@@ -1996,13 +1996,14 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data,
        if (xe->info.has_asid) {
                mutex_lock(&xe->usm.lock);
                err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm,
-                                     XA_LIMIT(0, XE_MAX_ASID - 1),
+                                     XA_LIMIT(1, XE_MAX_ASID - 1),
                                      &xe->usm.next_asid, GFP_KERNEL);
                mutex_unlock(&xe->usm.lock);
-               if (err) {
+               if (err < 0) {
                        xe_vm_close_and_put(vm);
                        return err;
                }
+               err = 0;
                vm->usm.asid = asid;
        }