From ae7f592cfc0d7b5ba56bbd219fbf8c56adb56dc0 Mon Sep 17 00:00:00 2001 From: Ruofei Ma Date: Mon, 13 Jan 2020 18:40:45 -0800 Subject: [PATCH] msm: cvp: CVP DSP driver restructure for Lahaina Restructure CVP DSP driver to enhance error handling path and accommodate features for future needs. Change-Id: Icae8110241fa9598a8d570cc1148a00834cda779 Signed-off-by: Ruofei Ma Signed-off-by: George Shen --- drivers/media/platform/msm/cvp/cvp.c | 17 +- drivers/media/platform/msm/cvp/cvp_core_hfi.h | 10 +- drivers/media/platform/msm/cvp/cvp_hfi.c | 105 +-- drivers/media/platform/msm/cvp/msm_cvp_dsp.c | 737 ++++++++---------- drivers/media/platform/msm/cvp/msm_cvp_dsp.h | 73 +- .../media/platform/msm/cvp/msm_cvp_internal.h | 14 +- 6 files changed, 389 insertions(+), 567 deletions(-) diff --git a/drivers/media/platform/msm/cvp/cvp.c b/drivers/media/platform/msm/cvp/cvp.c index 6155762c503e..09280360976f 100644 --- a/drivers/media/platform/msm/cvp/cvp.c +++ b/drivers/media/platform/msm/cvp/cvp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include @@ -26,7 +26,6 @@ #include "msm_cvp_clocks.h" #include "msm_cvp_dsp.h" -#define BASE_DEVICE_NUMBER 32 #define CLASS_NAME "cvp" #define DRIVER_NAME "cvp" @@ -34,18 +33,15 @@ struct msm_cvp_drv *cvp_driver; static int cvp_open(struct inode *inode, struct file *filp) { - int rc; struct msm_cvp_core *core = container_of(inode->i_cdev, struct msm_cvp_core, cdev); struct msm_cvp_inst *inst; dprintk(CVP_DBG, "%s: Enter\n", __func__); - rc = cvp_dsp_device_init(); inst = msm_cvp_open(core->id, MSM_CVP_USER); - if (!inst || rc) { - dprintk(CVP_ERR, - "Failed to create cvp instance rc=%d\n", rc); + if (!inst) { + dprintk(CVP_ERR, "Failed to create cvp instance\n"); return -ENOMEM; } filp->private_data = inst; @@ -551,8 +547,7 @@ static int __init msm_cvp_init(void) { int rc = 0; - cvp_driver = kzalloc(sizeof(*cvp_driver), - GFP_KERNEL); + cvp_driver = kzalloc(sizeof(*cvp_driver), GFP_KERNEL); if (!cvp_driver) { dprintk(CVP_ERR, "Failed to allocate memroy for msm_cvp_drv\n"); @@ -582,6 +577,10 @@ static int __init msm_cvp_init(void) cvp_driver->frame_buf_cache = KMEM_CACHE(msm_cvp_frame_buf, 0); cvp_driver->internal_buf_cache = KMEM_CACHE(msm_cvp_internal_buffer, 0); + rc = cvp_dsp_device_init(); + if (rc) + dprintk(CVP_WARN, "Failed to initialize DSP driver\n"); + return rc; } diff --git a/drivers/media/platform/msm/cvp/cvp_core_hfi.h b/drivers/media/platform/msm/cvp/cvp_core_hfi.h index 054cceed5807..427f06350358 100644 --- a/drivers/media/platform/msm/cvp/cvp_core_hfi.h +++ b/drivers/media/platform/msm/cvp/cvp_core_hfi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef __H_CVP_CORE_HFI_H__ @@ -201,11 +201,6 @@ struct iris_resources { struct msm_cvp_fw fw; }; -enum dsp_flag { - DSP_INIT = BIT(0), - DSP_SUSPEND = BIT(1), -}; - enum iris_hfi_state { IRIS_STATE_DEINIT = 1, IRIS_STATE_INIT, @@ -229,7 +224,6 @@ struct iris_hfi_vpu_ops { }; struct iris_hfi_device { - struct list_head list; struct list_head sess_head; u32 version; u32 intr_status; @@ -250,7 +244,6 @@ struct iris_hfi_device { struct cvp_mem_addr mem_addr; struct cvp_iface_q_info iface_queues[CVP_IFACEQ_NUMQ]; struct cvp_iface_q_info dsp_iface_queues[CVP_IFACEQ_NUMQ]; - u32 dsp_flags; struct cvp_hal_data *cvp_hal_data; struct workqueue_struct *cvp_workq; struct workqueue_struct *iris_pm_workq; @@ -267,7 +260,6 @@ struct iris_hfi_device { unsigned int skip_pc_count; struct msm_cvp_capability *sys_init_capabilities; struct iris_hfi_vpu_ops *vpu_ops; - struct delayed_work dsp_init_work; }; void cvp_iris_hfi_delete_device(void *device); diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index 1d5295d53d50..a2625c694f17 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -264,7 +264,6 @@ const int cvp_max_packets = 32; static void iris_hfi_pm_handler(struct work_struct *work); static DECLARE_DELAYED_WORK(iris_hfi_pm_work, iris_hfi_pm_handler); -static void dsp_init_work_handler(struct work_struct *work); static inline int __resume(struct iris_hfi_device *device); static inline int __suspend(struct iris_hfi_device *device); static int __disable_regulators(struct iris_hfi_device *device); @@ -420,41 +419,6 @@ static void __dump_packet(u8 *packet, enum cvp_msg_prio log_level) } } -static int __dsp_send_hfi_queue(struct iris_hfi_device *device) -{ - int rc; - - if (msm_cvp_dsp_disable) { - dprintk(CVP_WARN, "%s: DSP support is disabled\n", __func__); - return 0; - } - - if (!device->dsp_iface_q_table.mem_data.dma_handle) { - dprintk(CVP_ERR, "%s: invalid dsm_handle\n", __func__); - return -EINVAL; - } - - if (device->dsp_flags & DSP_INIT) { - dprintk(CVP_DBG, "%s: dsp already inited\n", __func__); - return 0; - } - - dprintk(CVP_DBG, "%s: hfi queue %#llx size %d\n", - __func__, device->dsp_iface_q_table.mem_data.dma_handle, - device->dsp_iface_q_table.mem_data.size); - rc = cvp_dsp_send_cmd_hfi_queue( - (phys_addr_t *)device->dsp_iface_q_table.mem_data.dma_handle, - device->dsp_iface_q_table.mem_data.size, device); - if (rc) { - dprintk(CVP_ERR, "%s: dsp hfi queue init failed\n", __func__); - return rc; - } - - device->dsp_flags |= DSP_INIT; - dprintk(CVP_DBG, "%s: dsp inited\n", __func__); - return rc; -} - static int __dsp_suspend(struct iris_hfi_device *device, bool force, u32 flags) { int rc; @@ -463,12 +427,6 @@ static int __dsp_suspend(struct iris_hfi_device *device, bool force, u32 flags) if (msm_cvp_dsp_disable) return 0; - if (!(device->dsp_flags & DSP_INIT)) - return 0; - - if (device->dsp_flags & DSP_SUSPEND) - return 0; - list_for_each_entry(temp, &device->sess_head, list) { /* if forceful suspend, don't check session pause info */ if (force) @@ -491,7 +449,6 @@ static int __dsp_suspend(struct iris_hfi_device *device, bool force, u32 flags) return -EINVAL; } - device->dsp_flags |= DSP_SUSPEND; dprintk(CVP_DBG, "%s: dsp suspended\n", __func__); return 0; } @@ -503,11 +460,6 @@ static int __dsp_resume(struct iris_hfi_device *device, u32 flags) if (msm_cvp_dsp_disable) return 0; - if (!(device->dsp_flags & DSP_SUSPEND)) { - dprintk(CVP_DBG, "%s: dsp not suspended\n", __func__); - return 0; - } - dprintk(CVP_DBG, "%s: resume dsp\n", __func__); rc = cvp_dsp_resume(flags); if (rc) { @@ -517,7 +469,6 @@ static int __dsp_resume(struct iris_hfi_device *device, u32 flags) return rc; } - device->dsp_flags &= ~DSP_SUSPEND; dprintk(CVP_DBG, "%s: dsp resumed\n", __func__); return rc; } @@ -529,13 +480,6 @@ static int __dsp_shutdown(struct iris_hfi_device *device, u32 flags) if (msm_cvp_dsp_disable) return 0; - cvp_dsp_set_cvp_ssr(); - - if (!(device->dsp_flags & DSP_INIT)) { - dprintk(CVP_WARN, "%s: dsp not inited\n", __func__); - return 0; - } - dprintk(CVP_DBG, "%s: shutdown dsp\n", __func__); rc = cvp_dsp_shutdown(flags); if (rc) { @@ -545,7 +489,6 @@ static int __dsp_shutdown(struct iris_hfi_device *device, u32 flags) WARN_ON(1); } - device->dsp_flags &= ~DSP_INIT; dprintk(CVP_DBG, "%s: dsp shutdown successful\n", __func__); return rc; } @@ -1992,43 +1935,6 @@ static int __sys_set_power_control(struct iris_hfi_device *device, return 0; } -static void dsp_init_work_handler(struct work_struct *work) -{ - int rc = 0; - static int retry_count; - struct iris_hfi_device *device; - - if (!work) { - dprintk(CVP_ERR, "%s: NULL device\n", __func__); - return; - } - - device = container_of(work, struct iris_hfi_device, dsp_init_work.work); - if (!device) { - dprintk(CVP_ERR, "%s: NULL device\n", __func__); - return; - } - - dprintk(CVP_PROF, "Entering %s\n", __func__); - - mutex_lock(&device->lock); - rc = __dsp_send_hfi_queue(device); - mutex_unlock(&device->lock); - - if (rc) { - if (retry_count > MAX_DSP_INIT_ATTEMPTS) { - dprintk(CVP_ERR, "%s: max trials exceeded\n", __func__); - return; - } - dprintk(CVP_PROF, "%s: Attempt to init DSP %d\n", - __func__, retry_count); - - schedule_delayed_work(&device->dsp_init_work, - msecs_to_jiffies(CVP_MAX_WAIT_TIME)); - ++retry_count; - } -} - static int iris_hfi_core_init(void *device) { int rc = 0; @@ -2115,13 +2021,12 @@ static int iris_hfi_core_init(void *device) pm_qos_add_request(&dev->qos, PM_QOS_CPU_DMA_LATENCY, dev->res->pm_qos_latency_us); - rc = __dsp_send_hfi_queue(device); - if (rc) - schedule_delayed_work(&dev->dsp_init_work, - msecs_to_jiffies(CVP_MAX_WAIT_TIME)); + mutex_unlock(&dev->lock); + + cvp_dsp_send_hfi_queue(); dprintk(CVP_DBG, "Core inited successfully\n"); - mutex_unlock(&dev->lock); + return 0; err_core_init: __set_state(dev, IRIS_STATE_DEINIT); @@ -4574,8 +4479,6 @@ static struct iris_hfi_device *__add_device(u32 device_id, mutex_init(&hdevice->lock); INIT_LIST_HEAD(&hdevice->sess_head); - INIT_DELAYED_WORK(&hdevice->dsp_init_work, dsp_init_work_handler); - return hdevice; err_cleanup: diff --git a/drivers/media/platform/msm/cvp/msm_cvp_dsp.c b/drivers/media/platform/msm/cvp/msm_cvp_dsp.c index 1e08f85234a3..daeaa63245f0 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_dsp.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_dsp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include #include @@ -8,405 +8,284 @@ #include #include #include "msm_cvp_dsp.h" - -#define VMID_CDSP_Q6 (30) -#define SRC_VM_NUM 1 -#define DEST_VM_NUM 2 -#define CVP_DSP_SEND_HFI_CMD_QUEUE 0 -#define CVP_DSP_SUSPEND 1 -#define CVP_DSP_RESUME 2 -#define CVP_DSP_SHUTDOWN 3 -#define CVP_DSP_REGISTER_BUFFER 4 -#define CVP_DSP_DEREGISTER_BUFFER 5 -#define STATUS_INIT 0 -#define STATUS_DEINIT 1 -#define STATUS_OK 2 -#define STATUS_SSR 3 -#define CVP_DSP_MAX_RESERVED 5 - -struct cvp_dsp_cmd_msg { - uint32_t cmd_msg_type; - int32_t ret_val; - uint64_t msg_ptr; - uint32_t msg_ptr_len; - uint32_t buff_fd_iova; - uint32_t buff_index; - uint32_t buff_size; - uint32_t session_id; - int32_t ddr_type; - uint32_t buff_fd; - uint32_t buff_offset; - uint32_t buff_fd_size; - uint32_t reserved1; - uint32_t reserved2; -}; - -struct cvp_dsp_rsp_msg { - uint32_t cmd_msg_type; - int32_t ret_val; - uint32_t reserved[CVP_DSP_MAX_RESERVED]; -}; - -struct cvp_dsp_rsp_context { - struct completion work; -}; +#include "msm_cvp_internal.h" struct cvp_dsp_apps { + struct mutex lock; struct rpmsg_device *chan; - struct mutex smd_mutex; - struct mutex reg_buffer_mutex; - struct mutex dereg_buffer_mutex; - int rpmsg_register; - uint32_t cdsp_state; - uint32_t cvp_shutdown; - struct completion reg_buffer_work; - struct completion dereg_buffer_work; - struct completion shutdown_work; - struct completion cmdqueue_send_work; - struct work_struct ssr_work; - struct iris_hfi_device *device; + uint32_t state; + bool hyp_assigned; + uint64_t addr; + uint32_t size; + struct completion completions[CVP_DSP_MAX_CMD]; }; - static struct cvp_dsp_apps gfa_cv; +static int hlosVM[HLOS_VM_NUM] = {VMID_HLOS}; +static int dspVM[DSP_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6}; +static int dspVMperm[DSP_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC, + PERM_READ | PERM_WRITE | PERM_EXEC }; +static int hlosVMperm[HLOS_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC }; -static struct cvp_dsp_cmd_msg cmd_msg; - -static struct cvp_dsp_rsp_msg cmd_msg_rsp; - -static int cvp_dsp_send_cmd(void *msg, uint32_t len) +static int cvp_dsp_send_cmd(struct cvp_dsp_cmd_msg *cmd, uint32_t len) { + int rc = 0; struct cvp_dsp_apps *me = &gfa_cv; - int err = 0; + + dprintk(CVP_DBG, "%s: cmd = %d\n", __func__, cmd->type); if (IS_ERR_OR_NULL(me->chan)) { dprintk(CVP_ERR, "%s: DSP GLink is not ready\n", __func__); - err = -EINVAL; - goto bail; + rc = -EINVAL; + goto exit; + } + rc = rpmsg_send(me->chan->ept, cmd, len); + if (rc) { + dprintk(CVP_ERR, "%s: DSP rpmsg_send failed rc=%d\n", + __func__, rc); + goto exit; } - err = rpmsg_send(me->chan->ept, msg, len); -bail: - return err; +exit: + return rc; } -void msm_cvp_cdsp_ssr_handler(struct work_struct *work) +static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd, uint32_t len) { - struct cvp_dsp_apps *me; - uint64_t msg_ptr; - uint32_t msg_ptr_len; - int err; + int rc = 0; + struct cvp_dsp_apps *me = &gfa_cv; - me = container_of(work, struct cvp_dsp_apps, ssr_work); - if (!me) { - dprintk(CVP_ERR, "%s: Invalid params\n", __func__); - return; + dprintk(CVP_DBG, "%s: cmd = %d\n", __func__, cmd->type); + + rc = cvp_dsp_send_cmd(cmd, len); + if (rc) { + dprintk(CVP_ERR, "%s: cvp_dsp_send_cmd failed rc=%d\n", + __func__, rc); + goto exit; } - msg_ptr = cmd_msg.msg_ptr; - msg_ptr_len = cmd_msg.msg_ptr_len; + if (!wait_for_completion_timeout(&me->completions[cmd->type], + msecs_to_jiffies(CVP_DSP_RESPONSE_TIMEOUT))) { + dprintk(CVP_ERR, "%s cmd %d timeout\n", __func__, cmd->type); + rc = -ETIMEDOUT; + goto exit; + } - err = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)msg_ptr, - msg_ptr_len, - (void *)NULL); - if (err) { +exit: + return rc; +} + +static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr, + uint32_t size_in_bytes) +{ + int rc = 0; + struct cvp_dsp_cmd_msg cmd; + + cmd.type = CVP_DSP_SEND_HFI_QUEUE; + cmd.msg_ptr = (uint64_t)phys_addr; + cmd.msg_ptr_len = size_in_bytes; + cmd.ddr_type = of_fdt_get_ddrtype(); + if (cmd.ddr_type < 0) { dprintk(CVP_ERR, - "%s: Failed to send HFI Queue address. err=%d\n", - __func__, err); - return; + "%s: Incorrect DDR type value %d\n", + __func__, cmd.ddr_type); + return -EINVAL; } - if (me->device) { - mutex_lock(&me->device->lock); - me->device->dsp_flags |= DSP_INIT; - mutex_unlock(&me->device->lock); + dprintk(CVP_DBG, + "%s: address of buffer, PA=0x%pK size_buff=%d ddr_type=%d\n", + __func__, phys_addr, size_in_bytes, cmd.ddr_type); + + rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg)); + if (rc) { + dprintk(CVP_ERR, + "%s: cvp_dsp_send_cmd failed rc = %d\n", + __func__, rc); + goto exit; } - dprintk(CVP_DBG, "%s: dsp recover from SSR successfully\n", __func__); +exit: + return rc; +} + +static int cvp_hyp_assign_to_dsp(uint64_t addr, uint32_t size) +{ + int rc = 0; + struct cvp_dsp_apps *me = &gfa_cv; + + if (!me->hyp_assigned) { + rc = hyp_assign_phys(addr, size, hlosVM, HLOS_VM_NUM, dspVM, + dspVMperm, DSP_VM_NUM); + if (rc) { + dprintk(CVP_ERR, "%s failed. rc=%d\n", __func__, rc); + return rc; + } + me->addr = addr; + me->size = size; + me->hyp_assigned = true; + } + + return rc; +} + +static int cvp_hyp_assign_from_dsp(void) +{ + int rc = 0; + struct cvp_dsp_apps *me = &gfa_cv; + + if (me->hyp_assigned) { + rc = hyp_assign_phys(me->addr, me->size, dspVM, DSP_VM_NUM, + hlosVM, hlosVMperm, HLOS_VM_NUM); + if (rc) { + dprintk(CVP_ERR, "%s failed. rc=%d\n", __func__, rc); + return rc; + } + me->addr = 0; + me->size = 0; + me->hyp_assigned = false; + } + + return rc; } static int cvp_dsp_rpmsg_probe(struct rpmsg_device *rpdev) { - int err = 0; struct cvp_dsp_apps *me = &gfa_cv; - uint32_t cdsp_state, cvp_shutdown; - uint64_t msg_ptr; - uint32_t msg_ptr_len; - 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 }; if (strcmp(rpdev->dev.parent->of_node->name, "cdsp")) { dprintk(CVP_ERR, "%s: Failed to probe rpmsg device.Node name:%s\n", __func__, rpdev->dev.parent->of_node->name); - err = -EINVAL; - goto bail; + return -EINVAL; } - mutex_lock(&me->smd_mutex); + + mutex_lock(&me->lock); me->chan = rpdev; - cdsp_state = me->cdsp_state; - cvp_shutdown = me->cvp_shutdown; - msg_ptr = cmd_msg.msg_ptr; - msg_ptr_len = cmd_msg.msg_ptr_len; - mutex_unlock(&me->smd_mutex); + me->state = DSP_PROBED; + mutex_unlock(&me->lock); - if (cdsp_state == STATUS_SSR && cvp_shutdown == STATUS_OK) { - err = hyp_assign_phys((uint64_t)msg_ptr, - msg_ptr_len, srcVM, DEST_VM_NUM, destVM, - destVMperm, SRC_VM_NUM); - if (err) { - dprintk(CVP_ERR, - "%s: Failed to hyp_assign. err=%d\n", - __func__, err); - return err; - } - schedule_work(&me->ssr_work); - mutex_lock(&me->smd_mutex); - cdsp_state = me->cdsp_state; - mutex_unlock(&me->smd_mutex); - } + cvp_dsp_send_hfi_queue(); - dprintk(CVP_INFO, - "%s: Successfully probed. cdsp_state=%d cvp_shutdown=%d\n", - __func__, cdsp_state, cvp_shutdown); -bail: - return err; + return 0; } static void cvp_dsp_rpmsg_remove(struct rpmsg_device *rpdev) { struct cvp_dsp_apps *me = &gfa_cv; - cancel_work_sync(&me->ssr_work); - mutex_lock(&me->smd_mutex); + dprintk(CVP_WARN, "%s: CDSP SSR triggered\n", __func__); + + mutex_lock(&me->lock); + cvp_hyp_assign_from_dsp(); + me->chan = NULL; - me->cdsp_state = STATUS_SSR; - if (me->device) { - mutex_lock(&me->device->lock); - me->device->dsp_flags &= ~DSP_INIT; - mutex_unlock(&me->device->lock); - } - mutex_unlock(&me->smd_mutex); - dprintk(CVP_INFO, - "%s: CDSP SSR triggered\n", __func__); + me->state = DSP_UNINIT; + mutex_unlock(&me->lock); + /* kernel driver needs clean all dsp sessions */ + } static int cvp_dsp_rpmsg_callback(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 addr) { - struct cvp_dsp_rsp_msg *dsp_response = - (struct cvp_dsp_rsp_msg *)data; + struct cvp_dsp_rsp_msg *rsp = (struct cvp_dsp_rsp_msg *)data; struct cvp_dsp_apps *me = &gfa_cv; - dprintk(CVP_DBG, - "%s: cmd_msg_type=0x%x dsp_response->ret_val =0x%x\n" - , __func__, dsp_response->cmd_msg_type, dsp_response->ret_val); - switch (dsp_response->cmd_msg_type) { - case CVP_DSP_REGISTER_BUFFER: - complete(&me->reg_buffer_work); - break; - case CVP_DSP_DEREGISTER_BUFFER: - complete(&me->dereg_buffer_work); - break; - case CVP_DSP_SHUTDOWN: - complete(&me->shutdown_work); - break; - case CVP_DSP_SUSPEND: - break; - case CVP_DSP_RESUME: - break; - case CVP_DSP_SEND_HFI_CMD_QUEUE: - complete(&me->cmdqueue_send_work); - break; - default: - dprintk(CVP_ERR, - "%s: Invalid cmd_msg_type received from dsp: %d\n", - __func__, dsp_response->cmd_msg_type); - break; + dprintk(CVP_DBG, "%s: type = 0x%x ret = 0x%x\n", + __func__, rsp->type, rsp->ret); + + if (rsp->type >= CVP_DSP_MAX_CMD) { + dprintk(CVP_ERR, "%s: Invalid type: %d\n", __func__, rsp->type); + return 0; } + + complete(&me->completions[rsp->type]); return 0; } -int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr, - uint32_t size_in_bytes, - struct iris_hfi_device *device) -{ - int err, timeout; - struct msm_cvp_core *core; - struct cvp_dsp_cmd_msg local_cmd_msg; - struct cvp_dsp_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 }; - - local_cmd_msg.cmd_msg_type = CVP_DSP_SEND_HFI_CMD_QUEUE; - local_cmd_msg.msg_ptr = (uint64_t)phys_addr; - local_cmd_msg.msg_ptr_len = size_in_bytes; - local_cmd_msg.ddr_type = of_fdt_get_ddrtype(); - if (local_cmd_msg.ddr_type < 0) { - dprintk(CVP_ERR, - "%s: Incorrect DDR type value %d\n", - __func__, local_cmd_msg.ddr_type); - err = -EINVAL; - goto exit; - } - - mutex_lock(&me->smd_mutex); - cmd_msg.msg_ptr = (uint64_t)phys_addr; - cmd_msg.msg_ptr_len = (size_in_bytes); - me->device = device; - mutex_unlock(&me->smd_mutex); - - dprintk(CVP_DBG, - "%s: address of buffer, PA=0x%pK size_buff=%d ddr_type=%d\n", - __func__, phys_addr, size_in_bytes, local_cmd_msg.ddr_type); - - 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) { - dprintk(CVP_ERR, - "%s: Failed in hyp_assign. err=%d\n", - __func__, err); - goto exit; - } - - err = cvp_dsp_send_cmd - (&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg)); - if (err) { - dprintk(CVP_ERR, - "%s: cvp_dsp_send_cmd faidmesgled with err=%d\n", - __func__, err); - goto exit; - } - - core = list_first_entry(&cvp_driver->cores, - struct msm_cvp_core, list); - timeout = msecs_to_jiffies( - core->resources.msm_cvp_dsp_rsp_timeout); - if (!wait_for_completion_timeout(&me->cmdqueue_send_work, timeout)) { - dprintk(CVP_ERR, "failed to send cmdqueue\n"); - err = -ETIMEDOUT; - goto exit; - } - - mutex_lock(&me->smd_mutex); - me->cvp_shutdown = STATUS_OK; - me->cdsp_state = STATUS_OK; - mutex_unlock(&me->smd_mutex); - -exit: - return err; -} - int cvp_dsp_suspend(uint32_t session_flag) { - int err = 0; - struct cvp_dsp_cmd_msg local_cmd_msg; + int rc = 0; + struct cvp_dsp_cmd_msg cmd; struct cvp_dsp_apps *me = &gfa_cv; - uint32_t cdsp_state; - mutex_lock(&me->smd_mutex); - cdsp_state = me->cdsp_state; - mutex_unlock(&me->smd_mutex); + cmd.type = CVP_DSP_SUSPEND; - if (cdsp_state == STATUS_SSR) - return 0; + mutex_lock(&me->lock); + if (me->state != DSP_READY) + goto exit; - local_cmd_msg.cmd_msg_type = CVP_DSP_SUSPEND; - err = cvp_dsp_send_cmd - (&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg)); - if (err != 0) + /* Use cvp_dsp_send_cmd_sync after dsp driver is ready */ + rc = cvp_dsp_send_cmd(&cmd, sizeof(struct cvp_dsp_cmd_msg)); + if (rc) { dprintk(CVP_ERR, - "%s: cvp_dsp_send_cmd failed with err=%d\n", - __func__, err); + "%s: cvp_dsp_send_cmd failed rc = %d\n", + __func__, rc); + me->state = DSP_UNINIT; + goto exit; + } - return err; + me->state = DSP_SUSPEND; + +exit: + mutex_unlock(&me->lock); + return rc; } int cvp_dsp_resume(uint32_t session_flag) { - int err; - struct cvp_dsp_cmd_msg local_cmd_msg; + int rc = 0; + struct cvp_dsp_cmd_msg cmd; struct cvp_dsp_apps *me = &gfa_cv; - uint32_t cdsp_state; - mutex_lock(&me->smd_mutex); - cdsp_state = me->cdsp_state; - mutex_unlock(&me->smd_mutex); + cmd.type = CVP_DSP_RESUME; - if (cdsp_state == STATUS_SSR) - return 0; + mutex_lock(&me->lock); + if (me->state != DSP_SUSPEND) + goto exit; - local_cmd_msg.cmd_msg_type = CVP_DSP_RESUME; - err = cvp_dsp_send_cmd - (&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg)); - if (err != 0) + /* Use cvp_dsp_send_cmd_sync after dsp driver is ready */ + rc = cvp_dsp_send_cmd(&cmd, sizeof(struct cvp_dsp_cmd_msg)); + if (rc) { dprintk(CVP_ERR, - "%s: cvp_dsp_send_cmd failed with err=%d\n", - __func__, err); + "%s: cvp_dsp_send_cmd failed rc = %d\n", + __func__, rc); + me->state = DSP_UNINIT; + goto exit; + } - return err; -} + me->state = DSP_READY; -void cvp_dsp_set_cvp_ssr(void) -{ - struct cvp_dsp_apps *me = &gfa_cv; - - mutex_lock(&me->smd_mutex); - me->cvp_shutdown = STATUS_SSR; - mutex_unlock(&me->smd_mutex); +exit: + mutex_unlock(&me->lock); + return rc; } int cvp_dsp_shutdown(uint32_t session_flag) { - struct msm_cvp_core *core; struct cvp_dsp_apps *me = &gfa_cv; - int err, local_cmd_msg_rsp, timeout; - struct cvp_dsp_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 }; + int rc = 0; + struct cvp_dsp_cmd_msg cmd; - local_cmd_msg.cmd_msg_type = CVP_DSP_SHUTDOWN; - err = cvp_dsp_send_cmd - (&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg)); - if (err != 0) + cmd.type = CVP_DSP_SHUTDOWN; + + mutex_lock(&me->lock); + if (me->state == DSP_INVALID) + goto exit; + + me->state = DSP_UNINIT; + rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg)); + if (rc) { dprintk(CVP_ERR, - "%s: cvp_dsp_send_cmd failed with err=%d\n", - __func__, err); - - core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); - timeout = msecs_to_jiffies(core->resources.msm_cvp_dsp_rsp_timeout); - err = wait_for_completion_timeout(&me->shutdown_work, timeout); - if (!err) { - dprintk(CVP_ERR, "failed to shutdown dsp\n"); - return -ETIMEDOUT; + "%s: cvp_dsp_send_cmd failed with rc = %d\n", + __func__, rc); + goto exit; } - mutex_lock(&me->smd_mutex); - local_cmd_msg.msg_ptr = cmd_msg.msg_ptr; - local_cmd_msg.msg_ptr_len = cmd_msg.msg_ptr_len; - mutex_unlock(&me->smd_mutex); - local_cmd_msg_rsp = cmd_msg_rsp.ret_val; - if (local_cmd_msg_rsp == 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) { - dprintk(CVP_ERR, - "%s: Failed to hyp_assign. err=%d\n", - __func__, err); - return err; - } - } else { - dprintk(CVP_ERR, - "%s: Skipping hyp_assign as CDSP sent invalid response=%d\n", - __func__, local_cmd_msg_rsp); - } + rc = cvp_hyp_assign_from_dsp(); - return err; +exit: + mutex_unlock(&me->lock); + return rc; } int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd, @@ -414,47 +293,37 @@ int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd, uint32_t buff_offset, uint32_t buff_index, uint32_t buff_fd_iova) { - struct cvp_dsp_cmd_msg local_cmd_msg; - int err; + struct cvp_dsp_cmd_msg cmd; + int rc; struct cvp_dsp_apps *me = &gfa_cv; - local_cmd_msg.cmd_msg_type = CVP_DSP_REGISTER_BUFFER; - local_cmd_msg.session_id = session_id; - local_cmd_msg.buff_fd = buff_fd; - local_cmd_msg.buff_fd_size = buff_fd_size; - local_cmd_msg.buff_size = buff_size; - local_cmd_msg.buff_offset = buff_offset; - local_cmd_msg.buff_index = buff_index; - local_cmd_msg.buff_fd_iova = buff_fd_iova; + cmd.type = CVP_DSP_REGISTER_BUFFER; + cmd.session_id = session_id; + cmd.buff_fd = buff_fd; + cmd.buff_fd_size = buff_fd_size; + cmd.buff_size = buff_size; + cmd.buff_offset = buff_offset; + cmd.buff_index = buff_index; + cmd.buff_fd_iova = buff_fd_iova; dprintk(CVP_DBG, - "%s: cmd_msg_type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n", - __func__, local_cmd_msg.cmd_msg_type, buff_fd_iova, - local_cmd_msg.buff_index); - dprintk(CVP_DBG, - "%s: buff_size=0x%x session_id=0x%x\n", - __func__, local_cmd_msg.buff_size, local_cmd_msg.session_id); + "%s: type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n", + __func__, cmd.type, buff_fd_iova, + cmd.buff_index); + dprintk(CVP_DBG, "%s: buff_size=0x%x session_id=0x%x\n", + __func__, cmd.buff_size, cmd.session_id); - mutex_lock(&me->reg_buffer_mutex); - err = cvp_dsp_send_cmd - (&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg)); - if (err != 0) { - dprintk(CVP_ERR, - "%s: cvp_dsp_send_cmd failed with err=%d\n", - __func__, err); - mutex_unlock(&me->reg_buffer_mutex); - return err; + mutex_lock(&me->lock); + rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg)); + if (rc) { + dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc); + me->state = DSP_UNINIT; + goto exit; } - dprintk(CVP_DBG, - "%s: calling wait_for_completion work=%pK\n", - __func__, &me->reg_buffer_work); - wait_for_completion(&me->reg_buffer_work); - mutex_unlock(&me->reg_buffer_mutex); - dprintk(CVP_DBG, - "%s: done calling wait_for_completion\n", __func__); - - return err; +exit: + mutex_unlock(&me->lock); + return rc; } int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd, @@ -462,47 +331,37 @@ int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd, uint32_t buff_offset, uint32_t buff_index, uint32_t buff_fd_iova) { - struct cvp_dsp_cmd_msg local_cmd_msg; - int err; + struct cvp_dsp_cmd_msg cmd; + int rc; struct cvp_dsp_apps *me = &gfa_cv; - local_cmd_msg.cmd_msg_type = CVP_DSP_DEREGISTER_BUFFER; - local_cmd_msg.session_id = session_id; - local_cmd_msg.buff_fd = buff_fd; - local_cmd_msg.buff_fd_size = buff_fd_size; - local_cmd_msg.buff_size = buff_size; - local_cmd_msg.buff_offset = buff_offset; - local_cmd_msg.buff_index = buff_index; - local_cmd_msg.buff_fd_iova = buff_fd_iova; + cmd.type = CVP_DSP_DEREGISTER_BUFFER; + cmd.session_id = session_id; + cmd.buff_fd = buff_fd; + cmd.buff_fd_size = buff_fd_size; + cmd.buff_size = buff_size; + cmd.buff_offset = buff_offset; + cmd.buff_index = buff_index; + cmd.buff_fd_iova = buff_fd_iova; dprintk(CVP_DBG, - "%s: cmd_msg_type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n", - __func__, local_cmd_msg.cmd_msg_type, buff_fd_iova, - local_cmd_msg.buff_index); - dprintk(CVP_DBG, - "%s: buff_size=0x%x session_id=0x%x\n", - __func__, local_cmd_msg.buff_size, local_cmd_msg.session_id); + "%s: type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n", + __func__, cmd.type, buff_fd_iova, + cmd.buff_index); + dprintk(CVP_DBG, "%s: buff_size=0x%x session_id=0x%x\n", + __func__, cmd.buff_size, cmd.session_id); - mutex_lock(&me->dereg_buffer_mutex); - err = cvp_dsp_send_cmd - (&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg)); - if (err != 0) { - dprintk(CVP_ERR, - "%s: cvp_dsp_send_cmd failed with err=%d\n", - __func__, err); - mutex_unlock(&me->dereg_buffer_mutex); - return err; + mutex_lock(&me->lock); + rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg)); + if (rc) { + dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc); + me->state = DSP_UNINIT; + goto exit; } - dprintk(CVP_DBG, - "%s: calling wait_for_completion work=%pK\n", - __func__, &me->dereg_buffer_work); - wait_for_completion(&me->dereg_buffer_work); - dprintk(CVP_DBG, - "%s: done calling wait_for_completion\n", __func__); - mutex_unlock(&me->dereg_buffer_mutex); - - return err; +exit: + mutex_unlock(&me->lock); + return rc; } static const struct rpmsg_device_id cvp_dsp_rpmsg_match[] = { @@ -520,48 +379,102 @@ static struct rpmsg_driver cvp_dsp_rpmsg_client = { }, }; +void cvp_dsp_send_hfi_queue(void) +{ + struct msm_cvp_core *core; + struct iris_hfi_device *device; + struct cvp_dsp_apps *me = &gfa_cv; + uint64_t addr; + uint32_t size; + int rc; + + core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); + if (core) + device = core->device->hfi_device_data; + else + return; + + if (!device) { + dprintk(CVP_ERR, "%s: NULL device\n", __func__); + return; + } + + dprintk(CVP_DBG, "Entering %s\n", __func__); + + mutex_lock(&device->lock); + mutex_lock(&me->lock); + + addr = (uint64_t)device->dsp_iface_q_table.mem_data.dma_handle; + size = device->dsp_iface_q_table.mem_data.size; + + if (!addr || !size) { + dprintk(CVP_DBG, "%s: HFI queue is not ready\n", __func__); + goto exit; + } + + if (me->state != DSP_PROBED) + goto exit; + + rc = cvp_hyp_assign_to_dsp(addr, size); + if (rc) { + dprintk(CVP_ERR, "%s: cvp_hyp_assign_to_dsp. rc=%d\n", + __func__, rc); + goto exit; + } + + rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size); + if (rc) { + dprintk(CVP_WARN, "%s: Send HFI Queue failed rc = %d\n", + __func__, rc); + + rc = cvp_hyp_assign_from_dsp(); + goto exit; + } + + dprintk(CVP_DBG, "%s: dsp initialized\n", __func__); + me->state = DSP_READY; + +exit: + mutex_unlock(&me->lock); + mutex_unlock(&device->lock); +} + int cvp_dsp_device_init(void) { struct cvp_dsp_apps *me = &gfa_cv; - int err; + int rc; + int i; - if (me->cdsp_state == STATUS_DEINIT) { - mutex_init(&me->smd_mutex); - mutex_init(&me->reg_buffer_mutex); - mutex_init(&me->dereg_buffer_mutex); - init_completion(&me->shutdown_work); - init_completion(&me->reg_buffer_work); - init_completion(&me->dereg_buffer_work); - init_completion(&me->cmdqueue_send_work); - me->cvp_shutdown = STATUS_INIT; - me->cdsp_state = STATUS_INIT; - INIT_WORK(&me->ssr_work, msm_cvp_cdsp_ssr_handler); - err = register_rpmsg_driver(&cvp_dsp_rpmsg_client); - if (err) { - dprintk(CVP_ERR, - "%s : register_rpmsg failed with err %d\n", - __func__, err); - goto register_bail; - } - me->rpmsg_register = 1; + mutex_init(&me->lock); + me->state = DSP_INVALID; + me->hyp_assigned = false; + + for (i = 0; i < CVP_DSP_MAX_CMD; i++) + init_completion(&me->completions[i]); + + rc = register_rpmsg_driver(&cvp_dsp_rpmsg_client); + if (rc) { + dprintk(CVP_ERR, + "%s : register_rpmsg_driver failed rc = %d\n", + __func__, rc); + goto register_bail; } + + me->state = DSP_UNINIT; return 0; register_bail: - me->cvp_shutdown = STATUS_DEINIT; - me->cdsp_state = STATUS_DEINIT; - return err; + return rc; } void cvp_dsp_device_exit(void) { struct cvp_dsp_apps *me = &gfa_cv; - me->cvp_shutdown = STATUS_DEINIT; - me->cdsp_state = STATUS_DEINIT; - mutex_destroy(&me->smd_mutex); - mutex_destroy(&me->reg_buffer_mutex); - mutex_destroy(&me->dereg_buffer_mutex); - if (me->rpmsg_register == 1) - unregister_rpmsg_driver(&cvp_dsp_rpmsg_client); + mutex_lock(&me->lock); + me->state = DSP_INVALID; + mutex_unlock(&me->lock); + + mutex_destroy(&me->lock); + unregister_rpmsg_driver(&cvp_dsp_rpmsg_client); } diff --git a/drivers/media/platform/msm/cvp/msm_cvp_dsp.h b/drivers/media/platform/msm/cvp/msm_cvp_dsp.h index 1a3da5773fde..fb2eeb486d39 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_dsp.h +++ b/drivers/media/platform/msm/cvp/msm_cvp_dsp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef MSM_CVP_DSP_H @@ -13,18 +13,48 @@ #define CVP_APPS_DSP_GLINK_GUID "cvp-glink-apps-dsp" #define CVP_APPS_DSP_SMD_GUID "cvp-smd-apps-dsp" -/* - * API for CVP driver to send physical address to dsp driver - * @param phys_addr - * Physical address of command message queue - * that needs to be mapped to CDSP. - * It should be allocated from CMA adsp_mem region. - * - * @param size_in_bytes - * Size in bytes of command message queue - */ -int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr, - uint32_t size_in_bytes, struct iris_hfi_device *device); +#define VMID_CDSP_Q6 (30) +#define HLOS_VM_NUM 1 +#define DSP_VM_NUM 2 +#define CVP_DSP_MAX_RESERVED 5 +#define CVP_DSP_RESPONSE_TIMEOUT 1000 + +int cvp_dsp_device_init(void); +void cvp_dsp_device_exit(void); +void cvp_dsp_send_hfi_queue(void); + +enum DSP_COMMAND { + CVP_DSP_SEND_HFI_QUEUE = 0, + CVP_DSP_SUSPEND = 1, + CVP_DSP_RESUME = 2, + CVP_DSP_SHUTDOWN = 3, + CVP_DSP_REGISTER_BUFFER = 4, + CVP_DSP_DEREGISTER_BUFFER = 5, + CVP_DSP_MAX_CMD +}; + +struct cvp_dsp_cmd_msg { + uint32_t type; + int32_t ret; + uint64_t msg_ptr; + uint32_t msg_ptr_len; + uint32_t buff_fd_iova; + uint32_t buff_index; + uint32_t buff_size; + uint32_t session_id; + int32_t ddr_type; + uint32_t buff_fd; + uint32_t buff_offset; + uint32_t buff_fd_size; + uint32_t reserved1; + uint32_t reserved2; +}; + +struct cvp_dsp_rsp_msg { + uint32_t type; + int32_t ret; + uint32_t reserved[CVP_DSP_MAX_RESERVED]; +}; /* * API for CVP driver to suspend CVP session during @@ -53,13 +83,6 @@ int cvp_dsp_resume(uint32_t session_flag); */ int cvp_dsp_shutdown(uint32_t session_flag); -/* - * API for CVP driver to set CVP status during - * cvp subsystem error. - * - */ -void cvp_dsp_set_cvp_ssr(void); - /* * API to register iova buffer address with CDSP * @@ -92,15 +115,5 @@ int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd, uint32_t buff_offset, uint32_t buff_index, uint32_t buff_fd_iova); -/* - * API to initialize CPU and DSP driver interface - */ -int cvp_dsp_device_init(void); - -/* - * API to deinitilized CPU and DSP driver interface - */ -void cvp_dsp_device_exit(void); - #endif // MSM_CVP_DSP_H diff --git a/drivers/media/platform/msm/cvp/msm_cvp_internal.h b/drivers/media/platform/msm/cvp/msm_cvp_internal.h index e88963ed56b1..bb8370e01aa7 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_internal.h +++ b/drivers/media/platform/msm/cvp/msm_cvp_internal.h @@ -44,10 +44,6 @@ #define SYS_MSG_INDEX(__msg) (__msg - SYS_MSG_START) #define SESSION_MSG_INDEX(__msg) (__msg - SESSION_MSG_START) -#define call_core_op(c, op, args...) \ - (((c) && (c)->core_ops && (c)->core_ops->op) ? \ - ((c)->core_ops->op(args)) : 0) - #define ARP_BUF_SIZE 0x100000 #define CVP_RT_PRIO_THRESHOLD 1 @@ -76,6 +72,14 @@ enum instance_state { MSM_CVP_CORE_INVALID }; +enum dsp_state { + DSP_INVALID, + DSP_UNINIT, + DSP_PROBED, + DSP_READY, + DSP_SUSPEND, +}; + struct msm_cvp_list { struct list_head list; struct mutex lock; @@ -314,9 +318,7 @@ struct msm_cvp_core { bool smmu_fault_handled; u32 last_fault_addr; bool trigger_ssr; - unsigned long min_freq; unsigned long curr_freq; - struct msm_cvp_core_ops *core_ops; atomic64_t kernel_trans_id; };