From 283fd1016a8158a1fe3a4a84d7046c72f7bdd0ef Mon Sep 17 00:00:00 2001 From: Jung Zhao Date: Tue, 22 Aug 2017 14:37:20 +0800 Subject: [PATCH] video: rockchip: vpu: add reset lock if someone call iommu translate during vpu_reset, it may cause core dump. add reset lock to avoid this situation. Change-Id: Ia58eb106525a2f97d07b69c23cc4ef1b4d4cf151 Signed-off-by: Jung Zhao --- drivers/video/rockchip/vcodec/vcodec_service.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c index 979dab150465..bf756d96be16 100644 --- a/drivers/video/rockchip/vcodec/vcodec_service.c +++ b/drivers/video/rockchip/vcodec/vcodec_service.c @@ -385,6 +385,13 @@ struct vpu_service_info { atomic_t power_off_cnt; atomic_t service_on; struct mutex shutdown_lock; + /* + * FIXME: if someone call iommu translate function during vpu_reset, + * it may cause system core dump without any message. we suggest + * modify iommu driver to avoid this situation. before that, + * this is a temporary solution. + */ + struct mutex reset_lock; struct vpu_reg *reg_codec; struct vpu_reg *reg_pproc; struct vpu_reg *reg_resev; @@ -723,7 +730,9 @@ static void vpu_reset(struct vpu_subdev_data *data) { struct vpu_service_info *pservice = data->pservice; + mutex_lock(&pservice->reset_lock); _vpu_reset(data); + mutex_unlock(&pservice->reset_lock); if (data->mmu_dev && test_bit(MMU_ACTIVATED, &data->state)) { clear_bit(MMU_ACTIVATED, &data->state); if (atomic_read(&pservice->enabled)) { @@ -1275,9 +1284,11 @@ static struct vpu_reg *reg_init(struct vpu_subdev_data *data, return NULL; } + mutex_lock(&pservice->reset_lock); if (vcodec_reg_address_translate(data, session, reg, &extra_info) < 0) { int i = 0; + mutex_unlock(&pservice->reset_lock); vpu_err("error: translate reg address failed, dumping regs\n"); for (i = 0; i < size >> 2; i++) dev_err(pservice->dev, "reg[%02d]: %08x\n", @@ -1286,6 +1297,7 @@ static struct vpu_reg *reg_init(struct vpu_subdev_data *data, kfree(reg); return NULL; } + mutex_unlock(&pservice->reset_lock); mutex_lock(&pservice->lock); list_add_tail(®->status_link, &pservice->waiting); @@ -2605,6 +2617,7 @@ static void vcodec_init_drvdata(struct vpu_service_info *pservice) INIT_LIST_HEAD(&pservice->running); mutex_init(&pservice->lock); mutex_init(&pservice->shutdown_lock); + mutex_init(&pservice->reset_lock); atomic_set(&pservice->service_on, 1); INIT_LIST_HEAD(&pservice->done);