drm/radeon: Add PASID manager for KFD
authorFelix Kuehling <Felix.Kuehling@amd.com>
Sat, 26 Aug 2017 01:30:18 +0000 (21:30 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 17:07:02 +0000 (13:07 -0400)
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/radeon_kfd.c

index f6578c9..a2ac8ac 100644 (file)
@@ -58,6 +58,10 @@ static uint64_t get_vmem_size(struct kgd_dev *kgd);
 static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd);
 
 static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd);
+
+static int alloc_pasid(unsigned int bits);
+static void free_pasid(unsigned int pasid);
+
 static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type);
 
 /*
@@ -112,6 +116,8 @@ static const struct kfd2kgd_calls kfd2kgd = {
        .get_vmem_size = get_vmem_size,
        .get_gpu_clock_counter = get_gpu_clock_counter,
        .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz,
+       .alloc_pasid = alloc_pasid,
+       .free_pasid = free_pasid,
        .program_sh_mem_settings = kgd_program_sh_mem_settings,
        .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
        .init_pipeline = kgd_init_pipeline,
@@ -341,6 +347,31 @@ static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd)
        return rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk / 100;
 }
 
+/*
+ * PASID manager
+ */
+static DEFINE_IDA(pasid_ida);
+
+int alloc_pasid(unsigned int bits)
+{
+       int pasid = -EINVAL;
+
+       for (bits = min(bits, 31U); bits > 0; bits--) {
+               pasid = ida_simple_get(&pasid_ida,
+                                      1U << (bits - 1), 1U << bits,
+                                      GFP_KERNEL);
+               if (pasid != -ENOSPC)
+                       break;
+       }
+
+       return pasid;
+}
+
+void free_pasid(unsigned int pasid)
+{
+       ida_simple_remove(&pasid_ida, pasid);
+}
+
 static inline struct radeon_device *get_radeon_device(struct kgd_dev *kgd)
 {
        return (struct radeon_device *)kgd;