camera: rockchip: camsys driver v0.0x21.9
authordalong.zhang <dalon.zhang@rock-chips.com>
Thu, 22 Dec 2016 03:26:08 +0000 (11:26 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Thu, 22 Dec 2016 06:00:27 +0000 (14:00 +0800)
Change-Id: I371f3bfc1e6276407bb9481f4a7897d4955903ba
Signed-off-by: dalong.zhang <dalon.zhang@rock-chips.com>
drivers/media/video/rk_camsys/camsys_internal.h
drivers/media/video/rk_camsys/camsys_marvin.c

index 4b73fddad5ca0cf67286eb6f171f9dbd85864a49..11efb236005f38bbdefaa65af985e3abfaff6850 100644 (file)
 *       1) remove memset function wrong called code.
 *v0.0x21.8:
 *       1) flash module exist risk, fix up it.
+*v0.0x21.9:
+       1) fix drm iommu crash.
+       if process cameraserver was died during streaming, iommu resource
+       was not released correctly. when cameraserver was recovered and
+       streaming again, iommu resource may be conflicted.
 */
-#define CAMSYS_DRIVER_VERSION                   KERNEL_VERSION(0, 0x21, 8)
+#define CAMSYS_DRIVER_VERSION                   KERNEL_VERSION(0, 0x21, 9)
 
 #define CAMSYS_PLATFORM_DRV_NAME                "RockChip-CamSys"
 #define CAMSYS_PLATFORM_MARVIN_NAME             "Platform_MarvinDev"
index 4321bddb87c24c909141c087ddb75db037031f88..e3e236f0e08589a8f535107b53b8f5ba8ba48559 100755 (executable)
@@ -393,13 +393,43 @@ static int camsys_mrv_drm_iommu_cb(void *ptr, camsys_sysctrl_t *devctl)
 
        dev = &camsys_dev->pdev->dev;
        iommu = (camsys_iommu_t *)(devctl->rev);
-       index = camsys_dev->dma_buf_cnt;
        if (devctl->on) {
-               if (index == 0) {
+               /*ummap mapped fd first*/
+               int cur_mapped_cnt = camsys_dev->dma_buf_cnt;
+
+               for (index = 0; index < cur_mapped_cnt; index++) {
+                       if (camsys_dev->dma_buf[index].fd == iommu->map_fd)
+                               break;
+               }
+               if (index != cur_mapped_cnt) {
+                       attach = camsys_dev->dma_buf[index].attach;
+                       dma_buf = camsys_dev->dma_buf[index].dma_buf;
+                       sgt = camsys_dev->dma_buf[index].sgt;
+                       dma_buf_unmap_attachment
+                               (attach,
+                               sgt,
+                               DMA_BIDIRECTIONAL);
+                       dma_buf_detach(dma_buf, attach);
+                       dma_buf_put(dma_buf);
+                       if (camsys_dev->dma_buf_cnt == 1)
+                               camsys_drm_dma_detach_device(camsys_dev);
+                       camsys_dev->dma_buf_cnt--;
+                       camsys_dev->dma_buf[index].fd = -1;
+               }
+               /*get a free slot*/
+               for (index = 0; index < CAMSYS_DMA_BUF_MAX_NUM; index++)
+                       if (camsys_dev->dma_buf[index].fd == -1)
+                               break;
+
+               if (index == CAMSYS_DMA_BUF_MAX_NUM)
+                       return -ENOMEM;
+
+               if (camsys_dev->dma_buf_cnt == 0) {
                        ret = camsys_drm_dma_attach_device(camsys_dev);
                        if (ret)
                                return ret;
                }
+
                dma_buf = dma_buf_get(iommu->map_fd);
                if (IS_ERR(dma_buf))
                        return PTR_ERR(dma_buf);
@@ -423,10 +453,25 @@ static int camsys_mrv_drm_iommu_cb(void *ptr, camsys_sysctrl_t *devctl)
                iommu->linear_addr = dma_addr;
                iommu->len = sg_dma_len(sgt->sgl);
                camsys_dev->dma_buf_cnt++;
+               camsys_trace
+                       (
+                       1,
+                       "%s:iommu map dma_addr 0x%lx,attach %p,"
+                       "dma_buf %p,sgt %p,fd %d,buf_cnt %d",
+                       __func__,
+                       (unsigned long)dma_addr,
+                       attach,
+                       dma_buf,
+                       sgt,
+                       iommu->map_fd,
+                       camsys_dev->dma_buf_cnt);
        } else {
-               if ((camsys_dev->dma_buf_cnt == 0) || (index < 0) ||
-                               (index >= CAMSYS_DMA_BUF_MAX_NUM))
+               if (
+                       (camsys_dev->dma_buf_cnt == 0) ||
+                       (index < 0) ||
+                       (index >= CAMSYS_DMA_BUF_MAX_NUM))
                        return -EINVAL;
+
                for (index = 0; index < camsys_dev->dma_buf_cnt; index++) {
                        if (camsys_dev->dma_buf[index].fd == iommu->map_fd)
                                break;
@@ -438,6 +483,16 @@ static int camsys_mrv_drm_iommu_cb(void *ptr, camsys_sysctrl_t *devctl)
                attach = camsys_dev->dma_buf[index].attach;
                dma_buf = camsys_dev->dma_buf[index].dma_buf;
                sgt = camsys_dev->dma_buf[index].sgt;
+               camsys_trace
+                               (
+                               1,
+                               "%s:iommu map ,attach %p,"
+                               "dma_buf %p,sgt %p,index %d",
+                               __func__,
+                               attach,
+                               dma_buf,
+                               sgt,
+                               index);
                dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
                dma_buf_detach(dma_buf, attach);
                dma_buf_put(dma_buf);
@@ -445,6 +500,7 @@ static int camsys_mrv_drm_iommu_cb(void *ptr, camsys_sysctrl_t *devctl)
                        camsys_drm_dma_detach_device(camsys_dev);
 
                camsys_dev->dma_buf_cnt--;
+               camsys_dev->dma_buf[index].fd = -1;
        }
 
        return ret;
@@ -1043,6 +1099,7 @@ int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
 
        np = of_find_node_by_name(NULL, "isp0_mmu");
        if (!np) {
+               int index = 0;
                /* iommu domain */
                domain = iommu_domain_alloc(&platform_bus_type);
                if (!domain)
@@ -1070,6 +1127,8 @@ int camsys_mrv_probe_cb(struct platform_device *pdev, camsys_dev_t *camsys_dev)
                camsys_dev->domain = domain;
                camsys_dev->dma_buf_cnt = 0;
                camsys_dev->iommu_cb = camsys_mrv_drm_iommu_cb;
+               for (index = 0; index < CAMSYS_DMA_BUF_MAX_NUM; index++)
+                       camsys_dev->dma_buf[index].fd = -1;
        } else {
                camsys_dev->iommu_cb = camsys_mrv_iommu_cb;
        }