14dea2d1aSSukadev Bhattiprolu /* 24dea2d1aSSukadev Bhattiprolu * Copyright 2016-17 IBM Corp. 34dea2d1aSSukadev Bhattiprolu * 44dea2d1aSSukadev Bhattiprolu * This program is free software; you can redistribute it and/or 54dea2d1aSSukadev Bhattiprolu * modify it under the terms of the GNU General Public License 64dea2d1aSSukadev Bhattiprolu * as published by the Free Software Foundation; either version 74dea2d1aSSukadev Bhattiprolu * 2 of the License, or (at your option) any later version. 84dea2d1aSSukadev Bhattiprolu */ 94dea2d1aSSukadev Bhattiprolu 10180fe15aSSukadev Bhattiprolu #define pr_fmt(fmt) "vas: " fmt 11180fe15aSSukadev Bhattiprolu 124dea2d1aSSukadev Bhattiprolu #include <linux/types.h> 134dea2d1aSSukadev Bhattiprolu #include <linux/mutex.h> 14180fe15aSSukadev Bhattiprolu #include <linux/slab.h> 15180fe15aSSukadev Bhattiprolu #include <linux/io.h> 164dea2d1aSSukadev Bhattiprolu 174dea2d1aSSukadev Bhattiprolu #include "vas.h" 184dea2d1aSSukadev Bhattiprolu 19180fe15aSSukadev Bhattiprolu /* 20180fe15aSSukadev Bhattiprolu * Compute the paste address region for the window @window using the 21180fe15aSSukadev Bhattiprolu * ->paste_base_addr and ->paste_win_id_shift we got from device tree. 22180fe15aSSukadev Bhattiprolu */ 23180fe15aSSukadev Bhattiprolu static void compute_paste_address(struct vas_window *window, u64 *addr, int *len) 24180fe15aSSukadev Bhattiprolu { 25180fe15aSSukadev Bhattiprolu int winid; 26180fe15aSSukadev Bhattiprolu u64 base, shift; 27180fe15aSSukadev Bhattiprolu 28180fe15aSSukadev Bhattiprolu base = window->vinst->paste_base_addr; 29180fe15aSSukadev Bhattiprolu shift = window->vinst->paste_win_id_shift; 30180fe15aSSukadev Bhattiprolu winid = window->winid; 31180fe15aSSukadev Bhattiprolu 32180fe15aSSukadev Bhattiprolu *addr = base + (winid << shift); 33180fe15aSSukadev Bhattiprolu if (len) 34180fe15aSSukadev Bhattiprolu *len = PAGE_SIZE; 35180fe15aSSukadev Bhattiprolu 36180fe15aSSukadev Bhattiprolu pr_debug("Txwin #%d: Paste addr 0x%llx\n", winid, *addr); 37180fe15aSSukadev Bhattiprolu } 38180fe15aSSukadev Bhattiprolu 39180fe15aSSukadev Bhattiprolu static inline void get_hvwc_mmio_bar(struct vas_window *window, 40180fe15aSSukadev Bhattiprolu u64 *start, int *len) 41180fe15aSSukadev Bhattiprolu { 42180fe15aSSukadev Bhattiprolu u64 pbaddr; 43180fe15aSSukadev Bhattiprolu 44180fe15aSSukadev Bhattiprolu pbaddr = window->vinst->hvwc_bar_start; 45180fe15aSSukadev Bhattiprolu *start = pbaddr + window->winid * VAS_HVWC_SIZE; 46180fe15aSSukadev Bhattiprolu *len = VAS_HVWC_SIZE; 47180fe15aSSukadev Bhattiprolu } 48180fe15aSSukadev Bhattiprolu 49180fe15aSSukadev Bhattiprolu static inline void get_uwc_mmio_bar(struct vas_window *window, 50180fe15aSSukadev Bhattiprolu u64 *start, int *len) 51180fe15aSSukadev Bhattiprolu { 52180fe15aSSukadev Bhattiprolu u64 pbaddr; 53180fe15aSSukadev Bhattiprolu 54180fe15aSSukadev Bhattiprolu pbaddr = window->vinst->uwc_bar_start; 55180fe15aSSukadev Bhattiprolu *start = pbaddr + window->winid * VAS_UWC_SIZE; 56180fe15aSSukadev Bhattiprolu *len = VAS_UWC_SIZE; 57180fe15aSSukadev Bhattiprolu } 58180fe15aSSukadev Bhattiprolu 59180fe15aSSukadev Bhattiprolu /* 60180fe15aSSukadev Bhattiprolu * Map the paste bus address of the given send window into kernel address 61180fe15aSSukadev Bhattiprolu * space. Unlike MMIO regions (map_mmio_region() below), paste region must 62180fe15aSSukadev Bhattiprolu * be mapped cache-able and is only applicable to send windows. 63180fe15aSSukadev Bhattiprolu */ 64180fe15aSSukadev Bhattiprolu void *map_paste_region(struct vas_window *txwin) 65180fe15aSSukadev Bhattiprolu { 66180fe15aSSukadev Bhattiprolu int len; 67180fe15aSSukadev Bhattiprolu void *map; 68180fe15aSSukadev Bhattiprolu char *name; 69180fe15aSSukadev Bhattiprolu u64 start; 70180fe15aSSukadev Bhattiprolu 71180fe15aSSukadev Bhattiprolu name = kasprintf(GFP_KERNEL, "window-v%d-w%d", txwin->vinst->vas_id, 72180fe15aSSukadev Bhattiprolu txwin->winid); 73180fe15aSSukadev Bhattiprolu if (!name) 74180fe15aSSukadev Bhattiprolu goto free_name; 75180fe15aSSukadev Bhattiprolu 76180fe15aSSukadev Bhattiprolu txwin->paste_addr_name = name; 77180fe15aSSukadev Bhattiprolu compute_paste_address(txwin, &start, &len); 78180fe15aSSukadev Bhattiprolu 79180fe15aSSukadev Bhattiprolu if (!request_mem_region(start, len, name)) { 80180fe15aSSukadev Bhattiprolu pr_devel("%s(): request_mem_region(0x%llx, %d) failed\n", 81180fe15aSSukadev Bhattiprolu __func__, start, len); 82180fe15aSSukadev Bhattiprolu goto free_name; 83180fe15aSSukadev Bhattiprolu } 84180fe15aSSukadev Bhattiprolu 85180fe15aSSukadev Bhattiprolu map = ioremap_cache(start, len); 86180fe15aSSukadev Bhattiprolu if (!map) { 87180fe15aSSukadev Bhattiprolu pr_devel("%s(): ioremap_cache(0x%llx, %d) failed\n", __func__, 88180fe15aSSukadev Bhattiprolu start, len); 89180fe15aSSukadev Bhattiprolu goto free_name; 90180fe15aSSukadev Bhattiprolu } 91180fe15aSSukadev Bhattiprolu 92180fe15aSSukadev Bhattiprolu pr_devel("Mapped paste addr 0x%llx to kaddr 0x%p\n", start, map); 93180fe15aSSukadev Bhattiprolu return map; 94180fe15aSSukadev Bhattiprolu 95180fe15aSSukadev Bhattiprolu free_name: 96180fe15aSSukadev Bhattiprolu kfree(name); 97180fe15aSSukadev Bhattiprolu return ERR_PTR(-ENOMEM); 98180fe15aSSukadev Bhattiprolu } 99180fe15aSSukadev Bhattiprolu 100180fe15aSSukadev Bhattiprolu 101180fe15aSSukadev Bhattiprolu static void *map_mmio_region(char *name, u64 start, int len) 102180fe15aSSukadev Bhattiprolu { 103180fe15aSSukadev Bhattiprolu void *map; 104180fe15aSSukadev Bhattiprolu 105180fe15aSSukadev Bhattiprolu if (!request_mem_region(start, len, name)) { 106180fe15aSSukadev Bhattiprolu pr_devel("%s(): request_mem_region(0x%llx, %d) failed\n", 107180fe15aSSukadev Bhattiprolu __func__, start, len); 108180fe15aSSukadev Bhattiprolu return NULL; 109180fe15aSSukadev Bhattiprolu } 110180fe15aSSukadev Bhattiprolu 111180fe15aSSukadev Bhattiprolu map = ioremap(start, len); 112180fe15aSSukadev Bhattiprolu if (!map) { 113180fe15aSSukadev Bhattiprolu pr_devel("%s(): ioremap(0x%llx, %d) failed\n", __func__, start, 114180fe15aSSukadev Bhattiprolu len); 115180fe15aSSukadev Bhattiprolu return NULL; 116180fe15aSSukadev Bhattiprolu } 117180fe15aSSukadev Bhattiprolu 118180fe15aSSukadev Bhattiprolu return map; 119180fe15aSSukadev Bhattiprolu } 120180fe15aSSukadev Bhattiprolu 121180fe15aSSukadev Bhattiprolu static void unmap_region(void *addr, u64 start, int len) 122180fe15aSSukadev Bhattiprolu { 123180fe15aSSukadev Bhattiprolu iounmap(addr); 124180fe15aSSukadev Bhattiprolu release_mem_region((phys_addr_t)start, len); 125180fe15aSSukadev Bhattiprolu } 126180fe15aSSukadev Bhattiprolu 127180fe15aSSukadev Bhattiprolu /* 128180fe15aSSukadev Bhattiprolu * Unmap the paste address region for a window. 129180fe15aSSukadev Bhattiprolu */ 130180fe15aSSukadev Bhattiprolu void unmap_paste_region(struct vas_window *window) 131180fe15aSSukadev Bhattiprolu { 132180fe15aSSukadev Bhattiprolu int len; 133180fe15aSSukadev Bhattiprolu u64 busaddr_start; 134180fe15aSSukadev Bhattiprolu 135180fe15aSSukadev Bhattiprolu if (window->paste_kaddr) { 136180fe15aSSukadev Bhattiprolu compute_paste_address(window, &busaddr_start, &len); 137180fe15aSSukadev Bhattiprolu unmap_region(window->paste_kaddr, busaddr_start, len); 138180fe15aSSukadev Bhattiprolu window->paste_kaddr = NULL; 139180fe15aSSukadev Bhattiprolu kfree(window->paste_addr_name); 140180fe15aSSukadev Bhattiprolu window->paste_addr_name = NULL; 141180fe15aSSukadev Bhattiprolu } 142180fe15aSSukadev Bhattiprolu } 143180fe15aSSukadev Bhattiprolu 144180fe15aSSukadev Bhattiprolu /* 145180fe15aSSukadev Bhattiprolu * Unmap the MMIO regions for a window. 146180fe15aSSukadev Bhattiprolu */ 147180fe15aSSukadev Bhattiprolu static void unmap_winctx_mmio_bars(struct vas_window *window) 148180fe15aSSukadev Bhattiprolu { 149180fe15aSSukadev Bhattiprolu int len; 150180fe15aSSukadev Bhattiprolu u64 busaddr_start; 151180fe15aSSukadev Bhattiprolu 152180fe15aSSukadev Bhattiprolu if (window->hvwc_map) { 153180fe15aSSukadev Bhattiprolu get_hvwc_mmio_bar(window, &busaddr_start, &len); 154180fe15aSSukadev Bhattiprolu unmap_region(window->hvwc_map, busaddr_start, len); 155180fe15aSSukadev Bhattiprolu window->hvwc_map = NULL; 156180fe15aSSukadev Bhattiprolu } 157180fe15aSSukadev Bhattiprolu 158180fe15aSSukadev Bhattiprolu if (window->uwc_map) { 159180fe15aSSukadev Bhattiprolu get_uwc_mmio_bar(window, &busaddr_start, &len); 160180fe15aSSukadev Bhattiprolu unmap_region(window->uwc_map, busaddr_start, len); 161180fe15aSSukadev Bhattiprolu window->uwc_map = NULL; 162180fe15aSSukadev Bhattiprolu } 163180fe15aSSukadev Bhattiprolu } 164180fe15aSSukadev Bhattiprolu 165180fe15aSSukadev Bhattiprolu /* 166180fe15aSSukadev Bhattiprolu * Find the Hypervisor Window Context (HVWC) MMIO Base Address Region and the 167180fe15aSSukadev Bhattiprolu * OS/User Window Context (UWC) MMIO Base Address Region for the given window. 168180fe15aSSukadev Bhattiprolu * Map these bus addresses and save the mapped kernel addresses in @window. 169180fe15aSSukadev Bhattiprolu */ 170180fe15aSSukadev Bhattiprolu int map_winctx_mmio_bars(struct vas_window *window) 171180fe15aSSukadev Bhattiprolu { 172180fe15aSSukadev Bhattiprolu int len; 173180fe15aSSukadev Bhattiprolu u64 start; 174180fe15aSSukadev Bhattiprolu 175180fe15aSSukadev Bhattiprolu get_hvwc_mmio_bar(window, &start, &len); 176180fe15aSSukadev Bhattiprolu window->hvwc_map = map_mmio_region("HVWCM_Window", start, len); 177180fe15aSSukadev Bhattiprolu 178180fe15aSSukadev Bhattiprolu get_uwc_mmio_bar(window, &start, &len); 179180fe15aSSukadev Bhattiprolu window->uwc_map = map_mmio_region("UWCM_Window", start, len); 180180fe15aSSukadev Bhattiprolu 181180fe15aSSukadev Bhattiprolu if (!window->hvwc_map || !window->uwc_map) { 182180fe15aSSukadev Bhattiprolu unmap_winctx_mmio_bars(window); 183180fe15aSSukadev Bhattiprolu return -1; 184180fe15aSSukadev Bhattiprolu } 185180fe15aSSukadev Bhattiprolu 186180fe15aSSukadev Bhattiprolu return 0; 187180fe15aSSukadev Bhattiprolu } 188180fe15aSSukadev Bhattiprolu 1894dea2d1aSSukadev Bhattiprolu /* stub for now */ 1904dea2d1aSSukadev Bhattiprolu int vas_win_close(struct vas_window *window) 1914dea2d1aSSukadev Bhattiprolu { 1924dea2d1aSSukadev Bhattiprolu return -1; 1934dea2d1aSSukadev Bhattiprolu } 194