Loading drivers/media/platform/msm/vidc/msm_vidc_common.c +34 −65 Original line number Diff line number Diff line Loading @@ -1084,54 +1084,12 @@ struct sys_err_handler_data { struct delayed_work work; }; void hw_sys_error_handler(struct work_struct *work) { struct msm_vidc_core *core = NULL; struct hfi_device *hdev = NULL; struct sys_err_handler_data *handler = NULL; int rc = 0; handler = container_of(work, struct sys_err_handler_data, work.work); if (!handler || !handler->core || !handler->core->device) { dprintk(VIDC_ERR, "%s - invalid work or core handle\n", __func__); goto exit; } core = handler->core; hdev = core->device; mutex_lock(&core->lock); /* * Restart the firmware to bring out of bad state. */ if ((core->state == VIDC_CORE_INVALID) && hdev->resurrect_fw) { rc = call_hfi_op(hdev, resurrect_fw, hdev->hfi_device_data); if (rc) { dprintk(VIDC_ERR, "%s - resurrect_fw failed: %d\n", __func__, rc); } core->state = VIDC_CORE_LOADED; } else { dprintk(VIDC_DBG, "fw unloaded after sys error, no need to resurrect\n"); } mutex_unlock(&core->lock); exit: /* free sys error handler, allocated in handle_sys_err */ kfree(handler); } static void handle_sys_error(enum command_response cmd, void *data) { struct msm_vidc_cb_cmd_done *response = data; struct msm_vidc_core *core = NULL; struct sys_err_handler_data *handler = NULL; struct hfi_device *hdev = NULL; int rc = 0; subsystem_crashed("venus"); if (!response) { Loading @@ -1149,24 +1107,25 @@ static void handle_sys_error(enum command_response cmd, void *data) dprintk(VIDC_WARN, "SYS_ERROR %d received for core %p\n", cmd, core); msm_comm_clean_notify_client(core); handler = kzalloc(sizeof(*handler), GFP_KERNEL); if (!handler) { dprintk(VIDC_ERR, "%s - failed to allocate sys error handler\n", __func__); hdev = core->device; mutex_lock(&core->lock); if (core->state == VIDC_CORE_INVALID) { dprintk(VIDC_DBG, "Calling core_release\n"); rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data); if (rc) { dprintk(VIDC_ERR, "core_release failed\n"); mutex_unlock(&core->lock); return; } handler->core = core; INIT_DELAYED_WORK(&handler->work, hw_sys_error_handler); /* * Sleep for 5 sec to ensure venus has completed any * pending cache operations. Without this sleep, we see * device reset when firmware is unloaded after a sys * error. */ schedule_delayed_work(&handler->work, msecs_to_jiffies(5000)); core->state = VIDC_CORE_UNINIT; call_hfi_op(hdev, unload_fw, hdev->hfi_device_data); dprintk(VIDC_DBG, "Firmware unloaded\n"); msm_comm_unvote_buses(core); } mutex_unlock(&core->lock); } void msm_comm_session_clean(struct msm_vidc_inst *inst) Loading Loading @@ -3031,7 +2990,8 @@ int msm_comm_qbuf(struct vb2_buffer *vb) } if (inst->state == MSM_VIDC_CORE_INVALID || core->state == VIDC_CORE_INVALID) { core->state == VIDC_CORE_INVALID || core->state == VIDC_CORE_UNINIT) { dprintk(VIDC_ERR, "Core is in bad state. Can't Queue\n"); return -EINVAL; } Loading Loading @@ -3836,8 +3796,8 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) } msm_comm_flush_dynamic_buffers(inst); if (inst->state == MSM_VIDC_CORE_INVALID || core->state == VIDC_CORE_UNINIT || core->state == VIDC_CORE_INVALID) { dprintk(VIDC_ERR, "Core %p and inst %p are in bad state\n", Loading Loading @@ -4330,10 +4290,12 @@ void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem) "%s: invalid params: %p %p\n", __func__, inst, mem); return; } mutex_lock(&inst->core->lock); if (inst->state != MSM_VIDC_CORE_INVALID) { if (power_on_for_smem(inst)) goto err_power_on; } msm_smem_free(inst->mem_client, mem); err_power_on: mutex_unlock(&inst->core->lock); Loading @@ -4359,6 +4321,13 @@ struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst, dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); return NULL; } if (inst->state == MSM_VIDC_CORE_INVALID) { dprintk(VIDC_ERR, "Core in Invalid state, returning from %s\n", __func__); return NULL; } mutex_lock(&inst->core->lock); if (power_on_for_smem(inst)) goto err_power_on; Loading drivers/media/platform/msm/vidc/venus_hfi.c +23 −51 Original line number Diff line number Diff line Loading @@ -2412,13 +2412,16 @@ static int venus_hfi_core_release(void *device) "%s: Power enable failed\n", __func__); return -EIO; } if (dev->state != VENUS_STATE_DEINIT) { mutex_lock(&dev->resource_lock); rc = __unset_free_ocmem(dev); mutex_unlock(&dev->resource_lock); if (rc) dprintk(VIDC_ERR, "Failed to unset and free OCMEM in core release, rc : %d\n", rc); "Failed in unset_free_ocmem() in %s, rc : %d\n", __func__, rc); } venus_hfi_write_register(dev, VIDC_CPU_CS_SCIACMDARG3, 0); if (!(dev->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) disable_irq_nosync(dev->hal_data->irq); Loading Loading @@ -3325,7 +3328,8 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) return; } dprintk(VIDC_INFO, "#####venus_hfi_response_handler#####\n"); if (device) { /* Process messages only if device is in valid state*/ if (device && device->state != VENUS_STATE_DEINIT) { if ((device->intr_status & VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK)) { dprintk(VIDC_ERR, "Received: Watchdog timeout %s\n", Loading @@ -3340,6 +3344,16 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) } while (!venus_hfi_iface_msgq_read(device, packet)) { /* During SYS_ERROR processing the device state * will be changed to DEINIT. Below check will * make sure no messages messages are read or * processed after processing SYS_ERROR */ if (device->state == VENUS_STATE_DEINIT) { dprintk(VIDC_ERR, "core DEINIT'd, stopping q reads\n"); break; } rc = hfi_process_msg_packet(device->callback, device->device_id, (struct vidc_hal_msg_pkt_hdr *) packet, Loading Loading @@ -4128,7 +4142,6 @@ static void venus_hfi_unload_fw(void *dev) return; } if (device->resources.fw.cookie) { flush_workqueue(device->vidc_workq); cancel_delayed_work(&venus_hfi_pm_work); flush_workqueue(device->venus_pm_workq); subsystem_put(device->resources.fw.cookie); Loading @@ -4148,46 +4161,6 @@ static void venus_hfi_unload_fw(void *dev) } } static int venus_hfi_resurrect_fw(void *dev) { struct venus_hfi_device *device = dev; int rc = 0; if (!device) { dprintk(VIDC_ERR, "%s Invalid paramter: %p\n", __func__, device); return -EINVAL; } rc = venus_hfi_core_release(device); if (rc) { dprintk(VIDC_ERR, "%s - failed to release venus core rc = %d\n", __func__, rc); goto exit; } dprintk(VIDC_ERR, "praying for firmware resurrection\n"); venus_hfi_unload_fw(device); rc = venus_hfi_vote_buses(device, device->bus_load.vote_data, device->bus_load.vote_data_count); if (rc) { dprintk(VIDC_ERR, "Failed to scale buses\n"); goto exit; } rc = venus_hfi_load_fw(device); if (rc) { dprintk(VIDC_ERR, "%s - failed to load venus fw rc = %d\n", __func__, rc); goto exit; } dprintk(VIDC_ERR, "Hurray!! firmware has restarted\n"); exit: return rc; } static int venus_hfi_get_fw_info(void *dev, enum fw_info info) { int rc = 0; Loading Loading @@ -4460,7 +4433,6 @@ static void venus_init_hfi_callbacks(struct hfi_device *hdev) hdev->iommu_get_domain_partition = venus_hfi_iommu_get_domain_partition; hdev->load_fw = venus_hfi_load_fw; hdev->unload_fw = venus_hfi_unload_fw; hdev->resurrect_fw = venus_hfi_resurrect_fw; hdev->get_fw_info = venus_hfi_get_fw_info; hdev->get_stride_scanline = venus_hfi_get_stride_scanline; hdev->get_core_capabilities = venus_hfi_get_core_capabilities; Loading drivers/media/platform/msm/vidc/vidc_hfi_api.h +0 −1 Original line number Diff line number Diff line Loading @@ -1348,7 +1348,6 @@ struct hfi_device { int *domain_num, int *partition_num); int (*load_fw)(void *dev); void (*unload_fw)(void *dev); int (*resurrect_fw)(void *dev); int (*get_fw_info)(void *dev, enum fw_info info); int (*get_stride_scanline)(int color_fmt, int width, int height, int *stride, int *scanlines); Loading Loading
drivers/media/platform/msm/vidc/msm_vidc_common.c +34 −65 Original line number Diff line number Diff line Loading @@ -1084,54 +1084,12 @@ struct sys_err_handler_data { struct delayed_work work; }; void hw_sys_error_handler(struct work_struct *work) { struct msm_vidc_core *core = NULL; struct hfi_device *hdev = NULL; struct sys_err_handler_data *handler = NULL; int rc = 0; handler = container_of(work, struct sys_err_handler_data, work.work); if (!handler || !handler->core || !handler->core->device) { dprintk(VIDC_ERR, "%s - invalid work or core handle\n", __func__); goto exit; } core = handler->core; hdev = core->device; mutex_lock(&core->lock); /* * Restart the firmware to bring out of bad state. */ if ((core->state == VIDC_CORE_INVALID) && hdev->resurrect_fw) { rc = call_hfi_op(hdev, resurrect_fw, hdev->hfi_device_data); if (rc) { dprintk(VIDC_ERR, "%s - resurrect_fw failed: %d\n", __func__, rc); } core->state = VIDC_CORE_LOADED; } else { dprintk(VIDC_DBG, "fw unloaded after sys error, no need to resurrect\n"); } mutex_unlock(&core->lock); exit: /* free sys error handler, allocated in handle_sys_err */ kfree(handler); } static void handle_sys_error(enum command_response cmd, void *data) { struct msm_vidc_cb_cmd_done *response = data; struct msm_vidc_core *core = NULL; struct sys_err_handler_data *handler = NULL; struct hfi_device *hdev = NULL; int rc = 0; subsystem_crashed("venus"); if (!response) { Loading @@ -1149,24 +1107,25 @@ static void handle_sys_error(enum command_response cmd, void *data) dprintk(VIDC_WARN, "SYS_ERROR %d received for core %p\n", cmd, core); msm_comm_clean_notify_client(core); handler = kzalloc(sizeof(*handler), GFP_KERNEL); if (!handler) { dprintk(VIDC_ERR, "%s - failed to allocate sys error handler\n", __func__); hdev = core->device; mutex_lock(&core->lock); if (core->state == VIDC_CORE_INVALID) { dprintk(VIDC_DBG, "Calling core_release\n"); rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data); if (rc) { dprintk(VIDC_ERR, "core_release failed\n"); mutex_unlock(&core->lock); return; } handler->core = core; INIT_DELAYED_WORK(&handler->work, hw_sys_error_handler); /* * Sleep for 5 sec to ensure venus has completed any * pending cache operations. Without this sleep, we see * device reset when firmware is unloaded after a sys * error. */ schedule_delayed_work(&handler->work, msecs_to_jiffies(5000)); core->state = VIDC_CORE_UNINIT; call_hfi_op(hdev, unload_fw, hdev->hfi_device_data); dprintk(VIDC_DBG, "Firmware unloaded\n"); msm_comm_unvote_buses(core); } mutex_unlock(&core->lock); } void msm_comm_session_clean(struct msm_vidc_inst *inst) Loading Loading @@ -3031,7 +2990,8 @@ int msm_comm_qbuf(struct vb2_buffer *vb) } if (inst->state == MSM_VIDC_CORE_INVALID || core->state == VIDC_CORE_INVALID) { core->state == VIDC_CORE_INVALID || core->state == VIDC_CORE_UNINIT) { dprintk(VIDC_ERR, "Core is in bad state. Can't Queue\n"); return -EINVAL; } Loading Loading @@ -3836,8 +3796,8 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags) } msm_comm_flush_dynamic_buffers(inst); if (inst->state == MSM_VIDC_CORE_INVALID || core->state == VIDC_CORE_UNINIT || core->state == VIDC_CORE_INVALID) { dprintk(VIDC_ERR, "Core %p and inst %p are in bad state\n", Loading Loading @@ -4330,10 +4290,12 @@ void msm_comm_smem_free(struct msm_vidc_inst *inst, struct msm_smem *mem) "%s: invalid params: %p %p\n", __func__, inst, mem); return; } mutex_lock(&inst->core->lock); if (inst->state != MSM_VIDC_CORE_INVALID) { if (power_on_for_smem(inst)) goto err_power_on; } msm_smem_free(inst->mem_client, mem); err_power_on: mutex_unlock(&inst->core->lock); Loading @@ -4359,6 +4321,13 @@ struct msm_smem *msm_comm_smem_user_to_kernel(struct msm_vidc_inst *inst, dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst); return NULL; } if (inst->state == MSM_VIDC_CORE_INVALID) { dprintk(VIDC_ERR, "Core in Invalid state, returning from %s\n", __func__); return NULL; } mutex_lock(&inst->core->lock); if (power_on_for_smem(inst)) goto err_power_on; Loading
drivers/media/platform/msm/vidc/venus_hfi.c +23 −51 Original line number Diff line number Diff line Loading @@ -2412,13 +2412,16 @@ static int venus_hfi_core_release(void *device) "%s: Power enable failed\n", __func__); return -EIO; } if (dev->state != VENUS_STATE_DEINIT) { mutex_lock(&dev->resource_lock); rc = __unset_free_ocmem(dev); mutex_unlock(&dev->resource_lock); if (rc) dprintk(VIDC_ERR, "Failed to unset and free OCMEM in core release, rc : %d\n", rc); "Failed in unset_free_ocmem() in %s, rc : %d\n", __func__, rc); } venus_hfi_write_register(dev, VIDC_CPU_CS_SCIACMDARG3, 0); if (!(dev->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) disable_irq_nosync(dev->hal_data->irq); Loading Loading @@ -3325,7 +3328,8 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) return; } dprintk(VIDC_INFO, "#####venus_hfi_response_handler#####\n"); if (device) { /* Process messages only if device is in valid state*/ if (device && device->state != VENUS_STATE_DEINIT) { if ((device->intr_status & VIDC_WRAPPER_INTR_CLEAR_A2HWD_BMSK)) { dprintk(VIDC_ERR, "Received: Watchdog timeout %s\n", Loading @@ -3340,6 +3344,16 @@ static void venus_hfi_response_handler(struct venus_hfi_device *device) } while (!venus_hfi_iface_msgq_read(device, packet)) { /* During SYS_ERROR processing the device state * will be changed to DEINIT. Below check will * make sure no messages messages are read or * processed after processing SYS_ERROR */ if (device->state == VENUS_STATE_DEINIT) { dprintk(VIDC_ERR, "core DEINIT'd, stopping q reads\n"); break; } rc = hfi_process_msg_packet(device->callback, device->device_id, (struct vidc_hal_msg_pkt_hdr *) packet, Loading Loading @@ -4128,7 +4142,6 @@ static void venus_hfi_unload_fw(void *dev) return; } if (device->resources.fw.cookie) { flush_workqueue(device->vidc_workq); cancel_delayed_work(&venus_hfi_pm_work); flush_workqueue(device->venus_pm_workq); subsystem_put(device->resources.fw.cookie); Loading @@ -4148,46 +4161,6 @@ static void venus_hfi_unload_fw(void *dev) } } static int venus_hfi_resurrect_fw(void *dev) { struct venus_hfi_device *device = dev; int rc = 0; if (!device) { dprintk(VIDC_ERR, "%s Invalid paramter: %p\n", __func__, device); return -EINVAL; } rc = venus_hfi_core_release(device); if (rc) { dprintk(VIDC_ERR, "%s - failed to release venus core rc = %d\n", __func__, rc); goto exit; } dprintk(VIDC_ERR, "praying for firmware resurrection\n"); venus_hfi_unload_fw(device); rc = venus_hfi_vote_buses(device, device->bus_load.vote_data, device->bus_load.vote_data_count); if (rc) { dprintk(VIDC_ERR, "Failed to scale buses\n"); goto exit; } rc = venus_hfi_load_fw(device); if (rc) { dprintk(VIDC_ERR, "%s - failed to load venus fw rc = %d\n", __func__, rc); goto exit; } dprintk(VIDC_ERR, "Hurray!! firmware has restarted\n"); exit: return rc; } static int venus_hfi_get_fw_info(void *dev, enum fw_info info) { int rc = 0; Loading Loading @@ -4460,7 +4433,6 @@ static void venus_init_hfi_callbacks(struct hfi_device *hdev) hdev->iommu_get_domain_partition = venus_hfi_iommu_get_domain_partition; hdev->load_fw = venus_hfi_load_fw; hdev->unload_fw = venus_hfi_unload_fw; hdev->resurrect_fw = venus_hfi_resurrect_fw; hdev->get_fw_info = venus_hfi_get_fw_info; hdev->get_stride_scanline = venus_hfi_get_stride_scanline; hdev->get_core_capabilities = venus_hfi_get_core_capabilities; Loading
drivers/media/platform/msm/vidc/vidc_hfi_api.h +0 −1 Original line number Diff line number Diff line Loading @@ -1348,7 +1348,6 @@ struct hfi_device { int *domain_num, int *partition_num); int (*load_fw)(void *dev); void (*unload_fw)(void *dev); int (*resurrect_fw)(void *dev); int (*get_fw_info)(void *dev, enum fw_info info); int (*get_stride_scanline)(int color_fmt, int width, int height, int *stride, int *scanlines); Loading