From e70f2f4ac48542dac72c7e437ed7af38bf220de1 Mon Sep 17 00:00:00 2001 From: Tao Huang Date: Thu, 27 May 2021 20:46:52 +0800 Subject: [PATCH] Revert "ANDROID: GKI: arm64: add support for NO_KERNEL_MAPPING and STRONGLY_ORDERED" This reverts commit 4ac42c440404fcda2d6baae7db6eb0a75136cf6d. DMA_ATTR_NO_KERNEL_MAPPING is not well supported on apply_to_page_range(), which causes the following error: [ 2.268586] nvme nvme0: pci function 0002:21:00.0 [ 2.268649] nvme 0002:21:00.0: enabling device (0000 -> 0002) [ 2.376361] nvme nvme0: missing or invalid SUBNQN field. [ 2.378661] Unable to handle kernel paging request at virtual address ffffffc400000000 [ 2.379360] Mem abort info: [ 2.379616] ESR = 0x96000045 [ 2.379895] Exception class = DABT (current EL), IL = 32 bits [ 2.380414] SET = 0, FnV = 0 [ 2.380691] EA = 0, S1PTW = 0 [ 2.380970] Data abort info: [ 2.381237] ISV = 0, ISS = 0x00000045 [ 2.381575] CM = 0, WnR = 1 [ 2.381846] swapper pgtable: 4k pages, 39-bit VAs, pgdp = 000000005a0c0862 [ 2.382446] [ffffffc400000000] pgd=0000000000000000, pud=0000000000000000 [ 2.383049] Internal error: Oops: 96000045 [#1] PREEMPT SMP [ 2.383546] Modules linked in: [ 2.383827] Process kworker/u8:0 (pid: 7, stack limit = 0x00000000b285d686) [ 2.384441] CPU: 3 PID: 7 Comm: kworker/u8:0 Not tainted 4.19.172 #134 [ 2.385017] Hardware name: Rockchip RK3568 EVB1 DDR4 V10 Board (DT) [ 2.385580] Workqueue: nvme-reset-wq nvme_reset_work [ 2.386022] pstate: 60c00009 (nZCv daif +PAN +UAO) [ 2.386453] pc : __dma_clear_pte+0x0/0xc [ 2.386804] lr : apply_to_page_range+0x1bc/0x274 [ 2.519225] [ 2.519366] Call trace: [ 2.519593] __dma_clear_pte+0x0/0xc [ 2.519908] __dma_alloc+0x240/0x3f0 [ 2.520224] nvme_reset_work+0xaf4/0xf14 [ 2.520575] process_one_work+0x26c/0x438 [ 2.520935] worker_thread+0x260/0x4a8 [ 2.521272] kthread+0x13c/0x14c [ 2.521564] ret_from_fork+0x10/0x18 Signed-off-by: Tao Huang Change-Id: Ifb10b05af6b9778990cad23e3d45cc440bbecb2f --- arch/arm64/mm/dma-mapping.c | 78 +++++-------------------------------- 1 file changed, 10 insertions(+), 68 deletions(-) diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index f309ad38fa94..3edcbd008507 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -45,9 +45,7 @@ static int swiotlb __ro_after_init; static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot, bool coherent) { - if (attrs & DMA_ATTR_STRONGLY_ORDERED) - return pgprot_noncached(prot); - else if (!coherent || (attrs & DMA_ATTR_WRITE_COMBINE)) + if (!coherent || (attrs & DMA_ATTR_WRITE_COMBINE)) return pgprot_writecombine(prot); return prot; } @@ -66,7 +64,6 @@ static bool is_dma_coherent(struct device *dev, unsigned long attrs) } static struct gen_pool *atomic_pool __ro_after_init; -#define NO_KERNEL_MAPPING_DUMMY 0x2222 #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K static size_t atomic_pool_size __initdata = DEFAULT_DMA_COHERENT_POOL_SIZE; @@ -114,43 +111,6 @@ static int __free_from_pool(void *start, size_t size) return 1; } -static int __dma_update_pte(pte_t *pte, pgtable_t token, unsigned long addr, - void *data) -{ - struct page *page = virt_to_page(addr); - pgprot_t prot = *(pgprot_t *)data; - - set_pte(pte, mk_pte(page, prot)); - return 0; -} - -static int __dma_clear_pte(pte_t *pte, pgtable_t token, unsigned long addr, - void *data) -{ - pte_clear(&init_mm, addr, pte); - return 0; -} - -static void __dma_remap(struct page *page, size_t size, pgprot_t prot, - bool no_kernel_map) -{ - unsigned long start = (unsigned long) page_address(page); - unsigned long end = start + size; - int (*func)(pte_t *pte, pgtable_t token, unsigned long addr, - void *data); - - if (no_kernel_map) - func = __dma_clear_pte; - else - func = __dma_update_pte; - - apply_to_page_range(&init_mm, start, size, func, &prot); - /* ensure prot is applied before returning */ - mb(); - flush_tlb_kernel_range(start, end); -} - - static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs) @@ -181,31 +141,19 @@ static void *__dma_alloc(struct device *dev, size_t size, if (coherent) return ptr; + /* remove any dirty cache lines on the kernel alias */ __dma_flush_area(ptr, size); - if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) { - coherent_ptr = (void *)NO_KERNEL_MAPPING_DUMMY; - __dma_remap(virt_to_page(ptr), size, __pgprot(0), true); - } else { - if ((attrs & DMA_ATTR_STRONGLY_ORDERED)) - __dma_remap(virt_to_page(ptr), size, __pgprot(0), true); + /* create a coherent mapping */ + page = virt_to_page(ptr); + coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP, + prot, __builtin_return_address(0)); + if (!coherent_ptr) + goto no_map; - /* create a coherent mapping */ - page = virt_to_page(ptr); - coherent_ptr = dma_common_contiguous_remap( - page, size, VM_USERMAP, prot, - __builtin_return_address(0)); - if (!coherent_ptr) - goto no_map; - } return coherent_ptr; no_map: - if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) || - (attrs & DMA_ATTR_STRONGLY_ORDERED)) - __dma_remap(phys_to_page(dma_to_phys(dev, *dma_handle)), - size, PAGE_KERNEL, false); - swiotlb_free(dev, size, ptr, *dma_handle, attrs); no_mem: return NULL; @@ -219,17 +167,11 @@ static void __dma_free(struct device *dev, size_t size, size = PAGE_ALIGN(size); - if (!is_dma_coherent(dev, attrs)) { + if (!is_device_dma_coherent(dev)) { if (__free_from_pool(vaddr, size)) return; - if (!(attrs & DMA_ATTR_NO_KERNEL_MAPPING)) - vunmap(vaddr); + vunmap(vaddr); } - if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) || - (attrs & DMA_ATTR_STRONGLY_ORDERED)) - __dma_remap(phys_to_page(dma_to_phys(dev, dma_handle)), - size, PAGE_KERNEL, false); - swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs); }