From bd07e7ccbe6b8ff55a5a2acac96ae1d42ddb103c Mon Sep 17 00:00:00 2001 From: Hu Kejun Date: Mon, 27 May 2019 10:07:16 +0800 Subject: [PATCH] media: rockchip: isp1: fix kernel reboot in monkey test 1. use the same mutex to serialize the calls from user application. 2. keep iommu attached state when last video is closed, because the user application may still access the buffer allocated by v4l2 driver. Change-Id: I667a42a07672e5d30cc4383e9f54388fe1b91f1c Signed-off-by: Hu Kejun --- .../media/platform/rockchip/isp1/capture.c | 13 ++++------ drivers/media/platform/rockchip/isp1/common.h | 2 -- drivers/media/platform/rockchip/isp1/dev.c | 26 ++++++++++++++++--- drivers/media/platform/rockchip/isp1/dev.h | 1 + drivers/media/platform/rockchip/isp1/dmarx.c | 5 ++-- .../media/platform/rockchip/isp1/isp_params.c | 5 ++-- .../media/platform/rockchip/isp1/isp_stats.c | 5 ++-- 7 files changed, 35 insertions(+), 22 deletions(-) diff --git a/drivers/media/platform/rockchip/isp1/capture.c b/drivers/media/platform/rockchip/isp1/capture.c index 16454d8e40a3..b179966b340b 100644 --- a/drivers/media/platform/rockchip/isp1/capture.c +++ b/drivers/media/platform/rockchip/isp1/capture.c @@ -944,6 +944,7 @@ static int raw_config_mi(struct rkisp1_stream *stream) in_size = raw->out_fmt.plane_fmt[0].sizeimage; } + dmatx0_set_pic_size(base, in_frm->width, in_frm->height); dmatx0_set_pic_off(base, 0); dmatx0_ctrl(base, @@ -1601,7 +1602,7 @@ static int rkisp_init_vb2_queue(struct vb2_queue *q, q->buf_struct_size = sizeof(struct rkisp1_buffer); q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN; q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->vlock; + q->lock = &stream->ispdev->apilock; return vb2_queue_init(q); } @@ -1720,9 +1721,7 @@ int rkisp1_fh_open(struct file *filp) ret = v4l2_fh_open(filp); if (!ret) { - if (atomic_inc_return(&dev->open_cnt) == 1) - rkisp1_dma_attach_device(dev); - + atomic_inc(&dev->open_cnt); ret = dev->pipe.pm_use(&vdev->entity, 1); if (ret < 0) v4l2_err(&dev->v4l2_dev, @@ -1746,8 +1745,7 @@ int rkisp1_fop_release(struct file *file) v4l2_err(&dev->v4l2_dev, "set pipeline power failed %d\n", ret); - if (atomic_dec_return(&dev->open_cnt) == 0) - rkisp1_dma_detach_device(dev); + atomic_dec(&dev->open_cnt); } return ret; @@ -2058,14 +2056,13 @@ static int rkisp1_register_stream_vdev(struct rkisp1_stream *stream) } strlcpy(vdev->name, vdev_name, sizeof(vdev->name)); node = vdev_to_node(vdev); - mutex_init(&node->vlock); vdev->ioctl_ops = &rkisp1_v4l2_ioctl_ops; vdev->release = video_device_release_empty; vdev->fops = &rkisp1_fops; vdev->minor = -1; vdev->v4l2_dev = v4l2_dev; - vdev->lock = &node->vlock; + vdev->lock = &dev->apilock; vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING; video_set_drvdata(vdev, stream); diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h index 7a41e40a8bcb..69557e179bea 100644 --- a/drivers/media/platform/rockchip/isp1/common.h +++ b/drivers/media/platform/rockchip/isp1/common.h @@ -69,8 +69,6 @@ enum rkisp1_sd_type { /* One structure per video node */ struct rkisp1_vdev_node { struct vb2_queue buf_queue; - /* vfd lock */ - struct mutex vlock; struct video_device vdev; struct media_pad pad; }; diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c index 29805442b027..2614900cbd6b 100644 --- a/drivers/media/platform/rockchip/isp1/dev.c +++ b/drivers/media/platform/rockchip/isp1/dev.c @@ -991,8 +991,10 @@ err: static int rkisp1_iommu_init(struct rkisp1_device *rkisp1_dev) { + struct device *dev = rkisp1_dev->dev; + struct iommu_domain *domain; struct iommu_group *group; - int ret; + int ret = 0; rkisp1_dev->domain = iommu_domain_alloc(&platform_bus_type); if (!rkisp1_dev->domain) { @@ -1000,6 +1002,7 @@ static int rkisp1_iommu_init(struct rkisp1_device *rkisp1_dev) goto err; } + domain = rkisp1_dev->domain; ret = iommu_get_dma_cookie(rkisp1_dev->domain); if (ret) goto err; @@ -1015,7 +1018,19 @@ static int rkisp1_iommu_init(struct rkisp1_device *rkisp1_dev) goto err; } - return 0; + ret = iommu_attach_device(domain, dev); + if (ret) { + dev_err(dev, "Failed to attach iommu device\n"); + goto err; + } + + if (!common_iommu_setup_dma_ops(dev, 0x10000000, SZ_2G, domain->ops)) { + dev_err(dev, "Failed to set dma_ops\n"); + iommu_detach_device(domain, dev); + ret = -ENODEV; + } + + return ret; err: dev_err(rkisp1_dev->dev, "Failed to setup IOMMU\n"); @@ -1025,7 +1040,11 @@ err: static void rkisp1_iommu_cleanup(struct rkisp1_device *rkisp1_dev) { - iommu_domain_free(rkisp1_dev->domain); + struct iommu_domain *domain = rkisp1_dev->domain; + struct device *dev = rkisp1_dev->dev; + + iommu_detach_device(domain, dev); + iommu_domain_free(domain); } static int rkisp1_vs_irq_parse(struct platform_device *pdev) @@ -1164,6 +1183,7 @@ static int rkisp1_plat_probe(struct platform_device *pdev) isp_dev->clk_rate_tbl = match_data->clk_rate_tbl; isp_dev->num_clk_rate_tbl = match_data->num_clk_rate_tbl; + mutex_init(&isp_dev->apilock); atomic_set(&isp_dev->pipe.power_cnt, 0); atomic_set(&isp_dev->pipe.stream_cnt, 0); atomic_set(&isp_dev->open_cnt, 0); diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h index 80e925abe865..632821e4e569 100644 --- a/drivers/media/platform/rockchip/isp1/dev.h +++ b/drivers/media/platform/rockchip/isp1/dev.h @@ -166,6 +166,7 @@ struct rkisp1_device { enum rkisp1_isp_state isp_state; unsigned int isp_err_cnt; enum rkisp1_isp_inp isp_inp; + struct mutex apilock; /* mutex to serialize the calls from user */ }; #endif diff --git a/drivers/media/platform/rockchip/isp1/dmarx.c b/drivers/media/platform/rockchip/isp1/dmarx.c index 8a7373e99148..ce271668beea 100644 --- a/drivers/media/platform/rockchip/isp1/dmarx.c +++ b/drivers/media/platform/rockchip/isp1/dmarx.c @@ -403,7 +403,7 @@ static int rkisp_init_vb2_queue(struct vb2_queue *q, q->buf_struct_size = sizeof(struct rkisp1_buffer); q->min_buffers_needed = CIF_ISP_REQ_BUFS_MIN; q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->vlock; + q->lock = &stream->ispdev->apilock; return vb2_queue_init(q); } @@ -594,13 +594,12 @@ static int rkisp1_register_dmarx_video(struct rkisp1_stream *stream) int ret = 0; node = vdev_to_node(vdev); - mutex_init(&node->vlock); vdev->release = video_device_release_empty; vdev->fops = &rkisp1_fops; vdev->minor = -1; vdev->v4l2_dev = v4l2_dev; - vdev->lock = &node->vlock; + vdev->lock = &dev->apilock; video_set_drvdata(vdev, stream); vdev->ioctl_ops = &rkisp1_dmarx_ioctl; diff --git a/drivers/media/platform/rockchip/isp1/isp_params.c b/drivers/media/platform/rockchip/isp1/isp_params.c index ccce1ab283df..0f8f3613f1c5 100644 --- a/drivers/media/platform/rockchip/isp1/isp_params.c +++ b/drivers/media/platform/rockchip/isp1/isp_params.c @@ -2557,7 +2557,7 @@ rkisp1_params_init_vb2_queue(struct vb2_queue *q, q->mem_ops = &vb2_vmalloc_memops; q->buf_struct_size = sizeof(struct rkisp1_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->vlock; + q->lock = ¶ms_vdev->dev->apilock; return vb2_queue_init(q); } @@ -2588,7 +2588,6 @@ int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev, struct video_device *vdev = &node->vdev; params_vdev->dev = dev; - mutex_init(&node->vlock); spin_lock_init(¶ms_vdev->config_lock); strlcpy(vdev->name, "rkisp1-input-params", sizeof(vdev->name)); @@ -2601,7 +2600,7 @@ int rkisp1_register_params_vdev(struct rkisp1_isp_params_vdev *params_vdev, * Provide a mutex to v4l2 core. It will be used * to protect all fops and v4l2 ioctls. */ - vdev->lock = &node->vlock; + vdev->lock = &dev->apilock; vdev->v4l2_dev = v4l2_dev; vdev->queue = &node->buf_queue; vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT; diff --git a/drivers/media/platform/rockchip/isp1/isp_stats.c b/drivers/media/platform/rockchip/isp1/isp_stats.c index 5e0998d1bc67..66d24b5270a9 100644 --- a/drivers/media/platform/rockchip/isp1/isp_stats.c +++ b/drivers/media/platform/rockchip/isp1/isp_stats.c @@ -215,7 +215,7 @@ static int rkisp1_stats_init_vb2_queue(struct vb2_queue *q, q->mem_ops = &vb2_vmalloc_memops; q->buf_struct_size = sizeof(struct rkisp1_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->vlock; + q->lock = &stats_vdev->dev->apilock; return vb2_queue_init(q); } @@ -623,7 +623,6 @@ int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev, struct video_device *vdev = &node->vdev; stats_vdev->dev = dev; - mutex_init(&node->vlock); INIT_LIST_HEAD(&stats_vdev->stat); spin_lock_init(&stats_vdev->irq_lock); spin_lock_init(&stats_vdev->rd_lock); @@ -634,7 +633,7 @@ int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev, vdev->ioctl_ops = &rkisp1_stats_ioctl; vdev->fops = &rkisp1_stats_fops; vdev->release = video_device_release_empty; - vdev->lock = &node->vlock; + vdev->lock = &dev->apilock; vdev->v4l2_dev = v4l2_dev; vdev->queue = &node->buf_queue; vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING;