From: Mukul Joshi <[email protected]>

This patch introduces AMDGPU UALink manager core infrastructure
which will be responsible for sharing buffer objects across
multiple GPUs, with each GPU running their own OS, in a rack scale
setup. The core infrastructure of the ualink manager will include:
- Store BOs exported from a GPU.
- Store BOs imported by a GPU.
- Store connection state with different GPUs.

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 | 42 +++++++++++++++++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h | 41 ++++++++++++++++++++-
 2 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 3bffb3cb21681..d91365399c767 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -22,9 +22,10 @@
  *
  */
 
+#include <linux/xarray.h>
+#include "amdgpu.h"
 #include "amdgpu_ualink.h"
 #include "amdgpu_xgmi.h"
-#include "amdgpu.h"
 #include <linux/sysfs.h>
 #include <linux/string.h>
 
@@ -1003,3 +1004,42 @@ void amdgpu_ualink_sysfs_fini(struct amdgpu_device *adev)
                adev->ualink.info = NULL;
        }
 }
+
+int amdgpu_ualink_manager_start(struct amdgpu_device *adev)
+{
+       int i, r;
+
+       adev->ualink.npa_wq = alloc_workqueue("NPA WQ", WQ_UNBOUND, 0);
+       if (unlikely(!adev->ualink.npa_wq)) {
+               dev_err(adev->dev, "Failed to allocate NPA WQ\n");
+               return -ENOMEM;
+       }
+
+       xa_init_flags(&adev->ualink.exp_xa, XA_FLAGS_LOCK_BH);
+       xa_init_flags(&adev->ualink.imp_xa, XA_FLAGS_LOCK_BH);
+       xa_init_flags(&adev->ualink.handle_invalid_xa, XA_FLAGS_LOCK_BH);
+
+       for (i = 0; i < AMDGPU_UALINK_ACCEL_MAX; i++) {
+               init_completion(&adev->ualink.conn_state[i].hello_done);
+               mutex_init(&adev->ualink.conn_state[i].lock);
+               adev->ualink.conn_state[i].state = AMDGPU_UALINK_CONN_NOT_READY;
+               INIT_LIST_HEAD(&adev->ualink.exp_handles_list[i]);
+               INIT_LIST_HEAD(&adev->ualink.imp_handles_list[i]);
+       }
+
+       return 0;
+}
+
+void amdgpu_ualink_manager_stop(struct amdgpu_device *adev)
+{
+       int i;
+
+       xa_destroy(&adev->ualink.exp_xa);
+       xa_destroy(&adev->ualink.imp_xa);
+       xa_destroy(&adev->ualink.handle_invalid_xa);
+
+       for (i = 0; i < AMDGPU_UALINK_ACCEL_MAX; i++)
+               mutex_destroy(&adev->ualink.conn_state[i].lock);
+
+       destroy_workqueue(adev->ualink.npa_wq);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
index 2d685f6dd7e7d..3882f29ccdae0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
@@ -35,6 +35,12 @@ struct amdgpu_device;
 #define AMDGPU_UALINK_LOCAL_ACCELS_MAX 8
 #define AMDGPU_UALINK_STATIONS_MAX 64
 
+enum amdgpu_ualink_conn_state {
+       AMDGPU_UALINK_CONN_NOT_READY                    = 0,
+       AMDGPU_UALINK_CONN_IN_PROGRESS                  = 1,
+       AMDGPU_UALINK_CONN_ESTABLISHED                  = 2
+};
+
 enum amdgpu_ualink_type {
        AMDGPU_UALINK_TYPE_UALOE = 0,
        AMDGPU_UALINK_TYPE_UALINK = 1,
@@ -119,14 +125,47 @@ struct amdgpu_ualink_station_config {
 };
 #define to_ualink_station_config(ko) container_of(ko, struct 
amdgpu_ualink_station_config, kobj)
 
+struct amdgpu_ualink_connection {
+       struct completion hello_done;
+       struct mutex lock;
+       u32 generation_count;
+       enum amdgpu_ualink_conn_state state;
+};
+
 struct amdgpu_ualink_mgr {
        struct amdgpu_ualink_info *info;
        struct amdgpu_ualink_ppod_setup *setup;
        struct amdgpu_ualink_vpod_config *config;
        struct amdgpu_ualink_station_config *stations;
+
+       /* Xarray to store info about exported BOs */
+       struct xarray   exp_xa;
+
+       /* Xarray to store info about imported ualink handles */
+       struct xarray   imp_xa;
+
+       /* Xarray to store handles to be deleted */
+       struct xarray   handle_invalid_xa;
+
+       /* Array to store connection state per remote GPU */
+       struct amdgpu_ualink_connection conn_state[AMDGPU_UALINK_ACCEL_MAX];
+
+       /* List of exported ualink handles per GPU. Used to quickly traverse
+        * the list of all handles exported to a remote GPU.
+        */
+       struct list_head exp_handles_list[AMDGPU_UALINK_ACCEL_MAX];
+
+       /* List of imported ualink handles per GPU. Used to quickly traverse
+        * the list of all handles imported from a remote GPU.
+        */
+       struct list_head imp_handles_list[AMDGPU_UALINK_ACCEL_MAX];
+
+       /* WQ to manage revocation of exported memory. */
+       struct workqueue_struct *npa_wq;
 };
 
 int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev);
 void amdgpu_ualink_sysfs_fini(struct amdgpu_device *adev);
-
+int amdgpu_ualink_manager_start(struct amdgpu_device *adev);
+void amdgpu_ualink_manager_stop(struct amdgpu_device *adev);
 #endif
-- 
2.55.0

Reply via email to