On Thu, 2017-03-16 at 20:33 -0700, Sukadev Bhattiprolu wrote: > Define some helper functions to access the MMIO regions. We use these > in a follow-on patches to read/write VAS hardware registers. These > helpers are also used to later issue 'paste' instructions to submit > requests to the NX hardware engines. > > Signed-off-by: Sukadev Bhattiprolu <suka...@linux.vnet.ibm.com> > --- > Changelog [v3]: > - Minor reorg/cleanup of map/unmap functions > > Changelog [v2]: > - Get HVWC, UWC and paste addresses from window->vinst (i.e DT) > rather than kernel macros. > --- > drivers/misc/vas/vas-window.c | 126 > ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 126 insertions(+) > > diff --git a/drivers/misc/vas/vas-window.c b/drivers/misc/vas/vas-window.c > index 468f3bf..32dd1d0 100644 > --- a/drivers/misc/vas/vas-window.c > +++ b/drivers/misc/vas/vas-window.c > @@ -9,9 +9,135 @@ > > #include <linux/types.h> > #include <linux/mutex.h> > +#include <linux/slab.h> > +#include <linux/io.h> > #include <asm/vas.h> > #include "vas-internal.h" > > +/* > + * Compute the paste address region for the window @window using the > + * ->win_base_addr and ->win_id_shift we got from device tree. > + */ > +void compute_paste_address(struct vas_window *window, uint64_t *addr, int > *len) > +{ > + uint64_t base, shift; > + int winid; > + > + base = window->vinst->win_base_addr; > + shift = window->vinst->win_id_shift; > + winid = window->winid; > + > + *addr = base + (winid << shift); > + *len = PAGE_SIZE; > + > + pr_debug("Txwin #%d: Paste addr 0x%llx\n", winid, *addr); > +} > + > +static inline void get_hvwc_mmio_bar(struct vas_window *window, > + uint64_t *start, int *len) > +{ > + uint64_t pbaddr; > + > + pbaddr = window->vinst->hvwc_bar_start; > + *start = pbaddr + window->winid * VAS_HVWC_SIZE; > + *len = VAS_HVWC_SIZE; > +} > + > +static inline void get_uwc_mmio_bar(struct vas_window *window, > + uint64_t *start, int *len) > +{ > + uint64_t pbaddr; > + > + pbaddr = window->vinst->uwc_bar_start; > + *start = pbaddr + window->winid * VAS_UWC_SIZE; > + *len = VAS_UWC_SIZE;
I'm not sure this works for 4K pages since VAS_UWC_SIZE = PAGE_SIZE but in reality I think it's always 64K. Right? Seem like we are mixing pages sizes and hardware sizes here. (I realise 4K isn't supported yet, but....) > +} > + > +static void *map_mmio_region(char *name, uint64_t start, int len) > +{ > + void *map; > + > + if (!request_mem_region(start, len, name)) { > + pr_devel("%s(): request_mem_region(0x%llx, %d) failed\n", > + __func__, start, len); > + return NULL; > + } > + > + map = __ioremap(start, len, pgprot_val(pgprot_cached(__pgprot(0)))); > + if (!map) { > + pr_devel("%s(): ioremap(0x%llx, %d) failed\n", __func__, > start, > + len); > + return NULL; > + } > + > + return map; > +} > + > +/* > + * Unmap the MMIO regions for a window. > + */ > +static void unmap_wc_paste_kaddr(struct vas_window *window) > +{ > + int len; > + uint64_t busaddr_start; > + > + if (window->paste_kaddr) { > + iounmap(window->paste_kaddr); > + compute_paste_address(window, &busaddr_start, &len); > + release_mem_region((phys_addr_t)busaddr_start, len); > + window->paste_kaddr = NULL; > + } > + > +} > + > +static void unmap_wc_mmio_bars(struct vas_window *window) > +{ > + int len; > + uint64_t busaddr_start; > + > + unmap_wc_paste_kaddr(window); > + > + if (window->hvwc_map) { > + iounmap(window->hvwc_map); > + get_hvwc_mmio_bar(window, &busaddr_start, &len); > + release_mem_region((phys_addr_t)busaddr_start, len); > + window->hvwc_map = NULL; > + } > + > + if (window->uwc_map) { > + iounmap(window->uwc_map); > + get_uwc_mmio_bar(window, &busaddr_start, &len); > + release_mem_region((phys_addr_t)busaddr_start, len); > + window->uwc_map = NULL; > + } > +} > + > +/* > + * Find the Hypervisor Window Context (HVWC) MMIO Base Address Region and the > + * OS/User Window Context (UWC) MMIO Base Address Region for the given > window. > + * Map these bus addresses and save the mapped kernel addresses in @window. > + */ > +int map_wc_mmio_bars(struct vas_window *window) > +{ > + int len; > + uint64_t start; > + > + window->paste_kaddr = window->hvwc_map = window->uwc_map = NULL; > + > + get_hvwc_mmio_bar(window, &start, &len); > + window->hvwc_map = map_mmio_region("HVWCM_Window", start, len); > + > + get_uwc_mmio_bar(window, &start, &len); > + window->uwc_map = map_mmio_region("UWCM_Window", start, len); > + > + if (!window->hvwc_map || !window->uwc_map) { > + unmap_wc_mmio_bars(window); > + return -1; > + } > + > + return 0; > +} > + > /* stub for now */ > int vas_window_reset(struct vas_instance *vinst, int winid) > {