Merge tag 'csky-for-linus-5.4-rc1' of git://github.com/c-sky/csky-linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 30 Sep 2019 17:16:17 +0000 (10:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 30 Sep 2019 17:16:17 +0000 (10:16 -0700)
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

1  2 
arch/csky/include/asm/pgtable.h
arch/csky/mm/dma-mapping.c

@@@ -258,6 -258,16 +258,16 @@@ static inline pgprot_t pgprot_noncached
  {
        unsigned long prot = pgprot_val(_prot);
  
+       prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED | _PAGE_SO;
+       return __pgprot(prot);
+ }
+ #define pgprot_writecombine pgprot_writecombine
+ static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
+ {
+       unsigned long prot = pgprot_val(_prot);
        prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
  
        return __pgprot(prot);
@@@ -296,6 -306,11 +306,6 @@@ void update_mmu_cache(struct vm_area_st
  /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
  #define kern_addr_valid(addr) (1)
  
 -/*
 - * No page table caches to initialise
 - */
 -#define pgtable_cache_init()  do {} while (0)
 -
  #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
        remap_pfn_range(vma, vaddr, pfn, size, prot)
  
  #include <linux/version.h>
  #include <asm/cache.h>
  
- void arch_dma_prep_coherent(struct page *page, size_t size)
 -static int __init atomic_pool_init(void)
--{
-       if (PageHighMem(page)) {
-               unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-               do {
-                       void *ptr = kmap_atomic(page);
-                       size_t _size = (size < PAGE_SIZE) ? size : PAGE_SIZE;
-                       memset(ptr, 0, _size);
-                       dma_wbinv_range((unsigned long)ptr,
-                                       (unsigned long)ptr + _size);
-                       kunmap_atomic(ptr);
-                       page++;
-                       size -= PAGE_SIZE;
-                       count--;
-               } while (count);
-       } else {
-               void *ptr = page_address(page);
-               memset(ptr, 0, size);
-               dma_wbinv_range((unsigned long)ptr, (unsigned long)ptr + size);
-       }
 -      return dma_atomic_pool_init(GFP_KERNEL, pgprot_noncached(PAGE_KERNEL));
--}
 -postcore_initcall(atomic_pool_init);
--
  static inline void cache_op(phys_addr_t paddr, size_t size,
                            void (*fn)(unsigned long start, unsigned long end))
  {
-       struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
-       unsigned int offset = paddr & ~PAGE_MASK;
-       size_t left = size;
-       unsigned long start;
+       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)) {
-                       void *addr;
+                       start = kmap_atomic(page);
  
-                       if (offset + len > PAGE_SIZE) {
-                               if (offset >= PAGE_SIZE) {
-                                       page += offset >> PAGE_SHIFT;
-                                       offset &= ~PAGE_MASK;
-                               }
-                               len = PAGE_SIZE - offset;
-                       }
+                       fn((unsigned long)start + offset,
+                                       (unsigned long)start + offset + len);
  
-                       addr = kmap_atomic(page);
-                       start = (unsigned long)(addr + offset);
-                       fn(start, start + len);
-                       kunmap_atomic(addr);
+                       kunmap_atomic(start);
                } else {
-                       start = (unsigned long)phys_to_virt(paddr);
-                       fn(start, start + size);
+                       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)
  {
@@@ -98,11 -85,10 +79,10 @@@ void arch_sync_dma_for_cpu(struct devic
  {
        switch (dir) {
        case DMA_TO_DEVICE:
-               cache_op(paddr, size, dma_wb_range);
-               break;
+               return;
        case DMA_FROM_DEVICE:
        case DMA_BIDIRECTIONAL:
-               cache_op(paddr, size, dma_wbinv_range);
+               cache_op(paddr, size, dma_inv_range);
                break;
        default:
                BUG();