165559100SMax Filippov /* 265559100SMax Filippov * High memory support for Xtensa architecture 365559100SMax Filippov * 465559100SMax Filippov * This file is subject to the terms and conditions of the GNU General 565559100SMax Filippov * Public License. See the file "COPYING" in the main directory of 665559100SMax Filippov * this archive for more details. 765559100SMax Filippov * 865559100SMax Filippov * Copyright (C) 2014 Cadence Design Systems Inc. 965559100SMax Filippov */ 1065559100SMax Filippov 1165559100SMax Filippov #include <linux/export.h> 1265559100SMax Filippov #include <linux/highmem.h> 1365559100SMax Filippov #include <asm/tlbflush.h> 1465559100SMax Filippov 158504b503SMax Filippov #if DCACHE_WAY_SIZE > PAGE_SIZE 168504b503SMax Filippov unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS]; 178504b503SMax Filippov wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS]; 188504b503SMax Filippov kmap_waitqueues_init(void)198504b503SMax Filippovstatic void __init kmap_waitqueues_init(void) 208504b503SMax Filippov { 218504b503SMax Filippov unsigned int i; 228504b503SMax Filippov 238504b503SMax Filippov for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i) 248504b503SMax Filippov init_waitqueue_head(pkmap_map_wait_arr + i); 258504b503SMax Filippov } 268504b503SMax Filippov kmap_idx(int type,unsigned long color)2732544d9cSMax Filippovstatic inline enum fixed_addresses kmap_idx(int type, unsigned long color) 2832544d9cSMax Filippov { 29*1eb0616cSThomas Gleixner int idx = (type + KM_MAX_IDX * smp_processor_id()) * DCACHE_N_COLORS; 30*1eb0616cSThomas Gleixner 31*1eb0616cSThomas Gleixner /* 32*1eb0616cSThomas Gleixner * The fixmap operates top down, so the color offset needs to be 33*1eb0616cSThomas Gleixner * reverse as well. 34*1eb0616cSThomas Gleixner */ 35*1eb0616cSThomas Gleixner return idx + DCACHE_N_COLORS - 1 - color; 3632544d9cSMax Filippov } 3732544d9cSMax Filippov kmap_local_map_idx(int type,unsigned long pfn)38629ed3f7SThomas Gleixnerenum fixed_addresses kmap_local_map_idx(int type, unsigned long pfn) 3965559100SMax Filippov { 40629ed3f7SThomas Gleixner return kmap_idx(type, DCACHE_ALIAS(pfn << PAGE_SHIFT)); 4165559100SMax Filippov } 4265559100SMax Filippov kmap_local_unmap_idx(int type,unsigned long addr)43629ed3f7SThomas Gleixnerenum fixed_addresses kmap_local_unmap_idx(int type, unsigned long addr) 4465559100SMax Filippov { 45629ed3f7SThomas Gleixner return kmap_idx(type, DCACHE_ALIAS(addr)); 4665559100SMax Filippov } 4765559100SMax Filippov 48*1eb0616cSThomas Gleixner #else kmap_waitqueues_init(void)49*1eb0616cSThomas Gleixnerstatic inline void kmap_waitqueues_init(void) { } 50*1eb0616cSThomas Gleixner #endif 51*1eb0616cSThomas Gleixner kmap_init(void)5265559100SMax Filippovvoid __init kmap_init(void) 5365559100SMax Filippov { 5421596872SIra Weiny /* Check if this memory layout is broken because PKMAP overlaps 5521596872SIra Weiny * page table. 5621596872SIra Weiny */ 5721596872SIra Weiny BUILD_BUG_ON(PKMAP_BASE < TLBTEMP_BASE_1 + TLBTEMP_SIZE); 588504b503SMax Filippov kmap_waitqueues_init(); 5965559100SMax Filippov } 60