video/rockchip: rga2: fix rga crash with high memory
authorMark Yao <mark.yao@rock-chips.com>
Wed, 19 Apr 2017 08:00:44 +0000 (16:00 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 24 Apr 2017 06:47:06 +0000 (14:47 +0800)
phys_to_virt not support highmem.

[   38.247986] Unable to handle kernel paging request at virtual address 20857000
[   38.306701] pgd = ed418000
[   38.309505] [20857000] *pgd=00000000
[   38.313118] Internal error: Oops: 2805 [#1] PREEMPT SMP ARM
[   38.318682] Modules linked in:
[   38.321746] CPU: 2 PID: 1410 Comm: DisplayThread Not tainted 4.4.55 #156
[   38.328435] Hardware name: Rockchip (Device Tree)
[   38.333131] task: dd2ad480 ti: dcc08000 task.ti: dcc08000
[   38.338527] PC is at v7_dma_flush_range+0x1c/0x34
[   38.343225] LR is at rga_dma_flush_range+0x30/0x68
[   39.215229] [<c0117440>] (v7_dma_flush_range) from [<c03f969c>] (rga_dma_flush_range+0x30/0x68)
[   39.223918] [<c03f969c>] (rga_dma_flush_range) from [<c03f98f4>] (rga2_MapUserMemory+0x220/0x2b0)
[   39.232777] [<c03f98f4>] (rga2_MapUserMemory) from [<c03f9bd4>] (rga2_set_mmu_info+0x1bc/0x928)
[   39.241461] [<c03f9bd4>] (rga2_set_mmu_info) from [<c03f8930>] (rga2_blit+0x2f4/0x448)
[   39.249366] [<c03f8930>] (rga2_blit) from [<c03f8ae8>] (rga2_blit_sync+0x64/0x1b0)
[   39.256923] [<c03f8ae8>] (rga2_blit_sync) from [<c03f91dc>] (rga_ioctl+0x4d0/0x6d8)
[   39.264570] [<c03f91dc>] (rga_ioctl) from [<c023ea58>] (do_vfs_ioctl+0x564/0x6a0)
[   39.272042] [<c023ea58>] (do_vfs_ioctl) from [<c023ebe0>] (SyS_ioctl+0x4c/0x74)
[   39.279342] [<c023ebe0>] (SyS_ioctl) from [<c0107180>] (ret_fast_syscall+0x0/0x3c)

Change-Id: I81fe2d108932a96414a2822c1329c4335753d1d9
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
drivers/video/rockchip/rga2/rga2_mmu_info.c

index 2cd40a5d040c9294213ba66593caa16df30116c5..1d41fa48b908c93c4a58ad2bfbcc2aeb5e0afc56 100644 (file)
@@ -269,6 +269,7 @@ static int rga2_MapUserMemory(struct page **pages, uint32_t *pageTable,
        uint32_t status;
        unsigned long Address;
        unsigned long pfn;
+       struct page __maybe_unused *page;
        void *virt;
        spinlock_t * ptl;
        pte_t * pte;
@@ -338,8 +339,30 @@ static int rga2_MapUserMemory(struct page **pages, uint32_t *pageTable,
                           << PAGE_SHIFT)) & ~PAGE_MASK));
                pte_unmap_unlock(pte, ptl);
                pageTable[i] = (uint32_t)Address;
-               virt = phys_to_virt(pageTable[i]);
-               rga_dma_flush_range(virt, virt + 4 * 1024);
+
+#ifdef CONFIG_ARM
+               page = pfn_to_page(pfn);
+               if (PageHighMem(page)) {
+                       if (cache_is_vipt_nonaliasing()) {
+                               virt = kmap_atomic(page);
+                               dmac_flush_range(virt, virt + PAGE_SIZE);
+                               kunmap_atomic(virt);
+                       } else {
+                               virt = kmap_high_get(page);
+                               if (virt) {
+                                       dmac_flush_range(virt,
+                                                        virt + PAGE_SIZE);
+                                       kunmap_high(page);
+                               }
+                       }
+                       outer_flush_range(pageTable[i],
+                                         pageTable[i] + PAGE_SIZE);
+               } else
+#endif
+               {
+                       virt = phys_to_virt(pageTable[i]);
+                       rga_dma_flush_range(virt, virt + 4 * 1024);
+               }
        }
        up_read(&current->mm->mmap_sem);
        return status;