162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * High memory support for Xtensa architecture 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General 562306a36Sopenharmony_ci * Public License. See the file "COPYING" in the main directory of 662306a36Sopenharmony_ci * this archive for more details. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2014 Cadence Design Systems Inc. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/export.h> 1262306a36Sopenharmony_ci#include <linux/highmem.h> 1362306a36Sopenharmony_ci#include <asm/tlbflush.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#if DCACHE_WAY_SIZE > PAGE_SIZE 1662306a36Sopenharmony_ciunsigned int last_pkmap_nr_arr[DCACHE_N_COLORS]; 1762306a36Sopenharmony_ciwait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS]; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic void __init kmap_waitqueues_init(void) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci unsigned int i; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i) 2462306a36Sopenharmony_ci init_waitqueue_head(pkmap_map_wait_arr + i); 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic inline enum fixed_addresses kmap_idx(int type, unsigned long color) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci int idx = (type + KM_MAX_IDX * smp_processor_id()) * DCACHE_N_COLORS; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci /* 3262306a36Sopenharmony_ci * The fixmap operates top down, so the color offset needs to be 3362306a36Sopenharmony_ci * reverse as well. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci return idx + DCACHE_N_COLORS - 1 - color; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cienum fixed_addresses kmap_local_map_idx(int type, unsigned long pfn) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci return kmap_idx(type, DCACHE_ALIAS(pfn << PAGE_SHIFT)); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cienum fixed_addresses kmap_local_unmap_idx(int type, unsigned long addr) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci return kmap_idx(type, DCACHE_ALIAS(addr)); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#else 4962306a36Sopenharmony_cistatic inline void kmap_waitqueues_init(void) { } 5062306a36Sopenharmony_ci#endif 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_civoid __init kmap_init(void) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci /* Check if this memory layout is broken because PKMAP overlaps 5562306a36Sopenharmony_ci * page table. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ci BUILD_BUG_ON(PKMAP_BASE < TLBTEMP_BASE_1 + TLBTEMP_SIZE); 5862306a36Sopenharmony_ci kmap_waitqueues_init(); 5962306a36Sopenharmony_ci} 60