AMDGPU already has a global PASID xarray used by the PASID allocator.
Currently allocated PASIDs store a dummy value in that xarray.
Add helper functions so DRM-owned PASIDs can store and retrieve their
owning DRM file-private object.
This prepares for using:
PASID -> fpriv -> vm
instead of the separate per-device:
PASID -> vm
mapping.
Cc: Alex Deucher <[email protected]>
Suggested-by: Christian König <[email protected]>
Signed-off-by: Srinivasan Shanmugam <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 91 +++++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h | 13 ++++
2 files changed, 104 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 684f40fce73f..f65d57b4cc04 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -78,6 +78,97 @@ int amdgpu_pasid_alloc(unsigned int bits)
return pasid;
}
+int amdgpu_pasid_set_fpriv(u32 pasid,
+ struct amdgpu_fpriv *fpriv)
+{
+ unsigned long flags;
+ void *entry;
+ int r = 0;
+
+ if (!pasid || !fpriv)
+ return -EINVAL;
+
+ xa_lock_irqsave(&amdgpu_pasid_xa, flags);
+
+ entry = xa_load(&amdgpu_pasid_xa, pasid);
+
+ if (!entry) {
+ r = -ENOENT;
+ goto unlock;
+ }
+
+ if (!xa_is_value(entry)) {
+ r = -EBUSY;
+ goto unlock;
+ }
+
+ entry = __xa_store(&amdgpu_pasid_xa, pasid,
+ fpriv, GFP_ATOMIC);
+ r = xa_err(entry);
+
+unlock:
+ xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
+
+ return r;
+}
+
+void amdgpu_pasid_clear_fpriv(u32 pasid,
+ struct amdgpu_fpriv *fpriv)
+{
+ unsigned long flags;
+ void *entry;
+
+ if (!pasid || !fpriv)
+ return;
+
+ xa_lock_irqsave(&amdgpu_pasid_xa, flags);
+
+ entry = xa_load(&amdgpu_pasid_xa, pasid);
+
+ if (entry == fpriv)
+ __xa_store(&amdgpu_pasid_xa,
+ pasid,
+ xa_mk_value(0),
+ GFP_ATOMIC);
+
+ xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
+}
+
+void amdgpu_pasid_lock(unsigned long *flags)
+{
+ xa_lock_irqsave(&amdgpu_pasid_xa, *flags);
+}
+
+void amdgpu_pasid_unlock(unsigned long flags)
+{
+ xa_unlock_irqrestore(&amdgpu_pasid_xa, flags);
+}
+
+/**
+ * amdgpu_pasid_get_fpriv_locked - get fpriv from PASID
+ * @pasid: PASID to resolve
+ *
+ * Caller must hold the PASID XA lock.
+ *
+ * The returned pointer is only protected by the PASID XA lock.
+ * Callers must not continue using it after dropping the lock
+ * unless additional lifetime protection exists.
+ *
+ * This intentionally does not add kref/RCU lifetime handling.
+ */
+ struct amdgpu_fpriv *
+amdgpu_pasid_get_fpriv_locked(u32 pasid)
+{
+ void *entry;
+
+ entry = xa_load(&amdgpu_pasid_xa, pasid);
+
+ if (!entry || xa_is_value(entry))
+ return NULL;
+
+ return entry;
+}
+
/**
* amdgpu_pasid_free - Free a PASID
* @pasid: PASID to free
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index a57919478d3b..220a0ba0cfb6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -38,6 +38,7 @@ struct amdgpu_vm;
struct amdgpu_ring;
struct amdgpu_sync;
struct amdgpu_job;
+struct amdgpu_fpriv;
struct amdgpu_vmid {
struct list_head list;
@@ -92,4 +93,16 @@ void amdgpu_vmid_reset_all(struct amdgpu_device *adev);
void amdgpu_vmid_mgr_init(struct amdgpu_device *adev);
void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev);
+int amdgpu_pasid_set_fpriv(u32 pasid,
+ struct amdgpu_fpriv *fpriv);
+
+void amdgpu_pasid_clear_fpriv(u32 pasid,
+ struct amdgpu_fpriv *fpriv);
+
+void amdgpu_pasid_lock(unsigned long *flags);
+void amdgpu_pasid_unlock(unsigned long flags);
+
+struct amdgpu_fpriv *
+amdgpu_pasid_get_fpriv_locked(u32 pasid);
+
#endif
--
2.34.1