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
Unified · Split
| @@ -5,8 +5,10 @@ · 4 unmodified lines | |||
| 5 | #include <linux/uaccess.h> | 5 | #include <linux/uaccess.h> |
| 6 | #include <linux/ptrace.h> | 6 | #include <linux/ptrace.h> |
| 7 | 7 | ||
| 8 | static int align_enable = 1; | 8 | static int align_kern_enable = 1; |
| 9 | static int align_count; | 9 | static int align_usr_enable = 1; |
| 10 | static int align_kern_count = 0; | ||
| 11 | static int align_usr_count = 0; | ||
| 10 | 12 | ||
| 11 | static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx) | 13 | static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx) |
| 12 | { | 14 | { |
| @@ -32,9 +34,6 @@ static int ldb_asm(uint32_t addr, uint32_t *valp) · 19 unmodified lines | |||
| 32 | uint32_t val; | 34 | uint32_t val; |
| 33 | int err; | 35 | int err; |
| 34 | 36 | ||
| 35 | if (!access_ok((void *)addr, 1)) | ||
| 36 | return 1; | ||
| 37 | |||
| 38 | asm volatile ( | 37 | asm volatile ( |
| 39 | "movi %0, 0\n" | 38 | "movi %0, 0\n" |
| 40 | "1:\n" | 39 | "1:\n" |
| @@ -67,9 +66,6 @@ static int stb_asm(uint32_t addr, uint32_t val) · 26 unmodified lines | |||
| 67 | { | 66 | { |
| 68 | int err; | 67 | int err; |
| 69 | 68 | ||
| 70 | if (!access_ok((void *)addr, 1)) | ||
| 71 | return 1; | ||
| 72 | |||
| 73 | asm volatile ( | 69 | asm volatile ( |
| 74 | "movi %0, 0\n" | 70 | "movi %0, 0\n" |
| 75 | "1:\n" | 71 | "1:\n" |
| @@ -203,8 +199,6 @@ static int stw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr) · 127 unmodified lines | |||
| 203 | if (stb_asm(addr, byte3)) | 199 | if (stb_asm(addr, byte3)) |
| 204 | return 1; | 200 | return 1; |
| 205 | 201 | ||
| 206 | align_count++; | ||
| 207 | |||
| 208 | return 0; | 202 | return 0; |
| 209 | } | 203 | } |
| 210 | 204 | ||
| @@ -226,7 +220,14 @@ void csky_alignment(struct pt_regs *regs) · 15 unmodified lines | |||
| 226 | uint32_t addr = 0; | 220 | uint32_t addr = 0; |
| 227 | 221 | ||
| 228 | if (!user_mode(regs)) | 222 | if (!user_mode(regs)) |
| 223 | goto kernel_area; | ||
| 224 | |||
| 225 | if (!align_usr_enable) { | ||
| 226 | pr_err("%s user disabled.\n", __func__); | ||
| 229 | goto bad_area; | 227 | goto bad_area; |
| 228 | } | ||
| 229 | |||
| 230 | align_usr_count++; | ||
| 230 | 231 | ||
| 231 | ret = get_user(tmp, (uint16_t *)instruction_pointer(regs)); | 232 | ret = get_user(tmp, (uint16_t *)instruction_pointer(regs)); |
| 232 | if (ret) { | 233 | if (ret) { |
| @@ -234,6 +235,19 @@ void csky_alignment(struct pt_regs *regs) · 1 unmodified line | |||
| 234 | goto bad_area; | 235 | goto bad_area; |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 238 | goto good_area; | ||
| 239 | |||
| 240 | kernel_area: | ||
| 241 | if (!align_kern_enable) { | ||
| 242 | pr_err("%s kernel disabled.\n", __func__); | ||
| 243 | goto bad_area; | ||
| 244 | } | ||
| 245 | |||
| 246 | align_kern_count++; | ||
| 247 | |||
| 248 | tmp = *(uint16_t *)instruction_pointer(regs); | ||
| 249 | |||
| 250 | good_area: | ||
| 237 | opcode = (uint32_t)tmp; | 251 | opcode = (uint32_t)tmp; |
| 238 | 252 | ||
| 239 | rx = opcode & 0xf; | 253 | rx = opcode & 0xf; |
| @@ -286,18 +300,32 @@ bad_area: · 46 unmodified lines | |||
| 286 | force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr); | 300 | force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr); |
| 287 | } | 301 | } |
| 288 | 302 | ||
| 289 | static struct ctl_table alignment_tbl[4] = { | 303 | static struct ctl_table alignment_tbl[5] = { |
| 304 | { | ||
| 305 | .procname = "kernel_enable", | ||
| 306 | .data = &align_kern_enable, | ||
| 307 | .maxlen = sizeof(align_kern_enable), | ||
| 308 | .mode = 0666, | ||
| 309 | .proc_handler = &proc_dointvec | ||
| 310 | }, | ||
| 311 | { | ||
| 312 | .procname = "user_enable", | ||
| 313 | .data = &align_usr_enable, | ||
| 314 | .maxlen = sizeof(align_usr_enable), | ||
| 315 | .mode = 0666, | ||
| 316 | .proc_handler = &proc_dointvec | ||
| 317 | }, | ||
| 290 | { | 318 | { |
| 291 | .procname = "enable", | 319 | .procname = "kernel_count", |
| 292 | .data = &align_enable, | 320 | .data = &align_kern_count, |
| 293 | .maxlen = sizeof(align_enable), | 321 | .maxlen = sizeof(align_kern_count), |
| 294 | .mode = 0666, | 322 | .mode = 0666, |
| 295 | .proc_handler = &proc_dointvec | 323 | .proc_handler = &proc_dointvec |
| 296 | }, | 324 | }, |
| 297 | { | 325 | { |
| 298 | .procname = "count", | 326 | .procname = "user_count", |
| 299 | .data = &align_count, | 327 | .data = &align_usr_count, |
| 300 | .maxlen = sizeof(align_count), | 328 | .maxlen = sizeof(align_usr_count), |
| 301 | .mode = 0666, | 329 | .mode = 0666, |
| 302 | .proc_handler = &proc_dointvec | 330 | .proc_handler = &proc_dointvec |
| 303 | }, | 331 | }, |
| @@ -11,42 +11,66 @@ · 10 unmodified lines | |||
| 11 | #include <asm/cacheflush.h> | 11 | #include <asm/cacheflush.h> |
| 12 | #include <asm/cachectl.h> | 12 | #include <asm/cachectl.h> |
| 13 | 13 | ||
| 14 | #define PG_dcache_clean PG_arch_1 | ||
| 15 | |||
| 14 | void flush_dcache_page(struct page *page) | 16 | void flush_dcache_page(struct page *page) |
| 15 | { | 17 | { |
| 16 | struct address_space *mapping = page_mapping(page); | 18 | struct address_space *mapping; |
| 17 | unsigned long addr; | ||
| 18 | 19 | ||
| 19 | if (mapping && !mapping_mapped(mapping)) { | 20 | if (page == ZERO_PAGE(0)) |
| 20 | set_bit(PG_arch_1, &(page)->flags); | ||
| 21 | return; | 21 | return; |
| 22 | } | ||
| 23 | 22 | ||
| 24 | /* | 23 | mapping = page_mapping_file(page); |
| 25 | * We could delay the flush for the !page_mapping case too. But that | 24 | |
| 26 | * case is for exec env/arg pages and those are %99 certainly going to | 25 | if (mapping && !page_mapcount(page)) |
| 27 | * get faulted into the tlb (and thus flushed) anyways. | 26 | clear_bit(PG_dcache_clean, &page->flags); |
| 28 | */ | 27 | else { |
| 29 | addr = (unsigned long) page_address(page); | 28 | dcache_wbinv_all(); |
| 30 | dcache_wb_range(addr, addr + PAGE_SIZE); | 29 | if (mapping) |
| 30 | icache_inv_all(); | ||
| 31 | set_bit(PG_dcache_clean, &page->flags); | ||
| 32 | } | ||
| 31 | } | 33 | } |
| 34 | EXPORT_SYMBOL(flush_dcache_page); | ||
| 32 | 35 | ||
| 33 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, | 36 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, |
| 34 | pte_t *pte) | 37 | pte_t *ptep) |
| 35 | { | 38 | { |
| 36 | unsigned long addr; | 39 | unsigned long pfn = pte_pfn(*ptep); |
| 37 | struct page *page; | 40 | struct page *page; |
| 38 | unsigned long pfn; | ||
| 39 | 41 | ||
| 40 | pfn = pte_pfn(*pte); | 42 | if (!pfn_valid(pfn)) |
| 41 | if (unlikely(!pfn_valid(pfn))) | ||
| 42 | return; | 43 | return; |
| 43 | 44 | ||
| 44 | page = pfn_to_page(pfn); | 45 | page = pfn_to_page(pfn); |
| 45 | addr = (unsigned long) page_address(page); | 46 | if (page == ZERO_PAGE(0)) |
| 47 | return; | ||
| 48 | |||
| 49 | if (!test_and_set_bit(PG_dcache_clean, &page->flags)) | ||
| 50 | dcache_wbinv_all(); | ||
| 46 | 51 | ||
| 47 | if (vma->vm_flags & VM_EXEC || | 52 | if (page_mapping_file(page)) { |
| 48 | pages_do_alias(addr, address & PAGE_MASK)) | 53 | if (vma->vm_flags & VM_EXEC) |
| 49 | cache_wbinv_all(); | 54 | icache_inv_all(); |
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | void flush_kernel_dcache_page(struct page *page) | ||
| 59 | { | ||
| 60 | struct address_space *mapping; | ||
| 61 | |||
| 62 | mapping = page_mapping_file(page); | ||
| 63 | |||
| 64 | if (!mapping || mapping_mapped(mapping)) | ||
| 65 | dcache_wbinv_all(); | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL(flush_kernel_dcache_page); | ||
| 68 | |||
| 69 | void flush_cache_range(struct vm_area_struct *vma, unsigned long start, | ||
| 70 | unsigned long end) | ||
| 71 | { | ||
| 72 | dcache_wbinv_all(); | ||
| 50 | 73 | ||
| 51 | clear_bit(PG_arch_1, &(page)->flags); | 74 | if (vma->vm_flags & VM_EXEC) |
| 75 | icache_inv_all(); | ||
| 52 | } | 76 | } |
| @@ -4,46 +4,63 @@ · 3 unmodified lines | |||
| 4 | #ifndef __ABI_CSKY_CACHEFLUSH_H | 4 | #ifndef __ABI_CSKY_CACHEFLUSH_H |
| 5 | #define __ABI_CSKY_CACHEFLUSH_H | 5 | #define __ABI_CSKY_CACHEFLUSH_H |
| 6 | 6 | ||
| 7 | #include <linux/compiler.h> | 7 | #include <linux/mm.h> |
| 8 | #include <asm/string.h> | 8 | #include <asm/string.h> |
| 9 | #include <asm/cache.h> | 9 | #include <asm/cache.h> |
| 10 | 10 | ||
| 11 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | 11 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 |
| 12 | extern void flush_dcache_page(struct page *); | 12 | extern void flush_dcache_page(struct page *); |
| 13 | 13 | ||
| 14 | #define flush_cache_mm(mm) cache_wbinv_all() | 14 | #define flush_cache_mm(mm) dcache_wbinv_all() |
| 15 | #define flush_cache_page(vma, page, pfn) cache_wbinv_all() | 15 | #define flush_cache_page(vma, page, pfn) cache_wbinv_all() |
| 16 | #define flush_cache_dup_mm(mm) cache_wbinv_all() | 16 | #define flush_cache_dup_mm(mm) cache_wbinv_all() |
| 17 | 17 | ||
| 18 | #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE | ||
| 19 | extern void flush_kernel_dcache_page(struct page *); | ||
| 20 | |||
| 21 | #define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages) | ||
| 22 | #define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages) | ||
| 23 | |||
| 24 | static inline void flush_kernel_vmap_range(void *addr, int size) | ||
| 25 | { | ||
| 26 | dcache_wbinv_all(); | ||
| 27 | } | ||
| 28 | static inline void invalidate_kernel_vmap_range(void *addr, int size) | ||
| 29 | { | ||
| 30 | dcache_wbinv_all(); | ||
| 31 | } | ||
| 32 | |||
| 33 | #define ARCH_HAS_FLUSH_ANON_PAGE | ||
| 34 | static inline void flush_anon_page(struct vm_area_struct *vma, | ||
| 35 | struct page *page, unsigned long vmaddr) | ||
| 36 | { | ||
| 37 | if (PageAnon(page)) | ||
| 38 | cache_wbinv_all(); | ||
| 39 | } | ||
| 40 | |||
| 18 | /* | 41 | /* |
| 19 | * if (current_mm != vma->mm) cache_wbinv_range(start, end) will be broken. | 42 | * if (current_mm != vma->mm) cache_wbinv_range(start, end) will be broken. |
| 20 | * Use cache_wbinv_all() here and need to be improved in future. | 43 | * Use cache_wbinv_all() here and need to be improved in future. |
| 21 | */ | 44 | */ |
| 22 | #define flush_cache_range(vma, start, end) cache_wbinv_all() | 45 | extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); |
| 23 | #define flush_cache_vmap(start, end) cache_wbinv_range(start, end) | 46 | #define flush_cache_vmap(start, end) cache_wbinv_all() |
| 24 | #define flush_cache_vunmap(start, end) cache_wbinv_range(start, end) | 47 | #define flush_cache_vunmap(start, end) cache_wbinv_all() |
| 25 | 48 | ||
| 26 | #define flush_icache_page(vma, page) cache_wbinv_all() | 49 | #define flush_icache_page(vma, page) do {} while (0); |
| 27 | #define flush_icache_range(start, end) cache_wbinv_range(start, end) | 50 | #define flush_icache_range(start, end) cache_wbinv_range(start, end) |
| 28 | 51 | ||
| 29 | #define flush_icache_user_range(vma, pg, adr, len) \ | 52 | #define flush_icache_user_range(vma,page,addr,len) \ |
| 30 | cache_wbinv_range(adr, adr + len) | 53 | flush_dcache_page(page) |
| 31 | 54 | ||
| 32 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | 55 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ |
| 33 | do { \ | 56 | do { \ |
| 34 | cache_wbinv_all(); \ | ||
| 35 | memcpy(dst, src, len); \ | 57 | memcpy(dst, src, len); \ |
| 36 | cache_wbinv_all(); \ | ||
| 37 | } while (0) | 58 | } while (0) |
| 38 | 59 | ||
| 39 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 60 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ |
| 40 | do { \ | 61 | do { \ |
| 41 | cache_wbinv_all(); \ | ||
| 42 | memcpy(dst, src, len); \ | 62 | memcpy(dst, src, len); \ |
| 43 | cache_wbinv_all(); \ | 63 | cache_wbinv_all(); \ |
| 44 | } while (0) | 64 | } while (0) |
| 45 | 65 | ||
| 46 | #define flush_dcache_mmap_lock(mapping) do {} while (0) | ||
| 47 | #define flush_dcache_mmap_unlock(mapping) do {} while (0) | ||
| 48 | |||
| 49 | #endif /* __ABI_CSKY_CACHEFLUSH_H */ | 66 | #endif /* __ABI_CSKY_CACHEFLUSH_H */ |
| @@ -1,13 +1,14 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. | 2 | // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. |
| 3 | 3 | ||
| 4 | extern unsigned long shm_align_mask; | 4 | #include <asm/shmparam.h> |
| 5 | |||
| 5 | extern void flush_dcache_page(struct page *page); | 6 | extern void flush_dcache_page(struct page *page); |
| 6 | 7 | ||
| 7 | static inline unsigned long pages_do_alias(unsigned long addr1, | 8 | static inline unsigned long pages_do_alias(unsigned long addr1, |
| 8 | unsigned long addr2) | 9 | unsigned long addr2) |
| 9 | { | 10 | { |
| 10 | return (addr1 ^ addr2) & shm_align_mask; | 11 | return (addr1 ^ addr2) & (SHMLBA-1); |
| 11 | } | 12 | } |
| 12 | 13 | ||
| 13 | static inline void clear_user_page(void *addr, unsigned long vaddr, | 14 | static inline void clear_user_page(void *addr, unsigned long vaddr, |
| @@ -9,58 +9,63 @@ · 8 unmodified lines | |||
| 9 | #include <linux/random.h> | 9 | #include <linux/random.h> |
| 10 | #include <linux/io.h> | 10 | #include <linux/io.h> |
| 11 | 11 | ||
| 12 | unsigned long shm_align_mask = (0x4000 >> 1) - 1; /* Sane caches */ | 12 | #define COLOUR_ALIGN(addr,pgoff) \ |
| 13 | ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \ | ||
| 14 | (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1))) | ||
| 13 | 15 | ||
| 14 | #define COLOUR_ALIGN(addr, pgoff) \ | 16 | /* |
| 15 | ((((addr) + shm_align_mask) & ~shm_align_mask) + \ | 17 | * We need to ensure that shared mappings are correctly aligned to |
| 16 | (((pgoff) << PAGE_SHIFT) & shm_align_mask)) | 18 | * avoid aliasing issues with VIPT caches. We need to ensure that |
| 17 | 19 | * a specific page of an object is always mapped at a multiple of | |
| 18 | unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, | 20 | * SHMLBA bytes. |
| 21 | * | ||
| 22 | * We unconditionally provide this function for all cases. | ||
| 23 | */ | ||
| 24 | unsigned long | ||
| 25 | arch_get_unmapped_area(struct file *filp, unsigned long addr, | ||
| 19 | unsigned long len, unsigned long pgoff, unsigned long flags) | 26 | unsigned long len, unsigned long pgoff, unsigned long flags) |
| 20 | { | 27 | { |
| 21 | struct vm_area_struct *vmm; | 28 | struct mm_struct *mm = current->mm; |
| 22 | int do_color_align; | 29 | struct vm_area_struct *vma; |
| 30 | int do_align = 0; | ||
| 31 | struct vm_unmapped_area_info info; | ||
| 32 | |||
| 33 | /* | ||
| 34 | * We only need to do colour alignment if either the I or D | ||
| 35 | * caches alias. | ||
| 36 | */ | ||
| 37 | do_align = filp || (flags & MAP_SHARED); | ||
| 23 | 38 | ||
| 39 | /* | ||
| 40 | * We enforce the MAP_FIXED case. | ||
| 41 | */ | ||
| 24 | if (flags & MAP_FIXED) { | 42 | if (flags & MAP_FIXED) { |
| 25 | /* | 43 | if (flags & MAP_SHARED && |
| 26 | * We do not accept a shared mapping if it would violate | 44 | (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1)) |
| 27 | * cache aliasing constraints. | ||
| 28 | */ | ||
| 29 | if ((flags & MAP_SHARED) && | ||
| 30 | ((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask)) | ||
| 31 | return -EINVAL; | 45 | return -EINVAL; |
| 32 | return addr; | 46 | return addr; |
| 33 | } | 47 | } |
| 34 | 48 | ||
| 35 | if (len > TASK_SIZE) | 49 | if (len > TASK_SIZE) |
| 36 | return -ENOMEM; | 50 | return -ENOMEM; |
| 37 | do_color_align = 0; | 51 | |
| 38 | if (filp || (flags & MAP_SHARED)) | ||
| 39 | do_color_align = 1; | ||
| 40 | if (addr) { | 52 | if (addr) { |
| 41 | if (do_color_align) | 53 | if (do_align) |
| 42 | addr = COLOUR_ALIGN(addr, pgoff); | 54 | addr = COLOUR_ALIGN(addr, pgoff); |
| 43 | else | 55 | else |
| 44 | addr = PAGE_ALIGN(addr); | 56 | addr = PAGE_ALIGN(addr); |
| 45 | vmm = find_vma(current->mm, addr); | 57 | |
| 58 | vma = find_vma(mm, addr); | ||
| 46 | if (TASK_SIZE - len >= addr && | 59 | if (TASK_SIZE - len >= addr && |
| 47 | (!vmm || addr + len <= vmm->vm_start)) | 60 | (!vma || addr + len <= vm_start_gap(vma))) |
| 48 | return addr; | 61 | return addr; |
| 49 | } | 62 | } |
| 50 | addr = TASK_UNMAPPED_BASE; | ||
| 51 | if (do_color_align) | ||
| 52 | addr = COLOUR_ALIGN(addr, pgoff); | ||
| 53 | else | ||
| 54 | addr = PAGE_ALIGN(addr); | ||
| 55 | 63 | ||
| 56 | for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { | 64 | info.flags = 0; |
| 57 | /* At this point: (!vmm || addr < vmm->vm_end). */ | 65 | info.length = len; |
| 58 | if (TASK_SIZE - len < addr) | 66 | info.low_limit = mm->mmap_base; |
| 59 | return -ENOMEM; | 67 | info.high_limit = TASK_SIZE; |
| 60 | if (!vmm || addr + len <= vmm->vm_start) | 68 | info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0; |
| 61 | return addr; | 69 | info.align_offset = pgoff << PAGE_SHIFT; |
| 62 | addr = vmm->vm_end; | 70 | return vm_unmapped_area(&info); |
| 63 | if (do_color_align) | ||
| 64 | addr = COLOUR_ALIGN(addr, pgoff); | ||
| 65 | } | ||
| 66 | } | 71 | } |
| @@ -9,11 +9,12 @@ · 8 unmodified lines | |||
| 9 | #define nop() asm volatile ("nop\n":::"memory") | 9 | #define nop() asm volatile ("nop\n":::"memory") |
| 10 | 10 | ||
| 11 | /* | 11 | /* |
| 12 | * sync: completion barrier | 12 | * sync: completion barrier, all sync.xx instructions |
| 13 | * sync.s: completion barrier and shareable to other cores | 13 | * guarantee the last response recieved by bus transaction |
| 14 | * sync.i: completion barrier with flush cpu pipeline | 14 | * made by ld/st instructions before sync.s |
| 15 | * sync.is: completion barrier with flush cpu pipeline and shareable to | 15 | * sync.s: inherit from sync, but also shareable to other cores |
| 16 | * other cores | 16 | * sync.i: inherit from sync, but also flush cpu pipeline |
| 17 | * sync.is: the same with sync.i + sync.s | ||
| 17 | * | 18 | * |
| 18 | * bar.brwarw: ordering barrier for all load/store instructions before it | 19 | * bar.brwarw: ordering barrier for all load/store instructions before it |
| 19 | * bar.brwarws: ordering barrier for all load/store instructions before it | 20 | * bar.brwarws: ordering barrier for all load/store instructions before it |
| @@ -27,9 +28,7 @@ · 7 unmodified lines | |||
| 27 | */ | 28 | */ |
| 28 | 29 | ||
| 29 | #ifdef CONFIG_CPU_HAS_CACHEV2 | 30 | #ifdef CONFIG_CPU_HAS_CACHEV2 |
| 30 | #define mb() asm volatile ("bar.brwarw\n":::"memory") | 31 | #define mb() asm volatile ("sync.s\n":::"memory") |
| 31 | #define rmb() asm volatile ("bar.brar\n":::"memory") | ||
| 32 | #define wmb() asm volatile ("bar.bwaw\n":::"memory") | ||
| 33 | 32 | ||
| 34 | #ifdef CONFIG_SMP | 33 | #ifdef CONFIG_SMP |
| 35 | #define __smp_mb() asm volatile ("bar.brwarws\n":::"memory") | 34 | #define __smp_mb() asm volatile ("bar.brwarws\n":::"memory") |
| @@ -24,6 +24,7 @@ void cache_wbinv_range(unsigned long start, unsigned long end); · 23 unmodified lines | |||
| 24 | void cache_wbinv_all(void); | 24 | void cache_wbinv_all(void); |
| 25 | 25 | ||
| 26 | void dma_wbinv_range(unsigned long start, unsigned long end); | 26 | void dma_wbinv_range(unsigned long start, unsigned long end); |
| 27 | void dma_inv_range(unsigned long start, unsigned long end); | ||
| 27 | void dma_wb_range(unsigned long start, unsigned long end); | 28 | void dma_wb_range(unsigned long start, unsigned long end); |
| 28 | 29 | ||
| 29 | #endif | 30 | #endif |
| @@ -4,17 +4,10 @@ · 3 unmodified lines | |||
| 4 | #ifndef __ASM_CSKY_IO_H | 4 | #ifndef __ASM_CSKY_IO_H |
| 5 | #define __ASM_CSKY_IO_H | 5 | #define __ASM_CSKY_IO_H |
| 6 | 6 | ||
| 7 | #include <abi/pgtable-bits.h> | 7 | #include <asm/pgtable.h> |
| 8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
| 9 | #include <linux/version.h> | 9 | #include <linux/version.h> |
| 10 | 10 | ||
| 11 | extern void __iomem *ioremap(phys_addr_t offset, size_t size); | ||
| 12 | |||
| 13 | extern void iounmap(void *addr); | ||
| 14 | |||
| 15 | extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr, | ||
| 16 | size_t size, unsigned long flags); | ||
| 17 | |||
| 18 | /* | 11 | /* |
| 19 | * I/O memory access primitives. Reads are ordered relative to any | 12 | * I/O memory access primitives. Reads are ordered relative to any |
| 20 | * following Normal memory access. Writes are ordered relative to any prior | 13 | * following Normal memory access. Writes are ordered relative to any prior |
| @@ -40,9 +33,17 @@ extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr, · 19 unmodified lines | |||
| 40 | #define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); mb(); }) | 33 | #define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); mb(); }) |
| 41 | #endif | 34 | #endif |
| 42 | 35 | ||
| 43 | #define ioremap_nocache(phy, sz) ioremap(phy, sz) | 36 | /* |
| 44 | #define ioremap_wc ioremap_nocache | 37 | * I/O memory mapping functions. |
| 45 | #define ioremap_wt ioremap_nocache | 38 | */ |
| 39 | extern void __iomem *ioremap_cache(phys_addr_t addr, size_t size); | ||
| 40 | extern void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot); | ||
| 41 | extern void iounmap(void *addr); | ||
| 42 | |||
| 43 | #define ioremap(addr, size) __ioremap((addr), (size), pgprot_noncached(PAGE_KERNEL)) | ||
| 44 | #define ioremap_wc(addr, size) __ioremap((addr), (size), pgprot_writecombine(PAGE_KERNEL)) | ||
| 45 | #define ioremap_nocache(addr, size) ioremap((addr), (size)) | ||
| 46 | #define ioremap_cache ioremap_cache | ||
| 46 | 47 | ||
| 47 | #include <asm-generic/io.h> | 48 | #include <asm-generic/io.h> |
| 48 | 49 | ||
| @@ -258,6 +258,16 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot) · 257 unmodified lines | |||
| 258 | { | 258 | { |
| 259 | unsigned long prot = pgprot_val(_prot); | 259 | unsigned long prot = pgprot_val(_prot); |
| 260 | 260 | ||
| 261 | prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED | _PAGE_SO; | ||
| 262 | |||
| 263 | return __pgprot(prot); | ||
| 264 | } | ||
| 265 | |||
| 266 | #define pgprot_writecombine pgprot_writecombine | ||
| 267 | static inline pgprot_t pgprot_writecombine(pgprot_t _prot) | ||
| 268 | { | ||
| 269 | unsigned long prot = pgprot_val(_prot); | ||
| 270 | |||
| 261 | prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED; | 271 | prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED; |
| 262 | 272 | ||
| 263 | return __pgprot(prot); | 273 | return __pgprot(prot); |
| @@ -17,6 +17,12 @@ · 16 unmodified lines | |||
| 17 | #define PTE_INDX_SHIFT 10 | 17 | #define PTE_INDX_SHIFT 10 |
| 18 | #define _PGDIR_SHIFT 22 | 18 | #define _PGDIR_SHIFT 22 |
| 19 | 19 | ||
| 20 | .macro zero_fp | ||
| 21 | #ifdef CONFIG_STACKTRACE | ||
| 22 | movi r8, 0 | ||
| 23 | #endif | ||
| 24 | .endm | ||
| 25 | |||
| 20 | .macro tlbop_begin name, val0, val1, val2 | 26 | .macro tlbop_begin name, val0, val1, val2 |
| 21 | ENTRY(csky_\name) | 27 | ENTRY(csky_\name) |
| 22 | mtcr a3, ss2 | 28 | mtcr a3, ss2 |
| @@ -96,6 +102,7 @@ ENTRY(csky_\name) · 73 unmodified lines | |||
| 96 | SAVE_ALL 0 | 102 | SAVE_ALL 0 |
| 97 | .endm | 103 | .endm |
| 98 | .macro tlbop_end is_write | 104 | .macro tlbop_end is_write |
| 105 | zero_fp | ||
| 99 | RD_MEH a2 | 106 | RD_MEH a2 |
| 100 | psrset ee, ie | 107 | psrset ee, ie |
| 101 | mov a0, sp | 108 | mov a0, sp |
| @@ -120,6 +127,7 @@ tlbop_end 1 · 18 unmodified lines | |||
| 120 | 127 | ||
| 121 | ENTRY(csky_systemcall) | 128 | ENTRY(csky_systemcall) |
| 122 | SAVE_ALL TRAP0_SIZE | 129 | SAVE_ALL TRAP0_SIZE |
| 130 | zero_fp | ||
| 123 | 131 | ||
| 124 | psrset ee, ie | 132 | psrset ee, ie |
| 125 | 133 | ||
| @@ -136,9 +144,9 @@ ENTRY(csky_systemcall) · 10 unmodified lines | |||
| 136 | mov r9, sp | 144 | mov r9, sp |
| 137 | bmaski r10, THREAD_SHIFT | 145 | bmaski r10, THREAD_SHIFT |
| 138 | andn r9, r10 | 146 | andn r9, r10 |
| 139 | ldw r8, (r9, TINFO_FLAGS) | 147 | ldw r12, (r9, TINFO_FLAGS) |
| 140 | ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) | 148 | ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) |
| 141 | cmpnei r8, 0 | 149 | cmpnei r12, 0 |
| 142 | bt csky_syscall_trace | 150 | bt csky_syscall_trace |
| 143 | #if defined(__CSKYABIV2__) | 151 | #if defined(__CSKYABIV2__) |
| 144 | subi sp, 8 | 152 | subi sp, 8 |
| @@ -180,7 +188,7 @@ csky_syscall_trace: · 35 unmodified lines | |||
| 180 | 188 | ||
| 181 | ENTRY(ret_from_kernel_thread) | 189 | ENTRY(ret_from_kernel_thread) |
| 182 | jbsr schedule_tail | 190 | jbsr schedule_tail |
| 183 | mov a0, r8 | 191 | mov a0, r10 |
| 184 | jsr r9 | 192 | jsr r9 |
| 185 | jbsr ret_from_exception | 193 | jbsr ret_from_exception |
| 186 | 194 | ||
| @@ -189,9 +197,9 @@ ENTRY(ret_from_fork) · 2 unmodified lines | |||
| 189 | mov r9, sp | 197 | mov r9, sp |
| 190 | bmaski r10, THREAD_SHIFT | 198 | bmaski r10, THREAD_SHIFT |
| 191 | andn r9, r10 | 199 | andn r9, r10 |
| 192 | ldw r8, (r9, TINFO_FLAGS) | 200 | ldw r12, (r9, TINFO_FLAGS) |
| 193 | ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) | 201 | ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) |
| 194 | cmpnei r8, 0 | 202 | cmpnei r12, 0 |
| 195 | bf ret_from_exception | 203 | bf ret_from_exception |
| 196 | mov a0, sp /* sp = pt_regs pointer */ | 204 | mov a0, sp /* sp = pt_regs pointer */ |
| 197 | jbsr syscall_trace_exit | 205 | jbsr syscall_trace_exit |
| @@ -209,9 +217,9 @@ ret_from_exception: · 11 unmodified lines | |||
| 209 | bmaski r10, THREAD_SHIFT | 217 | bmaski r10, THREAD_SHIFT |
| 210 | andn r9, r10 | 218 | andn r9, r10 |
| 211 | 219 | ||
| 212 | ldw r8, (r9, TINFO_FLAGS) | 220 | ldw r12, (r9, TINFO_FLAGS) |
| 213 | andi r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) | 221 | andi r12, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) |
| 214 | cmpnei r8, 0 | 222 | cmpnei r12, 0 |
| 215 | bt exit_work | 223 | bt exit_work |
| 216 | 1: | 224 | 1: |
| 217 | RESTORE_ALL | 225 | RESTORE_ALL |
| @@ -220,11 +228,11 @@ exit_work: · 2 unmodified lines | |||
| 220 | lrw syscallid, ret_from_exception | 228 | lrw syscallid, ret_from_exception |
| 221 | mov lr, syscallid | 229 | mov lr, syscallid |
| 222 | 230 | ||
| 223 | btsti r8, TIF_NEED_RESCHED | 231 | btsti r12, TIF_NEED_RESCHED |
| 224 | bt work_resched | 232 | bt work_resched |
| 225 | 233 | ||
| 226 | mov a0, sp | 234 | mov a0, sp |
| 227 | mov a1, r8 | 235 | mov a1, r12 |
| 228 | jmpi do_notify_resume | 236 | jmpi do_notify_resume |
| 229 | 237 | ||
| 230 | work_resched: | 238 | work_resched: |
| @@ -232,6 +240,7 @@ work_resched: · 1 unmodified line | |||
| 232 | 240 | ||
| 233 | ENTRY(csky_trap) | 241 | ENTRY(csky_trap) |
| 234 | SAVE_ALL 0 | 242 | SAVE_ALL 0 |
| 243 | zero_fp | ||
| 235 | psrset ee | 244 | psrset ee |
| 236 | mov a0, sp /* Push Stack pointer arg */ | 245 | mov a0, sp /* Push Stack pointer arg */ |
| 237 | jbsr trap_c /* Call C-level trap handler */ | 246 | jbsr trap_c /* Call C-level trap handler */ |
| @@ -265,6 +274,7 @@ ENTRY(csky_get_tls) · 27 unmodified lines | |||
| 265 | 274 | ||
| 266 | ENTRY(csky_irq) | 275 | ENTRY(csky_irq) |
| 267 | SAVE_ALL 0 | 276 | SAVE_ALL 0 |
| 277 | zero_fp | ||
| 268 | psrset ee | 278 | psrset ee |
| 269 | 279 | ||
| 270 | #ifdef CONFIG_PREEMPT | 280 | #ifdef CONFIG_PREEMPT |
| @@ -276,27 +286,23 @@ ENTRY(csky_irq) · 5 unmodified lines | |||
| 276 | * Get task_struct->stack.preempt_count for current, | 286 | * Get task_struct->stack.preempt_count for current, |
| 277 | * and increase 1. | 287 | * and increase 1. |
| 278 | */ | 288 | */ |
| 279 | ldw r8, (r9, TINFO_PREEMPT) | 289 | ldw r12, (r9, TINFO_PREEMPT) |
| 280 | addi r8, 1 | 290 | addi r12, 1 |
| 281 | stw r8, (r9, TINFO_PREEMPT) | 291 | stw r12, (r9, TINFO_PREEMPT) |
| 282 | #endif | 292 | #endif |
| 283 | 293 | ||
| 284 | mov a0, sp | 294 | mov a0, sp |
| 285 | jbsr csky_do_IRQ | 295 | jbsr csky_do_IRQ |
| 286 | 296 | ||
| 287 | #ifdef CONFIG_PREEMPT | 297 | #ifdef CONFIG_PREEMPT |
| 288 | subi r8, 1 | 298 | subi r12, 1 |
| 289 | stw r8, (r9, TINFO_PREEMPT) | 299 | stw r12, (r9, TINFO_PREEMPT) |
| 290 | cmpnei r8, 0 | 300 | cmpnei r12, 0 |
| 291 | bt 2f | 301 | bt 2f |
| 292 | ldw r8, (r9, TINFO_FLAGS) | 302 | ldw r12, (r9, TINFO_FLAGS) |
| 293 | btsti r8, TIF_NEED_RESCHED | 303 | btsti r12, TIF_NEED_RESCHED |
| 294 | bf 2f | 304 | bf 2f |
| 295 | 1: | ||
| 296 | jbsr preempt_schedule_irq /* irq en/disable is done inside */ | 305 | jbsr preempt_schedule_irq /* irq en/disable is done inside */ |
| 297 | ldw r7, (r9, TINFO_FLAGS) /* get new tasks TI_FLAGS */ | ||
| 298 | btsti r7, TIF_NEED_RESCHED | ||
| 299 | bt 1b /* go again */ | ||
| 300 | #endif | 306 | #endif |
| 301 | 2: | 307 | 2: |
| 302 | jmpi ret_from_exception | 308 | jmpi ret_from_exception |
| @@ -1306,7 +1306,7 @@ int csky_pmu_device_probe(struct platform_device *pdev, · 1305 unmodified lines | |||
| 1306 | &csky_pmu.count_width)) { | 1306 | &csky_pmu.count_width)) { |
| 1307 | csky_pmu.count_width = DEFAULT_COUNT_WIDTH; | 1307 | csky_pmu.count_width = DEFAULT_COUNT_WIDTH; |
| 1308 | } | 1308 | } |
| 1309 | csky_pmu.max_period = BIT(csky_pmu.count_width) - 1; | 1309 | csky_pmu.max_period = BIT_ULL(csky_pmu.count_width) - 1; |
| 1310 | 1310 | ||
| 1311 | csky_pmu.plat_device = pdev; | 1311 | csky_pmu.plat_device = pdev; |
| 1312 | 1312 | ||
| @@ -1337,7 +1337,7 @@ int csky_pmu_device_probe(struct platform_device *pdev, · 24 unmodified lines | |||
| 1337 | return ret; | 1337 | return ret; |
| 1338 | } | 1338 | } |
| 1339 | 1339 | ||
| 1340 | const static struct of_device_id csky_pmu_of_device_ids[] = { | 1340 | static const struct of_device_id csky_pmu_of_device_ids[] = { |
| 1341 | {.compatible = "csky,csky-pmu"}, | 1341 | {.compatible = "csky,csky-pmu"}, |
| 1342 | {}, | 1342 | {}, |
| 1343 | }; | 1343 | }; |
| @@ -55,7 +55,7 @@ int copy_thread(unsigned long clone_flags, · 54 unmodified lines | |||
| 55 | if (unlikely(p->flags & PF_KTHREAD)) { | 55 | if (unlikely(p->flags & PF_KTHREAD)) { |
| 56 | memset(childregs, 0, sizeof(struct pt_regs)); | 56 | memset(childregs, 0, sizeof(struct pt_regs)); |
| 57 | childstack->r15 = (unsigned long) ret_from_kernel_thread; | 57 | childstack->r15 = (unsigned long) ret_from_kernel_thread; |
| 58 | childstack->r8 = kthread_arg; | 58 | childstack->r10 = kthread_arg; |
| 59 | childstack->r9 = usp; | 59 | childstack->r9 = usp; |
| 60 | childregs->sr = mfcr("psr"); | 60 | childregs->sr = mfcr("psr"); |
| 61 | } else { | 61 | } else { |
| @@ -120,7 +120,12 @@ void dma_wbinv_range(unsigned long start, unsigned long end) · 119 unmodified lines | |||
| 120 | cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1); | 120 | cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | void dma_inv_range(unsigned long start, unsigned long end) | ||
| 124 | { | ||
| 125 | cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1); | ||
| 126 | } | ||
| 127 | |||
| 123 | void dma_wb_range(unsigned long start, unsigned long end) | 128 | void dma_wb_range(unsigned long start, unsigned long end) |
| 124 | { | 129 | { |
| 125 | cache_op_range(start, end, DATA_CACHE|CACHE_INV, 1); | 130 | cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1); |
| 126 | } | 131 | } |
| @@ -69,11 +69,20 @@ void dma_wbinv_range(unsigned long start, unsigned long end) · 68 unmodified lines | |||
| 69 | sync_is(); | 69 | sync_is(); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | void dma_inv_range(unsigned long start, unsigned long end) | ||
| 73 | { | ||
| 74 | unsigned long i = start & ~(L1_CACHE_BYTES - 1); | ||
| 75 | |||
| 76 | for (; i < end; i += L1_CACHE_BYTES) | ||
| 77 | asm volatile("dcache.iva %0\n"::"r"(i):"memory"); | ||
| 78 | sync_is(); | ||
| 79 | } | ||
| 80 | |||
| 72 | void dma_wb_range(unsigned long start, unsigned long end) | 81 | void dma_wb_range(unsigned long start, unsigned long end) |
| 73 | { | 82 | { |
| 74 | unsigned long i = start & ~(L1_CACHE_BYTES - 1); | 83 | unsigned long i = start & ~(L1_CACHE_BYTES - 1); |
| 75 | 84 | ||
| 76 | for (; i < end; i += L1_CACHE_BYTES) | 85 | for (; i < end; i += L1_CACHE_BYTES) |
| 77 | asm volatile("dcache.civa %0\n"::"r"(i):"memory"); | 86 | asm volatile("dcache.cva %0\n"::"r"(i):"memory"); |
| 78 | sync_is(); | 87 | sync_is(); |
| 79 | } | 88 | } |
| @@ -14,69 +14,50 @@ · 13 unmodified lines | |||
| 14 | #include <linux/version.h> | 14 | #include <linux/version.h> |
| 15 | #include <asm/cache.h> | 15 | #include <asm/cache.h> |
| 16 | 16 | ||
| 17 | void arch_dma_prep_coherent(struct page *page, size_t size) | ||
| 18 | { | ||
| 19 | if (PageHighMem(page)) { | ||
| 20 | unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
| 21 | |||
| 22 | do { | ||
| 23 | void *ptr = kmap_atomic(page); | ||
| 24 | size_t _size = (size < PAGE_SIZE) ? size : PAGE_SIZE; | ||
| 25 | |||
| 26 | memset(ptr, 0, _size); | ||
| 27 | dma_wbinv_range((unsigned long)ptr, | ||
| 28 | (unsigned long)ptr + _size); | ||
| 29 | |||
| 30 | kunmap_atomic(ptr); | ||
| 31 | |||
| 32 | page++; | ||
| 33 | size -= PAGE_SIZE; | ||
| 34 | count--; | ||
| 35 | } while (count); | ||
| 36 | } else { | ||
| 37 | void *ptr = page_address(page); | ||
| 38 | |||
| 39 | memset(ptr, 0, size); | ||
| 40 | dma_wbinv_range((unsigned long)ptr, (unsigned long)ptr + size); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | static inline void cache_op(phys_addr_t paddr, size_t size, | 17 | static inline void cache_op(phys_addr_t paddr, size_t size, |
| 45 | void (*fn)(unsigned long start, unsigned long end)) | 18 | void (*fn)(unsigned long start, unsigned long end)) |
| 46 | { | 19 | { |
| 47 | struct page *page = pfn_to_page(paddr >> PAGE_SHIFT); | 20 | struct page *page = phys_to_page(paddr); |
| 48 | unsigned int offset = paddr & ~PAGE_MASK; | 21 | void *start = __va(page_to_phys(page)); |
| 49 | size_t left = size; | 22 | unsigned long offset = offset_in_page(paddr); |
| 50 | unsigned long start; | 23 | size_t left = size; |
| 51 | 24 | ||
| 52 | do { | 25 | do { |
| 53 | size_t len = left; | 26 | size_t len = left; |
| 54 | 27 | ||
| 28 | if (offset + len > PAGE_SIZE) | ||
| 29 | len = PAGE_SIZE - offset; | ||
| 30 | |||
| 55 | if (PageHighMem(page)) { | 31 | if (PageHighMem(page)) { |
| 56 | void *addr; | 32 | start = kmap_atomic(page); |
| 57 | 33 | ||
| 58 | if (offset + len > PAGE_SIZE) { | 34 | fn((unsigned long)start + offset, |
| 59 | if (offset >= PAGE_SIZE) { | 35 | (unsigned long)start + offset + len); |
| 60 | page += offset >> PAGE_SHIFT; | ||
| 61 | offset &= ~PAGE_MASK; | ||
| 62 | } | ||
| 63 | len = PAGE_SIZE - offset; | ||
| 64 | } | ||
| 65 | 36 | ||
| 66 | addr = kmap_atomic(page); | 37 | kunmap_atomic(start); |
| 67 | start = (unsigned long)(addr + offset); | ||
| 68 | fn(start, start + len); | ||
| 69 | kunmap_atomic(addr); | ||
| 70 | } else { | 38 | } else { |
| 71 | start = (unsigned long)phys_to_virt(paddr); | 39 | fn((unsigned long)start + offset, |
| 72 | fn(start, start + size); | 40 | (unsigned long)start + offset + len); |
| 73 | } | 41 | } |
| 74 | offset = 0; | 42 | offset = 0; |
| 43 | |||
| 75 | page++; | 44 | page++; |
| 45 | start += PAGE_SIZE; | ||
| 76 | left -= len; | 46 | left -= len; |
| 77 | } while (left); | 47 | } while (left); |
| 78 | } | 48 | } |
| 79 | 49 | ||
| 50 | static void dma_wbinv_set_zero_range(unsigned long start, unsigned long end) | ||
| 51 | { | ||
| 52 | memset((void *)start, 0, end - start); | ||
| 53 | dma_wbinv_range(start, end); | ||
| 54 | } | ||
| 55 | |||
| 56 | void arch_dma_prep_coherent(struct page *page, size_t size) | ||
| 57 | { | ||
| 58 | cache_op(page_to_phys(page), size, dma_wbinv_set_zero_range); | ||
| 59 | } | ||
| 60 | |||
| 80 | void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, | 61 | void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr, |
| 81 | size_t size, enum dma_data_direction dir) | 62 | size_t size, enum dma_data_direction dir) |
| 82 | { | 63 | { |
| @@ -98,11 +79,10 @@ void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr, · 15 unmodified lines | |||
| 98 | { | 79 | { |
| 99 | switch (dir) { | 80 | switch (dir) { |
| 100 | case DMA_TO_DEVICE: | 81 | case DMA_TO_DEVICE: |
| 101 | cache_op(paddr, size, dma_wb_range); | 82 | return; |
| 102 | break; | ||
| 103 | case DMA_FROM_DEVICE: | 83 | case DMA_FROM_DEVICE: |
| 104 | case DMA_BIDIRECTIONAL: | 84 | case DMA_BIDIRECTIONAL: |
| 105 | cache_op(paddr, size, dma_wbinv_range); | 85 | cache_op(paddr, size, dma_inv_range); |
| 106 | break; | 86 | break; |
| 107 | default: | 87 | default: |
| 108 | BUG(); | 88 | BUG(); |
| @@ -60,22 +60,6 @@ void __init mem_init(void) · 59 unmodified lines | |||
| 60 | mem_init_print_info(NULL); | 60 | mem_init_print_info(NULL); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 64 | void free_initrd_mem(unsigned long start, unsigned long end) | ||
| 65 | { | ||
| 66 | if (start < end) | ||
| 67 | pr_info("Freeing initrd memory: %ldk freed\n", | ||
| 68 | (end - start) >> 10); | ||
| 69 | |||
| 70 | for (; start < end; start += PAGE_SIZE) { | ||
| 71 | ClearPageReserved(virt_to_page(start)); | ||
| 72 | init_page_count(virt_to_page(start)); | ||
| 73 | free_page(start); | ||
| 74 | totalram_pages_inc(); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | #endif | ||
| 78 | |||
| 79 | extern char __init_begin[], __init_end[]; | 63 | extern char __init_begin[], __init_end[]; |
| 80 | 64 | ||
| 81 | void free_initmem(void) | 65 | void free_initmem(void) |
| @@ -8,12 +8,12 @@ · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | #include <asm/pgtable.h> | 9 | #include <asm/pgtable.h> |
| 10 | 10 | ||
| 11 | void __iomem *ioremap(phys_addr_t addr, size_t size) | 11 | static void __iomem *__ioremap_caller(phys_addr_t addr, size_t size, |
| 12 | pgprot_t prot, void *caller) | ||
| 12 | { | 13 | { |
| 13 | phys_addr_t last_addr; | 14 | phys_addr_t last_addr; |
| 14 | unsigned long offset, vaddr; | 15 | unsigned long offset, vaddr; |
| 15 | struct vm_struct *area; | 16 | struct vm_struct *area; |
| 16 | pgprot_t prot; | ||
| 17 | 17 | ||
| 18 | last_addr = addr + size - 1; | 18 | last_addr = addr + size - 1; |
| 19 | if (!size || last_addr < addr) | 19 | if (!size || last_addr < addr) |
| @@ -23,15 +23,12 @@ void __iomem *ioremap(phys_addr_t addr, size_t size) · 3 unmodified lines | |||
| 23 | addr &= PAGE_MASK; | 23 | addr &= PAGE_MASK; |
| 24 | size = PAGE_ALIGN(size + offset); | 24 | size = PAGE_ALIGN(size + offset); |
| 25 | 25 | ||
| 26 | area = get_vm_area_caller(size, VM_ALLOC, __builtin_return_address(0)); | 26 | area = get_vm_area_caller(size, VM_IOREMAP, caller); |
| 27 | if (!area) | 27 | if (!area) |
| 28 | return NULL; | 28 | return NULL; |
| 29 | 29 | ||
| 30 | vaddr = (unsigned long)area->addr; | 30 | vaddr = (unsigned long)area->addr; |
| 31 | 31 | ||
| 32 | prot = __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | | ||
| 33 | _PAGE_GLOBAL | _CACHE_UNCACHED | _PAGE_SO); | ||
| 34 | |||
| 35 | if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) { | 32 | if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) { |
| 36 | free_vm_area(area); | 33 | free_vm_area(area); |
| 37 | return NULL; | 34 | return NULL; |
| @@ -39,7 +36,20 @@ void __iomem *ioremap(phys_addr_t addr, size_t size) · 1 unmodified line | |||
| 39 | 36 | ||
| 40 | return (void __iomem *)(vaddr + offset); | 37 | return (void __iomem *)(vaddr + offset); |
| 41 | } | 38 | } |
| 42 | EXPORT_SYMBOL(ioremap); | 39 | |
| 40 | void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot) | ||
| 41 | { | ||
| 42 | return __ioremap_caller(phys_addr, size, prot, | ||
| 43 | __builtin_return_address(0)); | ||
| 44 | } | ||
| 45 | EXPORT_SYMBOL(__ioremap); | ||
| 46 | |||
| 47 | void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size) | ||
| 48 | { | ||
| 49 | return __ioremap_caller(phys_addr, size, PAGE_KERNEL, | ||
| 50 | __builtin_return_address(0)); | ||
| 51 | } | ||
| 52 | EXPORT_SYMBOL(ioremap_cache); | ||
| 43 | 53 | ||
| 44 | void iounmap(void __iomem *addr) | 54 | void iounmap(void __iomem *addr) |
| 45 | { | 55 | { |
| @@ -51,10 +61,9 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, · 5 unmodified lines | |||
| 51 | unsigned long size, pgprot_t vma_prot) | 61 | unsigned long size, pgprot_t vma_prot) |
| 52 | { | 62 | { |
| 53 | if (!pfn_valid(pfn)) { | 63 | if (!pfn_valid(pfn)) { |
| 54 | vma_prot.pgprot |= _PAGE_SO; | ||
| 55 | return pgprot_noncached(vma_prot); | 64 | return pgprot_noncached(vma_prot); |
| 56 | } else if (file->f_flags & O_SYNC) { | 65 | } else if (file->f_flags & O_SYNC) { |
| 57 | return pgprot_noncached(vma_prot); | 66 | return pgprot_writecombine(vma_prot); |
| 58 | } | 67 | } |
| 59 | 68 | ||
| 60 | return vma_prot; | 69 | return vma_prot; |