Loading drivers/media/platform/msm/vidc/venus_hfi.c +39 −50 Original line number Original line Diff line number Diff line Loading @@ -1080,6 +1080,21 @@ static int venus_hfi_iface_cmdq_write(struct venus_hfi_device *device, dprintk(VIDC_ERR, "Invalid Params"); dprintk(VIDC_ERR, "Invalid Params"); return -EINVAL; return -EINVAL; } } if (device->res->sw_power_collapsible) { dprintk(VIDC_DBG, "Cancel and queue delayed work from %s\n", __func__); cancel_delayed_work_sync(&venus_hfi_pm_work); if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies( msm_vidc_pwr_collapse_delay))) { dprintk(VIDC_DBG, "PM work already scheduled\n"); } } mutex_lock(&device->write_lock); mutex_lock(&device->write_lock); result = venus_hfi_iface_cmdq_write_nolock(device, pkt); result = venus_hfi_iface_cmdq_write_nolock(device, pkt); mutex_unlock(&device->write_lock); mutex_unlock(&device->write_lock); Loading Loading @@ -1605,6 +1620,13 @@ static inline int venus_hfi_power_on(struct venus_hfi_device *device) return 0; return 0; dprintk(VIDC_DBG, "Resuming from power collapse\n"); dprintk(VIDC_DBG, "Resuming from power collapse\n"); rc = __alloc_ocmem(device); if (rc) { dprintk(VIDC_ERR, "Failed to allocate OCMEM"); return -EINVAL; } rc = venus_hfi_vote_buses(device, device->bus_load.vote_data, rc = venus_hfi_vote_buses(device, device->bus_load.vote_data, device->bus_load.vote_data_count); device->bus_load.vote_data_count); if (rc) { if (rc) { Loading Loading @@ -1675,27 +1697,10 @@ static inline int venus_hfi_power_on(struct venus_hfi_device *device) goto err_reset_core; goto err_reset_core; } } /* * set the flag here to skip venus_hfi_power_on() which is * being called again via __alloc_set_ocmem() if ocmem is enabled */ device->power_enabled = true; device->power_enabled = true; /* * write_lock is already acquired at this point, so to avoid * recursive lock in cmdq_write function, call nolock version * of alloc_ocmem */ WARN_ON(!mutex_is_locked(&device->write_lock)); rc = __alloc_set_ocmem(device, false); if (rc) { dprintk(VIDC_ERR, "Failed to allocate OCMEM"); goto err_alloc_ocmem; } dprintk(VIDC_INFO, "Resumed from power collapse\n"); dprintk(VIDC_INFO, "Resumed from power collapse\n"); return rc; return rc; err_alloc_ocmem: err_reset_core: err_reset_core: venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND); venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND); err_set_video_state: err_set_video_state: Loading Loading @@ -1811,18 +1816,6 @@ static int venus_hfi_iface_cmdq_write_nolock(struct venus_hfi_device *device, device, VIDC_CPU_IC_SOFTINT, device, VIDC_CPU_IC_SOFTINT, 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT); 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT); if (device->res->sw_power_collapsible) { dprintk(VIDC_DBG, "Cancel and queue delayed work again\n"); cancel_delayed_work(&venus_hfi_pm_work); if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies( msm_vidc_pwr_collapse_delay))) { dprintk(VIDC_DBG, "PM work already scheduled\n"); } } result = 0; result = 0; } else { } else { dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full\n"); dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full\n"); Loading Loading @@ -3102,9 +3095,13 @@ static int venus_hfi_core_pc_prep(void *device) dprintk(VIDC_ERR, "Failed to create sys pc prep pkt\n"); dprintk(VIDC_ERR, "Failed to create sys pc prep pkt\n"); goto err_create_pkt; goto err_create_pkt; } } /* Calling write_nolock() with write_lock instead of write() if (venus_hfi_iface_cmdq_write(dev, &pkt)) * because write() will cancel and rescheduling power collapse. */ mutex_lock(&dev->write_lock); if (venus_hfi_iface_cmdq_write_nolock(dev, &pkt)) rc = -ENOTEMPTY; rc = -ENOTEMPTY; mutex_unlock(&dev->write_lock); err_create_pkt: err_create_pkt: return rc; return rc; Loading Loading @@ -3144,6 +3141,7 @@ static void venus_hfi_pm_hndlr(struct work_struct *work) dprintk(VIDC_ERR, "%s: NULL device\n", __func__); dprintk(VIDC_ERR, "%s: NULL device\n", __func__); return; return; } } if (!device->power_enabled) { if (!device->power_enabled) { dprintk(VIDC_DBG, "%s: Power already disabled\n", dprintk(VIDC_DBG, "%s: Power already disabled\n", __func__); __func__); Loading @@ -3164,22 +3162,9 @@ static void venus_hfi_pm_hndlr(struct work_struct *work) dprintk(VIDC_DBG, "Prepare for power collapse\n"); dprintk(VIDC_DBG, "Prepare for power collapse\n"); mutex_lock(&device->resource_lock); rc = __unset_free_ocmem(device); mutex_unlock(&device->resource_lock); if (rc) { dprintk(VIDC_ERR, "Failed to unset and free OCMEM for PC, rc : %d\n", rc); return; } rc = venus_hfi_prepare_pc(device); rc = venus_hfi_prepare_pc(device); if (rc) { if (rc) { dprintk(VIDC_ERR, "Failed to prepare for PC, rc : %d\n", rc); dprintk(VIDC_ERR, "Failed to prepare for PC, rc : %d\n", rc); rc = __alloc_set_ocmem(device, true); if (rc) dprintk(VIDC_WARN, "Failed to re-allocate OCMEM. Performance will be impacted\n"); return; return; } } Loading Loading @@ -3212,6 +3197,13 @@ static void venus_hfi_pm_hndlr(struct work_struct *work) goto err_power_off; goto err_power_off; } } mutex_lock(&device->resource_lock); rc = __free_ocmem(device); mutex_unlock(&device->resource_lock); if (rc) dprintk(VIDC_ERR, "Failed to free OCMEM for PC, rc : %d\n", rc); /* Cancel pending delayed works if any */ /* Cancel pending delayed works if any */ cancel_delayed_work(&venus_hfi_pm_work); cancel_delayed_work(&venus_hfi_pm_work); Loading @@ -3234,10 +3226,6 @@ skip_power_off: device->last_packet_type, ctrl_status); device->last_packet_type, ctrl_status); mutex_unlock(&device->write_lock); mutex_unlock(&device->write_lock); rc = __alloc_set_ocmem(device, true); if (rc) dprintk(VIDC_WARN, "Failed to re-allocate OCMEM. Performance will be impacted\n"); return; return; } } Loading Loading @@ -3400,7 +3388,8 @@ static void venus_hfi_core_work_handler(struct work_struct *work) return; return; } } if (device->res->sw_power_collapsible) { if (device->res->sw_power_collapsible) { dprintk(VIDC_DBG, "Cancel and queue delayed work again.\n"); dprintk(VIDC_DBG, "Cancel and queue delayed work from %s\n", __func__); cancel_delayed_work(&venus_hfi_pm_work); cancel_delayed_work(&venus_hfi_pm_work); if (!queue_delayed_work(device->venus_pm_workq, if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, &venus_hfi_pm_work, Loading Loading
drivers/media/platform/msm/vidc/venus_hfi.c +39 −50 Original line number Original line Diff line number Diff line Loading @@ -1080,6 +1080,21 @@ static int venus_hfi_iface_cmdq_write(struct venus_hfi_device *device, dprintk(VIDC_ERR, "Invalid Params"); dprintk(VIDC_ERR, "Invalid Params"); return -EINVAL; return -EINVAL; } } if (device->res->sw_power_collapsible) { dprintk(VIDC_DBG, "Cancel and queue delayed work from %s\n", __func__); cancel_delayed_work_sync(&venus_hfi_pm_work); if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies( msm_vidc_pwr_collapse_delay))) { dprintk(VIDC_DBG, "PM work already scheduled\n"); } } mutex_lock(&device->write_lock); mutex_lock(&device->write_lock); result = venus_hfi_iface_cmdq_write_nolock(device, pkt); result = venus_hfi_iface_cmdq_write_nolock(device, pkt); mutex_unlock(&device->write_lock); mutex_unlock(&device->write_lock); Loading Loading @@ -1605,6 +1620,13 @@ static inline int venus_hfi_power_on(struct venus_hfi_device *device) return 0; return 0; dprintk(VIDC_DBG, "Resuming from power collapse\n"); dprintk(VIDC_DBG, "Resuming from power collapse\n"); rc = __alloc_ocmem(device); if (rc) { dprintk(VIDC_ERR, "Failed to allocate OCMEM"); return -EINVAL; } rc = venus_hfi_vote_buses(device, device->bus_load.vote_data, rc = venus_hfi_vote_buses(device, device->bus_load.vote_data, device->bus_load.vote_data_count); device->bus_load.vote_data_count); if (rc) { if (rc) { Loading Loading @@ -1675,27 +1697,10 @@ static inline int venus_hfi_power_on(struct venus_hfi_device *device) goto err_reset_core; goto err_reset_core; } } /* * set the flag here to skip venus_hfi_power_on() which is * being called again via __alloc_set_ocmem() if ocmem is enabled */ device->power_enabled = true; device->power_enabled = true; /* * write_lock is already acquired at this point, so to avoid * recursive lock in cmdq_write function, call nolock version * of alloc_ocmem */ WARN_ON(!mutex_is_locked(&device->write_lock)); rc = __alloc_set_ocmem(device, false); if (rc) { dprintk(VIDC_ERR, "Failed to allocate OCMEM"); goto err_alloc_ocmem; } dprintk(VIDC_INFO, "Resumed from power collapse\n"); dprintk(VIDC_INFO, "Resumed from power collapse\n"); return rc; return rc; err_alloc_ocmem: err_reset_core: err_reset_core: venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND); venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND); err_set_video_state: err_set_video_state: Loading Loading @@ -1811,18 +1816,6 @@ static int venus_hfi_iface_cmdq_write_nolock(struct venus_hfi_device *device, device, VIDC_CPU_IC_SOFTINT, device, VIDC_CPU_IC_SOFTINT, 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT); 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT); if (device->res->sw_power_collapsible) { dprintk(VIDC_DBG, "Cancel and queue delayed work again\n"); cancel_delayed_work(&venus_hfi_pm_work); if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, msecs_to_jiffies( msm_vidc_pwr_collapse_delay))) { dprintk(VIDC_DBG, "PM work already scheduled\n"); } } result = 0; result = 0; } else { } else { dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full\n"); dprintk(VIDC_ERR, "venus_hfi_iface_cmdq_write:queue_full\n"); Loading Loading @@ -3102,9 +3095,13 @@ static int venus_hfi_core_pc_prep(void *device) dprintk(VIDC_ERR, "Failed to create sys pc prep pkt\n"); dprintk(VIDC_ERR, "Failed to create sys pc prep pkt\n"); goto err_create_pkt; goto err_create_pkt; } } /* Calling write_nolock() with write_lock instead of write() if (venus_hfi_iface_cmdq_write(dev, &pkt)) * because write() will cancel and rescheduling power collapse. */ mutex_lock(&dev->write_lock); if (venus_hfi_iface_cmdq_write_nolock(dev, &pkt)) rc = -ENOTEMPTY; rc = -ENOTEMPTY; mutex_unlock(&dev->write_lock); err_create_pkt: err_create_pkt: return rc; return rc; Loading Loading @@ -3144,6 +3141,7 @@ static void venus_hfi_pm_hndlr(struct work_struct *work) dprintk(VIDC_ERR, "%s: NULL device\n", __func__); dprintk(VIDC_ERR, "%s: NULL device\n", __func__); return; return; } } if (!device->power_enabled) { if (!device->power_enabled) { dprintk(VIDC_DBG, "%s: Power already disabled\n", dprintk(VIDC_DBG, "%s: Power already disabled\n", __func__); __func__); Loading @@ -3164,22 +3162,9 @@ static void venus_hfi_pm_hndlr(struct work_struct *work) dprintk(VIDC_DBG, "Prepare for power collapse\n"); dprintk(VIDC_DBG, "Prepare for power collapse\n"); mutex_lock(&device->resource_lock); rc = __unset_free_ocmem(device); mutex_unlock(&device->resource_lock); if (rc) { dprintk(VIDC_ERR, "Failed to unset and free OCMEM for PC, rc : %d\n", rc); return; } rc = venus_hfi_prepare_pc(device); rc = venus_hfi_prepare_pc(device); if (rc) { if (rc) { dprintk(VIDC_ERR, "Failed to prepare for PC, rc : %d\n", rc); dprintk(VIDC_ERR, "Failed to prepare for PC, rc : %d\n", rc); rc = __alloc_set_ocmem(device, true); if (rc) dprintk(VIDC_WARN, "Failed to re-allocate OCMEM. Performance will be impacted\n"); return; return; } } Loading Loading @@ -3212,6 +3197,13 @@ static void venus_hfi_pm_hndlr(struct work_struct *work) goto err_power_off; goto err_power_off; } } mutex_lock(&device->resource_lock); rc = __free_ocmem(device); mutex_unlock(&device->resource_lock); if (rc) dprintk(VIDC_ERR, "Failed to free OCMEM for PC, rc : %d\n", rc); /* Cancel pending delayed works if any */ /* Cancel pending delayed works if any */ cancel_delayed_work(&venus_hfi_pm_work); cancel_delayed_work(&venus_hfi_pm_work); Loading @@ -3234,10 +3226,6 @@ skip_power_off: device->last_packet_type, ctrl_status); device->last_packet_type, ctrl_status); mutex_unlock(&device->write_lock); mutex_unlock(&device->write_lock); rc = __alloc_set_ocmem(device, true); if (rc) dprintk(VIDC_WARN, "Failed to re-allocate OCMEM. Performance will be impacted\n"); return; return; } } Loading Loading @@ -3400,7 +3388,8 @@ static void venus_hfi_core_work_handler(struct work_struct *work) return; return; } } if (device->res->sw_power_collapsible) { if (device->res->sw_power_collapsible) { dprintk(VIDC_DBG, "Cancel and queue delayed work again.\n"); dprintk(VIDC_DBG, "Cancel and queue delayed work from %s\n", __func__); cancel_delayed_work(&venus_hfi_pm_work); cancel_delayed_work(&venus_hfi_pm_work); if (!queue_delayed_work(device->venus_pm_workq, if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work, &venus_hfi_pm_work, Loading