video: rockchip: vpu: fix some bugs

1. fix scaling list write overflow
2. add reset lock when vpu_reset

Change-Id: Iead232b6469f4f8a37b464c50086934931f0747f
Signed-off-by: Jung Zhao <jung.zhao@rock-chips.com>
This commit is contained in:
Jung Zhao 2018-01-04 11:50:42 +08:00 committed by Tao Huang
parent 87e3d09740
commit 0a27ad80d8

View File

@ -522,6 +522,7 @@ static void vcodec_enter_mode(struct vpu_subdev_data *data)
struct vpu_service_info *pservice = data->pservice;
struct vpu_subdev_data *subdata, *n;
mutex_lock(&pservice->reset_lock);
/*
* For the RK3228H, it is not necessary to write a register to
* switch vpu combo mode, it is unsafe to write the grf.
@ -574,12 +575,15 @@ static void vcodec_enter_mode(struct vpu_subdev_data *data)
static void vcodec_exit_mode(struct vpu_subdev_data *data)
{
struct vpu_service_info *pservice = data->pservice;
/*
* In case of VPU Combo, it require HW switch its running mode
* before the other HW component start work. set current HW running
* mode to none, can ensure HW switch to its reqired mode properly.
*/
data->pservice->curr_mode = VCODEC_RUNNING_MODE_NONE;
mutex_unlock(&pservice->reset_lock);
}
static int vpu_get_clk(struct vpu_service_info *pservice)
@ -716,12 +720,9 @@ static void vpu_reset(struct vpu_subdev_data *data)
mutex_lock(&pservice->reset_lock);
_vpu_reset(data);
mutex_unlock(&pservice->reset_lock);
if (data->mmu_dev && test_bit(MMU_PAGEFAULT, &data->state)) {
if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) {
clear_bit(MMU_ACTIVATED, &data->state);
clear_bit(MMU_PAGEFAULT, &data->state);
} else if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) {
clear_bit(MMU_ACTIVATED, &data->state);
if (atomic_read(&pservice->enabled)) {
/* Need to reset iommu */
vcodec_iommu_detach(data->iommu_info);
@ -731,6 +732,8 @@ static void vpu_reset(struct vpu_subdev_data *data)
}
}
mutex_unlock(&pservice->reset_lock);
atomic_set(&pservice->reset_request, 0);
dev_info(pservice->dev, "reset done\n");
}
@ -801,12 +804,14 @@ static void vpu_service_power_off(struct vpu_service_info *pservice)
udelay(5);
mutex_lock(&pservice->reset_lock);
list_for_each_entry_safe(data, n, &pservice->subdev_list, lnk_service) {
if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) {
clear_bit(MMU_ACTIVATED, &data->state);
vcodec_iommu_detach(data->iommu_info);
}
}
mutex_unlock(&pservice->reset_lock);
pservice->curr_mode = VCODEC_RUNNING_MODE_NONE;
if (pservice->hw_ops->power_off)
pservice->hw_ops->power_off(pservice);
@ -985,7 +990,7 @@ static int fill_scaling_list_pps(struct vpu_subdev_data *data,
if (scaling_fd > 0) {
int i = 0;
dma_addr_t tmp = vcodec_fd_to_iova(data, reg->session, reg,
u32 tmp = vcodec_fd_to_iova(data, reg->session, reg,
scaling_fd);
if (IS_ERR_VALUE(tmp))
@ -1081,8 +1086,10 @@ static int vcodec_bufid_to_iova(struct vpu_subdev_data *data,
pps_info_count = 64;
pps_info_size = 80;
scaling_offset = 74;
offset = 0;
} break;
default: {
offset = 0;
pps_info_count = 0;
pps_info_size = 0;
scaling_offset = 0;
@ -2492,7 +2499,7 @@ _vcodec_sys_fault_hdl(struct device *dev, unsigned long iova, int status)
data->pa_iova,
IOMMU_PAGE_SIZE);
} else {
vpu_reset(data);
clear_bit(MMU_PAGEFAULT, &data->state);
}
}