}
#endif
+static int kfd_ptl_control(struct kfd_process_device *pdd, bool enable)
+{
+ struct amdgpu_device *adev = pdd->dev->adev;
+ struct amdgpu_ptl *ptl = &adev->psp.ptl;
+ enum amdgpu_ptl_fmt pref_format1 = ptl->fmt1;
+ enum amdgpu_ptl_fmt pref_format2 = ptl->fmt2;
+ uint32_t ptl_state = enable ? 1 : 0;
+ int ret;
+
+ if (!ptl->hw_supported)
+ return -EOPNOTSUPP;
+
+ if (!pdd->dev->kfd2kgd || !pdd->dev->kfd2kgd->ptl_ctrl)
+ return -EOPNOTSUPP;
+
+ ret = pdd->dev->kfd2kgd->ptl_ctrl(adev, PSP_PTL_PERF_MON_SET,
+ &ptl_state,
+ &pref_format1,
+ &pref_format2);
+ return ret;
+}
+
+int kfd_ptl_disable_request(struct kfd_process_device *pdd,
+ struct kfd_process *p)
+{
+ struct amdgpu_device *adev = pdd->dev->adev;
+ struct amdgpu_ptl *ptl = &adev->psp.ptl;
+ int ret = 0;
+
+ mutex_lock(&ptl->mutex);
+
+ if (pdd->ptl_disable_req)
+ goto out;
+
+ if (atomic_inc_return(&ptl->disable_ref) == 1) {
+ ret = kfd_ptl_control(pdd, false);
+ if (ret) {
+ atomic_dec(&ptl->disable_ref);
+ dev_warn(pdd->dev->adev->dev,
+ "failed to disable PTL\n");
+ goto out;
+ }
+ }
+ pdd->ptl_disable_req = true;
+
+out:
+ mutex_unlock(&ptl->mutex);
+ return ret;
+}
+
+int kfd_ptl_disable_release(struct kfd_process_device *pdd,
+ struct kfd_process *p)
+{
+ struct amdgpu_device *adev = pdd->dev->adev;
+ struct amdgpu_ptl *ptl = &adev->psp.ptl;
+ int ret = 0;
+
+ mutex_lock(&ptl->mutex);
+
+ if (!pdd->ptl_disable_req)
+ goto out;
+
+ if (atomic_dec_return(&ptl->disable_ref) == 0) {
+ ret = kfd_ptl_control(pdd, true);
+ if (ret) {
+ atomic_inc(&ptl->disable_ref);
+ dev_warn(adev->dev, "Failed to enable PTL on release: %d\n", ret);
+ goto out;
+ }
+ }
+ pdd->ptl_disable_req = false;
+
+out:
+ mutex_unlock(&ptl->mutex);
+ return ret;
+}
+
+static int kfd_profiler_ptl_control(struct kfd_process *p,
+ struct kfd_ioctl_ptl_control *args)
+{
+ struct kfd_process_device *pdd;
+ int ret;
+
+ mutex_lock(&p->mutex);
+ pdd = kfd_process_device_data_by_id(p, args->gpu_id);
+ mutex_unlock(&p->mutex);
+
+ if (!pdd || !pdd->dev || !pdd->dev->kfd)
+ return -EINVAL;
+
+ if (args->enable == 0)
+ ret = kfd_ptl_disable_request(pdd, p);
+ else
+ ret = kfd_ptl_disable_release(pdd, p);
+
+ return ret;
+}
+
static int criu_checkpoint_process(struct kfd_process *p,
uint8_t __user *user_priv_data,
uint64_t *priv_offset)
if (!kfd->profiler_process) {
kfd->profiler_process = p;
status = 0;
+ kfd_ptl_disable_request(pdd, p);
} else if (kfd->profiler_process == p) {
status = -EALREADY;
} else {
} else if (op == 0 && kfd->profiler_process == p) {
kfd->profiler_process = NULL;
status = 0;
+ kfd_ptl_disable_release(pdd, p);
}
mutex_unlock(&kfd->profiler_lock);
return 0;
case KFD_IOC_PROFILER_PMC:
return kfd_profiler_pmc(p, &args->pmc);
+ case KFD_IOC_PROFILER_PTL_CONTROL:
+ return kfd_profiler_ptl_control(p, &args->ptl);
}
return -EINVAL;
}
enum kfd_profiler_ops {
KFD_IOC_PROFILER_PMC = 0,
KFD_IOC_PROFILER_VERSION = 2,
+ KFD_IOC_PROFILER_PTL_CONTROL = 3,
};
/**
__u32 perfcount_enable; /* Force Perfcount Enable for queues on GPU */
};
+struct kfd_ioctl_ptl_control {
+ __u32 gpu_id; /* user_gpu_id */
+ __u32 enable; /* set 1 to enable PTL, set 0 to disable PTL */
+};
+
struct kfd_ioctl_profiler_args {
__u32 op; /* kfd_profiler_op */
union {
struct kfd_ioctl_pmc_settings pmc;
+ struct kfd_ioctl_ptl_control ptl;
__u32 version; /* KFD_IOC_PROFILER_VERSION_NUM */
};
};