18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 38c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 48c2ecf20Sopenharmony_ci * for more details. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007 Cavium Networks 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/export.h> 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/sched.h> 118c2ecf20Sopenharmony_ci#include <linux/smp.h> 128c2ecf20Sopenharmony_ci#include <linux/mm.h> 138c2ecf20Sopenharmony_ci#include <linux/bitops.h> 148c2ecf20Sopenharmony_ci#include <linux/cpu.h> 158c2ecf20Sopenharmony_ci#include <linux/io.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <asm/bcache.h> 188c2ecf20Sopenharmony_ci#include <asm/bootinfo.h> 198c2ecf20Sopenharmony_ci#include <asm/cacheops.h> 208c2ecf20Sopenharmony_ci#include <asm/cpu-features.h> 218c2ecf20Sopenharmony_ci#include <asm/cpu-type.h> 228c2ecf20Sopenharmony_ci#include <asm/page.h> 238c2ecf20Sopenharmony_ci#include <asm/r4kcache.h> 248c2ecf20Sopenharmony_ci#include <asm/traps.h> 258c2ecf20Sopenharmony_ci#include <asm/mmu_context.h> 268c2ecf20Sopenharmony_ci#include <asm/war.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <asm/octeon/octeon.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciunsigned long long cache_err_dcache[NR_CPUS]; 318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cache_err_dcache); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/** 348c2ecf20Sopenharmony_ci * Octeon automatically flushes the dcache on tlb changes, so 358c2ecf20Sopenharmony_ci * from Linux's viewpoint it acts much like a physically 368c2ecf20Sopenharmony_ci * tagged cache. No flushing is needed 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_cistatic void octeon_flush_data_cache_page(unsigned long addr) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci /* Nothing to do */ 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic inline void octeon_local_flush_icache(void) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci asm volatile ("synci 0($0)"); 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* 508c2ecf20Sopenharmony_ci * Flush local I-cache for the specified range. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_cistatic void local_octeon_flush_icache_range(unsigned long start, 538c2ecf20Sopenharmony_ci unsigned long end) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci octeon_local_flush_icache(); 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/** 598c2ecf20Sopenharmony_ci * Flush caches as necessary for all cores affected by a 608c2ecf20Sopenharmony_ci * vma. If no vma is supplied, all cores are flushed. 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * @vma: VMA to flush or NULL to flush all icaches. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_cistatic void octeon_flush_icache_all_cores(struct vm_area_struct *vma) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci extern void octeon_send_ipi_single(int cpu, unsigned int action); 678c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 688c2ecf20Sopenharmony_ci int cpu; 698c2ecf20Sopenharmony_ci cpumask_t mask; 708c2ecf20Sopenharmony_ci#endif 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci mb(); 738c2ecf20Sopenharmony_ci octeon_local_flush_icache(); 748c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 758c2ecf20Sopenharmony_ci preempt_disable(); 768c2ecf20Sopenharmony_ci cpu = smp_processor_id(); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* 798c2ecf20Sopenharmony_ci * If we have a vma structure, we only need to worry about 808c2ecf20Sopenharmony_ci * cores it has been used on 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci if (vma) 838c2ecf20Sopenharmony_ci mask = *mm_cpumask(vma->vm_mm); 848c2ecf20Sopenharmony_ci else 858c2ecf20Sopenharmony_ci mask = *cpu_online_mask; 868c2ecf20Sopenharmony_ci cpumask_clear_cpu(cpu, &mask); 878c2ecf20Sopenharmony_ci for_each_cpu(cpu, &mask) 888c2ecf20Sopenharmony_ci octeon_send_ipi_single(cpu, SMP_ICACHE_FLUSH); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci preempt_enable(); 918c2ecf20Sopenharmony_ci#endif 928c2ecf20Sopenharmony_ci} 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/** 968c2ecf20Sopenharmony_ci * Called to flush the icache on all cores 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_cistatic void octeon_flush_icache_all(void) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci octeon_flush_icache_all_cores(NULL); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/** 1058c2ecf20Sopenharmony_ci * Called to flush all memory associated with a memory 1068c2ecf20Sopenharmony_ci * context. 1078c2ecf20Sopenharmony_ci * 1088c2ecf20Sopenharmony_ci * @mm: Memory context to flush 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_cistatic void octeon_flush_cache_mm(struct mm_struct *mm) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci /* 1138c2ecf20Sopenharmony_ci * According to the R4K version of this file, CPUs without 1148c2ecf20Sopenharmony_ci * dcache aliases don't need to do anything here 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/** 1208c2ecf20Sopenharmony_ci * Flush a range of kernel addresses out of the icache 1218c2ecf20Sopenharmony_ci * 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_cistatic void octeon_flush_icache_range(unsigned long start, unsigned long end) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci octeon_flush_icache_all_cores(NULL); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/** 1308c2ecf20Sopenharmony_ci * Flush a range out of a vma 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * @vma: VMA to flush 1338c2ecf20Sopenharmony_ci * @start: 1348c2ecf20Sopenharmony_ci * @end: 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_cistatic void octeon_flush_cache_range(struct vm_area_struct *vma, 1378c2ecf20Sopenharmony_ci unsigned long start, unsigned long end) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci if (vma->vm_flags & VM_EXEC) 1408c2ecf20Sopenharmony_ci octeon_flush_icache_all_cores(vma); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/** 1458c2ecf20Sopenharmony_ci * Flush a specific page of a vma 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * @vma: VMA to flush page for 1488c2ecf20Sopenharmony_ci * @page: Page to flush 1498c2ecf20Sopenharmony_ci * @pfn: 1508c2ecf20Sopenharmony_ci */ 1518c2ecf20Sopenharmony_cistatic void octeon_flush_cache_page(struct vm_area_struct *vma, 1528c2ecf20Sopenharmony_ci unsigned long page, unsigned long pfn) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci if (vma->vm_flags & VM_EXEC) 1558c2ecf20Sopenharmony_ci octeon_flush_icache_all_cores(vma); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic void octeon_flush_kernel_vmap_range(unsigned long vaddr, int size) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci BUG(); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/** 1648c2ecf20Sopenharmony_ci * Probe Octeon's caches 1658c2ecf20Sopenharmony_ci * 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_cistatic void probe_octeon(void) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci unsigned long icache_size; 1708c2ecf20Sopenharmony_ci unsigned long dcache_size; 1718c2ecf20Sopenharmony_ci unsigned int config1; 1728c2ecf20Sopenharmony_ci struct cpuinfo_mips *c = ¤t_cpu_data; 1738c2ecf20Sopenharmony_ci int cputype = current_cpu_type(); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci config1 = read_c0_config1(); 1768c2ecf20Sopenharmony_ci switch (cputype) { 1778c2ecf20Sopenharmony_ci case CPU_CAVIUM_OCTEON: 1788c2ecf20Sopenharmony_ci case CPU_CAVIUM_OCTEON_PLUS: 1798c2ecf20Sopenharmony_ci c->icache.linesz = 2 << ((config1 >> 19) & 7); 1808c2ecf20Sopenharmony_ci c->icache.sets = 64 << ((config1 >> 22) & 7); 1818c2ecf20Sopenharmony_ci c->icache.ways = 1 + ((config1 >> 16) & 7); 1828c2ecf20Sopenharmony_ci c->icache.flags |= MIPS_CACHE_VTAG; 1838c2ecf20Sopenharmony_ci icache_size = 1848c2ecf20Sopenharmony_ci c->icache.sets * c->icache.ways * c->icache.linesz; 1858c2ecf20Sopenharmony_ci c->icache.waybit = ffs(icache_size / c->icache.ways) - 1; 1868c2ecf20Sopenharmony_ci c->dcache.linesz = 128; 1878c2ecf20Sopenharmony_ci if (cputype == CPU_CAVIUM_OCTEON_PLUS) 1888c2ecf20Sopenharmony_ci c->dcache.sets = 2; /* CN5XXX has two Dcache sets */ 1898c2ecf20Sopenharmony_ci else 1908c2ecf20Sopenharmony_ci c->dcache.sets = 1; /* CN3XXX has one Dcache set */ 1918c2ecf20Sopenharmony_ci c->dcache.ways = 64; 1928c2ecf20Sopenharmony_ci dcache_size = 1938c2ecf20Sopenharmony_ci c->dcache.sets * c->dcache.ways * c->dcache.linesz; 1948c2ecf20Sopenharmony_ci c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1; 1958c2ecf20Sopenharmony_ci c->options |= MIPS_CPU_PREFETCH; 1968c2ecf20Sopenharmony_ci break; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci case CPU_CAVIUM_OCTEON2: 1998c2ecf20Sopenharmony_ci c->icache.linesz = 2 << ((config1 >> 19) & 7); 2008c2ecf20Sopenharmony_ci c->icache.sets = 8; 2018c2ecf20Sopenharmony_ci c->icache.ways = 37; 2028c2ecf20Sopenharmony_ci c->icache.flags |= MIPS_CACHE_VTAG; 2038c2ecf20Sopenharmony_ci icache_size = c->icache.sets * c->icache.ways * c->icache.linesz; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci c->dcache.linesz = 128; 2068c2ecf20Sopenharmony_ci c->dcache.ways = 32; 2078c2ecf20Sopenharmony_ci c->dcache.sets = 8; 2088c2ecf20Sopenharmony_ci dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz; 2098c2ecf20Sopenharmony_ci c->options |= MIPS_CPU_PREFETCH; 2108c2ecf20Sopenharmony_ci break; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci case CPU_CAVIUM_OCTEON3: 2138c2ecf20Sopenharmony_ci c->icache.linesz = 128; 2148c2ecf20Sopenharmony_ci c->icache.sets = 16; 2158c2ecf20Sopenharmony_ci c->icache.ways = 39; 2168c2ecf20Sopenharmony_ci c->icache.flags |= MIPS_CACHE_VTAG; 2178c2ecf20Sopenharmony_ci icache_size = c->icache.sets * c->icache.ways * c->icache.linesz; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci c->dcache.linesz = 128; 2208c2ecf20Sopenharmony_ci c->dcache.ways = 32; 2218c2ecf20Sopenharmony_ci c->dcache.sets = 8; 2228c2ecf20Sopenharmony_ci dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz; 2238c2ecf20Sopenharmony_ci c->options |= MIPS_CPU_PREFETCH; 2248c2ecf20Sopenharmony_ci break; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci default: 2278c2ecf20Sopenharmony_ci panic("Unsupported Cavium Networks CPU type"); 2288c2ecf20Sopenharmony_ci break; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* compute a couple of other cache variables */ 2328c2ecf20Sopenharmony_ci c->icache.waysize = icache_size / c->icache.ways; 2338c2ecf20Sopenharmony_ci c->dcache.waysize = dcache_size / c->dcache.ways; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci c->icache.sets = icache_size / (c->icache.linesz * c->icache.ways); 2368c2ecf20Sopenharmony_ci c->dcache.sets = dcache_size / (c->dcache.linesz * c->dcache.ways); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (smp_processor_id() == 0) { 2398c2ecf20Sopenharmony_ci pr_info("Primary instruction cache %ldkB, %s, %d way, " 2408c2ecf20Sopenharmony_ci "%d sets, linesize %d bytes.\n", 2418c2ecf20Sopenharmony_ci icache_size >> 10, 2428c2ecf20Sopenharmony_ci cpu_has_vtag_icache ? 2438c2ecf20Sopenharmony_ci "virtually tagged" : "physically tagged", 2448c2ecf20Sopenharmony_ci c->icache.ways, c->icache.sets, c->icache.linesz); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci pr_info("Primary data cache %ldkB, %d-way, %d sets, " 2478c2ecf20Sopenharmony_ci "linesize %d bytes.\n", 2488c2ecf20Sopenharmony_ci dcache_size >> 10, c->dcache.ways, 2498c2ecf20Sopenharmony_ci c->dcache.sets, c->dcache.linesz); 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic void octeon_cache_error_setup(void) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci extern char except_vec2_octeon; 2568c2ecf20Sopenharmony_ci set_handler(0x100, &except_vec2_octeon, 0x80); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci/** 2608c2ecf20Sopenharmony_ci * Setup the Octeon cache flush routines 2618c2ecf20Sopenharmony_ci * 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_civoid octeon_cache_init(void) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci probe_octeon(); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci shm_align_mask = PAGE_SIZE - 1; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci flush_cache_all = octeon_flush_icache_all; 2708c2ecf20Sopenharmony_ci __flush_cache_all = octeon_flush_icache_all; 2718c2ecf20Sopenharmony_ci flush_cache_mm = octeon_flush_cache_mm; 2728c2ecf20Sopenharmony_ci flush_cache_page = octeon_flush_cache_page; 2738c2ecf20Sopenharmony_ci flush_cache_range = octeon_flush_cache_range; 2748c2ecf20Sopenharmony_ci flush_icache_all = octeon_flush_icache_all; 2758c2ecf20Sopenharmony_ci flush_data_cache_page = octeon_flush_data_cache_page; 2768c2ecf20Sopenharmony_ci flush_icache_range = octeon_flush_icache_range; 2778c2ecf20Sopenharmony_ci local_flush_icache_range = local_octeon_flush_icache_range; 2788c2ecf20Sopenharmony_ci __flush_icache_user_range = octeon_flush_icache_range; 2798c2ecf20Sopenharmony_ci __local_flush_icache_user_range = local_octeon_flush_icache_range; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci __flush_kernel_vmap_range = octeon_flush_kernel_vmap_range; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci build_clear_page(); 2848c2ecf20Sopenharmony_ci build_copy_page(); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci board_cache_error_setup = octeon_cache_error_setup; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/* 2908c2ecf20Sopenharmony_ci * Handle a cache error exception 2918c2ecf20Sopenharmony_ci */ 2928c2ecf20Sopenharmony_cistatic RAW_NOTIFIER_HEAD(co_cache_error_chain); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ciint register_co_cache_error_notifier(struct notifier_block *nb) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci return raw_notifier_chain_register(&co_cache_error_chain, nb); 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(register_co_cache_error_notifier); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ciint unregister_co_cache_error_notifier(struct notifier_block *nb) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci return raw_notifier_chain_unregister(&co_cache_error_chain, nb); 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(unregister_co_cache_error_notifier); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic void co_cache_error_call_notifiers(unsigned long val) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci int rv = raw_notifier_call_chain(&co_cache_error_chain, val, NULL); 3098c2ecf20Sopenharmony_ci if ((rv & ~NOTIFY_STOP_MASK) != NOTIFY_OK) { 3108c2ecf20Sopenharmony_ci u64 dcache_err; 3118c2ecf20Sopenharmony_ci unsigned long coreid = cvmx_get_core_num(); 3128c2ecf20Sopenharmony_ci u64 icache_err = read_octeon_c0_icacheerr(); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (val) { 3158c2ecf20Sopenharmony_ci dcache_err = cache_err_dcache[coreid]; 3168c2ecf20Sopenharmony_ci cache_err_dcache[coreid] = 0; 3178c2ecf20Sopenharmony_ci } else { 3188c2ecf20Sopenharmony_ci dcache_err = read_octeon_c0_dcacheerr(); 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci pr_err("Core%lu: Cache error exception:\n", coreid); 3228c2ecf20Sopenharmony_ci pr_err("cp0_errorepc == %lx\n", read_c0_errorepc()); 3238c2ecf20Sopenharmony_ci if (icache_err & 1) { 3248c2ecf20Sopenharmony_ci pr_err("CacheErr (Icache) == %llx\n", 3258c2ecf20Sopenharmony_ci (unsigned long long)icache_err); 3268c2ecf20Sopenharmony_ci write_octeon_c0_icacheerr(0); 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci if (dcache_err & 1) { 3298c2ecf20Sopenharmony_ci pr_err("CacheErr (Dcache) == %llx\n", 3308c2ecf20Sopenharmony_ci (unsigned long long)dcache_err); 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci/* 3368c2ecf20Sopenharmony_ci * Called when the the exception is recoverable 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ciasmlinkage void cache_parity_error_octeon_recoverable(void) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci co_cache_error_call_notifiers(0); 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/** 3458c2ecf20Sopenharmony_ci * Called when the the exception is not recoverable 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ciasmlinkage void cache_parity_error_octeon_non_recoverable(void) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci co_cache_error_call_notifiers(1); 3518c2ecf20Sopenharmony_ci panic("Can't handle cache error: nested exception"); 3528c2ecf20Sopenharmony_ci} 353