Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'xtensa-20161219' of git://github.com/jcmvbkbc/linux-xtensa

Pull Xtensa updates from Max Filippov:

- enable HAVE_DMA_CONTIGUOUS, configure shared DMA pool reservation in
kc705 DTS

- update xtensa DMA-related Documentation/features entries

- clean up arch/xtensa/kernel/setup.c: move S32C1I self-test out of it,
remove unused declarations, fix screen_info definition

* tag 'xtensa-20161219' of git://github.com/jcmvbkbc/linux-xtensa:
xtensa: update DMA-related Documentation/features entries
xtensa: configure shared DMA pool reservation in kc705 DTS
xtensa: enable HAVE_DMA_CONTIGUOUS
xtensa: move S32C1I self-test to a separate file
xtensa: fix screen_info, clean up unused declarations in setup.c

+176 -135
+1 -1
Documentation/features/io/dma-api-debug/arch-support.txt
··· 36 36 | um: | TODO | 37 37 | unicore32: | TODO | 38 38 | x86: | ok | 39 - | xtensa: | TODO | 39 + | xtensa: | ok | 40 40 -----------------------
+1 -1
Documentation/features/io/dma-contiguous/arch-support.txt
··· 36 36 | um: | TODO | 37 37 | unicore32: | TODO | 38 38 | x86: | ok | 39 - | xtensa: | TODO | 39 + | xtensa: | ok | 40 40 -----------------------
+1
arch/xtensa/Kconfig
··· 15 15 select GENERIC_SCHED_CLOCK 16 16 select HAVE_DEBUG_KMEMLEAK 17 17 select HAVE_DMA_API_DEBUG 18 + select HAVE_DMA_CONTIGUOUS 18 19 select HAVE_EXIT_THREAD 19 20 select HAVE_FUNCTION_TRACER 20 21 select HAVE_FUTEX_CMPXCHG if !MMU
+16
arch/xtensa/boot/dts/kc705.dts
··· 11 11 device_type = "memory"; 12 12 reg = <0x00000000 0x38000000>; 13 13 }; 14 + 15 + reserved-memory { 16 + #address-cells = <1>; 17 + #size-cells = <1>; 18 + ranges; 19 + 20 + /* global autoconfigured region for contiguous allocations */ 21 + linux,cma { 22 + compatible = "shared-dma-pool"; 23 + reusable; 24 + size = <0x04000000>; 25 + alignment = <0x2000>; 26 + alloc-ranges = <0x00000000 0x20000000>; 27 + linux,cma-default; 28 + }; 29 + }; 14 30 };
+1
arch/xtensa/include/asm/Kbuild
··· 3 3 generic-y += clkdev.h 4 4 generic-y += cputime.h 5 5 generic-y += div64.h 6 + generic-y += dma-contiguous.h 6 7 generic-y += emergency-restart.h 7 8 generic-y += errno.h 8 9 generic-y += exec.h
+1
arch/xtensa/kernel/Makefile
··· 14 14 obj-$(CONFIG_SMP) += smp.o mxhead.o 15 15 obj-$(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) += perf_event.o 16 16 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o 17 + obj-$(CONFIG_S32C1I_SELFTEST) += s32c1i_selftest.o 17 18 18 19 AFLAGS_head.o += -mtext-section-literals 19 20 AFLAGS_mxhead.o += -mtext-section-literals
+17 -4
arch/xtensa/kernel/pci-dma.c
··· 15 15 * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> 16 16 */ 17 17 18 + #include <linux/dma-contiguous.h> 18 19 #include <linux/gfp.h> 19 20 #include <linux/highmem.h> 20 21 #include <linux/mm.h> ··· 147 146 { 148 147 unsigned long ret; 149 148 unsigned long uncached = 0; 149 + unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; 150 + struct page *page = NULL; 150 151 151 152 /* ignore region speicifiers */ 152 153 ··· 156 153 157 154 if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) 158 155 flag |= GFP_DMA; 159 - ret = (unsigned long)__get_free_pages(flag, get_order(size)); 160 156 161 - if (ret == 0) 157 + if (gfpflags_allow_blocking(flag)) 158 + page = dma_alloc_from_contiguous(dev, count, get_order(size)); 159 + 160 + if (!page) 161 + page = alloc_pages(flag, get_order(size)); 162 + 163 + if (!page) 162 164 return NULL; 165 + 166 + ret = (unsigned long)page_address(page); 163 167 164 168 /* We currently don't support coherent memory outside KSEG */ 165 169 ··· 180 170 return (void *)uncached; 181 171 } 182 172 183 - static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr, 173 + static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr, 184 174 dma_addr_t dma_handle, unsigned long attrs) 185 175 { 186 176 unsigned long addr = (unsigned long)vaddr + 187 177 XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; 178 + struct page *page = virt_to_page(addr); 179 + unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; 188 180 189 181 BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || 190 182 addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); 191 183 192 - free_pages(addr, get_order(size)); 184 + if (!dma_release_from_contiguous(dev, page, count)) 185 + __free_pages(page, get_order(size)); 193 186 } 194 187 195 188 static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
+128
arch/xtensa/kernel/s32c1i_selftest.c
··· 1 + /* 2 + * S32C1I selftest. 3 + * 4 + * This file is subject to the terms and conditions of the GNU General Public 5 + * License. See the file "COPYING" in the main directory of this archive 6 + * for more details. 7 + * 8 + * Copyright (C) 2016 Cadence Design Systems Inc. 9 + */ 10 + 11 + #include <linux/init.h> 12 + #include <linux/kernel.h> 13 + 14 + #include <asm/traps.h> 15 + 16 + #if XCHAL_HAVE_S32C1I 17 + 18 + static int __initdata rcw_word, rcw_probe_pc, rcw_exc; 19 + 20 + /* 21 + * Basic atomic compare-and-swap, that records PC of S32C1I for probing. 22 + * 23 + * If *v == cmp, set *v = set. Return previous *v. 24 + */ 25 + static inline int probed_compare_swap(int *v, int cmp, int set) 26 + { 27 + int tmp; 28 + 29 + __asm__ __volatile__( 30 + " movi %1, 1f\n" 31 + " s32i %1, %4, 0\n" 32 + " wsr %2, scompare1\n" 33 + "1: s32c1i %0, %3, 0\n" 34 + : "=a" (set), "=&a" (tmp) 35 + : "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set) 36 + : "memory" 37 + ); 38 + return set; 39 + } 40 + 41 + /* Handle probed exception */ 42 + 43 + static void __init do_probed_exception(struct pt_regs *regs, 44 + unsigned long exccause) 45 + { 46 + if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ 47 + regs->pc += 3; /* skip the s32c1i instruction */ 48 + rcw_exc = exccause; 49 + } else { 50 + do_unhandled(regs, exccause); 51 + } 52 + } 53 + 54 + /* Simple test of S32C1I (soc bringup assist) */ 55 + 56 + static int __init check_s32c1i(void) 57 + { 58 + int n, cause1, cause2; 59 + void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ 60 + 61 + rcw_probe_pc = 0; 62 + handbus = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, 63 + do_probed_exception); 64 + handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, 65 + do_probed_exception); 66 + handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, 67 + do_probed_exception); 68 + 69 + /* First try an S32C1I that does not store: */ 70 + rcw_exc = 0; 71 + rcw_word = 1; 72 + n = probed_compare_swap(&rcw_word, 0, 2); 73 + cause1 = rcw_exc; 74 + 75 + /* took exception? */ 76 + if (cause1 != 0) { 77 + /* unclean exception? */ 78 + if (n != 2 || rcw_word != 1) 79 + panic("S32C1I exception error"); 80 + } else if (rcw_word != 1 || n != 1) { 81 + panic("S32C1I compare error"); 82 + } 83 + 84 + /* Then an S32C1I that stores: */ 85 + rcw_exc = 0; 86 + rcw_word = 0x1234567; 87 + n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde); 88 + cause2 = rcw_exc; 89 + 90 + if (cause2 != 0) { 91 + /* unclean exception? */ 92 + if (n != 0xabcde || rcw_word != 0x1234567) 93 + panic("S32C1I exception error (b)"); 94 + } else if (rcw_word != 0xabcde || n != 0x1234567) { 95 + panic("S32C1I store error"); 96 + } 97 + 98 + /* Verify consistency of exceptions: */ 99 + if (cause1 || cause2) { 100 + pr_warn("S32C1I took exception %d, %d\n", cause1, cause2); 101 + /* If emulation of S32C1I upon bus error gets implemented, 102 + * we can get rid of this panic for single core (not SMP) 103 + */ 104 + panic("S32C1I exceptions not currently supported"); 105 + } 106 + if (cause1 != cause2) 107 + panic("inconsistent S32C1I exceptions"); 108 + 109 + trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); 110 + trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); 111 + trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); 112 + return 0; 113 + } 114 + 115 + #else /* XCHAL_HAVE_S32C1I */ 116 + 117 + /* This condition should not occur with a commercially deployed processor. 118 + * Display reminder for early engr test or demo chips / FPGA bitstreams 119 + */ 120 + static int __init check_s32c1i(void) 121 + { 122 + pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); 123 + return 0; 124 + } 125 + 126 + #endif /* XCHAL_HAVE_S32C1I */ 127 + 128 + early_initcall(check_s32c1i);
+8 -129
arch/xtensa/kernel/setup.c
··· 31 31 # include <linux/console.h> 32 32 #endif 33 33 34 - #ifdef CONFIG_RTC 35 - # include <linux/timex.h> 36 - #endif 37 - 38 34 #ifdef CONFIG_PROC_FS 39 35 # include <linux/seq_file.h> 40 36 #endif ··· 44 48 #include <asm/page.h> 45 49 #include <asm/setup.h> 46 50 #include <asm/param.h> 47 - #include <asm/traps.h> 48 51 #include <asm/smp.h> 49 52 #include <asm/sysmem.h> 50 53 51 54 #include <platform/hardware.h> 52 55 53 56 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) 54 - struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16}; 57 + struct screen_info screen_info = { 58 + .orig_x = 0, 59 + .orig_y = 24, 60 + .orig_video_cols = 80, 61 + .orig_video_lines = 24, 62 + .orig_video_isVGA = 1, 63 + .orig_video_points = 16, 64 + }; 55 65 #endif 56 - 57 - #ifdef CONFIG_BLK_DEV_FD 58 - extern struct fd_ops no_fd_ops; 59 - struct fd_ops *fd_ops; 60 - #endif 61 - 62 - extern struct rtc_ops no_rtc_ops; 63 - struct rtc_ops *rtc_ops; 64 66 65 67 #ifdef CONFIG_BLK_DEV_INITRD 66 68 extern unsigned long initrd_start; ··· 71 77 void *dtb_start = __dtb_start; 72 78 #endif 73 79 74 - unsigned char aux_device_present; 75 80 extern unsigned long loops_per_jiffy; 76 81 77 82 /* Command line specified as configuration option. */ ··· 309 316 extern char _SecondaryResetVector_text_start; 310 317 extern char _SecondaryResetVector_text_end; 311 318 #endif 312 - 313 - 314 - #ifdef CONFIG_S32C1I_SELFTEST 315 - #if XCHAL_HAVE_S32C1I 316 - 317 - static int __initdata rcw_word, rcw_probe_pc, rcw_exc; 318 - 319 - /* 320 - * Basic atomic compare-and-swap, that records PC of S32C1I for probing. 321 - * 322 - * If *v == cmp, set *v = set. Return previous *v. 323 - */ 324 - static inline int probed_compare_swap(int *v, int cmp, int set) 325 - { 326 - int tmp; 327 - 328 - __asm__ __volatile__( 329 - " movi %1, 1f\n" 330 - " s32i %1, %4, 0\n" 331 - " wsr %2, scompare1\n" 332 - "1: s32c1i %0, %3, 0\n" 333 - : "=a" (set), "=&a" (tmp) 334 - : "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set) 335 - : "memory" 336 - ); 337 - return set; 338 - } 339 - 340 - /* Handle probed exception */ 341 - 342 - static void __init do_probed_exception(struct pt_regs *regs, 343 - unsigned long exccause) 344 - { 345 - if (regs->pc == rcw_probe_pc) { /* exception on s32c1i ? */ 346 - regs->pc += 3; /* skip the s32c1i instruction */ 347 - rcw_exc = exccause; 348 - } else { 349 - do_unhandled(regs, exccause); 350 - } 351 - } 352 - 353 - /* Simple test of S32C1I (soc bringup assist) */ 354 - 355 - static int __init check_s32c1i(void) 356 - { 357 - int n, cause1, cause2; 358 - void *handbus, *handdata, *handaddr; /* temporarily saved handlers */ 359 - 360 - rcw_probe_pc = 0; 361 - handbus = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, 362 - do_probed_exception); 363 - handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, 364 - do_probed_exception); 365 - handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, 366 - do_probed_exception); 367 - 368 - /* First try an S32C1I that does not store: */ 369 - rcw_exc = 0; 370 - rcw_word = 1; 371 - n = probed_compare_swap(&rcw_word, 0, 2); 372 - cause1 = rcw_exc; 373 - 374 - /* took exception? */ 375 - if (cause1 != 0) { 376 - /* unclean exception? */ 377 - if (n != 2 || rcw_word != 1) 378 - panic("S32C1I exception error"); 379 - } else if (rcw_word != 1 || n != 1) { 380 - panic("S32C1I compare error"); 381 - } 382 - 383 - /* Then an S32C1I that stores: */ 384 - rcw_exc = 0; 385 - rcw_word = 0x1234567; 386 - n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde); 387 - cause2 = rcw_exc; 388 - 389 - if (cause2 != 0) { 390 - /* unclean exception? */ 391 - if (n != 0xabcde || rcw_word != 0x1234567) 392 - panic("S32C1I exception error (b)"); 393 - } else if (rcw_word != 0xabcde || n != 0x1234567) { 394 - panic("S32C1I store error"); 395 - } 396 - 397 - /* Verify consistency of exceptions: */ 398 - if (cause1 || cause2) { 399 - pr_warn("S32C1I took exception %d, %d\n", cause1, cause2); 400 - /* If emulation of S32C1I upon bus error gets implemented, 401 - we can get rid of this panic for single core (not SMP) */ 402 - panic("S32C1I exceptions not currently supported"); 403 - } 404 - if (cause1 != cause2) 405 - panic("inconsistent S32C1I exceptions"); 406 - 407 - trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus); 408 - trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata); 409 - trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr); 410 - return 0; 411 - } 412 - 413 - #else /* XCHAL_HAVE_S32C1I */ 414 - 415 - /* This condition should not occur with a commercially deployed processor. 416 - Display reminder for early engr test or demo chips / FPGA bitstreams */ 417 - static int __init check_s32c1i(void) 418 - { 419 - pr_warn("Processor configuration lacks atomic compare-and-swap support!\n"); 420 - return 0; 421 - } 422 - 423 - #endif /* XCHAL_HAVE_S32C1I */ 424 - early_initcall(check_s32c1i); 425 - #endif /* CONFIG_S32C1I_SELFTEST */ 426 319 427 320 static inline int mem_reserve(unsigned long start, unsigned long end) 428 321 {
+2
arch/xtensa/mm/init.c
··· 26 26 #include <linux/nodemask.h> 27 27 #include <linux/mm.h> 28 28 #include <linux/of_fdt.h> 29 + #include <linux/dma-contiguous.h> 29 30 30 31 #include <asm/bootparam.h> 31 32 #include <asm/page.h> ··· 61 60 max_low_pfn = min(max_pfn, MAX_LOW_PFN); 62 61 63 62 memblock_set_current_limit(PFN_PHYS(max_low_pfn)); 63 + dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); 64 64 65 65 memblock_dump_all(); 66 66 }