diff options
author | hding3 <haitao.ding@intel.com> | 2015-08-24 18:47:45 -0700 |
---|---|---|
committer | hding3 <haitao.ding@intel.com> | 2015-08-25 13:57:36 +0800 |
commit | ca71cf6ceda8b86c2d31996a224414df4b10d4b0 (patch) | |
tree | a64f649ad1e3f050101088fca3aea524382013da | |
parent | c80a1e42fdee40827631616e21a5b9ef0c90b2f9 (diff) | |
download | x86_64-android-x86_64-fugu-3.10-marshmallow.tar.gz |
Refine VSP power managementandroid-6.0.0_r0.2android-x86_64-fugu-3.10-marshmallow
BUG: 22602467
Replace the legacy ospm_apm_power_down_vsp with the new framework/power_island_put
Add recovery logic when VSP hang
Change-Id: I03bafc9d9db315aae7ad53638ebd643b1830f4d5
Signed-off-by: hding3 <haitao.ding@intel.com>
4 files changed, 87 insertions, 32 deletions
diff --git a/drivers/external_drivers/intel_media/display/tng/drv/ospm/pwr_mgmt.c b/drivers/external_drivers/intel_media/display/tng/drv/ospm/pwr_mgmt.c index ad4c0803457d..2b124cb8e3c7 100755 --- a/drivers/external_drivers/intel_media/display/tng/drv/ospm/pwr_mgmt.c +++ b/drivers/external_drivers/intel_media/display/tng/drv/ospm/pwr_mgmt.c @@ -811,6 +811,7 @@ void ospm_apm_power_down_vsp(struct drm_device *dev) struct ospm_power_island *p_island; struct drm_psb_private *dev_priv = dev->dev_private; struct vsp_private *vsp_priv = dev_priv->vsp_private; + int island_ref; PSB_DEBUG_PM("Power down VPP...\n"); p_island = get_island_ptr(OSPM_VIDEO_VPP_ISLAND); @@ -825,9 +826,10 @@ void ospm_apm_power_down_vsp(struct drm_device *dev) if (!ospm_power_is_hw_on(OSPM_VIDEO_VPP_ISLAND)) goto out; - if (atomic_read(&p_island->ref_count)) + island_ref = atomic_read(&p_island->ref_count); + if (island_ref) PSB_DEBUG_PM("VPP ref_count has been set(%d), bypass\n", - atomic_read(&p_island->ref_count)); + island_ref); if (vsp_priv->vsp_cmd_num > 0) { VSP_DEBUG("command in VSP, by pass\n"); @@ -847,11 +849,16 @@ void ospm_apm_power_down_vsp(struct drm_device *dev) /* handle the dependency */ if (p_island->p_dependency) { /* Power down dependent island */ - power_down_island(p_island->p_dependency); + do { + power_down_island(p_island->p_dependency); + island_ref--; + } while (island_ref); } if (!any_island_on()) { PSB_DEBUG_PM("Suspending PCI\n"); + pm_qos_add_request(&dev_priv->s0ix_qos, + PM_QOS_CPU_DMA_LATENCY, CSTATE_EXIT_LATENCY_S0i1 - 1); pm_runtime_put(&g_ospm_data->dev->pdev->dev); wake_unlock(&dev_priv->ospm_wake_lock); } diff --git a/drivers/external_drivers/intel_media/video/common/psb_cmdbuf.c b/drivers/external_drivers/intel_media/video/common/psb_cmdbuf.c index 65579de79beb..3943c845168c 100644 --- a/drivers/external_drivers/intel_media/video/common/psb_cmdbuf.c +++ b/drivers/external_drivers/intel_media/video/common/psb_cmdbuf.c @@ -836,8 +836,10 @@ static int psb_handle_copyback(struct drm_device *dev, } if (__copy_to_user(vbuf->user_val_arg, - &arg, sizeof(arg))) + &arg, sizeof(arg))) { err = -EFAULT; + DRM_ERROR("call __copy_to_user() function error!\n"); + } if (arg.ret) break; diff --git a/drivers/external_drivers/intel_media/video/vsp/vsp.c b/drivers/external_drivers/intel_media/video/vsp/vsp.c index 3a00fc9bc173..15b54043baac 100755 --- a/drivers/external_drivers/intel_media/video/vsp/vsp.c +++ b/drivers/external_drivers/intel_media/video/vsp/vsp.c @@ -73,6 +73,43 @@ static inline void psb_clflush(void *addr) __asm__ __volatile__("wbinvd "); } + +static inline void force_power_down_vsp(void) +{ + int count = 0; + VSP_DEBUG("Force to power down VSP\n"); + while (is_island_on(OSPM_VIDEO_VPP_ISLAND) && (count < 255)) { + count++; + VSP_DEBUG("The VSP is on, power down it, tries %d\n", count); + power_island_put(OSPM_VIDEO_VPP_ISLAND); + } + VSP_DEBUG("The VSP is off now (tried %d times)\n", count); +} + +static inline void power_down_vsp(void) +{ + VSP_DEBUG("Try to power down VSP\n"); + + if (is_island_on(OSPM_VIDEO_VPP_ISLAND)) { + VSP_DEBUG("The VSP is on, power down it\n"); + power_island_put(OSPM_VIDEO_VPP_ISLAND); + } else + VSP_DEBUG("The VSP is already off\n"); +} + +static inline void power_up_vsp(void) +{ + VSP_DEBUG("Try to power up VSP\n"); + + if (is_island_on(OSPM_VIDEO_VPP_ISLAND)) + VSP_DEBUG("The VSP is alraedy on\n"); + else { + VSP_DEBUG("The VSP is off, power up it\n"); + power_island_get(OSPM_VIDEO_VPP_ISLAND); + } +} + + int vsp_handle_response(struct drm_psb_private *dev_priv) { struct vsp_private *vsp_priv = dev_priv->vsp_private; @@ -311,8 +348,13 @@ int vsp_cmdbuf_vpp(struct drm_file *priv, /* If VSP timeout, don't send cmd to hardware anymore */ if (vsp_priv->vsp_state == VSP_STATE_HANG) { - DRM_ERROR("The VSP is hang abnormally!"); - return -EFAULT; + DRM_ERROR("The VSP is hang abnormally, try to reset vsp hardware!\n"); + + VSP_DEBUG("Force state to DOWN to force power down\n"); + vsp_priv->ctrl->entry_kind = vsp_exit; + vsp_priv->vsp_state = VSP_STATE_DOWN; + force_power_down_vsp(); + //return -EFAULT; } memset(&cmd_kmap, 0, sizeof(cmd_kmap)); @@ -358,8 +400,9 @@ int vsp_cmdbuf_vpp(struct drm_file *priv, if (drm_vsp_vpp_batch_cmd == 0) vsp_priv->force_flush_cmd = 1; - if (vsp_priv->vsp_state == VSP_STATE_IDLE) - ospm_apm_power_down_vsp(dev); + if ((drm_vsp_pmpolicy != PSB_PMPOLICY_NOPM) && + (vsp_priv->vsp_state == VSP_STATE_IDLE)) + power_down_vsp(); if (vsp_priv->acc_num_cmd >= 1 || vsp_priv->force_flush_cmd != 0 || vsp_priv->delayed_burst_cnt > 0) { @@ -1108,7 +1151,7 @@ int vsp_new_context(struct drm_device *dev, struct file *filp, int ctx_type) mutex_unlock(&vsp_priv->vsp_mutex); VSP_DEBUG("context_vp8_num %d, context_vpp_num %d\n", - vsp_priv->context_vp8_num, vsp_priv->context_vpp_num); + vsp_priv->context_vp8_num, vsp_priv->context_vpp_num); return ret; } @@ -1116,7 +1159,6 @@ void vsp_rm_context(struct drm_device *dev, struct file *filp, int ctx_type) { struct drm_psb_private *dev_priv = dev->dev_private; struct vsp_private *vsp_priv = dev_priv->vsp_private; - bool ret = true; int count = 0; struct vss_command_t *cur_cmd; bool tmp = true; @@ -1153,11 +1195,10 @@ void vsp_rm_context(struct drm_device *dev, struct file *filp, int ctx_type) VSP_DEBUG("ctx_type=%d\n", ctx_type); + /* power on the VSP hardware to write registers */ + power_up_vsp(); + if (VAEntrypointEncSlice == ctx_type && filp != vsp_priv->vp8_filp[3]) { - /* power on again to send VssGenDestroyContext to firmware */ - if (power_island_get(OSPM_VIDEO_VPP_ISLAND) == false) { - tmp = -EBUSY; - } if (vsp_priv->vsp_state == VSP_STATE_SUSPEND) { tmp = vsp_resume_function(dev_priv); VSP_DEBUG("The VSP is on suspend, send resume!\n"); @@ -1217,26 +1258,26 @@ void vsp_rm_context(struct drm_device *dev, struct file *filp, int ctx_type) if (vsp_priv->context_vp8_num > 0 || vsp_priv->context_vpp_num > 0) { VSP_DEBUG("context_vp8_num %d, context_vpp_num %d\n", vsp_priv->context_vp8_num, vsp_priv->context_vpp_num); + + power_down_vsp(); mutex_unlock(&vsp_priv->vsp_mutex); return; } vsp_priv->ctrl->entry_kind = vsp_exit; - mutex_unlock(&vsp_priv->vsp_mutex); - VSP_DEBUG("After mutex_unlock, start to power off VSP!\n"); + VSP_DEBUG("No context now, set state to DOWN to force power down\n"); + PSB_UDELAY(800); + /* in case of power mode 0, HW always active, * * in case got no response from FW, vsp_state=hang but could not be powered off, * * force state to down */ vsp_priv->vsp_state = VSP_STATE_DOWN; - ospm_apm_power_down_vsp(dev); + force_power_down_vsp(); vsp_priv->vsp_state = VSP_STATE_DOWN; - if (ret == false) - PSB_DEBUG_PM("Couldn't power down VSP!"); - else - PSB_DEBUG_PM("VSP: OK. Power down the HW!\n"); - + mutex_unlock(&vsp_priv->vsp_mutex); + VSP_DEBUG("vsp_rm_context is successful\n"); /* FIXME: frequency should change */ VSP_PERF("the total time spend on VSP is %llu ms\n", div_u64(vsp_priv->vss_cc_acc, 200 * 1000)); @@ -1376,15 +1417,17 @@ void vsp_irq_task(struct work_struct *work) sequence, vsp_priv->current_sequence); } - if (vsp_priv->vsp_state == VSP_STATE_IDLE) { - if (vsp_priv->ctrl->cmd_rd == vsp_priv->ctrl->cmd_wr) - ospm_apm_power_down_vsp(dev); - else { - while (ospm_power_is_hw_on(OSPM_VIDEO_VPP_ISLAND)) - ospm_apm_power_down_vsp(dev); - VSP_DEBUG("successfully power down VSP\n"); - power_island_get(OSPM_VIDEO_VPP_ISLAND); - vsp_resume_function(dev_priv); + if (drm_vsp_pmpolicy != PSB_PMPOLICY_NOPM){ + if (vsp_priv->vsp_state == VSP_STATE_IDLE) { + if (vsp_priv->ctrl->cmd_rd == vsp_priv->ctrl->cmd_wr) + power_down_vsp(); + else { + force_power_down_vsp(); + + VSP_DEBUG("Now power up VSP again to resume\n"); + power_up_vsp(); + vsp_resume_function(dev_priv); + } } } mutex_unlock(&vsp_priv->vsp_mutex); diff --git a/drivers/external_drivers/intel_media/video/vsp/vsp_fw.h b/drivers/external_drivers/intel_media/video/vsp/vsp_fw.h index 064a0531dc65..89b888929deb 100644 --- a/drivers/external_drivers/intel_media/video/vsp/vsp_fw.h +++ b/drivers/external_drivers/intel_media/video/vsp/vsp_fw.h @@ -578,6 +578,8 @@ struct VssVp8encSequenceParameterBuffer { uint32_t cyclic_intra_refresh; uint32_t concatenate_partitions; uint32_t recon_buffer_mode; + uint32_t generate_skip_frames; + uint32_t max_num_dropped_frames; uint32_t ts_number_layers; uint32_t ts_target_bitrate[3]; uint32_t ts_rate_decimator[3]; @@ -596,8 +598,9 @@ struct VssVp8encEncodedFrame { uint32_t quantizer[4]; uint32_t frame_flags; uint32_t partition_id; - uint32_t buffer_level; + uint32_t buffer_level[3]; uint32_t quality; + uint32_t overflow_bytes; uint32_t surfaceId_of_ref_frame[4]; uint32_t reserved[15]; uint32_t coded_data[1]; |