linux-stable/arch/csky/mm/dma-mapping.c
Linus Torvalds 80b29b6b8c csky-for-linus-5.4-rc1: arch/csky patches for 5.4-rc1
This round of csky subsystem just some fixups.
 
 Fixup:
  - Fixup mb() synchronization problem
  - Fixup dma_alloc_coherent with PAGE_SO attribute
  - Fixup cache_op failed when cross memory ZONEs
  - Optimize arch_sync_dma_for_cpu/device with dma_inv_range
  - Fixup ioremap function losing
  - Fixup arch_get_unmapped_area() implementation
  - Fixup defer cache flush for 610
  - Support kernel non-aligned access
  - Fixup 610 vipt cache flush mechanism
  - Fixup add zero_fp fixup perf backtrace panic
  - Move static keyword to the front of declaration
  - Fixup csky_pmu.max_period assignment
  - Use generic free_initrd_mem()
  - entry: Remove unneeded need_resched() loop
 
 CI-Tested: https://gitlab.com/c-sky/buildroot/pipelines/77689888
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEE2KAv+isbWR/viAKHAXH1GYaIxXsFAl2Rfc0SHHJlbl9ndW9A
 Yy1za3kuY29tAAoJEAFx9RmGiMV7eEUQAIuuO1ym/o7zMWZsIRbISJYi6xuq752W
 RVhnPv957ktFYlqrtelDuZwkCPnK03YDTv8lPzcIhes+xYtuspN6NMum7SUWPt4c
 IbfQe4GmMwPGNrJ76NO9YcWQig8flT75wWE2CzOjhGpBfEkEHmtbOvOiZujcq4yN
 vhj8TKF9CjOSaDJNCOXinC6DeGoftRYTSRq6NMPfFfHIWqFcZIyb1Fz8tE/vFP4Y
 qEoG/ys/eu114DIZVnxr5ihmrJ4gjxmlXlnYA8WMRnRt6/oHEmmbtHLTT2eHbI2T
 u4TCssqrLoNADV7g7zyAyBnrgf4dXnJivGjc2NzVLAkgNbEJn+oGNYn+kdiRGd5X
 1CNVbzbZN0gHwLayDjJ4BWNxtpxxqmOjlDffjLVRW7dleTdfHvcxJwfhlvbQOPuq
 nMj4t1qJswn44f/bsj+F13hgXV0tWctYui/HS78xscE7t4yMNduf3JAm7TIxT0XN
 ej3102ffm4ycKZtfdwKwcACmMBJc+2QvGYmQo2L9pVLYIQe3QUWYs881V50PJXxV
 jdz4kmhpfKLie+yxmsdN1/8nTlcHF5wDiYwW9UColzfz1fCRkoPRx5tu/YI9zLoi
 K41CFEv4Z+aVzcp4HZNmOvVhGWgdmuwICMdY16wawhN6SAkvKJBFaP4g24h0J95M
 QyAPQl/VUMED
 =FLYg
 -----END PGP SIGNATURE-----

Merge tag 'csky-for-linus-5.4-rc1' of git://github.com/c-sky/csky-linux

Pull csky updates from Guo Ren:
 "This round of csky subsystem just some fixups:

   - Fix mb() synchronization problem

   - Fix dma_alloc_coherent with PAGE_SO attribute

   - Fix cache_op failed when cross memory ZONEs

   - Optimize arch_sync_dma_for_cpu/device with dma_inv_range

   - Fix ioremap function losing

   - Fix arch_get_unmapped_area() implementation

   - Fix defer cache flush for 610

   - Support kernel non-aligned access

   - Fix 610 vipt cache flush mechanism

   - Fix add zero_fp fixup perf backtrace panic

   - Move static keyword to the front of declaration

   - Fix csky_pmu.max_period assignment

   - Use generic free_initrd_mem()

   - entry: Remove unneeded need_resched() loop"

* tag 'csky-for-linus-5.4-rc1' of git://github.com/c-sky/csky-linux:
  csky: Move static keyword to the front of declaration
  csky: entry: Remove unneeded need_resched() loop
  csky: Fixup csky_pmu.max_period assignment
  csky: Fixup add zero_fp fixup perf backtrace panic
  csky: Use generic free_initrd_mem()
  csky: Fixup 610 vipt cache flush mechanism
  csky: Support kernel non-aligned access
  csky: Fixup defer cache flush for 610
  csky: Fixup arch_get_unmapped_area() implementation
  csky: Fixup ioremap function losing
  csky: Optimize arch_sync_dma_for_cpu/device with dma_inv_range
  csky/dma: Fixup cache_op failed when cross memory ZONEs
  csky: Fixup dma_alloc_coherent with PAGE_SO attribute
  csky: Fixup mb() synchronization problem
2019-09-30 10:16:17 -07:00

90 lines
2 KiB
C

// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
#include <linux/cache.h>
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
#include <linux/dma-noncoherent.h>
#include <linux/genalloc.h>
#include <linux/highmem.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/types.h>
#include <linux/version.h>
#include <asm/cache.h>
static inline void cache_op(phys_addr_t paddr, size_t size,
void (*fn)(unsigned long start, unsigned long end))
{
struct page *page = phys_to_page(paddr);
void *start = __va(page_to_phys(page));
unsigned long offset = offset_in_page(paddr);
size_t left = size;
do {
size_t len = left;
if (offset + len > PAGE_SIZE)
len = PAGE_SIZE - offset;
if (PageHighMem(page)) {
start = kmap_atomic(page);
fn((unsigned long)start + offset,
(unsigned long)start + offset + len);
kunmap_atomic(start);
} else {
fn((unsigned long)start + offset,
(unsigned long)start + offset + len);
}
offset = 0;
page++;
start += PAGE_SIZE;
left -= len;
} while (left);
}
static void dma_wbinv_set_zero_range(unsigned long start, unsigned long end)
{
memset((void *)start, 0, end - start);
dma_wbinv_range(start, end);
}
void arch_dma_prep_coherent(struct page *page, size_t size)
{
cache_op(page_to_phys(page), size, dma_wbinv_set_zero_range);
}
void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
size_t size, enum dma_data_direction dir)
{
switch (dir) {
case DMA_TO_DEVICE:
cache_op(paddr, size, dma_wb_range);
break;
case DMA_FROM_DEVICE:
case DMA_BIDIRECTIONAL:
cache_op(paddr, size, dma_wbinv_range);
break;
default:
BUG();
}
}
void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
size_t size, enum dma_data_direction dir)
{
switch (dir) {
case DMA_TO_DEVICE:
return;
case DMA_FROM_DEVICE:
case DMA_BIDIRECTIONAL:
cache_op(paddr, size, dma_inv_range);
break;
default:
BUG();
}
}