From: Mukul Joshi <[email protected]>

Add a address allocator, which uses DRM MM, for allocating and
deallocating NPA addresses for BOs exported/imported in a rack-scale
setup.

Signed-off-by: Mukul Joshi <[email protected]>
Reviewed-by: Felix Kuehling <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c | 86 ++++++++++++++++++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h | 10 +++
 2 files changed, 96 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 76aec9eaa59fe..4582299d96c4f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -23,6 +23,7 @@
  */
 
 #include <linux/xarray.h>
+#include <drm/drm_mm.h>
 #include "amdgpu.h"
 #include "amdgpu_ualink.h"
 #include "amdgpu_xgmi.h"
@@ -1070,6 +1071,87 @@ void amdgpu_ualink_sysfs_fini(struct amdgpu_device *adev)
        }
 }
 
+static int amdgpu_ualink_npa_alloc_va(struct amdgpu_device *adev,
+                              struct drm_mm_node *mm_node,
+                              u64 va, u64 range_start,
+                              u64 range_end, int size)
+{
+       struct amdgpu_ualink_npa_mm *npa_mm = &adev->ualink.npa_mm;
+       u64 alignment = 0;
+       int ret;
+
+       mutex_lock(&npa_mm->mm_lock);
+       if (va) {
+               mm_node->start = va;
+               mm_node->size = size;
+               ret = drm_mm_reserve_node(&npa_mm->mm, mm_node);
+       } else {
+               if (!range_start && !range_end) {
+                       range_start = npa_mm->va_start;
+                       range_end = npa_mm->va_start + npa_mm->va_size;
+               }
+
+               /* If size is greater than 2MB (or 512 pages),
+                * align it to 2MB (or 512 pages) granularity.
+                */
+               if (size >= 0x200)
+                       alignment = 0x200;
+
+               ret = drm_mm_insert_node_in_range(&npa_mm->mm, mm_node, size,
+                                                 alignment, 0, range_start,
+                                                 range_end, 0);
+       }
+       mutex_unlock(&npa_mm->mm_lock);
+
+       if (ret)
+               dev_err(adev->dev, "Failed to allocate NPA address\n");
+
+       return ret;
+}
+
+static void amdgpu_ualink_npa_free_va(struct amdgpu_device *adev,
+                              struct drm_mm_node *mm_node)
+{
+       struct amdgpu_ualink_npa_mm *npa_mm = &adev->ualink.npa_mm;
+
+       mutex_lock(&npa_mm->mm_lock);
+       drm_mm_remove_node(mm_node);
+       mutex_unlock(&npa_mm->mm_lock);
+}
+
+static void amdgpu_ualink_npa_mm_init(struct amdgpu_device *adev)
+{
+       struct amdgpu_ualink_npa_mm *npa_mm = &adev->ualink.npa_mm;
+       u32 addr_mode = adev->ualink.info->vpod.addr_mode;
+       u64 va_size;
+
+       mutex_init(&npa_mm->mm_lock);
+
+       if (addr_mode == AMDGPU_UALINK_ADDR_MODE_SOURCE_IDENT) {
+               /* 51 bit address space in Source-Identification mode.
+                * 39 bits in page granularity.
+                */
+               npa_mm->va_start = 0;
+               va_size = GENMASK_ULL(38, 0);
+       } else {
+               /* 41 bit address space in Source-Alias mode.
+                * 29 bits in page granularity.
+                */
+               /* First 8MB is reserved for Metadata NPAs */
+               npa_mm->va_start = 0x800;
+               va_size = GENMASK_ULL(28, 0);
+       }
+
+       npa_mm->va_size = va_size - npa_mm->va_start;
+       drm_mm_init(&npa_mm->mm, npa_mm->va_start, npa_mm->va_size);
+}
+
+static void amdgpu_ualink_npa_mm_fini(struct amdgpu_device *adev)
+{
+       mutex_destroy(&adev->ualink.npa_mm.mm_lock);
+       drm_mm_takedown(&adev->ualink.npa_mm.mm);
+}
+
 int amdgpu_ualink_manager_start(struct amdgpu_device *adev)
 {
        int i, r;
@@ -1092,6 +1174,8 @@ int amdgpu_ualink_manager_start(struct amdgpu_device 
*adev)
                INIT_LIST_HEAD(&adev->ualink.imp_handles_list[i]);
        }
 
+       amdgpu_ualink_npa_mm_init(adev);
+
        return 0;
 }
 
@@ -1099,6 +1183,8 @@ void amdgpu_ualink_manager_stop(struct amdgpu_device 
*adev)
 {
        int i;
 
+       amdgpu_ualink_npa_mm_fini(adev);
+
        xa_destroy(&adev->ualink.exp_xa);
        xa_destroy(&adev->ualink.imp_xa);
        xa_destroy(&adev->ualink.handle_invalid_xa);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
index 4b3e1f3af3333..a056d89d163ba 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
@@ -125,6 +125,13 @@ struct amdgpu_ualink_station_config {
 };
 #define to_ualink_station_config(ko) container_of(ko, struct 
amdgpu_ualink_station_config, kobj)
 
+struct amdgpu_ualink_npa_mm {
+       struct drm_mm                   mm;
+       u64                             va_start;
+       u64                             va_size;
+       struct mutex                    mm_lock;
+};
+
 struct amdgpu_ualink_connection {
        struct completion hello_done;
        struct mutex lock;
@@ -164,6 +171,9 @@ struct amdgpu_ualink_mgr {
 
        /* WQ to manage revocation of exported memory. */
        struct workqueue_struct *npa_wq;
+
+       /* Memory-manager for managing NPA address space. */
+       struct amdgpu_ualink_npa_mm npa_mm;
 };
 
 int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev);
-- 
2.55.0

Reply via email to