From: David Yat Sin <david.yatsin@xxxxxxx> Enable pc sampling create. Co-developed-by: James Zhu <James.Zhu@xxxxxxx> Signed-off-by: James Zhu <James.Zhu@xxxxxxx> Signed-off-by: David Yat Sin <david.yatsin@xxxxxxx> --- drivers/gpu/drm/amd/amdkfd/kfd_pc_sampling.c | 53 +++++++++++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 10 ++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pc_sampling.c b/drivers/gpu/drm/amd/amdkfd/kfd_pc_sampling.c index 987c415f8f0f..106fac0ba1b3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_pc_sampling.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_pc_sampling.c @@ -97,7 +97,58 @@ static int kfd_pc_sample_stop(struct kfd_process_device *pdd) static int kfd_pc_sample_create(struct kfd_process_device *pdd, struct kfd_ioctl_pc_sample_args __user *user_args) { - return -EINVAL; + struct kfd_pc_sample_info *supported_format = NULL; + struct kfd_pc_sample_info user_info; + int ret; + int i; + + if (user_args->num_sample_info != 1) + return -EINVAL; + + ret = copy_from_user(&user_info, (void __user *) user_args->sample_info_ptr, + sizeof(struct kfd_pc_sample_info)); + if (ret) { + pr_debug("Failed to copy PC sampling info from user\n"); + return -EFAULT; + } + + for (i = 0; i < ARRAY_SIZE(supported_formats); i++) { + if (KFD_GC_VERSION(pdd->dev) == supported_formats[i].ip_version + && user_info.method == supported_formats[i].sample_info->method + && user_info.type == supported_formats[i].sample_info->type + && user_info.interval <= supported_formats[i].sample_info->interval_max + && user_info.interval >= supported_formats[i].sample_info->interval_min) { + supported_format = + (struct kfd_pc_sample_info *)supported_formats[i].sample_info; + break; + } + } + + if (!supported_format) { + pr_debug("Sampling format is not supported!"); + return -EOPNOTSUPP; + } + + mutex_lock(&pdd->dev->pcs_data.mutex); + if (pdd->dev->pcs_data.hosttrap_entry.base.use_count && + memcmp(&pdd->dev->pcs_data.hosttrap_entry.base.pc_sample_info, + &user_info, sizeof(user_info))) { + ret = copy_to_user((void __user *) user_args->sample_info_ptr, + &pdd->dev->pcs_data.hosttrap_entry.base.pc_sample_info, + sizeof(struct kfd_pc_sample_info)); + mutex_unlock(&pdd->dev->pcs_data.mutex); + return ret ? -EFAULT : -EEXIST; + } + + /* TODO: add trace_id return */ + + if (!pdd->dev->pcs_data.hosttrap_entry.base.use_count) + pdd->dev->pcs_data.hosttrap_entry.base.pc_sample_info = user_info; + + pdd->dev->pcs_data.hosttrap_entry.base.use_count++; + mutex_unlock(&pdd->dev->pcs_data.mutex); + + return 0; } static int kfd_pc_sample_destroy(struct kfd_process_device *pdd, uint32_t trace_id) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index cbaa1bccd94b..db2d09db8000 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -269,9 +269,19 @@ struct kfd_vmid_info { struct kfd_dev; +struct kfd_dev_pc_sampling_data { + uint32_t use_count; /* Num of PC sampling sessions */ + struct kfd_pc_sample_info pc_sample_info; +}; + +struct kfd_dev_pcs_hosttrap { + struct kfd_dev_pc_sampling_data base; +}; + /* Per device PC Sampling data */ struct kfd_dev_pc_sampling { struct mutex mutex; + struct kfd_dev_pcs_hosttrap hosttrap_entry; }; struct kfd_node { -- 2.25.1