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

MIPS: c-r4k: Add r4k_blast_scache_node for Loongson-3

For multi-node Loongson-3 (NUMA configuration), r4k_blast_scache() can
only flush Node-0's scache. So we add r4k_blast_scache_node() by using
(CAC_BASE | (node_id << NODE_ADDRSPACE_SHIFT)) instead of CKSEG0 as the
start address.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
[paul.burton@mips.com: Include asm/mmzone.h from asm/r4kcache.h for
nid_to_addrbase(). Add asm/mach-generic/mmzone.h
to allow inclusion for all platforms.]
Signed-off-by: Paul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/21129/
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <james.hogan@mips.com>
Cc: Steven J . Hill <Steven.Hill@cavium.com>
Cc: linux-mips@linux-mips.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: <stable@vger.kernel.org> # 3.15+

authored by

Huacai Chen and committed by
Paul Burton
bb53fdf3 1e35918a

+70 -7
+2
arch/mips/include/asm/mach-generic/mmzone.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Intentionally empty */
+1
arch/mips/include/asm/mach-loongson64/mmzone.h
··· 21 21 #define NODE3_ADDRSPACE_OFFSET 0x300000000000UL 22 22 23 23 #define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT) 24 + #define nid_to_addrbase(nid) ((nid) << NODE_ADDRSPACE_SHIFT) 24 25 25 26 #define LEVELS_PER_SLICE 128 26 27
+8
arch/mips/include/asm/mmzone.h
··· 9 9 #include <asm/page.h> 10 10 #include <mmzone.h> 11 11 12 + #ifndef pa_to_nid 13 + #define pa_to_nid(addr) 0 14 + #endif 15 + 16 + #ifndef nid_to_addrbase 17 + #define nid_to_addrbase(nid) 0 18 + #endif 19 + 12 20 #ifdef CONFIG_DISCONTIGMEM 13 21 14 22 #define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT)
+22
arch/mips/include/asm/r4kcache.h
··· 20 20 #include <asm/cpu-features.h> 21 21 #include <asm/cpu-type.h> 22 22 #include <asm/mipsmtregs.h> 23 + #include <asm/mmzone.h> 23 24 #include <linux/uaccess.h> /* for uaccess_kernel() */ 24 25 25 26 extern void (*r4k_blast_dcache)(void); ··· 674 673 /* blast_inv_dcache_range */ 675 674 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , ) 676 675 __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , ) 676 + 677 + /* Currently, this is very specific to Loongson-3 */ 678 + #define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize) \ 679 + static inline void blast_##pfx##cache##lsize##_node(long node) \ 680 + { \ 681 + unsigned long start = CAC_BASE | nid_to_addrbase(node); \ 682 + unsigned long end = start + current_cpu_data.desc.waysize; \ 683 + unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \ 684 + unsigned long ws_end = current_cpu_data.desc.ways << \ 685 + current_cpu_data.desc.waybit; \ 686 + unsigned long ws, addr; \ 687 + \ 688 + for (ws = 0; ws < ws_end; ws += ws_inc) \ 689 + for (addr = start; addr < end; addr += lsize * 32) \ 690 + cache##lsize##_unroll32(addr|ws, indexop); \ 691 + } 692 + 693 + __BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16) 694 + __BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) 695 + __BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) 696 + __BUILD_BLAST_CACHE_NODE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) 677 697 678 698 #endif /* _ASM_R4KCACHE_H */
+37 -7
arch/mips/mm/c-r4k.c
··· 459 459 r4k_blast_scache = blast_scache128; 460 460 } 461 461 462 + static void (*r4k_blast_scache_node)(long node); 463 + 464 + static void r4k_blast_scache_node_setup(void) 465 + { 466 + unsigned long sc_lsize = cpu_scache_line_size(); 467 + 468 + if (current_cpu_type() != CPU_LOONGSON3) 469 + r4k_blast_scache_node = (void *)cache_noop; 470 + else if (sc_lsize == 16) 471 + r4k_blast_scache_node = blast_scache16_node; 472 + else if (sc_lsize == 32) 473 + r4k_blast_scache_node = blast_scache32_node; 474 + else if (sc_lsize == 64) 475 + r4k_blast_scache_node = blast_scache64_node; 476 + else if (sc_lsize == 128) 477 + r4k_blast_scache_node = blast_scache128_node; 478 + } 479 + 462 480 static inline void local_r4k___flush_cache_all(void * args) 463 481 { 464 482 switch (current_cpu_type()) { 465 483 case CPU_LOONGSON2: 466 - case CPU_LOONGSON3: 467 484 case CPU_R4000SC: 468 485 case CPU_R4000MC: 469 486 case CPU_R4400SC: ··· 495 478 * in one of the primary caches. 496 479 */ 497 480 r4k_blast_scache(); 481 + break; 482 + 483 + case CPU_LOONGSON3: 484 + /* Use get_ebase_cpunum() for both NUMA=y/n */ 485 + r4k_blast_scache_node(get_ebase_cpunum() >> 2); 498 486 break; 499 487 500 488 case CPU_BMIPS5000: ··· 862 840 863 841 preempt_disable(); 864 842 if (cpu_has_inclusive_pcaches) { 865 - if (size >= scache_size) 866 - r4k_blast_scache(); 867 - else 843 + if (size >= scache_size) { 844 + if (current_cpu_type() != CPU_LOONGSON3) 845 + r4k_blast_scache(); 846 + else 847 + r4k_blast_scache_node(pa_to_nid(addr)); 848 + } else { 868 849 blast_scache_range(addr, addr + size); 850 + } 869 851 preempt_enable(); 870 852 __sync(); 871 853 return; ··· 903 877 904 878 preempt_disable(); 905 879 if (cpu_has_inclusive_pcaches) { 906 - if (size >= scache_size) 907 - r4k_blast_scache(); 908 - else { 880 + if (size >= scache_size) { 881 + if (current_cpu_type() != CPU_LOONGSON3) 882 + r4k_blast_scache(); 883 + else 884 + r4k_blast_scache_node(pa_to_nid(addr)); 885 + } else { 909 886 /* 910 887 * There is no clearly documented alignment requirement 911 888 * for the cache instruction on MIPS processors and ··· 1947 1918 r4k_blast_scache_page_setup(); 1948 1919 r4k_blast_scache_page_indexed_setup(); 1949 1920 r4k_blast_scache_setup(); 1921 + r4k_blast_scache_node_setup(); 1950 1922 #ifdef CONFIG_EVA 1951 1923 r4k_blast_dcache_user_page_setup(); 1952 1924 r4k_blast_icache_user_page_setup();