diff --git a/drivers/char/fastcvpd.c b/drivers/char/fastcvpd.c index ef043bc85273..279fc71b53a7 100644 --- a/drivers/char/fastcvpd.c +++ b/drivers/char/fastcvpd.c @@ -14,8 +14,12 @@ #include #include #include +#include #include "linux/fastcvpd.h" +#define VMID_CDSP_Q6 (30) +#define SRC_VM_NUM 1 +#define DEST_VM_NUM 2 #define FASTCVPD_VIDEO_SEND_HFI_CMD_QUEUE 0 #define FASTCVPD_VIDEO_SUSPEND 1 #define FASTCVPD_VIDEO_RESUME 2 @@ -28,14 +32,25 @@ struct fastcvpd_cmd_msg { uint32_t msg_ptr_len; }; +struct fastcvpd_cmd_msg_rsp { + int ret_val; +}; + struct fastcvpd_apps { struct rpmsg_device *chan; struct mutex smd_mutex; int rpmsg_register; + spinlock_t hlock; }; +static struct completion work; + static struct fastcvpd_apps gfa_cv; +static struct fastcvpd_cmd_msg cmd_msg; + +static struct fastcvpd_cmd_msg_rsp cmd_msg_rsp; + static int fastcvpd_send_cmd(void *msg, uint32_t len) { struct fastcvpd_apps *me = &gfa_cv; @@ -82,6 +97,14 @@ static void fastcvpd_rpmsg_remove(struct rpmsg_device *rpdev) static int fastcvpd_rpmsg_callback(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 addr) { + int *rpmsg_resp = (int *)data; + struct fastcvpd_apps *me = &gfa_cv; + + spin_lock(&me->hlock); + cmd_msg_rsp.ret_val = *rpmsg_resp; + spin_unlock(&me->hlock); + complete(&work); + return 0; } @@ -89,17 +112,39 @@ int fastcvpd_video_send_cmd_hfi_queue(phys_addr_t *phys_addr, uint32_t size_in_bytes) { int err; - struct fastcvpd_cmd_msg cmd_msg; + struct fastcvpd_cmd_msg local_cmd_msg; + struct fastcvpd_apps *me = &gfa_cv; + int srcVM[SRC_VM_NUM] = {VMID_HLOS}; + int destVM[DEST_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6}; + int destVMperm[DEST_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC, + PERM_READ | PERM_WRITE | PERM_EXEC }; - cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_SEND_HFI_CMD_QUEUE; + local_cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_SEND_HFI_CMD_QUEUE; + local_cmd_msg.msg_ptr = (uint64_t)phys_addr; + local_cmd_msg.msg_ptr_len = size_in_bytes; + mutex_lock(&me->smd_mutex); cmd_msg.msg_ptr = (uint64_t)phys_addr; - cmd_msg.msg_ptr_len = size_in_bytes; + cmd_msg.msg_ptr_len = (size_in_bytes); + mutex_unlock(&me->smd_mutex); + + pr_debug("%s :: address of buffer, PA=0x%pK size_buff=%d\n", + __func__, phys_addr, size_in_bytes); + + err = hyp_assign_phys((uint64_t)local_cmd_msg.msg_ptr, + local_cmd_msg.msg_ptr_len, srcVM, SRC_VM_NUM, destVM, + destVMperm, DEST_VM_NUM); + if (err) { + pr_err("%s: Failed in hyp_assign. err=%d\n", + __func__, err); + return err; + } err = fastcvpd_send_cmd - (&cmd_msg, sizeof(struct fastcvpd_cmd_msg)); + (&local_cmd_msg, sizeof(struct fastcvpd_cmd_msg)); if (err != 0) pr_err("%s: fastcvpd_send_cmd failed with err=%d\n", __func__, err); + return err; } EXPORT_SYMBOL(fastcvpd_video_send_cmd_hfi_queue); @@ -107,14 +152,15 @@ EXPORT_SYMBOL(fastcvpd_video_send_cmd_hfi_queue); int fastcvpd_video_suspend(uint32_t session_flag) { int err = 0; - struct fastcvpd_cmd_msg cmd_msg; + struct fastcvpd_cmd_msg local_cmd_msg; - cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_SUSPEND; + local_cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_SUSPEND; err = fastcvpd_send_cmd - (&cmd_msg, sizeof(struct fastcvpd_cmd_msg)); + (&local_cmd_msg, sizeof(struct fastcvpd_cmd_msg)); if (err != 0) pr_err("%s: fastcvpd_send_cmd failed with err=%d\n", __func__, err); + return err; } EXPORT_SYMBOL(fastcvpd_video_suspend); @@ -122,29 +168,56 @@ EXPORT_SYMBOL(fastcvpd_video_suspend); int fastcvpd_video_resume(uint32_t session_flag) { int err; - struct fastcvpd_cmd_msg cmd_msg; + struct fastcvpd_cmd_msg local_cmd_msg; - cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_RESUME; + local_cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_RESUME; err = fastcvpd_send_cmd - (&cmd_msg, sizeof(struct fastcvpd_cmd_msg)); + (&local_cmd_msg, sizeof(struct fastcvpd_cmd_msg)); if (err != 0) pr_err("%s: fastcvpd_send_cmd failed with err=%d\n", __func__, err); + return err; } EXPORT_SYMBOL(fastcvpd_video_resume); int fastcvpd_video_shutdown(uint32_t session_flag) { + struct fastcvpd_apps *me = &gfa_cv; int err; - struct fastcvpd_cmd_msg cmd_msg; + struct fastcvpd_cmd_msg local_cmd_msg; + int srcVM[DEST_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6}; + int destVM[SRC_VM_NUM] = {VMID_HLOS}; + int destVMperm[SRC_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC }; - cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_SHUTDOWN; + local_cmd_msg.cmd_msg_type = FASTCVPD_VIDEO_SHUTDOWN; err = fastcvpd_send_cmd - (&cmd_msg, sizeof(struct fastcvpd_cmd_msg)); + (&local_cmd_msg, sizeof(struct fastcvpd_cmd_msg)); if (err != 0) pr_err("%s: fastcvpd_send_cmd failed with err=%d\n", __func__, err); + + wait_for_completion(&work); + + spin_lock(&me->hlock); + local_cmd_msg.msg_ptr = cmd_msg.msg_ptr; + local_cmd_msg.msg_ptr_len = cmd_msg.msg_ptr_len; + if (cmd_msg_rsp.ret_val == 0) { + err = hyp_assign_phys((uint64_t)local_cmd_msg.msg_ptr, + local_cmd_msg.msg_ptr_len, srcVM, DEST_VM_NUM, destVM, + destVMperm, SRC_VM_NUM); + if (err) { + pr_err("%s: Failed to hyp_assign. err=%d\n", + __func__, err); + spin_unlock(&me->hlock); + return err; + } + } else { + pr_err("%s: Skipping hyp_assign as CDSP sent invalid response=%d\n", + __func__, cmd_msg_rsp.ret_val); + } + spin_unlock(&me->hlock); + return err; } EXPORT_SYMBOL(fastcvpd_video_shutdown); @@ -169,7 +242,9 @@ static int __init fastcvpd_device_init(void) struct fastcvpd_apps *me = &gfa_cv; int err; + init_completion(&work); mutex_init(&me->smd_mutex); + spin_lock_init(&me->hlock); err = register_rpmsg_driver(&fastcvpd_rpmsg_client); if (err) { pr_err("%s : register_rpmsg_driver failed with err %d\n", @@ -187,6 +262,7 @@ static void __exit fastcvpd_device_exit(void) { struct fastcvpd_apps *me = &gfa_cv; + mutex_destroy(&me->smd_mutex); if (me->rpmsg_register == 1) unregister_rpmsg_driver(&fastcvpd_rpmsg_client); }